mirror of
https://github.com/openai/codex.git
synced 2026-11-03 19:53:25 +00:00
changes
This commit is contained in:
@@ -1447,6 +1447,7 @@ mod tests {
|
||||
result: serde_json::to_value(GetAccountResponse {
|
||||
account: None,
|
||||
requires_openai_auth: false,
|
||||
codex_managed_auth: false,
|
||||
})
|
||||
.expect("response should serialize"),
|
||||
}),
|
||||
@@ -1500,6 +1501,7 @@ mod tests {
|
||||
result: serde_json::to_value(GetAccountResponse {
|
||||
account: None,
|
||||
requires_openai_auth: false,
|
||||
codex_managed_auth: false,
|
||||
})
|
||||
.expect("response should serialize"),
|
||||
}),
|
||||
@@ -1575,6 +1577,7 @@ mod tests {
|
||||
GetAccountResponse {
|
||||
account: None,
|
||||
requires_openai_auth: false,
|
||||
codex_managed_auth: false,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1676,6 +1679,7 @@ mod tests {
|
||||
result: serde_json::to_value(GetAccountResponse {
|
||||
account: None,
|
||||
requires_openai_auth: false,
|
||||
codex_managed_auth: false,
|
||||
})
|
||||
.expect("response should serialize"),
|
||||
}),
|
||||
@@ -1729,6 +1733,7 @@ mod tests {
|
||||
GetAccountResponse {
|
||||
account: None,
|
||||
requires_openai_auth: false,
|
||||
codex_managed_auth: false,
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
+3
-3
@@ -288,8 +288,8 @@
|
||||
"environmentId": {
|
||||
"default": null,
|
||||
"type": [
|
||||
"null",
|
||||
"string"
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"itemId": {
|
||||
@@ -326,4 +326,4 @@
|
||||
],
|
||||
"title": "PermissionsRequestApprovalParams",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -1593,8 +1593,8 @@
|
||||
"environmentId": {
|
||||
"default": null,
|
||||
"type": [
|
||||
"null",
|
||||
"string"
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"itemId": {
|
||||
@@ -2005,4 +2005,4 @@
|
||||
}
|
||||
],
|
||||
"title": "ServerRequest"
|
||||
}
|
||||
}
|
||||
+39
-3
@@ -3786,8 +3786,8 @@
|
||||
"environmentId": {
|
||||
"default": null,
|
||||
"type": [
|
||||
"null",
|
||||
"string"
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"itemId": {
|
||||
@@ -5684,6 +5684,9 @@
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"authSource": {
|
||||
"$ref": "#/definitions/v2/AmazonBedrockAuthSource"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"amazonBedrock"
|
||||
@@ -5693,6 +5696,7 @@
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"authSource",
|
||||
"type"
|
||||
],
|
||||
"title": "AmazonBedrockAccount",
|
||||
@@ -5903,6 +5907,13 @@
|
||||
"AgentPath": {
|
||||
"type": "string"
|
||||
},
|
||||
"AmazonBedrockAuthSource": {
|
||||
"enum": [
|
||||
"codexManaged",
|
||||
"awsManaged"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"AnalyticsConfig": {
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
@@ -7702,6 +7713,31 @@
|
||||
"title": "ProjectConfigLayerSource",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Local Codex-owned provider state, such as a provider activated by managed auth.",
|
||||
"properties": {
|
||||
"file": {
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
"provider": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"providerState"
|
||||
],
|
||||
"title": "ProviderStateConfigLayerSourceType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file",
|
||||
"provider",
|
||||
"type"
|
||||
],
|
||||
"title": "ProviderStateConfigLayerSource",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Session-layer overrides supplied via `-c`/`--config`.",
|
||||
"properties": {
|
||||
@@ -19279,4 +19315,4 @@
|
||||
},
|
||||
"title": "CodexAppServerProtocol",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
+36
@@ -49,6 +49,9 @@
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"authSource": {
|
||||
"$ref": "#/definitions/AmazonBedrockAuthSource"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"amazonBedrock"
|
||||
@@ -58,6 +61,7 @@
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"authSource",
|
||||
"type"
|
||||
],
|
||||
"title": "AmazonBedrockAccount",
|
||||
@@ -268,6 +272,13 @@
|
||||
"AgentPath": {
|
||||
"type": "string"
|
||||
},
|
||||
"AmazonBedrockAuthSource": {
|
||||
"enum": [
|
||||
"codexManaged",
|
||||
"awsManaged"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"AnalyticsConfig": {
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
@@ -4064,6 +4075,31 @@
|
||||
"title": "ProjectConfigLayerSource",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Local Codex-owned provider state, such as a provider activated by managed auth.",
|
||||
"properties": {
|
||||
"file": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"provider": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"providerState"
|
||||
],
|
||||
"title": "ProviderStateConfigLayerSourceType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file",
|
||||
"provider",
|
||||
"type"
|
||||
],
|
||||
"title": "ProviderStateConfigLayerSource",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Session-layer overrides supplied via `-c`/`--config`.",
|
||||
"properties": {
|
||||
|
||||
@@ -589,6 +589,31 @@
|
||||
"title": "ProjectConfigLayerSource",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Local Codex-owned provider state, such as a provider activated by managed auth.",
|
||||
"properties": {
|
||||
"file": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"provider": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"providerState"
|
||||
],
|
||||
"title": "ProviderStateConfigLayerSourceType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file",
|
||||
"provider",
|
||||
"type"
|
||||
],
|
||||
"title": "ProviderStateConfigLayerSource",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Session-layer overrides supplied via `-c`/`--config`.",
|
||||
"properties": {
|
||||
|
||||
@@ -154,6 +154,31 @@
|
||||
"title": "ProjectConfigLayerSource",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Local Codex-owned provider state, such as a provider activated by managed auth.",
|
||||
"properties": {
|
||||
"file": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"provider": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"providerState"
|
||||
],
|
||||
"title": "ProviderStateConfigLayerSourceType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file",
|
||||
"provider",
|
||||
"type"
|
||||
],
|
||||
"title": "ProviderStateConfigLayerSource",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Session-layer overrides supplied via `-c`/`--config`.",
|
||||
"properties": {
|
||||
|
||||
@@ -45,6 +45,9 @@
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"authSource": {
|
||||
"$ref": "#/definitions/AmazonBedrockAuthSource"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"amazonBedrock"
|
||||
@@ -54,6 +57,7 @@
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"authSource",
|
||||
"type"
|
||||
],
|
||||
"title": "AmazonBedrockAccount",
|
||||
@@ -61,6 +65,13 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"AmazonBedrockAuthSource": {
|
||||
"enum": [
|
||||
"codexManaged",
|
||||
"awsManaged"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PlanType": {
|
||||
"enum": [
|
||||
"free",
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { PlanType } from "../PlanType";
|
||||
import type { AmazonBedrockAuthSource } from "./AmazonBedrockAuthSource";
|
||||
|
||||
export type Account = { "type": "apiKey", } | { "type": "chatgpt", email: string, planType: PlanType, } | { "type": "amazonBedrock", };
|
||||
export type Account = { "type": "apiKey", } | { "type": "chatgpt", email: string, planType: PlanType, } | { "type": "amazonBedrock", authSource: AmazonBedrockAuthSource, };
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type AmazonBedrockAuthSource = "codexManaged" | "awsManaged";
|
||||
@@ -28,4 +28,4 @@ file: AbsolutePathBuf,
|
||||
* Name of the selected profile-v2 config layered on top of the base
|
||||
* user config, when this layer represents one.
|
||||
*/
|
||||
profile: string | null, } | { "type": "project", dotCodexFolder: AbsolutePathBuf, } | { "type": "sessionFlags" } | { "type": "legacyManagedConfigTomlFromFile", file: AbsolutePathBuf, } | { "type": "legacyManagedConfigTomlFromMdm" };
|
||||
profile: string | null, } | { "type": "project", dotCodexFolder: AbsolutePathBuf, } | { "type": "providerState", provider: string, file: AbsolutePathBuf, } | { "type": "sessionFlags" } | { "type": "legacyManagedConfigTomlFromFile", file: AbsolutePathBuf, } | { "type": "legacyManagedConfigTomlFromMdm" };
|
||||
|
||||
@@ -13,6 +13,7 @@ export type { AdditionalFileSystemPermissions } from "./AdditionalFileSystemPerm
|
||||
export type { AdditionalNetworkPermissions } from "./AdditionalNetworkPermissions";
|
||||
export type { AdditionalPermissionProfile } from "./AdditionalPermissionProfile";
|
||||
export type { AgentMessageDeltaNotification } from "./AgentMessageDeltaNotification";
|
||||
export type { AmazonBedrockAuthSource } from "./AmazonBedrockAuthSource";
|
||||
export type { AnalyticsConfig } from "./AnalyticsConfig";
|
||||
export type { AppBranding } from "./AppBranding";
|
||||
export type { AppInfo } from "./AppInfo";
|
||||
|
||||
@@ -241,6 +241,7 @@ pub struct GetAccountParams {
|
||||
pub struct GetAccountResponse {
|
||||
pub account: Option<Account>,
|
||||
pub requires_openai_auth: bool,
|
||||
pub codex_managed_auth: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
|
||||
@@ -80,6 +80,15 @@ pub enum ConfigLayerSource {
|
||||
dot_codex_folder: AbsolutePathBuf,
|
||||
},
|
||||
|
||||
/// Local Codex-owned provider state, such as a provider activated by
|
||||
/// managed auth.
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(rename_all = "camelCase")]
|
||||
ProviderState {
|
||||
provider: String,
|
||||
file: AbsolutePathBuf,
|
||||
},
|
||||
|
||||
/// Session-layer overrides supplied via `-c`/`--config`.
|
||||
SessionFlags,
|
||||
|
||||
@@ -112,6 +121,7 @@ impl ConfigLayerSource {
|
||||
}
|
||||
}
|
||||
ConfigLayerSource::Project { .. } => 25,
|
||||
ConfigLayerSource::ProviderState { .. } => 28,
|
||||
ConfigLayerSource::SessionFlags => 30,
|
||||
ConfigLayerSource::LegacyManagedConfigTomlFromFile { .. } => 40,
|
||||
ConfigLayerSource::LegacyManagedConfigTomlFromMdm => 50,
|
||||
|
||||
@@ -1773,7 +1773,7 @@ Codex supports these authentication modes. The current mode is surfaced in `acco
|
||||
- `account/login/start` — begin login (`apiKey`, `chatgpt`, `chatgptDeviceCode`).
|
||||
- `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/logout` — sign out; triggers `account/updated` when Codex-managed auth changes.
|
||||
- `account/updated` (notify) — emitted whenever auth mode changes (`authMode`: `apikey`, `chatgpt`, or `null`) and includes the current ChatGPT `planType` when available.
|
||||
- `account/rateLimits/read` — fetch ChatGPT rate limits and an optional effective monthly credit limit; updates arrive via `account/rateLimits/updated` (notify).
|
||||
- `account/rateLimits/updated` (notify) — emitted whenever a user's ChatGPT rate limits change. This is a sparse rolling update; merge available values into the most recent `account/rateLimits/read` response or refetch that snapshot.
|
||||
@@ -1792,16 +1792,17 @@ Request:
|
||||
Response examples:
|
||||
|
||||
```json
|
||||
{ "id": 1, "result": { "account": null, "requiresOpenaiAuth": false } } // No OpenAI auth needed (e.g., OSS/local models)
|
||||
{ "id": 1, "result": { "account": null, "requiresOpenaiAuth": true } } // OpenAI auth required (typical for OpenAI-hosted models)
|
||||
{ "id": 1, "result": { "account": { "type": "apiKey" }, "requiresOpenaiAuth": true } }
|
||||
{ "id": 1, "result": { "account": { "type": "chatgpt", "email": "user@example.com", "planType": "pro" }, "requiresOpenaiAuth": true } }
|
||||
{ "id": 1, "result": { "account": null, "requiresOpenaiAuth": false, "codexManagedAuth": false } } // No OpenAI auth needed (e.g., OSS/local models)
|
||||
{ "id": 1, "result": { "account": null, "requiresOpenaiAuth": true, "codexManagedAuth": false } } // OpenAI auth required (typical for OpenAI-hosted models)
|
||||
{ "id": 1, "result": { "account": { "type": "apiKey" }, "requiresOpenaiAuth": true, "codexManagedAuth": true } }
|
||||
{ "id": 1, "result": { "account": { "type": "chatgpt", "email": "user@example.com", "planType": "pro" }, "requiresOpenaiAuth": true, "codexManagedAuth": true } }
|
||||
```
|
||||
|
||||
Field notes:
|
||||
|
||||
- `refreshToken` (bool): set `true` to force a token refresh.
|
||||
- `requiresOpenaiAuth` reflects the active provider; when `false`, Codex can run without OpenAI credentials.
|
||||
- `codexManagedAuth` is `true` when `account/logout` can clear Codex-owned persisted auth for the current account. When `false`, logout is a successful no-op for auth managed outside Codex.
|
||||
|
||||
### 2) Log in with an API key
|
||||
|
||||
|
||||
@@ -631,6 +631,12 @@ fn override_message(layer: &ConfigLayerSource) -> String {
|
||||
"Overridden by project config: {}/{CONFIG_TOML_FILE}",
|
||||
dot_codex_folder.display(),
|
||||
),
|
||||
ConfigLayerSource::ProviderState { provider, file } => {
|
||||
format!(
|
||||
"Overridden by provider state ({provider}): {}",
|
||||
file.display()
|
||||
)
|
||||
}
|
||||
ConfigLayerSource::SessionFlags => "Overridden by session flags".to_string(),
|
||||
ConfigLayerSource::User { file, .. } => {
|
||||
format!("Overridden by user config: {}", file.display())
|
||||
|
||||
@@ -47,8 +47,6 @@ use codex_app_server_protocol::CommandExecParams;
|
||||
use codex_app_server_protocol::CommandExecResizeParams;
|
||||
use codex_app_server_protocol::CommandExecTerminateParams;
|
||||
use codex_app_server_protocol::CommandExecWriteParams;
|
||||
use codex_app_server_protocol::ConfigBatchWriteParams;
|
||||
use codex_app_server_protocol::ConfigEdit as ConfigWriteEdit;
|
||||
use codex_app_server_protocol::ConfigWarningNotification;
|
||||
use codex_app_server_protocol::ConversationGitInfo;
|
||||
use codex_app_server_protocol::ConversationSummary;
|
||||
@@ -102,7 +100,6 @@ use codex_app_server_protocol::McpServerStatusDetail;
|
||||
use codex_app_server_protocol::McpServerToolCallParams;
|
||||
use codex_app_server_protocol::McpServerToolCallResponse;
|
||||
use codex_app_server_protocol::MemoryResetResponse;
|
||||
use codex_app_server_protocol::MergeStrategy;
|
||||
use codex_app_server_protocol::MockExperimentalMethodParams;
|
||||
use codex_app_server_protocol::MockExperimentalMethodResponse;
|
||||
use codex_app_server_protocol::ModelListParams;
|
||||
@@ -365,6 +362,7 @@ use codex_model_provider::is_supported_amazon_bedrock_region;
|
||||
use codex_model_provider::save_amazon_bedrock_auth;
|
||||
use codex_models_manager::collaboration_mode_presets::builtin_collaboration_mode_presets;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::account::ProviderAccount;
|
||||
use codex_protocol::config_types::CollaborationMode;
|
||||
use codex_protocol::config_types::ForcedLoginMethod;
|
||||
use codex_protocol::config_types::Personality;
|
||||
|
||||
@@ -331,31 +331,6 @@ impl AccountRequestProcessor {
|
||||
save_amazon_bedrock_auth(&self.config.codex_home, key, region)
|
||||
.map_err(|err| internal_error(format!("failed to save Amazon Bedrock auth: {err}")))?;
|
||||
|
||||
self.config_manager
|
||||
.batch_write(ConfigBatchWriteParams {
|
||||
edits: vec![
|
||||
ConfigWriteEdit {
|
||||
key_path: "model_provider".to_string(),
|
||||
value: serde_json::json!(AMAZON_BEDROCK_PROVIDER_ID),
|
||||
merge_strategy: MergeStrategy::Upsert,
|
||||
},
|
||||
ConfigWriteEdit {
|
||||
key_path: format!(
|
||||
"model_providers.{AMAZON_BEDROCK_PROVIDER_ID}.aws.region"
|
||||
),
|
||||
value: serde_json::json!(region),
|
||||
merge_strategy: MergeStrategy::Upsert,
|
||||
},
|
||||
],
|
||||
file_path: None,
|
||||
expected_version: None,
|
||||
reload_user_config: false,
|
||||
})
|
||||
.await
|
||||
.map_err(|err| {
|
||||
internal_error(format!("failed to update Amazon Bedrock config: {err}"))
|
||||
})?;
|
||||
|
||||
let next_config = self
|
||||
.config_manager
|
||||
.load_latest_config(/*fallback_cwd*/ None)
|
||||
@@ -796,54 +771,63 @@ impl AccountRequestProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
match self.auth_manager.logout_with_revoke().await {
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
return Err(internal_error(format!("logout failed: {err}")));
|
||||
let current_config = self
|
||||
.config_manager
|
||||
.load_latest_config(/*fallback_cwd*/ None)
|
||||
.await
|
||||
.map_err(|err| internal_error(format!("failed to reload config: {err}")))?;
|
||||
if current_config.model_provider_id == AMAZON_BEDROCK_PROVIDER_ID {
|
||||
let provider = create_model_provider(
|
||||
current_config.model_provider.clone(),
|
||||
Some(self.auth_manager.clone()),
|
||||
Some(current_config.codex_home.to_path_buf()),
|
||||
);
|
||||
let account_state = provider.account_state().map_err(|err| match err {
|
||||
ProviderAccountError::MissingChatgptAccountDetails => {
|
||||
invalid_request("email and plan type are required for chatgpt authentication")
|
||||
}
|
||||
})?;
|
||||
let codex_managed_auth = account_state.codex_managed_auth;
|
||||
let Some(ProviderAccount::AmazonBedrock) = account_state.account else {
|
||||
return Err(invalid_request(
|
||||
"active Amazon Bedrock provider did not report an Amazon Bedrock account",
|
||||
));
|
||||
};
|
||||
if !codex_managed_auth {
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
let removed_bedrock_auth =
|
||||
|
||||
delete_amazon_bedrock_auth(&self.config.codex_home).map_err(|err| {
|
||||
internal_error(format!("failed to remove Amazon Bedrock auth: {err}"))
|
||||
})?;
|
||||
if removed_bedrock_auth {
|
||||
let current_config = self
|
||||
let next_config = self
|
||||
.config_manager
|
||||
.load_latest_config(/*fallback_cwd*/ None)
|
||||
.await
|
||||
.map_err(|err| internal_error(format!("failed to reload config: {err}")))?;
|
||||
if current_config.model_provider_id == AMAZON_BEDROCK_PROVIDER_ID {
|
||||
self.config_manager
|
||||
.batch_write(ConfigBatchWriteParams {
|
||||
edits: vec![ConfigWriteEdit {
|
||||
key_path: "model_provider".to_string(),
|
||||
value: serde_json::Value::Null,
|
||||
merge_strategy: MergeStrategy::Replace,
|
||||
}],
|
||||
file_path: None,
|
||||
expected_version: None,
|
||||
reload_user_config: false,
|
||||
})
|
||||
.await
|
||||
.map_err(|err| {
|
||||
internal_error(format!("failed to update Amazon Bedrock config: {err}"))
|
||||
})?;
|
||||
for thread_id in self.thread_manager.list_thread_ids().await {
|
||||
let Ok(thread) = self.thread_manager.get_thread(thread_id).await else {
|
||||
continue;
|
||||
};
|
||||
thread.refresh_runtime_config(next_config.clone()).await;
|
||||
}
|
||||
Self::spawn_effective_plugins_changed_task(
|
||||
Arc::clone(&self.thread_manager),
|
||||
self.config_manager.clone(),
|
||||
);
|
||||
Self::maybe_refresh_remote_installed_plugins_cache_for_current_config(
|
||||
&self.config_manager,
|
||||
&self.thread_manager,
|
||||
self.auth_manager.auth_cached(),
|
||||
)
|
||||
.await;
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let next_config = self
|
||||
.config_manager
|
||||
.load_latest_config(/*fallback_cwd*/ None)
|
||||
.await
|
||||
.map_err(|err| internal_error(format!("failed to reload config: {err}")))?;
|
||||
for thread_id in self.thread_manager.list_thread_ids().await {
|
||||
let Ok(thread) = self.thread_manager.get_thread(thread_id).await else {
|
||||
continue;
|
||||
};
|
||||
thread.refresh_runtime_config(next_config.clone()).await;
|
||||
}
|
||||
Self::spawn_effective_plugins_changed_task(
|
||||
Arc::clone(&self.thread_manager),
|
||||
self.config_manager.clone(),
|
||||
);
|
||||
match self.auth_manager.logout_with_revoke().await {
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
return Err(internal_error(format!("logout failed: {err}")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -997,6 +981,7 @@ impl AccountRequestProcessor {
|
||||
Ok(GetAccountResponse {
|
||||
account,
|
||||
requires_openai_auth: account_state.requires_openai_auth,
|
||||
codex_managed_auth: account_state.codex_managed_auth,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1180,6 +1180,20 @@ impl TestAppServer {
|
||||
self.send_request("account/login/start", Some(params)).await
|
||||
}
|
||||
|
||||
/// Send an `account/login/start` JSON-RPC request for Amazon Bedrock login.
|
||||
pub async fn send_login_account_amazon_bedrock_request(
|
||||
&mut self,
|
||||
key: &str,
|
||||
region: &str,
|
||||
) -> anyhow::Result<i64> {
|
||||
let params = serde_json::json!({
|
||||
"type": "amazonBedrock",
|
||||
"key": key,
|
||||
"region": region,
|
||||
});
|
||||
self.send_request("account/login/start", Some(params)).await
|
||||
}
|
||||
|
||||
/// Send an `account/login/cancel` JSON-RPC request.
|
||||
pub async fn send_cancel_login_account_request(
|
||||
&mut self,
|
||||
|
||||
@@ -250,26 +250,34 @@ async fn logout_account_removes_auth_and_notifies() -> Result<()> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn logout_account_removes_bedrock_model_provider_after_managed_auth_removed() -> Result<()> {
|
||||
async fn logout_account_removes_managed_bedrock_provider_state() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(
|
||||
codex_home.path(),
|
||||
CreateConfigTomlParams {
|
||||
model_provider_id: Some("amazon-bedrock".to_string()),
|
||||
extra_provider_config: Some(
|
||||
r#"[model_providers.amazon-bedrock.aws]
|
||||
region = "us-west-2"
|
||||
"#
|
||||
.to_string(),
|
||||
),
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
save_amazon_bedrock_auth(codex_home.path(), "bedrock-key", "us-west-2")?;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
TestAppServer::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let account_id = mcp
|
||||
.send_get_account_request(GetAccountParams {
|
||||
refresh_token: false,
|
||||
})
|
||||
.await?;
|
||||
let account_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(account_id)),
|
||||
)
|
||||
.await??;
|
||||
let account: GetAccountResponse = to_response(account_resp)?;
|
||||
assert_eq!(account.account, Some(Account::AmazonBedrock {}));
|
||||
assert!(account.codex_managed_auth);
|
||||
|
||||
let id = mcp.send_logout_account_request().await?;
|
||||
let resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
@@ -289,22 +297,14 @@ region = "us-west-2"
|
||||
);
|
||||
let config = std::fs::read_to_string(codex_home.path().join("config.toml"))?;
|
||||
assert!(
|
||||
!config.contains("model_provider = \"amazon-bedrock\""),
|
||||
"active Bedrock model provider should be removed after managed Bedrock logout"
|
||||
);
|
||||
assert!(
|
||||
config.contains("[model_providers.amazon-bedrock.aws]"),
|
||||
"Bedrock provider config should be preserved"
|
||||
);
|
||||
assert!(
|
||||
config.contains("region = \"us-west-2\""),
|
||||
"Bedrock region should be preserved"
|
||||
config.contains("model_provider = \"mock_provider\""),
|
||||
"managed Bedrock login should not mutate user model provider config"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn logout_account_keeps_bedrock_model_provider_without_managed_auth() -> Result<()> {
|
||||
async fn logout_account_noops_for_aws_managed_bedrock_auth() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(
|
||||
codex_home.path(),
|
||||
@@ -320,7 +320,8 @@ region = "us-west-2"
|
||||
},
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
TestAppServer::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let id = mcp.send_logout_account_request().await?;
|
||||
@@ -339,6 +340,47 @@ region = "us-west-2"
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn login_account_amazon_bedrock_activates_provider_without_user_config_write() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), CreateConfigTomlParams::default())?;
|
||||
|
||||
let mut mcp = TestAppServer::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let login_id = mcp
|
||||
.send_login_account_amazon_bedrock_request("bedrock-key", "us-west-2")
|
||||
.await?;
|
||||
let login_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(login_id)),
|
||||
)
|
||||
.await??;
|
||||
let login: LoginAccountResponse = to_response(login_resp)?;
|
||||
assert_eq!(login, LoginAccountResponse::AmazonBedrock {});
|
||||
|
||||
let get_id = mcp
|
||||
.send_get_account_request(GetAccountParams {
|
||||
refresh_token: false,
|
||||
})
|
||||
.await?;
|
||||
let get_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(get_id)),
|
||||
)
|
||||
.await??;
|
||||
let account: GetAccountResponse = to_response(get_resp)?;
|
||||
assert_eq!(account.account, Some(Account::AmazonBedrock {}));
|
||||
assert!(account.codex_managed_auth);
|
||||
|
||||
let config = std::fs::read_to_string(codex_home.path().join("config.toml"))?;
|
||||
assert!(
|
||||
config.contains("model_provider = \"mock_provider\""),
|
||||
"Amazon Bedrock login should not mutate user model provider config"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn set_auth_token_updates_account_and_notifies() -> Result<()> {
|
||||
let codex_home = TempDir::new()?;
|
||||
@@ -410,6 +452,7 @@ async fn set_auth_token_updates_account_and_notifies() -> Result<()> {
|
||||
plan_type: AccountPlanType::Pro,
|
||||
}),
|
||||
requires_openai_auth: true,
|
||||
codex_managed_auth: true,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -478,6 +521,7 @@ async fn account_read_refresh_token_is_noop_in_external_mode() -> Result<()> {
|
||||
plan_type: AccountPlanType::Pro,
|
||||
}),
|
||||
requires_openai_auth: true,
|
||||
codex_managed_auth: true,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1688,6 +1732,7 @@ async fn get_account_with_api_key() -> Result<()> {
|
||||
let expected = GetAccountResponse {
|
||||
account: Some(Account::ApiKey {}),
|
||||
requires_openai_auth: true,
|
||||
codex_managed_auth: true,
|
||||
};
|
||||
assert_eq!(received, expected);
|
||||
Ok(())
|
||||
@@ -1722,6 +1767,7 @@ async fn get_account_when_auth_not_required() -> Result<()> {
|
||||
let expected = GetAccountResponse {
|
||||
account: None,
|
||||
requires_openai_auth: false,
|
||||
codex_managed_auth: false,
|
||||
};
|
||||
assert_eq!(received, expected);
|
||||
Ok(())
|
||||
@@ -1763,6 +1809,7 @@ region = "us-west-2"
|
||||
let expected = GetAccountResponse {
|
||||
account: Some(Account::AmazonBedrock {}),
|
||||
requires_openai_auth: false,
|
||||
codex_managed_auth: false,
|
||||
};
|
||||
assert_eq!(received, expected);
|
||||
Ok(())
|
||||
@@ -1808,6 +1855,7 @@ async fn get_account_with_chatgpt() -> Result<()> {
|
||||
plan_type: AccountPlanType::Pro,
|
||||
}),
|
||||
requires_openai_auth: true,
|
||||
codex_managed_auth: true,
|
||||
};
|
||||
assert_eq!(received, expected);
|
||||
Ok(())
|
||||
@@ -1891,6 +1939,7 @@ async fn get_account_omits_chatgpt_after_permanent_refresh_failure() -> Result<(
|
||||
GetAccountResponse {
|
||||
account: None,
|
||||
requires_openai_auth: true,
|
||||
codex_managed_auth: false,
|
||||
}
|
||||
);
|
||||
server.verify().await;
|
||||
@@ -1935,6 +1984,7 @@ async fn get_account_with_chatgpt_missing_plan_claim_returns_unknown() -> Result
|
||||
plan_type: AccountPlanType::Unknown,
|
||||
}),
|
||||
requires_openai_auth: true,
|
||||
codex_managed_auth: true,
|
||||
};
|
||||
assert_eq!(received, expected);
|
||||
Ok(())
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::time::Duration;
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use app_test_support::ChatGptAuthFixture;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::TestAppServer;
|
||||
use app_test_support::to_response;
|
||||
use app_test_support::write_chatgpt_auth;
|
||||
use codex_app_server_protocol::ItemCompletedNotification;
|
||||
@@ -76,7 +76,8 @@ async fn standalone_image_generation_persists_image_and_returns_it_to_model() ->
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = McpProcess::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
let mut mcp =
|
||||
TestAppServer::new_with_env(codex_home.path(), &[("OPENAI_API_KEY", None)]).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
@@ -157,7 +158,7 @@ async fn standalone_image_generation_persists_image_and_returns_it_to_model() ->
|
||||
}
|
||||
|
||||
async fn wait_for_image_generation_completed(
|
||||
mcp: &mut McpProcess,
|
||||
mcp: &mut TestAppServer,
|
||||
) -> Result<ItemCompletedNotification> {
|
||||
loop {
|
||||
let notification = mcp
|
||||
|
||||
@@ -20,6 +20,9 @@ pub fn format_config_layer_source(source: &ConfigLayerSource, config_toml_file:
|
||||
dot_codex_folder.as_path().display()
|
||||
)
|
||||
}
|
||||
ConfigLayerSource::ProviderState { provider, file } => {
|
||||
format!("provider state ({provider}, {})", file.as_path().display())
|
||||
}
|
||||
ConfigLayerSource::SessionFlags => "session-flags".to_string(),
|
||||
ConfigLayerSource::LegacyManagedConfigTomlFromFile { file } => {
|
||||
format!("legacy managed_config.toml ({})", file.as_path().display())
|
||||
|
||||
@@ -253,6 +253,7 @@ fn config_path_for_layer(layer: &ConfigLayerEntry, config_toml_file: &str) -> Op
|
||||
ConfigLayerSource::Project { dot_codex_folder } => {
|
||||
Some(dot_codex_folder.as_path().join(config_toml_file))
|
||||
}
|
||||
ConfigLayerSource::ProviderState { file, .. } => Some(file.to_path_buf()),
|
||||
ConfigLayerSource::LegacyManagedConfigTomlFromFile { file } => Some(file.to_path_buf()),
|
||||
ConfigLayerSource::Mdm { .. }
|
||||
| ConfigLayerSource::EnterpriseManaged { .. }
|
||||
|
||||
@@ -19,6 +19,7 @@ pub mod permissions_toml;
|
||||
mod plugin_edit;
|
||||
pub mod profile_toml;
|
||||
mod project_root_markers;
|
||||
mod provider_state;
|
||||
mod requirements_exec_policy;
|
||||
mod requirements_layers;
|
||||
pub mod schema;
|
||||
|
||||
@@ -22,6 +22,7 @@ use crate::merge::merge_toml_values;
|
||||
use crate::overrides::build_cli_overrides_layer;
|
||||
use crate::project_root_markers::default_project_root_markers;
|
||||
use crate::project_root_markers::project_root_markers_from_config;
|
||||
use crate::provider_state::load_provider_state_layer;
|
||||
use crate::state::ConfigLayerEntry;
|
||||
use crate::state::ConfigLayerStack;
|
||||
use crate::state::ConfigLoadOptions;
|
||||
@@ -348,6 +349,10 @@ pub async fn load_config_layers_state(
|
||||
startup_warnings = Some(project_layers.startup_warnings);
|
||||
}
|
||||
|
||||
if let Some(provider_state_layer) = load_provider_state_layer(fs, codex_home).await? {
|
||||
layers.push(provider_state_layer);
|
||||
}
|
||||
|
||||
// Add a layer for runtime overrides from the CLI or UI, if any exist.
|
||||
if let Some(cli_overrides_layer) = cli_overrides_layer {
|
||||
layers.push(ConfigLayerEntry::new(
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
use codex_app_server_protocol::ConfigLayerSource;
|
||||
use codex_file_system::ExecutorFileSystem;
|
||||
use codex_model_provider_info::AMAZON_BEDROCK_PROVIDER_ID;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use serde::Deserialize;
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use toml::Value as TomlValue;
|
||||
|
||||
use crate::ConfigLayerEntry;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct AmazonBedrockAuthState {
|
||||
#[serde(default = "default_activates_provider")]
|
||||
activates_provider: bool,
|
||||
}
|
||||
|
||||
pub(crate) async fn load_provider_state_layer(
|
||||
fs: &dyn ExecutorFileSystem,
|
||||
codex_home: &Path,
|
||||
) -> io::Result<Option<ConfigLayerEntry>> {
|
||||
let auth_file = amazon_bedrock_auth_file(codex_home);
|
||||
let contents = match fs.read_file_text(&auth_file, /*sandbox*/ None).await {
|
||||
Ok(contents) => contents,
|
||||
Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(None),
|
||||
Err(err) => {
|
||||
return Err(io::Error::new(
|
||||
err.kind(),
|
||||
format!(
|
||||
"Failed to read provider state file {}: {err}",
|
||||
auth_file.as_path().display()
|
||||
),
|
||||
));
|
||||
}
|
||||
};
|
||||
let state: AmazonBedrockAuthState = serde_json::from_str(&contents).map_err(|err| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
format!(
|
||||
"Failed to parse provider state file {}: {err}",
|
||||
auth_file.as_path().display()
|
||||
),
|
||||
)
|
||||
})?;
|
||||
if !state.activates_provider {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let mut root = toml::map::Map::new();
|
||||
root.insert(
|
||||
"model_provider".to_string(),
|
||||
TomlValue::String(AMAZON_BEDROCK_PROVIDER_ID.to_string()),
|
||||
);
|
||||
Ok(Some(ConfigLayerEntry::new(
|
||||
ConfigLayerSource::ProviderState {
|
||||
provider: AMAZON_BEDROCK_PROVIDER_ID.to_string(),
|
||||
file: auth_file,
|
||||
},
|
||||
TomlValue::Table(root),
|
||||
)))
|
||||
}
|
||||
|
||||
pub(crate) fn amazon_bedrock_auth_file(codex_home: &Path) -> AbsolutePathBuf {
|
||||
AbsolutePathBuf::resolve_path_against_base(
|
||||
"model-providers/amazon-bedrock/auth.json",
|
||||
codex_home,
|
||||
)
|
||||
}
|
||||
|
||||
fn default_activates_provider() -> bool {
|
||||
true
|
||||
}
|
||||
@@ -207,6 +207,7 @@ impl ConfigLayerEntry {
|
||||
ConfigLayerSource::EnterpriseManaged { .. } => None,
|
||||
ConfigLayerSource::User { file, .. } => file.parent(),
|
||||
ConfigLayerSource::Project { dot_codex_folder } => Some(dot_codex_folder.clone()),
|
||||
ConfigLayerSource::ProviderState { .. } => None,
|
||||
ConfigLayerSource::SessionFlags => None,
|
||||
ConfigLayerSource::LegacyManagedConfigTomlFromFile { .. } => None,
|
||||
ConfigLayerSource::LegacyManagedConfigTomlFromMdm => None,
|
||||
|
||||
@@ -351,6 +351,7 @@ fn skill_roots_from_layer_stack_inner(
|
||||
}
|
||||
ConfigLayerSource::Mdm { .. }
|
||||
| ConfigLayerSource::EnterpriseManaged { .. }
|
||||
| ConfigLayerSource::ProviderState { .. }
|
||||
| ConfigLayerSource::SessionFlags
|
||||
| ConfigLayerSource::LegacyManagedConfigTomlFromFile { .. }
|
||||
| ConfigLayerSource::LegacyManagedConfigTomlFromMdm => {}
|
||||
|
||||
@@ -371,6 +371,9 @@ fn config_toml_source_path(layer: &ConfigLayerEntry) -> AbsolutePathBuf {
|
||||
ConfigLayerSource::EnterpriseManaged { id, name } => synthetic_layer_path(&format!(
|
||||
"<enterprise-managed:{name}:{id}>/{CONFIG_TOML_FILE}"
|
||||
)),
|
||||
ConfigLayerSource::ProviderState { provider, .. } => {
|
||||
synthetic_layer_path(&format!("<provider-state:{provider}>/{CONFIG_TOML_FILE}"))
|
||||
}
|
||||
ConfigLayerSource::LegacyManagedConfigTomlFromMdm => {
|
||||
synthetic_layer_path("<legacy-managed-config.toml-mdm>/managed_config.toml")
|
||||
}
|
||||
@@ -612,6 +615,7 @@ fn hook_metadata_for_config_layer_source(source: &ConfigLayerSource) -> (HookSou
|
||||
ConfigLayerSource::Project { .. } => (HookSource::Project, false),
|
||||
ConfigLayerSource::Mdm { .. } => (HookSource::Mdm, true),
|
||||
ConfigLayerSource::EnterpriseManaged { .. } => (HookSource::CloudManagedConfig, true),
|
||||
ConfigLayerSource::ProviderState { .. } => (HookSource::Unknown, false),
|
||||
ConfigLayerSource::SessionFlags => (HookSource::SessionFlags, false),
|
||||
ConfigLayerSource::LegacyManagedConfigTomlFromFile { .. } => {
|
||||
(HookSource::LegacyManagedConfigFile, true)
|
||||
|
||||
@@ -217,6 +217,7 @@ mod tests {
|
||||
let auth = AmazonBedrockAuth {
|
||||
bearer_token: "stored-bedrock-key".to_string(),
|
||||
region: "eu-west-1".to_string(),
|
||||
activates_provider: true,
|
||||
};
|
||||
let stored_auth: StoredAmazonBedrockAuth = Ok(Some(auth));
|
||||
|
||||
|
||||
@@ -90,9 +90,11 @@ impl ModelProvider for AmazonBedrockModelProvider {
|
||||
}
|
||||
|
||||
fn account_state(&self) -> ProviderAccountResult {
|
||||
let codex_managed_auth = matches!(&self.stored_auth, Ok(Some(_)));
|
||||
Ok(ProviderAccountState {
|
||||
account: Some(ProviderAccount::AmazonBedrock),
|
||||
requires_openai_auth: false,
|
||||
codex_managed_auth,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ use serde::Serialize;
|
||||
pub struct AmazonBedrockAuth {
|
||||
pub bearer_token: String,
|
||||
pub region: String,
|
||||
#[serde(default = "default_activates_provider")]
|
||||
pub activates_provider: bool,
|
||||
}
|
||||
|
||||
pub(super) type StoredAmazonBedrockAuth = std::result::Result<Option<AmazonBedrockAuth>, String>;
|
||||
@@ -23,6 +25,7 @@ pub fn save_amazon_bedrock_auth(
|
||||
let auth = AmazonBedrockAuth {
|
||||
bearer_token: bearer_token.to_string(),
|
||||
region: region.to_string(),
|
||||
activates_provider: true,
|
||||
};
|
||||
let auth_path = amazon_bedrock_auth_file(codex_home);
|
||||
if let Some(parent) = auth_path.parent() {
|
||||
@@ -97,6 +100,7 @@ mod tests {
|
||||
Some(AmazonBedrockAuth {
|
||||
bearer_token: "bedrock-key".to_string(),
|
||||
region: "us-east-1".to_string(),
|
||||
activates_provider: true,
|
||||
})
|
||||
);
|
||||
assert!(delete_amazon_bedrock_auth(&codex_home).expect("delete auth"));
|
||||
@@ -108,3 +112,7 @@ mod tests {
|
||||
let _ = fs::remove_dir_all(&codex_home);
|
||||
}
|
||||
}
|
||||
|
||||
fn default_activates_provider() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ impl Default for ProviderCapabilities {
|
||||
pub struct ProviderAccountState {
|
||||
pub account: Option<ProviderAccount>,
|
||||
pub requires_openai_auth: bool,
|
||||
pub codex_managed_auth: bool,
|
||||
}
|
||||
|
||||
/// Error returned when a provider cannot construct its app-visible account state.
|
||||
@@ -231,6 +232,7 @@ impl ModelProvider for ConfiguredModelProvider {
|
||||
};
|
||||
|
||||
Ok(ProviderAccountState {
|
||||
codex_managed_auth: account.is_some(),
|
||||
account,
|
||||
requires_openai_auth: self.info.requires_openai_auth,
|
||||
})
|
||||
@@ -438,6 +440,7 @@ mod tests {
|
||||
Ok(ProviderAccountState {
|
||||
account: None,
|
||||
requires_openai_auth: true,
|
||||
codex_managed_auth: false,
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -457,6 +460,7 @@ mod tests {
|
||||
Ok(ProviderAccountState {
|
||||
account: Some(ProviderAccount::ApiKey),
|
||||
requires_openai_auth: true,
|
||||
codex_managed_auth: true,
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -480,6 +484,7 @@ mod tests {
|
||||
Ok(ProviderAccountState {
|
||||
account: None,
|
||||
requires_openai_auth: false,
|
||||
codex_managed_auth: false,
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -497,6 +502,7 @@ mod tests {
|
||||
Ok(ProviderAccountState {
|
||||
account: Some(ProviderAccount::AmazonBedrock),
|
||||
requires_openai_auth: false,
|
||||
codex_managed_auth: false,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,10 @@ pub enum PlanType {
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ProviderAccount {
|
||||
ApiKey,
|
||||
Chatgpt { email: String, plan_type: PlanType },
|
||||
Chatgpt {
|
||||
email: String,
|
||||
plan_type: PlanType,
|
||||
},
|
||||
AmazonBedrock,
|
||||
}
|
||||
|
||||
|
||||
@@ -308,7 +308,7 @@ impl AppServerSession {
|
||||
true,
|
||||
)
|
||||
}
|
||||
Some(Account::AmazonBedrock {}) => {
|
||||
Some(Account::AmazonBedrock { .. }) => {
|
||||
(None, None, None, None, FeedbackAudience::External, false)
|
||||
}
|
||||
None => (None, None, None, None, FeedbackAudience::External, false),
|
||||
|
||||
@@ -271,6 +271,7 @@ fn render_non_file_layer_details(layer: &ConfigLayerEntry) -> Vec<Line<'static>>
|
||||
ConfigLayerSource::SessionFlags => render_session_flag_details(&layer.config),
|
||||
ConfigLayerSource::Mdm { .. }
|
||||
| ConfigLayerSource::EnterpriseManaged { .. }
|
||||
| ConfigLayerSource::ProviderState { .. }
|
||||
| ConfigLayerSource::LegacyManagedConfigTomlFromMdm => render_non_file_layer_value(layer),
|
||||
ConfigLayerSource::System { .. }
|
||||
| ConfigLayerSource::User { .. }
|
||||
@@ -336,6 +337,7 @@ fn non_file_layer_value_label(source: &ConfigLayerSource) -> &'static str {
|
||||
}
|
||||
ConfigLayerSource::EnterpriseManaged { .. } => "Enterprise-managed config value",
|
||||
ConfigLayerSource::SessionFlags
|
||||
| ConfigLayerSource::ProviderState { .. }
|
||||
| ConfigLayerSource::System { .. }
|
||||
| ConfigLayerSource::User { .. }
|
||||
| ConfigLayerSource::Project { .. }
|
||||
|
||||
@@ -1901,7 +1901,7 @@ async fn get_login_status(
|
||||
Ok(match account.account {
|
||||
Some(AppServerAccount::ApiKey {}) => LoginStatus::AuthMode(AppServerAuthMode::ApiKey),
|
||||
Some(AppServerAccount::Chatgpt { .. }) => LoginStatus::AuthMode(AppServerAuthMode::Chatgpt),
|
||||
Some(AppServerAccount::AmazonBedrock {}) => LoginStatus::NotAuthenticated,
|
||||
Some(AppServerAccount::AmazonBedrock { .. }) => LoginStatus::NotAuthenticated,
|
||||
None => LoginStatus::NotAuthenticated,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user