Files
DevFlow/crates/df-nodes/src/script_node.rs

96 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,
shell_type: Default::default(),
};
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"
}
}