mirror of
https://github.com/openai/codex.git
synced 2026-05-02 12:21:26 +03:00
Add usage-based business plan types (#15934)
## Summary - add `self_serve_business_usage_based` and `enterprise_cbp_usage_based` to the public/internal plan enums and regenerate the app-server + Python SDK artifacts - map both plans through JWT login and backend rate-limit payloads, then bucket them with the existing Team/Business entitlement behavior in cloud requirements, usage-limit copy, tooltips, and status display - keep the earlier display-label remap commit on this branch so the new Team-like and Business-like plans render consistently in the UI ## Testing - `just write-app-server-schema` - `uv run --project sdk/python python sdk/python/scripts/update_sdk_artifacts.py generate-types` - `just fix -p codex-protocol -p codex-login -p codex-core -p codex-backend-client -p codex-cloud-requirements -p codex-tui -p codex-tui-app-server -p codex-backend-openapi-models` - `just fmt` - `just argument-comment-lint` - `cargo test -p codex-protocol usage_based_plan_types_use_expected_wire_names` - `cargo test -p codex-login usage_based` - `cargo test -p codex-backend-client usage_based` - `cargo test -p codex-cloud-requirements usage_based` - `cargo test -p codex-core usage_limit_reached_error_formats_` - `cargo test -p codex-tui plan_type_display_name_remaps_display_labels` - `cargo test -p codex-tui remapped` - `cargo test -p codex-tui-app-server plan_type_display_name_remaps_display_labels` - `cargo test -p codex-tui-app-server remapped` - `cargo test -p codex-tui-app-server preserves_usage_based_plan_type_wire_name` ## Notes - a broader multi-crate `cargo test` run still hits unrelated existing guardian-approval config failures in `codex-rs/core/src/config/config_tests.rs`
This commit is contained in:
@@ -41,7 +41,14 @@ pub struct IdTokenInfo {
|
||||
impl IdTokenInfo {
|
||||
pub fn get_chatgpt_plan_type(&self) -> Option<String> {
|
||||
self.chatgpt_plan_type.as_ref().map(|t| match t {
|
||||
PlanType::Known(plan) => format!("{plan:?}"),
|
||||
PlanType::Known(plan) => plan.display_name().to_string(),
|
||||
PlanType::Unknown(s) => s.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_chatgpt_plan_type_raw(&self) -> Option<String> {
|
||||
self.chatgpt_plan_type.as_ref().map(|t| match t {
|
||||
PlanType::Known(plan) => plan.raw_value().to_string(),
|
||||
PlanType::Unknown(s) => s.clone(),
|
||||
})
|
||||
}
|
||||
@@ -49,9 +56,7 @@ impl IdTokenInfo {
|
||||
pub fn is_workspace_account(&self) -> bool {
|
||||
matches!(
|
||||
self.chatgpt_plan_type,
|
||||
Some(PlanType::Known(
|
||||
KnownPlan::Team | KnownPlan::Business | KnownPlan::Enterprise | KnownPlan::Edu
|
||||
))
|
||||
Some(PlanType::Known(plan)) if plan.is_workspace_account()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -71,7 +76,11 @@ impl PlanType {
|
||||
"plus" => Self::Known(KnownPlan::Plus),
|
||||
"pro" => Self::Known(KnownPlan::Pro),
|
||||
"team" => Self::Known(KnownPlan::Team),
|
||||
"self_serve_business_usage_based" => {
|
||||
Self::Known(KnownPlan::SelfServeBusinessUsageBased)
|
||||
}
|
||||
"business" => Self::Known(KnownPlan::Business),
|
||||
"enterprise_cbp_usage_based" => Self::Known(KnownPlan::EnterpriseCbpUsageBased),
|
||||
"enterprise" | "hc" => Self::Known(KnownPlan::Enterprise),
|
||||
"education" | "edu" => Self::Known(KnownPlan::Edu),
|
||||
_ => Self::Unknown(raw.to_string()),
|
||||
@@ -79,7 +88,7 @@ impl PlanType {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum KnownPlan {
|
||||
Free,
|
||||
@@ -87,12 +96,60 @@ pub enum KnownPlan {
|
||||
Plus,
|
||||
Pro,
|
||||
Team,
|
||||
#[serde(rename = "self_serve_business_usage_based")]
|
||||
SelfServeBusinessUsageBased,
|
||||
Business,
|
||||
#[serde(rename = "enterprise_cbp_usage_based")]
|
||||
EnterpriseCbpUsageBased,
|
||||
#[serde(alias = "hc")]
|
||||
Enterprise,
|
||||
Edu,
|
||||
}
|
||||
|
||||
impl KnownPlan {
|
||||
pub fn display_name(self) -> &'static str {
|
||||
match self {
|
||||
Self::Free => "Free",
|
||||
Self::Go => "Go",
|
||||
Self::Plus => "Plus",
|
||||
Self::Pro => "Pro",
|
||||
Self::Team => "Team",
|
||||
Self::SelfServeBusinessUsageBased => "Self Serve Business Usage Based",
|
||||
Self::Business => "Business",
|
||||
Self::EnterpriseCbpUsageBased => "Enterprise CBP Usage Based",
|
||||
Self::Enterprise => "Enterprise",
|
||||
Self::Edu => "Edu",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn raw_value(self) -> &'static str {
|
||||
match self {
|
||||
Self::Free => "free",
|
||||
Self::Go => "go",
|
||||
Self::Plus => "plus",
|
||||
Self::Pro => "pro",
|
||||
Self::Team => "team",
|
||||
Self::SelfServeBusinessUsageBased => "self_serve_business_usage_based",
|
||||
Self::Business => "business",
|
||||
Self::EnterpriseCbpUsageBased => "enterprise_cbp_usage_based",
|
||||
Self::Enterprise => "enterprise",
|
||||
Self::Edu => "edu",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_workspace_account(self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::Team
|
||||
| Self::SelfServeBusinessUsageBased
|
||||
| Self::Business
|
||||
| Self::EnterpriseCbpUsageBased
|
||||
| Self::Enterprise
|
||||
| Self::Edu
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct IdClaims {
|
||||
#[serde(default)]
|
||||
|
||||
Reference in New Issue
Block a user