优化: AI模块(provider重试兼容+aichat交互+工具卡片可读化+diff高亮)

This commit is contained in:
2026-06-16 02:33:16 +08:00
parent d2cb38cdac
commit 10e4945e5a
26 changed files with 2337 additions and 332 deletions

View File

@@ -16,6 +16,24 @@ pub struct ShellResult {
pub duration_ms: u64,
}
/// Shell 类型选择
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum ShellType {
/// Windows cmd.exe (默认 Windows)
Cmd,
/// PowerShell
PowerShell,
/// Unix sh (默认非 Windows)
Sh,
}
impl Default for ShellType {
fn default() -> Self {
if cfg!(windows) { ShellType::Cmd } else { ShellType::Sh }
}
}
/// Shell 命令执行请求
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ShellRequest {
@@ -27,6 +45,9 @@ pub struct ShellRequest {
pub env: std::collections::HashMap<String, String>,
/// 超时时间None 表示不超时
pub timeout_secs: Option<u64>,
/// Shell 类型默认Windows→Cmd, 非Windows→Sh
#[serde(default)]
pub shell_type: Option<ShellType>,
}
/// 执行 Shell 命令
@@ -35,16 +56,26 @@ pub struct ShellRequest {
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.stdout(Stdio::piped()).stderr(Stdio::piped());
c
} else {
let mut c = tokio::process::Command::new("sh");
c.arg("-c").arg(&request.command);
c.stdout(Stdio::piped()).stderr(Stdio::piped());
c
let shell_type = request.shell_type.unwrap_or_default();
let mut cmd = match shell_type {
ShellType::PowerShell => {
let mut c = tokio::process::Command::new("powershell");
c.arg("-NoProfile").arg("-Command").arg(&request.command);
c.stdout(Stdio::piped()).stderr(Stdio::piped());
c
}
ShellType::Cmd => {
let mut c = tokio::process::Command::new("cmd");
c.arg("/C").arg(&request.command);
c.stdout(Stdio::piped()).stderr(Stdio::piped());
c
}
ShellType::Sh => {
let mut c = tokio::process::Command::new("sh");
c.arg("-c").arg(&request.command);
c.stdout(Stdio::piped()).stderr(Stdio::piped());
c
}
};
if let Some(dir) = &request.working_dir {