From 9d941949c9ea47f3e6277aab744860d83f6c0dcd Mon Sep 17 00:00:00 2001 From: Lynn Date: Wed, 4 Mar 2026 14:53:38 +0800 Subject: [PATCH] fix(tui): normalize session key to lowercase to match gateway canonicalization (#34013) Merged via squash. Prepared head SHA: cfe06ca131661d1fd669270345c549ee8141cc46 Co-authored-by: lynnzc <6257996+lynnzc@users.noreply.github.com> Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com> Reviewed-by: @altaywtf --- CHANGELOG.md | 1 + src/tui/tui.test.ts | 21 +++++++++++++++++++++ src/tui/tui.ts | 4 ++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57307903afd..d853f53faac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- TUI/session-key canonicalization: normalize `openclaw tui --session` values to lowercase so uppercase session names no longer drop real-time streaming updates due to gateway/TUI key mismatches. (#33866, #34013) thanks @lynnzc. - Outbound/send config threading: pass resolved SecretRef config through outbound adapters and helper send paths so send flows do not reload unresolved runtime config. (#33987) Thanks @joshavant. - Sessions/subagent attachments: remove `attachments[].content.maxLength` from `sessions_spawn` schema to avoid llama.cpp GBNF repetition overflow, and preflight UTF-8 byte size before buffer allocation while keeping runtime file-size enforcement unchanged. (#33648) Thanks @anisoptera. - Runtime/tool-state stability: recover from dangling Anthropic `tool_use` after compaction, serialize long-running Discord handler runs without blocking new inbound events, and prevent stale busy snapshots from suppressing stuck-channel recovery. (from #33630, #33583) Thanks @kevinWangSheng and @theotarr. diff --git a/src/tui/tui.test.ts b/src/tui/tui.test.ts index 9b46da66a99..2882cebcd64 100644 --- a/src/tui/tui.test.ts +++ b/src/tui/tui.test.ts @@ -74,6 +74,27 @@ describe("resolveTuiSessionKey", () => { }), ).toBe("agent:ops:incident"); }); + + it("lowercases session keys with uppercase characters", () => { + // Uppercase in agent-prefixed form + expect( + resolveTuiSessionKey({ + raw: "agent:main:Test1", + sessionScope: "global", + currentAgentId: "main", + sessionMainKey: "agent:main:main", + }), + ).toBe("agent:main:test1"); + // Uppercase in bare form (prefixed by currentAgentId) + expect( + resolveTuiSessionKey({ + raw: "Test1", + sessionScope: "global", + currentAgentId: "main", + sessionMainKey: "agent:main:main", + }), + ).toBe("agent:main:test1"); + }); }); describe("resolveGatewayDisconnectState", () => { diff --git a/src/tui/tui.ts b/src/tui/tui.ts index 847245b3b67..fe365477d91 100644 --- a/src/tui/tui.ts +++ b/src/tui/tui.ts @@ -203,9 +203,9 @@ export function resolveTuiSessionKey(params: { return trimmed; } if (trimmed.startsWith("agent:")) { - return trimmed; + return trimmed.toLowerCase(); } - return `agent:${params.currentAgentId}:${trimmed}`; + return `agent:${params.currentAgentId}:${trimmed.toLowerCase()}`; } export function resolveGatewayDisconnectState(reason?: string): {