Summary
In src/cortex-tui/src/bridge/event_adapter/adapters.rs, adapt_turn_aborted() maps all three TurnAbortReason variants to AppEvent::StreamingError. Two of the three variants (Replaced and ReviewEnded) represent normal, expected conditions — not errors. This causes the TUI to display an error message to the user when no error occurred.
Root Cause
Lines 41-48:
pub fn adapt_turn_aborted(e: &TurnAbortedEvent) -> Option<AppEvent> {
let reason = match e.reason {
cortex_protocol::TurnAbortReason::Interrupted => "Turn interrupted by user",
cortex_protocol::TurnAbortReason::Replaced => "Turn replaced by new request",
cortex_protocol::TurnAbortReason::ReviewEnded => "Review mode ended",
};
Some(AppEvent::StreamingError(reason.to_string())) // ← ALL variants → StreamingError
}
The three variants have different semantics:
Interrupted — User pressed Ctrl+C. This is intentional but could reasonably be shown as a warning/info.
Replaced — User sent a new message while the agent was still responding. The old turn is cancelled to process the new one. This is normal behavior, not an error.
ReviewEnded — Review mode ended normally. This is not an error.
Impact
When a user sends a new message while the agent is still responding (the most common case for Replaced), the TUI displays:
StreamingError: "Turn replaced by new request"
This is shown as an error in the UI (via AppEvent::StreamingError), alarming the user with a false error message for a completely normal interaction pattern. The same applies to ReviewEnded.
Reproduction
- Start a long agent response
- Send a new message before the response completes
- The UI displays "Turn replaced by new request" as a StreamingError — even though everything worked correctly
Fix
Map each variant to the appropriate event type:
pub fn adapt_turn_aborted(e: &TurnAbortedEvent) -> Option<AppEvent> {
match e.reason {
cortex_protocol::TurnAbortReason::Interrupted => {
Some(AppEvent::StreamingError("Turn interrupted by user".to_string()))
}
cortex_protocol::TurnAbortReason::Replaced => {
Some(AppEvent::StreamingCompleted) // Normal — new message replaced old turn
}
cortex_protocol::TurnAbortReason::ReviewEnded => {
Some(AppEvent::Info("Review mode ended".to_string())) // Normal
}
}
}
File
src/cortex-tui/src/bridge/event_adapter/adapters.rs, adapt_turn_aborted function, lines 41-48
Summary
In
src/cortex-tui/src/bridge/event_adapter/adapters.rs,adapt_turn_aborted()maps all threeTurnAbortReasonvariants toAppEvent::StreamingError. Two of the three variants (ReplacedandReviewEnded) represent normal, expected conditions — not errors. This causes the TUI to display an error message to the user when no error occurred.Root Cause
Lines 41-48:
The three variants have different semantics:
Interrupted— User pressed Ctrl+C. This is intentional but could reasonably be shown as a warning/info.Replaced— User sent a new message while the agent was still responding. The old turn is cancelled to process the new one. This is normal behavior, not an error.ReviewEnded— Review mode ended normally. This is not an error.Impact
When a user sends a new message while the agent is still responding (the most common case for
Replaced), the TUI displays:This is shown as an error in the UI (via
AppEvent::StreamingError), alarming the user with a false error message for a completely normal interaction pattern. The same applies toReviewEnded.Reproduction
Fix
Map each variant to the appropriate event type:
File
src/cortex-tui/src/bridge/event_adapter/adapters.rs,adapt_turn_abortedfunction, lines 41-48