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:
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user