pub mod config;
pub mod credentials;
pub mod provider;
mod runtime;
pub mod thinking;
pub mod values;
pub use provider::{ResolveError, ResolvedModel, RuntimeFactories as ProviderRegistry};
pub use runtime::{ModelIdentity, ModelSelection, Runtime, RuntimeSnapshot};
pub use values::ValueSource;
#[derive(Clone)]
pub struct ProviderDeclaration {
pub id: String,
pub models: Vec<rpi_ai::Model>,
pub api_key_env: Option<String>,
pub requires_auth: bool,
}
#[derive(Clone, Default, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RuntimeSettings {
pub default_provider: Option<String>,
pub default_model: Option<String>,
pub default_thinking_level: Option<String>,
pub theme: Option<String>,
pub http_idle_timeout_ms: Option<i64>,
}
#[derive(Default)]
pub struct ModelRequest<'a> {
pub provider: Option<&'a str>,
pub api: Option<rpi_ai::Api>,
pub model: Option<&'a str>,
pub thinking: Option<rpi_ai::ThinkingLevel>,
pub api_key: Option<&'a str>,
pub base_url: Option<&'a str>,
}
#[derive(Clone, Default)]
pub struct RuntimeConfig {
pub models: config::ModelsConfig,
pub credentials: config::AuthStore,
pub settings: RuntimeSettings,
}
impl RuntimeConfig {
pub fn auth_states(
&self,
providers: &ProviderRegistry,
values: &dyn ValueSource,
) -> std::collections::BTreeMap<String, credentials::AuthState> {
let mut ids: std::collections::BTreeSet<String> = provider::builtin_catalog()
.into_iter()
.map(|model| model.provider)
.collect();
ids.extend(self.models.providers.keys().cloned());
ids.extend(self.credentials.keys().cloned());
ids.extend(
providers
.manifests
.iter()
.map(|manifest| manifest.id.clone()),
);
ids.into_iter()
.map(|id| {
let state = self.auth_status(&id, providers, values);
(id, state)
})
.collect()
}
pub fn auth_status(
&self,
provider: &str,
providers: &ProviderRegistry,
values: &dyn ValueSource,
) -> credentials::AuthState {
credentials::state(
provider,
self.models.providers.get(provider),
&self.credentials,
providers
.manifests
.iter()
.find(|manifest| manifest.id == provider),
values,
|| {
provider::provider_has_auth_headers(
provider,
&self.models,
&providers.manifests,
values,
)
},
)
}
pub fn resolve(
&self,
request: &ModelRequest<'_>,
providers: &ProviderRegistry,
values: &dyn ValueSource,
) -> Result<ResolvedModel, ResolveError> {
provider::resolve_with_factories(request, self, providers, values)
}
pub fn catalog(
&self,
providers: &ProviderRegistry,
values: &dyn ValueSource,
) -> (Vec<rpi_ai::Model>, Vec<String>) {
provider::catalog_with_diagnostics(self.models.clone(), &providers.manifests, values)
}
}
#[cfg(test)]
mod test_host;