修复: grep搜索误标Medium致每次审批

This commit is contained in:
2026-06-24 23:04:26 +08:00
parent 93172a6844
commit 7d2998e04e
2 changed files with 11 additions and 2 deletions

View File

@@ -968,6 +968,11 @@
> - **B 前端兜底**(useAiStream onStreamTimeout):stillGenerating 守卫后扫 messages running 工具卡→resetStreamWatchdog 续等不抛错(防心跳丢失/老后端/审批后路径误杀)。审批路径(chat.rs:575/877)非盲区——已包 60s timeout<130s watchdog 互补治理(论证勘误维度3 误判)。
> - 验证:cargo check exit 0(RAII 编译过)+ vue-tsc 0。B 维度因网络错未跑,已自核验 ToolCard approving 计时器仅复位按钮 loading 非 running(running 由后端 AiToolCallCompleted 驱动),真死锁续等优于误报(用户可 stop),A 心跳覆盖正常执行。
>
> **BUG-260624-04 搜索工具误授权根治**(用户 b1f644a7「搜索代码也要授权,检查这样的会话搜索为什么需要授权」):
> - 根因:`grep` 工具被标 `RiskLevel::Medium`(tool_registry.rs:1682),而同类只读 `read_file`/`search_files`/`read_symbol` 均 Low。注释 line 1661 "risk:Med(读文件内容,授权目录内放行/外申请)" 把"读内容需 path_auth 授权"误塞 risk_level —— path_auth 是独立安全层(read_file Low 也走),与 risk_level(只读/写/删)混淆。默认 low 模式下 Medium 需审批 → 每次搜索弹审批。叠加 `tool_display_hint`(tool_registry:2116)无 grep 条目 → reason.rs:158 fallback default `"创建操作,请确认是否执行"` → 只读搜索显示"创建操作"误导。
> - 修复:`grep` Medium→**Low**(对齐只读同类)+ tool_display_hint 加 `"grep" => Some("搜索代码内容")`(文案准确)+ 注释更正。cargo check exit 0。
> - 全量核对:28 工具 risk_level 分级,**除 `restore_project`: High 过保守(恢复非破坏,对齐 create/update 该 Medium;但 High 安全方向不算错,未改)** 外全合理。
>
> **剩余低优 [ ](非阻断)**:
> - [x] ✅(2026-06-24·ebba973) BUG-260624-01 残留:① MessageList:503 scrollToFirstPending return 过早修复(遍历全实例调,各内部 querySelector 无 pending 则 no-op,治 pending 落后续实例滚不到)+ ② ToolCardList listener 加 props.toolCalls.some(pending) 过滤短路(降大列表 N 实例×M emit 的 DOM 查询)。**scrollToFirstPending 时间窗去抖评估后不做**:同 id 连发被上游守卫拦截(AiDirAuthRequired/AiApprovalRequired useAiEvents:359/472 some 去重 + AiToolCallStarted:427 findToolCall 守卫),不同 id 连发是多 pending 合理场景每次滚到首个合理,vue-tsc EXIT 0。
> - [ ] BUG-260624-02 残留:审批超时倒计时 UI(5min 无倒计时,ToolCard pending 态显 mm:ss 到期前 60s 变红)+ 核 detached 窗口 emit 作用域(分离窗口是否独立 startListener,否则 ai-pending-arrived 收不到)

View File

@@ -1658,7 +1658,10 @@ fn register_file_tools(
// 二进制文件(对齐 read_file/list_directory:\0 检测)。
// path_auth:授权目录内放行;未授权走 AiDirAuthRequired 申请(audit/mod.rs check_file_tool_auth
// 经 extract_file_tool_paths 单路径分支触发,非 search_files 盲拒)。
// risk:Med(读文件内容,授权目录内放行/外申请)。
// risk:Low(只读内容搜索,对齐 read_file/search_files;目录授权走 path_auth 独立层,
// 不混入 risk_level——read_file 同样读内容+走 path_auth 但 Low。原 Med 过保守致每次搜索审批)。
// BUG-260624-04:用户报"搜索代码也要授权",根因即此 Med 错标 + tool_display_hint 无 grep 条目
// 致 reason fallback "创建操作"文案误导。降 Low + 补 hint 双修。
// 注册顺序:read_file/list_directory 后,search_files 前(高频检索工具靠前)。
let grep_schema = {
let mut props = serde_json::Map::new();
@@ -1679,7 +1682,7 @@ fn register_file_tools(
registry.register(
"grep", "跨文件内容搜索(grep -rn 模式)。参数:pattern(正则,大小写敏感,无特殊字符时等价字面包含)、path(搜索根,锚 workspace + path_auth 授权)、glob(可选文件名过滤如 *.rs)、output_mode(content/files_with_matches/count)、-n(行号默认 true)、-i(大小写不敏感默认 false)、-C(上下文行数默认 0)、max_results(上限默认 50)。跳过噪音目录/噪音文件/symlink/二进制文件。返回 matches(files_with_matches 模式)或 matches(含 file/line/content/context,content 模式)+ total + truncated。授权目录内放行,未授权触发目录授权申请(AiDirAuthRequired)",
grep_schema,
RiskLevel::Medium,
RiskLevel::Low,
{ let allowed_dirs = allowed_dirs.clone(); Box::new(move |args: serde_json::Value| {
let allowed_dirs = allowed_dirs.clone();
Box::pin(async move {
@@ -2119,6 +2122,7 @@ pub(crate) fn tool_display_hint(name: &str) -> Option<&'static str> {
"read_file" => Some("读取文件"),
"list_directory" => Some("列出目录"),
"search_files" => Some("搜索文件"),
"grep" => Some("搜索代码内容"),
"create_project" => Some("创建项目"),
"update_project" => Some("修改项目"),
"delete_project" => Some("删除项目"),