Skip to content

Commit 24be9ac

Browse files
authored
Restore TUI working status after steer message is set (#19939)
Fix for #19925 Restore the `Working` indicator after a streamed final answer finishes when a user steer message is sent. Add regression coverage for long output plus a mid-stream steer: `cargo test -p codex-tui final_answer_completion_restores_status_indicator_for_pending_steer` Duplication/testing steps: 1. Start a new thread and ask for a long response. 2. While the response is streaming, submit a steer message. 3. When the first response finishes, observe whether `Working...` is shown while waiting for the steer message response.
1 parent c9f7c88 commit 24be9ac

2 files changed

Lines changed: 60 additions & 1 deletion

File tree

codex-rs/tui/src/chatwidget.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4974,7 +4974,7 @@ impl ChatWidget {
49744974
}
49754975
self.pending_status_indicator_restore = match item.phase {
49764976
// Models that don't support preambles only output AgentMessageItems on turn completion.
4977-
Some(MessagePhase::FinalAnswer) | None => false,
4977+
Some(MessagePhase::FinalAnswer) | None => !self.pending_steers.is_empty(),
49784978
Some(MessagePhase::Commentary) => true,
49794979
};
49804980
self.maybe_restore_status_indicator_after_stream_idle();

codex-rs/tui/src/chatwidget/tests/status_and_layout.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,65 @@ async fn idle_commit_ticks_do_not_restore_status_without_commentary_completion()
947947
assert_eq!(chat.bottom_pane.status_indicator_visible(), false);
948948
}
949949

950+
#[tokio::test]
951+
async fn final_answer_completion_restores_status_indicator_for_pending_steer() {
952+
let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
953+
chat.thread_id = Some(ThreadId::new());
954+
955+
chat.on_task_started();
956+
assert_eq!(chat.bottom_pane.status_indicator_visible(), true);
957+
958+
chat.on_agent_message_delta("Long output line 1\n".to_string());
959+
chat.on_commit_tick();
960+
drain_insert_history(&mut rx);
961+
chat.on_agent_message_delta("Long output line 2\n".to_string());
962+
chat.on_commit_tick();
963+
drain_insert_history(&mut rx);
964+
965+
assert_eq!(chat.bottom_pane.status_indicator_visible(), false);
966+
assert_eq!(chat.bottom_pane.is_task_running(), true);
967+
968+
chat.bottom_pane.set_composer_text(
969+
"Please summarize the rest more briefly.".to_string(),
970+
Vec::new(),
971+
Vec::new(),
972+
);
973+
chat.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE));
974+
975+
assert_eq!(chat.pending_steers.len(), 1);
976+
let items = match next_submit_op(&mut op_rx) {
977+
Op::UserTurn { items, .. } => items,
978+
other => panic!("expected Op::UserTurn, got {other:?}"),
979+
};
980+
assert_eq!(
981+
items,
982+
vec![UserInput::Text {
983+
text: "Please summarize the rest more briefly.".to_string(),
984+
text_elements: Vec::new(),
985+
}]
986+
);
987+
988+
complete_assistant_message(
989+
&mut chat,
990+
"msg-final",
991+
"Long output line 1\nLong output line 2\n",
992+
Some(MessagePhase::FinalAnswer),
993+
);
994+
995+
assert_eq!(chat.bottom_pane.status_indicator_visible(), true);
996+
assert_eq!(chat.bottom_pane.is_task_running(), true);
997+
998+
complete_user_message(
999+
&mut chat,
1000+
"user-steer",
1001+
"Please summarize the rest more briefly.",
1002+
);
1003+
1004+
assert!(chat.pending_steers.is_empty());
1005+
assert_eq!(chat.bottom_pane.status_indicator_visible(), true);
1006+
assert_eq!(chat.bottom_pane.is_task_running(), true);
1007+
}
1008+
9501009
#[tokio::test]
9511010
async fn commentary_completion_restores_status_indicator_before_exec_begin() {
9521011
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;

0 commit comments

Comments
 (0)