fix(web-chat): prevent blank chat pane after assistant response (#67035)#77418
fix(web-chat): prevent blank chat pane after assistant response (#67035)#77418carlytwozero wants to merge 1 commit into
Conversation
After a turn completes, the UI could briefly or permanently show blank content. Two related issues: 1. When loadChatHistory is triggered by a final event (tool turns or non-renderable final messages), chatLoading was only set inside the async function body — synchronously, but still after the void call site returned. In practice loadChatHistory sets it before the first await, but explicitly pre-setting chatLoading = true at every call site in handleTerminalChatEvent and handleChatGatewayEvent makes the loading state visible to any synchronous re-render that fires between the call and the function body running. 2. When loadChatHistory returned early because the client was disconnected (!state.client || !state.connected), any chatLoading = true that had been pre-set externally was never cleared, leaving the UI stuck in a loading state rather than showing cached messages. Together these close the window where: streaming ends → chatStream = null → chatMessages not yet updated → chatLoading still false → UI renders empty (isEmpty = true) before the history reload finishes. Fixes openclaw#67035 Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
|
Codex review: needs real behavior proof before merge. Summary Reproducibility: no. Source inspection confirms the current reload and empty/loading render paths, but there is no high-confidence live reproduction and the claimed async call-site gap remains inferred. Real behavior proof Next step before merge Security Review detailsBest possible solution: Review this as a narrow WebChat loading-state fix only after redacted real browser proof is added, and keep #67035 open or rescope it for the remaining IME/streaming symptoms. Do we have a high-confidence way to reproduce the issue? No. Source inspection confirms the current reload and empty/loading render paths, but there is no high-confidence live reproduction and the claimed async call-site gap remains inferred. Is this the best way to solve the issue? Unclear. The disconnected early-return cleanup is narrow, but the call-site pre-set duplicates behavior already performed synchronously by Acceptance criteria:
What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against b7e8f6da6ac1. |
|
Heads up: this PR needs to be updated against current |
|
Thanks for taking this on. I’m closing this now because the linked bug path has been superseded by #89530, which landed on What changed since this PR was opened:
Why I’m not landing this PR separately:
If there is still a blank WebChat pane on current |
Problem
After a turn completes, the chat UI could render blank — showing nothing where the assistant's response should be — until the user manually refreshed the page. The content was there in gateway history, just not displayed.
Root cause
Two gaps in the
chatLoadingflag lifecycle when history reloads are triggered by terminal chat events:Gap 1 — pre-set missing before
voidcallsIn
handleTerminalChatEventandhandleChatGatewayEvent,loadChatHistoryis called withvoid(fire-and-forget).chatLoading = trueis set inside the async function synchronously before the firstawait, but there's no guarantee a reactive render won't fire in the gap between the call site and function entry. Explicitly pre-settingchatLoading = trueat each call site eliminates this window.Gap 2 — early-exit path never cleared
chatLoadingIf
loadChatHistoryreturned early due to!state.client || !state.connected, anychatLoading = truethat had been pre-set externally was never reset. This left the UI stuck showing a loading state instead of cached messages. Addingstate.chatLoading = falseto the early-exit branch fixes this.Together these close the render window where:
chatStream = null→chatMessagesnot yet updated →chatLoadingstill false →isEmpty = true→ blank pane.Changes
ui/src/ui/app-gateway.ts— pre-setchatLoading = trueat all threevoid loadChatHistory()call sites (tool-turn path inhandleTerminalChatEvent, final-event-needs-reload path, and deferred session-message reload path).ui/src/ui/controllers/chat.ts— resetchatLoading = falsein the early-return path so pre-set loading flag doesn't get stuck.Test plan
Fixes #67035
🤖 Generated with Claude Code