initial commit
This commit is contained in:
130
src/packet.test.ts
Normal file
130
src/packet.test.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
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<MemoryCandidate, "kind" | "subject" | "text"> = {
|
||||
scope: "session",
|
||||
sourceEntryId: "seed",
|
||||
sourceType: "user",
|
||||
timestamp: 1,
|
||||
confidence: 1,
|
||||
};
|
||||
|
||||
function estimateTokens(text: string) {
|
||||
return Math.ceil(text.length / 4);
|
||||
}
|
||||
|
||||
function memory(candidate: Pick<MemoryCandidate, "kind" | "subject" | "text"> & Partial<Omit<MemoryCandidate, "kind" | "subject" | "text">>): 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);
|
||||
});
|
||||
Reference in New Issue
Block a user