新增: 初始化 DevFlow 项目仓库
Tauri 2 + Vue 3 + Vite 6 桌面应用,Rust workspace 含 13 个 crate (df-ai / df-storage / df-workflow / df-core / df-execute 等)。 核心能力:AI 聊天 agentic 循环(工具调用+人工审批)、工作流引擎、 任务/想法/项目/阶段管理、可追溯性,及配套前端组件。
This commit is contained in:
73
crates/df-execute/src/shell.rs
Normal file
73
crates/df-execute/src/shell.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
//! Shell 执行器 — 通过 tokio::process 执行 shell 命令
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Shell 命令执行结果
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ShellResult {
|
||||
/// 标准输出
|
||||
pub stdout: String,
|
||||
/// 标准错误
|
||||
pub stderr: String,
|
||||
/// 退出码
|
||||
pub exit_code: Option<i32>,
|
||||
/// 执行耗时(毫秒)
|
||||
pub duration_ms: u64,
|
||||
}
|
||||
|
||||
/// Shell 命令执行请求
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ShellRequest {
|
||||
/// 要执行的命令
|
||||
pub command: String,
|
||||
/// 工作目录
|
||||
pub working_dir: Option<String>,
|
||||
/// 环境变量
|
||||
pub env: std::collections::HashMap<String, String>,
|
||||
/// 超时时间(秒),None 表示不超时
|
||||
pub timeout_secs: Option<u64>,
|
||||
}
|
||||
|
||||
/// 执行 Shell 命令
|
||||
///
|
||||
/// TODO: 完整实现,支持超时、环境变量、工作目录等
|
||||
pub async fn execute(request: ShellRequest) -> anyhow::Result<ShellResult> {
|
||||
let start = std::time::Instant::now();
|
||||
|
||||
let mut cmd = if cfg!(windows) {
|
||||
let mut c = tokio::process::Command::new("cmd");
|
||||
c.arg("/C").arg(&request.command);
|
||||
c
|
||||
} else {
|
||||
let mut c = tokio::process::Command::new("sh");
|
||||
c.arg("-c").arg(&request.command);
|
||||
c
|
||||
};
|
||||
|
||||
if let Some(dir) = &request.working_dir {
|
||||
cmd.current_dir(dir);
|
||||
}
|
||||
|
||||
for (key, value) in &request.env {
|
||||
cmd.env(key, value);
|
||||
}
|
||||
|
||||
let output = match request.timeout_secs {
|
||||
Some(secs) => tokio::time::timeout(
|
||||
std::time::Duration::from_secs(secs),
|
||||
cmd.output(),
|
||||
)
|
||||
.await
|
||||
.map_err(|_| anyhow::anyhow!("命令执行超时: {}秒", secs))??,
|
||||
None => cmd.output().await?,
|
||||
};
|
||||
|
||||
let duration = start.elapsed().as_millis() as u64;
|
||||
|
||||
Ok(ShellResult {
|
||||
stdout: String::from_utf8_lossy(&output.stdout).to_string(),
|
||||
stderr: String::from_utf8_lossy(&output.stderr).to_string(),
|
||||
exit_code: output.status.code(),
|
||||
duration_ms: duration,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user