mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
clawdbot-83f: backport exact-key session accessor
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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">> = {},
|
||||
|
||||
Reference in New Issue
Block a user