diff --git a/codex-rs/core/src/guardian/approval_request.rs b/codex-rs/core/src/guardian/approval_request.rs index 250ed7e924..b89d020ca8 100644 --- a/codex-rs/core/src/guardian/approval_request.rs +++ b/codex-rs/core/src/guardian/approval_request.rs @@ -160,6 +160,7 @@ fn command_assessment_action( } } +#[cfg(unix)] fn guardian_command_source_tool_name(source: GuardianCommandSource) -> &'static str { match source { GuardianCommandSource::Shell => "shell", diff --git a/codex-rs/tui/src/app.rs b/codex-rs/tui/src/app.rs index add9e63741..75286b8d63 100644 --- a/codex-rs/tui/src/app.rs +++ b/codex-rs/tui/src/app.rs @@ -2202,7 +2202,7 @@ impl App { match op.view() { AppCommandView::Interrupt => { let Some(turn_id) = self.active_turn_id_for_thread(thread_id).await else { - return Ok(false); + return Ok(true); }; app_server.turn_interrupt(thread_id, turn_id).await?; Ok(true) @@ -10663,6 +10663,24 @@ guardian_approval = true ); } + #[tokio::test] + async fn interrupt_without_active_turn_is_treated_as_handled() { + let mut app = make_test_app().await; + let thread_id = ThreadId::new(); + let mut app_server = + crate::start_embedded_app_server_for_picker(app.chat_widget.config_ref()) + .await + .expect("embedded app server"); + let op = AppCommand::interrupt(); + + let handled = app + .try_submit_active_thread_op_via_app_server(&mut app_server, thread_id, &op) + .await + .expect("interrupt submission should not fail"); + + assert_eq!(handled, true); + } + #[tokio::test] async fn clear_only_ui_reset_preserves_chat_session_state() { let mut app = make_test_app().await;