Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion codex-rs/tui/src/chatwidget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4973,7 +4973,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();
Expand Down
59 changes: 59 additions & 0 deletions codex-rs/tui/src/chatwidget/tests/status_and_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -947,6 +947,65 @@ 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.thread_id = Some(ThreadId::new());

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;
Expand Down
Loading