fix(ui): clear pending run state on cross-run final to fix stuck typing indicator#57887
fix(ui): clear pending run state on cross-run final to fix stuck typing indicator#57887haoyu-haoyu wants to merge 1 commit intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR fixes a frontend state bug where the typing/processing indicator remained stuck after a subagent's cross-run Key observations:
Confidence Score: 5/5
Reviews (1): Last reviewed commit: "fix(ui): clear pending run state on cros..." | Re-trigger Greptile |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6429e8738b
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| state.chatRunId = null; | ||
| state.chatStream = null; | ||
| state.chatStreamStartedAt = null; |
There was a problem hiding this comment.
Preserve active run when processing other-run finals
Clearing chatRunId/stream state in the cross-run branch treats another run’s final event as if the active run had finished, which can incorrectly unlock the chat input and hide stop/tool progress while the original run is still in flight. This is reachable because the gateway emits assistant final events with unrelated run IDs for non-terminal updates (for example chat.inject uses synthetic inject-* run IDs in src/gateway/server-methods/chat.ts:1942-1953), so this code can prematurely drop the active run state before the matching run’s own terminal event arrives.
Useful? React with 👍 / 👎.
…ng indicator When a subagent completes and sends a final event with a different runId, the WebChat UI appends the message but did not clear chatRunId / chatStream / chatStreamStartedAt. This left the parent agent visually stuck in a typing / processing state even after the final response was already visible. Refreshing the page cleared it. Now clear the pending run state when a cross-run final carries a real (non-NO_REPLY) assistant message. NO_REPLY / empty finals still preserve the parent run state since the parent agent may still be processing. Closes openclaw#57795 Assisted-by: Claude Code
6429e87 to
eb2b75b
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: eb2b75b506
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| state.chatRunId = null; | ||
| state.chatStream = null; | ||
| state.chatStreamStartedAt = null; |
There was a problem hiding this comment.
Preserve active run state on foreign final events
Clearing chatRunId/stream in the cross-run final branch makes the UI treat any other run’s terminal event as completion of the active run, which is incorrect when the user’s run is still in flight. The gateway still emits assistant final events with different run IDs (for example chat.inject broadcasts runId: inject-* in src/gateway/server-methods/chat.ts), so this path can prematurely drop busy state, hide ongoing tool/progress updates, and let queued messages flush early through isChatBusy/flushChatQueueForEvent even though the original run has not finished.
Useful? React with 👍 / 👎.
|
Closing this as duplicate or superseded after Codex automated review. Close PR #57887 as superseded by the canonical open bug #57795. Current main intentionally preserves active WebChat run state for foreign Best possible solution: Close this unsafe PR and keep #57795 as the canonical tracker. The best fix is a run-ownership-aware WebChat reconciliation change that clears What I checked:
So I’m closing this here and keeping the remaining discussion on the canonical linked item. Codex Review notes: model gpt-5.5, reasoning high; reviewed against 4ad8b613c9b6. |
Summary
finalevent carries a real assistant message, clearchatRunId,chatStream, andchatStreamStartedAtso the UI exits the typing/processing indicator.Root cause
In
handleChatEvent, the cross-run final branch (line 283–293) appended the subagent's message but returned without clearing the pending run state. This left the parent agent visually stuck in typing state even after the final response was visible. Refreshing the page cleared it immediately — confirming a frontend state bug, not a backend hang.Validation
pnpm test -- ui/src/ui/controllers/chat.test.ts— updated test to expect state cleared on cross-run final with message contentNotes
finalMessageis present and non-silent. If a cross-run final is NO_REPLY or has no message, the parent run state is preserved since the parent agent may still be actively streaming.Closes #57795