use crate::layout::Layout;
use crate::provider::{ManifestError, Provider};
include!(concat!(env!("OUT_DIR"), "/builtin_manifests.rs"));
#[derive(Debug, Clone, Default)]
pub struct Registry {
providers: Vec<Provider>,
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[error("unknown provider `{id}` (known: {})", known.join(", "))]
pub struct UnknownProvider {
pub id: String,
pub known: Vec<String>,
}
impl Registry {
pub fn builtin(layout: &Layout) -> Result<Self, ManifestError> {
Self::load(
layout,
BUILTIN_MANIFESTS.iter().map(|(name, text)| (*name, *text)),
)
}
pub fn load<'a>(
layout: &Layout,
sources: impl IntoIterator<Item = (&'a str, &'a str)>,
) -> Result<Self, ManifestError> {
let mut registry = Self::default();
for (name, text) in sources {
let provider =
crate::provider::parse(name, text, |kind| layout.canonical(kind).clone())?;
registry.insert(provider);
}
registry.providers.sort_by(|a, b| a.id.cmp(&b.id));
Ok(registry)
}
pub fn with_local<'a>(
layout: &Layout,
locals: impl IntoIterator<Item = (&'a str, &'a str)>,
) -> Result<Self, ManifestError> {
let mut registry = Self::builtin(layout)?;
for (name, text) in locals {
let provider =
crate::provider::parse(name, text, |kind| layout.canonical(kind).clone())?;
registry.insert(provider);
}
registry.providers.sort_by(|a, b| a.id.cmp(&b.id));
Ok(registry)
}
fn insert(&mut self, provider: Provider) {
self.providers.retain(|existing| existing.id != provider.id);
self.providers.push(provider);
}
pub fn all(&self) -> &[Provider] {
&self.providers
}
pub fn get(&self, id: &str) -> Option<&Provider> {
self.providers.iter().find(|provider| provider.id == id)
}
pub fn ids(&self) -> Vec<String> {
self.providers
.iter()
.map(|provider| provider.id.clone())
.collect()
}
pub fn select(&self, ids: Option<&[String]>) -> Result<Vec<&Provider>, UnknownProvider> {
match ids {
None => Ok(self.providers.iter().collect()),
Some(ids) => ids
.iter()
.map(|id| {
self.get(id).ok_or_else(|| UnknownProvider {
id: id.clone(),
known: self.ids(),
})
})
.collect(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::model::{ResourceKind, Strategy};
#[test]
fn every_shipped_manifest_is_valid() {
let registry = Registry::builtin(&Layout::default()).expect("shipped manifests must parse");
assert!(!registry.all().is_empty(), "no providers were embedded");
}
#[test]
fn shipped_manifests_have_unique_ids() {
let registry = Registry::builtin(&Layout::default()).unwrap();
let mut ids = registry.ids();
let total = ids.len();
ids.sort();
ids.dedup();
assert_eq!(
ids.len(),
total,
"duplicate provider ids among shipped manifests"
);
}
#[test]
fn the_reference_providers_are_present_and_correct() {
let registry = Registry::builtin(&Layout::default()).unwrap();
let claude = registry.get("claude-code").expect("claude-code manifest");
let instructions = claude.capability(ResourceKind::Instructions).unwrap();
assert_eq!(instructions.strategy, Strategy::Link);
assert_eq!(instructions.path.as_str(), "CLAUDE.md");
assert!(
instructions.has_import_fallback(),
"CLAUDE.md cannot be symlinked on unprivileged Windows, so a fallback is required"
);
let agy = registry.get("antigravity").expect("antigravity manifest");
for &resource in ResourceKind::ALL {
assert_eq!(
agy.capability(resource).unwrap().strategy,
Strategy::Native,
"antigravity should need no work for {resource}"
);
}
}
#[test]
fn most_capabilities_need_no_writes_at_all() {
let registry = Registry::builtin(&Layout::default()).unwrap();
let (native, total) = registry.all().iter().flat_map(|p| &p.capabilities).fold(
(0, 0),
|(native, total), cap| {
(
native + usize::from(cap.strategy == Strategy::Native),
total + 1,
)
},
);
assert!(
native * 2 > total,
"expected a majority of native capabilities, got {native}/{total}"
);
}
#[test]
fn local_manifests_override_shipped_ones_by_id() {
let layout = Layout::default();
let registry = Registry::load(
&layout,
[
("a.toml", "schema = 1\nid = \"dup\"\nname = \"First\"\n"),
("b.toml", "schema = 1\nid = \"dup\"\nname = \"Second\"\n"),
],
)
.unwrap();
assert_eq!(registry.all().len(), 1);
assert_eq!(registry.get("dup").unwrap().name, "Second");
}
#[test]
fn selecting_an_unknown_provider_lists_the_valid_ones() {
let registry = Registry::builtin(&Layout::default()).unwrap();
let err = registry.select(Some(&["nope".to_string()])).unwrap_err();
assert_eq!(err.id, "nope");
assert!(err.known.contains(&"claude-code".to_string()));
}
#[test]
fn selecting_none_yields_every_provider() {
let registry = Registry::builtin(&Layout::default()).unwrap();
assert_eq!(registry.select(None).unwrap().len(), registry.all().len());
}
}