mirror of
https://github.com/openai/codex.git
synced 2026-09-09 15:58:47 +00:00
## Why Auth managers should use the application's resolved HTTP client factory instead of silently falling back to the transport's default proxy behavior. ## What changed - Make `AuthRouteConfig` required when constructing an `AuthManager` or `AuthConfig`. - Pass each production caller's resolved routing configuration through without wrapping it in an optional value. - Add a test helper that explicitly selects the transport-default proxy policy for callers that do not exercise custom routing. GitOrigin-RevId: d89a3b1f8b5d4007650cdac0aae241c94d598580
87 lines
3.0 KiB
Rust
87 lines
3.0 KiB
Rust
use crate::backend::BackendBundleClient;
|
|
use crate::service::CLOUD_CONFIG_BUNDLE_TIMEOUT;
|
|
use crate::service::CloudConfigBundleService;
|
|
use codex_config::CloudConfigBundleLoadError;
|
|
use codex_config::CloudConfigBundleLoadErrorCode;
|
|
use codex_config::CloudConfigBundleLoader;
|
|
use codex_config::types::AuthCredentialsStoreMode;
|
|
use codex_http_client::HttpClientFactory;
|
|
use codex_login::AuthKeyringBackendKind;
|
|
use codex_login::AuthManager;
|
|
use codex_login::AuthRouteConfig;
|
|
use std::path::PathBuf;
|
|
use std::sync::Arc;
|
|
use std::sync::Mutex;
|
|
use std::sync::OnceLock;
|
|
use tokio::task::JoinHandle;
|
|
|
|
fn refresher_task_slot() -> &'static Mutex<Option<JoinHandle<()>>> {
|
|
static REFRESHER_TASK: OnceLock<Mutex<Option<JoinHandle<()>>>> = OnceLock::new();
|
|
REFRESHER_TASK.get_or_init(|| Mutex::new(None))
|
|
}
|
|
|
|
pub fn cloud_config_bundle_loader(
|
|
auth_manager: Arc<AuthManager>,
|
|
chatgpt_base_url: String,
|
|
codex_home: PathBuf,
|
|
http_client_factory: HttpClientFactory,
|
|
) -> CloudConfigBundleLoader {
|
|
let service = CloudConfigBundleService::new(
|
|
auth_manager,
|
|
Arc::new(BackendBundleClient::new(
|
|
chatgpt_base_url,
|
|
http_client_factory,
|
|
)),
|
|
codex_home,
|
|
CLOUD_CONFIG_BUNDLE_TIMEOUT,
|
|
);
|
|
let refresh_service = service.clone();
|
|
let task = tokio::spawn(async move { service.load_startup_bundle_with_timeout().await });
|
|
let refresh_task =
|
|
tokio::spawn(async move { refresh_service.refresh_cache_in_background().await });
|
|
let mut refresher_guard = refresher_task_slot().lock().unwrap_or_else(|err| {
|
|
tracing::warn!("cloud config bundle refresher task slot was poisoned");
|
|
err.into_inner()
|
|
});
|
|
if let Some(existing_task) = refresher_guard.replace(refresh_task) {
|
|
existing_task.abort();
|
|
}
|
|
CloudConfigBundleLoader::new(async move {
|
|
task.await.map_err(|err| {
|
|
tracing::error!(error = %err, "Cloud config bundle task failed");
|
|
CloudConfigBundleLoadError::new(
|
|
CloudConfigBundleLoadErrorCode::Internal,
|
|
/*status_code*/ None,
|
|
format!("cloud config bundle load failed: {err}"),
|
|
)
|
|
})?
|
|
})
|
|
}
|
|
|
|
pub async fn cloud_config_bundle_loader_for_storage(
|
|
codex_home: PathBuf,
|
|
enable_codex_api_key_env: bool,
|
|
credentials_store_mode: AuthCredentialsStoreMode,
|
|
keyring_backend_kind: AuthKeyringBackendKind,
|
|
chatgpt_base_url: String,
|
|
auth_route_config: AuthRouteConfig,
|
|
) -> CloudConfigBundleLoader {
|
|
let http_client_factory = auth_route_config.http_client_factory().clone();
|
|
let auth_manager = AuthManager::shared(
|
|
codex_home.clone(),
|
|
enable_codex_api_key_env,
|
|
credentials_store_mode,
|
|
/*forced_chatgpt_workspace_id*/ None,
|
|
Some(chatgpt_base_url.clone()),
|
|
keyring_backend_kind,
|
|
auth_route_config,
|
|
)
|
|
.await;
|
|
cloud_config_bundle_loader(
|
|
auth_manager,
|
|
chatgpt_base_url,
|
|
codex_home,
|
|
http_client_factory,
|
|
)
|
|
}
|