fix(tui): recover activity status when no runs are in flight#64862
fix(tui): recover activity status when no runs are in flight#64862Yanhu007 wants to merge 1 commit intoopenclaw:mainfrom
Conversation
The TUI status bar can get stuck on "streaming" indefinitely after a
chat turn completes. This happens when `state.activeChatRunId` is
cleared by a concurrent event before the "final" event arrives, making
`wasActiveRun` false in `finalizeRun` and skipping the
`setActivityStatus("idle")` call.
Add a recovery condition: when `wasActiveRun` is false but there are
provably no other runs in flight (`sessionRuns.size === 0` and
`activeChatRunId` is null), still transition the activity status. This
is safe because it only fires when the state machine has confirmed no
other work is active.
Apply the same fix to `terminateRun` for consistency.
Fixes openclaw#64825
Greptile SummaryThis PR adds a fallback condition in Confidence Score: 5/5Safe to merge — the recovery condition is conservative and only fires when provably no work is in flight. Both changed call-sites are symmetric, the guard is logically sound (noteFinalizedRun/sessionRuns.delete already removed the run before the check), and the condition cannot spuriously fire while another run is active. All remaining findings are at P2 or lower. No files require special attention. Reviews (1): Last reviewed commit: "fix(tui): recover activity status when n..." | Re-trigger Greptile |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8f47aacb35
ℹ️ 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".
| clearActiveRunIfMatch(params.runId); | ||
| flushPendingHistoryRefreshIfIdle(); | ||
| if (params.wasActiveRun) { | ||
| if (params.wasActiveRun || (sessionRuns.size === 0 && !state.activeChatRunId)) { |
There was a problem hiding this comment.
Skip fallback status updates for local BTW runs
handleChatEvent deliberately keeps /btw runs out of activeChatRunId tracking, but this new fallback in terminateRun updates activity when there are no in-flight runs even when wasActiveRun is false. If a local BTW run ends with aborted/error, the TUI status can now flip to aborted/error and stay there despite no main chat run being active, which is a regression from prior behavior where non-active BTW runs did not mutate global activity state.
Useful? React with 👍 / 👎.
|
Closing this as implemented after Codex automated review. Current main already fixes the user-visible stuck TUI Best possible solution: Close #64862 and keep the shipped #67401 watchdog implementation. If a stuck TUI status is still reproducible on current releases, it should be tracked as a fresh bug with event-ordering logs, version details, affected plugin/channel context, and a regression test for the new ordering. What I checked:
So I’m closing this as already implemented rather than keeping a duplicate issue open. Codex Review notes: model gpt-5.5, reasoning high; reviewed against d54d2d6b9b8a; fix evidence: release v2026.4.15, commit 352527393079. |
Summary
The TUI status bar can get stuck on
streamingindefinitely after a chat turn completes. WhenactiveChatRunIdis cleared by a concurrent event before the final event arrives,wasActiveRunis false andsetActivityStatus("idle")is never called.Changes
Add a recovery condition to
finalizeRunandterminateRun: whenwasActiveRunis false but no other runs are in flight (sessionRuns.size === 0andactiveChatRunIdis null), still transition the activity status. Safe because it only fires when no work is active.Fixes #64825