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 crate::tools::toolproxy::{ProxyToolExecutor, ProxyToolDef};
10use crate::workflow::context::WorkflowContext;
11use crate::workflow::def::NodeDef;
12use crate::workflow::template::TemplateRenderer;
13use super::node_executor::NodeExecutor;
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.task.as_ref()
61            .ok_or_else(|| anyhow::anyhow!("Proxy executor requires a task name"))?;
62
63        // 检查工具是否存在
64        if !self.has_tool(tool_name) {
65            return Err(anyhow::anyhow!("Proxy tool '{}' not found", tool_name));
66        }
67
68        // 渲染参数
69        let params = self.template_renderer.render_params(&node.params, &context.variables)?;
70
71        // 执行代理工具
72        let result = self.executor.exec(tool_name, params.clone()).await
73            .with_context(|| format!("Proxy tool '{}' execution failed", tool_name))?;
74
75        // 解析结果
76        let output = if let Ok(json) = serde_json::from_str::<serde_json::Value>(&result) {
77            json
78        } else {
79            serde_json::json!({
80                "result": result,
81                "tool": tool_name,
82            })
83        };
84
85        // 更新上下文
86        if let serde_json::Value::Object(map) = &output {
87            for (key, value) in map {
88                context.set_variable(key.clone(), value.clone());
89            }
90        }
91
92        Ok(output)
93    }
94
95    fn name(&self) -> &str {
96        "proxy_executor"
97    }
98}