mirror of
https://github.com/openai/codex.git
synced 2026-11-10 21:00:47 +00:00
Rename status surfaces thread id item
Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
+1
-1
@@ -13,7 +13,7 @@ expression: "render_lines(&view, 72)"
|
||||
[x] git-branch Current Git branch (omitted when unavaila…
|
||||
[ ] model-with-reasoning Current model name with reasoning level
|
||||
[ ] project-name Project name (omitted when unavailable)
|
||||
[ ] run-state Compact session run-state text (Ready, Wo…
|
||||
[ ] run-state Compact thread run-state text (Ready, Wor…
|
||||
[ ] context-remaining Percentage of context window remaining (o…
|
||||
[ ] context-used Percentage of context window used (omitte…
|
||||
|
||||
|
||||
+1
-1
@@ -10,7 +10,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] run-state Compact thread run-state text (Ready, Working, Thinking)
|
||||
[x] thread-title Current thread title (omitted when unavailable)
|
||||
[ ] app-name Codex app name
|
||||
[ ] current-dir Current working directory
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
//! - Git information (branch name)
|
||||
//! - Context usage (remaining %, used %, window size)
|
||||
//! - Usage limits (5-hour, weekly)
|
||||
//! - Session info (thread title, ID, tokens used)
|
||||
//! - Thread info (thread title, ID, tokens used)
|
||||
//! - Application version
|
||||
|
||||
use ratatui::buffer::Buffer;
|
||||
@@ -44,7 +44,7 @@ use crate::render::renderable::Renderable;
|
||||
/// 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 thread has started
|
||||
#[derive(EnumIter, EnumString, Display, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||
#[strum(serialize_all = "kebab_case")]
|
||||
pub(crate) enum StatusLineItem {
|
||||
@@ -94,7 +94,7 @@ pub(crate) enum StatusLineItem {
|
||||
/// Total context window size in tokens.
|
||||
ContextWindowSize,
|
||||
|
||||
/// Total tokens used in the current session.
|
||||
/// Total tokens used in the current thread.
|
||||
UsedTokens,
|
||||
|
||||
/// Total input tokens consumed.
|
||||
@@ -103,8 +103,9 @@ pub(crate) enum StatusLineItem {
|
||||
/// Total output tokens generated.
|
||||
TotalOutputTokens,
|
||||
|
||||
/// Full session UUID.
|
||||
SessionId,
|
||||
/// Full thread UUID.
|
||||
#[strum(to_string = "thread-id", serialize = "session-id")]
|
||||
ThreadId,
|
||||
|
||||
/// Whether Fast mode is currently active.
|
||||
FastMode,
|
||||
@@ -125,7 +126,7 @@ impl StatusLineItem {
|
||||
StatusLineItem::CurrentDir => "Current working directory",
|
||||
StatusLineItem::ProjectRoot => "Project name (omitted when unavailable)",
|
||||
StatusLineItem::GitBranch => "Current Git branch (omitted when unavailable)",
|
||||
StatusLineItem::Status => "Compact session run-state text (Ready, Working, Thinking)",
|
||||
StatusLineItem::Status => "Compact thread run-state text (Ready, Working, Thinking)",
|
||||
StatusLineItem::ContextRemaining => {
|
||||
"Percentage of context window remaining (omitted when unknown)"
|
||||
}
|
||||
@@ -142,12 +143,10 @@ impl StatusLineItem {
|
||||
StatusLineItem::ContextWindowSize => {
|
||||
"Total context window size in tokens (omitted when unknown)"
|
||||
}
|
||||
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::UsedTokens => "Total tokens used in thread (omitted when zero)",
|
||||
StatusLineItem::TotalInputTokens => "Total input tokens used in thread",
|
||||
StatusLineItem::TotalOutputTokens => "Total output tokens used in thread",
|
||||
StatusLineItem::ThreadId => "Current thread identifier (omitted until thread starts)",
|
||||
StatusLineItem::FastMode => "Whether Fast mode is currently active",
|
||||
StatusLineItem::ThreadTitle => "Current thread title (omitted when unavailable)",
|
||||
StatusLineItem::TaskProgress => {
|
||||
@@ -173,7 +172,7 @@ impl StatusLineItem {
|
||||
StatusLineItem::UsedTokens => StatusSurfacePreviewItem::UsedTokens,
|
||||
StatusLineItem::TotalInputTokens => StatusSurfacePreviewItem::TotalInputTokens,
|
||||
StatusLineItem::TotalOutputTokens => StatusSurfacePreviewItem::TotalOutputTokens,
|
||||
StatusLineItem::SessionId => StatusSurfacePreviewItem::SessionId,
|
||||
StatusLineItem::ThreadId => StatusSurfacePreviewItem::ThreadId,
|
||||
StatusLineItem::FastMode => StatusSurfacePreviewItem::FastMode,
|
||||
StatusLineItem::ThreadTitle => StatusSurfacePreviewItem::ThreadTitle,
|
||||
StatusLineItem::TaskProgress => StatusSurfacePreviewItem::TaskProgress,
|
||||
@@ -385,6 +384,19 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn thread_id_is_canonical_and_accepts_session_id_legacy_id() {
|
||||
assert_eq!(StatusLineItem::ThreadId.to_string(), "thread-id");
|
||||
assert_eq!(
|
||||
"thread-id".parse::<StatusLineItem>(),
|
||||
Ok(StatusLineItem::ThreadId)
|
||||
);
|
||||
assert_eq!(
|
||||
"session-id".parse::<StatusLineItem>(),
|
||||
Ok(StatusLineItem::ThreadId)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_status_line_items_accepts_title_only_variants() {
|
||||
let items = ["run-state", "task-progress"]
|
||||
|
||||
@@ -20,7 +20,7 @@ pub(crate) enum StatusSurfacePreviewItem {
|
||||
UsedTokens,
|
||||
TotalInputTokens,
|
||||
TotalOutputTokens,
|
||||
SessionId,
|
||||
ThreadId,
|
||||
FastMode,
|
||||
Model,
|
||||
ModelWithReasoning,
|
||||
@@ -46,7 +46,7 @@ impl StatusSurfacePreviewItem {
|
||||
StatusSurfacePreviewItem::UsedTokens => "0 used",
|
||||
StatusSurfacePreviewItem::TotalInputTokens => "0 in",
|
||||
StatusSurfacePreviewItem::TotalOutputTokens => "0 out",
|
||||
StatusSurfacePreviewItem::SessionId => "550e8400-e29b-41d4",
|
||||
StatusSurfacePreviewItem::ThreadId => "550e8400-e29b-41d4",
|
||||
StatusSurfacePreviewItem::FastMode => "Fast on",
|
||||
StatusSurfacePreviewItem::Model => "gpt-5.2-codex",
|
||||
StatusSurfacePreviewItem::ModelWithReasoning => "gpt-5.2-codex medium",
|
||||
@@ -72,7 +72,7 @@ impl StatusSurfacePreviewItem {
|
||||
Self::UsedTokens,
|
||||
Self::TotalInputTokens,
|
||||
Self::TotalOutputTokens,
|
||||
Self::SessionId,
|
||||
Self::ThreadId,
|
||||
Self::FastMode,
|
||||
Self::Model,
|
||||
Self::ModelWithReasoning,
|
||||
|
||||
@@ -65,14 +65,15 @@ pub(crate) enum TerminalTitleItem {
|
||||
WeeklyLimit,
|
||||
/// Codex application version.
|
||||
CodexVersion,
|
||||
/// Total tokens used in the current session.
|
||||
/// Total tokens used in the current thread.
|
||||
UsedTokens,
|
||||
/// Total input tokens consumed.
|
||||
TotalInputTokens,
|
||||
/// Total output tokens generated.
|
||||
TotalOutputTokens,
|
||||
/// Full session UUID.
|
||||
SessionId,
|
||||
/// Full thread UUID.
|
||||
#[strum(to_string = "thread-id", serialize = "session-id")]
|
||||
ThreadId,
|
||||
/// Whether Fast mode is currently active.
|
||||
FastMode,
|
||||
/// Current model name.
|
||||
@@ -93,9 +94,7 @@ impl TerminalTitleItem {
|
||||
TerminalTitleItem::Spinner => {
|
||||
"Spinner while working, action-required message while blocked."
|
||||
}
|
||||
TerminalTitleItem::Status => {
|
||||
"Compact session run-state text (Ready, Working, Thinking)"
|
||||
}
|
||||
TerminalTitleItem::Status => "Compact thread run-state text (Ready, Working, Thinking)",
|
||||
TerminalTitleItem::Thread => "Current thread title (omitted when unavailable)",
|
||||
TerminalTitleItem::GitBranch => "Current Git branch (omitted when unavailable)",
|
||||
TerminalTitleItem::ContextRemaining => {
|
||||
@@ -111,11 +110,11 @@ impl TerminalTitleItem {
|
||||
"Remaining usage on weekly usage limit (omitted when unavailable)"
|
||||
}
|
||||
TerminalTitleItem::CodexVersion => "Codex application version",
|
||||
TerminalTitleItem::UsedTokens => "Total tokens used in session (omitted when zero)",
|
||||
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)"
|
||||
TerminalTitleItem::UsedTokens => "Total tokens used in thread (omitted when zero)",
|
||||
TerminalTitleItem::TotalInputTokens => "Total input tokens used in thread",
|
||||
TerminalTitleItem::TotalOutputTokens => "Total output tokens used in thread",
|
||||
TerminalTitleItem::ThreadId => {
|
||||
"Current thread identifier (omitted until thread starts)"
|
||||
}
|
||||
TerminalTitleItem::FastMode => "Whether Fast mode is currently active",
|
||||
TerminalTitleItem::Model => "Current model name",
|
||||
@@ -145,7 +144,7 @@ impl TerminalTitleItem {
|
||||
TerminalTitleItem::TotalOutputTokens => {
|
||||
Some(StatusSurfacePreviewItem::TotalOutputTokens)
|
||||
}
|
||||
TerminalTitleItem::SessionId => Some(StatusSurfacePreviewItem::SessionId),
|
||||
TerminalTitleItem::ThreadId => Some(StatusSurfacePreviewItem::ThreadId),
|
||||
TerminalTitleItem::FastMode => Some(StatusSurfacePreviewItem::FastMode),
|
||||
TerminalTitleItem::Model => Some(StatusSurfacePreviewItem::Model),
|
||||
TerminalTitleItem::ModelWithReasoning => {
|
||||
@@ -479,6 +478,19 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn thread_id_is_canonical_and_accepts_session_id_legacy_id() {
|
||||
assert_eq!(TerminalTitleItem::ThreadId.to_string(), "thread-id");
|
||||
assert_eq!(
|
||||
"thread-id".parse::<TerminalTitleItem>(),
|
||||
Ok(TerminalTitleItem::ThreadId)
|
||||
);
|
||||
assert_eq!(
|
||||
"session-id".parse::<TerminalTitleItem>(),
|
||||
Ok(TerminalTitleItem::ThreadId)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn model_with_reasoning_has_distinct_id() {
|
||||
assert_eq!(
|
||||
@@ -510,7 +522,7 @@ mod tests {
|
||||
"used-tokens",
|
||||
"total-input-tokens",
|
||||
"total-output-tokens",
|
||||
"session-id",
|
||||
"thread-id",
|
||||
"fast-mode",
|
||||
]
|
||||
.into_iter(),
|
||||
@@ -533,7 +545,7 @@ mod tests {
|
||||
TerminalTitleItem::UsedTokens,
|
||||
TerminalTitleItem::TotalInputTokens,
|
||||
TerminalTitleItem::TotalOutputTokens,
|
||||
TerminalTitleItem::SessionId,
|
||||
TerminalTitleItem::ThreadId,
|
||||
TerminalTitleItem::FastMode,
|
||||
])
|
||||
);
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ expression: status_line_popup_snapshot(&mut chat)
|
||||
[ ] model Current model name
|
||||
[ ] model-with-reasoning Current model name with reasoning level
|
||||
[ ] current-dir Current working directory
|
||||
[ ] run-state Compact session run-state text (Ready, Working, Thinking)
|
||||
[ ] run-state Compact thread run-state text (Ready, Working, Thinking)
|
||||
[ ] context-remaining Percentage of context window remaining (omitted when unknown)
|
||||
|
||||
my-project · feat/awesome-feature · thread title
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ expression: status_line_popup_snapshot(&mut chat)
|
||||
[ ] model Current model name
|
||||
[ ] model-with-reasoning Current model name with reasoning level
|
||||
[ ] current-dir Current working directory
|
||||
[ ] run-state Compact session run-state text (Ready, Working, Thinking)
|
||||
[ ] run-state Compact thread run-state text (Ready, Working, Thinking)
|
||||
[ ] context-remaining Percentage of context window remaining (omitted when unknown)
|
||||
|
||||
preview-live-root · feature/live-preview-branch · Live preview thread
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ expression: status_line_popup_snapshot(&mut chat)
|
||||
[ ] model Current model name
|
||||
[ ] model-with-reasoning Current model name with reasoning level
|
||||
[ ] current-dir Current working directory
|
||||
[ ] run-state Compact session run-state text (Ready, Working, Thinking)
|
||||
[ ] run-state Compact thread run-state text (Ready, Working, Thinking)
|
||||
[ ] context-remaining Percentage of context window remaining (omitted when unknown)
|
||||
|
||||
my-project · feature/mixed-preview · Mixed preview thread
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ expression: terminal_title_popup_snapshot(&mut chat)
|
||||
[ ] project-name Project name (falls back to current directory name)
|
||||
[ ] current-dir Current working directory
|
||||
[ ] activity Spinner while working, action-required message while blocked.
|
||||
[ ] run-state Compact session run-state text (Ready, Working, Thinking)
|
||||
[ ] run-state Compact thread run-state text (Ready, Working, Thinking)
|
||||
|
||||
thread title | feat/awesome-feature | Tasks 0/0
|
||||
Use ↑↓ to navigate, ←→ to move, space to select, enter to confirm, esc to cancel.
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ expression: terminal_title_popup_snapshot(&mut chat)
|
||||
[ ] app-name Codex app name
|
||||
[ ] current-dir Current working directory
|
||||
[ ] activity Spinner while working, action-required message while blocked.
|
||||
[ ] run-state Compact session run-state text (Ready, Working, Thinking)
|
||||
[ ] run-state Compact thread run-state text (Ready, Working, Thinking)
|
||||
|
||||
preview-live-root | Live preview thread | feature/live-preview-branch | Tasks 2/5
|
||||
Use ↑↓ to navigate, ←→ to move, space to select, enter to confirm, esc to cancel.
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ expression: terminal_title_popup_snapshot(&mut chat)
|
||||
[ ] app-name Codex app name
|
||||
[ ] current-dir Current working directory
|
||||
[ ] activity Spinner while working, action-required message while blocked.
|
||||
[ ] run-state Compact session run-state text (Ready, Working, Thinking)
|
||||
[ ] run-state Compact thread run-state text (Ready, Working, Thinking)
|
||||
[ ] git-branch Current Git branch (omitted when unavailable)
|
||||
|
||||
project | Mixed preview thread | Tasks 0/0
|
||||
|
||||
@@ -494,7 +494,7 @@ impl ChatWidget {
|
||||
/// Resolves a display string for one configured status-line item.
|
||||
///
|
||||
/// Returning `None` means "omit this item for now", not "configuration error". Callers rely on
|
||||
/// this to keep partially available status lines readable while waiting for session, token, or
|
||||
/// this to keep partially available status lines readable while waiting for thread, token, or
|
||||
/// git metadata.
|
||||
pub(super) fn status_line_value_for_item(&mut self, item: &StatusLineItem) -> Option<String> {
|
||||
match item {
|
||||
@@ -558,7 +558,7 @@ impl ChatWidget {
|
||||
"{} out",
|
||||
format_tokens_compact(self.status_line_total_usage().output_tokens)
|
||||
)),
|
||||
StatusLineItem::SessionId => self.thread_id.map(|id| id.to_string()),
|
||||
StatusLineItem::ThreadId => self.thread_id.map(|id| id.to_string()),
|
||||
StatusLineItem::FastMode => Some(
|
||||
if matches!(self.current_service_tier(), Some(ServiceTier::Fast)) {
|
||||
"Fast on".to_string()
|
||||
@@ -596,7 +596,7 @@ impl ChatWidget {
|
||||
StatusSurfacePreviewItem::UsedTokens => StatusLineItem::UsedTokens,
|
||||
StatusSurfacePreviewItem::TotalInputTokens => StatusLineItem::TotalInputTokens,
|
||||
StatusSurfacePreviewItem::TotalOutputTokens => StatusLineItem::TotalOutputTokens,
|
||||
StatusSurfacePreviewItem::SessionId => StatusLineItem::SessionId,
|
||||
StatusSurfacePreviewItem::ThreadId => StatusLineItem::ThreadId,
|
||||
StatusSurfacePreviewItem::FastMode => StatusLineItem::FastMode,
|
||||
StatusSurfacePreviewItem::Model => StatusLineItem::ModelName,
|
||||
StatusSurfacePreviewItem::ModelWithReasoning => StatusLineItem::ModelWithReasoning,
|
||||
@@ -659,8 +659,8 @@ impl ChatWidget {
|
||||
TerminalTitleItem::TotalOutputTokens => self
|
||||
.status_line_value_for_item(&StatusLineItem::TotalOutputTokens)
|
||||
.map(|value| Self::truncate_terminal_title_part(value, /*max_chars*/ 32)),
|
||||
TerminalTitleItem::SessionId => self
|
||||
.status_line_value_for_item(&StatusLineItem::SessionId)
|
||||
TerminalTitleItem::ThreadId => self
|
||||
.status_line_value_for_item(&StatusLineItem::ThreadId)
|
||||
.map(|value| Self::truncate_terminal_title_part(value, /*max_chars*/ 32)),
|
||||
TerminalTitleItem::FastMode => self
|
||||
.status_line_value_for_item(&StatusLineItem::FastMode)
|
||||
|
||||
@@ -1376,6 +1376,25 @@ async fn status_line_legacy_context_usage_renders_context_used_percent() {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn status_line_thread_id_renders_and_accepts_legacy_session_id() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
let thread_id = ThreadId::new();
|
||||
chat.thread_id = Some(thread_id);
|
||||
|
||||
chat.config.tui_status_line = Some(vec!["thread-id".to_string()]);
|
||||
chat.refresh_status_line();
|
||||
assert_eq!(status_line_text(&chat), Some(thread_id.to_string()));
|
||||
|
||||
chat.config.tui_status_line = Some(vec!["session-id".to_string()]);
|
||||
chat.refresh_status_line();
|
||||
assert_eq!(status_line_text(&chat), Some(thread_id.to_string()));
|
||||
assert!(
|
||||
drain_insert_history(&mut rx).is_empty(),
|
||||
"thread-id and legacy session-id should remain valid status line items"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn status_line_branch_state_resets_when_git_branch_disabled() {
|
||||
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
|
||||
@@ -80,6 +80,23 @@ async fn terminal_title_action_required_respects_spinner_setting() {
|
||||
assert!(!chat.should_animate_terminal_title_action_required());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn terminal_title_thread_id_renders_and_accepts_legacy_session_id() {
|
||||
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
let thread_id = ThreadId::new();
|
||||
let expected_title =
|
||||
ChatWidget::truncate_terminal_title_part(thread_id.to_string(), /*max_chars*/ 32);
|
||||
chat.thread_id = Some(thread_id);
|
||||
|
||||
chat.config.tui_terminal_title = Some(vec!["thread-id".to_string()]);
|
||||
chat.refresh_terminal_title();
|
||||
assert_eq!(chat.last_terminal_title, Some(expected_title.clone()));
|
||||
|
||||
chat.config.tui_terminal_title = Some(vec!["session-id".to_string()]);
|
||||
chat.refresh_terminal_title();
|
||||
assert_eq!(chat.last_terminal_title, Some(expected_title));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn terminal_title_action_required_blinks_when_animations_are_enabled() {
|
||||
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
|
||||
Reference in New Issue
Block a user