pub mod model;
pub mod models_dev;
pub mod override_;
pub mod provider;
pub mod runtime;
pub use model::{BuiltinModelEntry, builtin_model_count, load_builtin_models};
pub use models_dev::enrich as enrich_from_models_dev;
pub use models_dev::{MdCatalog, enrich, get as models_dev_get, init_models_dev, provider_map};
pub use override_::{
OverrideFile, apply_model_overrides, apply_provider_overrides, find_override_files,
load_overrides,
};
pub use provider::{
AuthMethod, BuiltinProviderEntry, builtin_providers_count, load_builtin_providers,
};
pub use runtime::{discover_all, discover_all_authenticated, discover_all_local, discover_models};
use std::sync::OnceLock;
static CATALOG: OnceLock<CatalogRoot> = OnceLock::new();
#[derive(Debug, Clone, serde::Deserialize)]
pub struct CatalogRoot {
#[serde(default)]
pub provider: Vec<BuiltinProviderEntry>,
#[serde(default)]
pub models: std::collections::BTreeMap<String, Vec<BuiltinModelEntry>>,
}
impl CatalogRoot {
pub fn get() -> &'static Self {
CATALOG.get_or_init(|| {
let providers_toml = include_str!("../../data/catalog/providers.toml");
let mut root: CatalogRoot = toml::from_str(providers_toml).expect(
"BUG: built-in providers.toml failed to parse. \
This is a build-time error — the file is validated at startup. \
Run `cargo test -p oxi-ai catalog` to reproduce.",
);
let model_dir_models = load_all_model_files();
for (provider_id, models) in model_dir_models {
root.models.insert(provider_id, models);
}
root
})
}
pub fn find_provider(&self, name: &str) -> Option<&BuiltinProviderEntry> {
self.provider
.iter()
.find(|p| p.id == name || p.aliases.iter().any(|a| a == name))
}
pub fn resolve_provider_id(&self, name: &str) -> Option<&str> {
self.find_provider(name).map(|p| p.id.as_str())
}
pub fn models_for(&self, provider_id: &str) -> &[BuiltinModelEntry] {
self.models
.get(provider_id)
.map(|v| v.as_slice())
.unwrap_or(&[])
}
}
fn load_all_model_files() -> std::collections::BTreeMap<String, Vec<BuiltinModelEntry>> {
let mut out: std::collections::BTreeMap<String, Vec<BuiltinModelEntry>> =
std::collections::BTreeMap::new();
for (_provider_id, toml_str) in model::models_index() {
match toml::from_str::<ModelFile>(toml_str) {
Ok(file) => {
out.entry(file.provider).or_default().extend(file.model);
}
Err(e) => {
panic!(
"BUG: built-in model file failed to parse: {e}\n\
TOML:\n{toml_str}"
);
}
}
}
out
}
#[derive(Debug, serde::Deserialize)]
struct ModelFile {
provider: String,
#[serde(default)]
model: Vec<BuiltinModelEntry>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn catalog_loads() {
let root = CatalogRoot::get();
assert!(
!root.provider.is_empty(),
"providers.toml should not be empty"
);
}
#[test]
fn all_providers_have_unique_ids() {
let root = CatalogRoot::get();
let mut seen = std::collections::HashSet::new();
for p in &root.provider {
assert!(seen.insert(&p.id), "duplicate provider id: {}", p.id);
}
}
#[test]
fn all_provider_aliases_resolve() {
let root = CatalogRoot::get();
for p in &root.provider {
for alias in &p.aliases {
let resolved = root.resolve_provider_id(alias);
assert!(resolved.is_some(), "alias {alias} does not resolve");
}
}
}
#[test]
fn find_provider_by_id_and_alias() {
let root = CatalogRoot::get();
assert!(root.find_provider("anthropic").is_some());
assert!(root.find_provider("kimi").is_some()); assert!(root.find_provider("nonexistent").is_none());
}
}