diff --git a/codex-rs/app-server-protocol/schema/json/ServerNotification.json b/codex-rs/app-server-protocol/schema/json/ServerNotification.json index 7f53cdbf0c..636a2433c2 100644 --- a/codex-rs/app-server-protocol/schema/json/ServerNotification.json +++ b/codex-rs/app-server-protocol/schema/json/ServerNotification.json @@ -2915,6 +2915,7 @@ "team", "self_serve_business_usage_based", "business", + "ent26", "enterprise_cbp_usage_based", "enterprise", "edu", diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json index c17421a10f..d9466b3eab 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json @@ -13999,6 +13999,7 @@ "team", "self_serve_business_usage_based", "business", + "ent26", "enterprise_cbp_usage_based", "enterprise", "edu", diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json index 1fb9fd8024..d126778627 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json @@ -10341,6 +10341,7 @@ "team", "self_serve_business_usage_based", "business", + "ent26", "enterprise_cbp_usage_based", "enterprise", "edu", diff --git a/codex-rs/app-server-protocol/schema/json/v2/AccountRateLimitsUpdatedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/AccountRateLimitsUpdatedNotification.json index c2dfb3e499..d66af3fbe4 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/AccountRateLimitsUpdatedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/AccountRateLimitsUpdatedNotification.json @@ -32,6 +32,7 @@ "team", "self_serve_business_usage_based", "business", + "ent26", "enterprise_cbp_usage_based", "enterprise", "edu", diff --git a/codex-rs/app-server-protocol/schema/json/v2/AccountUpdatedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/AccountUpdatedNotification.json index 710e0ecedd..c10c49132f 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/AccountUpdatedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/AccountUpdatedNotification.json @@ -65,6 +65,7 @@ "team", "self_serve_business_usage_based", "business", + "ent26", "enterprise_cbp_usage_based", "enterprise", "edu", diff --git a/codex-rs/app-server-protocol/schema/json/v2/GetAccountRateLimitsResponse.json b/codex-rs/app-server-protocol/schema/json/v2/GetAccountRateLimitsResponse.json index 9d75ca14c8..a7d91a6281 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/GetAccountRateLimitsResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/GetAccountRateLimitsResponse.json @@ -32,6 +32,7 @@ "team", "self_serve_business_usage_based", "business", + "ent26", "enterprise_cbp_usage_based", "enterprise", "edu", diff --git a/codex-rs/app-server-protocol/schema/json/v2/GetAccountResponse.json b/codex-rs/app-server-protocol/schema/json/v2/GetAccountResponse.json index 89d8827d73..a65e3066d3 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/GetAccountResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/GetAccountResponse.json @@ -78,6 +78,7 @@ "team", "self_serve_business_usage_based", "business", + "ent26", "enterprise_cbp_usage_based", "enterprise", "edu", diff --git a/codex-rs/app-server-protocol/schema/typescript/PlanType.ts b/codex-rs/app-server-protocol/schema/typescript/PlanType.ts index 44891467e9..9685328149 100644 --- a/codex-rs/app-server-protocol/schema/typescript/PlanType.ts +++ b/codex-rs/app-server-protocol/schema/typescript/PlanType.ts @@ -2,4 +2,4 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -export type PlanType = "free" | "go" | "plus" | "pro" | "prolite" | "team" | "self_serve_business_usage_based" | "business" | "enterprise_cbp_usage_based" | "enterprise" | "edu" | "unknown"; +export type PlanType = "free" | "go" | "plus" | "pro" | "prolite" | "team" | "self_serve_business_usage_based" | "business" | "ent26" | "enterprise_cbp_usage_based" | "enterprise" | "edu" | "unknown"; diff --git a/codex-rs/backend-client/src/client.rs b/codex-rs/backend-client/src/client.rs index 97e3bdaee9..1073a3d50b 100644 --- a/codex-rs/backend-client/src/client.rs +++ b/codex-rs/backend-client/src/client.rs @@ -689,6 +689,7 @@ impl Client { AccountPlanType::SelfServeBusinessUsageBased } crate::types::PlanType::Business => AccountPlanType::Business, + crate::types::PlanType::Ent26 => AccountPlanType::Ent26, crate::types::PlanType::EnterpriseCbpUsageBased => { AccountPlanType::EnterpriseCbpUsageBased } @@ -740,6 +741,9 @@ mod tests { Client::map_plan_type(crate::types::PlanType::EnterpriseCbpUsageBased), AccountPlanType::EnterpriseCbpUsageBased ); + let ent26 = serde_json::from_str::("\"ent26\"") + .expect("ent26 backend plan should deserialize"); + assert_eq!(Client::map_plan_type(ent26), AccountPlanType::Ent26); } #[test] diff --git a/codex-rs/cloud-config/src/service_tests.rs b/codex-rs/cloud-config/src/service_tests.rs index 42486e67aa..dd1469ad7e 100644 --- a/codex-rs/cloud-config/src/service_tests.rs +++ b/codex-rs/cloud-config/src/service_tests.rs @@ -416,6 +416,7 @@ async fn get_bundle_skips_individual_plan() { async fn get_bundle_allows_eligible_workspace_plans_and_writes_cache() { for plan_type in [ "business", + "ent26", "enterprise_cbp_usage_based", "enterprise", "hc", diff --git a/codex-rs/codex-backend-openapi-models/src/models/rate_limit_status_payload.rs b/codex-rs/codex-backend-openapi-models/src/models/rate_limit_status_payload.rs index 066a81b524..252b9b1d17 100644 --- a/codex-rs/codex-backend-openapi-models/src/models/rate_limit_status_payload.rs +++ b/codex-rs/codex-backend-openapi-models/src/models/rate_limit_status_payload.rs @@ -116,6 +116,8 @@ pub enum PlanType { SelfServeBusinessUsageBased, #[serde(rename = "business")] Business, + #[serde(rename = "ent26")] + Ent26, #[serde(rename = "enterprise_cbp_usage_based")] EnterpriseCbpUsageBased, #[serde(rename = "education")] diff --git a/codex-rs/login/src/token_data_tests.rs b/codex-rs/login/src/token_data_tests.rs index f39a7cb25d..d84a040133 100644 --- a/codex-rs/login/src/token_data_tests.rs +++ b/codex-rs/login/src/token_data_tests.rs @@ -69,6 +69,21 @@ fn id_token_info_parses_hc_plan_as_enterprise() { assert_eq!(info.is_workspace_account(), true); } +#[test] +fn id_token_info_parses_ent26_plan() { + let fake_jwt = fake_jwt(serde_json::json!({ + "email": "user@example.com", + "https://api.openai.com/auth": { + "chatgpt_plan_type": "ent26" + } + })); + + let info = parse_chatgpt_jwt_claims(&fake_jwt).expect("should parse"); + assert_eq!(info.get_chatgpt_plan_type().as_deref(), Some("Enterprise")); + assert_eq!(info.get_chatgpt_plan_type_raw().as_deref(), Some("ent26")); + assert_eq!(info.is_workspace_account(), true); +} + #[test] fn id_token_info_parses_usage_based_business_plans() { let self_serve_business_jwt = fake_jwt(serde_json::json!({ diff --git a/codex-rs/protocol/src/account.rs b/codex-rs/protocol/src/account.rs index aedf5474be..2a7b842a1e 100644 --- a/codex-rs/protocol/src/account.rs +++ b/codex-rs/protocol/src/account.rs @@ -21,6 +21,7 @@ pub enum PlanType { #[ts(rename = "self_serve_business_usage_based")] SelfServeBusinessUsageBased, Business, + Ent26, #[serde(rename = "enterprise_cbp_usage_based")] #[ts(rename = "enterprise_cbp_usage_based")] EnterpriseCbpUsageBased, @@ -49,7 +50,10 @@ impl PlanType { } pub fn is_business_like(self) -> bool { - matches!(self, Self::Business | Self::EnterpriseCbpUsageBased) + matches!( + self, + Self::Business | Self::Ent26 | Self::EnterpriseCbpUsageBased + ) } pub fn is_workspace_account(self) -> bool { @@ -58,6 +62,7 @@ impl PlanType { Self::Team | Self::SelfServeBusinessUsageBased | Self::Business + | Self::Ent26 | Self::EnterpriseCbpUsageBased | Self::Enterprise | Self::Edu @@ -85,6 +90,7 @@ impl From for PlanType { KnownPlan::Team => Self::Team, KnownPlan::SelfServeBusinessUsageBased => Self::SelfServeBusinessUsageBased, KnownPlan::Business => Self::Business, + KnownPlan::Ent26 => Self::Ent26, KnownPlan::EnterpriseCbpUsageBased => Self::EnterpriseCbpUsageBased, KnownPlan::Enterprise => Self::Enterprise, KnownPlan::Edu => Self::Edu, @@ -111,6 +117,10 @@ mod tests { .expect("enterprise cbp usage based should serialize"), "\"enterprise_cbp_usage_based\"" ); + assert_eq!( + serde_json::to_string(&PlanType::Ent26).expect("ent26 should serialize"), + "\"ent26\"" + ); assert_eq!( serde_json::to_string(&PlanType::ProLite).expect("prolite should serialize"), "\"prolite\"" @@ -129,6 +139,10 @@ mod tests { .expect("enterprise cbp usage based should deserialize"), PlanType::EnterpriseCbpUsageBased ); + assert_eq!( + serde_json::from_str::("\"ent26\"").expect("ent26 should deserialize"), + PlanType::Ent26 + ); } #[test] @@ -136,8 +150,10 @@ mod tests { assert_eq!(PlanType::Team.is_team_like(), true); assert_eq!(PlanType::SelfServeBusinessUsageBased.is_team_like(), true); assert_eq!(PlanType::Business.is_team_like(), false); + assert_eq!(PlanType::Ent26.is_team_like(), false); assert_eq!(PlanType::Business.is_business_like(), true); + assert_eq!(PlanType::Ent26.is_business_like(), true); assert_eq!(PlanType::EnterpriseCbpUsageBased.is_business_like(), true); assert_eq!(PlanType::Team.is_business_like(), false); } @@ -150,6 +166,7 @@ mod tests { true ); assert_eq!(PlanType::Business.is_workspace_account(), true); + assert_eq!(PlanType::Ent26.is_workspace_account(), true); assert_eq!( PlanType::EnterpriseCbpUsageBased.is_workspace_account(), true @@ -165,6 +182,10 @@ mod tests { PlanType::from(AuthPlanType::Known(KnownPlan::EnterpriseCbpUsageBased)), PlanType::EnterpriseCbpUsageBased ); + assert_eq!( + PlanType::from(AuthPlanType::Known(KnownPlan::Ent26)), + PlanType::Ent26 + ); assert_eq!( PlanType::from(AuthPlanType::Known(KnownPlan::Enterprise)), PlanType::Enterprise diff --git a/codex-rs/protocol/src/auth.rs b/codex-rs/protocol/src/auth.rs index a537c0268d..af5eb8a793 100644 --- a/codex-rs/protocol/src/auth.rs +++ b/codex-rs/protocol/src/auth.rs @@ -75,6 +75,7 @@ impl PlanType { Self::Known(KnownPlan::SelfServeBusinessUsageBased) } "business" => Self::Known(KnownPlan::Business), + "ent26" => Self::Known(KnownPlan::Ent26), "enterprise_cbp_usage_based" => Self::Known(KnownPlan::EnterpriseCbpUsageBased), "enterprise" | "hc" => Self::Known(KnownPlan::Enterprise), "education" | "edu" => Self::Known(KnownPlan::Edu), @@ -95,6 +96,7 @@ pub enum KnownPlan { #[serde(rename = "self_serve_business_usage_based")] SelfServeBusinessUsageBased, Business, + Ent26, #[serde(rename = "enterprise_cbp_usage_based")] EnterpriseCbpUsageBased, #[serde(alias = "hc")] @@ -114,6 +116,7 @@ impl KnownPlan { Self::Team => "Team", Self::SelfServeBusinessUsageBased => "Self Serve Business Usage Based", Self::Business => "Business", + Self::Ent26 => "Enterprise", Self::EnterpriseCbpUsageBased => "Enterprise CBP Usage Based", Self::Enterprise => "Enterprise", Self::Edu => "Edu", @@ -130,6 +133,7 @@ impl KnownPlan { Self::Team => "team", Self::SelfServeBusinessUsageBased => "self_serve_business_usage_based", Self::Business => "business", + Self::Ent26 => "ent26", Self::EnterpriseCbpUsageBased => "enterprise_cbp_usage_based", Self::Enterprise => "enterprise", Self::Edu => "edu", @@ -142,6 +146,7 @@ impl KnownPlan { Self::Team | Self::SelfServeBusinessUsageBased | Self::Business + | Self::Ent26 | Self::EnterpriseCbpUsageBased | Self::Enterprise | Self::Edu diff --git a/codex-rs/protocol/src/error.rs b/codex-rs/protocol/src/error.rs index 0cf660b096..68e0f7fc94 100644 --- a/codex-rs/protocol/src/error.rs +++ b/codex-rs/protocol/src/error.rs @@ -688,6 +688,7 @@ impl std::fmt::Display for UsageLimitReachedError { KnownPlan::Team | KnownPlan::SelfServeBusinessUsageBased | KnownPlan::Business + | KnownPlan::Ent26 | KnownPlan::EnterpriseCbpUsageBased, )) => { format!( diff --git a/codex-rs/protocol/src/error_tests.rs b/codex-rs/protocol/src/error_tests.rs index 22ccf0a327..146aa41b91 100644 --- a/codex-rs/protocol/src/error_tests.rs +++ b/codex-rs/protocol/src/error_tests.rs @@ -336,17 +336,19 @@ fn usage_limit_reached_error_formats_team_plan() { #[test] fn usage_limit_reached_error_formats_business_plan_without_reset() { - let err = UsageLimitReachedError { - plan_type: Some(PlanType::Known(KnownPlan::Business)), - resets_at: None, - rate_limits: Some(Box::new(rate_limit_snapshot())), - promo_message: None, - rate_limit_reached_type: None, - }; - assert_eq!( - err.to_string(), - "You've hit your usage limit. To get more access now, send a request to your admin or try again later." - ); + for plan in [KnownPlan::Business, KnownPlan::Ent26] { + let err = UsageLimitReachedError { + plan_type: Some(PlanType::Known(plan)), + resets_at: None, + rate_limits: Some(Box::new(rate_limit_snapshot())), + promo_message: None, + rate_limit_reached_type: None, + }; + assert_eq!( + err.to_string(), + "You've hit your usage limit. To get more access now, send a request to your admin or try again later." + ); + } } #[test]