import assert from "node:assert/strict"; import { describe, it } from "node:test"; import { buildCompactionDigest, collectVisibleFenceIds, CUSTOM_TYPE_DESCRIPTION, CUSTOM_TYPE_VIDEO_DESCRIPTION, DIGEST_IMAGE_CHARS, DIGEST_LEAN_IMAGE_CHARS, DIGEST_MAX_IMAGES, findDescriptions, findVideoDescriptions, truncateForDigest, type VideoDescriptionEntry, } from "../internal.ts"; // SessionEntry minimal shape — typed loose because peer dep types are not loaded in test type Entry = any; const customEntry = (customType: string, data: unknown): Entry => ({ type: "custom", customType, data, }); const video = (hash: string, description = `video ${hash}`): VideoDescriptionEntry => ({ hash, filename: `${hash}.mp4`, mimeType: "video/mp4", description, }); describe("findVideoDescriptions", () => { it("collects hash → entry from video description entries", () => { const entries: Entry[] = [ customEntry(CUSTOM_TYPE_VIDEO_DESCRIPTION, video("v1")), customEntry(CUSTOM_TYPE_DESCRIPTION, { hash: "img", description: "not a video" }), customEntry(CUSTOM_TYPE_VIDEO_DESCRIPTION, { hash: "", description: "skip" }), customEntry(CUSTOM_TYPE_VIDEO_DESCRIPTION, video("v2")), ]; const map = findVideoDescriptions(entries); assert.equal(map.size, 2); assert.equal(map.get("v1")?.filename, "v1.mp4"); assert.equal(map.get("v2")?.mimeType, "video/mp4"); }); it("keeps the most recent entry per hash", () => { const entries: Entry[] = [ customEntry(CUSTOM_TYPE_VIDEO_DESCRIPTION, video("v1", "old")), customEntry(CUSTOM_TYPE_VIDEO_DESCRIPTION, video("v1", "new")), ]; assert.equal(findVideoDescriptions(entries).get("v1")?.description, "new"); }); it("moves a re-described hash to the end of the iteration order", () => { const entries: Entry[] = [ customEntry(CUSTOM_TYPE_VIDEO_DESCRIPTION, video("v1", "first")), customEntry(CUSTOM_TYPE_VIDEO_DESCRIPTION, video("v2", "second")), customEntry(CUSTOM_TYPE_VIDEO_DESCRIPTION, video("v1", "updated")), ]; assert.deepEqual([...findVideoDescriptions(entries).keys()], ["v2", "v1"]); }); it("backfills filename and mimeType on malformed entries instead of crashing later", () => { const entries: Entry[] = [ customEntry(CUSTOM_TYPE_VIDEO_DESCRIPTION, { hash: "v1", description: "d" }), customEntry(CUSTOM_TYPE_VIDEO_DESCRIPTION, { hash: "v2", description: "d", filename: 42, mimeType: null }), ]; const map = findVideoDescriptions(entries); assert.equal(map.get("v1")?.filename, "unknown"); assert.equal(map.get("v1")?.mimeType, "application/octet-stream"); assert.equal(map.get("v2")?.filename, "unknown"); assert.equal(map.get("v2")?.mimeType, "application/octet-stream"); // The digest builder accepts the backfilled entries without throwing. const digest = buildCompactionDigest([], [...map.values()]); assert.ok(digest.includes('file="unknown"')); }); }); describe("findDescriptions ordering", () => { it("moves a re-described hash to the end of the iteration order", () => { const entries: Entry[] = [ customEntry(CUSTOM_TYPE_DESCRIPTION, { hash: "a", description: "first" }), customEntry(CUSTOM_TYPE_DESCRIPTION, { hash: "b", description: "second" }), customEntry(CUSTOM_TYPE_DESCRIPTION, { hash: "a", description: "updated" }), ]; const map = findDescriptions(entries); assert.deepEqual([...map.keys()], ["b", "a"]); assert.equal(map.get("a"), "updated"); }); }); describe("truncateForDigest", () => { it("returns short text unchanged", () => { assert.equal(truncateForDigest("short text", 100), "short text"); }); it("trims surrounding whitespace", () => { assert.equal(truncateForDigest(" padded ", 100), "padded"); }); it("cuts long text at a word boundary and marks the truncation", () => { // slice(0,20) is "alpha beta gamma del"; the boundary cut must drop "del". const out = truncateForDigest("alpha beta gamma delta epsilon", 20); assert.equal(out, "alpha beta gamma … [truncated]"); }); it("hard-cuts when there is no usable word boundary", () => { const out = truncateForDigest("a".repeat(50), 20); assert.equal(out, `${"a".repeat(20)} … [truncated]`); }); it("never splits a surrogate pair on a hard cut", () => { // "💥" is 2 UTF-16 code units; a cut at max=21 would land mid-pair. const out = truncateForDigest(`${"x".repeat(20)}💥${"y".repeat(30)}`, 21); assert.ok(!/[\uD800-\uDBFF]$/.test(out.replace(" … [truncated]", ""))); assert.ok(!out.includes("�")); assert.equal(out, `${"x".repeat(20)} … [truncated]`); }); }); describe("collectVisibleFenceIds", () => { const h1 = "a".repeat(32); const h2 = "b".repeat(32); const h3 = "c".repeat(32); it("collects ids from description, analysis, joint, and video fences", () => { const text = [ `body\n`, `body\n`, `dimensions='[{"image":"${h3}","width":5}]'`, `t\n`, ].join("\n"); const ids = collectVisibleFenceIds(text); assert.deepEqual([...ids].sort(), [h1, h2, h3]); }); it("ignores bare hashes and user-typed recall references", () => { const ids = collectVisibleFenceIds(`zoom into image="${h1}" and also ${h2} please`); assert.equal(ids.size, 0); }); it("accumulates into a provided set", () => { const out = new Set(); collectVisibleFenceIds(`x\n`, out); collectVisibleFenceIds(`x\n`, out); assert.equal(out.size, 2); }); }); describe("buildCompactionDigest", () => { it("returns empty string when there is nothing to restore", () => { assert.equal(buildCompactionDigest([], []), ""); }); it("restores image fences with id, meta, and untrusted warning", () => { const digest = buildCompactionDigest( [{ hash: "hash-a", description: "a red square", meta: { width: 10, height: 20, filename: "sq.png" } }], [], ); assert.ok(digest.includes("post-compaction recall")); assert.ok(digest.includes('image="hash-a"')); assert.ok(digest.includes('width="10"')); assert.ok(digest.includes('filename="sq.png"')); assert.ok(digest.includes("a red square")); assert.ok(digest.includes("UNTRUSTED")); }); it("includes video fences", () => { const digest = buildCompactionDigest([], [video("v9", "a talking head")]); assert.ok(digest.includes('hash="v9"')); assert.ok(digest.includes('file="v9.mp4"')); assert.ok(digest.includes("a talking head")); assert.ok(digest.includes("1 video/audio file")); }); it("mentions analyze_image recall only when the tool is enabled", () => { const imgs = [{ hash: "h", description: "d" }]; assert.ok(buildCompactionDigest(imgs, [], { toolEnabled: true }).includes("analyze_image")); assert.ok(!buildCompactionDigest(imgs, [], { toolEnabled: false }).includes("analyze_image")); }); it("keeps only the most recent images when over the cap", () => { const imgs = Array.from({ length: DIGEST_MAX_IMAGES + 3 }, (_, i) => ({ hash: `h${i}`, description: `d${i}`, })); const digest = buildCompactionDigest(imgs, []); assert.ok(!digest.includes('image="h0"'), "oldest images dropped"); assert.ok(!digest.includes('image="h2"')); assert.ok(digest.includes('image="h3"')); assert.ok(digest.includes(`image="h${DIGEST_MAX_IMAGES + 2}"`)); }); it("applies tighter budgets in lean mode", () => { const long = "word ".repeat(400); const [full] = buildCompactionDigest([{ hash: "h", description: long }], []) .split("\n\n") .slice(1); const [lean] = buildCompactionDigest([{ hash: "h", description: long }], [], { lean: true }) .split("\n\n") .slice(1); assert.ok(full!.length > lean!.length); assert.ok(lean!.length < DIGEST_LEAN_IMAGE_CHARS + 200); assert.ok(full!.length < DIGEST_IMAGE_CHARS + 200); }); it("counts both media kinds in the header", () => { const digest = buildCompactionDigest( [ { hash: "a", description: "d1" }, { hash: "b", description: "d2" }, ], [video("v1"), video("v2")], ); assert.ok(digest.includes("2 images and 2 video/audio files")); }); });