fix(session-memory): fallback to rotated transcript after /new
When /new rotates <session>.jsonl to <session>.jsonl.reset.*, the session-memory hook may read an empty active transcript and write header-only memory entries. Add fallback logic to read the latest .jsonl.reset.* sibling when the primary file has no usable content. Also add a unit test covering the rotated transcript path. Fixes #18088 Refs #17563
This commit is contained in:
committed by
Peter Steinberger
parent
769f7631d5
commit
19ae7a4e17
@@ -67,6 +67,46 @@ async function getRecentSessionContent(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try the active transcript first; if /new already rotated it,
|
||||
* fallback to the latest .jsonl.reset.* sibling.
|
||||
*/
|
||||
async function getRecentSessionContentWithResetFallback(
|
||||
sessionFilePath: string,
|
||||
messageCount: number = 15,
|
||||
): Promise<string | null> {
|
||||
const primary = await getRecentSessionContent(sessionFilePath, messageCount);
|
||||
if (primary) {
|
||||
return primary;
|
||||
}
|
||||
|
||||
try {
|
||||
const dir = path.dirname(sessionFilePath);
|
||||
const base = path.basename(sessionFilePath);
|
||||
const resetPrefix = `${base}.reset.`;
|
||||
const files = await fs.readdir(dir);
|
||||
const resetCandidates = files.filter((name) => name.startsWith(resetPrefix)).toSorted();
|
||||
|
||||
if (resetCandidates.length === 0) {
|
||||
return primary;
|
||||
}
|
||||
|
||||
const latestResetPath = path.join(dir, resetCandidates[resetCandidates.length - 1]);
|
||||
const fallback = await getRecentSessionContent(latestResetPath, messageCount);
|
||||
|
||||
if (fallback) {
|
||||
log.debug("Loaded session content from reset fallback", {
|
||||
sessionFilePath,
|
||||
latestResetPath,
|
||||
});
|
||||
}
|
||||
|
||||
return fallback || primary;
|
||||
} catch {
|
||||
return primary;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save session context to memory when /new command is triggered
|
||||
*/
|
||||
@@ -119,8 +159,8 @@ const saveSessionToMemory: HookHandler = async (event) => {
|
||||
let sessionContent: string | null = null;
|
||||
|
||||
if (sessionFile) {
|
||||
// Get recent conversation content
|
||||
sessionContent = await getRecentSessionContent(sessionFile, messageCount);
|
||||
// Get recent conversation content, with fallback to rotated reset transcript.
|
||||
sessionContent = await getRecentSessionContentWithResetFallback(sessionFile, messageCount);
|
||||
log.debug("Session content loaded", {
|
||||
length: sessionContent?.length ?? 0,
|
||||
messageCount,
|
||||
|
||||
Reference in New Issue
Block a user