omniference 0.1.8

A multi-protocol inference engine with provider adapters
Documentation
use super::convert::raw_to_entry;
use super::raw::{RawCatalogEntry, RawProvider};
use super::schema::CatalogEntry;
use crate::types::ProviderKind;
use std::collections::HashMap;

pub fn provider_slug(kind: &ProviderKind, configured_slug: Option<&str>) -> Option<String> {
	if let Some(slug) = configured_slug {
		return Some(slug.to_string());
	}

	PROVIDER_SLUGS.iter().find_map(|(known_kind, slug)| (known_kind == kind).then(|| (*slug).to_string()))
}

pub fn parse_api_json(json: &str) -> anyhow::Result<Vec<(String, String, CatalogEntry)>> {
	let providers: HashMap<String, RawProvider> = serde_json::from_str(json)?;
	let mut entries = Vec::new();

	for (provider_slug, provider) in providers {
		let slug = provider.id.unwrap_or(provider_slug);
		for (model_id, mut raw) in provider.models {
			if raw.id.is_none() {
				raw.id = Some(model_id.clone());
			}
			entries.push((slug.clone(), model_id, raw_to_entry(raw)));
		}
	}

	Ok(entries)
}

pub fn raw_key(raw: &RawCatalogEntry) -> Option<(Option<String>, String)> {
	raw.id
		.as_ref()
		.map(|id| (raw.provider.as_ref().and_then(|provider| provider.as_str()).map(ToString::to_string), id.clone()))
		.or_else(|| raw.canonical.as_ref().map(|id| (None, id.clone())))
}

const PROVIDER_SLUGS: &[(ProviderKind, &str)] = &[
	(ProviderKind::OpenAI, "openai"),
	(ProviderKind::OpenRouter, "openrouter"),
	(ProviderKind::Anthropic, "anthropic"),
	(ProviderKind::Google, "google"),
];