chore: thread tui (#21767)

This commit is contained in:
jif-oai
2026-05-08 17:53:23 +02:00
committed by GitHub
Unverified
parent 607b0dd1f0
commit 5b87bd2845
11 changed files with 49 additions and 32 deletions
@@ -11,7 +11,7 @@ expression: "render_lines(&view, 84)"
[x] project-name Project name (falls back to current directory name)
[x] activity Spinner while working, action-required message while blo…
[x] run-state Compact session run-state text (Ready, Working, Thinking)
[x] thread-title Current thread title (omitted when unavailable)
[x] thread-title Current thread title, or thread identifier when unnamed
[ ] app-name Codex app name
[ ] current-dir Current working directory
[ ] git-branch Current Git branch (omitted when unavailable)
@@ -16,7 +16,7 @@
//! - Approval mode
//! - Context usage (remaining %, used %, window size)
//! - Usage limits (5-hour, weekly)
//! - Session info (thread title, ID, tokens used)
//! - Session info (thread title, thread ID, tokens used)
//! - Application version
use ratatui::buffer::Buffer;
@@ -48,7 +48,7 @@ const STATUS_LINE_USE_THEME_COLORS_ITEM_ID: &str = "status-line-use-theme-colors
/// Some items are conditionally displayed based on availability:
/// - Git-related items only show when in a git repository
/// - Context/limit items only show when data is available from the API
/// - Session ID only shows after a session has started
/// - Thread ID only shows after a session has started
#[derive(EnumIter, EnumString, Display, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
#[strum(serialize_all = "kebab_case")]
pub(crate) enum StatusLineItem {
@@ -120,7 +120,8 @@ pub(crate) enum StatusLineItem {
/// Total output tokens generated.
TotalOutputTokens,
/// Full session UUID.
/// Full thread UUID.
#[strum(to_string = "thread-id", serialize = "session-id")]
SessionId,
/// Whether Fast mode is currently active.
@@ -173,12 +174,12 @@ impl StatusLineItem {
StatusLineItem::UsedTokens => "Total tokens used in session (omitted when zero)",
StatusLineItem::TotalInputTokens => "Total input tokens used in session",
StatusLineItem::TotalOutputTokens => "Total output tokens used in session",
StatusLineItem::SessionId => {
"Current session identifier (omitted until session starts)"
}
StatusLineItem::SessionId => "Current thread identifier (omitted until thread starts)",
StatusLineItem::FastMode => "Whether Fast mode is currently active",
StatusLineItem::RawOutput => "Whether raw scrollback mode is active",
StatusLineItem::ThreadTitle => "Current thread title (omitted when unavailable)",
StatusLineItem::ThreadTitle => {
"Current thread title, or thread identifier when unnamed"
}
StatusLineItem::TaskProgress => {
"Latest task progress from update_plan (omitted until available)"
}
+4 -3
View File
@@ -71,7 +71,8 @@ pub(crate) enum TerminalTitleItem {
TotalInputTokens,
/// Total output tokens generated.
TotalOutputTokens,
/// Full session UUID.
/// Full thread UUID.
#[strum(to_string = "thread-id", serialize = "session-id")]
SessionId,
/// Whether Fast mode is currently active.
FastMode,
@@ -96,7 +97,7 @@ impl TerminalTitleItem {
TerminalTitleItem::Status => {
"Compact session run-state text (Ready, Working, Thinking)"
}
TerminalTitleItem::Thread => "Current thread title (omitted when unavailable)",
TerminalTitleItem::Thread => "Current thread title, or thread identifier when unnamed",
TerminalTitleItem::GitBranch => "Current Git branch (omitted when unavailable)",
TerminalTitleItem::ContextRemaining => {
"Percentage of context window remaining (omitted when unknown)"
@@ -115,7 +116,7 @@ impl TerminalTitleItem {
TerminalTitleItem::TotalInputTokens => "Total input tokens used in session",
TerminalTitleItem::TotalOutputTokens => "Total output tokens used in session",
TerminalTitleItem::SessionId => {
"Current session identifier (omitted until session starts)"
"Current thread identifier (omitted until thread starts)"
}
TerminalTitleItem::FastMode => "Whether Fast mode is currently active",
TerminalTitleItem::Model => "Current model name",
@@ -11,7 +11,7 @@ expression: status_line_popup_snapshot(&mut chat)
───────────────────────
[x] project-name Project name (omitted when unavailable)
[x] git-branch Current Git branch (omitted when unavailable)
[x] thread-title Current thread title (omitted when unavailable)
[x] thread-title Current thread title, or thread identifier when unnamed
[ ] model Current model name
[ ] model-with-reasoning Current model name with reasoning level
[ ] current-dir Current working directory
@@ -11,7 +11,7 @@ expression: status_line_popup_snapshot(&mut chat)
───────────────────────
[x] project-name Project name (omitted when unavailable)
[x] git-branch Current Git branch (omitted when unavailable)
[x] thread-title Current thread title (omitted when unavailable)
[x] thread-title Current thread title, or thread identifier when unnamed
[ ] model Current model name
[ ] model-with-reasoning Current model name with reasoning level
[ ] current-dir Current working directory
@@ -11,7 +11,7 @@ expression: status_line_popup_snapshot(&mut chat)
───────────────────────
[x] project-name Project name (omitted when unavailable)
[x] git-branch Current Git branch (omitted when unavailable)
[x] thread-title Current thread title (omitted when unavailable)
[x] thread-title Current thread title, or thread identifier when unnamed
[ ] model Current model name
[ ] model-with-reasoning Current model name with reasoning level
[ ] current-dir Current working directory
@@ -7,7 +7,7 @@ expression: terminal_title_popup_snapshot(&mut chat)
Type to search
>
[x] thread-title Current thread title (omitted when unavailable)
[x] thread-title Current thread title, or thread identifier when unnamed
[x] git-branch Current Git branch (omitted when unavailable)
[x] task-progress Latest task progress from update_plan (omitted until available)
[ ] app-name Codex app name
@@ -8,7 +8,7 @@ expression: terminal_title_popup_snapshot(&mut chat)
Type to search
>
[x] project-name Project name (falls back to current directory name)
[x] thread-title Current thread title (omitted when unavailable)
[x] thread-title Current thread title, or thread identifier when unnamed
[x] git-branch Current Git branch (omitted when unavailable)
[x] task-progress Latest task progress from update_plan (omitted until available)
[ ] app-name Codex app name
@@ -8,7 +8,7 @@ expression: terminal_title_popup_snapshot(&mut chat)
Type to search
>
[x] project-name Project name (falls back to current directory name)
[x] thread-title Current thread title (omitted when unavailable)
[x] thread-title Current thread title, or thread identifier when unnamed
[x] task-progress Latest task progress from update_plan (omitted until available)
[ ] app-name Codex app name
[ ] current-dir Current working directory
+14 -15
View File
@@ -655,10 +655,17 @@ impl ChatWidget {
},
),
StatusLineItem::RawOutput => self.raw_output_mode().then(|| "raw output".to_string()),
StatusLineItem::ThreadTitle => self.thread_name.as_ref().and_then(|name| {
let trimmed = name.trim();
(!trimmed.is_empty()).then(|| trimmed.to_string())
}),
StatusLineItem::ThreadTitle => self.thread_name.as_ref().map_or_else(
|| self.thread_id.map(|id| id.to_string()),
|name| {
let trimmed = name.trim();
if trimmed.is_empty() {
self.thread_id.map(|id| id.to_string())
} else {
Some(trimmed.to_string())
}
},
),
StatusLineItem::TaskProgress => self.terminal_title_task_progress(),
}
}
@@ -722,17 +729,9 @@ impl ChatWidget {
)),
TerminalTitleItem::Spinner => self.terminal_title_spinner_text_at(now),
TerminalTitleItem::Status => Some(self.run_state_status_text()),
TerminalTitleItem::Thread => self.thread_name.as_ref().and_then(|name| {
let trimmed = name.trim();
if trimmed.is_empty() {
None
} else {
Some(Self::truncate_terminal_title_part(
trimmed.to_string(),
/*max_chars*/ 48,
))
}
}),
TerminalTitleItem::Thread => self
.status_line_value_for_item(StatusLineItem::ThreadTitle)
.map(|value| Self::truncate_terminal_title_part(value, /*max_chars*/ 48)),
TerminalTitleItem::GitBranch => self.status_line_branch.as_ref().map(|branch| {
Self::truncate_terminal_title_part(branch.clone(), /*max_chars*/ 32)
}),
@@ -125,6 +125,22 @@ async fn status_surface_preview_lines_hardcoded_only_snapshot() {
assert_chatwidget_snapshot!("status_surface_previews_hardcoded_only", snapshot);
}
#[tokio::test]
async fn thread_title_falls_back_to_thread_id_when_unnamed() {
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
let thread_id = ThreadId::new();
chat.thread_id = Some(thread_id);
assert_eq!(
status_preview_line(&mut chat, &[StatusLineItem::ThreadTitle]),
thread_id.to_string()
);
assert_eq!(
title_preview_line(&mut chat, &[TerminalTitleItem::Thread]),
thread_id.to_string()
);
}
#[tokio::test]
async fn status_line_setup_popup_hardcoded_only_snapshot() {
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;