import { join } from "node:path"; import { fileURLToPath, pathToFileURL } from "node:url"; import { resolvePrimeRoot } from "./prime-root.mjs"; const primeRoot = resolvePrimeRoot(); const { loadExtensions } = await import(pathToFileURL(join(primeRoot, "dist/core/extensions/loader.js"))); const ai = await import(pathToFileURL(join( primeRoot, "node_modules/@earendil-works/pi-ai/dist/index.js", ))); const extensionPath = fileURLToPath(new URL("../index.ts", import.meta.url)); const registration = ai.registerFauxProvider({ models: [{ id: "snapcompact-text-tracking", name: "SnapCompact text tracking test", input: ["text"], reasoning: false, contextWindow: 128_000, maxTokens: 8192, }], tokensPerSecond: 100_000, }); const model = registration.getModel(); registration.setResponses([ ai.fauxAssistantMessage("first tracked native summary"), ai.fauxAssistantMessage("second tracked native summary"), ]); const usage = { input: 1000, output: 100, cacheRead: 0, cacheWrite: 0, totalTokens: 1100, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }, }; const messages = [ { role: "user", content: "continue tracked compaction", timestamp: 1 }, { role: "assistant", content: [{ type: "text", text: "tracked evidence" }], api: model.api, provider: model.provider, model: model.id, usage, stopReason: "stop", timestamp: 2, }, ]; const preparation = (read, edited, previousSummary) => ({ firstKeptEntryId: "kept", messagesToSummarize: messages, turnPrefixMessages: [], isSplitTurn: false, tokensBefore: 20_000, previousSummary, fileOps: { read: new Set(read), written: new Set(), edited: new Set(edited) }, settings: { enabled: true, reserveTokens: 8192, keepRecentTokens: 10_000 }, }); const trackedEntry = (id, details, summary = "prior summary") => ({ type: "compaction", id, parentId: null, timestamp: Date.now(), summary, firstKeptEntryId: "kept", tokensBefore: 10_000, details, fromHook: true, }); let branch = [trackedEntry("tracked-1", { readFiles: ["old-read.ts"], modifiedFiles: ["old-modified.ts"], snapcompactText: { schema: 1 }, })]; const ctx = { cwd: process.cwd(), hasUI: false, ui: { notify() {} }, model, modelRegistry: { async getApiKeyAndHeaders() { return { ok: true, apiKey: "snapcompact-test" }; }, }, sessionManager: { getBranch: () => branch, getEntries: () => branch, getSessionFile: () => undefined, getSessionDir: () => process.cwd(), getSessionId: () => "tracking", }, getSystemPrompt: () => "test system prompt", }; const loaded = await loadExtensions([extensionPath], process.cwd()); if (loaded.errors.length) throw new Error(JSON.stringify(loaded.errors)); loaded.runtime.getThinkingLevel = () => "medium"; const before = loaded.extensions[0].handlers.get("session_before_compact")[0]; const signal = new AbortController().signal; try { const first = await before({ type: "session_before_compact", preparation: preparation(["new-read.ts"], ["new-modified.ts"], "prior summary"), branchEntries: branch, customInstructions: undefined, signal, }, ctx); const firstDetails = first?.compaction?.details; if (firstDetails?.snapcompactText?.schema !== 1) { throw new Error("tracked native compaction lost its extension marker"); } for (const file of ["old-read.ts", "new-read.ts"]) { if (!firstDetails.readFiles.includes(file)) throw new Error(`missing cumulative read file ${file}`); } for (const file of ["old-modified.ts", "new-modified.ts"]) { if (!firstDetails.modifiedFiles.includes(file)) throw new Error(`missing cumulative modified file ${file}`); } branch = [trackedEntry("tracked-2", firstDetails, first.compaction.summary)]; const second = await before({ type: "session_before_compact", preparation: preparation(["third-read.ts"], ["third-modified.ts"], first.compaction.summary), branchEntries: branch, customInstructions: undefined, signal, }, ctx); const secondDetails = second?.compaction?.details; for (const file of ["old-read.ts", "new-read.ts", "third-read.ts"]) { if (!secondDetails.readFiles.includes(file)) throw new Error(`second compaction lost read file ${file}`); } for (const file of ["old-modified.ts", "new-modified.ts", "third-modified.ts"]) { if (!secondDetails.modifiedFiles.includes(file)) throw new Error(`second compaction lost modified file ${file}`); } console.log(JSON.stringify({ trackedNativeCompactions: 2, cumulativeReadFiles: secondDetails.readFiles.length, cumulativeModifiedFiles: secondDetails.modifiedFiles.length, }, null, 2)); } finally { registration.unregister(); }