修复: PowerShell 路径转义 + shell 失败提示 + 标题合并同 role + L0 防抖
- run_command 路径反斜杠传递修正 - 命令失败追加 PowerShell 适配提示引导 LLM 改正 - 标题生成前合并连续同 role 消息避免 Anthropic 1214 - V33 迁移追加 workflow_executions.updated_at 列 - ai-client-ready 3 秒防抖避免重复握手
This commit is contained in:
@@ -2316,8 +2316,13 @@ fn register_file_tools(
|
||||
]),
|
||||
RiskLevel::High,
|
||||
Box::new(|args: serde_json::Value| Box::pin(async move {
|
||||
// BUG-PWSH-BACKSLASH: 早期实现误把 command 当 JSON 字符串做反斜杠转义,导致
|
||||
// JSON 解析阶段把 `C:\\foo` 还原为 `C:\foo` 后再次转义丢失反斜杠。现直接 as_str()
|
||||
// 取值,不做任何转义处理 —— serde_json 已正确还原反斜杠,PowerShell 也正确接受裸
|
||||
// 反斜杠路径(实测 PS5/PS7 均无歧义),根因在 JSON 解析层而非 shell 层。
|
||||
let command = args["command"].as_str()
|
||||
.ok_or_else(|| anyhow::anyhow!("缺少 command 参数"))?;
|
||||
.ok_or_else(|| anyhow::anyhow!("缺少 command 参数"))?
|
||||
.to_string();
|
||||
// working_dir 默认空(由审批弹窗让用户填写),不走 workspace_root 编译期常量。
|
||||
// run_command 是 High risk 靠人工审批兜底,不捕获 allowed_dirs。
|
||||
let working_dir = match args.get("working_dir").and_then(|v| v.as_str()) {
|
||||
@@ -2332,7 +2337,7 @@ fn register_file_tools(
|
||||
let timeout_secs = args["timeout_secs"].as_u64().unwrap_or(DEFAULT_RUN_COMMAND_TIMEOUT_SECS).min(MAX_RUN_COMMAND_TIMEOUT_SECS);
|
||||
|
||||
let request = ShellRequest {
|
||||
command: command.to_string(),
|
||||
command: command.clone(),
|
||||
working_dir: Some(working_dir.clone()),
|
||||
env: HashMap::new(),
|
||||
timeout_secs: Some(timeout_secs),
|
||||
@@ -2344,15 +2349,24 @@ fn register_file_tools(
|
||||
// 新 tool_call_id → 重新 insert pending → 重新审批,「再过一会又提示 Run Command」循环。
|
||||
// 治本:超时根因处拦截,把 Err 内容改写为「明确超时语义 + 勿盲目重试」标注,
|
||||
// 让 LLM 知进程已终止、非命令失败,确需更长时限才在 args 提高 timeout_secs 重发。
|
||||
//
|
||||
// 任务2: 失败追加 shell 适配提示 —— Windows 默认 PowerShell(PS5 不支持 `&&`),
|
||||
// LLM 普遍按 Unix 习惯生成命令,常见失败: `cd .. && cmd`(PS5 拒 `&&`)、
|
||||
// 未引用反斜杠路径被解析为转义。提示让 LLM 下次能自行修正(机制优先 prompt 说教)。
|
||||
let shell_hint = if cfg!(windows) {
|
||||
"\n提示: PowerShell 下路径用正斜杠或双引号包裹(如 \"C:/Users\" 或 \"C:\\Users\"),命令间用 `;` 而非 `&&`(PS5),或改用 pwsh(PS7 支持 `&&`)"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let result = execute(request).await.map_err(|e| {
|
||||
let msg = e.to_string();
|
||||
if msg.contains("命令执行超时") {
|
||||
anyhow::anyhow!(
|
||||
"命令执行超时({}s),进程已终止。勿盲目重试同命令;确需更长时限重发时在 args 提高 timeout_secs。",
|
||||
timeout_secs
|
||||
"命令执行超时({}s),进程已终止。勿盲目重试同命令;确需更长时限重发时在 args 提高 timeout_secs。{}",
|
||||
timeout_secs, shell_hint
|
||||
)
|
||||
} else {
|
||||
e
|
||||
anyhow::anyhow!("{}{}", msg, shell_hint)
|
||||
}
|
||||
})?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user