Files
kilocode/packages/kilo-vscode/tests/unit/slim-metadata.test.ts
T

383 lines
13 KiB
TypeScript

import { describe, it, expect } from "bun:test"
import { slimInfo, slimPart } from "../../src/kilo-provider/slim-metadata"
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function part(tool: string, state: Record<string, unknown>) {
return { type: "tool", id: "p1", tool, state }
}
function bytes(obj: unknown): number {
return JSON.stringify(obj).length
}
function bigPatch() {
return `Index: a.ts\n===================================================================\n--- a.ts\t\n+++ a.ts\t\n@@ -1,1 +1,1 @@\n-${"x".repeat(70_000)}\n+${"y".repeat(70_000)}\n`
}
/**
* Hard ceiling per slimmed tool state (JSON bytes). Real slimmed parts
* should be well under this. If a slimmer leaks even one file-content
* field (~50-500 KB each) the test blows past this immediately.
*/
const MAX_SLIM_BYTES = 10_000
const PATCH =
"Index: a.ts\n===================================================================\n--- a.ts\t\n+++ a.ts\t\n@@ -1,2 +1,2 @@\n one\n-two\n+three\n"
const BIG = "x".repeat(200_000) // 200 KB — typical file content size
const DIAG = [
{ range: { start: { line: 1, character: 0 }, end: { line: 1, character: 5 } }, message: "err", severity: 1 },
]
// Regression for #13001: slimmers used to rebuild `metadata` from an explicit allowlist that
// didn't include `approval`, silently dropping the auto-approval reason (and the
// outside-workspace note) before it ever reached the webview.
const APPROVAL = { source: "agent", agent: "code", outsideWorkspace: true, outsideWorkspacePath: "/tmp/a.ts" }
// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------
describe("slimInfo", () => {
it("drops summary patches while keeping visible diff fields", () => {
const info = {
role: "user",
summary: {
title: "Updated files",
diffs: [{ file: "a.ts", patch: BIG, additions: 3, deletions: 1, status: "modified" }],
},
}
const slim = slimInfo(info)
expect(slim.summary.title).toBe("Updated files")
expect(slim.summary.diffs).toEqual([{ file: "a.ts", additions: 3, deletions: 1, status: "modified" }])
expect(info.summary.diffs[0]?.patch).toBe(BIG)
})
it("passes through summaries without patches unchanged", () => {
const info = { role: "user", summary: { diffs: [{ file: "a.ts", additions: 1, deletions: 0 }] } }
expect(slimInfo(info)).toBe(info)
})
})
describe("slimPart", () => {
it("passes through non-tool parts unchanged", () => {
const text = { type: "text", id: "t1", content: "hello" }
expect(slimPart(text)).toBe(text)
})
it("passes through unknown tool types unchanged", () => {
const p = part("some_new_tool", { status: "completed", metadata: { big: BIG } })
expect(slimPart(p)).toBe(p)
})
it("drops encrypted OpenAI reasoning metadata while keeping other provider fields", () => {
const reasoning = {
type: "reasoning",
id: "r1",
text: "Considering options",
metadata: {
openai: { reasoningEncryptedContent: BIG, itemId: "item-1" },
anthropic: { signature: "sig-1" },
},
}
const slim = slimPart(reasoning)
expect(slim.metadata).toEqual({ openai: { itemId: "item-1" }, anthropic: { signature: "sig-1" } })
expect(reasoning.metadata.openai.reasoningEncryptedContent).toBe(BIG)
})
// -----------------------------------------------------------------------
// edit
// -----------------------------------------------------------------------
describe("edit", () => {
const heavy = part("edit", {
status: "completed",
input: { filePath: "/a.ts", oldString: "old", newString: "new" },
output: "Edit applied successfully.",
metadata: {
diff: BIG,
filediff: { file: "/a.ts", patch: PATCH, before: BIG, after: BIG, additions: 3, deletions: 1 },
diagnostics: { "/a.ts": DIAG },
approval: APPROVAL,
},
})
it("stays under size cap", () => {
expect(bytes(slimPart(heavy))).toBeLessThan(MAX_SLIM_BYTES)
})
it("keeps filediff counts, diagnostics, and approval", () => {
const slim = slimPart(heavy) as Record<string, any>
const meta = slim.state.metadata
expect(meta.filediff.file).toBe("/a.ts")
expect(meta.filediff.patch).toBe(PATCH)
expect(meta.filediff.additions).toBe(3)
expect(meta.filediff.deletions).toBe(1)
expect(meta.diagnostics).toEqual({ "/a.ts": DIAG })
expect(meta.approval).toEqual(APPROVAL)
})
it("keeps output and input intact", () => {
const slim = slimPart(heavy) as Record<string, any>
expect(slim.state.output).toBe("Edit applied successfully.")
expect(slim.state.input.filePath).toBe("/a.ts")
})
it("drops unknown heavy metadata fields", () => {
const withUnknown = part("edit", {
...heavy.state,
metadata: { ...(heavy.state.metadata as object), newUpstreamBlob: BIG, otherData: BIG },
})
expect(bytes(slimPart(withUnknown))).toBeLessThan(MAX_SLIM_BYTES)
})
it("drops oversized filediff patches", () => {
const wide = part("edit", {
...heavy.state,
metadata: {
...(heavy.state.metadata as object),
filediff: { file: "/a.ts", patch: bigPatch(), before: BIG, after: BIG, additions: 1, deletions: 1 },
},
})
const slim = slimPart(wide) as Record<string, any>
expect(slim.state.metadata.filediff.patch).toBeUndefined()
expect(bytes(slim)).toBeLessThan(MAX_SLIM_BYTES)
})
})
// -----------------------------------------------------------------------
// apply_patch
// -----------------------------------------------------------------------
describe("apply_patch", () => {
const heavy = part("apply_patch", {
status: "completed",
input: { patchText: BIG },
output: "Success. Updated the following files:\n a.ts",
metadata: {
diff: BIG,
files: [
{
filePath: "/a.ts",
relativePath: "a.ts",
type: "update",
before: BIG,
after: BIG,
patch: PATCH,
diff: BIG,
additions: 5,
deletions: 2,
},
{
filePath: "/b.ts",
relativePath: "b.ts",
type: "add",
before: undefined,
after: BIG,
diff: BIG,
additions: 10,
deletions: 0,
movePath: undefined,
},
],
diagnostics: { "/a.ts": DIAG },
approval: APPROVAL,
},
})
it("stays under size cap", () => {
expect(bytes(slimPart(heavy))).toBeLessThan(MAX_SLIM_BYTES)
})
it("keeps file summary fields, diagnostics, and approval", () => {
const slim = slimPart(heavy) as Record<string, any>
const meta = slim.state.metadata
expect(meta.files[0].filePath).toBe("/a.ts")
expect(meta.files[0].relativePath).toBe("a.ts")
expect(meta.files[0].type).toBe("update")
expect(meta.files[0].patch).toBe(PATCH)
expect(meta.files[0].additions).toBe(5)
expect(meta.files[1].type).toBe("add")
expect(meta.diagnostics).toEqual({ "/a.ts": DIAG })
expect(meta.approval).toEqual(APPROVAL)
})
it("drops unknown heavy metadata fields", () => {
const withUnknown = part("apply_patch", {
...heavy.state,
metadata: { ...(heavy.state.metadata as object), rawPatch: BIG, snapshot: BIG },
})
expect(bytes(slimPart(withUnknown))).toBeLessThan(MAX_SLIM_BYTES)
})
it("drops unknown heavy fields inside files[]", () => {
const withUnknown = part("apply_patch", {
...heavy.state,
metadata: {
...(heavy.state.metadata as Record<string, unknown>),
files: [
{
filePath: "/a.ts",
relativePath: "a.ts",
type: "update",
additions: 1,
deletions: 0,
newHeavyField: BIG,
anotherBlob: BIG,
},
],
},
})
expect(bytes(slimPart(withUnknown))).toBeLessThan(MAX_SLIM_BYTES)
})
it("drops oversized per-file patches", () => {
const wide = part("apply_patch", {
...heavy.state,
metadata: {
...(heavy.state.metadata as Record<string, unknown>),
files: [
{
filePath: "/a.ts",
relativePath: "a.ts",
type: "update",
patch: bigPatch(),
additions: 1,
deletions: 1,
},
],
},
})
const slim = slimPart(wide) as Record<string, any>
expect(slim.state.metadata.files[0].patch).toBeUndefined()
expect(bytes(slim)).toBeLessThan(MAX_SLIM_BYTES)
})
})
// -----------------------------------------------------------------------
// multiedit
// -----------------------------------------------------------------------
describe("multiedit", () => {
const heavy = part("multiedit", {
status: "completed",
input: { edits: [] },
output: "Applied 2 edits.",
metadata: {
diff: BIG,
diagnostics: { "/a.ts": DIAG },
results: [
{
filediff: { file: "/a.ts", patch: PATCH, before: BIG, after: BIG, additions: 1, deletions: 1 },
diagnostics: { "/a.ts": DIAG },
diff: BIG,
},
{ filediff: { file: "/b.ts", before: BIG, after: BIG, additions: 2, deletions: 0 }, diagnostics: {} },
],
approval: APPROVAL,
},
})
it("stays under size cap", () => {
expect(bytes(slimPart(heavy))).toBeLessThan(MAX_SLIM_BYTES)
})
it("keeps filediff counts, per-result diagnostics, and approval", () => {
const slim = slimPart(heavy) as Record<string, any>
const meta = slim.state.metadata
expect(meta.results[0].filediff.file).toBe("/a.ts")
expect(meta.results[0].filediff.patch).toBe(PATCH)
expect(meta.results[0].filediff.additions).toBe(1)
expect(meta.results[0].diagnostics).toEqual({ "/a.ts": DIAG })
expect(meta.results[1].filediff.file).toBe("/b.ts")
expect(meta.diagnostics).toEqual({ "/a.ts": DIAG })
expect(meta.approval).toEqual(APPROVAL)
})
it("drops unknown heavy metadata fields", () => {
const withUnknown = part("multiedit", {
...heavy.state,
metadata: { ...(heavy.state.metadata as object), rawCombinedDiff: BIG },
})
expect(bytes(slimPart(withUnknown))).toBeLessThan(MAX_SLIM_BYTES)
})
it("drops unknown heavy fields inside results[]", () => {
const withUnknown = part("multiedit", {
...heavy.state,
metadata: {
...(heavy.state.metadata as Record<string, unknown>),
results: [{ filediff: { file: "/a.ts", additions: 1, deletions: 0 }, diagnostics: {}, newBlob: BIG }],
},
})
expect(bytes(slimPart(withUnknown))).toBeLessThan(MAX_SLIM_BYTES)
})
})
// -----------------------------------------------------------------------
// write
// -----------------------------------------------------------------------
describe("write", () => {
const heavy = part("write", {
status: "completed",
input: { filePath: "/a.ts", content: BIG },
output: "File written.",
metadata: {
filepath: "/a.ts",
exists: true,
diff: BIG,
filediff: { file: "/a.ts", patch: PATCH, before: BIG, after: BIG, additions: 100, deletions: 0 },
diagnostics: { "/a.ts": DIAG },
approval: APPROVAL,
},
})
it("stays under size cap", () => {
expect(bytes(slimPart(heavy))).toBeLessThan(MAX_SLIM_BYTES)
})
it("keeps filepath, exists, filediff counts, diagnostics, and approval", () => {
const slim = slimPart(heavy) as Record<string, any>
const meta = slim.state.metadata
expect(meta.filepath).toBe("/a.ts")
expect(meta.exists).toBe(true)
expect(meta.filediff.file).toBe("/a.ts")
expect(meta.filediff.patch).toBe(PATCH)
expect(meta.filediff.additions).toBe(100)
expect(meta.filediff.deletions).toBe(0)
expect(meta.diagnostics).toEqual({ "/a.ts": DIAG })
expect(meta.approval).toEqual(APPROVAL)
})
it("drops unknown heavy metadata fields", () => {
const withUnknown = part("write", {
...heavy.state,
metadata: { ...(heavy.state.metadata as object), compiled: BIG },
})
expect(bytes(slimPart(withUnknown))).toBeLessThan(MAX_SLIM_BYTES)
})
})
// -----------------------------------------------------------------------
// bash
// -----------------------------------------------------------------------
describe("bash", () => {
const heavy = part("bash", {
status: "completed",
input: { command: "ls" },
output: BIG,
metadata: { output: BIG },
})
it("truncates metadata.output and state.output", () => {
const slim = slimPart(heavy) as Record<string, any>
expect(slim.state.metadata.output.length).toBeLessThan(BIG.length)
expect((slim.state.output as string).length).toBeLessThan(BIG.length)
})
it("stays under size cap", () => {
expect(bytes(slimPart(heavy))).toBeLessThan(MAX_SLIM_BYTES)
})
})
})