mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
a9ee6618fe
* 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>
36 lines
1.2 KiB
TypeScript
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;
|
|
}
|