From 2fc7bb32d848bc92cd455b1189d7a53e3fa859b9 Mon Sep 17 00:00:00 2001 From: Charles Cunningham Date: Mon, 2 Mar 2026 19:30:08 -0800 Subject: [PATCH] tui: replay review agent messages in thread snapshots --- codex-rs/tui/src/chatwidget.rs | 8 +++++--- codex-rs/tui/src/chatwidget/tests.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index 5ed21514e7..f78764ab31 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -4468,12 +4468,14 @@ impl ChatWidget { EventMsg::SessionConfigured(e) => self.on_session_configured(e), EventMsg::ThreadNameUpdated(e) => self.on_thread_name_updated(e), EventMsg::AgentMessage(AgentMessageEvent { .. }) - if matches!(replay_kind, Some(ReplayKind::ThreadSnapshot)) => {} + if matches!(replay_kind, Some(ReplayKind::ThreadSnapshot)) + && !self.is_review_mode => {} EventMsg::AgentMessage(AgentMessageEvent { message, .. }) if from_replay || self.is_review_mode => { - // TODO(ccunningham): stop relying on legacy AgentMessage in review mode and - // forward ItemCompleted(TurnItem::AgentMessage(_)) instead. + // TODO(ccunningham): stop relying on legacy AgentMessage in review mode, + // including thread-snapshot replay, and forward + // ItemCompleted(TurnItem::AgentMessage(_)) instead. self.on_agent_message(message) } EventMsg::AgentMessage(AgentMessageEvent { .. }) => {} diff --git a/codex-rs/tui/src/chatwidget/tests.rs b/codex-rs/tui/src/chatwidget/tests.rs index 9fbc3cc186..8e8bc0e380 100644 --- a/codex-rs/tui/src/chatwidget/tests.rs +++ b/codex-rs/tui/src/chatwidget/tests.rs @@ -1505,6 +1505,32 @@ async fn live_agent_message_renders_during_review_mode() { assert!(lines_to_single_string(&inserted[0]).contains("Review progress update")); } +#[tokio::test] +async fn thread_snapshot_replay_preserves_agent_message_during_review_mode() { + let (mut chat, mut rx, _ops) = make_chatwidget_manual(None).await; + + chat.handle_codex_event_replay(Event { + id: "review-start".into(), + msg: EventMsg::EnteredReviewMode(ReviewRequest { + target: ReviewTarget::UncommittedChanges, + user_facing_hint: None, + }), + }); + let _ = drain_insert_history(&mut rx); + + chat.handle_codex_event_replay(Event { + id: "review-message".into(), + msg: EventMsg::AgentMessage(AgentMessageEvent { + message: "Review progress update".to_string(), + phase: None, + }), + }); + + let inserted = drain_insert_history(&mut rx); + assert_eq!(inserted.len(), 1); + assert!(lines_to_single_string(&inserted[0]).contains("Review progress update")); +} + /// Exiting review restores the pre-review context window indicator. #[tokio::test] async fn review_restores_context_window_indicator() {