From f2d626134bc97a2a2b24137fe366ddd604fb0587 Mon Sep 17 00:00:00 2001 From: canvrno-oai Date: Mon, 27 Apr 2026 23:15:15 -0700 Subject: [PATCH 1/2] Display status message when steer messages are submitted after thread completes --- codex-rs/tui/src/chatwidget.rs | 2 +- .../src/chatwidget/tests/status_and_layout.rs | 58 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index 8fbb2fe832b9..88c1a5c39dc3 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -4949,7 +4949,7 @@ impl ChatWidget { } self.pending_status_indicator_restore = match item.phase { // Models that don't support preambles only output AgentMessageItems on turn completion. - Some(MessagePhase::FinalAnswer) | None => false, + Some(MessagePhase::FinalAnswer) | None => !self.pending_steers.is_empty(), Some(MessagePhase::Commentary) => true, }; self.maybe_restore_status_indicator_after_stream_idle(); diff --git a/codex-rs/tui/src/chatwidget/tests/status_and_layout.rs b/codex-rs/tui/src/chatwidget/tests/status_and_layout.rs index d7aefbe4b4fa..f70000994257 100644 --- a/codex-rs/tui/src/chatwidget/tests/status_and_layout.rs +++ b/codex-rs/tui/src/chatwidget/tests/status_and_layout.rs @@ -957,6 +957,64 @@ async fn idle_commit_ticks_do_not_restore_status_without_commentary_completion() assert_eq!(chat.bottom_pane.status_indicator_visible(), false); } +#[tokio::test] +async fn final_answer_completion_restores_status_indicator_for_pending_steer() { + let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + + chat.on_task_started(); + assert_eq!(chat.bottom_pane.status_indicator_visible(), true); + + chat.on_agent_message_delta("Long output line 1\n".to_string()); + chat.on_commit_tick(); + drain_insert_history(&mut rx); + chat.on_agent_message_delta("Long output line 2\n".to_string()); + chat.on_commit_tick(); + drain_insert_history(&mut rx); + + assert_eq!(chat.bottom_pane.status_indicator_visible(), false); + assert_eq!(chat.bottom_pane.is_task_running(), true); + + chat.bottom_pane.set_composer_text( + "Please summarize the rest more briefly.".to_string(), + Vec::new(), + Vec::new(), + ); + chat.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); + + assert_eq!(chat.pending_steers.len(), 1); + let items = match next_submit_op(&mut op_rx) { + Op::UserTurn { items, .. } => items, + other => panic!("expected Op::UserTurn, got {other:?}"), + }; + assert_eq!( + items, + vec![UserInput::Text { + text: "Please summarize the rest more briefly.".to_string(), + text_elements: Vec::new(), + }] + ); + + complete_assistant_message( + &mut chat, + "msg-final", + "Long output line 1\nLong output line 2\n", + Some(MessagePhase::FinalAnswer), + ); + + assert_eq!(chat.bottom_pane.status_indicator_visible(), true); + assert_eq!(chat.bottom_pane.is_task_running(), true); + + complete_user_message( + &mut chat, + "user-steer", + "Please summarize the rest more briefly.", + ); + + assert!(chat.pending_steers.is_empty()); + assert_eq!(chat.bottom_pane.status_indicator_visible(), true); + assert_eq!(chat.bottom_pane.is_task_running(), true); +} + #[tokio::test] async fn commentary_completion_restores_status_indicator_before_exec_begin() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; From 8b031b66080d20706a8d1da64c030e53e17cb176 Mon Sep 17 00:00:00 2001 From: canvrno-oai Date: Tue, 28 Apr 2026 10:18:57 -0700 Subject: [PATCH 2/2] Fix new test --- codex-rs/tui/src/chatwidget/tests/status_and_layout.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/codex-rs/tui/src/chatwidget/tests/status_and_layout.rs b/codex-rs/tui/src/chatwidget/tests/status_and_layout.rs index f70000994257..158d466ab9c8 100644 --- a/codex-rs/tui/src/chatwidget/tests/status_and_layout.rs +++ b/codex-rs/tui/src/chatwidget/tests/status_and_layout.rs @@ -960,6 +960,7 @@ async fn idle_commit_ticks_do_not_restore_status_without_commentary_completion() #[tokio::test] async fn final_answer_completion_restores_status_indicator_for_pending_steer() { let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await; + chat.thread_id = Some(ThreadId::new()); chat.on_task_started(); assert_eq!(chat.bottom_pane.status_indicator_visible(), true);