Skip to content

Commit 453b08f

Browse files
committed
fix session metadata id normalization
1 parent 4ae113b commit 453b08f

2 files changed

Lines changed: 32 additions & 1 deletion

File tree

src/config/sessions/sessions.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,23 @@ describe("session store writer queue", () => {
473473
expect(store["agent:main:unsafe-id"]).toBeUndefined();
474474
});
475475

476+
it("keeps metadata-only canonical sessions without treating their ids as transcript ids", async () => {
477+
const { storePath } = await makeTmpStore({
478+
"agent:main:metadata": {
479+
sessionId: "agent:main:metadata",
480+
updatedAt: Date.now(),
481+
groupActivation: "always",
482+
},
483+
} as unknown as Record<string, SessionEntry>);
484+
485+
const store = loadSessionStore(storePath, { skipCache: true });
486+
487+
expect(store["agent:main:metadata"]).toMatchObject({
488+
groupActivation: "always",
489+
});
490+
expect(store["agent:main:metadata"]?.sessionId).toBeUndefined();
491+
});
492+
476493
it("skips session store disk writes when payload is unchanged", async () => {
477494
const key = "agent:main:no-op-save";
478495
const { storePath } = await makeTmpStore({

src/config/sessions/store-entry-shape.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { validateSessionId } from "./paths.js";
12
import type { SessionEntry } from "./types.js";
23

34
function isRecord(value: unknown): value is Record<string, unknown> {
@@ -18,6 +19,14 @@ function isSafeSessionId(value: unknown): value is string {
1819
return /^[A-Za-z0-9][A-Za-z0-9._:@-]*$/.test(trimmed);
1920
}
2021

22+
function normalizeTranscriptSessionId(value: string): string | undefined {
23+
try {
24+
return validateSessionId(value);
25+
} catch {
26+
return undefined;
27+
}
28+
}
29+
2130
function normalizeOptionalTimestamp(value: unknown): number | undefined {
2231
if (value === undefined) {
2332
return undefined;
@@ -31,12 +40,17 @@ export function normalizePersistedSessionEntryShape(value: unknown): SessionEntr
3140
}
3241

3342
let next = value as unknown as SessionEntry;
43+
const sessionFile = typeof value.sessionFile === "string" ? value.sessionFile.trim() : undefined;
3444
if (value.sessionId !== undefined) {
3545
if (!isSafeSessionId(value.sessionId)) {
3646
return undefined;
3747
}
3848
const sessionId = value.sessionId.trim();
39-
if (sessionId !== value.sessionId) {
49+
const transcriptSessionId = normalizeTranscriptSessionId(sessionId);
50+
if (!transcriptSessionId && !sessionFile) {
51+
const { sessionId: _dropSessionId, ...rest } = next;
52+
next = rest as SessionEntry;
53+
} else if (sessionId !== value.sessionId) {
4054
next = { ...next, sessionId };
4155
}
4256
}

0 commit comments

Comments
 (0)