Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 85 additions & 19 deletions open-sse/services/compression/engines/rtk/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ function processRtkCodeBlocksOnly(

export function processRtkText(
text: string,
options: { command?: string | null; config?: Partial<RtkConfig> } = {}
options: { command?: string | null; config?: Partial<RtkConfig>; skipFilters?: boolean } = {}
): RtkProcessResult {
const config = mergeRtkConfig(options.config);
const originalTokens = estimateCompressionTokens(text);
Expand All @@ -278,20 +278,22 @@ export function processRtkText(
let result = text;

const detection = detectCommandType(text, options.command);
const filter = matchRtkFilter(text, detection.command, {
customFiltersEnabled: config.customFiltersEnabled,
trustProjectFilters: config.trustProjectFilters,
});
if (filter && !config.disabledFilters.includes(filter.id)) {
if (config.enabledFilters.length === 0 || config.enabledFilters.includes(filter.id)) {
const filtered = applyLineFilter(result, {
...filter,
maxLines: filter.maxLines || config.maxLinesPerResult,
});
result = filtered.text;
if (filtered.appliedRules.length > 0) {
techniquesUsed.push("rtk-filter");
rulesApplied.push(...filtered.appliedRules);
if (!options.skipFilters) {
const filter = matchRtkFilter(text, detection.command, {
customFiltersEnabled: config.customFiltersEnabled,
trustProjectFilters: config.trustProjectFilters,
});
if (filter && !config.disabledFilters.includes(filter.id)) {
if (config.enabledFilters.length === 0 || config.enabledFilters.includes(filter.id)) {
const filtered = applyLineFilter(result, {
...filter,
maxLines: filter.maxLines || config.maxLinesPerResult,
});
result = filtered.text;
if (filtered.appliedRules.length > 0) {
techniquesUsed.push("rtk-filter");
rulesApplied.push(...filtered.appliedRules);
}
}
}
}
Expand Down Expand Up @@ -362,7 +364,8 @@ export function processRtkText(

function processRtkContent(
content: Message["content"],
config: RtkConfig
config: RtkConfig,
options?: { command?: string | null; skipFilters?: boolean }
): {
content: Message["content"];
compressed: boolean;
Expand All @@ -387,7 +390,11 @@ function processRtkContent(
if (!content) {
return { content, compressed: false, techniquesUsed, rulesApplied, rawOutputPointers };
}
const processed = processRtkText(content, { config });
const processed = processRtkText(content, {
config,
command: options?.command,
skipFilters: options?.skipFilters,
});
collect(processed);
return {
content: processed.compressed ? processed.text : content,
Expand All @@ -405,7 +412,11 @@ function processRtkContent(
let compressed = false;
const nextContent = content.map((part) => {
if (!isTextBlock(part) || !part.text) return part;
const processed = processRtkText(part.text, { config });
const processed = processRtkText(part.text, {
config,
command: options?.command,
skipFilters: options?.skipFilters,
});
collect(processed);
if (!processed.compressed) return part;
compressed = true;
Expand Down Expand Up @@ -438,9 +449,64 @@ export function applyRtkCompression(
const allTechniques: string[] = [];
const allRules: string[] = [];
const rawOutputPointers: RtkRawOutputPointer[] = [];

// Build tool_call_id → tool metadata lookup from assistant messages.
// This lets us distinguish bash tool results (which RTK filters are designed for)
// from non-shell tool results (read, grep, glob, etc.) that should skip filters.
const toolCallLookup = new Map<string, { toolName: string; command: string | null }>();
for (const msg of messages) {
if (msg.role !== "assistant") continue;
const toolCalls = msg.tool_calls;
if (!Array.isArray(toolCalls)) continue;
for (const tc of toolCalls as Array<Record<string, unknown>>) {
if (!tc || typeof tc !== "object") continue;
const id = typeof tc.id === "string" ? tc.id : null;
if (!id) continue;
const fn = tc.function as Record<string, unknown> | undefined;
if (!fn || typeof fn !== "object") continue;
const toolName = typeof fn.name === "string" ? fn.name : "";
let command: string | null = null;
if (typeof fn.arguments === "string") {
try {
const args = JSON.parse(fn.arguments);
command =
typeof args.command === "string"
? args.command
: typeof args.cmd === "string"
? args.cmd
: null;
} catch {
// non-JSON arguments
}
}
Comment on lines +469 to +481

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current implementation for extracting the command argument has two potential issues:

  1. It only handles fn.arguments when it is a string. Some providers or internal transformations may pass arguments as a pre-parsed object.
  2. JSON.parse can return null (e.g., if the input is the string "null"), which would cause an error when accessing args.command or args.cmd. Although wrapped in a try-catch, it's better to explicitly check the type and value of args for robustness.
      const rawArgs = fn.arguments;
      let args: any = null;
      if (typeof rawArgs === "string") {
        try {
          args = JSON.parse(rawArgs);
        } catch {
          // non-JSON arguments
        }
      } else if (rawArgs && typeof rawArgs === "object") {
        args = rawArgs;
      }

      if (args && typeof args === "object") {
        command =
          typeof args.command === "string"
            ? args.command
            : typeof args.cmd === "string"
              ? args.cmd
              : null;
      }

toolCallLookup.set(id, { toolName, command });
}
}

const compressedMessages = messages.map((message) => {
if (!shouldCompressMessage(message, config)) return message;
const processed = processRtkContent(message.content, config);

// Resolve tool metadata from the preceding assistant tool_calls entry.
let command: string | null = null;
let skipFilters = false;
if (message.role === "tool") {
const callId = typeof message.tool_call_id === "string" ? message.tool_call_id : null;
const meta = callId ? toolCallLookup.get(callId) : null;
if (meta) {
const name = meta.toolName.toLowerCase();
// Match the same terminal tool pattern used in grok-web.ts isTerminalTool().
// Only apply RTK filters to bash/shell tool results.
// Non-shell tools (read, glob, grep, edit, write, etc.) skip filter matching
// to prevent content-based false positives (e.g. a TS file matching build-typescript).
if (/\b(bash|shell|terminal|run_command|execute_command|exec|command)\b/.test(name)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The regular expression for identifying shell tools is instantiated on every iteration of the messages.map loop. To improve performance and avoid redundant compilation, this regex should be defined as a constant outside the applyRtkCompression function.

command = meta.command;
} else {
skipFilters = true;
}
}
}

const processed = processRtkContent(message.content, config, { command, skipFilters });
allTechniques.push(...processed.techniquesUsed);
allRules.push(...processed.rulesApplied);
rawOutputPointers.push(...processed.rawOutputPointers);
Expand Down