sz_rust_capability/
capability.rs1use async_trait::async_trait;
5use serde::Serialize;
6
7use crate::error::CapResult;
8use crate::source::CapabilitySource;
9
10#[async_trait]
44pub trait Capability: Send + Sync + 'static {
45 fn name(&self) -> &'static str;
47
48 fn description(&self) -> &'static str;
50
51 fn schema(&self) -> serde_json::Value;
53
54 fn tags(&self) -> &[&'static str];
56
57 fn source(&self) -> CapabilitySource;
59
60 async fn call(&self, args: serde_json::Value) -> CapResult<serde_json::Value>;
62
63 fn version(&self) -> &'static str {
65 "1.0.0"
66 }
67
68 fn requires_confirmation(&self) -> bool {
70 false
71 }
72
73 async fn validate_args(&self, args: &serde_json::Value) -> CapResult<()> {
76 crate::registry::validate_json_schema(&self.schema(), args)
77 }
78}
79
80#[derive(Debug, Clone, Serialize)]
82pub struct CapabilityInfo {
83 pub name: &'static str,
84 pub description: &'static str,
85 pub tags: Vec<&'static str>,
86 pub source: CapabilitySource,
87 pub version: &'static str,
88 pub requires_confirmation: bool,
89}
90
91impl CapabilityInfo {
92 pub fn from_trait(cap: &dyn Capability) -> Self {
94 Self {
95 name: cap.name(),
96 description: cap.description(),
97 tags: cap.tags().to_vec(),
98 source: cap.source(),
99 version: cap.version(),
100 requires_confirmation: cap.requires_confirmation(),
101 }
102 }
103}
104#[cfg(test)]
105mod tests {
106 use super::*;
107 use async_trait::async_trait;
108 use serde_json::json;
109
110 struct TestCap;
111
112 #[async_trait]
113 impl Capability for TestCap {
114 fn name(&self) -> &'static str {
115 "test.cap"
116 }
117 fn description(&self) -> &'static str {
118 "测试能力"
119 }
120 fn schema(&self) -> serde_json::Value {
121 json!({"type": "object"})
122 }
123 fn tags(&self) -> &[&'static str] {
124 &["test", "demo"]
125 }
126 fn source(&self) -> CapabilitySource {
127 CapabilitySource::Skill
128 }
129 async fn call(&self, args: serde_json::Value) -> CapResult<serde_json::Value> {
130 Ok(args)
131 }
132 }
133
134 struct CustomVersionCap;
135
136 #[async_trait]
137 impl Capability for CustomVersionCap {
138 fn name(&self) -> &'static str {
139 "custom.version"
140 }
141 fn description(&self) -> &'static str {
142 "自定义版本能力"
143 }
144 fn schema(&self) -> serde_json::Value {
145 json!({})
146 }
147 fn tags(&self) -> &[&'static str] {
148 &[]
149 }
150 fn source(&self) -> CapabilitySource {
151 CapabilitySource::Plugin
152 }
153 fn version(&self) -> &'static str {
154 "2.0.0"
155 }
156 fn requires_confirmation(&self) -> bool {
157 true
158 }
159 async fn call(&self, _: serde_json::Value) -> CapResult<serde_json::Value> {
160 Ok(json!({}))
161 }
162 }
163
164 #[test]
165 fn test_capability_info_from_trait_defaults() {
166 let cap = TestCap;
167 let info = CapabilityInfo::from_trait(&cap);
168 assert_eq!(info.name, "test.cap");
169 assert_eq!(info.description, "测试能力");
170 assert_eq!(info.tags, vec!["test", "demo"]);
171 assert_eq!(info.source, CapabilitySource::Skill);
172 assert_eq!(info.version, "1.0.0");
173 assert!(!info.requires_confirmation);
174 }
175
176 #[test]
177 fn test_capability_info_from_trait_custom() {
178 let cap = CustomVersionCap;
179 let info = CapabilityInfo::from_trait(&cap);
180 assert_eq!(info.name, "custom.version");
181 assert_eq!(info.version, "2.0.0");
182 assert!(info.requires_confirmation);
183 assert_eq!(info.source, CapabilitySource::Plugin);
184 assert!(info.tags.is_empty());
185 }
186
187 #[tokio::test]
188 async fn test_capability_default_validate_args() {
189 let cap = TestCap;
190 let result = cap.validate_args(&json!({"key": "value"})).await;
191 assert!(result.is_ok());
192 }
193
194 #[test]
195 fn test_capability_info_serialize() {
196 let cap = TestCap;
197 let info = CapabilityInfo::from_trait(&cap);
198 let json = serde_json::to_string(&info).expect("序列化失败");
199 assert!(json.contains("test.cap"));
200 assert!(json.contains("测试能力"));
201 }
202}