agent_diva_agent/agent_loop/
loop_tools.rs1use super::{AgentLoop, ToolConfig};
2use crate::tool_assembly::{SubagentSpawner, ToolAssembly};
3use crate::tool_config::network::NetworkToolConfig;
4use agent_diva_core::config::MCPServerConfig;
5use agent_diva_tooling::ToolError;
6use std::collections::HashMap;
7use std::sync::Arc;
8use tracing::info;
9
10struct RuntimeSubagentSpawner {
11 manager: Arc<crate::subagent::SubagentManager>,
12}
13
14#[async_trait::async_trait]
15impl SubagentSpawner for RuntimeSubagentSpawner {
16 async fn spawn(
17 &self,
18 task: String,
19 label: Option<String>,
20 channel: String,
21 chat_id: String,
22 ) -> Result<String, ToolError> {
23 self.manager
24 .spawn(task, label, channel, chat_id)
25 .await
26 .map_err(|e| ToolError::ExecutionFailed(e.to_string()))
27 }
28}
29
30impl AgentLoop {
31 pub fn register_default_tools(&mut self, tool_config: ToolConfig) {
33 self.tool_config = tool_config.clone();
34 let mut assembly = ToolAssembly::new(self.workspace.clone())
35 .builtin(tool_config.builtin)
36 .with_network_config(tool_config.network)
37 .with_exec_timeout(tool_config.exec_timeout)
38 .restrict_to_workspace(tool_config.restrict_to_workspace)
39 .mcp_servers(tool_config.mcp_servers)
40 .with_subagent_spawner(Arc::new(RuntimeSubagentSpawner {
41 manager: self.subagent_manager.clone(),
42 }))
43 .with_file_manager(self.file_manager.clone());
44 if let Some(cron_service) = tool_config.cron_service {
45 assembly = assembly.with_cron_service(cron_service);
46 }
47 self.tools = assembly.build();
48 }
49
50 pub(super) async fn apply_network_config(&mut self, network: NetworkToolConfig) {
51 self.tool_config.network = network.clone();
52 self.tools.unregister("web_search");
53 self.tools.unregister("web_fetch");
54 if self.tool_config.builtin.web_search && network.web.search.enabled {
55 self.tools.register(Arc::new(
56 agent_diva_tools::WebSearchTool::with_provider_and_max_results(
57 network.web.search.provider.clone(),
58 network.web.search.api_key.clone(),
59 network.web.search.normalized_max_results(),
60 ),
61 ));
62 }
63 if self.tool_config.builtin.web_fetch && network.web.fetch.enabled {
64 self.tools
65 .register(Arc::new(agent_diva_tools::WebFetchTool::new()));
66 }
67 self.subagent_manager.update_network_config(network).await;
68 info!("Applied runtime network tool configuration update");
69 }
70
71 pub(super) async fn apply_mcp_config(&mut self, servers: HashMap<String, MCPServerConfig>) {
72 self.tool_config.mcp_servers = servers.clone();
73 for name in self
74 .tools
75 .tool_names()
76 .into_iter()
77 .filter(|name| name.starts_with("mcp_"))
78 {
79 self.tools.unregister(&name);
80 }
81
82 if self.tool_config.builtin.mcp {
83 for mcp_tool in agent_diva_tools::load_mcp_tools_sync(&servers) {
84 self.tools.register(mcp_tool);
85 }
86 }
87
88 self.subagent_manager.update_mcp_servers(servers).await;
89
90 info!("Applied runtime MCP tool configuration update");
91 }
92}