sz_rust_capability/
facade.rs1use std::sync::{Arc, OnceLock};
2
3use crate::capability::Capability;
4use crate::error::{CapError, CapResult};
5use crate::metrics::CapMetrics;
6use crate::permission::PermissionChecker;
7use crate::registry::CapabilityRegistry;
8use crate::source::CapabilitySource;
9
10struct CapInstance {
11 registry: Arc<CapabilityRegistry>,
12}
13
14static GLOBAL: OnceLock<CapInstance> = OnceLock::new();
15
16pub struct Cap;
29
30impl Cap {
31 pub fn init_with(registry: Arc<CapabilityRegistry>) -> CapResult<()> {
38 GLOBAL
39 .set(CapInstance { registry })
40 .map_err(|_| CapError::NotInitialized)
41 }
42
43 pub fn init() -> CapResult<()> {
44 Self::init_with(Arc::new(CapabilityRegistry::new()))
45 }
46
47 pub fn is_initialized() -> bool {
48 GLOBAL.get().is_some()
49 }
50
51 fn instance() -> CapResult<&'static CapInstance> {
52 GLOBAL.get().ok_or(CapError::NotInitialized)
53 }
54
55 pub fn register(cap: Arc<dyn Capability>) -> CapResult<Option<Arc<dyn Capability>>> {
56 Ok(Self::instance()?.registry.register(cap))
57 }
58
59 pub fn unregister(name: &str) -> CapResult<Option<Arc<dyn Capability>>> {
60 Ok(Self::instance()?.registry.unregister(name))
61 }
62
63 pub fn get(name: &str) -> CapResult<Option<Arc<dyn Capability>>> {
64 Ok(Self::instance()?.registry.get(name))
65 }
66
67 pub fn find_by_tags(
68 tags: &[&str],
69 source: Option<CapabilitySource>,
70 ) -> CapResult<Vec<Arc<dyn Capability>>> {
71 Ok(Self::instance()?.registry.find_by_tags(tags, source))
72 }
73
74 pub fn search(query: &str) -> CapResult<Vec<Arc<dyn Capability>>> {
75 Ok(Self::instance()?.registry.search(query))
76 }
77
78 pub fn list_all() -> CapResult<Vec<Arc<dyn Capability>>> {
79 Ok(Self::instance()?.registry.list_all())
80 }
81
82 pub fn list_by_source(source: CapabilitySource) -> CapResult<Vec<Arc<dyn Capability>>> {
83 Ok(Self::instance()?.registry.list_by_source(source))
84 }
85
86 pub async fn call(name: &str, args: serde_json::Value) -> CapResult<serde_json::Value> {
87 Self::instance()?.registry.call(name, args).await
88 }
89
90 pub async fn call_with_tenant(
92 name: &str,
93 args: serde_json::Value,
94 tenant_id: i64,
95 ) -> CapResult<serde_json::Value> {
96 Self::instance()?
97 .registry
98 .call_with_tenant(name, args, tenant_id)
99 .await
100 }
101
102 pub fn set_permission_checker(checker: Arc<dyn PermissionChecker>) -> CapResult<()> {
104 Self::instance()?.registry.set_permission_checker(checker);
105 Ok(())
106 }
107
108 pub fn metrics() -> CapResult<CapMetrics> {
109 Ok(Self::instance()?.registry.metrics())
110 }
111
112 pub fn len() -> CapResult<usize> {
113 Ok(Self::instance()?.registry.len())
114 }
115
116 pub fn is_empty() -> CapResult<bool> {
117 Ok(Self::instance()?.registry.is_empty())
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124 use async_trait::async_trait;
125 use serde_json::json;
126
127 struct TestCapability;
128
129 #[async_trait]
130 impl Capability for TestCapability {
131 fn name(&self) -> &'static str {
132 "test_cap"
133 }
134 fn description(&self) -> &'static str {
135 "测试能力"
136 }
137 fn schema(&self) -> serde_json::Value {
138 json!({})
139 }
140 fn tags(&self) -> &[&'static str] {
141 &["test"]
142 }
143 fn source(&self) -> CapabilitySource {
144 CapabilitySource::Skill
145 }
146 async fn call(&self, args: serde_json::Value) -> CapResult<serde_json::Value> {
147 Ok(args)
148 }
149 }
150
151 #[test]
152 fn test_facade_lifecycle() {
153 Cap::init().ok();
154 let cap = Arc::new(TestCapability) as Arc<dyn Capability>;
155 Cap::register(cap).unwrap();
156 assert!(Cap::get("test_cap").unwrap().is_some());
157 assert!(Cap::len().unwrap() >= 1);
158 }
159
160 #[tokio::test]
161 async fn test_call_through_facade() {
162 Cap::init().ok();
163 let cap = Arc::new(TestCapability) as Arc<dyn Capability>;
164 Cap::register(cap).ok();
165 let result = Cap::call("test_cap", json!({"hello": "world"})).await;
166 assert!(result.is_ok());
167 }
168}