






















@@ -5,9 +5,11 @@ import path from "node:path";
55import type { AssistantMessage, UserMessage } from "@mariozechner/pi-ai";
66import { SessionManager } from "@mariozechner/pi-coding-agent";
77import { afterEach, describe, expect, test } from "vitest";
8+import type { OpenClawConfig } from "../config/types.openclaw.js";
89import {
910captureCompactionCheckpointSnapshot,
1011cleanupCompactionCheckpointSnapshot,
12+persistSessionCompactionCheckpoint,
1113} from "./session-compaction-checkpoints.js";
12141315const tempDirs: string[] = [];
@@ -81,4 +83,83 @@ describe("session-compaction-checkpoints", () => {
8183expect(fsSync.existsSync(snapshot!.sessionFile)).toBe(false);
8284expect(fsSync.existsSync(sessionFile!)).toBe(true);
8385});
86+87+test("persist trims old checkpoint metadata and removes trimmed snapshot files", async () => {
88+const dir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-checkpoint-trim-"));
89+tempDirs.push(dir);
90+91+const storePath = path.join(dir, "sessions.json");
92+const sessionId = "sess";
93+const sessionKey = "agent:main:main";
94+const now = Date.now();
95+const existingCheckpoints = Array.from({ length: 26 }, (_, index) => {
96+const uuid = `${String(index + 1).padStart(8, "0")}-1111-4111-8111-111111111111`;
97+const sessionFile = path.join(dir, `sess.checkpoint.${uuid}.jsonl`);
98+fsSync.writeFileSync(sessionFile, `checkpoint ${index}`, "utf-8");
99+return {
100+checkpointId: `old-${index}`,
101+ sessionKey,
102+ sessionId,
103+createdAt: now + index,
104+reason: "manual" as const,
105+preCompaction: {
106+ sessionId,
107+ sessionFile,
108+leafId: `old-leaf-${index}`,
109+},
110+postCompaction: { sessionId },
111+};
112+});
113+await fs.writeFile(
114+storePath,
115+JSON.stringify(
116+{
117+[sessionKey]: {
118+ sessionId,
119+updatedAt: now,
120+compactionCheckpoints: existingCheckpoints,
121+},
122+},
123+null,
124+2,
125+),
126+"utf-8",
127+);
128+129+const currentSnapshotFile = path.join(
130+dir,
131+"sess.checkpoint.99999999-9999-4999-8999-999999999999.jsonl",
132+);
133+await fs.writeFile(currentSnapshotFile, "current", "utf-8");
134+135+const stored = await persistSessionCompactionCheckpoint({
136+cfg: {
137+session: { store: storePath },
138+agents: { list: [{ id: "main", default: true }] },
139+} as OpenClawConfig,
140+sessionKey: "main",
141+ sessionId,
142+reason: "manual",
143+snapshot: {
144+ sessionId,
145+sessionFile: currentSnapshotFile,
146+leafId: "current-leaf",
147+},
148+createdAt: now + 100,
149+});
150+151+expect(stored).not.toBeNull();
152+expect(fsSync.existsSync(existingCheckpoints[0].preCompaction.sessionFile)).toBe(false);
153+expect(fsSync.existsSync(existingCheckpoints[1].preCompaction.sessionFile)).toBe(false);
154+expect(fsSync.existsSync(existingCheckpoints[2].preCompaction.sessionFile)).toBe(true);
155+expect(fsSync.existsSync(currentSnapshotFile)).toBe(true);
156+157+const nextStore = JSON.parse(await fs.readFile(storePath, "utf-8")) as Record<
158+string,
159+{ compactionCheckpoints?: unknown[] }
160+>;
161+expect(
162+Object.values(nextStore).find((entry) => entry.compactionCheckpoints)?.compactionCheckpoints,
163+).toHaveLength(25);
164+});
84165});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。