跳到主要内容

Coding Agents — 「对世界采取动作」分支里最成熟的一支

这条分支在货架里的位置: 总纲把这 189 个库的共性讲成一句话——「把一个只会吐文本的 LLM,包成能在循环里感知-动作、能被放心运营的程序」。围绕这条共性分出 6 条分支,本章是其中**分支 B「对世界采取动作」**里被拆得最透的一支:当那个「动作」是改一个真实代码库时,LLM 文本怎么可靠地变成对磁盘文件的精确编辑。 别的分支只是把「动作」换成查文档 / 控浏览器 / 搭流程——内核同源,但编码 agent 把「意图→精确落盘」这一环逼到了极致,所以最值得先读。

30 秒导读: 这一档库都在干同一件事——让 LLM 可靠地改一个真实的代码库。难点从来不是「调用模型」,而是四个工程问题:① 该改哪(怎么给模型看代码上下文)、② 把模型说的改动精确落到磁盘文件、③ 改错了怎么恢复、④ 一个大任务跑很久怎么管。本章把 19 个库横过来切,告诉你这四个问题各有哪几种流派、各自的代表作、以及整个领域在往哪走。读完你应该能自己画出这张地图。

怎么读本章: 正文是给人读的白话综述,不出现路径行号。每个论断后面挂一个脚注 [^x],精确的 仓库/路径:行 + 符号名都在脚注里;对比矩阵则单开一列「代码锚点」放引用。人读正文,agent 读脚注 / 锚点列。


1. 这条分支要解决什么(第一性原理)

承上:整个货架的共性是「给只会说话的 LLM 装手脚,让它能对世界采取动作」。本分支把「动作」锁死成**「改代码」**——这恰好是最难、也最能看清工程取舍的一种动作,因为「改对一个文件」比「点一个按钮」要求高得多:差一个缩进就落盘失败。

假设你在一个几百个文件的项目里,想让 AI 帮你加个功能。把整个项目贴进聊天窗口不现实(太大),AI 给你的代码你还得手动对齐、复制粘贴到正确位置。一个「编码 agent」就是替你把这两件苦工自动化的程序。

把它拆开,所有编码 agent 都在解四个子问题:

子问题白话难在哪
代码上下文该让模型看哪些代码?仓库装不进上下文窗口
编辑落盘「把这段换成那段」怎么打到文件上?模型给的旧代码几乎从不和文件一字不差
错误恢复对不上 / 跑测试报错怎么办?不能静默吞,也不能死循环
长任务管理改十个文件、跑半小时怎么不跑飞?上下文会爆、会偏题、会忘

一句话直觉: 模型负责「理解需求、想出改动」,确定性代码负责「把改动精确落盘、挑相关上下文、出错重试」。一个编码 agent 的工程价值,几乎全在后半句。本章 §2–§3 主要围绕编辑落盘代码上下文这两条主轴展开,因为它们的流派分化最清楚、最能体现各库的取舍。

形态上,这 19 个库落在三种壳子里:CLI / 终端(aider、codex、crush、gemini-cli、qwen-code、plandex、gptme、pi、oh-my-pi、ra-aid、kilocode、openwork)、IDE 扩展(cline、continue、tabby)、Neovim 插件(avante-nvim、codecompanion-nvim)。还有两个特例:tabby 其实是代码补全服务器(不做 agentic 编辑),auto-code-rover 是面向 SWE-bench 的研究型程序修复 agent。


2. 流派一:编辑怎么落盘(本分支的灵魂)

这是分化最剧烈的一条主轴。「模型描述一处改动,程序把它打到文件上」——光这一步就长出了五个流派。

怎么读这张图: 从左到右是「模型负责精确」的程度递增。最左边模型只管出意图、程序兜底容错;越往右越依赖模型自己给出能精确定位的编辑。最下面单列的⑤换了一套思路——不匹配文本,靠结构 / 锚点定位。

模型只出意图 ────────────────────────────────► 模型自己给精确定位
程序兜底容错 运行时只做执行

