Remap displayed ChatGPT plan labels

This commit is contained in:
Ben Wanner
2026-03-26 16:10:14 -07:00
parent 609019c6e5
commit d0f8b4c7f0
4 changed files with 128 additions and 18 deletions

View File

@@ -94,14 +94,21 @@ pub(crate) fn compose_account_display(
CoreAuthMode::ApiKey => Some(StatusAccountDisplay::ApiKey),
CoreAuthMode::Chatgpt | CoreAuthMode::ChatgptAuthTokens => {
let email = auth.get_account_email();
let plan = plan
.map(|plan_type| title_case(format!("{plan_type:?}").as_str()))
.or_else(|| Some("Unknown".to_string()));
let plan = plan.map(plan_type_display_name);
let plan = plan.or_else(|| Some("Unknown".to_string()));
Some(StatusAccountDisplay::ChatGpt { email, plan })
}
}
}
pub(crate) fn plan_type_display_name(plan_type: PlanType) -> String {
match plan_type {
PlanType::Team => "Business".to_string(),
PlanType::Business => "Enterprise".to_string(),
_ => title_case(format!("{plan_type:?}").as_str()),
}
}
pub(crate) fn format_tokens_compact(value: i64) -> String {
let value = value.max(0);
if value == 0 {
@@ -187,3 +194,44 @@ pub(crate) fn title_case(s: &str) -> String {
let rest: String = chars.as_str().to_ascii_lowercase();
first.to_uppercase().collect::<String>() + &rest
}
#[cfg(test)]
mod tests {
use super::*;
use codex_core::auth::CodexAuth;
use pretty_assertions::assert_eq;
#[test]
fn plan_type_display_name_remaps_display_labels() {
let cases = [
(PlanType::Free, "Free"),
(PlanType::Go, "Go"),
(PlanType::Plus, "Plus"),
(PlanType::Pro, "Pro"),
(PlanType::Team, "Business"),
(PlanType::Business, "Enterprise"),
(PlanType::Enterprise, "Enterprise"),
(PlanType::Edu, "Edu"),
(PlanType::Unknown, "Unknown"),
];
for (plan_type, expected) in cases {
assert_eq!(plan_type_display_name(plan_type), expected);
}
}
#[test]
fn compose_account_display_uses_remapped_plan_label() {
let auth_manager =
AuthManager::from_auth_for_testing(CodexAuth::create_dummy_chatgpt_auth_for_testing());
let display = compose_account_display(auth_manager.as_ref(), Some(PlanType::Team));
assert!(matches!(
display,
Some(StatusAccountDisplay::ChatGpt {
email: None,
plan: Some(ref plan),
}) if plan == "Business"
));
}
}

View File

@@ -1,5 +1,6 @@
use crate::bottom_pane::FeedbackAudience;
use crate::status::StatusAccountDisplay;
use crate::status::plan_type_display_name;
use codex_app_server_client::AppServerClient;
use codex_app_server_client::AppServerEvent;
use codex_app_server_client::AppServerRequestHandle;
@@ -228,7 +229,7 @@ impl AppServerSession {
Some(TelemetryAuthMode::Chatgpt),
Some(StatusAccountDisplay::ChatGpt {
email: Some(email),
plan: Some(title_case(format!("{plan_type:?}").as_str())),
plan: Some(plan_type_display_name(plan_type)),
}),
Some(plan_type),
feedback_audience,
@@ -733,19 +734,6 @@ impl AppServerSession {
}
}
fn title_case(s: &str) -> String {
if s.is_empty() {
return String::new();
}
let mut chars = s.chars();
let Some(first) = chars.next() else {
return String::new();
};
let rest = chars.as_str().to_ascii_lowercase();
first.to_uppercase().collect::<String>() + &rest
}
pub(crate) fn status_account_display_from_auth_mode(
auth_mode: Option<AuthMode>,
plan_type: Option<codex_protocol::account::PlanType>,
@@ -755,7 +743,7 @@ pub(crate) fn status_account_display_from_auth_mode(
Some(AuthMode::Chatgpt) | Some(AuthMode::ChatgptAuthTokens) => {
Some(StatusAccountDisplay::ChatGpt {
email: None,
plan: plan_type.map(|plan_type| title_case(format!("{plan_type:?}").as_str())),
plan: plan_type.map(plan_type_display_name),
})
}
None => None,
@@ -1264,4 +1252,31 @@ mod tests {
assert_ne!(session.history_log_id, 0);
assert_eq!(session.history_entry_count, 2);
}
#[test]
fn status_account_display_from_auth_mode_uses_remapped_plan_labels() {
let business = status_account_display_from_auth_mode(
Some(AuthMode::Chatgpt),
Some(codex_protocol::account::PlanType::Business),
);
assert!(matches!(
business,
Some(StatusAccountDisplay::ChatGpt {
email: None,
plan: Some(ref plan),
}) if plan == "Enterprise"
));
let team = status_account_display_from_auth_mode(
Some(AuthMode::Chatgpt),
Some(codex_protocol::account::PlanType::Team),
);
assert!(matches!(
team,
Some(StatusAccountDisplay::ChatGpt {
email: None,
plan: Some(ref plan),
}) if plan == "Business"
));
}
}

View File

@@ -5,6 +5,7 @@ use chrono::DateTime;
use chrono::Local;
use codex_core::config::Config;
use codex_core::project_doc::discover_project_doc_paths;
use codex_protocol::account::PlanType;
use std::path::Path;
use unicode_width::UnicodeWidthStr;
@@ -86,6 +87,14 @@ pub(crate) fn compose_account_display(
account_display.cloned()
}
pub(crate) fn plan_type_display_name(plan_type: PlanType) -> String {
match plan_type {
PlanType::Team => "Business".to_string(),
PlanType::Business => "Enterprise".to_string(),
_ => title_case(format!("{plan_type:?}").as_str()),
}
}
pub(crate) fn format_tokens_compact(value: i64) -> String {
let value = value.max(0);
if value == 0 {
@@ -158,3 +167,40 @@ pub(crate) fn format_reset_timestamp(dt: DateTime<Local>, captured_at: DateTime<
format!("{time} on {}", dt.format("%-d %b"))
}
}
fn title_case(s: &str) -> String {
if s.is_empty() {
return String::new();
}
let mut chars = s.chars();
let Some(first) = chars.next() else {
return String::new();
};
let rest = chars.as_str().to_ascii_lowercase();
first.to_uppercase().collect::<String>() + &rest
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn plan_type_display_name_remaps_display_labels() {
let cases = [
(PlanType::Free, "Free"),
(PlanType::Go, "Go"),
(PlanType::Plus, "Plus"),
(PlanType::Pro, "Pro"),
(PlanType::Team, "Business"),
(PlanType::Business, "Enterprise"),
(PlanType::Enterprise, "Enterprise"),
(PlanType::Edu, "Edu"),
(PlanType::Unknown, "Unknown"),
];
for (plan_type, expected) in cases {
assert_eq!(plan_type_display_name(plan_type), expected);
}
}
}

View File

@@ -18,6 +18,7 @@ pub(crate) use card::new_status_output;
pub(crate) use card::new_status_output_with_rate_limits;
pub(crate) use helpers::format_directory_display;
pub(crate) use helpers::format_tokens_compact;
pub(crate) use helpers::plan_type_display_name;
pub(crate) use rate_limits::RateLimitSnapshotDisplay;
pub(crate) use rate_limits::RateLimitWindowDisplay;
#[cfg(test)]