use super::{
AuthState, ProviderCredential, codex_credential_from_store, read_auth,
resolve_provider_credential,
};
use crate::config::{
CliConfigOverrides, ConfigError, EffectiveConfig, McPaths, Settings, read_settings,
reject_retired_provider_selection, resolve_output_style,
};
impl EffectiveConfig {
pub(crate) fn from_loaded_settings(
paths: McPaths,
cli: CliConfigOverrides,
settings: Settings,
) -> anyhow::Result<Self> {
let (color_enabled, _) = resolve_output_style(&settings, cli.color);
let (provider, model) = Self::selected_provider_model(&settings);
let provider = cli.provider.or(provider);
let model = cli.model.or(model);
let provider_id = provider
.as_deref()
.unwrap_or(crate::provider_ids::OPENAI_CODEX_PROVIDER);
reject_retired_provider_selection(provider_id, model.as_deref().unwrap_or(""))?;
let auth_file = read_auth(&paths)?;
let auth = resolve_provider_credential(
provider_id,
&auth_file,
cli.api_key,
&settings.custom_providers,
)?;
Ok(Self {
provider,
model,
no_color: !color_enabled,
file_autocomplete_respects_gitignore: settings.file_autocomplete_respects_gitignore,
custom_providers: settings.custom_providers,
thinking_level: settings.selected_model.thinking_level.unwrap_or_default(),
auth,
paths,
})
}
pub(crate) fn auth_state(&self) -> AuthState {
AuthState::for_provider_with_custom(
self.provider_id(),
self.auth.as_ref(),
&self.custom_providers,
)
}
pub(crate) fn require_auth(&self) -> Result<ProviderCredential, ConfigError> {
self.auth_state()
.credential()
.cloned()
.ok_or_else(|| self.missing_auth_error())
}
pub(crate) fn resolve_provider_auth_for_runtime(&self) -> anyhow::Result<ProviderCredential> {
self.resolve_provider_auth_for_runtime_with(codex_credential_from_store)
}
fn resolve_provider_auth_for_runtime_with(
&self,
prepare_codex_auth: impl FnOnce(&McPaths) -> anyhow::Result<ProviderCredential>,
) -> anyhow::Result<ProviderCredential> {
if self.provider_id() == crate::provider_ids::ANTHROPIC_PROVIDER {
return resolve_provider_credential(
self.provider_id(),
&read_auth(&self.paths)?,
None,
&self.custom_providers,
)?
.ok_or_else(|| self.missing_auth_error().into());
}
if self.provider_id() == crate::provider_ids::CLAUDE_SUBSCRIPTION_PROVIDER {
return resolve_provider_credential(
self.provider_id(),
&read_auth(&self.paths)?,
None,
&self.custom_providers,
)?
.ok_or_else(|| self.missing_auth_error().into());
}
if self.provider_id() != crate::provider_ids::OPENAI_CODEX_PROVIDER {
return self.require_auth().map_err(Into::into);
}
prepare_codex_auth(&self.paths)
}
}
pub(crate) fn load_effective_provider_selection(
paths: &McPaths,
provider: &str,
model: &str,
) -> anyhow::Result<EffectiveConfig> {
load_effective_provider_selection_with_settings(paths, provider, model, &read_settings(paths)?)
}
pub(crate) fn load_effective_provider_selection_with_settings(
paths: &McPaths,
provider: &str,
model: &str,
settings: &Settings,
) -> anyhow::Result<EffectiveConfig> {
reject_retired_provider_selection(provider, model)?;
let auth_file = read_auth(paths)?;
let auth = resolve_provider_credential(provider, &auth_file, None, &settings.custom_providers)?;
let (color_enabled, _) = resolve_output_style(settings, None);
Ok(EffectiveConfig {
provider: Some(provider.to_string()),
model: Some(model.to_string()),
no_color: !color_enabled,
file_autocomplete_respects_gitignore: settings.file_autocomplete_respects_gitignore,
custom_providers: settings.custom_providers.clone(),
thinking_level: settings.selected_model.thinking_level.unwrap_or_default(),
auth,
paths: paths.clone(),
})
}