┌──────────┐ ┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ ① 整文件 │──►│ ② 文本 │──►│ ③ 结构化工具 │──►│ ④ 第二个模型 │
│ 重写 │ │ diff 块 │ │ 调用 │ │ 来 apply │
│whole file│ │SEARCH/ │ │str_replace / │ │ apply model │
│ │ │REPLACE │ │ apply_patch │ │ fast-apply │
└──────────┘ └──────────┘ └──────────────┘ └──────────────┘

┌────────────────────────────────────────────────────────────────┐
│ ⑤ 结构 / 锚点定位(不匹配文本):tree-sitter 引用 / hash anchor │
└────────────────────────────────────────────────────────────────┘

下面逐个流派接地。关键洞察:无论哪个流派,只要模型给的是「一段要被找到的旧文本」,就绕不开模糊匹配——这是②③⑤共同的暗线(见 §2.6)。

2.1 整文件重写(whole file)

最朴素:让 LLM 把整个文件重写一遍,程序直接覆盖写盘。简单、不会「对不上」,但浪费 token、还容易误删没动的代码。

  • aider 把整文件重写做成一个独立 coder,并且它是模型设置里的默认格式——弱模型用它最稳。1 详见子库 doc aider/04-loop-and-git.md §4.6。
  • plandex 在需要时走「重建整文件」路径,有专门的整文件提示模板。2
  • cline 的整文件写工具(write_to_file)同样直接覆盖,创建新文件或大段重写时用它。3

2.2 文本 diff 块:SEARCH / REPLACE

更省的做法:让模型只说「把这段旧代码换成这段新代码」,用一对围栏标记包起来。这是 aider 的默认,也是被抄得最多的格式。

<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
  • aider:解析靠一个状态机逐行扫围栏(find_original_update_blocks)——这是该流派的教科书实现4 详见子库 doc aider/01-edit-formats.md
  • cline(VS Code 主程序):replace_in_file 工具用同一套 SEARCH … ======= … REPLACE 围栏,失败恢复提示还会教模型「一次只改 50–100 行」。5
  • gptme:patch_many 工具用 ORIGINAL / DIVIDER / UPDATED 标记,且能一次原子改多文件6
  • avante-nvim:非 fast-apply 模式下把 LLM 的 diff 转成 search/replace 再落盘。7

2.3 结构化工具调用:str_replace / apply_patch

新一代趋势:不再让模型在自由文本里写围栏,而是给它一个带 schema 的工具,参数是 old_string / new_string(或一段 patch),由工具运行时保证精确。这把「格式正确性」从「模型自觉」变成了「schema 强约束」。两个子流派:

(a) str_replace 风格(old_string 必须在文件里唯一出现):

  • crush:edit 工具,出现 0 次或多次直接报错,要求模型加上下文或显式 replace_all8
  • pi:edit 工具,要求旧文本「在原文件唯一」,支持一次传一批编辑批量改。9
  • cline(SDK):edit_file 工具,严格要求「恰好命中一次」,0 次或多次都报错。10
  • gemini-cli / qwen-code:都是 replace 工具,默认要求唯一命中、要改多处得显式开门控;但门控参数已分化——gemini-cli 用 allow_multiple,qwen-code 在 fork 后改用布尔 replace_all11

(b) apply_patch 语法(一段带 *** Update File / @@ 上下文的 patch):

  • codex:有专门的 apply-patch crate,工具名 apply_patch,patch 语法用 *** Begin Patch / *** Update File / @@ 上下文行12
  • cline(SDK):除了 edit_file,还提供 apply_patch 工具,直接声明用「canonical apply_patch grammar」——同一个 agent 同时给两种工具,是这一代的典型做法。13

2.4 第二个模型来 apply(apply model / fast-apply)

