weft_core/app/
core_capabilities.rs1use 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(®istry), 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}