diff --git a/codex-rs/app-server-protocol/schema/json/ClientRequest.json b/codex-rs/app-server-protocol/schema/json/ClientRequest.json index d391cac16546..5da27a074cac 100644 --- a/codex-rs/app-server-protocol/schema/json/ClientRequest.json +++ b/codex-rs/app-server-protocol/schema/json/ClientRequest.json @@ -1543,6 +1543,31 @@ ], "title": "ChatgptAuthTokensLoginAccountParams", "type": "object" + }, + { + "description": "[UNSTABLE] Managed Amazon Bedrock login is experimental.", + "properties": { + "apiKey": { + "type": "string" + }, + "region": { + "type": "string" + }, + "type": { + "enum": [ + "amazonBedrock" + ], + "title": "AmazonBedrockLoginAccountParamsType", + "type": "string" + } + }, + "required": [ + "apiKey", + "region", + "type" + ], + "title": "AmazonBedrockLoginAccountParams", + "type": "object" } ] }, 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 b7526b080da1..a0f893b7f818 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 @@ -11591,6 +11591,31 @@ ], "title": "ChatgptAuthTokensv2::LoginAccountParams", "type": "object" + }, + { + "description": "[UNSTABLE] Managed Amazon Bedrock login is experimental.", + "properties": { + "apiKey": { + "type": "string" + }, + "region": { + "type": "string" + }, + "type": { + "enum": [ + "amazonBedrock" + ], + "title": "AmazonBedrockv2::LoginAccountParamsType", + "type": "string" + } + }, + "required": [ + "apiKey", + "region", + "type" + ], + "title": "AmazonBedrockv2::LoginAccountParams", + "type": "object" } ], "title": "LoginAccountParams" @@ -11684,6 +11709,22 @@ ], "title": "ChatgptAuthTokensv2::LoginAccountResponse", "type": "object" + }, + { + "properties": { + "type": { + "enum": [ + "amazonBedrock" + ], + "title": "AmazonBedrockv2::LoginAccountResponseType", + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "AmazonBedrockv2::LoginAccountResponse", + "type": "object" } ], "title": "LoginAccountResponse" 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 e1afc7883a51..0fe34feff3cb 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 @@ -7995,6 +7995,31 @@ ], "title": "ChatgptAuthTokensv2::LoginAccountParams", "type": "object" + }, + { + "description": "[UNSTABLE] Managed Amazon Bedrock login is experimental.", + "properties": { + "apiKey": { + "type": "string" + }, + "region": { + "type": "string" + }, + "type": { + "enum": [ + "amazonBedrock" + ], + "title": "AmazonBedrockv2::LoginAccountParamsType", + "type": "string" + } + }, + "required": [ + "apiKey", + "region", + "type" + ], + "title": "AmazonBedrockv2::LoginAccountParams", + "type": "object" } ], "title": "LoginAccountParams" @@ -8088,6 +8113,22 @@ ], "title": "ChatgptAuthTokensv2::LoginAccountResponse", "type": "object" + }, + { + "properties": { + "type": { + "enum": [ + "amazonBedrock" + ], + "title": "AmazonBedrockv2::LoginAccountResponseType", + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "AmazonBedrockv2::LoginAccountResponse", + "type": "object" } ], "title": "LoginAccountResponse" diff --git a/codex-rs/app-server-protocol/schema/json/v2/LoginAccountParams.json b/codex-rs/app-server-protocol/schema/json/v2/LoginAccountParams.json index e6c82237d315..0c89965ab6cc 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/LoginAccountParams.json +++ b/codex-rs/app-server-protocol/schema/json/v2/LoginAccountParams.json @@ -112,6 +112,31 @@ ], "title": "ChatgptAuthTokensv2::LoginAccountParams", "type": "object" + }, + { + "description": "[UNSTABLE] Managed Amazon Bedrock login is experimental.", + "properties": { + "apiKey": { + "type": "string" + }, + "region": { + "type": "string" + }, + "type": { + "enum": [ + "amazonBedrock" + ], + "title": "AmazonBedrockv2::LoginAccountParamsType", + "type": "string" + } + }, + "required": [ + "apiKey", + "region", + "type" + ], + "title": "AmazonBedrockv2::LoginAccountParams", + "type": "object" } ], "title": "LoginAccountParams" diff --git a/codex-rs/app-server-protocol/schema/json/v2/LoginAccountResponse.json b/codex-rs/app-server-protocol/schema/json/v2/LoginAccountResponse.json index a800bffccd94..802440d637bf 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/LoginAccountResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/LoginAccountResponse.json @@ -87,6 +87,22 @@ ], "title": "ChatgptAuthTokensv2::LoginAccountResponse", "type": "object" + }, + { + "properties": { + "type": { + "enum": [ + "amazonBedrock" + ], + "title": "AmazonBedrockv2::LoginAccountResponseType", + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "AmazonBedrockv2::LoginAccountResponse", + "type": "object" } ], "title": "LoginAccountResponse" diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/LoginAccountParams.ts b/codex-rs/app-server-protocol/schema/typescript/v2/LoginAccountParams.ts index 1606f167fa3d..41d6075ef01a 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/LoginAccountParams.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/LoginAccountParams.ts @@ -19,4 +19,4 @@ chatgptAccountId: string, * When `null`, Codex attempts to derive the plan type from access-token * claims. If unavailable, the plan defaults to `unknown`. */ -chatgptPlanType?: string | null, }; +chatgptPlanType?: string | null, } | { "type": "amazonBedrock", apiKey: string, region: string, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/LoginAccountResponse.ts b/codex-rs/app-server-protocol/schema/typescript/v2/LoginAccountResponse.ts index 34bccd6578e1..5a9f34ead3c1 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/LoginAccountResponse.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/LoginAccountResponse.ts @@ -14,4 +14,4 @@ verificationUrl: string, /** * One-time code the user must enter after signing in. */ -userCode: string, } | { "type": "chatgptAuthTokens", }; +userCode: string, } | { "type": "chatgptAuthTokens", } | { "type": "amazonBedrock", }; diff --git a/codex-rs/app-server-protocol/src/protocol/common.rs b/codex-rs/app-server-protocol/src/protocol/common.rs index 27a8b0205da7..bf56f7f28af1 100644 --- a/codex-rs/app-server-protocol/src/protocol/common.rs +++ b/codex-rs/app-server-protocol/src/protocol/common.rs @@ -2722,6 +2722,34 @@ mod tests { Ok(()) } + #[test] + fn serialize_account_login_amazon_bedrock() -> Result<()> { + let request = ClientRequest::LoginAccount { + request_id: RequestId::Integer(2), + params: v2::LoginAccountParams::AmazonBedrock { + api_key: "secret".to_string(), + region: "us-west-2".to_string(), + }, + }; + assert_eq!( + json!({ + "method": "account/login/start", + "id": 2, + "params": { + "type": "amazonBedrock", + "apiKey": "secret", + "region": "us-west-2" + } + }), + serde_json::to_value(&request)?, + ); + assert_eq!( + json!({"type": "amazonBedrock"}), + serde_json::to_value(v2::LoginAccountResponse::AmazonBedrock {})?, + ); + Ok(()) + } + #[test] fn serialize_account_login_chatgpt() -> Result<()> { let request = ClientRequest::LoginAccount { diff --git a/codex-rs/app-server-protocol/src/protocol/v2/account.rs b/codex-rs/app-server-protocol/src/protocol/v2/account.rs index 44551e400d55..ec44ef3959b7 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2/account.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2/account.rs @@ -105,6 +105,11 @@ pub enum LoginAccountParams { #[ts(optional = nullable)] chatgpt_plan_type: Option, }, + /// [UNSTABLE] Managed Amazon Bedrock login is experimental. + #[experimental("account/login/start.amazonBedrock")] + #[serde(rename = "amazonBedrock", rename_all = "camelCase")] + #[ts(rename = "amazonBedrock", rename_all = "camelCase")] + AmazonBedrock { api_key: String, region: String }, } #[derive(Serialize, Deserialize, Debug, Default, Clone, Copy, PartialEq, Eq, JsonSchema, TS)] @@ -148,6 +153,9 @@ pub enum LoginAccountResponse { #[serde(rename = "chatgptAuthTokens", rename_all = "camelCase")] #[ts(rename = "chatgptAuthTokens", rename_all = "camelCase")] ChatgptAuthTokens {}, + #[serde(rename = "amazonBedrock", rename_all = "camelCase")] + #[ts(rename = "amazonBedrock", rename_all = "camelCase")] + AmazonBedrock {}, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] diff --git a/codex-rs/app-server/README.md b/codex-rs/app-server/README.md index 6ee6baf2dc6c..6280cf520409 100644 --- a/codex-rs/app-server/README.md +++ b/codex-rs/app-server/README.md @@ -1921,16 +1921,17 @@ Codex supports these authentication modes. The current mode is surfaced in `acco - **API key (`apiKey`)**: Caller supplies an OpenAI API key via `account/login/start` with `type: "apiKey"`. The API key is saved and used for API requests. - **ChatGPT managed (`chatgpt`)** (recommended): Codex owns the ChatGPT OAuth flow and refresh tokens. Start via `account/login/start` with `type: "chatgpt"` for the browser flow or `type: "chatgptDeviceCode"` for device code; Codex persists tokens to disk and refreshes them automatically. +- **Codex managed Amazon Bedrock auth (`amazonBedrock`, experimental)**: Caller supplies an Amazon Bedrock API key and region via `account/login/start` with `type: "amazonBedrock"`. The client must enable the `experimentalApi` initialization capability for Codex-managed Amazon Bedrock login. Codex replaces the current primary auth with the Bedrock credential and writes `model_provider = "amazon-bedrock"` to the user config. - **Personal access token (`personalAccessToken`)**: Codex uses a ChatGPT-backed personal access token loaded outside the app-server login RPCs, such as with `codex login --with-access-token` or `CODEX_ACCESS_TOKEN`. ### API Overview - `account/read` — fetch current account info; optionally refresh tokens. -- `account/login/start` — begin login (`apiKey`, `chatgpt`, `chatgptDeviceCode`). +- `account/login/start` — begin login (`apiKey`, `chatgpt`, `chatgptDeviceCode`, `amazonBedrock`). - `account/login/completed` (notify) — emitted when a login attempt finishes (success or error). - `account/login/cancel` — cancel a pending managed ChatGPT login by `loginId`. - `account/logout` — sign out; triggers `account/updated`. -- `account/updated` (notify) — emitted whenever auth mode changes (`authMode`: `apikey`, `chatgpt`, `personalAccessToken`, or `null`) and includes the current ChatGPT `planType` when available. +- `account/updated` (notify) — emitted whenever auth mode changes (`authMode`: `apikey`, `bedrockApiKey`, `chatgpt`, `personalAccessToken`, or `null`) and includes the current ChatGPT `planType` when available. - `account/rateLimits/read` — fetch ChatGPT rate limits, an optional effective monthly credit limit, and the earned rate-limit resets currently available, including expiry details when provided by the backend. Rate-limit updates arrive via `account/rateLimits/updated` (notify); reset-credit data is snapshot-only. - `account/rateLimitResetCredit/consume` — consume one earned reset using a caller-provided idempotency key, optionally selecting a reset-credit ID returned by `account/rateLimits/read`. - `account/usage/read` — fetch ChatGPT account token-activity summary and daily buckets. @@ -2006,6 +2007,30 @@ Field notes: { "method": "account/updated", "params": { "authMode": "chatgpt", "planType": "plus" } } ``` +### 3) Log in with an Amazon Bedrock API key + +This experimental flow requires the client to initialize with `experimentalApi: true`. + +1. Send: + ```json + { + "method": "account/login/start", + "id": 3, + "params": { "type": "amazonBedrock", "apiKey": "…", "region": "us-west-2" } + } + ``` +2. Expect: + ```json + { "id": 3, "result": { "type": "amazonBedrock" } } + ``` +3. Notifications: + ```json + { "method": "account/login/completed", "params": { "loginId": null, "success": true, "error": null } } + { "method": "account/updated", "params": { "authMode": "bedrockApiKey", "planType": null } } + ``` + +Codex stores the key and region as the primary Codex auth, replacing any previously stored login, and writes `model_provider = "amazon-bedrock"` to the active user config. Existing loaded sessions keep their current provider selection, so clients should restart the app-server before sending more model requests. This limitation will be addressed in a follow-up. + ### 4) Log in with ChatGPT (device code flow) 1. Start: diff --git a/codex-rs/app-server/src/request_processors/account_processor.rs b/codex-rs/app-server/src/request_processors/account_processor.rs index f4acc5a8e45a..d98977ce580b 100644 --- a/codex-rs/app-server/src/request_processors/account_processor.rs +++ b/codex-rs/app-server/src/request_processors/account_processor.rs @@ -293,6 +293,9 @@ impl AccountRequestProcessor { ) .await; } + LoginAccountParams::AmazonBedrock { .. } => { + return Err(invalid_request("Amazon Bedrock login is not implemented")); + } } Ok(()) }