一个更激进的思路:让「主模型」只输出带省略号的新代码(// ... existing code ...),再交给一个专门的、便宜的 apply 模型把它和原文件合并。主模型不必精确,合并交给专家。

  • continue:先判断能不能「确定性瞬时应用」(用 AST 把省略块直接塞回去,判定函数 isLazyText),不行再调 apply 模型流式合并(streamLazyApply)。14
  • avante-nvim:agentic 模式下若开 fast-apply,edit_file 工具走 morph 这个 fast-apply 提供商做合并,失败再退回 str_replace。15

2.5 结构 / 锚点定位(tree-sitter / hash anchor)

最后一类不靠「匹配文本」,而靠结构或锚点定位要改的位置:

  • plandex:用 tree-sitter 把改动表示成对原文件的引用和删除区间,再按锚点把「提议文件」重建出来,另有独立的「唯一替换」校验。16
  • oh-my-pi:独有 hashline 模式——给每行一个哈希锚点,模型用锚点而非行号定位,patcher 验证锚点再落盘;锚点对不上时会精确提示「re-read the file」而不是让模型瞎猜。17

2.6 暗线:几乎人人都要做「多级降级模糊匹配」

只要模型给的是「一段要在文件里找到的旧文本」(②③⑤都是),它就几乎从不和文件一字不差——缩进会差、会用 ... 省略、空行会多。于是各库不约而同地实现了一套从严到松、命中即停的降级匹配。这是本领域最值得带走的工程智慧:

降级阶梯(从严到松,命中即停)代码锚点
aider精确 → 容忍缩进 → 丢开头空行 → ... 省略18
opencode(kilocode / openwork 行为)九级级联:Simple → LineTrimmed → BlockAnchor → WhitespaceNormalized → IndentationFlexible → EscapeNormalized → TrimmedBoundary → ContextAware → MultiOccurrence19
codex精确 → 忽略行尾空白 → 忽略首尾空白(注释明说 "decreasing strictness")20
gemini-cli精确 → 逐行 trim 的 flexible 匹配并按真实缩进重排 → 再不行调 LLM 去修21
codecompanionexact_match → trimmed_lines …,多个候选相似度差 < 0.15 就换下一策略22

领域智慧: opencode 的九级级联和 aider 的四级,本质是同一个发现——「宁可多写几级确定性的容错,也别让模型去精确数空格」。gemini-cli 更进一步,把 LLM 自己当作最后一级模糊匹配器(对不上就让模型修),这是 §6 趋势的伏笔。


3. 流派二:代码上下文怎么给

第二条主轴:仓库装不进上下文窗口,该让模型看哪些代码?三个流派。

怎么读这张图: 从左到右是「谁来挑上下文」——左边程序预先压缩,右边模型自己边查边读。

程序预先压缩 ──────────────────────────────► 模型自己边查边读

┌──────────────┐ ┌──────────────┐ ┌──────────────────┐
│ ① 静态 │──►│ ② 结构感知 │──►│ ③ agentic 探索 │
│ repo-map │ │ 检索 │ │ 模型自己 │
│ tree-sitter │ │ AST 符号 API │ │ grep / read │
│ + PageRank │ │ │ │ + LSP │
└──────────────┘ └──────────────┘ └──────────────────┘
aider auto-code-rover crush / codex / cline …

3.1 静态 repo-map(程序预先压缩)

把整个仓库压成一张「目录 + 关键符号」的地图,预先塞进提示。代表作只有一个,但极有分量:

  • aider:用 tree-sitter 抽符号,把「谁引用谁」建成图跑 PageRank 排重要性,再二分搜索贴近 token 预算挑选。23 这是该流派的标志性实现,详见子库 doc aider/03-repo-map.md

3.2 结构感知检索(AST 符号 API)

不给全图,而给模型一组按结构查代码的工具——「查这个类/方法/代码片段定义在哪」。

  • auto-code-rover:核心就是一组 AST 检索 API(search_class / search_method / search_method_in_class / search_code),模型迭代调用它们「按符号定位」上下文。24 这是它在 SWE-bench 上的方法论核心。

3.3 agentic 探索(模型自己 grep / read)

最主流的当代做法:不预先压缩,给模型 grep / glob / read / ls 等工具,让它自己边查边读,按需检索。

  • crush:完整的探索工具集 glob / grep / rg / ls / view / sourcegraph,外加 LSP 取诊断与符号。25
  • codex:没有 repo-map,靠 shell 里的 grep/glob + 环境上下文做 agentic 探索。26
  • cline / gemini-cli / qwen-code / pi / oh-my-pi / gptme / kilocode / openwork:都属此类——给模型搜索与读文件工具,让它自主探索。

对照: aider 偏预先压缩(一张静态地图,便宜但有损),agentic 流派偏按需检索(更准但更费 token、更慢)。auto-code-rover 介于两者之间——结构化但仍由模型驱动检索。


4. 对比矩阵(逐格接地)

维度:编辑落盘方式(§2)、上下文策略(§3)、错误恢复模型绑定形态。描述列写白话,精确 path:line+符号 全在最右「代码锚点」列。 表示该维度对此库不适用。

库 (id)编辑落盘上下文策略错误恢复形态代码锚点
aider② SEARCH/REPLACE(默认),含 whole/udiff 变体① 静态 repo-map + PageRank多级模糊匹配 → 对不上报错反喂CLI01-edit-formats;03-repo-map;editblock_coder.py:439/:157,repomap.py:365
clineedit_file(唯一)+ apply_patch;VS Code 程序另有 SEARCH/REPLACE③ agentic严格唯一匹配,失败即报错引导IDE 扩展 + CLI + SDKsdk/.../executors/editor.ts:133,schemas.ts:204;apps/vscode/.../shared/tools.ts:12
continue④ apply model:lazy 块 → 确定性 AST 或 apply 模型合并③ agentic + 自家检索apply 不支持模型则报错IDE 扩展(VS Code/JetBrains)core/edit/lazy/streamLazyApply.ts:14,deterministic.ts:19
codexapply_patch 语法,专属 crate③ agentic(shell grep/glob,无 repo-map)seek_sequence 三级降级匹配CLI(Rust)codex-rs/core/src/tools/handlers/apply_patch.rs;apply-patch/src/seek_sequence.rs:1
crushedit(old/new + replace_all)+ multiedit③ agentic:glob/grep/rg/view + LSP0/多次匹配报错要求加上下文CLI(Go)internal/agent/tools/edit.go:26/:47;internal/lsp/manager.go
qwen-codereplace(默认唯一,replace_all 多匹配);fork 自 gemini-cli 后已分化③ agentic(承袭 gemini-cli 工具)同 gemini-cli flexible 匹配CLI(TS)packages/core/src/tools/edit.ts:104/:148/:305(replace_all);README.md:157(fork 自述)
gemini-clireplace(默认唯一,allow_multiple 多匹配)③ agentic精确 → flexible(trim+重排)→ LLM 修CLI(TS)packages/core/src/tools/edit.ts:368(allow_multiple)/:299/:547;utils/llm-edit-fixer.ts:142
kilocode②/③ 打包 opencode 的九级替换器 edit 工具③ agentic(opencode 工具集)九级替换器级联CLI(OpenCode fork)+ VS Code 扩展packages/opencode/src/tool/edit.ts:241/:710
plandex⑤ tree-sitter 结构/引用定位 + ① whole-file 回退③ agentic(面向大项目/长任务)唯一替换校验CLI(Go)app/server/syntax/structured_edits_apply.go:91;unique_replacement.go;prompts/build_whole_file.go
gpt-pilot② diff 块(unified hunk)文件描述 + relevant_files 过滤逐 hunk review:apply/rework/ignore + 人在环上CLI(自治开发者,step-by-step)core/agents/code_monkey.py:26/:37-49/:68
tabby— (代码补全,不做 agentic 编辑)FIM:prefix/suffix segments补全服务器 + IDE 客户端crates/tabby/src/services/completion.rs:135 Segments
piedit(唯一 + edits[] 批量)③ agentic(Read/Write/Edit/Bash 极简集)唯一匹配要求CLI(TS,极简自扩展)packages/coding-agent/src/core/tools/edit.ts:35
oh-my-pihashline 哈希锚点 + 兼容 pi 的 str_replace③ agentic + LSP + subagents锚点不符精确提示 re-read + noop 循环守卫CLI(Pi 衍生)packages/coding-agent/src/edit/hashline/execute.ts:21/:73;noop-loop-guard.ts
avante-nvim④ fast-apply(morph)→ ② diff2search_replace 回退③ agentic(llm_tools/)fast-apply 失败退 str_replaceNeovim 插件lua/avante/llm_tools/edit_file.lua:62/:218;utils/diff2search_replace.lua
codecompanion-nviminsert_edit_into_file 多策略匹配③ agentic + 编辑器上下文多策略 + 相似度阈值 0.15 换策略Neovim 插件.../insert_edit_into_file/strategies.lua:8/:122/:177
gptmepatch_many,ORIGINAL/UPDATED 标记,多文件原子③ agentic(read/shell/python/browser 工具)patch 对不上报错重试CLIgptme/tools/patch_many.py:18/:30
ra-aid委派给 aider 落盘③ agentic(ripgrep + emit_related_files)由 aider 兜底CLI(研究→规划→实现三阶段)ra_aid/tools/programmer.py:31/:58
auto-code-rover② SEARCH/REPLACE 风格补丁(SWE-bench 程序修复)结构感知:search_class/method/code检索→定位→打补丁迭代,失败回检索研究型 agent(SWE-bench)app/search/search_backend.py:276/:451/:481
openwork行为继承自 opencodeedit(同 kilocode 九级替换器);本仓不 vendor opencode 源码,在 PATH 上跑外部 opencode③ agentic(opencode 工具集)同 opencode 九级级联(由外部 opencode 提供)桌面 app(OpenCode 驱动)openwork README.md:10「powered by OpenCode」;九级实现见 kilocode/packages/opencode/src/tool/edit.ts:710
kunedit(exact str_replace:oldText/newText,支持 edits[] 批量 disjoint,要求唯一命中)③ agentic:ripgrep/fd backed ls/grep/read + lsp 工具(无 repo-map)无模糊匹配:0 次/多次命中即报错要求加上下文或拆分;ToolStormBreaker 拦重复调用 + 截断参数提示重试桌面 app(Electron GUI + 本地 kun serve 运行时,PolyForm 非商业许可)kun/src/adapters/tool/builtin-file-tools.ts:87(edit);builtin-tool-utils.ts:718 findOccurrences/:735-740 唯一命中报错;builtin-search-tools.ts:31/:183(ls/grep)、builtin-lsp-tool.ts:66(lsp);loop/tool-storm-breaker.ts;loop/agent-loop.ts:762 AgentLoop
whaleedit(search/replace/all,str_replace 风格)+ multi_edit;提交前用字节快照校验文件未变,否则回 write_conflict③ agentic(grep/view/ls/search_files;无 repo-map、无 LSP)多级模糊匹配(exact → whitespace-relaxed → JSON-escape unwrap)+ 行级 divergence 诊断;搜不到报 search_not_found 引导 re-readCLI/TUI(Go,仅 DeepSeek)internal/tools/edit.go:45/:147(resolveEditSearch)/:271(editSearchDivergence);file_mutation.go:111(verifyFilePlanCurrent, bytes.Equal);catalog_files.go:74(edit)/:108(multi_edit)

矩阵里反复出现的两个「家族」:opencode 家族(kilocode 直接 vendor 了 opencode 的 edit 工具源码,openwork 则在 PATH 上跑外部 opencode、行为同源)和 pi 家族(pi → oh-my-pi)。长尾库不必逐一拆解——它们在编辑/上下文上往往落进上面某个已接地的格子。


5. 模式与权衡(可带走的领域智慧)

读完矩阵,几条横跨全分支的规律浮出来:

  • 「格式正确」的责任在往运行时迁移。 从「模型在自由文本里写围栏」(②,模型自觉)→「模型调带 schema 的工具」(③,运行时强约束)。后者让畸形输出更难发生,也更好做权限/审批门控(如 codex 的 apply_patch 审批、cline 的 tool policies)。

  • 「精确」和「省事」的取舍贯穿始终。 whole(①)最不会对不上但最费;str_replace(③)省但要求唯一匹配;apply model(④)让主模型彻底不管精确、把脏活外包给 apply 专家。没有免费的午餐——容错放哪儿,就是这个领域的核心设计决策

  • 模糊匹配是隐形的护城河。 aider 四级、opencode 九级、codex 三级——谁的降级阶梯更稳,谁的「编辑成功率」就更高。这是用户感知不到、但决定体验的地方。

  • 错误恢复 = 「报错 + 反喂」闭环,而非静默猜。 aider 明确禁用了纯编辑距离模糊匹配(宁可报错重试也不赌一个改错位置的猜测,见 aider/02-apply-and-match.md §2.4);crush/pi/cline 在多次匹配时拒绝并要求模型加上下文。共识是:改错比改不上更糟

  • 上下文:预压缩 vs 按需检索的钟摆。 静态 repo-map(aider)便宜但有损;agentic grep(crush/codex/…)准但费 token。当代主流明显倒向后者——但代价是更长的探索回合。

  • 形态决定边界,不决定内核。 CLI、IDE 扩展、nvim 插件壳子不同,但内核都是「上下文 + 编辑落盘 + 恢复」这三件套。avante-nvim 用 morph fast-apply、cline 用 SDK 抽象,都是把同一内核塞进不同宿主。


6. 演化趋势(这条分支往哪走)

把时间轴拉出来,三条趋势很清楚:

  1. 文本 diff → 结构化工具调用。 早期(aider、cline VS Code 程序)靠自由文本里的 SEARCH/REPLACE 围栏;新一代(codex 的 apply_patch、cline SDK 的 edit_file+apply_patch、crush/pi/gemini-cli 的 str_replace 工具)改用带 schema 的工具。同一个 cline 仓库里两代并存(VS Code 程序的 SEARCH/REPLACE vs SDK 的工具),正是这次迁移的活化石。

  2. 静态 repo-map → agentic 探索。 aider 的 PageRank 地图是「预先压缩」的巅峰;但越来越多的库(codex 干脆没有 repo-map)倒向「给模型 grep/read/LSP,让它自己边查边读」。模型能力变强后,按需检索比「猜测式预压缩」更准。

  3. 确定性容错 → 把 LLM 当容错器。 模糊匹配从纯算法(aider/opencode 的多级字符串匹配)开始,gemini-cli 已经走到「对不上就调一个 LLM 去修编辑」,avante/continue 则把整个 apply 步骤交给专门的 apply 模型。容错正从「确定性代码」长出「模型」的环节。

三条趋势其实同源:模型越可靠,系统就越敢把「精确」的责任还给模型——但好的工程仍坚持「报错而非静默猜」,这条底线没变。这也呼应总纲的共性:把 LLM 包成可信程序,关键不在模型多聪明,而在出错时脚手架兜不兜得住。


7. 代表作 + 深入读哪些

按流派点名代表作,想深入就从这里下钻:

想学的东西代表作入口
SEARCH/REPLACE + 多级模糊匹配(必修)aider子库 doc 02-edit-formats.md
静态 repo-map + PageRankaider子库 doc 03-repo-map.md
中央循环 / 反思恢复闭环aider子库 doc 01-main-loop.md
整文件 vs 变体调度 / architect 两段式aider子库 doc 04-git-and-variants.md
结构化 apply_patch 语法 + 容错codex克隆 codex-rs/apply-patch/
str_replace 工具 + agentic grep + LSPcrush克隆 internal/agent/tools/、lsp/
九级替换器级联(diff 容错天花板)opencode(经 kilocode / openwork)克隆 packages/opencode/src/tool/edit.ts
apply model / fast-applycontinue · avante-nvimcontinue core/edit/lazy/;avante edit_file.lua
结构 / 锚点定位编辑plandex · oh-my-piplandex syntax/;oh-my-pi hashline/
结构感知检索(AST 符号 API)auto-code-rover克隆 app/search/search_backend.py
LLM 修编辑(把模型当容错器)gemini-cli克隆 utils/llm-edit-fixer.ts
人在环上 / 逐 hunk reviewgpt-pilot克隆 core/agents/code_monkey.py
委派落盘(自己规划,交 aider 改)ra-aid克隆 ra_aid/tools/programmer.py
代码补全(FIM,非 agentic)tabby克隆 crates/tabby/src/services/completion.rs

给入门者的学习路径: 先把 aider 四章读完(它把上下文、编辑落盘、恢复三件套讲得最完整)→ 再对照 codex / crush 看「结构化工具调用 + agentic 探索」这代怎么做 → 想看容错天花板就读 opencode 的九级替换器 → 最后用 continue / avante 理解「apply model」这条新路线。读完回总纲 index.md,你会发现别的 5 条分支只是把这套「上下文+动作落盘+恢复」直觉换了个动作对象。


8. 代码地图(导航索引)

给 agent 的精确入口表(库 / 路径 / 符号),按主题排:

主题路径符号
SEARCH/REPLACE 解析aider/aider/coders/editblock_coder.pyfind_original_update_blocks
多级降级匹配(aider)aider/aider/coders/editblock_coder.py:157replace_most_similar_chunk
repo-map + PageRankaider/aider/repomap.py:365RepoMap.get_ranked_tags
str_replace 工具(cline SDK)cline/sdk/packages/core/src/extensions/tools/executors/editor.ts:133countOccurrences
apply_patch 工具(cline SDK)cline/sdk/packages/core/src/extensions/tools/executors/apply-patch.tsApplyPatchExecutor
apply_patch crate(codex)codex/codex-rs/apply-patch/src/lib.rsapply_patch grammar
降级序列匹配(codex)codex/codex-rs/apply-patch/src/seek_sequence.rs:12seek_sequence
str_replace 工具(crush)crush/internal/agent/tools/edit.go:26old_string/new_string/replace_all
九级替换器级联(opencode)kilocode/packages/opencode/src/tool/edit.ts:710Replacer 数组
flexible 匹配 + LLM 修(gemini)gemini-cli/packages/core/src/tools/edit.ts:299 · utils/llm-edit-fixer.ts:142calculateReplacement / FixLLMEditWithInstruction
replace_all 多匹配门控(qwen)qwen-code/packages/core/src/tools/edit.ts:148,:305replaceAll = params.replace_all
lazy apply(continue)continue/core/edit/lazy/streamLazyApply.ts:14 · deterministic.ts:19streamLazyApply / isLazyText
fast-apply(avante)avante-nvim/lua/avante/llm_tools/edit_file.lua:62morph provider
多策略匹配(codecompanion)codecompanion-nvim/lua/codecompanion/interactions/chat/tools/builtin/insert_edit_into_file/strategies.lua:122exact_match / trimmed_lines
tree-sitter 结构编辑(plandex)plandex/app/server/syntax/structured_edits_apply.go:91ApplyChanges / isRef
hashline 锚点(oh-my-pi)oh-my-pi/packages/coding-agent/src/edit/hashline/execute.ts:21hashline runner / Patcher
AST 检索 API(auto-code-rover)auto-code-rover/app/search/search_backend.py:276search_class / search_method / search_code
逐 hunk review(gpt-pilot)gpt-pilot/core/agents/code_monkey.py:68CodeMonkey / PATCH_HEADER_PATTERN
委派 aider 落盘(ra-aid)ra-aid/ra_aid/tools/programmer.py:31run_programming_task
patch_many 多文件(gptme)gptme/gptme/tools/patch_many.py:30patch_many(ORIGINAL/UPDATED)
FIM 补全(tabby)tabby/crates/tabby/src/services/completion.rs:135Segments(prefix/suffix)

Footnotes

  1. aider/aider/models.py:131 ModelSettings.edit_format 默认 "whole";整文件 coder 见 aider/aider/coders/wholefile_coder.py WholeFileCoder

  2. plandex/app/server/model/prompts/build_whole_file.go 整文件重建提示。

  3. cline 整文件写工具 write_to_file(枚举 ClineDefaultTool.FILE_NEW)定义在 VS Code 一侧:cline/apps/vscode/src/shared/tools.ts:14;失败恢复提示见 apps/vscode/src/core/prompts/responses.ts:68(「don't retry write_to_file」)。SDK 侧 schemas.ts:172-200 的 EditFileInputSchemaedit_file(old_text 为空时创建/整写),不是 write_to_file

  4. cline/apps/vscode/src/core/prompts/responses.ts:70 是 replace_in_file 连续失败时的 error-recovery 提示串(consecutiveFailures 警告),里面顺带提到 write_to_file/replace_in_file 与「每次 ≤50–100 行」分段建议;replace_in_file 工具名定义在 apps/vscode/src/shared/tools.ts:12 ClineDefaultTool.FILE_EDIT

  5. gptme/gptme/tools/patch_many.py:18,:30 patch_many,复用 patch.py 的 ORIGINAL/DIVIDER/UPDATED,多文件原子应用。

  6. avante-nvim/lua/avante/utils/diff2search_replace.lua 把 LLM diff 转 search/replace。

  7. crush/internal/agent/tools/edit.go:26-28 参数 old_string/new_string/replace_all;:47-48 / :254 0 次或多次报错。

  8. pi/packages/coding-agent/src/core/tools/edit.ts:35-39 edit(oldText/newText 唯一 + edits[] 批量)。

  9. cline/sdk/packages/core/src/extensions/tools/executors/editor.ts:62 countOccurrences;:133-141 非「恰好一次」即报错。

  10. gemini-cli 一侧:packages/core/src/tools/edit.ts replace(old_string/new_string),工具名见 packages/core/src/tools/definitions/base-declarations.ts:65 EDIT_TOOL_NAME = 'replace';多匹配门控用布尔 allow_multiple(edit.ts:147 / :368 !params.allow_multiple && occurrences !== 1)。qwen-code 一侧:README.md:157 自述基于 gemini-cli v0.8.2 fork,但 edit.ts 在 fork 后已分化——它改用布尔 replace_all(qwen-code/packages/core/src/tools/edit.ts:104 字段定义、:148 replaceAll = params.replace_all ?? false、:305 !replaceAll && occurrences > 1 报错门控),而非 gemini-cli 的 allow_multiple

  11. codex/codex-rs/core/src/tools/handlers/apply_patch.rs 工具 apply_patch;语法定义 codex/codex-rs/apply-patch/src/lib.rs *** Begin Patch/*** Update File/@@

  12. cline/sdk/packages/core/src/extensions/tools/schemas.ts:204-216 apply_patch「canonical patch grammar」,实现 executors/apply-patch.ts。

  13. continue/core/edit/lazy/deterministic.ts:19 isLazyText;continue/core/edit/lazy/streamLazyApply.ts:14,:21 streamLazyApply + lazyApplyPromptForModel

  14. avante-nvim/lua/avante/llm_tools/edit_file.lua:11 enable_fastapply;:62 morph provider;:218-224 失败退回 str_replace。

  15. plandex/app/server/syntax/structured_edits_apply.go:91 ApplyChanges、:69 isRef、:44 AnchorMap;syntax/unique_replacement.go 唯一替换校验。

  16. oh-my-pi/packages/coding-agent/src/edit/hashline/execute.ts:21(@oh-my-pi/hashline)、:55/:73 锚点不符精确提示 re-read;edit/hashline/block-resolver.ts 锚点解析、noop-loop-guard.ts 循环守卫。

  17. aider/aider/coders/editblock_coder.py:157 replace_most_similar_chunk(精确 → 容忍缩进 → 丢首部空行 → ... 省略)。

  18. kilocode/packages/opencode/src/tool/edit.ts:241 type Replacer;:710-718 九级级联数组 SimpleReplacer … MultiOccurrenceReplacer(各 Replacer 定义,按级联顺序::268/:272/:312/:447/:491/:519/:582/:608/:568)。

  19. codex/codex-rs/apply-patch/src/seek_sequence.rs:1-12 doc 注释明说 "decreasing strictness";seek_sequence

  20. gemini-cli/packages/core/src/tools/edit.ts:299 calculateReplacement(flexible 段);:547 调 FixLLMEditWithInstruction(定义 packages/core/src/utils/llm-edit-fixer.ts:142)。

  21. codecompanion-nvim/lua/codecompanion/interactions/chat/tools/builtin/insert_edit_into_file/strategies.lua:8 相似度差 <0.15 换策略;:122 exact_match、:177 trimmed_lines

  22. aider/aider/repomap.py:365 RepoMap.get_ranked_tags;:525 nx.pagerank;get_ranked_tags_map 二分逼近 token 预算。

  23. crush/internal/agent/tools/(glob/grep/rg/ls/view/sourcegraph);crush/internal/lsp/manager.go LSP 诊断与符号。

  24. codex/codex-rs 全树无 pagerank/repomap;环境上下文 codex/codex-rs/core/src/context/environment_context.rs。