# PR #1831: handle PatchApplyEnd - URL: https://github.com/openai/codex/pull/1831 - Author: nornagon-openai - Created: 2025-08-04 22:52:35 UTC - Updated: 2025-08-13 17:44:48 UTC - Changes: +28/-0, Files changed: 2, Commits: 1 ## 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 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 human‑friendly 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> = 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) -> Vec { ``` ## Review Comments ### codex-rs/tui/src/chatwidget.rs - Created: 2025-08-04 23:37:45 UTC | Link: https://github.com/openai/codex/pull/1831#discussion_r2252795192 ```diff @@ -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 - Created: 2025-08-04 23:36:29 UTC | Link: https://github.com/openai/codex/pull/1831#discussion_r2252794001 ```diff @@ -629,6 +634,18 @@ impl HistoryCell { view: TextBlock::new(lines), } } + + pub fn new_patch_failed_event(stdout: String, stderr: String) -> Self { + let lines: Vec> = 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?