This commit is contained in:
celia-oai
2026-05-29 21:56:34 -07:00
parent 5379cb3b27
commit 7f3d9ca324
3 changed files with 136 additions and 4 deletions

View File

@@ -802,9 +802,50 @@ impl AccountRequestProcessor {
return Err(internal_error(format!("logout failed: {err}")));
}
}
delete_amazon_bedrock_auth(&self.config.codex_home).map_err(|err| {
internal_error(format!("failed to remove Amazon Bedrock auth: {err}"))
})?;
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
.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}"))
})?;
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(),
);
}
}
Self::maybe_refresh_remote_installed_plugins_cache_for_current_config(
&self.config_manager,

View File

@@ -35,6 +35,7 @@ use codex_app_server_protocol::TurnStatus;
use codex_config::types::AuthCredentialsStoreMode;
use codex_login::REFRESH_TOKEN_URL_OVERRIDE_ENV_VAR;
use codex_login::login_with_api_key;
use codex_model_provider::save_amazon_bedrock_auth;
use codex_protocol::account::PlanType as AccountPlanType;
use core_test_support::responses;
use pretty_assertions::assert_eq;
@@ -248,6 +249,96 @@ async fn logout_account_removes_auth_and_notifies() -> Result<()> {
Ok(())
}
#[tokio::test]
async fn logout_account_removes_bedrock_model_provider_after_managed_auth_removed() -> 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?;
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
let id = mcp.send_logout_account_request().await?;
let resp: JSONRPCResponse = timeout(
DEFAULT_READ_TIMEOUT,
mcp.read_stream_until_response_message(RequestId::Integer(id)),
)
.await??;
let _ok: LogoutAccountResponse = to_response(resp)?;
assert!(
!codex_home
.path()
.join("model-providers")
.join("amazon-bedrock")
.join("auth.json")
.exists(),
"managed Amazon Bedrock auth should be deleted"
);
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"
);
Ok(())
}
#[tokio::test]
async fn logout_account_keeps_bedrock_model_provider_without_managed_auth() -> 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()
},
)?;
let mut mcp = McpProcess::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?;
let resp: JSONRPCResponse = timeout(
DEFAULT_READ_TIMEOUT,
mcp.read_stream_until_response_message(RequestId::Integer(id)),
)
.await??;
let _ok: LogoutAccountResponse = to_response(resp)?;
let config = std::fs::read_to_string(codex_home.path().join("config.toml"))?;
assert!(
config.contains("model_provider = \"amazon-bedrock\""),
"unmanaged Bedrock logout should not change the active provider"
);
Ok(())
}
#[tokio::test]
async fn set_auth_token_updates_account_and_notifies() -> Result<()> {
let codex_home = TempDir::new()?;

View File

@@ -18,7 +18,6 @@ use crate::BearerAuthProvider;
use super::mantle::aws_auth_config;
use super::mantle::region_from_config;
use super::provider_auth::AmazonBedrockAuth;
use super::provider_auth::StoredAmazonBedrockAuth;
const AWS_BEARER_TOKEN_BEDROCK_ENV_VAR: &str = "AWS_BEARER_TOKEN_BEDROCK";
@@ -174,6 +173,7 @@ mod tests {
use http::HeaderValue;
use pretty_assertions::assert_eq;
use super::super::provider_auth::AmazonBedrockAuth;
use super::*;
fn missing_env_var(_: &'static str) -> std::result::Result<String, std::env::VarError> {