Files
openclaw/extensions/memory-core/src/session-reset-recall-metadata.ts
T
Vitor Cepeda Lopes a9ee6618fe fix(memory): recall prior conversation after session reset (#122051)
* fix(memory): recall archived session generations after reset

* test(memory): prove private recall across reset

* fix(memory): keep deleted transcripts outside reset recall

* fix(memory): reject deleted archives from reset recall

* fix(memory): isolate recall across sqlite resets

* test(memory): split reset recall coverage

* fix(memory): keep reset recall metadata private

* fix(memory): keep reset authority scoped

---------

Co-authored-by: TheAngryPit <16145902+TheAngryPit@users.noreply.github.com>
2026-08-12 12:38:13 -07:00

36 lines
1.2 KiB
TypeScript

export type SessionResetRecallCutoff =
| { state: "absent" }
| { state: "invalid" }
| { cutoffLine: number; state: "valid" };
const RESET_RECALL_CUTOFF = Symbol.for("openclaw.memory.sessionResetRecallCutoff");
export function readSessionResetRecallCutoffMetadata(value: unknown): SessionResetRecallCutoff {
if (!value || typeof value !== "object") {
return { state: "invalid" };
}
const cutoff = (value as Record<PropertyKey, unknown>)[RESET_RECALL_CUTOFF];
if (!cutoff || typeof cutoff !== "object") {
return { state: "invalid" };
}
const state = (cutoff as { state?: unknown }).state;
if (state === "absent" || state === "invalid") {
return { state };
}
const cutoffLine = (cutoff as { cutoffLine?: unknown }).cutoffLine;
return state === "valid" && typeof cutoffLine === "number" && Number.isInteger(cutoffLine)
? { state, cutoffLine }
: { state: "invalid" };
}
export function readSessionArchiveReasonFromHitPath(
hitPath: string,
): "reset" | "deleted" | undefined {
const match =
/\.jsonl\.(reset|deleted)\.\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(?:\.\d{3})?Z(?:\.zst)?$/.exec(
hitPath,
);
const reason = match?.[1];
return reason === "reset" || reason === "deleted" ? reason : undefined;
}