diff --git a/codex-rs/tui/src/app/event_dispatch.rs b/codex-rs/tui/src/app/event_dispatch.rs index 8d340f0cef..6cf65cba7f 100644 --- a/codex-rs/tui/src/app/event_dispatch.rs +++ b/codex-rs/tui/src/app/event_dispatch.rs @@ -739,7 +739,7 @@ impl App { .finish_token_activity_refresh(request_id, result) { // Commit synchronously so an already queued /clear cannot overtake this card. - // Do not route through ChatWidget::add_to_history: /tokens may complete during + // Do not route through ChatWidget::add_to_history: /usage may complete during // active work, and flushing an in-progress tool cell would corrupt its lifecycle. // If an answer stream is active, keep the settled card transient until its // provisional transcript cells have been consolidated. diff --git a/codex-rs/tui/src/app/history_ui.rs b/codex-rs/tui/src/app/history_ui.rs index 128898876b..ce9a607cea 100644 --- a/codex-rs/tui/src/app/history_ui.rs +++ b/codex-rs/tui/src/app/history_ui.rs @@ -28,7 +28,7 @@ impl App { .history_wrap_width(tui.terminal.last_known_screen_size.width), ); } - // A committed cell can unblock a settled /tokens card that was waiting + // A committed cell can unblock a settled /usage card that was waiting // behind a transient active cell or a provisional stream tail. self.chat_widget .request_completed_token_activity_output_insertion(); diff --git a/codex-rs/tui/src/app_event.rs b/codex-rs/tui/src/app_event.rs index 3d9e9b711f..71d66e99ac 100644 --- a/codex-rs/tui/src/app_event.rs +++ b/codex-rs/tui/src/app_event.rs @@ -293,7 +293,7 @@ pub(crate) enum AppEvent { result: Result, String>, }, - /// Fetch account-wide token activity for a `/tokens` history card. + /// Fetch account-wide token activity for a `/usage` history card. RefreshTokenActivity { request_id: u64, }, diff --git a/codex-rs/tui/src/bottom_pane/slash_commands.rs b/codex-rs/tui/src/bottom_pane/slash_commands.rs index a4aba21c79..02837f3bfe 100644 --- a/codex-rs/tui/src/bottom_pane/slash_commands.rs +++ b/codex-rs/tui/src/bottom_pane/slash_commands.rs @@ -76,7 +76,7 @@ pub(crate) fn builtins_for_input(flags: BuiltinCommandFlags) -> Vec<(&'static st .filter(|(_, cmd)| flags.collaboration_modes_enabled || *cmd != SlashCommand::Plan) .filter(|(_, cmd)| flags.connectors_enabled || *cmd != SlashCommand::Apps) .filter(|(_, cmd)| flags.plugins_command_enabled || *cmd != SlashCommand::Plugins) - .filter(|(_, cmd)| flags.token_activity_command_enabled || *cmd != SlashCommand::Tokens) + .filter(|(_, cmd)| flags.token_activity_command_enabled || *cmd != SlashCommand::Usage) .filter(|(_, cmd)| flags.goal_command_enabled || *cmd != SlashCommand::Goal) .filter(|(_, cmd)| flags.personality_command_enabled || *cmd != SlashCommand::Personality) .filter(|(_, cmd)| flags.realtime_conversation_enabled || *cmd != SlashCommand::Realtime) @@ -262,24 +262,24 @@ mod tests { } #[test] - fn tokens_command_is_hidden_from_input_when_account_token_activity_is_disabled() { + fn usage_command_is_hidden_from_input_when_account_token_activity_is_disabled() { let mut flags = all_enabled_flags(); flags.token_activity_command_enabled = false; assert_eq!( builtins_for_input(flags) .into_iter() - .find(|(_, command)| *command == SlashCommand::Tokens), + .find(|(_, command)| *command == SlashCommand::Usage), None ); } #[test] - fn tokens_command_exact_lookup_still_resolves_when_account_token_activity_is_disabled() { + fn usage_command_exact_lookup_still_resolves_when_account_token_activity_is_disabled() { let mut flags = all_enabled_flags(); flags.token_activity_command_enabled = false; assert_eq!( - find_builtin_command("tokens", flags), - Some(SlashCommand::Tokens) + find_builtin_command("usage", flags), + Some(SlashCommand::Usage) ); } @@ -324,7 +324,7 @@ mod tests { SlashCommand::Diff, SlashCommand::Mention, SlashCommand::Status, - SlashCommand::Tokens, + SlashCommand::Usage, ] ); } diff --git a/codex-rs/tui/src/chatwidget/slash_dispatch.rs b/codex-rs/tui/src/chatwidget/slash_dispatch.rs index 356cee103e..48100eda70 100644 --- a/codex-rs/tui/src/chatwidget/slash_dispatch.rs +++ b/codex-rs/tui/src/chatwidget/slash_dispatch.rs @@ -35,7 +35,7 @@ const SIDE_SLASH_COMMAND_UNAVAILABLE_HINT: &str = const GOAL_USAGE: &str = "Usage: /goal "; const GOAL_USAGE_HINT: &str = "Example: /goal improve benchmark coverage"; const RAW_USAGE: &str = "Usage: /raw [on|off]"; -const TOKENS_CHATGPT_LOGIN_REQUIRED: &str = "Sign in with ChatGPT to use /tokens."; +const USAGE_CHATGPT_LOGIN_REQUIRED: &str = "Sign in with ChatGPT to use /usage."; impl ChatWidget { /// Dispatch a bare slash command and record its staged local-history entry. @@ -415,7 +415,7 @@ impl ChatWidget { ); } } - SlashCommand::Tokens => { + SlashCommand::Usage => { if self.ensure_token_activity_command_available() { self.add_token_activity_output(tokens::TokenActivityView::Daily); } @@ -620,12 +620,12 @@ impl ChatWidget { } = prepared; let trimmed = args.trim(); match cmd { - SlashCommand::Tokens => { + SlashCommand::Usage => { if self.ensure_token_activity_command_available() { match tokens::TokenActivityView::parse(trimmed) { Some(view) => self.add_token_activity_output(view), None => self.add_error_message( - "Usage: /tokens [daily|weekly|cumulative]".to_string(), + "Usage: /usage [daily|weekly|cumulative]".to_string(), ), } } @@ -975,7 +975,7 @@ impl ChatWidget { if self.has_chatgpt_account { return true; } - self.add_error_message(TOKENS_CHATGPT_LOGIN_REQUIRED.to_string()); + self.add_error_message(USAGE_CHATGPT_LOGIN_REQUIRED.to_string()); false } @@ -986,7 +986,7 @@ impl ChatWidget { match cmd { SlashCommand::Ide | SlashCommand::Status - | SlashCommand::Tokens + | SlashCommand::Usage | SlashCommand::DebugConfig | SlashCommand::Ps | SlashCommand::Stop diff --git a/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__pending_token_activity_refresh_renders_above_composer_snapshot.snap b/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__pending_token_activity_refresh_renders_above_composer_snapshot.snap index 5bb1a44daa..964f801c93 100644 --- a/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__pending_token_activity_refresh_renders_above_composer_snapshot.snap +++ b/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__pending_token_activity_refresh_renders_above_composer_snapshot.snap @@ -3,7 +3,7 @@ source: tui/src/chatwidget/tests/slash_commands.rs expression: normalize_snapshot_paths(term.backend().vt100().screen().contents()) --- -/tokens daily +/usage daily Token activity Loading... diff --git a/codex-rs/tui/src/chatwidget/tests/slash_commands.rs b/codex-rs/tui/src/chatwidget/tests/slash_commands.rs index af069e5613..410dcc8bd0 100644 --- a/codex-rs/tui/src/chatwidget/tests/slash_commands.rs +++ b/codex-rs/tui/src/chatwidget/tests/slash_commands.rs @@ -1137,10 +1137,10 @@ async fn usage_error_slash_command_is_available_from_local_recall() { } #[tokio::test] -async fn signed_out_tokens_command_reports_chatgpt_login_requirement() { +async fn signed_out_usage_command_reports_chatgpt_login_requirement() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; - submit_composer_text(&mut chat, "/tokens"); + submit_composer_text(&mut chat, "/usage"); let cells = drain_insert_history(&mut rx); let rendered = cells @@ -1149,17 +1149,17 @@ async fn signed_out_tokens_command_reports_chatgpt_login_requirement() { .collect::>() .join("\n"); assert!( - rendered.contains("Sign in with ChatGPT to use /tokens."), + rendered.contains("Sign in with ChatGPT to use /usage."), "expected ChatGPT login requirement, got: {rendered:?}" ); - assert_eq!(recall_latest_after_clearing(&mut chat), "/tokens"); + assert_eq!(recall_latest_after_clearing(&mut chat), "/usage"); } #[tokio::test] -async fn signed_out_tokens_command_with_args_reports_chatgpt_login_requirement() { +async fn signed_out_usage_command_with_args_reports_chatgpt_login_requirement() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; - submit_composer_text(&mut chat, "/tokens weekly"); + submit_composer_text(&mut chat, "/usage weekly"); let cells = drain_insert_history(&mut rx); let rendered = cells @@ -1168,10 +1168,10 @@ async fn signed_out_tokens_command_with_args_reports_chatgpt_login_requirement() .collect::>() .join("\n"); assert!( - rendered.contains("Sign in with ChatGPT to use /tokens."), + rendered.contains("Sign in with ChatGPT to use /usage."), "expected ChatGPT login requirement, got: {rendered:?}" ); - assert_eq!(recall_latest_after_clearing(&mut chat), "/tokens weekly"); + assert_eq!(recall_latest_after_clearing(&mut chat), "/usage weekly"); } #[tokio::test] @@ -1179,7 +1179,7 @@ async fn clearing_pending_token_activity_refreshes_discards_late_result() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); - chat.dispatch_command(SlashCommand::Tokens); + chat.dispatch_command(SlashCommand::Usage); let request_id = match rx.try_recv() { Ok(AppEvent::RefreshTokenActivity { request_id }) => request_id, @@ -1188,12 +1188,12 @@ async fn clearing_pending_token_activity_refreshes_discards_late_result() { assert_eq!( chat.pending_token_activity_output() .map(|cell| lines_to_single_string(&cell.display_lines(u16::MAX))), - Some("/tokens daily\n\n Token activity\n Loading...\n".to_string()), + Some("/usage daily\n\n Token activity\n Loading...\n".to_string()), ); assert_eq!( chat.active_cell_transcript_lines(u16::MAX) .map(|lines| lines_to_single_string(&lines)), - Some("/tokens daily\n\n Token activity\n Loading...\n".to_string()), + Some("/usage daily\n\n Token activity\n Loading...\n".to_string()), ); chat.clear_pending_token_activity_refreshes(); @@ -1211,7 +1211,7 @@ async fn pending_token_activity_refresh_renders_above_composer_snapshot() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); - chat.dispatch_command(SlashCommand::Tokens); + chat.dispatch_command(SlashCommand::Usage); assert_matches!( rx.try_recv(), Ok(AppEvent::RefreshTokenActivity { .. }), @@ -1238,7 +1238,7 @@ async fn completed_token_activity_refresh_returns_one_history_cell() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); - chat.dispatch_command(SlashCommand::Tokens); + chat.dispatch_command(SlashCommand::Usage); let request_id = match rx.try_recv() { Ok(AppEvent::RefreshTokenActivity { request_id }) => request_id, @@ -1260,7 +1260,7 @@ async fn completed_token_activity_refresh_returns_one_history_cell() { assert!(chat.pending_token_activity_output().is_none()); assert_eq!( lines_to_single_string(&cell.display_lines(u16::MAX)), - "/tokens daily\n\n Token activity\n Token activity unavailable\n", + "/usage daily\n\n Token activity\n Token activity unavailable\n", ); } @@ -1269,7 +1269,7 @@ async fn completed_token_activity_refresh_waits_for_active_stream() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); - chat.dispatch_command(SlashCommand::Tokens); + chat.dispatch_command(SlashCommand::Usage); let request_id = match rx.try_recv() { Ok(AppEvent::RefreshTokenActivity { request_id }) => request_id, other => panic!("expected token activity refresh request, got {other:?}"), @@ -1286,7 +1286,7 @@ async fn completed_token_activity_refresh_waits_for_active_stream() { assert_eq!( chat.pending_token_activity_output() .map(|cell| lines_to_single_string(&cell.display_lines(u16::MAX))), - Some("/tokens daily\n\n Token activity\n Token activity unavailable\n".to_string()), + Some("/usage daily\n\n Token activity\n Token activity unavailable\n".to_string()), ); chat.finalize_turn(); @@ -1303,7 +1303,7 @@ async fn completed_token_activity_refresh_waits_for_queued_stream_consolidation( let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); - chat.dispatch_command(SlashCommand::Tokens); + chat.dispatch_command(SlashCommand::Usage); let request_id = match rx.try_recv() { Ok(AppEvent::RefreshTokenActivity { request_id }) => request_id, other => panic!("expected token activity refresh request, got {other:?}"), @@ -1330,7 +1330,7 @@ async fn completed_token_activity_refresh_waits_for_active_history_cell() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); - chat.dispatch_command(SlashCommand::Tokens); + chat.dispatch_command(SlashCommand::Usage); let request_id = match rx.try_recv() { Ok(AppEvent::RefreshTokenActivity { request_id }) => request_id, other => panic!("expected token activity refresh request, got {other:?}"), @@ -1360,7 +1360,7 @@ async fn completed_token_activity_refresh_retries_after_plan_item_completion() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); - chat.dispatch_command(SlashCommand::Tokens); + chat.dispatch_command(SlashCommand::Usage); let request_id = match rx.try_recv() { Ok(AppEvent::RefreshTokenActivity { request_id }) => request_id, other => panic!("expected token activity refresh request, got {other:?}"), @@ -1395,7 +1395,7 @@ async fn pending_token_activity_refresh_keeps_composer_visible_in_short_viewport std::iter::repeat_n(Line::from("active output"), /*n*/ 20).collect(), ))); - chat.dispatch_command(SlashCommand::Tokens); + chat.dispatch_command(SlashCommand::Usage); assert_matches!( rx.try_recv(), Ok(AppEvent::RefreshTokenActivity { .. }), @@ -1426,13 +1426,13 @@ async fn repeated_token_activity_refreshes_keep_only_latest_card() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; set_chatgpt_auth(&mut chat); - chat.dispatch_command(SlashCommand::Tokens); + chat.dispatch_command(SlashCommand::Usage); let first_request_id = match rx.try_recv() { Ok(AppEvent::RefreshTokenActivity { request_id }) => request_id, other => panic!("expected first token activity refresh request, got {other:?}"), }; - chat.dispatch_command_with_args(SlashCommand::Tokens, "weekly".to_string(), Vec::new()); + chat.dispatch_command_with_args(SlashCommand::Usage, "weekly".to_string(), Vec::new()); let second_request_id = match rx.try_recv() { Ok(AppEvent::RefreshTokenActivity { request_id }) => request_id, other => panic!("expected second token activity refresh request, got {other:?}"), @@ -1441,7 +1441,7 @@ async fn repeated_token_activity_refreshes_keep_only_latest_card() { assert_eq!( chat.pending_token_activity_output() .map(|cell| lines_to_single_string(&cell.display_lines(u16::MAX))), - Some("/tokens weekly\n\n Token activity\n Loading...\n".to_string()), + Some("/usage weekly\n\n Token activity\n Loading...\n".to_string()), ); assert!(!chat.finish_token_activity_refresh( first_request_id, diff --git a/codex-rs/tui/src/chatwidget/tokens.rs b/codex-rs/tui/src/chatwidget/tokens.rs index be75491857..9c23549da1 100644 --- a/codex-rs/tui/src/chatwidget/tokens.rs +++ b/codex-rs/tui/src/chatwidget/tokens.rs @@ -1,4 +1,4 @@ -//! Renders account token activity and coordinates asynchronous `/tokens` cards. +//! Renders account token activity and coordinates asynchronous `/usage` cards. //! //! The slash command builds a composite history cell immediately, but the widget //! keeps that cell transient while the account request runs. The transient card is @@ -72,9 +72,9 @@ pub(super) enum TokenActivityView { } impl TokenActivityView { - /// Parses the optional `/tokens` argument into a supported chart view. + /// Parses the optional `/usage` argument into a supported chart view. /// - /// An empty argument selects the daily view so `/tokens` and `/tokens daily` + /// An empty argument selects the daily view so `/usage` and `/usage daily` /// behave identically. Returning `None` lets the slash-command dispatcher /// report unsupported arguments instead of silently choosing a view. pub(super) fn parse(value: &str) -> Option { @@ -115,7 +115,7 @@ pub(super) struct TokenActivityHandle { /// Holds the one transient token activity card waiting on its background response. /// -/// The request ID prevents late results from mutating a newer `/tokens` card. The +/// The request ID prevents late results from mutating a newer `/usage` card. The /// cell stays out of transcript history until the matching response completes and /// the widget confirms that active output no longer blocks insertion. pub(super) struct PendingTokenActivityOutput { @@ -141,14 +141,14 @@ impl TokenActivityHandle { } } -/// Renders one `/tokens` card from shared asynchronous state. +/// Renders one `/usage` card from shared asynchronous state. #[derive(Debug)] struct TokenActivityHistoryCell { view: TokenActivityView, state: Arc>, } -/// Creates the card contents and completion handle for one `/tokens` invocation. +/// Creates the card contents and completion handle for one `/usage` invocation. /// /// The composite cell includes the echoed slash command and a loading card from /// the start. Callers must retain the returned handle and complete it when the @@ -157,7 +157,7 @@ pub(super) fn new_token_activity_output( view: TokenActivityView, ) -> (CompositeHistoryCell, TokenActivityHandle) { let command = PlainHistoryCell::new(vec![ - format!("/tokens {}", view.label().to_lowercase()) + format!("/usage {}", view.label().to_lowercase()) .magenta() .into(), ]); @@ -464,7 +464,7 @@ fn bar_caption(view: TokenActivityView, values: &[i64]) -> Line<'static> { .into() } -/// Dim footer that surfaces the other `/tokens` views and emphasizes the +/// Dim footer that surfaces the other `/usage` views and emphasizes the /// active one, so the weekly/cumulative modes are discoverable from the card. fn view_footer(active: TokenActivityView) -> Line<'static> { let mut spans = vec![Span::styled(" ", label_style())]; @@ -743,7 +743,7 @@ impl ChatWidget { /// /// Returns `true` when the pending request matched and moved into the completed /// slot. Late responses return `false`, including responses for cards replaced - /// by a newer `/tokens` invocation or cleared during transcript changes. + /// by a newer `/usage` invocation or cleared during transcript changes. pub(crate) fn finish_token_activity_refresh( &mut self, request_id: u64, diff --git a/codex-rs/tui/src/slash_command.rs b/codex-rs/tui/src/slash_command.rs index 94bd176e2f..5f720cc68a 100644 --- a/codex-rs/tui/src/slash_command.rs +++ b/codex-rs/tui/src/slash_command.rs @@ -45,7 +45,7 @@ pub enum SlashCommand { Diff, Mention, Status, - Tokens, + Usage, DebugConfig, Title, Statusline, @@ -99,7 +99,7 @@ impl SlashCommand { SlashCommand::Skills => "use skills to improve how Codex performs specific tasks", SlashCommand::Hooks => "view and manage lifecycle hooks", SlashCommand::Status => "show current session configuration and token usage", - SlashCommand::Tokens => "show account token activity", + SlashCommand::Usage => "show account usage activity", SlashCommand::DebugConfig => "show config layers and requirement sources for debugging", SlashCommand::Title => "configure which items appear in the terminal title", SlashCommand::Statusline => "configure which items appear in the status line", @@ -159,7 +159,7 @@ impl SlashCommand { | SlashCommand::Keymap | SlashCommand::Mcp | SlashCommand::Raw - | SlashCommand::Tokens + | SlashCommand::Usage | SlashCommand::Pets | SlashCommand::Side | SlashCommand::Btw @@ -177,7 +177,7 @@ impl SlashCommand { | SlashCommand::Diff | SlashCommand::Mention | SlashCommand::Status - | SlashCommand::Tokens + | SlashCommand::Usage | SlashCommand::Ide ) } @@ -214,7 +214,7 @@ impl SlashCommand { | SlashCommand::Skills | SlashCommand::Hooks | SlashCommand::Status - | SlashCommand::Tokens + | SlashCommand::Usage | SlashCommand::DebugConfig | SlashCommand::Ps | SlashCommand::Stop