diff --git a/src/auto-reply/reply/session.test.ts b/src/auto-reply/reply/session.test.ts index e24262a0fa9..1b80294a978 100644 --- a/src/auto-reply/reply/session.test.ts +++ b/src/auto-reply/reply/session.test.ts @@ -2680,4 +2680,30 @@ describe("initSessionState internal channel routing preservation", () => { expect(result.sessionEntry.deliveryContext?.channel).toBe("whatsapp"); expect(result.sessionEntry.deliveryContext?.to).toBe("+15555550123"); }); + + it("uses the configured default account for persisted routing when AccountId is omitted", async () => { + const storePath = await createStorePath("default-account-routing-context-"); + const cfg = { + session: { store: storePath }, + channels: { + discord: { + defaultAccount: "work", + }, + }, + } as OpenClawConfig; + + const result = await initSessionState({ + ctx: { + Body: "hello", + SessionKey: "agent:main:discord:channel:24680", + OriginatingChannel: "discord", + OriginatingTo: "channel:24680", + }, + cfg, + commandAuthorized: true, + }); + + expect(result.sessionEntry.lastAccountId).toBe("work"); + expect(result.sessionEntry.deliveryContext?.accountId).toBe("work"); + }); }); diff --git a/src/auto-reply/reply/session.ts b/src/auto-reply/reply/session.ts index d82761682ff..a3771f70d2a 100644 --- a/src/auto-reply/reply/session.ts +++ b/src/auto-reply/reply/session.ts @@ -66,6 +66,31 @@ function resolveExplicitSessionEndReason( return matchedResetTriggerLower === "/reset" ? "reset" : "new"; } +function resolveSessionDefaultAccountId(params: { + cfg: OpenClawConfig; + channelRaw?: string; + accountIdRaw?: string; + persistedLastAccountId?: string; +}): string | undefined { + const explicit = params.accountIdRaw?.trim(); + if (explicit) { + return explicit; + } + const persisted = params.persistedLastAccountId?.trim(); + if (persisted) { + return persisted; + } + const channel = params.channelRaw?.trim().toLowerCase(); + if (!channel) { + return undefined; + } + const channels = params.cfg.channels as Record; + const configuredDefault = channels?.[channel]?.defaultAccount; + return typeof configuredDefault === "string" && configuredDefault.trim() + ? configuredDefault.trim() + : undefined; +} + function resolveStaleSessionEndReason(params: { entry: SessionEntry | undefined; freshness?: SessionFreshness; @@ -507,7 +532,12 @@ export async function initSessionState(params: { persistedLastChannel: baseEntry?.lastChannel, sessionKey, }); - const lastAccountIdRaw = ctx.AccountId || baseEntry?.lastAccountId; + const lastAccountIdRaw = resolveSessionDefaultAccountId({ + cfg, + channelRaw: lastChannelRaw, + accountIdRaw: ctx.AccountId, + persistedLastAccountId: baseEntry?.lastAccountId, + }); // Only fall back to persisted threadId for thread sessions. Non-thread // sessions (e.g. DM without topics) must not inherit a stale threadId from a // previous interaction that happened inside a topic/thread.