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
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
source: tui/src/chatwidget/tests/exec_flow.rs
expression: normalized_backend_snapshot(terminal.backend())
---
" "
"• Working (0s • esc to interrupt) "
" "
" "
"› Ask Codex to do anything "
" "
" gpt-5.6-sol default · /tmp/project "
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
source: tui/src/chatwidget/tests/status_and_layout.rs
expression: normalize_snapshot_paths(terminal.backend().vt100().screen().contents())
---

› count to 1


• 1


› Ask Codex to do anything

gpt-5 default · /tmp/project
5 changes: 5 additions & 0 deletions codex-rs/tui/src/chatwidget/streaming.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ impl ChatWidget {
};
self.clear_active_stream_tail();
let (cell, source) = controller.finalize();
// Match newline-committed streaming behavior: once assistant output is ready to be
// committed into history, hide the inline status row so transcript content replaces it.
if cell.is_some() {
self.bottom_pane.hide_status_indicator();
}
let deferred_history_cell =
if scrollback_reflow == crate::app_event::ConsolidationScrollbackReflow::Required {
cell
Expand Down
24 changes: 24 additions & 0 deletions codex-rs/tui/src/chatwidget/tests/exec_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,30 @@ async fn view_image_tool_call_preserves_foreign_path() {
assert_chatwidget_snapshot!("foreign_image_attachment_history_snapshot", combined);
}

#[tokio::test]
async fn image_generation_begin_restores_working_status_after_single_line_preamble() {
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;

chat.on_task_started();
chat.on_agent_message_delta("Generating an image.".to_string());
chat.on_image_generation_begin();

assert!(chat.bottom_pane.is_task_running());
assert!(chat.bottom_pane.status_indicator_visible());

let width: u16 = 80;
let height = chat.desired_height(width);
let mut terminal = ratatui::Terminal::new(ratatui::backend::TestBackend::new(width, height))
.expect("create terminal");
terminal
.draw(|frame| chat.render(frame.area(), frame.buffer_mut()))
.expect("draw image generation status");
assert_chatwidget_snapshot!(
"image_generation_begin_restores_working_status",
normalized_backend_snapshot(terminal.backend())
);
}

#[tokio::test]
async fn image_generation_call_adds_history_cell() {
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
Expand Down
39 changes: 39 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 @@ -1525,6 +1525,45 @@ async fn streaming_final_answer_keeps_task_running_state() {
assert!(!chat.bottom_pane.quit_shortcut_hint_visible());
}

#[tokio::test]
async fn single_line_final_answer_hides_working_status_snapshot() {
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(Some("gpt-5")).await;
chat.thread_id = Some(ThreadId::new());

complete_user_message(&mut chat, "user-1", "count to 1");
chat.on_task_started();
complete_assistant_message(
&mut chat,
"msg-final-single-line",
"1",
Some(MessagePhase::FinalAnswer),
);

assert!(chat.bottom_pane.is_task_running());
assert!(!chat.bottom_pane.status_indicator_visible());

let width: u16 = 40;
let vt_height: u16 = 10;
let ui_height = chat.desired_height(width);
let viewport = Rect::new(0, vt_height - ui_height - 1, width, ui_height);
let backend = VT100Backend::new(width, vt_height);
let mut terminal = crate::custom_terminal::Terminal::with_options(backend).expect("terminal");
terminal.set_viewport_area(viewport);

for lines in drain_insert_history(&mut rx) {
crate::insert_history::insert_history_lines(&mut terminal, lines)
.expect("insert history lines");
}

terminal
.draw(|frame| chat.render(frame.area(), frame.buffer_mut()))
.expect("draw final answer");
assert_chatwidget_snapshot!(
"single_line_final_answer_hides_working_status",
normalize_snapshot_paths(terminal.backend().vt100().screen().contents())
);
}

#[tokio::test]
async fn ctrl_c_interrupt_pauses_active_goal_turn() {
let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
Expand Down
3 changes: 3 additions & 0 deletions codex-rs/tui/src/chatwidget/tool_lifecycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ impl ChatWidget {
pub(super) fn on_image_generation_begin(&mut self) {
self.record_visible_turn_activity();
self.flush_answer_stream_with_separator();
if self.bottom_pane.is_task_running() {
self.bottom_pane.ensure_status_indicator();
}
}

pub(super) fn on_image_generation_end(
Expand Down
Loading