feat(stardomain): 实现完整的沙箱执行引擎(local + Docker 双模式)

local 模式通过 tokio::process 真实执行命令,Docker 模式通过 bollard 创建容器运行,
两种模式均支持超时强杀、输出捕获和策略过滤。同时提供同步和异步 Python 接口。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-04 11:07:39 +00:00
parent 32bdbe77ff
commit 0bbd08638c
6 changed files with 331 additions and 28 deletions
+47 -9
View File
@@ -8,16 +8,54 @@
* http://www.apache.org/licenses/LICENSE-2.0
*/
/// Executor: responsible for running commands either locally or in Docker.
/// This is a stub — actual Docker execution will be implemented later.
pub struct Executor;
use std::time::Duration;
use tokio::process::Command;
use tokio::time::timeout;
impl Executor {
pub fn run_local(_command: &str) -> (String, String, i32) {
("".to_string(), "".to_string(), 0)
}
use crate::sandbox::SandboxResult;
pub fn run_docker(_command: &str) -> (String, String, i32) {
("".to_string(), "[stardomain] Docker execution not yet implemented".to_string(), 1)
pub async fn run_local(
command: &str,
workspace: &str,
timeout_secs: u64,
) -> SandboxResult {
let fut = Command::new("sh")
.arg("-c")
.arg(command)
.current_dir(workspace)
.output();
match timeout(Duration::from_secs(timeout_secs), fut).await {
Ok(Ok(output)) => SandboxResult {
stdout: String::from_utf8_lossy(&output.stdout).to_string(),
stderr: String::from_utf8_lossy(&output.stderr).to_string(),
exit_code: output.status.code().unwrap_or(-1),
killed_by_timeout: false,
},
Ok(Err(e)) => SandboxResult {
stdout: String::new(),
stderr: format!("执行失败: {}", e),
exit_code: -1,
killed_by_timeout: false,
},
Err(_) => SandboxResult {
stdout: String::new(),
stderr: "执行超时".to_string(),
exit_code: -1,
killed_by_timeout: true,
},
}
}
pub async fn run_python_local(
code: &str,
workspace: &str,
timeout_secs: u64,
) -> SandboxResult {
let cmd = format!("python3 -c {}", shell_escape(code));
run_local(&cmd, workspace, timeout_secs).await
}
fn shell_escape(s: &str) -> String {
format!("'{}'", s.replace('\'', "'\\''"))
}
@@ -35,4 +35,13 @@ impl SandboxResult {
killed_by_timeout: false,
}
}
pub fn error(msg: &str) -> Self {
SandboxResult {
stdout: String::new(),
stderr: msg.to_string(),
exit_code: -1,
killed_by_timeout: false,
}
}
}