starweaver_runtime/capability/
bundle.rs1use std::sync::Arc;
4
5use starweaver_model::{ModelRequestParameters, ModelSettings};
6use starweaver_tools::{DynTool, DynToolset, ToolRegistry};
7
8use starweaver_usage::UsageLimits;
9
10use crate::{
11 instructions::DynDynamicInstruction,
12 output::{DynOutputFunction, OutputValidator},
13};
14
15use super::{AgentCapability, CapabilitySpec};
16
17pub trait CapabilityBundle: Send + Sync {
19 fn name(&self) -> &str;
21
22 fn spec(&self) -> CapabilitySpec {
24 CapabilitySpec::new(self.name())
25 }
26
27 fn hooks(&self) -> Vec<Arc<dyn AgentCapability>> {
29 Vec::new()
30 }
31
32 fn stream_observers(&self) -> Vec<Arc<dyn AgentCapability>> {
34 Vec::new()
35 }
36
37 fn get_instructions(&self) -> Vec<String> {
39 Vec::new()
40 }
41
42 fn dynamic_instructions(&self) -> Vec<DynDynamicInstruction> {
44 Vec::new()
45 }
46
47 fn get_tools(&self) -> Option<ToolRegistry> {
49 None
50 }
51
52 fn model_settings(&self) -> Option<ModelSettings> {
54 None
55 }
56
57 fn request_params(&self) -> Option<ModelRequestParameters> {
59 None
60 }
61
62 fn output_functions(&self) -> Vec<DynOutputFunction> {
64 Vec::new()
65 }
66
67 fn output_validators(&self) -> Vec<Arc<dyn OutputValidator>> {
69 Vec::new()
70 }
71
72 fn usage_limits(&self) -> Option<UsageLimits> {
74 None
75 }
76}
77
78#[derive(Clone, Default)]
80pub struct StaticCapabilityBundle {
81 name: String,
82 spec: Option<CapabilitySpec>,
83 hooks: Vec<Arc<dyn AgentCapability>>,
84 stream_observers: Vec<Arc<dyn AgentCapability>>,
85 instructions: Vec<String>,
86 dynamic_instructions: Vec<DynDynamicInstruction>,
87 tools: ToolRegistry,
88 model_settings: Option<ModelSettings>,
89 request_params: Option<ModelRequestParameters>,
90 output_functions: Vec<DynOutputFunction>,
91 output_validators: Vec<Arc<dyn OutputValidator>>,
92 usage_limits: Option<UsageLimits>,
93}
94
95impl StaticCapabilityBundle {
96 #[must_use]
98 pub fn new(name: impl Into<String>) -> Self {
99 Self {
100 name: name.into(),
101 spec: None,
102 hooks: Vec::new(),
103 stream_observers: Vec::new(),
104 instructions: Vec::new(),
105 dynamic_instructions: Vec::new(),
106 tools: ToolRegistry::new(),
107 model_settings: None,
108 request_params: None,
109 output_functions: Vec::new(),
110 output_validators: Vec::new(),
111 usage_limits: None,
112 }
113 }
114
115 #[must_use]
117 pub fn with_spec(mut self, spec: CapabilitySpec) -> Self {
118 self.spec = Some(spec);
119 self
120 }
121
122 #[must_use]
124 pub fn with_hook(mut self, hook: Arc<dyn AgentCapability>) -> Self {
125 self.hooks.push(hook);
126 self
127 }
128
129 #[must_use]
131 pub fn with_stream_observer(mut self, observer: Arc<dyn AgentCapability>) -> Self {
132 self.stream_observers.push(observer);
133 self
134 }
135
136 #[must_use]
138 pub fn with_instruction(mut self, instruction: impl Into<String>) -> Self {
139 self.instructions.push(instruction.into());
140 self
141 }
142
143 #[must_use]
145 pub fn with_dynamic_instruction(mut self, instruction: DynDynamicInstruction) -> Self {
146 self.dynamic_instructions.push(instruction);
147 self
148 }
149
150 #[must_use]
152 pub fn with_tool(mut self, tool: DynTool) -> Self {
153 self.tools.insert(tool);
154 self
155 }
156
157 #[must_use]
159 pub fn with_toolset(mut self, toolset: &DynToolset) -> Self {
160 self.tools.insert_toolset(toolset);
161 self
162 }
163
164 #[must_use]
166 pub fn with_model_settings(mut self, settings: ModelSettings) -> Self {
167 self.model_settings = Some(settings);
168 self
169 }
170
171 #[must_use]
173 pub fn with_request_params(mut self, params: ModelRequestParameters) -> Self {
174 self.request_params = Some(params);
175 self
176 }
177
178 #[must_use]
180 pub fn with_output_function(mut self, function: DynOutputFunction) -> Self {
181 self.output_functions.push(function);
182 self
183 }
184
185 #[must_use]
187 pub fn with_output_validator(mut self, validator: Arc<dyn OutputValidator>) -> Self {
188 self.output_validators.push(validator);
189 self
190 }
191
192 #[must_use]
194 pub const fn with_usage_limits(mut self, limits: UsageLimits) -> Self {
195 self.usage_limits = Some(limits);
196 self
197 }
198}
199
200impl CapabilityBundle for StaticCapabilityBundle {
201 fn name(&self) -> &str {
202 &self.name
203 }
204
205 fn spec(&self) -> CapabilitySpec {
206 self.spec
207 .clone()
208 .unwrap_or_else(|| CapabilitySpec::new(self.name.clone()))
209 }
210
211 fn hooks(&self) -> Vec<Arc<dyn AgentCapability>> {
212 self.hooks.clone()
213 }
214
215 fn stream_observers(&self) -> Vec<Arc<dyn AgentCapability>> {
216 self.stream_observers.clone()
217 }
218
219 fn get_instructions(&self) -> Vec<String> {
220 self.instructions.clone()
221 }
222
223 fn dynamic_instructions(&self) -> Vec<DynDynamicInstruction> {
224 self.dynamic_instructions.clone()
225 }
226
227 fn get_tools(&self) -> Option<ToolRegistry> {
228 if self.tools.is_empty() && self.tools.get_instructions().is_empty() {
229 None
230 } else {
231 Some(self.tools.clone())
232 }
233 }
234
235 fn model_settings(&self) -> Option<ModelSettings> {
236 self.model_settings.clone()
237 }
238
239 fn request_params(&self) -> Option<ModelRequestParameters> {
240 self.request_params.clone()
241 }
242
243 fn output_functions(&self) -> Vec<DynOutputFunction> {
244 self.output_functions.clone()
245 }
246
247 fn output_validators(&self) -> Vec<Arc<dyn OutputValidator>> {
248 self.output_validators.clone()
249 }
250
251 fn usage_limits(&self) -> Option<UsageLimits> {
252 self.usage_limits.clone()
253 }
254}