Files
codex/prs/bolinfest/PR-1827.md
2025-09-02 15:17:45 -07:00

6.1 KiB

PR #1827: Get rid of unnecessary ERROR messages

Description

When interrupting a model turn with ctr-c or at end of exec, we print an ERROR message, which is jank. Let's not do that.

Full Diff

diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs
index 568d87c4a8..f2b5101ed2 100644
--- a/codex-rs/core/src/codex.rs
+++ b/codex-rs/core/src/codex.rs
@@ -627,8 +627,8 @@ impl AgentTask {
             self.handle.abort();
             let event = Event {
                 id: self.sub_id,
-                msg: EventMsg::Error(ErrorEvent {
-                    message: "Turn interrupted".to_string(),
+                msg: EventMsg::BackgroundEvent(BackgroundEventEvent {
+                    message: "Response interrupted.".to_string(),
                 }),
             };
             let tx_event = self.sess.tx_event.clone();
diff --git a/codex-rs/exec/src/lib.rs b/codex-rs/exec/src/lib.rs
index ce4d7f65cc..fe3b058970 100644
--- a/codex-rs/exec/src/lib.rs
+++ b/codex-rs/exec/src/lib.rs
@@ -181,20 +181,22 @@ pub async fn run_main(cli: Cli, codex_linux_sandbox_exe: Option<PathBuf>) -> any
                             )
                             .await;
 
-                        // Exit the inner loop and return to the main input prompt.  The codex
-                        // will emit a `TurnInterrupted` (Error) event which is drained later.
                         break;
                     }
                     res = codex.next_event() => match res {
                         Ok(event) => {
+                            let is_shutdown = matches!(event.msg, EventMsg::ShutdownComplete);
                             debug!("Received event: {event:?}");
                             if let Err(e) = tx.send(event) {
                                 error!("Error sending event: {e:?}");
                                 break;
                             }
+                            if is_shutdown {
+                                break;
+                            }
                         },
                         Err(e) => {
-                            error!("Error receiving event: {e:?}");
+                            debug!("Event stream ended: {e:?}");
                             break;
                         }
                     }
diff --git a/codex-rs/tui/src/bottom_pane/mod.rs b/codex-rs/tui/src/bottom_pane/mod.rs
index cab78bbe3f..c8c88e3a24 100644
--- a/codex-rs/tui/src/bottom_pane/mod.rs
+++ b/codex-rs/tui/src/bottom_pane/mod.rs
@@ -286,8 +286,8 @@ impl BottomPane<'_> {
 impl WidgetRef for &BottomPane<'_> {
     fn render_ref(&self, area: Rect, buf: &mut Buffer) {
         // Show BottomPaneView if present.
-        if let Some(ov) = &self.active_view {
-            ov.render(area, buf);
+        if let Some(active_view) = &self.active_view {
+            active_view.render(area, buf);
         } else {
             (&self.composer).render_ref(area, buf);
         }
diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs
index e5ebf58a07..68778f5ec0 100644
--- a/codex-rs/tui/src/chatwidget.rs
+++ b/codex-rs/tui/src/chatwidget.rs
@@ -10,6 +10,7 @@ use codex_core::protocol::AgentMessageEvent;
 use codex_core::protocol::AgentReasoningDeltaEvent;
 use codex_core::protocol::AgentReasoningEvent;
 use codex_core::protocol::ApplyPatchApprovalRequestEvent;
+use codex_core::protocol::BackgroundEventEvent;
 use codex_core::protocol::ErrorEvent;
 use codex_core::protocol::Event;
 use codex_core::protocol::EventMsg;
@@ -220,6 +221,13 @@ impl ChatWidget<'_> {
     pub(crate) fn handle_codex_event(&mut self, event: Event) {
         let Event { id, msg } = event;
         match msg {
+            EventMsg::BackgroundEvent(BackgroundEventEvent { message }) => {
+                self.add_to_history(HistoryCell::new_background_event(message.clone()));
+                if message.contains("Turn interrupted") {
+                    self.bottom_pane.set_task_running(false);
+                }
+                self.request_redraw();
+            }
             EventMsg::SessionConfigured(event) => {
                 self.bottom_pane
                     .set_history_metadata(event.history_log_id, event.history_entry_count);

Review Comments

codex-rs/core/src/codex.rs

@@ -601,8 +601,8 @@ impl AgentTask {
             self.handle.abort();
             let event = Event {
                 id: self.sub_id,
-                msg: EventMsg::Error(ErrorEvent {
-                    message: "Turn interrupted".to_string(),
+                msg: EventMsg::BackgroundEvent(BackgroundEventEvent {

Let's introduce a new variant in EventMsg for this and then let the UI decide how it wants to present it.

codex-rs/exec/src/lib.rs

@@ -181,20 +181,22 @@ pub async fn run_main(cli: Cli, codex_linux_sandbox_exe: Option<PathBuf>) -> any
                             )
                             .await;
 
-                        // Exit the inner loop and return to the main input prompt.  The codex
-                        // will emit a `TurnInterrupted` (Error) event which is drained later.
                         break;
                     }
                     res = codex.next_event() => match res {
                         Ok(event) => {
+                            let is_shutdown = matches!(event.msg, EventMsg::ShutdownComplete);
                             debug!("Received event: {event:?}");
                             if let Err(e) = tx.send(event) {
                                 error!("Error sending event: {e:?}");
                                 break;
                             }
+                            if is_shutdown {

I don't think this is a safe way to change the control flow.