diff --git a/src/gateway/session-compaction-checkpoints.test.ts b/src/gateway/session-compaction-checkpoints.test.ts new file mode 100644 index 00000000000..485dd1b7931 --- /dev/null +++ b/src/gateway/session-compaction-checkpoints.test.ts @@ -0,0 +1,58 @@ +import fsSync from "node:fs"; +import fs from "node:fs/promises"; +import os from "node:os"; +import path from "node:path"; +import { SessionManager } from "@mariozechner/pi-coding-agent"; +import { afterEach, describe, expect, test } from "vitest"; +import { + captureCompactionCheckpointSnapshot, + cleanupCompactionCheckpointSnapshot, +} from "./session-compaction-checkpoints.js"; + +const tempDirs: string[] = []; + +afterEach(async () => { + await Promise.all(tempDirs.splice(0).map((dir) => fs.rm(dir, { recursive: true, force: true }))); +}); + +describe("session-compaction-checkpoints", () => { + test("capture stores the copied pre-compaction transcript path and cleanup removes only the copy", async () => { + const dir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-checkpoint-")); + tempDirs.push(dir); + + const session = SessionManager.create(dir, dir); + session.appendMessage({ role: "user", content: "before compaction" }); + session.appendMessage({ + role: "assistant", + content: [{ type: "text", text: "working on it" }], + }); + + const sessionFile = session.getSessionFile(); + const leafId = session.getLeafId(); + expect(sessionFile).toBeTruthy(); + expect(leafId).toBeTruthy(); + + const originalBefore = await fs.readFile(sessionFile!, "utf-8"); + const snapshot = captureCompactionCheckpointSnapshot({ + sessionManager: session, + sessionFile: sessionFile!, + }); + + expect(snapshot).not.toBeNull(); + expect(snapshot?.leafId).toBe(leafId); + expect(snapshot?.sessionFile).not.toBe(sessionFile); + expect(snapshot?.sessionFile).toContain(".checkpoint."); + expect(fsSync.existsSync(snapshot!.sessionFile)).toBe(true); + expect(await fs.readFile(snapshot!.sessionFile, "utf-8")).toBe(originalBefore); + + session.appendCompaction("checkpoint summary", leafId!, 123, { ok: true }); + + expect(await fs.readFile(snapshot!.sessionFile, "utf-8")).toBe(originalBefore); + expect(await fs.readFile(sessionFile!, "utf-8")).not.toBe(originalBefore); + + await cleanupCompactionCheckpointSnapshot(snapshot); + + expect(fsSync.existsSync(snapshot!.sessionFile)).toBe(false); + expect(fsSync.existsSync(sessionFile!)).toBe(true); + }); +}); diff --git a/src/gateway/session-compaction-checkpoints.ts b/src/gateway/session-compaction-checkpoints.ts index 12fd1268408..142db040dea 100644 --- a/src/gateway/session-compaction-checkpoints.ts +++ b/src/gateway/session-compaction-checkpoints.ts @@ -99,7 +99,7 @@ export function captureCompactionCheckpointSnapshot(params: { } return { sessionId: getSessionId(), - sessionFile, + sessionFile: snapshotFile, leafId, }; }