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
34 changes: 33 additions & 1 deletion codex-rs/tui/src/bottom_pane/status_line_setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
//! - Git information (branch name)
//! - Context usage (meter, window size)
//! - Usage limits (5-hour, weekly)
//! - Session info (ID, tokens used)
//! - Session info (thread title, ID, tokens used)
//! - Application version

use ratatui::buffer::Buffer;
Expand Down Expand Up @@ -98,6 +98,9 @@ pub(crate) enum StatusLineItem {

/// Whether Fast mode is currently active.
FastMode,

/// Current thread title (if set by user).
ThreadTitle,
}

impl StatusLineItem {
Expand Down Expand Up @@ -129,6 +132,7 @@ impl StatusLineItem {
"Current session identifier (omitted until session starts)"
}
StatusLineItem::FastMode => "Whether Fast mode is currently active",
StatusLineItem::ThreadTitle => "Current thread title (omitted unless changed by user)",
}
}
}
Expand All @@ -149,6 +153,7 @@ const SELECTABLE_STATUS_LINE_ITEMS: &[StatusLineItem] = &[
StatusLineItem::TotalOutputTokens,
StatusLineItem::SessionId,
StatusLineItem::FastMode,
StatusLineItem::ThreadTitle,
];

/// Runtime values used to preview the current status-line selection.
Expand Down Expand Up @@ -380,6 +385,33 @@ mod tests {
);
}

#[test]
fn preview_includes_thread_title() {
let preview_data = StatusLinePreviewData::from_iter([
(StatusLineItem::ModelName, "gpt-5".to_string()),
(StatusLineItem::ThreadTitle, "Roadmap cleanup".to_string()),
]);
let items = vec![
MultiSelectItem {
id: StatusLineItem::ModelName.to_string(),
name: String::new(),
description: None,
enabled: true,
},
MultiSelectItem {
id: StatusLineItem::ThreadTitle.to_string(),
name: String::new(),
description: None,
enabled: true,
},
];

assert_eq!(
preview_data.line_for_items(&items),
Some(Line::from("gpt-5 · Roadmap cleanup"))
);
}

#[test]
fn setup_view_snapshot_uses_runtime_preview_values() {
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
Expand Down
1 change: 1 addition & 0 deletions codex-rs/tui/src/chatwidget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2151,6 +2151,7 @@ impl ChatWidget {
}
self.thread_name = event.thread_name;
self.refresh_terminal_title();
self.refresh_status_surfaces();
self.request_redraw();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
source: tui/src/chatwidget/tests.rs
expression: terminal.backend()
---
" "
" "
"› Ask Codex to do anything "
" "
" gpt-5.3-codex high · Roadmap cleanup "
4 changes: 4 additions & 0 deletions codex-rs/tui/src/chatwidget/status_surfaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,10 @@ impl ChatWidget {
"Fast off".to_string()
},
),
StatusLineItem::ThreadTitle => self.thread_name.as_ref().and_then(|name| {
let trimmed = name.trim();
(!trimmed.is_empty()).then(|| trimmed.to_string())
}),
}
}

Expand Down
36 changes: 36 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 @@ -1198,6 +1198,42 @@ async fn status_line_model_with_reasoning_plan_mode_footer_snapshot() {
);
}

#[tokio::test]
async fn renamed_thread_footer_title_snapshot() {
use ratatui::Terminal;
use ratatui::backend::TestBackend;

let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.3-codex")).await;
chat.show_welcome_banner = false;
chat.config.tui_status_line = Some(vec![
"model-with-reasoning".to_string(),
"thread-title".to_string(),
]);
chat.set_reasoning_effort(Some(ReasoningEffortConfig::High));
chat.refresh_status_line();

let thread_id = ThreadId::new();
chat.thread_id = Some(thread_id);
chat.handle_codex_event(Event {
id: "rename".to_string(),
msg: EventMsg::ThreadNameUpdated(codex_protocol::protocol::ThreadNameUpdatedEvent {
thread_id,
thread_name: Some("Roadmap cleanup".to_string()),
}),
});

let width = 80;
let height = chat.desired_height(width);
let mut terminal = Terminal::new(TestBackend::new(width, height)).expect("create terminal");
terminal
.draw(|f| chat.render(f.area(), f.buffer_mut()))
.expect("draw renamed-thread footer");
assert_chatwidget_snapshot!(
"renamed_thread_footer_title",
normalized_backend_snapshot(terminal.backend())
);
}

#[tokio::test]
async fn status_line_model_with_reasoning_fast_footer_snapshot() {
use ratatui::Terminal;
Expand Down
Loading