feat: add opt-in provider runtime abstraction (#17713)

## Summary

- Add `codex-model-provider` as the runtime home for model-provider
behavior that does not belong in `codex-core`, `codex-login`, or
`codex-api`.
- The new crate wraps configured `ModelProviderInfo` in a
`ModelProvider` trait object that can resolve the API provider config,
provider-scoped auth manager, and request auth provider for each call.
- This centralizes provider auth behavior in one place today, and gives
us an extension point for future provider-specific auth, model listing,
request setup, and related runtime behavior.

## Tests
Ran tests manually to make sure that provider auth under different
configs still work as expected.

---------

Co-authored-by: pakrym-oai <pakrym@openai.com>
This commit is contained in:
Celia Chenandpakrym-oai authored and GitHub committed 2026-04-17 02:27:45 +00:00
1 parent 91e8eebd03
commit a803790a10
45 files changed
+577 -369

No files matched your search

-40
View File
@@ -1,40 +0,0 @@
use codex_api::CoreAuthProvider;
use codex_model_provider_info::ModelProviderInfo;
use crate::CodexAuth;
pub fn auth_provider_from_auth(
auth: Option<CodexAuth>,
provider: &ModelProviderInfo,
) -> codex_protocol::error::Result<CoreAuthProvider> {
if let Some(api_key) = provider.api_key()? {
return Ok(CoreAuthProvider {
token: Some(api_key),
account_id: None,
is_fedramp_account: false,
});
}
if let Some(token) = provider.experimental_bearer_token.clone() {
return Ok(CoreAuthProvider {
token: Some(token),
account_id: None,
is_fedramp_account: false,
});
}
if let Some(auth) = auth {
let token = auth.get_token()?;
Ok(CoreAuthProvider {
token: Some(token),
account_id: auth.get_account_id(),
is_fedramp_account: auth.is_fedramp_account(),
})
} else {
Ok(CoreAuthProvider {
token: None,
account_id: None,
is_fedramp_account: false,
})
}
}
-5
View File
@@ -1,7 +1,5 @@
pub mod api_bridge;
pub mod auth;
pub mod auth_env_telemetry;
pub mod provider_auth;
pub mod token_data;
mod device_code_auth;
@@ -19,7 +17,6 @@ pub use server::ServerOptions;
pub use server::ShutdownHandle;
pub use server::run_login_server;
pub use api_bridge::auth_provider_from_auth;
pub use auth::AgentIdentityAuthRecord;
pub use auth::AuthConfig;
pub use auth::AuthDotJson;
@@ -46,6 +43,4 @@ pub use auth::read_openai_api_key_from_env;
pub use auth::save_auth;
pub use auth_env_telemetry::AuthEnvTelemetry;
pub use auth_env_telemetry::collect_auth_env_telemetry;
pub use provider_auth::auth_manager_for_provider;
pub use provider_auth::required_auth_manager_for_provider;
pub use token_data::TokenData;
-32
View File
@@ -1,32 +0,0 @@
use std::sync::Arc;
use codex_model_provider_info::ModelProviderInfo;
use crate::AuthManager;
/// Returns the provider-scoped auth manager when this provider uses command-backed auth.
///
/// Providers without custom auth continue using the caller-supplied base manager.
pub fn auth_manager_for_provider(
auth_manager: Option<Arc<AuthManager>>,
provider: &ModelProviderInfo,
) -> Option<Arc<AuthManager>> {
match provider.auth.clone() {
Some(config) => Some(AuthManager::external_bearer_only(config)),
None => auth_manager,
}
}
/// Returns an auth manager for request paths that always require authentication.
///
/// Providers with command-backed auth get a bearer-only manager; otherwise the caller's manager
/// is reused unchanged.
pub fn required_auth_manager_for_provider(
auth_manager: Arc<AuthManager>,
provider: &ModelProviderInfo,
) -> Arc<AuthManager> {
match provider.auth.clone() {
Some(config) => AuthManager::external_bearer_only(config),
None => auth_manager,
}
}