fix(agent): seeded startup learned memory snapshot
Use the pre-session memory prompt snapshot as the learned.md baseline when startup consolidation refreshes before a session-scoped cache exists. This keeps active-session learn writes out of the refreshed prompt while still surfacing the new consolidated summary. Refs #3743
This commit is contained in:
@@ -166,6 +166,11 @@ const memoryToolDeveloperInstructionsBySession = new WeakMap<
|
||||
MemoryInstructionSession,
|
||||
CachedMemoryToolDeveloperInstructions
|
||||
>();
|
||||
const memoryToolDeveloperInstructionsByRoot = new Map<string, MemoryToolDeveloperInstructionsSnapshot | undefined>();
|
||||
|
||||
function getMemoryInstructionRoot(agentDir: string, settings: Settings): string {
|
||||
return getMemoryRoot(agentDir, settings.getCwd());
|
||||
}
|
||||
|
||||
function getMemoryInstructionSessionFile(session: MemoryInstructionSession): string | undefined {
|
||||
return session.sessionManager.getSessionFile() ?? undefined;
|
||||
@@ -177,7 +182,7 @@ async function readMemoryToolDeveloperInstructionsSnapshot(
|
||||
): Promise<MemoryToolDeveloperInstructionsSnapshot | undefined> {
|
||||
const cfg = loadMemoryConfig(settings);
|
||||
if (!cfg.enabled) return undefined;
|
||||
const memoryRoot = getMemoryRoot(agentDir, settings.getCwd());
|
||||
const memoryRoot = getMemoryInstructionRoot(agentDir, settings);
|
||||
|
||||
let summary = "";
|
||||
try {
|
||||
@@ -255,8 +260,10 @@ export async function refreshMemoryToolDeveloperInstructionsCacheAfterStartup(
|
||||
const sessionFile = getMemoryInstructionSessionFile(session);
|
||||
const cached = memoryToolDeveloperInstructionsBySession.get(session);
|
||||
const current = await readMemoryToolDeveloperInstructionsSnapshot(agentDir, settings);
|
||||
const root = getMemoryInstructionRoot(agentDir, settings);
|
||||
const baseline = memoryToolDeveloperInstructionsByRoot.get(root);
|
||||
const cachedLearned = cached && cached.sessionFile === sessionFile ? cached.snapshot?.learned : undefined;
|
||||
const learned = cachedLearned ?? current?.learned ?? "";
|
||||
const learned = cachedLearned ?? baseline?.learned ?? "";
|
||||
const snapshot = current ? { summary: current.summary, learned } : undefined;
|
||||
cacheMemoryToolDeveloperInstructions(session, sessionFile, snapshot, settings);
|
||||
}
|
||||
@@ -271,6 +278,7 @@ export async function buildMemoryToolDeveloperInstructions(
|
||||
): Promise<string | undefined> {
|
||||
if (!session) {
|
||||
const snapshot = await readMemoryToolDeveloperInstructionsSnapshot(agentDir, settings);
|
||||
memoryToolDeveloperInstructionsByRoot.set(getMemoryInstructionRoot(agentDir, settings), snapshot);
|
||||
return renderMemoryToolDeveloperInstructionsSnapshot(snapshot, settings);
|
||||
}
|
||||
|
||||
|
||||
@@ -198,13 +198,15 @@ describe("learned-lesson read-back", () => {
|
||||
expect(await buildMemoryToolDeveloperInstructions(agentDir, settings, session)).toBeUndefined();
|
||||
});
|
||||
|
||||
it("refreshes consolidated summaries without rereading learned lessons from the active session", async () => {
|
||||
it("uses the pre-session learned snapshot when startup refresh has no session cache yet", async () => {
|
||||
const settings = Settings.isolated({ "memory.backend": "local" });
|
||||
const session = sessionWithFile("session-consolidate.jsonl");
|
||||
// First build (before background consolidation finishes) snapshots an empty learned.md.
|
||||
expect(await buildMemoryToolDeveloperInstructions(agentDir, settings, session)).toBeUndefined();
|
||||
await saveLearnedLesson(agentDir, settings.getCwd(), { content: "Prior-session lesson" });
|
||||
const initial = await buildMemoryToolDeveloperInstructions(agentDir, settings);
|
||||
expect(initial).toContain("Prior-session lesson");
|
||||
|
||||
// The active session learns while the background pipeline is still running.
|
||||
const session = sessionWithFile("session-consolidate.jsonl");
|
||||
// The active session learns while the background pipeline is still running,
|
||||
// before any session-scoped prompt rebuild has populated the WeakMap.
|
||||
await saveLearnedLesson(agentDir, settings.getCwd(), { content: "Active-session lesson" });
|
||||
// Background pipeline writes the consolidated summary later.
|
||||
const root = getMemoryRoot(agentDir, settings.getCwd());
|
||||
@@ -213,6 +215,7 @@ describe("learned-lesson read-back", () => {
|
||||
await refreshMemoryToolDeveloperInstructionsCacheAfterStartup(session, agentDir, settings);
|
||||
const out = await buildMemoryToolDeveloperInstructions(agentDir, settings, session);
|
||||
expect(out).toContain("Consolidated guidance here.");
|
||||
expect(out).toContain("Prior-session lesson");
|
||||
expect(out).not.toContain("Active-session lesson");
|
||||
|
||||
const nextSession = sessionWithFile("session-after-consolidate.jsonl");
|
||||
|
||||
Reference in New Issue
Block a user