Skip to content

Commit 1882a8e

Browse files
committed
fix: refresh preflight rotated runs
1 parent f5f4f51 commit 1882a8e

2 files changed

Lines changed: 96 additions & 2 deletions

File tree

src/auto-reply/reply/agent-runner-memory.test.ts

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,15 @@ describe("runMemoryFlushIfNeeded", () => {
6767
};
6868
if (typeof params.newSessionId === "string" && params.newSessionId) {
6969
nextEntry.sessionId = params.newSessionId;
70-
const storePath = typeof params.storePath === "string" ? params.storePath : rootDir;
71-
nextEntry.sessionFile = path.join(path.dirname(storePath), `${params.newSessionId}.jsonl`);
70+
if (typeof params.newSessionFile === "string" && params.newSessionFile) {
71+
nextEntry.sessionFile = params.newSessionFile;
72+
} else {
73+
const storePath = typeof params.storePath === "string" ? params.storePath : rootDir;
74+
nextEntry.sessionFile = path.join(
75+
path.dirname(storePath),
76+
`${params.newSessionId}.jsonl`,
77+
);
78+
}
7279
}
7380
params.sessionStore[sessionKey] = nextEntry;
7481
if (typeof params.storePath === "string") {
@@ -287,6 +294,76 @@ describe("runMemoryFlushIfNeeded", () => {
287294
);
288295
});
289296

297+
it("updates the active preflight run after transcript rotation", async () => {
298+
const sessionFile = path.join(rootDir, "session.jsonl");
299+
const successorFile = path.join(rootDir, "session-rotated.jsonl");
300+
await fs.writeFile(
301+
sessionFile,
302+
`${JSON.stringify({ message: { role: "user", content: "x".repeat(5_000) } })}\n`,
303+
"utf8",
304+
);
305+
registerMemoryFlushPlanResolver(() => ({
306+
softThresholdTokens: 1,
307+
forceFlushTranscriptBytes: 1_000_000_000,
308+
reserveTokensFloor: 0,
309+
prompt: "Pre-compaction memory flush.\nNO_REPLY",
310+
systemPrompt: "Write memory to memory/YYYY-MM-DD.md.",
311+
relativePath: "memory/2023-11-14.md",
312+
}));
313+
compactEmbeddedPiSessionMock.mockResolvedValueOnce({
314+
ok: true,
315+
compacted: true,
316+
result: {
317+
tokensAfter: 42,
318+
sessionId: "session-rotated",
319+
sessionFile: successorFile,
320+
},
321+
});
322+
const sessionEntry: SessionEntry = {
323+
sessionId: "session",
324+
sessionFile,
325+
updatedAt: Date.now(),
326+
totalTokensFresh: false,
327+
};
328+
const sessionStore = { "agent:main:main": sessionEntry };
329+
const followupRun = createTestFollowupRun({
330+
sessionId: "session",
331+
sessionFile,
332+
sessionKey: "agent:main:main",
333+
});
334+
const updateSessionId = vi.fn();
335+
const replyOperation = {
336+
abortSignal: new AbortController().signal,
337+
setPhase: vi.fn(),
338+
updateSessionId,
339+
} as never;
340+
341+
const entry = await runPreflightCompactionIfNeeded({
342+
cfg: { agents: { defaults: { compaction: { memoryFlush: {} } } } },
343+
followupRun,
344+
defaultModel: "anthropic/claude-opus-4-6",
345+
agentCfgContextTokens: 100,
346+
sessionEntry,
347+
sessionStore,
348+
sessionKey: "agent:main:main",
349+
storePath: path.join(rootDir, "sessions.json"),
350+
isHeartbeat: false,
351+
replyOperation,
352+
});
353+
354+
expect(entry?.sessionId).toBe("session-rotated");
355+
expect(entry?.sessionFile).toBe(successorFile);
356+
expect(followupRun.run.sessionId).toBe("session-rotated");
357+
expect(followupRun.run.sessionFile).toBe(successorFile);
358+
expect(updateSessionId).toHaveBeenCalledWith("session-rotated");
359+
expect(refreshQueuedFollowupSessionMock).toHaveBeenCalledWith({
360+
key: "agent:main:main",
361+
previousSessionId: "session",
362+
nextSessionId: "session-rotated",
363+
nextSessionFile: successorFile,
364+
});
365+
});
366+
290367
it("uses configured prompts and stored bootstrap warning signatures", async () => {
291368
const sessionEntry: SessionEntry = {
292369
sessionId: "session",

src/auto-reply/reply/agent-runner-memory.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,23 @@ export async function runPreflightCompactionIfNeeded(params: {
514514
followupRun: params.followupRun,
515515
});
516516
entry = params.sessionStore?.[params.sessionKey] ?? entry;
517+
if (entry) {
518+
const previousSessionId = params.followupRun.run.sessionId;
519+
params.followupRun.run.sessionId = entry.sessionId;
520+
params.replyOperation.updateSessionId(entry.sessionId);
521+
if (entry.sessionFile) {
522+
params.followupRun.run.sessionFile = entry.sessionFile;
523+
}
524+
const queueKey = params.followupRun.run.sessionKey ?? params.sessionKey;
525+
if (queueKey) {
526+
memoryDeps.refreshQueuedFollowupSession({
527+
key: queueKey,
528+
previousSessionId,
529+
nextSessionId: entry.sessionId,
530+
nextSessionFile: entry.sessionFile,
531+
});
532+
}
533+
}
517534
return entry ?? params.sessionEntry;
518535
}
519536

0 commit comments

Comments
 (0)