mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-17 08:00:59 +00:00
fix(agent): Properly handle ESC interrupt in TUI with centralized event emission
Fixed the interrupt mechanism to show "[Interrupted by user]" message when ESC is pressed: - Removed duplicate UI cleanup from ESC key handler that interfered with event processing - Added centralized interrupted event emission in exception handler when abort signal is detected - Removed duplicate event emissions from API call methods to prevent multiple messages - Added abort signal support to preflight reasoning check for proper cancellation - Simplified abort detection to only check signal state, not error messages
This commit is contained in:
parent
1f9d10cab0
commit
1d9b77298c
5 changed files with 218 additions and 22 deletions
|
|
@ -0,0 +1,79 @@
|
|||
# Analysis: Interrupted Message Not Showing in TUI
|
||||
|
||||
## Problem Summary
|
||||
When pressing ESC to interrupt the agent while it's working, the "interrupted" message is not appearing in the TUI interface.
|
||||
|
||||
## Research Findings
|
||||
|
||||
### Interrupt Handling Flow
|
||||
|
||||
1. **ESC Key Detection** (TuiRenderer line 110)
|
||||
- ESC key is detected as `\x1b` in the `onGlobalKeyPress` handler
|
||||
- Only triggers when `this.currentLoadingAnimation` is active (agent is processing)
|
||||
|
||||
2. **Immediate UI Cleanup** (TuiRenderer lines 112-128)
|
||||
- Calls `this.onInterruptCallback()` (which calls `agent.interrupt()`)
|
||||
- Stops loading animation and clears status container
|
||||
- Re-enables text editor submission
|
||||
- Requests UI render
|
||||
|
||||
3. **Agent Interruption** (Agent.ts line 615-617)
|
||||
- `agent.interrupt()` calls `this.abortController?.abort()`
|
||||
- This triggers AbortSignal in ongoing API calls
|
||||
|
||||
4. **Interrupted Event Generation** (Agent.ts multiple locations)
|
||||
- When signal is aborted, code checks `signal?.aborted`
|
||||
- Emits `{ type: "interrupted" }` event via `eventReceiver?.on()`
|
||||
- Throws `new Error("Interrupted")` to exit processing
|
||||
|
||||
5. **Message Display** (TuiRenderer line 272-283)
|
||||
- Handles `"interrupted"` event
|
||||
- Adds red "[Interrupted by user]" message to chat container
|
||||
- Requests render
|
||||
|
||||
### Root Cause Analysis
|
||||
|
||||
The issue appears to be a **race condition with duplicate cleanup**:
|
||||
|
||||
1. When ESC is pressed, the key handler **immediately** (lines 115-120):
|
||||
- Stops the loading animation
|
||||
- Clears the status container
|
||||
- Sets `currentLoadingAnimation = null`
|
||||
|
||||
2. Later, when the "interrupted" event arrives (lines 273-277), it tries to:
|
||||
- Stop the loading animation again (but it's already null)
|
||||
- Clear the status container again (already cleared)
|
||||
|
||||
3. The comment on line 123 says "Don't show message here - the interrupted event will handle it", but the event handler at line 280 **does** add the message to the chat container.
|
||||
|
||||
### The Actual Problem
|
||||
|
||||
Looking closely at the code flow:
|
||||
|
||||
1. ESC handler clears animation and calls `agent.interrupt()` (synchronous)
|
||||
2. Agent aborts the controller (synchronous)
|
||||
3. API call code detects abort and emits "interrupted" event (asynchronous)
|
||||
4. TUI renderer receives "interrupted" event and adds message (asynchronous)
|
||||
|
||||
The issue is likely that:
|
||||
- The interrupted event IS being emitted and handled
|
||||
- The message IS being added to the chat container
|
||||
- But the UI render might not be properly triggered or the differential rendering isn't detecting the change
|
||||
|
||||
### Additional Issues Found
|
||||
|
||||
1. **Duplicate Animation Cleanup**: The loading animation is stopped twice - once in the ESC handler and once in the interrupted event handler. This is redundant but shouldn't cause the missing message.
|
||||
|
||||
2. **Render Request Timing**: The ESC handler requests a render immediately after clearing the UI, then the interrupted event handler adds the message but doesn't explicitly request another render (it relies on the Container's automatic render request).
|
||||
|
||||
3. **Container Change Detection**: Recent commit 192d8d2 fixed container change detection issues. The interrupted message addition might not be triggering proper change detection.
|
||||
|
||||
## Solution Approach
|
||||
|
||||
The fix needs to ensure the interrupted message is properly displayed. Options:
|
||||
|
||||
1. **Add explicit render request** after adding the interrupted message
|
||||
2. **Remove duplicate cleanup** in the ESC handler and let the event handler do all the work
|
||||
3. **Ensure proper change detection** when adding the message to the chat container
|
||||
|
||||
The cleanest solution is likely option 2 - let the interrupted event handler do all the UI updates to avoid race conditions and ensure proper sequencing.
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
# Fix interrupted message not showing when ESC pressed in agent TUI
|
||||
|
||||
**Status:** Done
|
||||
**Agent PID:** 47968
|
||||
|
||||
## Original Todo
|
||||
agent/tui: not seeing a read "interrupted" mesage anymore if i press ESC while agnet works
|
||||
|
||||
## Description
|
||||
Fix the issue where the "interrupted" message is not displayed in the TUI when pressing ESC to interrupt the agent while it's processing. The root cause is duplicate UI cleanup in the ESC key handler that interferes with the asynchronous interrupted event handler.
|
||||
|
||||
*Read [analysis.md](./analysis.md) in full for detailed codebase research and context*
|
||||
|
||||
## Implementation Plan
|
||||
Remove duplicate UI cleanup from ESC key handler and ensure interrupted event handler properly displays the message:
|
||||
- [x] Remove duplicate loading animation cleanup from ESC key handler in tui-renderer.ts (lines 115-120)
|
||||
- [x] Add explicit render request after adding interrupted message (line 280)
|
||||
- [x] Fix core issue: Emit "interrupted" event when API call is aborted (agent.ts line 606-607)
|
||||
- [x] Pass abort signal to preflight reasoning check
|
||||
- [x] Test interruption during API call (e.g., "write a poem")
|
||||
- [x] Verify "[Interrupted by user]" message appears and UI is restored
|
||||
|
||||
## Notes
|
||||
[Implementation notes]
|
||||
Loading…
Add table
Add a link
Reference in a new issue