跳到主要内容

工具集:Cline 的「手」

本章讲什么: 模型缺的第二样东西是手 —— 把它说的「改这个文件」精确落到真实磁盘上。这章讲 Cline 内置哪些工具、文件编辑为什么用「唯一匹配才替换」、以及 Plan 模式和 Act 模式怎么用一组开关切换工具集。

1. 工具是什么(在 Cline 里)

一个工具就是 { name, description, inputSchema, execute } 四件套,用 createTool(sdk/packages/shared/src/tools/create.ts)造出来。模型看到 descriptioninputSchema 决定调不调、传什么参数;execute 是真正干活的函数。

Cline 的默认工具由一组工厂函数生产,集中在 definitions.ts,由 createDefaultTools(definitions.ts:806)按配置组装。

2. 默认工具清单

工具干什么工厂函数
read_files读一个或多个文件(支持行范围分页)createReadFilesTool
search_codebase正则搜代码库createSearchTool
run_commands跑 shell 命令(支持 heredoc 合并)(definitions.ts 内)
editor改文件:str_replace / 插入行 / 新建createEditorTool(executor: createEditorExecutor)
apply_patch用 GPT-5 补丁语法批量改(executor: apply-patch.ts)
fetch_web_content抓网页(web-fetch.ts)
skills调用预置 skills
ask_question向用户提问
submit_and_exit提交最终答案并结束(完成工具)createSubmitAndExitTool
spawn_agent派生子 agent(见 05 章)createSpawnAgentTool

每个工具的 description 都写得很细致 —— 比如 read_files 明确告诉模型「已知多个文件就一次读完,和其它独立调用放同一回合」(definitions.ts:250 附近),这是在 prompt 层鼓励并行工具调用

3. 文件编辑:为什么是「唯一匹配才替换」

Cline 的主力编辑工具 editor 用的是 str_replace 语义,实现极其保守。看 replaceInFile(sdk/packages/core/src/extensions/tools/executors/editor.ts:125):

// 示意,非源码 —— 提炼自 editor.ts:125-150 replaceInFile
const occurrences = countOccurrences(content, oldStr);
if (occurrences === 0) throw new Error("文本没找到"); // 一个都没匹配 → 报错
if (occurrences > 1) throw new Error("多处匹配"); // 匹配到多处 → 也报错
const updated = content.replace(oldStr, newStr ?? ""); // 恰好一处 → 安全替换

重点看那个 occurrences > 1 的检查。 这是有意为之的安全设计:

  • 如果模型给的 old_text 在文件里出现多次,Cline 拒绝替换而不是替换第一个。因为「替错地方」是编码 agent 最危险的失败模式之一 —— 默默改错一处,后面全连环崩。
  • 不做模糊匹配(不像有些 agent 会容忍空白差异、做相似度匹配)。要么精确唯一命中,要么报错让模型重新给一段更大、更独特的上下文。

这是「宁可让模型多试一次,也绝不改错地方」的取舍。替换成功后还会生成一个紧凑的行级 diff 返回(createLineDiff,editor.ts:67),让模型看到改动效果。

编辑工具还有两条旁路:insert_line != null 走插入(insertInFile,editor.ts:152),目标文件不存在则直接 createFile(editor.ts:106)。路径安全由 resolveFilePath(editor.ts:37)守:相对路径默认不许逃出 cwd。

4. 第二条编辑路:apply_patch

apply_patch(executors/apply-patch.ts)是另一种风格 —— 接受 GPT-5 的 apply_patch 补丁语法(文件头注释明说),一次可以增/删/改/移动多个文件。它有自己的解析器 PatchParser(apply-patch-parser.ts),还兼容老式 shell 包装写法。

两者的取舍:

editor(str_replace)apply_patch
粒度单文件、单处替换多文件、多 hunk
匹配精确唯一字符串补丁上下文行
谁更稳改一两处时最安全大批量重构时更高效
默认开关Act 模式默认开默认关(enableApplyPatch: false)

5. Plan 模式 vs Act 模式:换一套工具

Cline 有个标志性概念:Plan(只读规划)Act(动手干活) 两种模式。实现不靠复杂状态机,就是换一组工具开关 —— 见 ToolPresets(sdk/packages/core/src/extensions/tools/presets.ts:20)。

关键差异就一行:

开关planact
enableEditorfalsetrue
enableReadFilestruetrue
enableSearchtruetrue
enableBashtruetrue

直觉: Plan 模式 = 把 editor 这把「会改文件的刀」收起来。模型还能读、能搜、能跑命令调研,但碰不到写文件,所以它只能输出一份计划。resolveToolPresetName(presets.ts:115 附近)根据 mode 选预设。

预设表里还有 search(纯探索)、minimalyolo(自动批准、带 submit_and_exit、给可信本地自动化用)几档,都是同一组 boolean 开关的不同组合。

6. 系统提示词怎么配合

工具集要配上系统提示词才好用。默认提示词 DEFAULT_CLINE_SYSTEM_PROMPT(sdk/packages/shared/src/prompt/system.ts:1)里有几条值得注意:

  • 反复强调并行工具调用:「识别出下一步所有独立的读/搜/命令/编辑,现在就全部发出,别等一个结果再发下一个」。
  • 强制绝对路径先给计划再动手改完要验证
  • 末尾约定:没有工具调用的回复就视为「带最终答案的完成」(system.ts:30)—— 这正好对上 01 章里「toolCalls 为空就收尾」的循环逻辑。

还有一个 YOLO_CLINE_SYSTEM_PROMPT(system.ts:38)给无头/后台模式:它要求模型一直跑工具直到调 submit_and_exit,且「修 bug 后必须跑相关测试套件直到通过」。

7. 巧妙之处

  • 编辑的安全性写进了语义:多处匹配直接拒绝(editor.ts:139),把「改错地方」从可能变成不可能。
  • 模式 = 工具子集,不是新代码路径:Plan/Act 只是 ToolPresets 里的 boolean 开关,极易理解和扩展(presets.ts:20)。
  • 完成靠工具属性:submit_and_exitlifecycle.completesRun: true(definitions.ts:747),内核据此收尾,无需特判工具名。

8. 边界与局限

  • str_replace 不做模糊匹配 —— 模型给的 old_text 必须和磁盘字符级一致且唯一,否则要重试,偶尔会多耗一轮。
  • 工具是否真的执行,还要过内核的批准层(01 章 §5)和 SessionRuntime 的策略过滤(03 章),工具清单里有不代表一定能跑。

9. 代码地图

主题文件路径符号名
默认工具工厂sdk/packages/core/src/extensions/tools/definitions.tscreateDefaultToolscreateReadFilesToolcreateSearchTool
完成工具sdk/packages/core/src/extensions/tools/definitions.tscreateSubmitAndExitTool(completesRun: true)
精确编辑sdk/packages/core/src/extensions/tools/executors/editor.tsreplaceInFilecreateEditorExecutor
补丁编辑sdk/packages/core/src/extensions/tools/executors/apply-patch.tsPatchParser
工具预设/模式sdk/packages/core/src/extensions/tools/presets.tsToolPresetsresolveToolPresetName
系统提示词sdk/packages/shared/src/prompt/system.tsDEFAULT_CLINE_SYSTEM_PROMPTYOLO_CLINE_SYSTEM_PROMPT
createTool 原语sdk/packages/shared/src/tools/create.tscreateTool