• thzxx released this 2026-07-21 16:09:15 +08:00 | 3 commits to master since this release

    概述

    本次版本聚焦 AI 文件与代码工程操作 的精细性和稳定性,对 13 个既有工具完成 14 项优化,并新增 2 个工具(file_move / file_info),工具总数从 13 提升至 15。所有修改均通过 tsc --noEmit 类型检查和人工审查,无破坏性变更。


    一、阶段一 · 紧急修复(F1-1 ~ F1-4)

    针对既有 bug 和潜在数据安全问题进行紧急修复。

    F1-1 · file_editor regex 计数 bug 修复

    问题regex 操作使用两次独立的 RegExp 实例(一次 match 计数、一次 replace 替换),由于 g 标志的 lastIndex 状态不同步,导致计数与实际替换次数不一致。

    修复

    • 强制 regex 含 g 标志(若用户未传则自动追加)
    • 使用同一个 RegExp 实例完成 match 计数 + replace 替换
    • 逐行处理时每行匹配前重置 lastIndex = 0,避免 g 标志导致漏匹配

    F1-2 · code_search 统一路径校验

    问题code_search 原先使用裸 resolve() 拼接路径,未经过 isPathWithinWorkspace 路径遍历防护和 MEMORY.md 受保护文件拦截。

    修复:统一改用 safeResolvePath,复用 isPathWithinWorkspace(含 realpathSync 符号链接逃逸二次校验)+ isProtectedWorkspaceFile 两层安全检查。

    F1-3 · git_commit amend 模式增强

    问题:amend 模式下 message 字段为 required,但 git amend 原生语义允许保留原 message — 这导致用户想修改提交内容但保留原 message 时必须重新输入。

    修复

    • message 字段改为非 required
    • 非 amend 模式仍强制要求 message(动态校验)
    • amend 模式下:
      • 提供 message → 用新 message 覆盖
      • 未提供 message → 自动追加 --no-edit 明确保留原 message(避免 git 打开编辑器 hang 等待输入)
    • 返回值新增 amended: boolean 字段

    F1-4 · write_file append 模式原子化

    问题:原 fs.appendFile 内部为 open(O_APPEND) + write + close,存在两个隐患:

    1. fsync:write 后数据仅停留在 page cache,系统崩溃可能丢失
    2. 大内容(> 4KB)非完全原子:可能被分成多个 write 调用

    修复:改用显式 open('a') + 循环 write(直到 buffer 完整写入)+ fsync + close,在 保持 append 语义(O_APPEND 内核级追加) 的前提下保证数据持久化到磁盘,不改变并发行为。


    二、阶段二 · 增强现有工具(F2-1 ~ F2-7)

    提升文件读写和编辑工具的健壮性与适用性。

    F2-1 · read_file 智能编码检测

    问题:Windows 中文环境下大量历史文件为 GBK 编码,原 readFile(path, 'utf-8') 会产生乱码;UTF-16 文件(带 BOM)也无法正确读取。

    方案:新增共享函数 decodeBufferWithDetection,采用 BOM 检测 + 三级降级策略:

    1. BOM 检测(优先):
      • EF BB BF → UTF-8 BOM,剥离 BOM 后解码
      • FF FE → UTF-16 LE,用 utf16le 解码
      • FE FF → UTF-16 BE,字节交换后用 utf16le 解码(含奇偶长度保护)
    2. 无 BOM 三级降级
      • UTF-8 strict(fatal: true,失败则降级)
      • GBK(Windows 中文环境常见)
      • UTF-8 loose(兜底,用替换字符代替非法字节)

    返回值新增 encoding 字段,标识实际检测到的编码(utf-8 / utf-8-bom / utf-16le / utf-16be / gbk / utf-8-loose)。

    F2-2 · read_file 支持 tail 模式

    场景:读取大日志文件的末尾 N 行(类似 tail -n)。

    方案:新增 tail 参数(1~2000),优先级高于 offset/limit。返回值新增:

    • start_line:实际起始行号(tail 模式下为 max(1, total - tail + 1)
    • mode'tail''offset'

    F2-3 · search_files 二进制过滤 + 智能编码检测

    问题:搜索文件内容时会误读二进制文件(图片/可执行文件)产生乱码匹配,且非 UTF-8 文件无法被搜索到。

    修复

    • 复用 isBinaryFile(NULL 字节检查,只读前 8KB)过滤二进制文件
    • 改用 decodeBufferWithDetection 读取文件内容,支持 GBK 等编码

    F2-4 · search_files 多 glob 匹配

    场景:一次搜索多种文件类型(如 *.ts,*.js,*.tsx)。

    方案:新增共享函数 matchAnyGlob(逗号分隔,任一匹配即通过)。list_directorysearch_fileswalkDir 均改用此函数。空字符串视为匹配所有。

    F2-5 · file_editor 新增 find_replace 操作

    场景:精准替换代码片段,但片段中含正则元字符(如 .*+?^$()[])会被误解析为正则。

    方案:新增 find_replace 操作,采用字面量字符串替换(split + join 统计匹配次数并替换),不解析任何正则元字符。

    参数

    • find:要查找的字面量字符串(必填,非空)
    • replace:替换字符串(默认空串)
    • replace_alltrue(默认)替换全部,false 只替换第一个

    F2-6 · file_editor regex 支持跨行匹配

    场景:替换多行代码块(如函数定义、多行注释),原逐行匹配无法处理跨行模式。

    方案:新增 multiline 参数。为 true 时对整个目标内容块(start_lineend_line 的 join)做正则替换,支持 ^/$ 匹配行首行尾、\s 跨行空白等模式。

    F2-7 · file_editor 新增 backup 参数

    场景:编辑重要文件前希望自动备份原始内容。

    方案:新增 backup 参数(默认 false)。为 true 时在写入前将原始内容保存为 ${file_path}.bak。备份在写入前进行,确保即使写入失败也有原始备份。返回值新增 backup_path 字段(未备份时为 null)。


    三、阶段三 · 新增工具(F3-1 ~ F3-2)

    补齐文件工程操作的关键能力缺口。

    F3-1 · 新增 file_move 工具

    场景:AI 需要移动或重命名文件/目录,原先只能通过 delete_file + write_file 组合实现,数据安全性差。

    实现

    • 双路径 safeResolvePath 校验(源和目标都必须在工作空间内 + 非 MEMORY.md
    • 禁止移动工作空间根目录
    • overwrite 参数(默认 false):为 true 时先删除已存在的目标再 rename
    • 自动创建目标父目录(递归 mkdir
    • 使用 rename(同文件系统上为原子操作)
    • 权限策略:WRITE + requireConfirmation: true + 频率限制 30/min

    F3-2 · 新增 file_info 工具

    场景:AI 需要查询文件元信息(大小、时间、类型、编码、权限等),原先只能通过 run_command 调用 stat 命令,效率低且需确认。

    实现

    • 路径 safeResolvePath 校验
    • 返回字段:path / absolute_path / type(file/directory/symlink)/ size / created / modified / accessed / mode(八进制权限位)
    • 文件类型额外信息(仅对普通文件):
      • is_binary:NULL 字节检查(读前 8KB)
      • encoding:智能编码检测(仅非二进制文件,复用 decodeBufferWithDetection
    • 只读前 8KB,避免大文件 OOM
    • 权限策略:READ,无需确认

    四、阶段四 · 优化(F4-1 ~ F4-2)

    F4-1 · diff_viewer 内存优化 + 统一路径与编码

    优化 1 · Uint32Array → Uint16Array

    LCS 算法的 lcs 表从 new Uint32Array((sm+1) * (sn+1)) 改为 new Uint16Array(...)。LCS 长度最大值为 min(sm, sn) ≤ 5000,远小于 Uint16Array 上限 65535,安全。内存占用减半。

    优化 2 · 统一路径校验 + 智能编码检测

    原先 diff_viewer 手动调用 resolve + isPathWithinWorkspace + isProtectedWorkspaceFile 三步,且文件读取用 readFile(path, 'utf-8')。改为:

    • safeResolvePath 统一路径校验
    • decodeBufferWithDetection 智能解码(支持 GBK/UTF-16 文件对比)

    F4-2 · 错误处理统一

    问题:各工具 catch 块中错误提取方式不统一( (err as Error).message / String(err) / extractErrorMessage(err)),非 Error 抛出值(如字符串、对象)可能丢失信息。

    修复:扩展共享 extractErrorMessage(error, includeStderr?) 支持 stderr 附加,并统一以下位置:

    • diff-viewer.ts 末尾 catch 块:(err as Error).messageextractErrorMessage(err)
    • file-editor.ts regex 构造 catch 块:(err as Error).messageextractErrorMessage(err)
    • code-search.ts execute() 新增外层 try-catch(原先缺失,safeResolvePath 异常会向上传播)

    保留 searchWithRipgrep 内部的 err.stderr || err.message(stderr 优先语义,子进程错误信息在 stderr)。


    五、阶段五 · 验证(F5)

    F5-1 · TypeScript 类型检查

    npx tsc --noEmit 退出码 0,无类型错误。

    F5-2 · 人工审查

    逐文件审查通过,覆盖维度:

    • 路径校验:所有工具均使用 safeResolvePath,无裸 resolve()
    • 错误处理:catch 块统一 extractErrorMessage,无非 Error 抛出值丢失
    • 原子性:write_file / file_editor 用临时文件 + rename;file_move 用 rename
    • 资源释放:所有 FileHandle 在 finally 块中 close;临时文件在失败时清理
    • 权限策略:file_move(WRITE+确认+30/min)、file_info(READ)配置合理
    • 导出注册index.ts 导出 + main.ts 注册齐全(29 个工具)
    • 跨工具一致性:grep (err as Error).message 无匹配,错误处理统一无遗漏

    六、修改文件清单(12 个)

    文件 修改内容
    package.json 版本号 0.3.11 → 0.3.12
    package-lock.json 版本号 0.3.11 → 0.3.12(根 + packages[''])
    README.md 版本徽章 0.3.11 → 0.3.12
    electron/main.ts 注册 FileMoveTool + FileInfoTool
    electron/harness/sandbox/permissions.ts 新增 file_move / file_info 权限策略
    electron/harness/tools/built-in/index.ts 导出 FileMoveTool / FileInfoTool,注释更新至 29 个工具
    electron/harness/tools/built-in/file-guard.ts 新增 decodeBufferWithDetection / matchAnyGlob / 扩展 extractErrorMessage
    electron/harness/tools/built-in/filesystem.ts 7 个工具全面优化(read/write/list/search/delete/move/info)
    electron/harness/tools/built-in/file-editor.ts 新增 find_replace / multiline regex / backup,regex bug 修复
    electron/harness/tools/built-in/code-search.ts 统一 safeResolvePath + 外层 try-catch + extractErrorMessage
    electron/harness/tools/built-in/diff-viewer.ts Uint16Array 内存优化 + safeResolvePath + 智能编码 + 错误处理统一
    electron/harness/tools/built-in/git.ts git_commit amend 模式 message 可选 + --no-edit

    变更统计:588 insertions(+), 102 deletions(-)


    七、工具数量变化

    类别 v0.3.11 v0.3.12 变化
    文件系统工具 5(read/write/list/search/delete) 7(+file_move/file_info) +2
    文件编辑工具 1(file_editor) 1 -
    代码搜索工具 1(code_search) 1 -
    差异对比工具 1(diff_viewer) 1 -
    Git 工具 4(status/diff/log/commit) 4 -
    文件/代码类小计 13 15 +2
    工具总数 29 31 +2

    八、设计权衡说明

    本次实施中有以下设计权衡(非 bug,符合规范):

    1. file_editor 仍用 readFile('utf-8') 而非 decodeBufferWithDetection

    原因:这是正确的设计选择。

    • readFile('utf-8') 会保留 UTF-8 BOM 字符,编辑后写回时 BOM 自动保留
    • 若改用 decodeBufferWithDetection,BOM 会被剥离,写回时 BOM 丢失 — 反而破坏文件
    • 对 GBK/UTF-16 文件,建议用户先用 write_file 转码再编辑

    2. file_move overwrite 模式边缘风险

    说明overwrite=true 且目标已存在时,先删除目标再 rename。若 rename 失败(如跨文件系统 EXDEV、源文件被锁定),目标已被删除。

    实际影响:低。工作空间内文件通常在同一文件系统,rename 失败概率极低。源文件仍在原位置(只有目标丢失)。修复会增加复杂度(rename-to-tmp + rename + cleanup 三步序列),暂保持现状。

    3. code-search searchWithRipgrep 保留 err.stderr || err.message

    原因:子进程错误的关键信息在 stderr,err.stderr || err.message 是 stderr 优先语义,符合子进程错误处理惯例。未统一为 extractErrorMessage(err, true) 避免冗长。


    九、升级须知

    升级步骤

    1. 拉取最新代码:git pull origin master
    2. 安装依赖(无新增依赖,可跳过):npm install
    3. 重启应用(使新工具注册生效)

    兼容性

    • 完全向后兼容:所有既有工具的 API 参数均向后兼容(新增参数均为可选)
    • 新增工具自动可用file_move / file_info 已在 main.ts 中注册,无需额外配置
    • 权限策略自动生效permissions.ts 已配置默认策略,无需手动修改

    建议测试场景

    1. 大日志文件 tail 读取
    2. GBK / UTF-16 旧文件 read_file 解码
    3. file_move 跨目录移动 + overwrite 覆盖
    4. find_replace 替换含正则元字符的代码片段
    5. file_editor multiline regex 替换多行代码块
    6. backup: true 编辑后检查 .bak 文件
    7. file_info 查询文件元信息

    十、提交信息

    commit 058ee2d
    feat: 升级至 v0.3.12 — 文件与代码类工具全面优化(16 项)
    
    12 files changed, 588 insertions(+), 102 deletions(-)
    

    玥玥 · 2026-07-21

    Downloads