clawdbot-83f: backport exact-key session accessor

This commit is contained in:
Josh Lehman
2026-06-01 07:57:34 -07:00
parent cd62186882
commit b9d71bc226
2 changed files with 53 additions and 0 deletions

View File

@@ -7,6 +7,7 @@ import {
appendTranscriptMessage,
appendTranscriptEvent,
listSessionEntries,
loadExactSessionEntry,
loadSessionEntry,
loadTranscriptEvents,
patchSessionEntry,
@@ -106,6 +107,35 @@ describe("session accessor file-backed seam", () => {
);
});
it("keeps exact persisted-key lookup separate from canonical entry reads", async () => {
fs.writeFileSync(
storePath,
JSON.stringify({
"agent:main:main": {
sessionId: "session-1",
updatedAt: 10,
model: "gpt-5.5",
},
}),
"utf8",
);
const mixedCaseScope = {
sessionKey: "AGENT:MAIN:MAIN",
storePath,
};
expect(loadSessionEntry(mixedCaseScope)?.sessionId).toBe("session-1");
expect(loadExactSessionEntry(mixedCaseScope)).toBeUndefined();
expect(loadExactSessionEntry({ sessionKey: "agent:main:main", storePath })).toEqual({
sessionKey: "agent:main:main",
entry: expect.objectContaining({
sessionId: "session-1",
model: "gpt-5.5",
}),
});
});
it("updates existing entries without creating missing sessions", async () => {
const scope = {
sessionKey: "agent:main:main",

View File

@@ -58,6 +58,12 @@ export type SessionEntrySummary = {
entry: SessionEntry;
};
/** Session entry read by the exact persisted session key, without alias resolution. */
export type ExactSessionEntry = {
sessionKey: string;
entry: SessionEntry;
};
export type TranscriptEvent = unknown;
export type TranscriptMessageAppendOptions<TMessage> = {
@@ -105,6 +111,23 @@ export function loadSessionEntry(scope: SessionAccessScope): SessionEntry | unde
return getSessionEntry(scope);
}
/**
* Loads one entry only when the persisted key exactly matches the requested key.
* Approval routing uses this to avoid canonical alias lookup crossing accounts.
*/
export function loadExactSessionEntry(scope: SessionAccessScope): ExactSessionEntry | undefined {
const sessionKey = scope.sessionKey.trim();
if (!sessionKey) {
return undefined;
}
const store = loadSessionStore(resolveAccessStorePath(scope), {
...(scope.clone === false ? { clone: false } : {}),
...(scope.hydrateSkillPromptRefs === false ? { hydrateSkillPromptRefs: false } : {}),
});
const entry = Object.hasOwn(store, sessionKey) ? store[sessionKey] : undefined;
return entry ? { sessionKey, entry } : undefined;
}
/** Lists session entries through the storage-neutral accessor seam. */
export function listSessionEntries(
scope: Partial<Omit<SessionAccessScope, "sessionKey">> = {},