1use mofa_foundation::llm::{LLMError, LLMResult, Tool, ToolExecutor};
4use mofa_plugins::{ToolCall, ToolDefinition, ToolPlugin};
5use std::sync::Arc;
6use tokio::sync::RwLock;
7
8pub struct ToolPluginExecutor {
13 tool_plugin: Arc<RwLock<ToolPlugin>>,
14 cached_tools: Arc<RwLock<Option<Vec<Tool>>>>,
15}
16
17impl ToolPluginExecutor {
18 pub fn new(tool_plugin: ToolPlugin) -> Self {
20 Self {
21 tool_plugin: Arc::new(RwLock::new(tool_plugin)),
22 cached_tools: Arc::new(RwLock::new(None)),
23 }
24 }
25
26 pub fn with_shared(tool_plugin: Arc<RwLock<ToolPlugin>>) -> Self {
28 Self {
29 tool_plugin,
30 cached_tools: Arc::new(RwLock::new(None)),
31 }
32 }
33
34 pub fn tool_plugin(&self) -> Arc<RwLock<ToolPlugin>> {
36 self.tool_plugin.clone()
37 }
38
39 pub async fn invalidate_cache(&self) {
41 let mut cache = self.cached_tools.write().await;
42 *cache = None;
43 }
44
45 pub async fn refresh_tools(&self) -> LLMResult<Vec<Tool>> {
47 let plugin = self.tool_plugin.read().await;
48 let tools = plugin
49 .list_tools()
50 .into_iter()
51 .map(|def| Self::definition_to_tool(&def))
52 .collect::<Vec<_>>();
53
54 let mut cache = self.cached_tools.write().await;
55 *cache = Some(tools.clone());
56 Ok(tools)
57 }
58
59 fn definition_to_tool(def: &ToolDefinition) -> Tool {
60 Tool::function(&def.name, &def.description, def.parameters.clone())
61 }
62}
63
64#[async_trait::async_trait]
65impl ToolExecutor for ToolPluginExecutor {
66 async fn execute(&self, name: &str, arguments: &str) -> LLMResult<String> {
67 let args: serde_json::Value = serde_json::from_str(arguments)
68 .map_err(|e| LLMError::Other(format!("参数解析失败: {}", e)))?;
69
70 let call = ToolCall {
71 call_id: uuid::Uuid::now_v7().to_string(),
72 name: name.to_string(),
73 arguments: args,
74 };
75
76 let mut plugin = self.tool_plugin.write().await;
77 let result = plugin
78 .call_tool(call)
79 .await
80 .map_err(|e| LLMError::Other(format!("工具执行失败: {}", e)))?;
81
82 if result.success {
83 serde_json::to_string(&result.result)
84 .map_err(|e| LLMError::Other(format!("结果序列化失败: {}", e)))
85 } else {
86 Err(LLMError::Other(
87 result.error.unwrap_or_else(|| "未知错误".to_string()),
88 ))
89 }
90 }
91
92 async fn available_tools(&self) -> LLMResult<Vec<Tool>> {
93 let cached = { self.cached_tools.read().await.clone() };
94 if let Some(tools) = cached {
95 return Ok(tools);
96 }
97
98 self.refresh_tools().await
99 }
100}