From 86cc78d593b207cc7fc149b02c301d6d1fa9d678 Mon Sep 17 00:00:00 2001 From: zeroaltitude Date: Sun, 8 Mar 2026 00:29:12 -0700 Subject: [PATCH] fix: resolve normalized account IDs before token-override checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When normalizeAccountId transforms config keys (e.g. 'Router D' → 'router-d'), listAccountIds returns normalized IDs but the everyAccountHasOwnTokens check used accounts[normalizedId], which misses the raw config key. Added a reverse map from normalized ID to raw key for the lookup. Regression test: non-canonical key normalizes correctly and default is still injected when the account has its own tokens. --- src/channels/plugins/account-helpers.test.ts | 18 ++++++++++++++++++ src/channels/plugins/account-helpers.ts | 13 ++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/channels/plugins/account-helpers.test.ts b/src/channels/plugins/account-helpers.test.ts index 2d4a40088e9..60640ada486 100644 --- a/src/channels/plugins/account-helpers.test.ts +++ b/src/channels/plugins/account-helpers.test.ts @@ -95,6 +95,24 @@ describe("createAccountListHelpers", () => { expect(listAccountIds(config)).toEqual(["default", "tank"]); }); + it("includes default when normalized IDs differ from raw config keys", () => { + const normalizedHelpers = createAccountListHelpers("testchannel", { + normalizeAccountId: (id: string) => id.toLowerCase().replace(/\s+/g, "-"), + }); + const config = { + channels: { + testchannel: { + botToken: "xoxb-base", + accounts: { + "Router D": { botToken: "xoxb-router-d" }, + }, + }, + }, + } as unknown as OpenClawConfig; + // "Router D" normalizes to "router-d" — should still detect own token + expect(normalizedHelpers.listAccountIds(config)).toEqual(["default", "router-d"]); + }); + it("does NOT inject default in mixed configs (some accounts inherit base tokens)", () => { const config = { channels: { diff --git a/src/channels/plugins/account-helpers.ts b/src/channels/plugins/account-helpers.ts index f3e66537b82..35403728c1a 100644 --- a/src/channels/plugins/account-helpers.ts +++ b/src/channels/plugins/account-helpers.ts @@ -63,8 +63,19 @@ export function createAccountListHelpers( ); if (baseTokenFields.length > 0) { const accounts = (base?.accounts ?? {}) as Record>; + // Build reverse map from normalized ID → raw config key so we can look + // up the account object even when normalizeAccountId transforms the keys. + const rawKeys = Object.keys(accounts); + const normalizedToRaw = new Map(); + for (const key of rawKeys) { + const normalized = normalizeAccountId(key); + if (normalized && !normalizedToRaw.has(normalized)) { + normalizedToRaw.set(normalized, key); + } + } const everyAccountHasOwnTokens = ids.every((id) => { - const acct = accounts[id]; + const rawKey = normalizedToRaw.get(id) ?? id; + const acct = accounts[rawKey]; if (!acct) { return false; }