This commit is contained in:
celia-oai
2026-06-10 17:46:56 -07:00
parent 221f3ac987
commit 222e8924d5
6 changed files with 73 additions and 5 deletions
+40
View File
@@ -74,6 +74,8 @@ async fn build_refresh_config(
config.mcp_oauth_credentials_store_mode,
)
.map_err(io::Error::other)?,
auth_keyring_backend_kind: serde_json::to_value(config.auth_keyring_backend_kind())
.map_err(io::Error::other)?,
})
}
@@ -108,6 +110,7 @@ mod tests {
use codex_config::ThreadConfigLoadErrorCode;
use codex_config::ThreadConfigLoader;
use codex_config::ThreadConfigSource;
use codex_config::types::AuthKeyringBackendKind;
use codex_core::config::ConfigOverrides;
use codex_core::init_state_db;
use codex_core::thread_store_from_config;
@@ -145,6 +148,39 @@ mod tests {
Ok(())
}
#[tokio::test]
async fn refresh_config_uses_latest_auth_keyring_backend() -> anyhow::Result<()> {
let (temp_dir, thread_manager, config_manager, _loader) = refresh_test_state().await?;
std::fs::write(
temp_dir.path().join(codex_config::CONFIG_TOML_FILE),
"[features]\nsecret_auth_storage = true\n",
)?;
let mut good_thread = None;
for thread_id in thread_manager.list_thread_ids().await {
let thread = thread_manager.get_thread(thread_id).await?;
let thread_config = thread.config().await;
if thread_config.cwd.ends_with("good") {
good_thread = Some((thread, thread_config));
break;
}
}
let (thread, thread_config) = good_thread.expect("good test thread should exist");
let refresh_config =
build_refresh_config(&thread_manager, &config_manager, thread_config).await?;
let backend = serde_json::from_value::<AuthKeyringBackendKind>(
refresh_config.auth_keyring_backend_kind,
)?;
assert_eq!(
thread.config().await.auth_keyring_backend_kind(),
AuthKeyringBackendKind::Direct
);
assert_eq!(backend, AuthKeyringBackendKind::Secrets);
Ok(())
}
async fn refresh_test_state() -> anyhow::Result<(
TempDir,
Arc<ThreadManager>,
@@ -156,6 +192,10 @@ mod tests {
let bad_cwd = temp_dir.path().join("bad");
std::fs::create_dir_all(&good_cwd)?;
std::fs::create_dir_all(&bad_cwd)?;
std::fs::write(
temp_dir.path().join(codex_config::CONFIG_TOML_FILE),
"[features]\nsecret_auth_storage = false\n",
)?;
let initial_config_manager =
ConfigManager::without_managed_config_for_tests(temp_dir.path().to_path_buf());
@@ -212,6 +212,7 @@ pub(crate) async fn maybe_install_mcp_dependencies(
turn_context,
refresh_servers,
config.mcp_oauth_credentials_store_mode,
config.auth_keyring_backend_kind(),
elicitation_reviewer,
)
.await;
+27 -5
View File
@@ -285,6 +285,7 @@ impl Session {
turn_context: &TurnContext,
mcp_servers: HashMap<String, McpServerConfig>,
store_mode: OAuthCredentialsStoreMode,
keyring_backend_kind: AuthKeyringBackendKind,
elicitation_reviewer: Option<ElicitationReviewerHandle>,
) {
let auth = self.services.auth_manager.auth().await;
@@ -303,7 +304,6 @@ impl Session {
effective_mcp_servers_from_configured(mcp_servers, &mcp_config, auth.as_ref());
let host_owned_codex_apps_enabled =
host_owned_codex_apps_enabled(&mcp_config, auth.as_ref());
let keyring_backend_kind = config.auth_keyring_backend_kind();
let auth_statuses = compute_auth_statuses(
mcp_servers.iter(),
store_mode,
@@ -372,6 +372,7 @@ impl Session {
let McpServerRefreshConfig {
mcp_servers,
mcp_oauth_credentials_store_mode,
auth_keyring_backend_kind,
} = refresh_config;
let mcp_servers =
@@ -391,9 +392,23 @@ impl Session {
return;
}
};
let keyring_backend_kind =
match serde_json::from_value::<AuthKeyringBackendKind>(auth_keyring_backend_kind) {
Ok(kind) => kind,
Err(err) => {
warn!("failed to parse MCP auth keyring backend refresh config: {err}");
return;
}
};
self.refresh_mcp_servers_inner(turn_context, mcp_servers, store_mode, elicitation_reviewer)
.await;
self.refresh_mcp_servers_inner(
turn_context,
mcp_servers,
store_mode,
keyring_backend_kind,
elicitation_reviewer,
)
.await;
}
pub(crate) async fn refresh_mcp_servers_now(
@@ -401,10 +416,17 @@ impl Session {
turn_context: &TurnContext,
mcp_servers: HashMap<String, McpServerConfig>,
store_mode: OAuthCredentialsStoreMode,
keyring_backend_kind: AuthKeyringBackendKind,
elicitation_reviewer: Option<ElicitationReviewerHandle>,
) {
self.refresh_mcp_servers_inner(turn_context, mcp_servers, store_mode, elicitation_reviewer)
.await;
self.refresh_mcp_servers_inner(
turn_context,
mcp_servers,
store_mode,
keyring_backend_kind,
elicitation_reviewer,
)
.await;
}
#[cfg(test)]
+1
View File
@@ -47,6 +47,7 @@ use codex_analytics::SubAgentThreadStartedInput;
use codex_analytics::TurnCodexErrorFact;
use codex_app_server_protocol::McpServerElicitationRequest;
use codex_app_server_protocol::McpServerElicitationRequestParams;
use codex_config::types::AuthKeyringBackendKind;
use codex_config::types::OAuthCredentialsStoreMode;
use codex_exec_server::Environment;
use codex_exec_server::EnvironmentManager;
+3
View File
@@ -7065,9 +7065,12 @@ async fn refresh_mcp_servers_is_deferred_until_next_turn() {
let mcp_oauth_credentials_store_mode =
serde_json::to_value(OAuthCredentialsStoreMode::Auto).expect("serialize store mode");
let auth_keyring_backend_kind =
serde_json::to_value(AuthKeyringBackendKind::Secrets).expect("serialize keyring backend");
let refresh_config = McpServerRefreshConfig {
mcp_servers: json!({}),
mcp_oauth_credentials_store_mode,
auth_keyring_backend_kind,
};
{
let mut guard = session.pending_mcp_server_refresh_config.lock().await;
+1
View File
@@ -179,6 +179,7 @@ pub struct W3cTraceContext {
pub struct McpServerRefreshConfig {
pub mcp_servers: Value,
pub mcp_oauth_credentials_store_mode: Value,
pub auth_keyring_backend_kind: Value,
}
#[derive(Debug, Clone, PartialEq)]