chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,220 @@
|
||||
import { describe, it } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import {
|
||||
RuleBasedSummarizer,
|
||||
createSummarizer,
|
||||
} from "../../../open-sse/services/compression/summarizer.ts";
|
||||
|
||||
function makeMessages(messages: Array<{ role: string; content: string }>) {
|
||||
return messages;
|
||||
}
|
||||
|
||||
describe("RuleBasedSummarizer", () => {
|
||||
const summarizer = new RuleBasedSummarizer();
|
||||
|
||||
it("returns empty string for empty messages array", () => {
|
||||
const result = summarizer.summarize([]);
|
||||
assert.equal(result, "");
|
||||
});
|
||||
|
||||
it("extracts intent from single user message", () => {
|
||||
const result = summarizer.summarize(
|
||||
makeMessages([
|
||||
{ role: "user", content: "fix: bug in src/lib/db/core.ts causing Error: TS2304" },
|
||||
])
|
||||
);
|
||||
assert.ok(result.startsWith("[COMPRESSED:summary]"));
|
||||
assert.ok(result.includes("fix:"));
|
||||
assert.ok(result.includes("src/lib/db/core.ts"));
|
||||
});
|
||||
|
||||
it("extracts intent from first user message when no trigger phrase", () => {
|
||||
const result = summarizer.summarize(
|
||||
makeMessages([{ role: "user", content: "How do I implement authentication?" }])
|
||||
);
|
||||
assert.ok(result.startsWith("[COMPRESSED:summary]"));
|
||||
assert.ok(result.includes("How do I implement"));
|
||||
});
|
||||
|
||||
it("extracts file paths from messages", () => {
|
||||
const result = summarizer.summarize(
|
||||
makeMessages([
|
||||
{
|
||||
role: "user",
|
||||
content: "Edit src/lib/db/core.ts and fix the bug in tests/unit/db/compression.test.ts",
|
||||
},
|
||||
])
|
||||
);
|
||||
assert.ok(result.includes("src/lib/db/core.ts"));
|
||||
assert.ok(result.includes("tests/unit/db/compression.test.ts"));
|
||||
});
|
||||
|
||||
it("extracts errors from messages", () => {
|
||||
const result = summarizer.summarize(
|
||||
makeMessages([
|
||||
{
|
||||
role: "assistant",
|
||||
content: "The build failed with Error: TS2304 and Exception: NullPointerException",
|
||||
},
|
||||
])
|
||||
);
|
||||
assert.ok(result.includes("Error: TS2304") || result.includes("Exception:"));
|
||||
});
|
||||
|
||||
it("extracts last assistant decision", () => {
|
||||
const result = summarizer.summarize(
|
||||
makeMessages([
|
||||
{ role: "user", content: "fix the bug" },
|
||||
{ role: "assistant", content: "I've patched the file and will run tests next." },
|
||||
])
|
||||
);
|
||||
assert.ok(result.includes("Last decision:"));
|
||||
assert.ok(result.includes("patched"));
|
||||
});
|
||||
|
||||
it("skips messages with [COMPRESSED: prefix", () => {
|
||||
const result = summarizer.summarize(
|
||||
makeMessages([
|
||||
{ role: "system", content: "[COMPRESSED:summary] prior context" },
|
||||
{ role: "user", content: "implement: new feature" },
|
||||
])
|
||||
);
|
||||
assert.ok(!result.includes("prior context"));
|
||||
assert.ok(result.includes("implement:"));
|
||||
});
|
||||
|
||||
it("trims code fences in long code blocks", () => {
|
||||
const longCode = Array.from({ length: 50 }, (_, i) => `line ${i}`).join("\n");
|
||||
const content = "```ts\n" + longCode + "\n```";
|
||||
const result = summarizer.summarize(makeMessages([{ role: "assistant", content: content }]), {
|
||||
preserveCode: true,
|
||||
});
|
||||
assert.ok(result.includes("[COMPRESSED:summary]"));
|
||||
assert.ok(result.includes("line 0"));
|
||||
});
|
||||
|
||||
it("respects maxLen option", () => {
|
||||
const longContent = "x".repeat(5000);
|
||||
const result = summarizer.summarize(makeMessages([{ role: "user", content: longContent }]), {
|
||||
maxLen: 100,
|
||||
});
|
||||
assert.ok(result.length <= 103);
|
||||
});
|
||||
|
||||
it("respects preserveCode=false option", () => {
|
||||
const result = summarizer.summarize(
|
||||
makeMessages([
|
||||
{ role: "user", content: "fix: the bug" },
|
||||
{ role: "assistant", content: "```ts\nconst x = 1;\nconst y = 2;\n```" },
|
||||
]),
|
||||
{ preserveCode: false }
|
||||
);
|
||||
assert.ok(result.startsWith("[COMPRESSED:summary]"));
|
||||
});
|
||||
|
||||
it("handles mixed user/assistant turns", () => {
|
||||
const result = summarizer.summarize(
|
||||
makeMessages([
|
||||
{ role: "user", content: "implement: auth module" },
|
||||
{ role: "assistant", content: "Created src/auth/login.ts" },
|
||||
{ role: "user", content: "fix: typo in login.ts" },
|
||||
{ role: "assistant", content: "Fixed the typo." },
|
||||
])
|
||||
);
|
||||
assert.ok(result.includes("implement:"));
|
||||
assert.ok(result.includes("fix:"));
|
||||
assert.ok(result.includes("src/auth/login.ts"));
|
||||
});
|
||||
|
||||
it("handles messages with array content (tool results)", () => {
|
||||
const result = summarizer.summarize([
|
||||
{ role: "user", content: [{ type: "text", text: "fix: the error in app.ts" }] },
|
||||
] as unknown[]);
|
||||
assert.ok(result.includes("fix:"));
|
||||
});
|
||||
|
||||
it("handles messages with undefined content", () => {
|
||||
const result = summarizer.summarize([{ role: "user" }] as unknown[]);
|
||||
assert.equal(result, "");
|
||||
});
|
||||
|
||||
it("extracts multiple error formats", () => {
|
||||
const result = summarizer.summarize(
|
||||
makeMessages([
|
||||
{ role: "assistant", content: "Build failed: Error: TS2304 and error TS2551 found" },
|
||||
])
|
||||
);
|
||||
assert.ok(result.includes("Error: TS2304") || result.includes("error TS2551"));
|
||||
});
|
||||
|
||||
it("limits file paths to 20 entries", () => {
|
||||
const files = Array.from({ length: 30 }, (_, i) => `src/file${i}.ts`).join(" ");
|
||||
const result = summarizer.summarize(makeMessages([{ role: "user", content: `fix: ${files}` }]));
|
||||
const filesSection = result.match(/Files touched: (.+?)\./);
|
||||
assert.ok(filesSection);
|
||||
const fileCount = filesSection[1].split(",").length;
|
||||
assert.ok(fileCount <= 20, `Expected <= 20 files, got ${fileCount}`);
|
||||
});
|
||||
|
||||
it("limits errors to 10 entries", () => {
|
||||
const errors = Array.from({ length: 15 }, (_, i) => `Error: bug${i}`).join(". ");
|
||||
const result = summarizer.summarize(makeMessages([{ role: "assistant", content: errors }]));
|
||||
const errorsSection = result.match(/Errors: (.+?)\./);
|
||||
if (errorsSection) {
|
||||
const errorCount = errorsSection[1].split(";").length;
|
||||
assert.ok(errorCount <= 10, `Expected <= 10 errors, got ${errorCount}`);
|
||||
}
|
||||
});
|
||||
|
||||
it("truncates last decision to 200 chars", () => {
|
||||
const longDecision = "x".repeat(500);
|
||||
const result = summarizer.summarize(
|
||||
makeMessages([{ role: "assistant", content: longDecision }])
|
||||
);
|
||||
const decisionMatch = result.match(/Last decision: (.+?)\./s);
|
||||
if (decisionMatch) {
|
||||
assert.ok(decisionMatch[1].length <= 210, `Decision too long: ${decisionMatch[1].length}`);
|
||||
}
|
||||
});
|
||||
|
||||
it("handles single message with no trigger phrase", () => {
|
||||
const result = summarizer.summarize(
|
||||
makeMessages([{ role: "user", content: "Hello, how are you?" }])
|
||||
);
|
||||
assert.ok(result.startsWith("[COMPRESSED:summary]"));
|
||||
assert.ok(result.includes("Hello"));
|
||||
});
|
||||
|
||||
it("createSummarizer factory returns RuleBasedSummarizer instance", () => {
|
||||
const s = createSummarizer();
|
||||
assert.ok(s instanceof RuleBasedSummarizer);
|
||||
assert.equal(s.summarize([]), "");
|
||||
});
|
||||
|
||||
it("handles messages with only system role", () => {
|
||||
const result = summarizer.summarize(
|
||||
makeMessages([{ role: "system", content: "You are a helpful assistant." }])
|
||||
);
|
||||
assert.ok(result.startsWith("[COMPRESSED:summary]"));
|
||||
});
|
||||
|
||||
it("handles empty string content", () => {
|
||||
const result = summarizer.summarize(makeMessages([{ role: "user", content: "" }]));
|
||||
assert.equal(result, "");
|
||||
});
|
||||
|
||||
it("produces summary with all sections for rich input", () => {
|
||||
const result = summarizer.summarize(
|
||||
makeMessages([
|
||||
{ role: "user", content: "implement: auth module in src/auth/login.ts" },
|
||||
{ role: "assistant", content: "Created the auth module. Error: TS2304 found." },
|
||||
{ role: "user", content: "fix: the TS2304 error" },
|
||||
{ role: "assistant", content: "Fixed the type error in login.ts" },
|
||||
])
|
||||
);
|
||||
assert.ok(result.includes("Intents:"));
|
||||
assert.ok(result.includes("Files touched:"));
|
||||
assert.ok(result.includes("Errors:"));
|
||||
assert.ok(result.includes("Last decision:"));
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user