1pub mod cache;
13pub mod executor;
14pub mod orchestrator;
15pub mod rate_limiter;
16pub mod result_store;
17pub mod subtask;
18
19pub use cache::{CacheConfig, CacheStats, SwarmCache};
20pub use executor::{SwarmExecutor, run_agent_loop};
21pub use orchestrator::Orchestrator;
22pub use rate_limiter::{AdaptiveRateLimiter, RateLimitInfo, RateLimitStats};
23pub use result_store::{ResultStore, ResultStoreContext, SharedResult, SubTaskStoreHandle};
24pub use subtask::{SubAgent, SubTask, SubTaskContext, SubTaskResult, SubTaskStatus};
25
26use anyhow::Result;
27use async_trait::async_trait;
28
29#[async_trait]
34pub trait Actor: Send + Sync {
35 fn actor_id(&self) -> &str;
37
38 fn actor_status(&self) -> ActorStatus;
40
41 async fn initialize(&mut self) -> Result<()>;
43
44 async fn shutdown(&mut self) -> Result<()>;
46}
47
48#[async_trait]
53pub trait Handler<M>: Actor {
54 type Response: Send + Sync;
56
57 async fn handle(&mut self, message: M) -> Result<Self::Response>;
59}
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub enum ActorStatus {
64 Initializing,
66 Ready,
68 Busy,
70 Paused,
72 ShuttingDown,
74 Stopped,
76}
77
78impl std::fmt::Display for ActorStatus {
79 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 match self {
81 ActorStatus::Initializing => write!(f, "initializing"),
82 ActorStatus::Ready => write!(f, "ready"),
83 ActorStatus::Busy => write!(f, "busy"),
84 ActorStatus::Paused => write!(f, "paused"),
85 ActorStatus::ShuttingDown => write!(f, "shutting_down"),
86 ActorStatus::Stopped => write!(f, "stopped"),
87 }
88 }
89}
90
91#[derive(Debug, Clone)]
93pub enum SwarmMessage {
94 ExecuteTask {
96 task_id: String,
97 instruction: String,
98 },
99 Progress {
101 task_id: String,
102 progress: f32,
103 message: String,
104 },
105 TaskCompleted { task_id: String, result: String },
107 TaskFailed { task_id: String, error: String },
109 ToolRequest {
111 tool_id: String,
112 arguments: serde_json::Value,
113 },
114 ToolResponse {
116 tool_id: String,
117 result: crate::tool::ToolResult,
118 },
119}
120
121use serde::{Deserialize, Serialize};
122
123pub const MAX_SUBAGENTS: usize = 100;
125
126pub const MAX_TOOL_CALLS: usize = 1500;
128
129#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct SwarmConfig {
132 pub max_subagents: usize,
134
135 pub max_steps_per_subagent: usize,
137
138 pub max_total_steps: usize,
140
141 pub subagent_timeout_secs: u64,
143
144 pub parallel_enabled: bool,
146
147 pub critical_path_threshold: usize,
149
150 pub model: Option<String>,
152
153 pub max_concurrent_requests: usize,
155
156 pub request_delay_ms: u64,
158
159 pub worktree_enabled: bool,
161
162 pub worktree_auto_merge: bool,
164
165 pub working_dir: Option<String>,
167}
168
169impl Default for SwarmConfig {
170 fn default() -> Self {
171 Self {
172 max_subagents: MAX_SUBAGENTS,
173 max_steps_per_subagent: 100,
174 max_total_steps: MAX_TOOL_CALLS,
175 subagent_timeout_secs: 600, parallel_enabled: true,
177 critical_path_threshold: 10,
178 model: Some("zai/glm-5".to_string()),
179 max_concurrent_requests: 3, request_delay_ms: 1000, worktree_enabled: true, worktree_auto_merge: true, working_dir: None,
184 }
185 }
186}
187
188#[derive(Debug, Clone, Default, Serialize, Deserialize)]
190pub struct SwarmStats {
191 pub subagents_spawned: usize,
193
194 pub subagents_completed: usize,
196
197 pub subagents_failed: usize,
199
200 pub total_tool_calls: usize,
202
203 pub critical_path_length: usize,
205
206 pub execution_time_ms: u64,
208
209 pub sequential_time_estimate_ms: u64,
211
212 pub speedup_factor: f64,
214
215 pub stages: Vec<StageStats>,
217
218 pub rate_limit_stats: RateLimitStats,
220}
221
222#[derive(Debug, Clone, Default, Serialize, Deserialize)]
224pub struct StageStats {
225 pub stage: usize,
227
228 pub subagent_count: usize,
230
231 pub max_steps: usize,
233
234 pub total_steps: usize,
236
237 pub execution_time_ms: u64,
239}
240
241impl SwarmStats {
242 pub fn calculate_speedup(&mut self) {
244 if self.execution_time_ms > 0 {
245 self.speedup_factor =
246 self.sequential_time_estimate_ms as f64 / self.execution_time_ms as f64;
247 }
248 }
249
250 pub fn calculate_critical_path(&mut self) {
252 self.critical_path_length = self.stages.iter().map(|s| s.max_steps).sum();
253 }
254}
255
256#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
258#[serde(rename_all = "snake_case")]
259pub enum DecompositionStrategy {
260 Automatic,
262
263 ByDomain,
265
266 ByData,
268
269 ByStage,
271
272 None,
274}
275
276impl Default for DecompositionStrategy {
277 fn default() -> Self {
278 Self::Automatic
279 }
280}
281
282#[derive(Debug, Clone, Serialize, Deserialize)]
284pub struct SwarmResult {
285 pub success: bool,
287
288 pub result: String,
290
291 pub subtask_results: Vec<SubTaskResult>,
293
294 pub stats: SwarmStats,
296
297 pub artifacts: Vec<SwarmArtifact>,
299
300 pub error: Option<String>,
302}
303
304#[derive(Debug, Clone, Serialize, Deserialize)]
306pub struct SwarmArtifact {
307 pub artifact_type: String,
309
310 pub name: String,
312
313 pub content: String,
315
316 pub source_subagent: Option<String>,
318
319 pub mime_type: Option<String>,
321}