Files
DevFlow/crates/df-nodes/src/script_node.rs
绝尘 98393b4908 新增: 初始化 DevFlow 项目仓库
Tauri 2 + Vue 3 + Vite 6 桌面应用,Rust workspace 含 13 个 crate
(df-ai / df-storage / df-workflow / df-core / df-execute 等)。
核心能力:AI 聊天 agentic 循环(工具调用+人工审批)、工作流引擎、
任务/想法/项目/阶段管理、可追溯性,及配套前端组件。
2026-06-12 01:31:05 +08:00

95 lines
2.8 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 脚本节点 — 执行 Shell 脚本或自定义命令
use async_trait::async_trait;
use df_workflow::node::{Node, NodeContext, NodeOutput, NodeResult, NodeSchema};
/// 脚本节点
pub struct ScriptNode;
#[async_trait]
impl Node for ScriptNode {
async fn execute(&self, ctx: NodeContext) -> NodeResult {
tracing::info!("ScriptNode 执行: {}", ctx.node_id);
// 从 config 解析 command必填
let command = ctx
.config
.get("command")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("ScriptNode 缺少必填参数: command"))?;
// 解析可选参数
let timeout_secs = ctx
.config
.get("timeout_secs")
.and_then(|v| v.as_u64());
let working_dir = ctx
.config
.get("working_dir")
.and_then(|v| v.as_str())
.map(|s| s.to_string());
// 构建请求并执行
let request = df_execute::shell::ShellRequest {
command: command.to_string(),
working_dir,
env: std::collections::HashMap::new(),
timeout_secs,
};
tracing::info!("ScriptNode 执行命令: {}", command);
let result = df_execute::shell::execute(request).await?;
// 非零退出码视为执行失败
let exit_code = result.exit_code.unwrap_or(-1);
if exit_code != 0 {
anyhow::bail!(
"脚本执行失败 (exit_code={}): {}",
exit_code,
result.stderr.trim()
);
}
tracing::info!(
"ScriptNode 完成: 耗时 {}ms, exit_code={}",
result.duration_ms,
exit_code
);
Ok(NodeOutput::from_value(serde_json::json!({
"stdout": result.stdout,
"stderr": result.stderr,
"exit_code": exit_code,
"duration_ms": result.duration_ms,
})))
}
fn schema(&self) -> NodeSchema {
NodeSchema {
params: serde_json::json!({
"type": "object",
"properties": {
"command": { "type": "string" },
"timeout_secs": { "type": "integer" },
"working_dir": { "type": "string" }
},
"required": ["command"]
}),
output: serde_json::json!({
"type": "object",
"properties": {
"stdout": { "type": "string" },
"stderr": { "type": "string" },
"exit_code": { "type": "integer" },
"duration_ms": { "type": "integer" }
}
}),
}
}
fn node_type(&self) -> &str {
"script"
}
}