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

4.5 KiB
Raw Blame History

PR #1831: handle PatchApplyEnd

Description

This is more to drop the ugly unhandled PatchApplyEnd messages than it is about showing patch failures cleanly (I haven't been able to get a patch failure to occur so it's hard for me to test the failure message).

Full Diff

diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs
index e5ebf58a07..d90882bd05 100644
--- a/codex-rs/tui/src/chatwidget.rs
+++ b/codex-rs/tui/src/chatwidget.rs
@@ -21,6 +21,7 @@ use codex_core::protocol::McpToolCallBeginEvent;
 use codex_core::protocol::McpToolCallEndEvent;
 use codex_core::protocol::Op;
 use codex_core::protocol::PatchApplyBeginEvent;
+use codex_core::protocol::PatchApplyEndEvent;
 use codex_core::protocol::TaskCompleteEvent;
 use codex_core::protocol::TokenUsage;
 use crossterm::event::KeyEvent;
@@ -386,6 +387,16 @@ impl ChatWidget<'_> {
                     changes,
                 ));
             }
+            EventMsg::PatchApplyEnd(PatchApplyEndEvent {
+                call_id: _,
+                stdout,
+                stderr,
+                success,
+            }) => {
+                if !success {
+                    self.add_to_history(HistoryCell::new_patch_failed_event(stdout, stderr));
+                }
+            }
             EventMsg::ExecCommandEnd(ExecCommandEndEvent {
                 call_id,
                 exit_code,
diff --git a/codex-rs/tui/src/history_cell.rs b/codex-rs/tui/src/history_cell.rs
index c2aafdd522..3d9cf85f03 100644
--- a/codex-rs/tui/src/history_cell.rs
+++ b/codex-rs/tui/src/history_cell.rs
@@ -113,6 +113,9 @@ pub(crate) enum HistoryCell {
     /// model wants to apply before being prompted to approve or deny it.
     PendingPatch { view: TextBlock },
 
+    /// A patch failed to apply.
+    PatchFailed { view: TextBlock },
+
     /// A humanfriendly rendering of the model's current plan and step
     /// statuses provided via the `update_plan` tool.
     PlanUpdate { view: TextBlock },
@@ -137,6 +140,7 @@ impl HistoryCell {
             | HistoryCell::CompletedExecCommand { view }
             | HistoryCell::CompletedMcpToolCall { view }
             | HistoryCell::PendingPatch { view }
+            | HistoryCell::PatchFailed { view }
             | HistoryCell::PlanUpdate { view }
             | HistoryCell::ActiveExecCommand { view, .. }
             | HistoryCell::ActiveMcpToolCall { view, .. } => {
@@ -148,6 +152,7 @@ impl HistoryCell {
             ],
         }
     }
+
     pub(crate) fn new_session_info(
         config: &Config,
         event: SessionConfiguredEvent,
@@ -629,6 +634,18 @@ impl HistoryCell {
             view: TextBlock::new(lines),
         }
     }
+
+    pub fn new_patch_failed_event(stdout: String, stderr: String) -> Self {
+        let lines: Vec<Line<'static>> = vec![
+            Line::from("patch failed".red().bold()),
+            Line::from(stdout),
+            Line::from(stderr),
+            Line::from(""),
+        ];
+        HistoryCell::PatchFailed {
+            view: TextBlock::new(lines),
+        }
+    }
 }
 
 fn create_diff_summary(changes: HashMap<PathBuf, FileChange>) -> Vec<String> {

Review Comments

codex-rs/tui/src/chatwidget.rs

@@ -386,6 +387,16 @@ impl ChatWidget<'_> {
                     changes,
                 ));
             }
+            EventMsg::PatchApplyEnd(PatchApplyEndEvent {
+                call_id: _,
+                stdout,
+                stderr,
+                success,
+            }) => {
+                if !success {

I feel like it might be nice to have the changes from the PatchApplyBegin for better UI presentation, but I guess we can start with this.

codex-rs/tui/src/history_cell.rs

@@ -629,6 +634,18 @@ impl HistoryCell {
             view: TextBlock::new(lines),
         }
     }
+
+    pub fn new_patch_failed_event(stdout: String, stderr: String) -> Self {
+        let lines: Vec<Line<'static>> = vec![
+            Line::from("patch failed".red().bold()),

Not sure how intuitive this UI will be. You might want to omit Line::from() if stdout or stderr is empty?