Files
OmniRoute/tests/unit/compression/aggressive.test.ts
oyi77 6bf7b9601d feat(compression): Phase 3 — aggressive mode with summarization, tool compression, and progressive aging
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.
2026-04-28 16:58:17 +07:00

85 lines
3.2 KiB
TypeScript

import { describe, it } from "node:test";
import assert from "node:assert/strict";
import { compressAggressive } from "../../../open-sse/services/compression/aggressive.ts";
import type { AggressiveConfig } from "../../../open-sse/services/compression/types.ts";
function makeMessages(count: number): Array<{ role: string; content: string }> {
return Array.from({ length: count }, (_, i) => ({
role: i % 2 === 0 ? "user" : "assistant",
content: `Message ${i}: ${"x".repeat(200)}`,
}));
}
describe("compressAggressive", () => {
it("returns messages unchanged for empty input", () => {
const result = compressAggressive([]);
assert.equal(result.messages.length, 0);
assert.equal(result.stats.mode, "aggressive");
});
it("returns messages for single message (no compression needed)", () => {
const msgs = [{ role: "user", content: "Hello" }];
const result = compressAggressive(msgs);
assert.equal(result.messages.length, 1);
});
it("compresses 20-message conversation and returns stats", () => {
const msgs = makeMessages(20);
const result = compressAggressive(msgs);
assert.ok(result.messages.length > 0);
assert.equal(result.stats.mode, "aggressive");
assert.ok(typeof result.stats.originalTokens === "number");
assert.ok(typeof result.stats.compressedTokens === "number");
});
it("skips messages with [COMPRESSED: prefix (recursion guard)", () => {
const msgs = [{ role: "assistant", content: "[COMPRESSED:aging:fullSummary] prior summary" }];
const result = compressAggressive(msgs);
const content =
typeof result.messages[0].content === "string" ? result.messages[0].content : "";
assert.ok(content.startsWith("[COMPRESSED:"));
assert.ok(!content.includes("[COMPRESSED:aging:fullSummary][COMPRESSED:"));
});
it("step failure triggers downgrade, not crash", () => {
const msgs = makeMessages(10);
const config: Partial<AggressiveConfig> = {
toolStrategies: {
fileContent: false,
grepSearch: false,
shellOutput: false,
json: false,
errorMessage: false,
},
};
const result = compressAggressive(msgs, config);
assert.ok(result.messages.length > 0);
assert.ok(typeof result.stats.savingsPercent === "number");
});
it("config merge overrides defaults", () => {
const msgs = makeMessages(10);
const config: Partial<AggressiveConfig> = {
maxTokensPerMessage: 100,
minSavingsThreshold: 0.5,
};
const result = compressAggressive(msgs, config);
assert.ok(result.messages.length > 0);
});
it("aggressive stats breakdown is populated", () => {
const msgs = makeMessages(20);
const result = compressAggressive(msgs);
assert.ok(result.stats.aggressive !== undefined);
assert.ok(typeof result.stats.aggressive!.summarizerSavings === "number");
assert.ok(typeof result.stats.aggressive!.toolResultSavings === "number");
assert.ok(typeof result.stats.aggressive!.agingSavings === "number");
});
it("techniquesUsed lists applied strategies", () => {
const msgs = makeMessages(20);
const result = compressAggressive(msgs);
assert.ok(Array.isArray(result.stats.techniquesUsed));
});
});