agent_diva_agent/agent_loop/
loop_tools.rs1use super::{AgentLoop, ToolConfig};
2use crate::tool_config::network::NetworkToolConfig;
3use agent_diva_core::config::MCPServerConfig;
4use agent_diva_memory::WorkspaceMemoryService;
5use agent_diva_tools::{
6 load_mcp_tools_sync, CronTool, DiaryListTool, DiaryReadTool, EditFileTool, ExecTool,
7 ListDirTool, MemoryGetTool, MemoryRecallTool, MemorySearchTool, ReadFileTool, SpawnTool,
8 ToolError, ToolRegistry, WebFetchTool, WebSearchTool, WriteFileTool,
9};
10use std::collections::HashMap;
11use std::sync::Arc;
12use tracing::info;
13
14impl AgentLoop {
15 pub fn register_default_tools(&mut self, tool_config: ToolConfig) {
17 let sm = self.subagent_manager.clone();
19 self.tools.register(Arc::new(SpawnTool::new(
20 move |task, label, channel, chat_id| {
21 let sm = sm.clone();
22 async move {
23 sm.spawn(task, label, channel, chat_id)
24 .await
25 .map_err(|e| ToolError::ExecutionFailed(e.to_string()))
26 }
27 },
28 )));
29
30 let allowed_dir = if tool_config.restrict_to_workspace {
32 Some(self.workspace.clone())
33 } else {
34 None
35 };
36 self.tools
37 .register(Arc::new(ReadFileTool::new(allowed_dir.clone())));
38 self.tools
39 .register(Arc::new(WriteFileTool::new(allowed_dir.clone())));
40 self.tools
41 .register(Arc::new(EditFileTool::new(allowed_dir.clone())));
42 self.tools.register(Arc::new(ListDirTool::new(allowed_dir)));
43 Self::register_memory_tools(&mut self.tools, self.memory_service.clone());
44
45 self.tools.register(Arc::new(ExecTool::with_config(
47 tool_config.exec_timeout,
48 Some(self.workspace.clone()),
49 tool_config.restrict_to_workspace,
50 )));
51
52 Self::register_web_tools(&mut self.tools, &tool_config.network);
54
55 for mcp_tool in load_mcp_tools_sync(&tool_config.mcp_servers) {
57 self.tools.register(mcp_tool);
58 }
59
60 if let Some(cron_service) = tool_config.cron_service {
62 self.tools.register(Arc::new(CronTool::new(cron_service)));
63 }
64 }
65
66 pub(super) fn register_memory_tools(
67 tools: &mut ToolRegistry,
68 service: Arc<WorkspaceMemoryService>,
69 ) {
70 tools.register(Arc::new(MemoryRecallTool::new(service.clone())));
71 tools.register(Arc::new(MemorySearchTool::new(service.clone())));
72 tools.register(Arc::new(MemoryGetTool::new(service.clone())));
73 tools.register(Arc::new(DiaryReadTool::new(service.clone())));
74 tools.register(Arc::new(DiaryListTool::new(service)));
75 }
76
77 pub(super) fn register_web_tools(tools: &mut ToolRegistry, network: &NetworkToolConfig) {
78 if network.web.search.enabled {
79 tools.register(Arc::new(WebSearchTool::with_provider_and_max_results(
80 network.web.search.provider.clone(),
81 network.web.search.api_key.clone(),
82 network.web.search.normalized_max_results(),
83 )));
84 }
85 if network.web.fetch.enabled {
86 tools.register(Arc::new(WebFetchTool::new()));
87 }
88 }
89
90 pub(super) async fn apply_network_config(&mut self, network: NetworkToolConfig) {
91 self.tools.unregister("web_search");
92 self.tools.unregister("web_fetch");
93 Self::register_web_tools(&mut self.tools, &network);
94 self.subagent_manager.update_network_config(network).await;
95 info!("Applied runtime network tool configuration update");
96 }
97
98 pub(super) async fn apply_mcp_config(&mut self, servers: HashMap<String, MCPServerConfig>) {
99 for name in self
100 .tools
101 .tool_names()
102 .into_iter()
103 .filter(|name| name.starts_with("mcp_"))
104 {
105 self.tools.unregister(&name);
106 }
107
108 for mcp_tool in load_mcp_tools_sync(&servers) {
109 self.tools.register(mcp_tool);
110 }
111
112 info!("Applied runtime MCP tool configuration update");
113 }
114}