


























@@ -1,10 +1,11 @@
1-import fs from "node:fs/promises";
21import type { AgentMessage } from "@mariozechner/pi-agent-core";
3-import { SessionManager } from "@mariozechner/pi-coding-agent";
2+import type { SessionEntry } from "@mariozechner/pi-coding-agent";
3+import {
4+readTranscriptFileState,
5+TranscriptFileState,
6+writeTranscriptFileAtomic,
7+} from "./transcript-file-state.js";
485-type SessionManagerLike = ReturnType<typeof SessionManager.open>;
6-type SessionEntry = ReturnType<SessionManagerLike["getEntries"]>[number];
7-type SessionHeader = NonNullable<ReturnType<SessionManagerLike["getHeader"]>>;
89type CompactionEntry = Extract<SessionEntry, { type: "compaction" }>;
9101011export type HardenedManualCompactionBoundary = {
@@ -14,12 +15,6 @@ export type HardenedManualCompactionBoundary = {
1415messages: AgentMessage[];
1516};
161717-function serializeSessionFile(header: SessionHeader, entries: SessionEntry[]): string {
18-return (
19-[JSON.stringify(header), ...entries.map((entry) => JSON.stringify(entry))].join("\n") + "\n"
20-);
21-}
22-2318function replaceLatestCompactionBoundary(params: {
2419entries: SessionEntry[];
2520compactionEntryId: string;
@@ -42,76 +37,60 @@ export async function hardenManualCompactionBoundary(params: {
4237sessionFile: string;
4338preserveRecentTail?: boolean;
4439}): Promise<HardenedManualCompactionBoundary> {
45-const sessionManager = SessionManager.open(params.sessionFile) as Partial<SessionManagerLike>;
46-if (
47-typeof sessionManager.getHeader !== "function" ||
48-typeof sessionManager.getLeafEntry !== "function" ||
49-typeof sessionManager.buildSessionContext !== "function" ||
50-typeof sessionManager.getEntries !== "function"
51-) {
40+const state = await readTranscriptFileState(params.sessionFile);
41+const header = state.getHeader();
42+if (!header) {
5243return {
5344applied: false,
5445messages: [],
5546};
5647}
574858-const header = sessionManager.getHeader();
59-const leaf = sessionManager.getLeafEntry();
60-if (!header || leaf?.type !== "compaction") {
61-const sessionContext = sessionManager.buildSessionContext();
49+const leaf = state.getLeafEntry();
50+if (leaf?.type !== "compaction") {
51+const sessionContext = state.buildSessionContext();
6252return {
6353applied: false,
64-leafId:
65-typeof sessionManager.getLeafId === "function"
66- ? (sessionManager.getLeafId() ?? undefined)
67- : undefined,
54+leafId: state.getLeafId() ?? undefined,
6855messages: sessionContext.messages,
6956};
7057}
71587259if (params.preserveRecentTail) {
73-const sessionContext = sessionManager.buildSessionContext();
60+const sessionContext = state.buildSessionContext();
7461return {
7562applied: false,
7663firstKeptEntryId: leaf.firstKeptEntryId,
77-leafId:
78-typeof sessionManager.getLeafId === "function"
79- ? (sessionManager.getLeafId() ?? undefined)
80- : undefined,
64+leafId: state.getLeafId() ?? undefined,
8165messages: sessionContext.messages,
8266};
8367}
84688569if (leaf.firstKeptEntryId === leaf.id) {
86-const sessionContext = sessionManager.buildSessionContext();
70+const sessionContext = state.buildSessionContext();
8771return {
8872applied: false,
8973firstKeptEntryId: leaf.id,
90-leafId:
91-typeof sessionManager.getLeafId === "function"
92- ? (sessionManager.getLeafId() ?? undefined)
93- : undefined,
74+leafId: state.getLeafId() ?? undefined,
9475messages: sessionContext.messages,
9576};
9677}
977898-const content = serializeSessionFile(
79+const replacedEntries = replaceLatestCompactionBoundary({
80+entries: state.getEntries(),
81+compactionEntryId: leaf.id,
82+});
83+const replacedState = new TranscriptFileState({
9984 header,
100-replaceLatestCompactionBoundary({
101-entries: sessionManager.getEntries(),
102-compactionEntryId: leaf.id,
103-}),
104-);
105-const tmpFile = `${params.sessionFile}.manual-compaction-tmp`;
106-await fs.writeFile(tmpFile, content, "utf-8");
107-await fs.rename(tmpFile, params.sessionFile);
85+entries: replacedEntries,
86+});
87+await writeTranscriptFileAtomic(params.sessionFile, [header, ...replacedEntries]);
10888109-const refreshed = SessionManager.open(params.sessionFile);
110-const sessionContext = refreshed.buildSessionContext();
89+const sessionContext = replacedState.buildSessionContext();
11190return {
11291applied: true,
11392firstKeptEntryId: leaf.id,
114-leafId: refreshed.getLeafId() ?? undefined,
93+leafId: replacedState.getLeafId() ?? undefined,
11594messages: sessionContext.messages,
11695};
11796}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。