From 8e8d5ce5303c32b4306b616a27b396821dd773ba Mon Sep 17 00:00:00 2001 From: Gustavo Madeira Santana Date: Sun, 19 Apr 2026 18:13:04 -0400 Subject: [PATCH] fix: preserve deleted main-store ownership --- src/gateway/session-store-key.ts | 19 ++++++++-- src/gateway/sessions-resolve-store.test.ts | 44 +++++++++++++++++++++- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/gateway/session-store-key.ts b/src/gateway/session-store-key.ts index 7046fbbe909..8c165c69eb8 100644 --- a/src/gateway/session-store-key.ts +++ b/src/gateway/session-store-key.ts @@ -34,11 +34,16 @@ function resolveDefaultStoreAgentId(cfg: OpenClawConfig): string { function shouldRemapLegacyDefaultMainAlias( cfg: OpenClawConfig, parsed: ParsedAgentSessionKey, + options?: { storeAgentId?: string }, ): boolean { const agentId = normalizeAgentId(parsed.agentId); if (agentId !== DEFAULT_AGENT_ID || listAgentIds(cfg).includes(DEFAULT_AGENT_ID)) { return false; } + const defaultAgentId = resolveDefaultStoreAgentId(cfg); + if (options?.storeAgentId && normalizeAgentId(options.storeAgentId) !== defaultAgentId) { + return false; + } const rest = normalizeLowercaseStringOrEmpty(parsed.rest); const mainKey = normalizeMainKey(cfg.session?.mainKey); return rest === "main" || rest === mainKey; @@ -48,8 +53,9 @@ function resolveParsedSessionStoreKey( cfg: OpenClawConfig, raw: string, parsed: ParsedAgentSessionKey, + options?: { storeAgentId?: string }, ): { agentId: string; sessionKey: string } { - if (!shouldRemapLegacyDefaultMainAlias(cfg, parsed)) { + if (!shouldRemapLegacyDefaultMainAlias(cfg, parsed, options)) { return { agentId: normalizeAgentId(parsed.agentId), sessionKey: normalizeLowercaseStringOrEmpty(raw), @@ -63,6 +69,7 @@ function resolveParsedSessionStoreKey( export function resolveSessionStoreKey(params: { cfg: OpenClawConfig; sessionKey: string; + storeAgentId?: string; }): string { const raw = normalizeOptionalString(params.sessionKey) ?? ""; if (!raw) { @@ -75,7 +82,9 @@ export function resolveSessionStoreKey(params: { const parsed = parseAgentSessionKey(raw); if (parsed) { - const resolved = resolveParsedSessionStoreKey(params.cfg, raw, parsed); + const resolved = resolveParsedSessionStoreKey(params.cfg, raw, parsed, { + storeAgentId: params.storeAgentId, + }); const canonical = canonicalizeMainSessionAlias({ cfg: params.cfg, agentId: resolved.agentId, @@ -121,7 +130,11 @@ export function resolveStoredSessionKeyForAgentStore(params: { return lowered; } const key = parseAgentSessionKey(raw) ? raw : canonicalizeSessionKeyForAgent(params.agentId, raw); - return resolveSessionStoreKey({ cfg: params.cfg, sessionKey: key }); + return resolveSessionStoreKey({ + cfg: params.cfg, + sessionKey: key, + storeAgentId: params.agentId, + }); } export function resolveStoredSessionOwnerAgentId(params: { diff --git a/src/gateway/sessions-resolve-store.test.ts b/src/gateway/sessions-resolve-store.test.ts index 7afb86f3363..3b849f4f920 100644 --- a/src/gateway/sessions-resolve-store.test.ts +++ b/src/gateway/sessions-resolve-store.test.ts @@ -1,6 +1,6 @@ import path from "node:path"; import { describe, expect, it } from "vitest"; -import { saveSessionStore } from "../config/sessions.js"; +import { resolveStorePath, saveSessionStore } from "../config/sessions.js"; import type { OpenClawConfig } from "../config/types.openclaw.js"; import { withStateDirEnv } from "../test-helpers/state-dir-env.js"; import { ErrorCodes } from "./protocol/index.js"; @@ -67,4 +67,46 @@ describe("resolveSessionKeyFromResolveParams store canonicalization", () => { }); }); }); + + it("does not adopt legacy main aliases from discovered deleted-agent stores", async () => { + await withStateDirEnv("openclaw-sessions-resolve-discovered-main-", async () => { + const cfg: OpenClawConfig = { + agents: { list: [{ id: "ops", default: true }] }, + }; + const staleMainStorePath = resolveStorePath(cfg.session?.store, { agentId: "main" }); + await saveSessionStore(staleMainStorePath, { + "agent:main:main": { + sessionId: "sess-discovered-main", + label: "discovered-main", + updatedAt: 1, + }, + }); + + await expect( + resolveSessionKeyFromResolveParams({ + cfg, + p: { sessionId: "sess-discovered-main" }, + }), + ).resolves.toEqual({ + ok: false, + error: { + code: ErrorCodes.INVALID_REQUEST, + message: 'Agent "main" no longer exists in configuration', + }, + }); + + await expect( + resolveSessionKeyFromResolveParams({ + cfg, + p: { label: "discovered-main" }, + }), + ).resolves.toEqual({ + ok: false, + error: { + code: ErrorCodes.INVALID_REQUEST, + message: 'Agent "main" no longer exists in configuration', + }, + }); + }); + }); });