mirror of
https://github.com/openai/codex.git
synced 2026-04-24 06:35:50 +00:00
changes
This commit is contained in:
@@ -105,7 +105,7 @@ use codex_feedback::emit_feedback_request_tags_with_auth_env;
|
||||
use codex_login::api_bridge::auth_provider_from_auth;
|
||||
use codex_login::api_bridge::auth_provider_from_runtime;
|
||||
use codex_login::auth_env_telemetry::AuthEnvTelemetry;
|
||||
use codex_login::auth_env_telemetry::collect_auth_env_telemetry;
|
||||
use codex_login::auth_env_telemetry::collect_auth_env_telemetry_for_runtime;
|
||||
use codex_login::provider_auth::auth_manager_for_provider_runtime;
|
||||
use codex_model_provider::ProviderRuntime;
|
||||
use codex_model_provider::ResolvedModelProvider;
|
||||
@@ -283,12 +283,11 @@ impl ModelClient {
|
||||
let codex_api_key_env_enabled = auth_manager
|
||||
.as_ref()
|
||||
.is_some_and(|manager| manager.codex_api_key_env_enabled());
|
||||
let auth_env_provider = match &provider_runtime {
|
||||
ProviderRuntime::Legacy => &provider,
|
||||
ProviderRuntime::Resolved(provider) => &provider.info,
|
||||
};
|
||||
let auth_env_telemetry =
|
||||
collect_auth_env_telemetry(auth_env_provider, codex_api_key_env_enabled);
|
||||
let auth_env_telemetry = collect_auth_env_telemetry_for_runtime(
|
||||
&provider_runtime,
|
||||
&provider,
|
||||
codex_api_key_env_enabled,
|
||||
);
|
||||
Self {
|
||||
state: Arc::new(ModelClientState {
|
||||
auth_manager,
|
||||
|
||||
@@ -120,11 +120,15 @@ async fn current_client_setup_uses_resolved_runtime_provider() {
|
||||
let mut resolved_provider =
|
||||
create_oss_provider_with_base_url("https://resolved.example.com/v1", WireApi::Responses);
|
||||
resolved_provider.experimental_bearer_token = Some("resolved-token".to_string());
|
||||
let runtime = resolve_model_provider(
|
||||
let mut runtime = resolve_model_provider(
|
||||
"custom",
|
||||
&resolved_provider,
|
||||
&ProviderResolutionPolicy::with_enabled_provider_ids([String::from("custom")]),
|
||||
);
|
||||
let ProviderRuntime::Resolved(provider) = &mut runtime else {
|
||||
panic!("enabled provider should resolve through the provider framework");
|
||||
};
|
||||
provider.info.experimental_bearer_token = None;
|
||||
let client = ModelClient::new(
|
||||
/*auth_manager*/ None,
|
||||
ThreadId::new(),
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
use codex_api::CoreAuthProvider;
|
||||
use codex_model_provider::ProviderAuthKind;
|
||||
use codex_model_provider::ProviderRuntime;
|
||||
use codex_model_provider_info::ModelProviderInfo;
|
||||
use codex_protocol::error::CodexErr;
|
||||
use codex_protocol::error::EnvVarError;
|
||||
|
||||
use crate::CodexAuth;
|
||||
|
||||
@@ -41,11 +44,60 @@ pub fn auth_provider_from_runtime(
|
||||
provider_runtime: &ProviderRuntime,
|
||||
legacy_provider: &ModelProviderInfo,
|
||||
) -> codex_protocol::error::Result<CoreAuthProvider> {
|
||||
let provider = match provider_runtime {
|
||||
ProviderRuntime::Legacy => legacy_provider,
|
||||
ProviderRuntime::Resolved(provider) => &provider.info,
|
||||
};
|
||||
auth_provider_from_auth(auth, provider)
|
||||
match provider_runtime {
|
||||
ProviderRuntime::Legacy => auth_provider_from_auth(auth, legacy_provider),
|
||||
ProviderRuntime::Resolved(provider) => {
|
||||
auth_provider_from_provider_auth(auth, &provider.auth)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn auth_provider_from_provider_auth(
|
||||
auth: Option<CodexAuth>,
|
||||
provider_auth: &ProviderAuthKind,
|
||||
) -> codex_protocol::error::Result<CoreAuthProvider> {
|
||||
match provider_auth {
|
||||
ProviderAuthKind::EnvBearer {
|
||||
env_key,
|
||||
instructions,
|
||||
} => {
|
||||
let token = std::env::var(env_key)
|
||||
.ok()
|
||||
.filter(|value| !value.trim().is_empty())
|
||||
.ok_or_else(|| {
|
||||
CodexErr::EnvVar(EnvVarError {
|
||||
var: env_key.clone(),
|
||||
instructions: instructions.clone(),
|
||||
})
|
||||
})?;
|
||||
Ok(CoreAuthProvider {
|
||||
token: Some(token),
|
||||
account_id: None,
|
||||
})
|
||||
}
|
||||
ProviderAuthKind::StaticBearer { token } => Ok(CoreAuthProvider {
|
||||
token: Some(token.clone()),
|
||||
account_id: None,
|
||||
}),
|
||||
ProviderAuthKind::OpenAi | ProviderAuthKind::CommandBearer { .. } => {
|
||||
if let Some(auth) = auth {
|
||||
let token = auth.get_token()?;
|
||||
Ok(CoreAuthProvider {
|
||||
token: Some(token),
|
||||
account_id: auth.get_account_id(),
|
||||
})
|
||||
} else {
|
||||
Ok(CoreAuthProvider {
|
||||
token: None,
|
||||
account_id: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
ProviderAuthKind::None => Ok(CoreAuthProvider {
|
||||
token: None,
|
||||
account_id: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -102,13 +154,17 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn runtime_auth_adapter_delegates_bearer_auth_to_legacy_provider() {
|
||||
fn runtime_auth_adapter_uses_resolved_static_bearer_auth() {
|
||||
let provider = bearer_provider();
|
||||
let runtime = resolve_model_provider(
|
||||
let mut runtime = resolve_model_provider(
|
||||
"custom",
|
||||
&provider,
|
||||
&ProviderResolutionPolicy::with_enabled_provider_ids(["custom".to_string()]),
|
||||
);
|
||||
let ProviderRuntime::Resolved(resolved) = &mut runtime else {
|
||||
panic!("enabled provider should resolve through the provider framework");
|
||||
};
|
||||
resolved.info.experimental_bearer_token = None;
|
||||
|
||||
let legacy = auth_provider_from_auth(None, &provider).expect("legacy auth");
|
||||
let resolved = auth_provider_from_runtime(None, &runtime, &provider).expect("runtime auth");
|
||||
@@ -118,13 +174,18 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn runtime_auth_adapter_delegates_env_key_errors_to_legacy_provider() {
|
||||
fn runtime_auth_adapter_uses_resolved_env_key_errors() {
|
||||
let provider = missing_env_key_provider();
|
||||
let runtime = resolve_model_provider(
|
||||
let mut runtime = resolve_model_provider(
|
||||
"custom",
|
||||
&provider,
|
||||
&ProviderResolutionPolicy::with_enabled_provider_ids(["custom".to_string()]),
|
||||
);
|
||||
let ProviderRuntime::Resolved(resolved) = &mut runtime else {
|
||||
panic!("enabled provider should resolve through the provider framework");
|
||||
};
|
||||
resolved.info.env_key = None;
|
||||
resolved.info.env_key_instructions = None;
|
||||
|
||||
let legacy = match auth_provider_from_auth(None, &provider) {
|
||||
Ok(_) => panic!("missing env key should fail"),
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use codex_model_provider::ProviderAuthKind;
|
||||
use codex_model_provider::ProviderRuntime;
|
||||
use codex_model_provider_info::ModelProviderInfo;
|
||||
use codex_otel::AuthEnvTelemetryMetadata;
|
||||
|
||||
@@ -31,13 +33,50 @@ impl AuthEnvTelemetry {
|
||||
pub fn collect_auth_env_telemetry(
|
||||
provider: &ModelProviderInfo,
|
||||
codex_api_key_env_enabled: bool,
|
||||
) -> AuthEnvTelemetry {
|
||||
let provider_env_key = provider.env_key.as_deref();
|
||||
collect_auth_env_telemetry_for_env_key(provider_env_key, codex_api_key_env_enabled)
|
||||
}
|
||||
|
||||
pub fn collect_auth_env_telemetry_for_runtime(
|
||||
provider_runtime: &ProviderRuntime,
|
||||
legacy_provider: &ModelProviderInfo,
|
||||
codex_api_key_env_enabled: bool,
|
||||
) -> AuthEnvTelemetry {
|
||||
match provider_runtime {
|
||||
ProviderRuntime::Legacy => {
|
||||
collect_auth_env_telemetry(legacy_provider, codex_api_key_env_enabled)
|
||||
}
|
||||
ProviderRuntime::Resolved(provider) => {
|
||||
collect_auth_env_telemetry_for_provider_auth(&provider.auth, codex_api_key_env_enabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn collect_auth_env_telemetry_for_provider_auth(
|
||||
provider_auth: &ProviderAuthKind,
|
||||
codex_api_key_env_enabled: bool,
|
||||
) -> AuthEnvTelemetry {
|
||||
let provider_env_key = match provider_auth {
|
||||
ProviderAuthKind::EnvBearer { env_key, .. } => Some(env_key.as_str()),
|
||||
ProviderAuthKind::OpenAi
|
||||
| ProviderAuthKind::StaticBearer { .. }
|
||||
| ProviderAuthKind::CommandBearer { .. }
|
||||
| ProviderAuthKind::None => None,
|
||||
};
|
||||
collect_auth_env_telemetry_for_env_key(provider_env_key, codex_api_key_env_enabled)
|
||||
}
|
||||
|
||||
fn collect_auth_env_telemetry_for_env_key(
|
||||
provider_env_key: Option<&str>,
|
||||
codex_api_key_env_enabled: bool,
|
||||
) -> AuthEnvTelemetry {
|
||||
AuthEnvTelemetry {
|
||||
openai_api_key_env_present: env_var_present(OPENAI_API_KEY_ENV_VAR),
|
||||
codex_api_key_env_present: env_var_present(CODEX_API_KEY_ENV_VAR),
|
||||
codex_api_key_env_enabled,
|
||||
provider_env_key_name: provider.env_key.as_ref().map(|_| "configured".to_string()),
|
||||
provider_env_key_present: provider.env_key.as_deref().map(env_var_present),
|
||||
provider_env_key_name: provider_env_key.map(|_| "configured".to_string()),
|
||||
provider_env_key_present: provider_env_key.map(env_var_present),
|
||||
refresh_token_url_override_present: env_var_present(REFRESH_TOKEN_URL_OVERRIDE_ENV_VAR),
|
||||
}
|
||||
}
|
||||
@@ -53,6 +92,9 @@ fn env_var_present(name: &str) -> bool {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use codex_model_provider::ProviderResolutionPolicy;
|
||||
use codex_model_provider::ProviderRuntime;
|
||||
use codex_model_provider::resolve_model_provider;
|
||||
use codex_model_provider_info::WireApi;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
@@ -85,4 +127,45 @@ mod tests {
|
||||
Some("configured".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn runtime_auth_env_telemetry_uses_resolved_provider_auth() {
|
||||
let provider = ModelProviderInfo {
|
||||
name: "Custom".to_string(),
|
||||
base_url: None,
|
||||
env_key: Some("PATH".to_string()),
|
||||
env_key_instructions: None,
|
||||
experimental_bearer_token: None,
|
||||
auth: None,
|
||||
wire_api: WireApi::Responses,
|
||||
query_params: None,
|
||||
http_headers: None,
|
||||
env_http_headers: None,
|
||||
request_max_retries: None,
|
||||
stream_max_retries: None,
|
||||
stream_idle_timeout_ms: None,
|
||||
websocket_connect_timeout_ms: None,
|
||||
requires_openai_auth: false,
|
||||
supports_websockets: false,
|
||||
};
|
||||
let mut runtime = resolve_model_provider(
|
||||
"custom",
|
||||
&provider,
|
||||
&ProviderResolutionPolicy::with_enabled_provider_ids(["custom".to_string()]),
|
||||
);
|
||||
let ProviderRuntime::Resolved(resolved) = &mut runtime else {
|
||||
panic!("enabled provider should resolve through the provider framework");
|
||||
};
|
||||
resolved.info.env_key = None;
|
||||
|
||||
let telemetry = collect_auth_env_telemetry_for_runtime(
|
||||
&runtime, &provider, /*codex_api_key_env_enabled*/ false,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
telemetry.provider_env_key_name,
|
||||
Some("configured".to_string())
|
||||
);
|
||||
assert_eq!(telemetry.provider_env_key_present, Some(true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use codex_model_provider::ProviderAuthKind;
|
||||
use codex_model_provider::ProviderRuntime;
|
||||
use codex_model_provider_info::ModelProviderInfo;
|
||||
|
||||
@@ -23,11 +24,27 @@ pub fn auth_manager_for_provider_runtime(
|
||||
provider_runtime: &ProviderRuntime,
|
||||
legacy_provider: &ModelProviderInfo,
|
||||
) -> Option<Arc<AuthManager>> {
|
||||
let provider = match provider_runtime {
|
||||
ProviderRuntime::Legacy => legacy_provider,
|
||||
ProviderRuntime::Resolved(provider) => &provider.info,
|
||||
};
|
||||
auth_manager_for_provider(auth_manager, provider)
|
||||
match provider_runtime {
|
||||
ProviderRuntime::Legacy => auth_manager_for_provider(auth_manager, legacy_provider),
|
||||
ProviderRuntime::Resolved(provider) => {
|
||||
auth_manager_for_provider_auth(auth_manager, &provider.auth)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn auth_manager_for_provider_auth(
|
||||
auth_manager: Option<Arc<AuthManager>>,
|
||||
provider_auth: &ProviderAuthKind,
|
||||
) -> Option<Arc<AuthManager>> {
|
||||
match provider_auth {
|
||||
ProviderAuthKind::CommandBearer { config } => {
|
||||
Some(AuthManager::external_bearer_only(config.clone()))
|
||||
}
|
||||
ProviderAuthKind::OpenAi
|
||||
| ProviderAuthKind::EnvBearer { .. }
|
||||
| ProviderAuthKind::StaticBearer { .. }
|
||||
| ProviderAuthKind::None => auth_manager,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an auth manager for request paths that always require authentication.
|
||||
@@ -83,13 +100,17 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn runtime_auth_manager_adapter_delegates_command_auth_to_legacy_provider() {
|
||||
fn runtime_auth_manager_adapter_uses_resolved_command_auth() {
|
||||
let provider = provider_with_command_auth();
|
||||
let runtime = resolve_model_provider(
|
||||
let mut runtime = resolve_model_provider(
|
||||
"custom",
|
||||
&provider,
|
||||
&ProviderResolutionPolicy::with_enabled_provider_ids(["custom".to_string()]),
|
||||
);
|
||||
let ProviderRuntime::Resolved(resolved) = &mut runtime else {
|
||||
panic!("enabled provider should resolve through the provider framework");
|
||||
};
|
||||
resolved.info.auth = None;
|
||||
|
||||
assert!(auth_manager_for_provider(None, &provider).is_some());
|
||||
assert!(auth_manager_for_provider_runtime(None, &runtime, &provider).is_some());
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
use codex_model_provider_info::ModelProviderInfo;
|
||||
use codex_model_provider_info::WireApi;
|
||||
use codex_protocol::config_types::ModelProviderAuthInfo;
|
||||
use codex_protocol::error::Result as CodexResult;
|
||||
use codex_protocol::openai_models::ModelsResponse;
|
||||
use serde::Deserialize;
|
||||
@@ -20,18 +21,13 @@ use std::time::Duration;
|
||||
pub const PROVIDER_FRAMEWORK_ENABLED_PROVIDER_IDS: &[&str] = &[];
|
||||
|
||||
/// Runtime strategy selected for the active model provider.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
pub enum ProviderRuntime {
|
||||
/// Preserve the existing provider implementation.
|
||||
#[default]
|
||||
Legacy,
|
||||
/// Use provider-owned runtime strategies.
|
||||
Resolved(ResolvedModelProvider),
|
||||
}
|
||||
|
||||
impl Default for ProviderRuntime {
|
||||
fn default() -> Self {
|
||||
Self::Legacy
|
||||
}
|
||||
Resolved(Box<ResolvedModelProvider>),
|
||||
}
|
||||
|
||||
/// Runtime provider object resolved from config-facing provider metadata.
|
||||
@@ -57,17 +53,20 @@ impl ResolvedModelProvider {
|
||||
}
|
||||
|
||||
/// Provider-owned authentication strategy.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
pub enum ProviderAuthKind {
|
||||
/// Preserve the existing provider-auth behavior for resolved test providers.
|
||||
Legacy,
|
||||
/// OpenAI-managed auth.
|
||||
OpenAi,
|
||||
/// Bearer token read from a configured environment variable.
|
||||
EnvBearer { env_key: String },
|
||||
EnvBearer {
|
||||
env_key: String,
|
||||
instructions: Option<String>,
|
||||
},
|
||||
/// Bearer token read from provider config.
|
||||
StaticBearer { token: String },
|
||||
/// Command-backed bearer token.
|
||||
CommandBearer,
|
||||
CommandBearer { config: ModelProviderAuthInfo },
|
||||
/// No provider auth is required.
|
||||
None,
|
||||
}
|
||||
@@ -169,7 +168,10 @@ pub fn resolve_model_provider(
|
||||
return ProviderRuntime::Legacy;
|
||||
}
|
||||
|
||||
ProviderRuntime::Resolved(resolve_generic_model_provider(provider_id, provider))
|
||||
ProviderRuntime::Resolved(Box::new(resolve_generic_model_provider(
|
||||
provider_id,
|
||||
provider,
|
||||
)))
|
||||
}
|
||||
|
||||
fn resolve_generic_model_provider(
|
||||
@@ -179,7 +181,7 @@ fn resolve_generic_model_provider(
|
||||
ResolvedModelProvider {
|
||||
id: provider_id.to_string(),
|
||||
info: provider.clone(),
|
||||
auth: ProviderAuthKind::Legacy,
|
||||
auth: resolve_provider_auth(provider),
|
||||
model_catalog: ProviderModelCatalog::Legacy,
|
||||
transport: ProviderTransport {
|
||||
base_url: provider.base_url.clone(),
|
||||
@@ -191,6 +193,27 @@ fn resolve_generic_model_provider(
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_provider_auth(provider: &ModelProviderInfo) -> ProviderAuthKind {
|
||||
if let Some(env_key) = &provider.env_key {
|
||||
ProviderAuthKind::EnvBearer {
|
||||
env_key: env_key.clone(),
|
||||
instructions: provider.env_key_instructions.clone(),
|
||||
}
|
||||
} else if let Some(token) = &provider.experimental_bearer_token {
|
||||
ProviderAuthKind::StaticBearer {
|
||||
token: token.clone(),
|
||||
}
|
||||
} else if let Some(config) = &provider.auth {
|
||||
ProviderAuthKind::CommandBearer {
|
||||
config: config.clone(),
|
||||
}
|
||||
} else if provider.requires_openai_auth {
|
||||
ProviderAuthKind::OpenAi
|
||||
} else {
|
||||
ProviderAuthKind::None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -318,7 +341,7 @@ mod tests {
|
||||
};
|
||||
assert_eq!(resolved.id, OPENAI_PROVIDER_ID);
|
||||
assert_eq!(resolved.info, *provider);
|
||||
assert_eq!(resolved.auth, ProviderAuthKind::Legacy);
|
||||
assert_eq!(resolved.auth, ProviderAuthKind::OpenAi);
|
||||
assert_eq!(resolved.model_catalog, ProviderModelCatalog::Legacy);
|
||||
assert_eq!(
|
||||
resolved.capabilities,
|
||||
@@ -326,6 +349,84 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enabled_policy_resolves_env_bearer_auth() {
|
||||
let provider = ModelProviderInfo {
|
||||
name: "custom".to_string(),
|
||||
base_url: Some("https://example.com/v1".to_string()),
|
||||
env_key: Some("CUSTOM_API_KEY".to_string()),
|
||||
env_key_instructions: Some("set CUSTOM_API_KEY".to_string()),
|
||||
experimental_bearer_token: None,
|
||||
auth: None,
|
||||
wire_api: WireApi::Responses,
|
||||
query_params: None,
|
||||
http_headers: None,
|
||||
env_http_headers: None,
|
||||
request_max_retries: None,
|
||||
stream_max_retries: None,
|
||||
stream_idle_timeout_ms: None,
|
||||
websocket_connect_timeout_ms: None,
|
||||
requires_openai_auth: false,
|
||||
supports_websockets: false,
|
||||
};
|
||||
let ProviderRuntime::Resolved(resolved) = resolve_model_provider(
|
||||
"custom",
|
||||
&provider,
|
||||
&ProviderResolutionPolicy::with_enabled_provider_ids(["custom".to_string()]),
|
||||
) else {
|
||||
panic!("enabled provider should resolve through the provider framework");
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
resolved.auth,
|
||||
ProviderAuthKind::EnvBearer {
|
||||
env_key: "CUSTOM_API_KEY".to_string(),
|
||||
instructions: Some("set CUSTOM_API_KEY".to_string()),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enabled_policy_resolves_command_bearer_auth() {
|
||||
let auth = ModelProviderAuthInfo {
|
||||
command: "print-token".to_string(),
|
||||
args: Vec::new(),
|
||||
timeout_ms: NonZeroU64::MIN,
|
||||
refresh_interval_ms: 0,
|
||||
cwd: AbsolutePathBuf::resolve_path_against_base(".", "/tmp"),
|
||||
};
|
||||
let provider = ModelProviderInfo {
|
||||
name: "custom".to_string(),
|
||||
base_url: Some("https://example.com/v1".to_string()),
|
||||
env_key: None,
|
||||
env_key_instructions: None,
|
||||
experimental_bearer_token: None,
|
||||
auth: Some(auth.clone()),
|
||||
wire_api: WireApi::Responses,
|
||||
query_params: None,
|
||||
http_headers: None,
|
||||
env_http_headers: None,
|
||||
request_max_retries: None,
|
||||
stream_max_retries: None,
|
||||
stream_idle_timeout_ms: None,
|
||||
websocket_connect_timeout_ms: None,
|
||||
requires_openai_auth: false,
|
||||
supports_websockets: false,
|
||||
};
|
||||
let ProviderRuntime::Resolved(resolved) = resolve_model_provider(
|
||||
"custom",
|
||||
&provider,
|
||||
&ProviderResolutionPolicy::with_enabled_provider_ids(["custom".to_string()]),
|
||||
) else {
|
||||
panic!("enabled provider should resolve through the provider framework");
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
resolved.auth,
|
||||
ProviderAuthKind::CommandBearer { config: auth }
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generic_resolved_provider_uses_legacy_api_provider_adapter() {
|
||||
let providers =
|
||||
|
||||
Reference in New Issue
Block a user