Skip to main content

weft_core/app/
core_capabilities.rs

1use crate::app::{CapabilityProviderRecord, CapabilityRegistry, CapabilityRegistryEntry};
2
3pub fn merge_core_capabilities(registry: &mut CapabilityRegistry) {
4    register_core_capability(registry, "core.files");
5    register_core_capability(registry, "core.execution");
6}
7
8fn register_core_capability(registry: &mut CapabilityRegistry, capability: &str) {
9    let entry = registry
10        .entry(capability.to_string())
11        .or_insert_with(|| CapabilityRegistryEntry {
12            capability: capability.to_string(),
13            ..Default::default()
14        });
15
16    if !entry
17        .providers
18        .iter()
19        .any(|provider| provider.provider == "core" && provider.runtime == "core")
20    {
21        entry.providers.push(CapabilityProviderRecord {
22            provider: "core".into(),
23            runtime: "core".into(),
24            priority: 0,
25        });
26    }
27
28    entry.providers.sort_by(|left, right| {
29        left.provider
30            .cmp(&right.provider)
31            .then(left.runtime.cmp(&right.runtime))
32    });
33}
34
35#[cfg(test)]
36mod tests {
37    use super::merge_core_capabilities;
38    use crate::app::resolve::resolve_app_manifest_with_policy;
39    use crate::app::{build_capability_registry, AppManifest, ResolvedAppStatus};
40
41    #[test]
42    fn core_capabilities_are_added_to_registry() {
43        let mut registry = build_capability_registry(&[], &Default::default());
44        merge_core_capabilities(&mut registry);
45
46        let execution = registry
47            .get("core.execution")
48            .expect("core.execution should exist");
49        assert!(execution
50            .providers
51            .iter()
52            .any(|provider| provider.provider == "core" && provider.runtime == "core"));
53    }
54
55    #[test]
56    fn resolve_app_accepts_core_execution_binding() {
57        let manifest: AppManifest = toml::from_str(
58            r#"
59[app]
60name = "weft-claw"
61version = "0.1.0"
62display_name = "Weft Claw"
63description = "test"
64
65[requires]
66capabilities = ["core.execution"]
67
68[bindings.core.execution]
69provider = "core"
70mutable = false
71"#,
72        )
73        .expect("manifest parses");
74
75        let mut registry = build_capability_registry(&[], &Default::default());
76        merge_core_capabilities(&mut registry);
77
78        let resolved =
79            resolve_app_manifest_with_policy(&manifest, &[], None, None, Some(&registry), None)
80                .expect("core execution binding should resolve");
81
82        assert_eq!(resolved.status, ResolvedAppStatus::Resolved);
83        assert_eq!(resolved.bindings.len(), 1);
84        assert_eq!(resolved.bindings[0].capability, "core.execution");
85        assert_eq!(resolved.bindings[0].provider, "core");
86    }
87}