From e734cb5713086aa31db81f9180c78c0742a446b9 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Mon, 18 May 2026 09:02:38 -0700 Subject: [PATCH] Hide ChatGPT usage link for non-OpenAI status (#23127) Addresses #22778 ## Summary Provider deployments such as Bedrock manage rate limits and billing outside ChatGPT, so the `/status` link to the ChatGPT usage page is irrelevant and confusing for those users. Custom providers that are explicitly configured to use OpenAI/ChatGPT auth still point at OpenAI-backed usage, so they should keep the link. ## Changes - Render the ChatGPT usage note only when the configured provider uses OpenAI auth. - Keep the note hidden when `/status` displays a provider such as Bedrock that manages limits elsewhere. - Add regression coverage for both Bedrock and a custom OpenAI-auth proxy provider. ## Manual Repro 1. Configure Codex with a non-OpenAI-auth provider, for example `model_provider = "amazon-bedrock"`. 2. Start the TUI and run `/status`. 3. Confirm the status card shows the custom provider, for example `Model provider: Amazon Bedrock`, and does not show `https://chatgpt.com/codex/settings/usage`. 4. Configure a custom provider that proxies to OpenAI and has OpenAI/ChatGPT auth enabled. 5. Run `/status` again and confirm the ChatGPT usage link appears for that OpenAI-auth provider. --- codex-rs/tui/src/status/card.rs | 11 +++++++-- codex-rs/tui/src/status/tests.rs | 38 +++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/codex-rs/tui/src/status/card.rs b/codex-rs/tui/src/status/card.rs index 3d30f800b..7f7768e2c 100644 --- a/codex-rs/tui/src/status/card.rs +++ b/codex-rs/tui/src/status/card.rs @@ -106,6 +106,7 @@ struct StatusHistoryCell { agents_summary: Arc>, collaboration_mode: Option, model_provider: Option, + show_chatgpt_usage_link: bool, account: Option, thread_name: Option, session_id: Option, @@ -308,6 +309,7 @@ impl StatusHistoryCell { workspace_root_suffix.as_deref(), ); let model_provider = format_model_provider(config, runtime_model_provider_base_url); + let show_chatgpt_usage_link = config.model_provider.requires_openai_auth; let account = compose_account_display(account_display); let session_id = session_id.as_ref().map(std::string::ToString::to_string); let forked_from = forked_from.map(|id| id.to_string()); @@ -347,6 +349,7 @@ impl StatusHistoryCell { permissions, collaboration_mode: collaboration_mode.map(ToString::to_string), model_provider, + show_chatgpt_usage_link, account, thread_name, session_id, @@ -765,8 +768,12 @@ impl HistoryCell for StatusHistoryCell { [note_first_line, note_second_line], RtOptions::new(available_inner_width), ); - lines.extend(note_lines); - lines.push(Line::from(Vec::>::new())); + // The ChatGPT usage page only applies to providers backed by OpenAI auth; + // providers like Bedrock manage limits and billing elsewhere. + if self.show_chatgpt_usage_link { + lines.extend(note_lines); + lines.push(Line::from(Vec::>::new())); + } let mut model_spans = vec![Span::from(self.model_name.clone())]; if !self.model_details.is_empty() { diff --git a/codex-rs/tui/src/status/tests.rs b/codex-rs/tui/src/status/tests.rs index 3a10e0ed9..286767e64 100644 --- a/codex-rs/tui/src/status/tests.rs +++ b/codex-rs/tui/src/status/tests.rs @@ -582,7 +582,7 @@ async fn status_snapshot_shows_active_user_defined_profile() { } #[tokio::test] -async fn status_model_provider_uses_bedrock_runtime_base_url() { +async fn status_model_provider_uses_bedrock_runtime_base_url_and_gates_usage_link() { let temp_home = TempDir::new().expect("temp home"); let mut config = test_config(&temp_home).await; config.model_provider_id = "amazon-bedrock".to_string(); @@ -629,6 +629,42 @@ async fn status_model_provider_uses_bedrock_runtime_base_url() { !rendered.contains("bedrock-mantle.us-east-1"), "expected /status to ignore configured Bedrock base URL, got: {rendered}" ); + assert!( + !rendered.contains("https://chatgpt.com/codex/settings/usage"), + "expected /status to hide ChatGPT usage link for Bedrock, got: {rendered}" + ); + + config.model_provider_id = "openai-proxy".to_string(); + config.model_provider = ModelProviderInfo { + name: "OpenAI Proxy".to_string(), + base_url: Some("https://openai-proxy.example/v1".to_string()), + requires_openai_auth: true, + ..ModelProviderInfo::default() + }; + let (composite, _handle) = new_status_output_with_rate_limits_handle( + &config, + /*runtime_model_provider_base_url*/ None, + test_status_account_display().as_ref(), + /*token_info*/ None, + &usage, + &None, + /*thread_name*/ None, + /*forked_from*/ None, + /*rate_limits*/ &[], + None, + captured_at, + &model_slug, + /*collaboration_mode*/ None, + /*reasoning_effort_override*/ None, + "".to_string(), + /*refreshing_rate_limits*/ false, + ); + let rendered = render_lines(&composite.display_lines(/*width*/ 120)).join("\n"); + + assert!( + rendered.contains("https://chatgpt.com/codex/settings/usage"), + "expected /status to show ChatGPT usage link for OpenAI-auth proxy, got: {rendered}" + ); } #[tokio::test]