详解 Claude Code 源码
赛博浮世绘 · 晓风乾 · 24 站拆解
回首页
详解 Claude Code 工具系统 3.3 · FileEditTool 与并发
篇章三 · 3.3

FileEditTool 与并发

精确字符串替换:old_string 换 new_string。听起来简单,但一次编辑要过 12 道验证关,还有一把基于 mtime 的乐观锁。

12 道关卡,一道都不能少

从「团队记忆里的秘密检测」到「智能引号归一化」,每道关都来自真实踩坑。点下面的按钮,看一个编辑请求怎么闯关——有的关会把它当场拦下

选个场景再发起——看请求走到哪关被挡。
12 道关卡清单
#关卡拦什么
1秘密检测团队记忆里标了 secret 的内容,防把密钥写进代码
2old == new替换内容一样 = 无效编辑
3deny 规则权限规则直接禁止此文件
4UNC 路径Windows 网络路径——防 NTLM 凭证泄露
5大小 ≤ 1GiB超大文件不收
6编码检测UTF-8 / UTF-16LE,别的编码先转换
7文件存在 + 相似建议不存在时给你 findSimilarFile() 建议(打错路径神器)
8Jupyter 重定向.ipynb 转交 NotebookEditTool
9必须先读没读过的文件不许编辑——readFileState 里没有它就拦
10mtime 乐观锁读文件之后文件被别人改了(mtime 变了)→ 拒绝,要求重读
11智能引号归一化从网页复制的 " " ' ' 转成 " '——防匹配失败
12多匹配检测replace_all=false 时 old_string 命中多处 → 拒绝(有歧义)
准原子写入 · 临界区不许异步
// 临界区外——可以慢
await fs.mkdir(dirname)
await fileHistoryTrackEdit()

// ⚠️ 临界区——全部同步,一口气完成
const content = readFileForEdit(path)      // 同步读
if (lastWriteTime > lastRead.timestamp)    // mtime 检查
  throw new StaleFileError()               // 有人在编辑期间改了它
const patch = getPatchForEdit(...)         // 计算 diff
writeTextContent(path, updatedFile)        // 同步写

「读 → 查 → 写」之间不允许任何 await——一旦让出事件循环,别的进程就可能插进来改文件。这就是乐观并发:不锁文件,但提交前核对 mtime,冲突就放弃。

本站要点:乐观并发(mtime 比对)比悲观锁(锁文件)适合 AI 场景——冲突极低、代价极小;12 道关卡每道都是一次真实事故的化石。下一站看工具是怎么被「按需组装」出来的。