use crate::protocol::common::AuthMode;use codex_experimental_api_macros::ExperimentalApi;use codex_protocol::account::AmazonBedrockCredentialSource;use codex_protocol::account::PlanType;use codex_protocol::account::ProviderAccount;use codex_protocol::protocol::CreditsSnapshot as CoreCreditsSnapshot;use codex_protocol::protocol::RateLimitReachedType as CoreRateLimitReachedType;use codex_protocol::protocol::RateLimitSnapshot as CoreRateLimitSnapshot;use codex_protocol::protocol::RateLimitWindow as CoreRateLimitWindow;use codex_protocol::protocol::SpendControlLimitSnapshot as CoreSpendControlLimitSnapshot;use schemars::JsonSchema;use serde::Deserialize;use serde::Serialize;use std::collections::HashMap;use ts_rs::TS;#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(tag = "type", rename_all = "camelCase")]#[ts(tag = "type")]#[ts(export_to = "v2/")]pub enum Account { #[serde(rename = "apiKey", rename_all = "camelCase")] #[ts(rename = "apiKey", rename_all = "camelCase")] ApiKey {}, #[serde(rename = "chatgpt", rename_all = "camelCase")] #[ts(rename = "chatgpt", rename_all = "camelCase")] Chatgpt { email: String, plan_type: PlanType }, #[serde(rename = "amazonBedrock", rename_all = "camelCase")] #[ts(rename = "amazonBedrock", rename_all = "camelCase")] AmazonBedrock { #[serde(default = "default_bedrock_credential_source")] credential_source: AmazonBedrockCredentialSource, },}fn default_bedrock_credential_source() -> AmazonBedrockCredentialSource { AmazonBedrockCredentialSource::AwsManaged}impl From<ProviderAccount> for Account { fn from(account: ProviderAccount) -> Self { match account { ProviderAccount::ApiKey => Self::ApiKey {}, ProviderAccount::Chatgpt { email, plan_type } => Self::Chatgpt { email, plan_type }, ProviderAccount::AmazonBedrock { credential_source } => { Self::AmazonBedrock { credential_source } } } }}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS, ExperimentalApi)]#[serde(tag = "type")]#[ts(tag = "type")]#[ts(export_to = "v2/")]pub enum LoginAccountParams { #[serde(rename = "apiKey", rename_all = "camelCase")] #[ts(rename = "apiKey", rename_all = "camelCase")] ApiKey { #[serde(rename = "apiKey")] #[ts(rename = "apiKey")] api_key: String, }, #[serde(rename = "chatgpt", rename_all = "camelCase")] #[ts(rename = "chatgpt", rename_all = "camelCase")] Chatgpt { #[serde(default, skip_serializing_if = "std::ops::Not::not")] codex_streamlined_login: bool, }, #[serde(rename = "chatgptDeviceCode")] #[ts(rename = "chatgptDeviceCode")] ChatgptDeviceCode, /// [UNSTABLE] FOR OPENAI INTERNAL USE ONLY - DO NOT USE. /// The access token must contain the same scopes that Codex-managed ChatGPT auth tokens have. #[experimental("account/login/start.chatgptAuthTokens")] #[serde(rename = "chatgptAuthTokens", rename_all = "camelCase")] #[ts(rename = "chatgptAuthTokens", rename_all = "camelCase")] ChatgptAuthTokens { /// Access token (JWT) supplied by the client. /// This token is used for backend API requests and email extraction. access_token: String, /// Workspace/account identifier supplied by the client. chatgpt_account_id: String, /// Optional plan type supplied by the client. /// /// When `null`, Codex attempts to derive the plan type from access-token /// claims. If unavailable, the plan defaults to `unknown`. #[ts(optional = nullable)] chatgpt_plan_type: Option<String>, },}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(tag = "type", rename_all = "camelCase")]#[ts(tag = "type")]#[ts(export_to = "v2/")]pub enum LoginAccountResponse { #[serde(rename = "apiKey", rename_all = "camelCase")] #[ts(rename = "apiKey", rename_all = "camelCase")] ApiKey {}, #[serde(rename = "chatgpt", rename_all = "camelCase")] #[ts(rename = "chatgpt", rename_all = "camelCase")] Chatgpt { // Use plain String for identifiers to avoid TS/JSON Schema quirks around uuid-specific types. // Convert to/from UUIDs at the application layer as needed. login_id: String, /// URL the client should open in a browser to initiate the OAuth flow. auth_url: String, }, #[serde(rename = "chatgptDeviceCode", rename_all = "camelCase")] #[ts(rename = "chatgptDeviceCode", rename_all = "camelCase")] ChatgptDeviceCode { // Use plain String for identifiers to avoid TS/JSON Schema quirks around uuid-specific types. // Convert to/from UUIDs at the application layer as needed. login_id: String, /// URL the client should open in a browser to complete device code authorization. verification_url: String, /// One-time code the user must enter after signing in. user_code: String, }, #[serde(rename = "chatgptAuthTokens", rename_all = "camelCase")] #[ts(rename = "chatgptAuthTokens", rename_all = "camelCase")] ChatgptAuthTokens {},}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct CancelLoginAccountParams { pub login_id: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub enum CancelLoginAccountStatus { Canceled, NotFound,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct CancelLoginAccountResponse { pub status: CancelLoginAccountStatus,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct AccountSessionsAddParams { #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub switch_to_added_account: bool,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct AccountSessionsListParams { #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub refresh_workspace_metadata: bool,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct AccountSessionsLogoutParams { pub session_id: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct AccountSessionsSwitchParams { pub session_id: String, pub account_id: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct AccountSessionsResponse { pub active_session_id: Option<String>, pub sessions: Vec<AccountSession>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct AccountSession { pub session_id: String, pub email: Option<String>, pub user_id: Option<String>, pub display_name: Option<String>, pub image_url: Option<String>, pub last_used_at: i64, pub is_active: bool, pub selected_workspace_account_id: Option<String>, pub workspaces: Vec<AccountSessionWorkspace>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct AccountSessionWorkspace { pub account_id: String, pub name: Option<String>, pub image_url: Option<String>, pub kind: Option<AccountSessionWorkspaceKind>,}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub enum AccountSessionWorkspaceKind { Personal, Workspace,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct LogoutAccountResponse {}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub enum ChatgptAuthTokensRefreshReason { /// Codex attempted a backend request and received `401 Unauthorized`. Unauthorized,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ChatgptAuthTokensRefreshParams { pub reason: ChatgptAuthTokensRefreshReason, /// Workspace/account identifier that Codex was previously using. /// /// Clients that manage multiple accounts/workspaces can use this as a hint /// to refresh the token for the correct workspace. /// /// This may be `null` when the prior auth state did not include a workspace /// identifier (`chatgpt_account_id`). #[ts(optional = nullable)] pub previous_account_id: Option<String>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ChatgptAuthTokensRefreshResponse { pub access_token: String, pub chatgpt_account_id: String, pub chatgpt_plan_type: Option<String>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct GetAccountRateLimitsResponse { /// Backward-compatible single-bucket view; mirrors the historical payload. pub rate_limits: RateLimitSnapshot, /// Multi-bucket view keyed by metered `limit_id` (for example, `codex`). pub rate_limits_by_limit_id: Option<HashMap<String, RateLimitSnapshot>>, pub rate_limit_reset_credits: Option<RateLimitResetCreditsSummary>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct RateLimitResetCreditsSummary { pub available_count: i64,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ConsumeAccountRateLimitResetCreditParams { /// Identifies one logical reset attempt. A UUID is recommended; reuse the same value when /// retrying that attempt. pub idempotency_key: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct ConsumeAccountRateLimitResetCreditResponse { pub outcome: ConsumeAccountRateLimitResetCreditOutcome,}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/", rename_all = "camelCase")]pub enum ConsumeAccountRateLimitResetCreditOutcome { /// A reset credit was consumed and the eligible rate-limit windows were reset. Reset, /// No current rate-limit window is eligible for a reset. NothingToReset, /// The account has no earned reset credits available. NoCredit, /// The same idempotency key already completed a reset successfully. AlreadyRedeemed,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct GetAccountTokenUsageResponse { pub summary: AccountTokenUsageSummary, pub daily_usage_buckets: Option<Vec<AccountTokenUsageDailyBucket>>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct AccountTokenUsageSummary { pub lifetime_tokens: Option<i64>, pub peak_daily_tokens: Option<i64>, pub longest_running_turn_sec: Option<i64>, pub current_streak_days: Option<i64>, pub longest_streak_days: Option<i64>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct AccountTokenUsageDailyBucket { pub start_date: String, pub tokens: i64,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct SendAddCreditsNudgeEmailParams { pub credit_type: AddCreditsNudgeCreditType,}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "snake_case")]#[ts(export_to = "v2/", rename_all = "snake_case")]pub enum AddCreditsNudgeCreditType { Credits, UsageLimit,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct SendAddCreditsNudgeEmailResponse { pub status: AddCreditsNudgeEmailStatus,}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "snake_case")]#[ts(export_to = "v2/", rename_all = "snake_case")]pub enum AddCreditsNudgeEmailStatus { Sent, CooldownActive,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct GetAccountParams { /// When `true`, requests a proactive token refresh before returning. /// /// In managed auth mode this triggers the normal refresh-token flow. In /// external auth mode this flag is ignored. Clients should refresh tokens /// themselves and call `account/login/start` with `chatgptAuthTokens`. #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub refresh_token: bool,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct GetAccountResponse { pub account: Option<Account>, pub requires_openai_auth: bool,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct AccountUpdatedNotification { pub auth_mode: Option<AuthMode>, pub plan_type: Option<PlanType>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]/// Sparse rolling rate-limit update.////// Clients should merge available values into the most recent `account/rateLimits/read` response/// or refetch that snapshot. Nullable account metadata may be unavailable in a rolling update and/// does not clear a previously observed value.pub struct AccountRateLimitsUpdatedNotification { pub rate_limits: RateLimitSnapshot,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct RateLimitSnapshot { pub limit_id: Option<String>, pub limit_name: Option<String>, pub primary: Option<RateLimitWindow>, pub secondary: Option<RateLimitWindow>, pub credits: Option<CreditsSnapshot>, pub individual_limit: Option<SpendControlLimitSnapshot>, pub plan_type: Option<PlanType>, pub rate_limit_reached_type: Option<RateLimitReachedType>,}impl From<CoreRateLimitSnapshot> for RateLimitSnapshot { fn from(value: CoreRateLimitSnapshot) -> Self { Self { limit_id: value.limit_id, limit_name: value.limit_name, primary: value.primary.map(RateLimitWindow::from), secondary: value.secondary.map(RateLimitWindow::from), credits: value.credits.map(CreditsSnapshot::from), individual_limit: value.individual_limit.map(SpendControlLimitSnapshot::from), plan_type: value.plan_type, rate_limit_reached_type: value .rate_limit_reached_type .map(RateLimitReachedType::from), } }}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "snake_case")]#[ts(export_to = "v2/", rename_all = "snake_case")]pub enum RateLimitReachedType { RateLimitReached, WorkspaceOwnerCreditsDepleted, WorkspaceMemberCreditsDepleted, WorkspaceOwnerUsageLimitReached, WorkspaceMemberUsageLimitReached,}impl From<CoreRateLimitReachedType> for RateLimitReachedType { fn from(value: CoreRateLimitReachedType) -> Self { match value { CoreRateLimitReachedType::RateLimitReached => Self::RateLimitReached, CoreRateLimitReachedType::WorkspaceOwnerCreditsDepleted => { Self::WorkspaceOwnerCreditsDepleted } CoreRateLimitReachedType::WorkspaceMemberCreditsDepleted => { Self::WorkspaceMemberCreditsDepleted } CoreRateLimitReachedType::WorkspaceOwnerUsageLimitReached => { Self::WorkspaceOwnerUsageLimitReached } CoreRateLimitReachedType::WorkspaceMemberUsageLimitReached => { Self::WorkspaceMemberUsageLimitReached } } }}impl From<RateLimitReachedType> for CoreRateLimitReachedType { fn from(value: RateLimitReachedType) -> Self { match value { RateLimitReachedType::RateLimitReached => Self::RateLimitReached, RateLimitReachedType::WorkspaceOwnerCreditsDepleted => { Self::WorkspaceOwnerCreditsDepleted } RateLimitReachedType::WorkspaceMemberCreditsDepleted => { Self::WorkspaceMemberCreditsDepleted } RateLimitReachedType::WorkspaceOwnerUsageLimitReached => { Self::WorkspaceOwnerUsageLimitReached } RateLimitReachedType::WorkspaceMemberUsageLimitReached => { Self::WorkspaceMemberUsageLimitReached } } }}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct RateLimitWindow { pub used_percent: i32, #[ts(type = "number | null")] pub window_duration_mins: Option<i64>, #[ts(type = "number | null")] pub resets_at: Option<i64>,}impl From<CoreRateLimitWindow> for RateLimitWindow { fn from(value: CoreRateLimitWindow) -> Self { Self { used_percent: value.used_percent.round() as i32, window_duration_mins: value.window_minutes, resets_at: value.resets_at, } }}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct CreditsSnapshot { pub has_credits: bool, pub unlimited: bool, pub balance: Option<String>,}impl From<CoreCreditsSnapshot> for CreditsSnapshot { fn from(value: CoreCreditsSnapshot) -> Self { Self { has_credits: value.has_credits, unlimited: value.unlimited, balance: value.balance, } }}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct SpendControlLimitSnapshot { pub limit: String, pub used: String, pub remaining_percent: i32, #[ts(type = "number")] pub resets_at: i64,}impl From<CoreSpendControlLimitSnapshot> for SpendControlLimitSnapshot { fn from(value: CoreSpendControlLimitSnapshot) -> Self { Self { limit: value.limit, used: value.used, remaining_percent: value.remaining_percent, resets_at: value.resets_at, } }}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct AccountLoginCompletedNotification { // Use plain String for identifiers to avoid TS/JSON Schema quirks around uuid-specific types. // Convert to/from UUIDs at the application layer as needed. pub login_id: Option<String>, pub success: bool, pub error: Option<String>,}