Summary
The TUI can show connected | error in the footer without rendering the actual run error in the transcript. The input can remain blocked with:
agent is busy - press Esc to abort before sending a new message
If the user does not have logs open, there is no visible explanation for what failed.
Actual behavior
A runtime/provider failure can reach the TUI as an agent lifecycle error, which updates the footer activity status to error.
However, the visible transcript error path is separate. The TUI only renders a visible run error: ... message and clears the active run when it receives a terminal chat event with state: "error".
When only the lifecycle error is observed, the TUI can end up in this confusing state:
- footer shows
connected | error
- watchdog text may remain visible
- no provider/runtime error is rendered in the transcript
activeChatRunId remains set
- sending another prompt is blocked as busy
Expected behavior
A terminal runtime/provider failure for the active TUI chat run should become a visible terminal chat error in the TUI.
Expected behavior:
- dismiss stale watchdog text for that run
- render a visible message such as
run error: <provider/runtime error>
- clear the active run
- keep activity status as
error
- unblock input so the user can continue
- preserve existing successful streaming and final-response behavior
Notes
Relevant TUI paths:
src/tui/tui-event-handlers.ts
src/tui/tui-command-handlers.ts
The footer status and input lock are currently driven by different state paths. connected | error means the lifecycle status reached the TUI, but it does not guarantee that a terminal chat error was rendered or that the active chat run was cleared.
The old watchdog behavior could mask this by clearing the active run after a timeout and telling the user to send another message. That did not actually surface the underlying provider/runtime error. The safer behavior is to keep the active run locked while it is genuinely active, but terminal failures must be rendered and must clear the active run.
Acceptance criteria
- Lifecycle/provider failure for an active TUI chat run renders a visible error.
- The active run is cleared after the terminal error.
- The user can send a new message after the error.
- Watchdog pending text does not remain stale after the error.
- Add a focused TUI regression test for lifecycle-error handling.
Summary
The TUI can show
connected | errorin the footer without rendering the actual run error in the transcript. The input can remain blocked with:If the user does not have logs open, there is no visible explanation for what failed.
Actual behavior
A runtime/provider failure can reach the TUI as an agent lifecycle error, which updates the footer activity status to
error.However, the visible transcript error path is separate. The TUI only renders a visible
run error: ...message and clears the active run when it receives a terminalchatevent withstate: "error".When only the lifecycle error is observed, the TUI can end up in this confusing state:
connected | erroractiveChatRunIdremains setExpected behavior
A terminal runtime/provider failure for the active TUI chat run should become a visible terminal chat error in the TUI.
Expected behavior:
run error: <provider/runtime error>errorNotes
Relevant TUI paths:
src/tui/tui-event-handlers.tssrc/tui/tui-command-handlers.tsThe footer status and input lock are currently driven by different state paths.
connected | errormeans the lifecycle status reached the TUI, but it does not guarantee that a terminal chat error was rendered or that the active chat run was cleared.The old watchdog behavior could mask this by clearing the active run after a timeout and telling the user to send another message. That did not actually surface the underlying provider/runtime error. The safer behavior is to keep the active run locked while it is genuinely active, but terminal failures must be rendered and must clear the active run.
Acceptance criteria