1#![allow(dead_code)]
8
9use crate::agency::agent::Agent;
10use crate::agency::error::{AgencyError, AgencyResult};
11use crate::agency::executor::{ExecutionContext, ExecutionResult, Executor};
12use crate::agency::models::AgencyEvent;
13use crate::agency::orchestrator::{Orchestrator, OrchestratorResult, Pipeline, Swarm};
14use crate::agency::session::{Session, SessionManager};
15use crate::agency::tools::ToolRegistry;
16use serde::{Deserialize, Serialize};
17use std::collections::HashMap;
18use std::path::PathBuf;
19use std::sync::Arc;
20use tokio::sync::mpsc;
21
22#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct RuntimeConfig {
25 pub db_path: PathBuf,
27 pub default_model: String,
29 pub max_tool_calls: u32,
31 pub timeout_seconds: u64,
33 pub streaming: bool,
35 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
37 pub api_keys: HashMap<String, String>,
38}
39
40impl Default for RuntimeConfig {
41 fn default() -> Self {
42 Self {
43 db_path: PathBuf::from("Agency_sessions.db"),
44 default_model: "gemini-2.5-flash".to_string(),
45 max_tool_calls: 10,
46 timeout_seconds: 120,
47 streaming: true,
48 api_keys: HashMap::new(),
49 }
50 }
51}
52
53pub struct Runtime {
55 config: RuntimeConfig,
56 tool_registry: Arc<ToolRegistry>,
57 session_manager: Arc<SessionManager>,
58 executor: Arc<Executor>,
59 orchestrator: Orchestrator,
60 agents: HashMap<String, Arc<Agent>>,
61}
62
63impl Runtime {
64 pub fn new() -> AgencyResult<Self> {
66 Self::with_config(RuntimeConfig::default())
67 }
68
69 pub fn with_config(config: RuntimeConfig) -> AgencyResult<Self> {
71 let tool_registry = Arc::new(ToolRegistry::with_builtins());
72 let session_manager = Arc::new(SessionManager::new(&config.db_path)?);
73 let executor = Arc::new(Executor::new(tool_registry.clone()));
74 let orchestrator = Orchestrator::new(executor.clone());
75
76 Ok(Self {
77 config,
78 tool_registry,
79 session_manager,
80 executor,
81 orchestrator,
82 agents: HashMap::new(),
83 })
84 }
85
86 pub fn in_memory() -> AgencyResult<Self> {
88 let tool_registry = Arc::new(ToolRegistry::with_builtins());
89 let session_manager = Arc::new(SessionManager::in_memory()?);
90 let executor = Arc::new(Executor::new(tool_registry.clone()));
91 let orchestrator = Orchestrator::new(executor.clone());
92
93 Ok(Self {
94 config: RuntimeConfig::default(),
95 tool_registry,
96 session_manager,
97 executor,
98 orchestrator,
99 agents: HashMap::new(),
100 })
101 }
102
103 pub fn register_agent(&mut self, agent: Agent) {
105 self.agents
106 .insert(agent.name().to_string(), Arc::new(agent));
107 }
108
109 pub fn get_agent(&self, name: &str) -> Option<&Arc<Agent>> {
111 self.agents.get(name)
112 }
113
114 pub fn list_agents(&self) -> Vec<&str> {
116 self.agents.keys().map(|s| s.as_str()).collect()
117 }
118
119 pub fn tools(&self) -> &ToolRegistry {
121 &self.tool_registry
122 }
123
124 pub fn sessions(&self) -> &SessionManager {
126 &self.session_manager
127 }
128
129 pub async fn run(
131 &self,
132 agent_name: &str,
133 message: &str,
134 options: Option<RunOptions>,
135 ) -> AgencyResult<ExecutionResult> {
136 let options = options.unwrap_or_default();
137
138 let agent_arc = self
140 .agents
141 .get(agent_name)
142 .ok_or_else(|| AgencyError::AgentNotFound(agent_name.to_string()))?;
143
144 let mut session = if let Some(session_id) = &options.session_id {
146 self.session_manager
147 .get(session_id)?
148 .ok_or_else(|| AgencyError::SessionNotFound(session_id.clone()))?
149 } else {
150 self.session_manager
151 .create(agent_name, options.user_id.clone())?
152 };
153
154 let mut ctx = ExecutionContext::new(&session);
156 ctx.user_id = options.user_id;
157 ctx.allow_tools = options.allow_tools;
158 ctx.max_tool_calls = options.max_tool_calls.unwrap_or(self.config.max_tool_calls);
159 ctx.event_sender = options.event_sender;
160
161 let result = self
163 .executor
164 .execute(agent_arc.as_ref(), &mut session, message, &mut ctx)
165 .await?;
166
167 self.session_manager.save(&session)?;
169
170 Ok(result)
171 }
172
173 pub async fn run_stream(
175 &self,
176 agent_name: &str,
177 message: &str,
178 options: Option<RunOptions>,
179 ) -> AgencyResult<(ExecutionResult, mpsc::Receiver<AgencyEvent>)> {
180 let (tx, rx) = mpsc::channel(100);
181 let mut options = options.unwrap_or_default();
182 options.event_sender = Some(tx);
183
184 let result = self.run(agent_name, message, Some(options)).await?;
185 Ok((result, rx))
186 }
187
188 pub async fn run_pipeline(
190 &self,
191 pipeline: &Pipeline,
192 input: &str,
193 options: Option<RunOptions>,
194 ) -> AgencyResult<OrchestratorResult> {
195 let options = options.unwrap_or_default();
196
197 let session = Session::new(&pipeline.name, options.user_id.clone());
198 let mut ctx = ExecutionContext::new(&session);
199 ctx.user_id = options.user_id;
200 ctx.allow_tools = options.allow_tools;
201 ctx.event_sender = options.event_sender;
202
203 self.orchestrator
204 .run_pipeline(pipeline, input, &mut ctx)
205 .await
206 }
207
208 pub async fn run_swarm(
210 &self,
211 swarm: &Swarm,
212 input: &str,
213 options: Option<RunOptions>,
214 ) -> AgencyResult<OrchestratorResult> {
215 let options = options.unwrap_or_default();
216
217 let session = Session::new(&swarm.name, options.user_id.clone());
218 let mut ctx = ExecutionContext::new(&session);
219 ctx.user_id = options.user_id;
220 ctx.allow_tools = options.allow_tools;
221 ctx.event_sender = options.event_sender;
222
223 self.orchestrator.run_swarm(swarm, input, &mut ctx).await
224 }
225
226 pub fn create_session(
228 &self,
229 agent_name: &str,
230 user_id: Option<String>,
231 ) -> AgencyResult<Session> {
232 self.session_manager.create(agent_name, user_id)
233 }
234
235 pub fn get_session(&self, session_id: &str) -> AgencyResult<Option<Session>> {
237 self.session_manager.get(session_id)
238 }
239
240 pub fn list_sessions(
242 &self,
243 agent_name: &str,
244 limit: Option<u32>,
245 ) -> AgencyResult<Vec<Session>> {
246 self.session_manager.list_by_agent(agent_name, limit)
247 }
248
249 pub fn delete_session(&self, session_id: &str) -> AgencyResult<bool> {
251 self.session_manager.delete(session_id)
252 }
253}
254
255#[derive(Debug, Clone, Default)]
257pub struct RunOptions {
258 pub session_id: Option<String>,
260 pub user_id: Option<String>,
262 pub allow_tools: bool,
264 pub max_tool_calls: Option<u32>,
266 pub event_sender: Option<mpsc::Sender<AgencyEvent>>,
268}
269
270impl RunOptions {
271 pub fn new() -> Self {
272 Self {
273 allow_tools: true,
274 ..Default::default()
275 }
276 }
277
278 pub fn with_session(mut self, session_id: impl Into<String>) -> Self {
279 self.session_id = Some(session_id.into());
280 self
281 }
282
283 pub fn with_user(mut self, user_id: impl Into<String>) -> Self {
284 self.user_id = Some(user_id.into());
285 self
286 }
287
288 pub fn with_tools(mut self, allow: bool) -> Self {
289 self.allow_tools = allow;
290 self
291 }
292}
293
294#[cfg(test)]
295mod tests {
296 use super::*;
297 use crate::agency::agent::AgentBuilder;
298
299 #[tokio::test]
300 #[ignore = "Integration test - requires API credentials"]
301 async fn test_runtime() -> AgencyResult<()> {
302 let mut runtime = Runtime::in_memory()?;
303
304 let agent = AgentBuilder::new("assistant")
305 .description("A helpful assistant")
306 .instruction("You are a helpful AI assistant.")
307 .model("gemini-2.5-flash")
308 .build();
309
310 runtime.register_agent(agent);
311
312 let result = runtime.run("assistant", "Hello!", None).await?;
313 assert!(result.success);
314 assert!(!result.response.is_empty());
315
316 Ok(())
317 }
318
319 #[tokio::test]
320 #[ignore = "Integration test - requires API credentials"]
321 async fn test_runtime_sessions() -> AgencyResult<()> {
322 let mut runtime = Runtime::in_memory()?;
323
324 let agent = AgentBuilder::new("test_agent")
325 .instruction("You are a test agent.")
326 .build();
327
328 runtime.register_agent(agent);
329
330 let session = runtime.create_session("test_agent", Some("user1".to_string()))?;
332 assert_eq!(session.agent_name, "test_agent");
333
334 let options = RunOptions::new()
336 .with_session(&session.id)
337 .with_user("user1");
338
339 let result = runtime
340 .run("test_agent", "Test message", Some(options))
341 .await?;
342 assert!(result.success);
343
344 let updated_session = runtime.get_session(&session.id)?.unwrap();
346 assert!(!updated_session.messages.is_empty());
347
348 Ok(())
349 }
350}