import test from "node:test"; import assert from "node:assert/strict"; import { resolvePolicy } from "./config.ts"; import { buildContextPacket } from "./packet.ts"; import { createEmptyLedger, mergeCandidates, type MemoryCandidate } from "./ledger.ts"; const baseCandidate: Omit = { scope: "session", sourceEntryId: "seed", sourceType: "user", timestamp: 1, confidence: 1, }; function estimateTokens(text: string) { return Math.ceil(text.length / 4); } function memory(candidate: Pick & Partial>): MemoryCandidate { return { ...baseCandidate, ...candidate, sourceEntryId: candidate.sourceEntryId ?? candidate.subject, }; } function buildPolicy(packetTokenCap: number) { return { ...resolvePolicy({ mode: "balanced", contextWindow: 200_000 }), packetTokenCap, }; } test("buildContextPacket keeps top-ranked facts from a section when the cap is tight", () => { const expected = [ "## Active goal", "- Keep packets compact.", "", "## Constraints", "- Preserve the highest-priority constraint.", "", "## Key decisions", "- Render selected sections in stable order.", ].join("\n"); const policy = buildPolicy(estimateTokens(expected)); const ledger = mergeCandidates(createEmptyLedger(), [ memory({ kind: "goal", subject: "goal", text: "Keep packets compact." }), memory({ kind: "constraint", subject: "constraint-a", text: "Preserve the highest-priority constraint.", confidence: 1, timestamp: 3 }), memory({ kind: "constraint", subject: "constraint-b", text: "Avoid dropping every constraint just because one extra bullet is too large for a tight packet cap.", confidence: 0.6, timestamp: 2, }), memory({ kind: "decision", subject: "decision-a", text: "Render selected sections in stable order.", confidence: 0.9, timestamp: 4, sourceType: "assistant", }), ]); const packet = buildContextPacket(ledger, policy); assert.equal(packet.text, expected); assert.equal(packet.estimatedTokens, policy.packetTokenCap); }); test("buildContextPacket uses cross-kind weights when only one lower-priority section can fit", () => { const expected = [ "## Active goal", "- Keep the agent moving.", "", "## Current task", "- Fix packet trimming.", ].join("\n"); const policy = buildPolicy(estimateTokens(expected)); const ledger = mergeCandidates(createEmptyLedger(), [ memory({ kind: "goal", subject: "goal", text: "Keep the agent moving." }), memory({ kind: "decision", subject: "decision-a", text: "Keep logs concise.", confidence: 1, timestamp: 2, sourceType: "assistant", }), memory({ kind: "activeTask", subject: "task-a", text: "Fix packet trimming.", confidence: 1, timestamp: 2, sourceType: "assistant", }), ]); const packet = buildContextPacket(ledger, policy); assert.equal(packet.text, expected); assert.equal(packet.estimatedTokens, policy.packetTokenCap); }); test("buildContextPacket keeps a goal ahead of newer low-priority facts at realistic timestamp scales", () => { const expected = [ "## Active goal", "- Keep the agent on track.", ].join("\n"); const policy = buildPolicy(estimateTokens(expected)); const ledger = mergeCandidates(createEmptyLedger(), [ memory({ kind: "goal", subject: "goal", text: "Keep the agent on track.", timestamp: 1_000_000 }), memory({ kind: "relevantFile", subject: "runtime-file", text: "src/runtime.ts", timestamp: 10_000_000, confidence: 1, sourceType: "assistant", scope: "branch", }), ]); const packet = buildContextPacket(ledger, policy); assert.equal(packet.text, expected); assert.equal(packet.estimatedTokens, policy.packetTokenCap); });