mirror of
https://github.com/openai/codex.git
synced 2026-09-08 15:50:34 +00:00
## Why AWS/Bedrock mode currently reports `account: null` with `requiresOpenaiAuth: false` from `account/read`. That suppresses the OpenAI-auth requirement, but it does not let app clients distinguish AWS auth from any other non-OpenAI custom provider. For the prototype AWS provider UX, clients need a simple provider-derived signal so they can suppress ChatGPT/API-key login and token-refresh paths without hardcoding Bedrock checks. ## What changed - Adds an `aws` variant to the v2 `Account` protocol union. - Adds `ProviderAccountKind` to `codex-model-provider` so the runtime provider owns the app-visible account classification. - Makes Amazon Bedrock return `ProviderAccountKind::Aws` from the model-provider layer. - Updates app-server `account/read` to map `ProviderAccountKind` to the existing `GetAccountResponse` wire shape. - Preserves the existing `account: null, requiresOpenaiAuth: false` behavior for other non-OpenAI providers. - Regenerates the app-server protocol schema fixtures. - Adds coverage for provider account classification and for the Amazon Bedrock `account/read` response. ## Testing - `cargo test -p codex-model-provider` - `cargo test -p codex-app-server-protocol` - `cargo test -p codex-app-server get_account_with_aws_provider` ## Notes I attempted `just bazel-lock-update` and `just bazel-lock-check`, but both are blocked in my local environment because `bazel` is not installed.
125 lines
4.0 KiB
Rust
125 lines
4.0 KiB
Rust
use schemars::JsonSchema;
|
|
use serde::Deserialize;
|
|
use serde::Serialize;
|
|
use ts_rs::TS;
|
|
|
|
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq, JsonSchema, TS, Default)]
|
|
#[serde(rename_all = "lowercase")]
|
|
#[ts(rename_all = "lowercase")]
|
|
pub enum PlanType {
|
|
#[default]
|
|
Free,
|
|
Go,
|
|
Plus,
|
|
Pro,
|
|
ProLite,
|
|
Team,
|
|
#[serde(rename = "self_serve_business_usage_based")]
|
|
#[ts(rename = "self_serve_business_usage_based")]
|
|
SelfServeBusinessUsageBased,
|
|
Business,
|
|
#[serde(rename = "enterprise_cbp_usage_based")]
|
|
#[ts(rename = "enterprise_cbp_usage_based")]
|
|
EnterpriseCbpUsageBased,
|
|
Enterprise,
|
|
Edu,
|
|
#[serde(other)]
|
|
Unknown,
|
|
}
|
|
|
|
/// Account state returned by a model provider before it is adapted to an app-facing wire type.
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub enum ProviderAccount {
|
|
ApiKey,
|
|
Chatgpt { email: String, plan_type: PlanType },
|
|
AmazonBedrock,
|
|
}
|
|
|
|
impl PlanType {
|
|
pub fn is_team_like(self) -> bool {
|
|
matches!(self, Self::Team | Self::SelfServeBusinessUsageBased)
|
|
}
|
|
|
|
pub fn is_business_like(self) -> bool {
|
|
matches!(self, Self::Business | Self::EnterpriseCbpUsageBased)
|
|
}
|
|
|
|
pub fn is_workspace_account(self) -> bool {
|
|
matches!(
|
|
self,
|
|
Self::Team
|
|
| Self::SelfServeBusinessUsageBased
|
|
| Self::Business
|
|
| Self::EnterpriseCbpUsageBased
|
|
| Self::Enterprise
|
|
| Self::Edu
|
|
)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::PlanType;
|
|
use pretty_assertions::assert_eq;
|
|
|
|
#[test]
|
|
fn usage_based_plan_types_use_expected_wire_names() {
|
|
assert_eq!(
|
|
serde_json::to_string(&PlanType::SelfServeBusinessUsageBased)
|
|
.expect("self-serve business usage based should serialize"),
|
|
"\"self_serve_business_usage_based\""
|
|
);
|
|
assert_eq!(
|
|
serde_json::to_string(&PlanType::EnterpriseCbpUsageBased)
|
|
.expect("enterprise cbp usage based should serialize"),
|
|
"\"enterprise_cbp_usage_based\""
|
|
);
|
|
assert_eq!(
|
|
serde_json::to_string(&PlanType::ProLite).expect("prolite should serialize"),
|
|
"\"prolite\""
|
|
);
|
|
assert_eq!(
|
|
serde_json::from_str::<PlanType>("\"self_serve_business_usage_based\"")
|
|
.expect("self-serve business usage based should deserialize"),
|
|
PlanType::SelfServeBusinessUsageBased
|
|
);
|
|
assert_eq!(
|
|
serde_json::from_str::<PlanType>("\"prolite\"").expect("prolite should deserialize"),
|
|
PlanType::ProLite
|
|
);
|
|
assert_eq!(
|
|
serde_json::from_str::<PlanType>("\"enterprise_cbp_usage_based\"")
|
|
.expect("enterprise cbp usage based should deserialize"),
|
|
PlanType::EnterpriseCbpUsageBased
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn plan_family_helpers_group_usage_based_variants_with_existing_plans() {
|
|
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::Business.is_business_like(), true);
|
|
assert_eq!(PlanType::EnterpriseCbpUsageBased.is_business_like(), true);
|
|
assert_eq!(PlanType::Team.is_business_like(), false);
|
|
}
|
|
|
|
#[test]
|
|
fn workspace_account_helper_includes_usage_based_workspace_plans() {
|
|
assert_eq!(PlanType::Team.is_workspace_account(), true);
|
|
assert_eq!(
|
|
PlanType::SelfServeBusinessUsageBased.is_workspace_account(),
|
|
true
|
|
);
|
|
assert_eq!(PlanType::Business.is_workspace_account(), true);
|
|
assert_eq!(
|
|
PlanType::EnterpriseCbpUsageBased.is_workspace_account(),
|
|
true
|
|
);
|
|
assert_eq!(PlanType::Enterprise.is_workspace_account(), true);
|
|
assert_eq!(PlanType::Edu.is_workspace_account(), true);
|
|
assert_eq!(PlanType::Pro.is_workspace_account(), false);
|
|
}
|
|
}
|