Skip to main content

matrixcode_core/workflow/executors/
proxy.rs

1//! Proxy Executor
2//!
3//! 代理工具执行器,包装 ProxyToolExecutor 为 NodeExecutor。
4
5use anyhow::{Context, Result};
6use async_trait::async_trait;
7use std::sync::Arc;
8
9use super::node_executor::NodeExecutor;
10use crate::tools::toolproxy::{ProxyToolDef, ProxyToolExecutor};
11use crate::workflow::context::WorkflowContext;
12use crate::workflow::def::NodeDef;
13use crate::workflow::template::TemplateRenderer;
14
15/// 代理工具执行器
16///
17/// 包装 ProxyToolExecutor 为 NodeExecutor,让 workflow 可以调用代理工具。
18pub struct ProxyExecutor {
19    /// 代理工具执行器
20    executor: Arc<dyn ProxyToolExecutor>,
21    /// 工具定义列表
22    tool_defs: Vec<ProxyToolDef>,
23    /// 模板渲染器
24    template_renderer: TemplateRenderer,
25}
26
27impl ProxyExecutor {
28    /// 创建新的代理执行器
29    pub fn new(executor: Arc<dyn ProxyToolExecutor>, tool_defs: Vec<ProxyToolDef>) -> Self {
30        Self {
31            executor,
32            tool_defs,
33            template_renderer: TemplateRenderer::new(),
34        }
35    }
36
37    /// 检查是否支持该工具
38    pub fn has_tool(&self, name: &str) -> bool {
39        self.tool_defs.iter().any(|t| t.definition.name == name)
40    }
41
42    /// 获取工具超时时间
43    pub fn get_timeout(&self, name: &str) -> u64 {
44        self.tool_defs
45            .iter()
46            .find(|t| t.definition.name == name)
47            .map(|t| t.timeout_ms)
48            .unwrap_or(30000)
49    }
50}
51
52#[async_trait]
53impl NodeExecutor for ProxyExecutor {
54    async fn execute(
55        &self,
56        node: &NodeDef,
57        context: &mut WorkflowContext,
58    ) -> Result<serde_json::Value> {
59        // 获取工具名称
60        let tool_name = node
61            .task
62            .as_ref()
63            .ok_or_else(|| anyhow::anyhow!("Proxy executor requires a task name"))?;
64
65        // 检查工具是否存在
66        if !self.has_tool(tool_name) {
67            return Err(anyhow::anyhow!("Proxy tool '{}' not found", tool_name));
68        }
69
70        // 渲染参数
71        let params = self
72            .template_renderer
73            .render_params(&node.params, &context.variables)?;
74
75        // 执行代理工具
76        let result = self
77            .executor
78            .exec(tool_name, params.clone())
79            .await
80            .with_context(|| format!("Proxy tool '{}' execution failed", tool_name))?;
81
82        // 解析结果
83        let output = if let Ok(json) = serde_json::from_str::<serde_json::Value>(&result) {
84            json
85        } else {
86            serde_json::json!({
87                "result": result,
88                "tool": tool_name,
89            })
90        };
91
92        // 更新上下文
93        if let serde_json::Value::Object(map) = &output {
94            for (key, value) in map {
95                context.set_variable(key.clone(), value.clone());
96            }
97        }
98
99        Ok(output)
100    }
101
102    fn name(&self) -> &str {
103        "proxy_executor"
104    }
105}