From 0f5a58be650e43d7fdc5b6b92ebb92bd85ea6f7d Mon Sep 17 00:00:00 2001 From: Charles Cunningham Date: Thu, 26 Feb 2026 23:45:06 -0800 Subject: [PATCH] tui: avoid duplicate user prompt rendering --- codex-rs/tui/src/chatwidget.rs | 9 +++++++-- codex-rs/tui/src/chatwidget/tests.rs | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index 8bccb294f5..7f07d93df7 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -4547,11 +4547,16 @@ impl ChatWidget { && let EventMsg::UserMessage(user_message) = item.as_legacy_event() { let rendered = Self::rendered_user_message_event_from_event(&user_message); - if self.pending_nudges.front() == Some(&rendered) { + let should_render = if self.pending_nudges.front() == Some(&rendered) { self.pending_nudges.pop_front(); self.refresh_pending_input_preview(); + true + } else { + self.last_rendered_user_message_event.as_ref() != Some(&rendered) + }; + if should_render { + self.on_user_message_event(user_message); } - self.on_user_message_event(user_message); } } EventMsg::EnteredReviewMode(review_request) => { diff --git a/codex-rs/tui/src/chatwidget/tests.rs b/codex-rs/tui/src/chatwidget/tests.rs index 2a3e6f2ef6..3aabaff4b4 100644 --- a/codex-rs/tui/src/chatwidget/tests.rs +++ b/codex-rs/tui/src/chatwidget/tests.rs @@ -3626,6 +3626,24 @@ async fn raw_response_item_with_canonicalized_user_payload_clears_pending_nudge( assert!(lines_to_single_string(&inserted[0]).contains("hello world")); } +#[tokio::test] +async fn raw_response_item_does_not_duplicate_locally_rendered_user_message() { + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + chat.thread_id = Some(ThreadId::new()); + + chat.bottom_pane + .set_composer_text("hello".to_string(), Vec::new(), Vec::new()); + chat.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); + + let inserted = drain_insert_history(&mut rx); + assert_eq!(inserted.len(), 1); + assert!(lines_to_single_string(&inserted[0]).contains("hello")); + + chat.handle_codex_event(raw_user_message_event("hello")); + + assert!(drain_insert_history(&mut rx).is_empty()); +} + #[tokio::test] async fn raw_response_item_only_pops_front_pending_nudge() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await;