修复: patch_file 小改动自动放行 + tool_result JSON 压缩 + prompt 项目路径

- C-260627: patch_file ≤5 行自动放行,不阻塞 AI 工作流
- tool_result 压缩: JSON 数组截断到 10 条 + _truncated 标记
- system_prompt: 项目清单增加「目录:」路径信息
This commit is contained in:
2026-06-27 23:59:07 +08:00
parent 6212002270
commit b7b54eb2a6
4 changed files with 38 additions and 2 deletions

View File

@@ -506,11 +506,19 @@ pub(crate) async fn process_tool_calls(
// low(默认):Low→auto, Med/High→审批(等价现状)
// medium:Low/Med→auto, High→审批
// all:全 auto(完全接管,无审批)
let should_auto = match risk_level {
let mut should_auto = match risk_level {
RiskLevel::Low => true,
RiskLevel::Medium => auto_exec_mode == "medium" || auto_exec_mode == "all",
RiskLevel::High => auto_exec_mode == "all",
};
// C-260627: patch_file 小改动(≤5 行)自动放行,不阻塞 AI 工作流
if !should_auto && draft.name == "patch_file" {
if let Some(text) = args.get("new_text").and_then(|v| v.as_str()) {
if text.lines().count() <= 5 {
should_auto = true;
}
}
}
if should_auto {
low_risk.push((draft, args, risk_level));
} else {

View File

@@ -163,6 +163,9 @@ pub(crate) async fn build_system_prompt_with_excluded(
continue;
}
prompt.push_str(&format!("- {} ({}): {}\n", p.name, p.status, p.description));
if let Some(ref dir) = p.path {
prompt.push_str(&format!(" 目录: {}\n", dir));
}
}
// 机制层注明语(中/英):项目已全部列出,降 list_projects 重复调用
prompt.push_str(&projects_listed_note(lang, 20));

View File

@@ -1693,7 +1693,7 @@ fn register_file_tools(
})
};
registry.register(
"patch_file", "局部更新文件内容三模式互斥。模式1 old_text精确匹配原文替换含空格/缩进CAS 语义。模式2 replace_lines按行号区间 {start,end}1-based 含首尾)替换,不需原文,配 expected_hash 防行号漂移。模式3 anchor按首尾子串锚点 {start,end}(大小写敏感,子串匹配)定位行号区间替换,不需完整原文。三模式均需 path+new_textexpected_hash 可选通用。属 Medium 风险操作(修改已有文件),需人工审批。注意:若文件已被外部修改,请先重新 read_file 获取最新内容",
"patch_file", "局部更新文件内容三模式互斥。模式1 old_text精确匹配原文替换含空格/缩进CAS 语义。模式2 replace_lines按行号区间 {start,end}1-based 含首尾)替换,不需原文,配 expected_hash 防行号漂移。模式3 anchor按首尾子串锚点 {start,end}(大小写敏感,子串匹配)定位行号区间替换,不需完整原文。三模式均需 path+new_textexpected_hash 可选通用。小改动(≤5 行)自动放行不阻塞,大改动需人工审批。注意:若文件已被外部修改,请先重新 read_file 获取最新内容",
patch_file_schema,
RiskLevel::Medium,
{ let allowed_dirs = allowed_dirs.clone(); Box::new(move |args: serde_json::Value| {