From f504bfdde8256fe9540b335d6b25d6d4a6a2e555 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 12 Jan 2026 01:21:44 +0000 Subject: [PATCH] refactor(gateway): use canonical session store keys --- src/gateway/server-bridge.ts | 28 ++++++++---------------- src/gateway/server-methods/agent.ts | 9 +++----- src/gateway/server-methods/chat.ts | 11 ++++------ src/gateway/server.sessions.test.ts | 34 +++++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 32 deletions(-) diff --git a/src/gateway/server-bridge.ts b/src/gateway/server-bridge.ts index 9cc520d81..e170c8505 100644 --- a/src/gateway/server-bridge.ts +++ b/src/gateway/server-bridge.ts @@ -94,7 +94,6 @@ import { readSessionMessages, resolveGatewaySessionStoreTarget, resolveSessionModelRef, - resolveSessionStoreKey, resolveSessionTranscriptCandidates, type SessionsPatchResult, } from "./session-utils.js"; @@ -867,9 +866,8 @@ export function createBridgeHandlers(ctx: BridgeHandlersContext) { } } - const { cfg, storePath, store, entry } = loadSessionEntry( - p.sessionKey, - ); + const { cfg, storePath, store, entry, canonicalKey } = + loadSessionEntry(p.sessionKey); const timeoutMs = resolveAgentTimeoutMs({ cfg, overrideMs: p.timeoutMs, @@ -946,12 +944,8 @@ export function createBridgeHandlers(ctx: BridgeHandlersContext) { clientRunId, }); - const storeKey = resolveSessionStoreKey({ - cfg, - sessionKey: p.sessionKey, - }); if (store) { - store[storeKey] = sessionEntry; + store[canonicalKey] = sessionEntry; if (storePath) { await saveSessionStore(storePath, store); } @@ -1068,11 +1062,11 @@ export function createBridgeHandlers(ctx: BridgeHandlersContext) { const rawMainKey = normalizeMainKey(cfg.session?.mainKey); const sessionKey = sessionKeyRaw.length > 0 ? sessionKeyRaw : rawMainKey; - const { storePath, store, entry } = loadSessionEntry(sessionKey); - const storeKey = resolveSessionStoreKey({ cfg, sessionKey }); + const { storePath, store, entry, canonicalKey } = + loadSessionEntry(sessionKey); const now = Date.now(); const sessionId = entry?.sessionId ?? randomUUID(); - store[storeKey] = { + store[canonicalKey] = { sessionId, updatedAt: now, thinkingLevel: entry?.thinkingLevel, @@ -1146,15 +1140,11 @@ export function createBridgeHandlers(ctx: BridgeHandlersContext) { const sessionKeyRaw = (link?.sessionKey ?? "").trim(); const sessionKey = sessionKeyRaw.length > 0 ? sessionKeyRaw : `node-${nodeId}`; - const { storePath, store, entry } = loadSessionEntry(sessionKey); - const nodeCfg = loadConfig(); - const nodeStoreKey = resolveSessionStoreKey({ - cfg: nodeCfg, - sessionKey, - }); + const { storePath, store, entry, canonicalKey } = + loadSessionEntry(sessionKey); const now = Date.now(); const sessionId = entry?.sessionId ?? randomUUID(); - store[nodeStoreKey] = { + store[canonicalKey] = { sessionId, updatedAt: now, thinkingLevel: entry?.thinkingLevel, diff --git a/src/gateway/server-methods/agent.ts b/src/gateway/server-methods/agent.ts index ba1e633ae..d8494f19c 100644 --- a/src/gateway/server-methods/agent.ts +++ b/src/gateway/server-methods/agent.ts @@ -28,7 +28,7 @@ import { validateAgentParams, validateAgentWaitParams, } from "../protocol/index.js"; -import { loadSessionEntry, resolveSessionStoreKey } from "../session-utils.js"; +import { loadSessionEntry } from "../session-utils.js"; import { formatForLog } from "../ws-log.js"; import { waitForAgentJob } from "./agent-job.js"; import type { GatewayRequestHandlers } from "./types.js"; @@ -146,7 +146,7 @@ export const agentHandlers: GatewayRequestHandlers = { let cfgForAgent: ReturnType | undefined; if (requestedSessionKey) { - const { cfg, storePath, store, entry } = + const { cfg, storePath, store, entry, canonicalKey } = loadSessionEntry(requestedSessionKey); cfgForAgent = cfg; const now = Date.now(); @@ -189,10 +189,7 @@ export const agentHandlers: GatewayRequestHandlers = { return; } resolvedSessionId = sessionId; - const canonicalSessionKey = resolveSessionStoreKey({ - cfg, - sessionKey: requestedSessionKey, - }); + const canonicalSessionKey = canonicalKey; const agentId = resolveAgentIdFromSessionKey(canonicalSessionKey); const mainSessionKey = resolveAgentMainSessionKey({ cfg, agentId }); if (store) { diff --git a/src/gateway/server-methods/chat.ts b/src/gateway/server-methods/chat.ts index 5f6ef9f6d..1103fac5b 100644 --- a/src/gateway/server-methods/chat.ts +++ b/src/gateway/server-methods/chat.ts @@ -32,7 +32,6 @@ import { loadSessionEntry, readSessionMessages, resolveSessionModelRef, - resolveSessionStoreKey, } from "../session-utils.js"; import { formatForLog } from "../ws-log.js"; import type { GatewayRequestHandlers } from "./types.js"; @@ -223,7 +222,9 @@ export const chatHandlers: GatewayRequestHandlers = { return; } } - const { cfg, storePath, store, entry } = loadSessionEntry(p.sessionKey); + const { cfg, storePath, store, entry, canonicalKey } = loadSessionEntry( + p.sessionKey, + ); const timeoutMs = resolveAgentTimeoutMs({ cfg, overrideMs: p.timeoutMs, @@ -307,12 +308,8 @@ export const chatHandlers: GatewayRequestHandlers = { clientRunId, }); - const storeKey = resolveSessionStoreKey({ - cfg, - sessionKey: p.sessionKey, - }); if (store) { - store[storeKey] = sessionEntry; + store[canonicalKey] = sessionEntry; if (storePath) { await saveSessionStore(storePath, store); } diff --git a/src/gateway/server.sessions.test.ts b/src/gateway/server.sessions.test.ts index fa948ea16..85377e0c8 100644 --- a/src/gateway/server.sessions.test.ts +++ b/src/gateway/server.sessions.test.ts @@ -464,4 +464,38 @@ describe("gateway server sessions", () => { "agent:work:main", ]); }); + + test("resolves and patches main alias to default agent main key", async () => { + const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-sessions-")); + const storePath = path.join(dir, "sessions.json"); + testState.sessionStorePath = storePath; + testState.agentsConfig = { list: [{ id: "ops", default: true }] }; + testState.sessionConfig = { mainKey: "work" }; + + await fs.writeFile(storePath, JSON.stringify({}, null, 2), "utf-8"); + + const { ws } = await startServerWithClient(); + const resolved = await rpcReq<{ ok: true; key: string }>( + ws, + "sessions.resolve", + { key: "main" }, + ); + expect(resolved.ok).toBe(true); + expect(resolved.payload?.key).toBe("agent:ops:work"); + + const patched = await rpcReq<{ ok: true; key: string }>( + ws, + "sessions.patch", + { key: "main", thinkingLevel: "medium" }, + ); + expect(patched.ok).toBe(true); + expect(patched.payload?.key).toBe("agent:ops:work"); + + const stored = JSON.parse(await fs.readFile(storePath, "utf-8")) as Record< + string, + { thinkingLevel?: string } + >; + expect(stored["agent:ops:work"]?.thinkingLevel).toBe("medium"); + expect(stored.main).toBeUndefined(); + }); });