mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 04:12:10 +03:00
Implements the aggressive compression pipeline (issue #1588) with three core stages: tool-result compression, progressive aging, and rule-based summarization. Includes downgrade chain to caveman/lite when savings are insufficient. Core modules: - summarizer.ts: RuleBasedSummarizer with intent/file/error/decision extraction, code fence trimming, skip-already-compressed guard - toolResultCompressor.ts: 5 auto-detected strategies (fileContent, grepSearch, shellOutput, json, errorMessage) with toggle support - progressiveAging.ts: 4-tier degradation (verbatim→light→moderate→ fullSummary) with [COMPRESSED:aging:<tier>] markers - aggressive.ts: Orchestrator with 3-step pipeline and downgrade chain (aggressive→caveman→lite→as-is) Integration: - strategySelector.ts: applyCompression() now dispatches mode='aggressive' - compression.ts: aggressiveConfig CRUD with deep merge of nested objects - API route: Zod schema for aggressiveConfig thresholds/strategies - CompressionSettingsTab: aggressive mode card, thresholds, toggles, i18n - Migration 031: SELECT 1 no-op (config stored as kv key) Tests: 109 across 8 files (types, summarizer, toolResultCompressor, progressiveAging, aggressive, integration, golden eval, caveman regression) All pass. Typecheck clean. Lint clean (0 errors). Build succeeds.
230 lines
8.8 KiB
TypeScript
230 lines
8.8 KiB
TypeScript
import { describe, it } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { compressToolResult } from "../../../open-sse/services/compression/toolResultCompressor.ts";
|
|
import type { ToolStrategiesConfig } from "../../../open-sse/services/compression/types.ts";
|
|
|
|
const ALL_ON: ToolStrategiesConfig = {
|
|
fileContent: true,
|
|
grepSearch: true,
|
|
shellOutput: true,
|
|
json: true,
|
|
errorMessage: true,
|
|
};
|
|
|
|
describe("compressToolResult", () => {
|
|
it("returns 'none' strategy for plain prose input", () => {
|
|
const result = compressToolResult("Hello, this is a simple message.", ALL_ON);
|
|
assert.equal(result.strategy, "none");
|
|
assert.equal(result.saved, 0);
|
|
assert.equal(result.compressed, "Hello, this is a simple message.");
|
|
});
|
|
|
|
it("returns 'none' for empty string", () => {
|
|
const result = compressToolResult("", ALL_ON);
|
|
assert.equal(result.strategy, "none");
|
|
});
|
|
|
|
it("compresses file content with code indicators", () => {
|
|
const lines = Array.from({ length: 100 }, (_, i) => `line ${i}`);
|
|
const code = `import x from "y";\nfunction f() {\n${lines.join("\n")}\n}`;
|
|
const result = compressToolResult(code, ALL_ON);
|
|
assert.equal(result.strategy, "fileContent");
|
|
assert.ok(result.saved > 0);
|
|
assert.ok(result.compressed.includes("…") || result.compressed.includes("elided"));
|
|
});
|
|
|
|
it("compresses grep search output", () => {
|
|
const lines = Array.from(
|
|
{ length: 100 },
|
|
(_, i) => `src/file${i % 5}.ts:${i + 1}:10: match found`
|
|
);
|
|
const content = lines.join("\n");
|
|
const result = compressToolResult(content, ALL_ON);
|
|
assert.equal(result.strategy, "grepSearch");
|
|
assert.ok(result.saved > 0);
|
|
assert.ok(result.compressed.includes("… [") || result.compressed.includes("more matches"));
|
|
});
|
|
|
|
it("compresses shell output with ANSI codes", () => {
|
|
const content =
|
|
"\x1b[32mSuccess\x1b[0m\n" +
|
|
Array.from({ length: 60 }, (_, i) => `output line ${i}`).join("\n");
|
|
const result = compressToolResult(content, ALL_ON);
|
|
assert.equal(result.strategy, "shellOutput");
|
|
assert.ok(result.saved > 0);
|
|
assert.ok(!result.compressed.includes("\x1b["));
|
|
});
|
|
|
|
it("compresses shell output with $ prompt", () => {
|
|
const content = "$ ls -la\ntotal 42\nfile1.txt\nfile2.txt";
|
|
const result = compressToolResult(content, ALL_ON);
|
|
assert.equal(result.strategy, "shellOutput");
|
|
});
|
|
|
|
it("compresses large JSON array", () => {
|
|
const arr = Array.from({ length: 100 }, (_, i) => ({
|
|
id: i,
|
|
name: `item${i}`,
|
|
data: "x".repeat(50),
|
|
}));
|
|
const content = JSON.stringify(arr);
|
|
const result = compressToolResult(content, ALL_ON);
|
|
assert.equal(result.strategy, "json");
|
|
assert.ok(result.saved > 0);
|
|
assert.ok(result.compressed.includes("total"));
|
|
});
|
|
|
|
it("compresses large JSON object", () => {
|
|
const obj: Record<string, unknown> = {};
|
|
for (let i = 0; i < 30; i++) {
|
|
obj[`key${i}`] = { nested: "value".repeat(20) };
|
|
}
|
|
const content = JSON.stringify(obj);
|
|
const result = compressToolResult(content, ALL_ON);
|
|
assert.equal(result.strategy, "json");
|
|
assert.ok(result.saved > 0);
|
|
});
|
|
|
|
it("does not compress small JSON", () => {
|
|
const content = JSON.stringify({ a: 1, b: 2 });
|
|
const result = compressToolResult(content, ALL_ON);
|
|
assert.equal(result.strategy, "none");
|
|
});
|
|
|
|
it("compresses error messages with stack trace", () => {
|
|
const frames = Array.from(
|
|
{ length: 20 },
|
|
(_, i) => ` at func${i} (file${i}.ts:${i + 1}:${i + 10})`
|
|
);
|
|
const content = `TypeError: Cannot read property 'x' of undefined\n${frames.join("\n")}`;
|
|
const result = compressToolResult(content, ALL_ON);
|
|
assert.equal(result.strategy, "errorMessage");
|
|
assert.ok(result.saved > 0);
|
|
});
|
|
|
|
it("compresses Python Traceback", () => {
|
|
const content =
|
|
"Traceback (most recent call last):\n File 'app.py', line 42\n x = undefined()\nException: NameError";
|
|
const result = compressToolResult(content, ALL_ON);
|
|
assert.equal(result.strategy, "errorMessage");
|
|
});
|
|
|
|
it("skips strategy when toggle is off", () => {
|
|
const code =
|
|
`import x from "y";\nfunction f() {}\n` +
|
|
Array.from({ length: 50 }, (_, i) => `line ${i}`).join("\n");
|
|
const opts: ToolStrategiesConfig = { ...ALL_ON, fileContent: false };
|
|
const result = compressToolResult(code, opts);
|
|
assert.notEqual(result.strategy, "fileContent");
|
|
});
|
|
|
|
it("skips grep strategy when toggle is off", () => {
|
|
const content = "src/file.ts:10:5: match\nsrc/file.ts:20:8: match";
|
|
const opts: ToolStrategiesConfig = { ...ALL_ON, grepSearch: false };
|
|
const result = compressToolResult(content, opts);
|
|
assert.notEqual(result.strategy, "grepSearch");
|
|
});
|
|
|
|
it("skips shell strategy when toggle is off", () => {
|
|
const content = "\x1b[32moutput\x1b[0m\n$ command";
|
|
const opts: ToolStrategiesConfig = { ...ALL_ON, shellOutput: false };
|
|
const result = compressToolResult(content, opts);
|
|
assert.notEqual(result.strategy, "shellOutput");
|
|
});
|
|
|
|
it("skips json strategy when toggle is off", () => {
|
|
const arr = Array.from({ length: 100 }, (_, i) => ({ id: i }));
|
|
const content = JSON.stringify(arr);
|
|
const opts: ToolStrategiesConfig = { ...ALL_ON, json: false };
|
|
const result = compressToolResult(content, opts);
|
|
assert.notEqual(result.strategy, "json");
|
|
});
|
|
|
|
it("skips error strategy when toggle is off", () => {
|
|
const content = "Error: something went wrong\n at func (file.ts:1:1)";
|
|
const opts: ToolStrategiesConfig = { ...ALL_ON, errorMessage: false };
|
|
const result = compressToolResult(content, opts);
|
|
assert.notEqual(result.strategy, "errorMessage");
|
|
});
|
|
|
|
it("all toggles off returns 'none'", () => {
|
|
const content = "Error: bad\nsrc/file.ts:10:5: match\n$ ls";
|
|
const opts: ToolStrategiesConfig = {
|
|
fileContent: false,
|
|
grepSearch: false,
|
|
shellOutput: false,
|
|
json: false,
|
|
errorMessage: false,
|
|
};
|
|
const result = compressToolResult(content, opts);
|
|
assert.equal(result.strategy, "none");
|
|
assert.equal(result.saved, 0);
|
|
});
|
|
|
|
it("deduplicates consecutive identical lines in shell output", () => {
|
|
const lines = ["$ ls", "file1.txt", "file1.txt", "file1.txt", "file2.txt"];
|
|
const content = lines.join("\n");
|
|
const result = compressToolResult(content, ALL_ON);
|
|
assert.equal(result.strategy, "shellOutput");
|
|
const deduped = result.compressed.split("\n");
|
|
const file1Count = deduped.filter((l) => l === "file1.txt").length;
|
|
assert.ok(file1Count <= 2, `Expected <= 2 'file1.txt' lines, got ${file1Count}`);
|
|
});
|
|
|
|
it("handles malformed JSON gracefully", () => {
|
|
const content = "{invalid json" + "x".repeat(3000);
|
|
const result = compressToolResult(content, ALL_ON);
|
|
assert.notEqual(result.strategy, "json");
|
|
});
|
|
|
|
it("handles short code without compression", () => {
|
|
const content = "import x from 'y';\nconst z = 1;";
|
|
const result = compressToolResult(content, ALL_ON);
|
|
assert.equal(result.strategy, "none");
|
|
});
|
|
|
|
it("fileContent keeps first 20 and last 5 lines", () => {
|
|
const lines = Array.from({ length: 100 }, (_, i) => `line ${i}`);
|
|
const code = `import x from "y";\nfunction f() {\n${lines.join("\n")}\n}`;
|
|
const result = compressToolResult(code, ALL_ON);
|
|
assert.equal(result.strategy, "fileContent");
|
|
assert.ok(result.compressed.includes("line 0"));
|
|
assert.ok(result.compressed.includes("line 99"));
|
|
});
|
|
|
|
it("grepSearch deduplicates paths", () => {
|
|
const lines = Array.from({ length: 50 }, (_, i) => `src/app.ts:${i + 1}:10: match`);
|
|
const content = lines.join("\n");
|
|
const result = compressToolResult(content, ALL_ON);
|
|
assert.equal(result.strategy, "grepSearch");
|
|
assert.ok(result.compressed.includes("Files:"));
|
|
assert.ok(result.compressed.includes("src/app.ts"));
|
|
});
|
|
|
|
it("errorMessage keeps error type and stack frames", () => {
|
|
const content =
|
|
"Error: TS2304 Cannot find name 'x'\n at func1 (a.ts:1:1)\n at func2 (b.ts:2:2)\n at func3 (c.ts:3:3)";
|
|
const result = compressToolResult(content, ALL_ON);
|
|
assert.equal(result.strategy, "errorMessage");
|
|
assert.ok(result.compressed.includes("Error: TS2304"));
|
|
});
|
|
|
|
it("json array compression preserves first 5 and last 2 elements", () => {
|
|
const arr = Array.from({ length: 20 }, (_, i) => ({ id: i, name: `item${i}` }));
|
|
const content = JSON.stringify(arr);
|
|
const padded = content.padEnd(3000, " ");
|
|
const result = compressToolResult(padded, ALL_ON);
|
|
if (result.strategy === "json") {
|
|
assert.ok(result.compressed.includes("total"));
|
|
}
|
|
});
|
|
|
|
it("returns original content unchanged for 'none' strategy", () => {
|
|
const content = "Just some plain text without any patterns.";
|
|
const result = compressToolResult(content, ALL_ON);
|
|
assert.equal(result.compressed, content);
|
|
assert.equal(result.strategy, "none");
|
|
assert.equal(result.saved, 0);
|
|
});
|
|
});
|