OpenCode 学习笔记 02:核心工具 - AI 如何操作代码

Phase 2 完整实现:read, write, edit, bash, grep, glob

January 19, 2026·4 min read·Yimin
#AI#Agent#OpenCode#TypeScript#Tool

AI Agent 的能力 = 工具的能力。工具越强,Agent 越强。

本篇目标

实现 6 个核心工具,让 Agent 能真正操作代码:

工具功能核心问题
read读取文件Phase 1 已实现
write写入文件创建/覆盖文件
edit局部编辑模糊匹配如何工作?
bash执行命令如何处理危险命令?
grep搜索内容搜索工具如何配合?
glob查找文件文件定位

一、edit 工具 - 模糊匹配的艺术

1.1 为什么需要模糊匹配?

LLM 生成的代码经常有细微差异:

LLM 想替换:          实际文件:
"  const x = 1"      "    const x = 1"   ← 缩进不同
"function foo()"     "function foo() "   ← 尾部空格

如果只用精确匹配,很多替换会失败。

1.2 OpenCode 的 9 种匹配策略

OpenCode 的 edit.ts9 种 Replacer,按优先级尝试:

#策略说明
1SimpleReplacer精确匹配
2LineTrimmedReplacer每行 trim 后匹配
3BlockAnchorReplacer首尾行锚定 + 中间模糊
4WhitespaceNormalizedReplacer所有空白标准化
5IndentationFlexibleReplacer缩进灵活匹配
6EscapeNormalizedReplacer转义字符处理
7TrimmedBoundaryReplacer边界修剪
8ContextAwareReplacer上下文感知
9MultiOccurrenceReplacer多次出现处理

1.3 核心算法:Levenshtein 距离

OpenCode 使用 Levenshtein 距离(编辑距离)计算相似度:

"hello" → "hallo"  距离 = 1(改1个字符)
"hello" → "helo"   距离 = 1(删1个字符)
"hello" → "helloo" 距离 = 1(加1个字符)

相似度计算

similarity = 1 - (levenshtein距离 / 最大长度)

当相似度 > 阈值时,认为匹配成功。

1.4 BlockAnchorReplacer 详解

这是最聪明的策略,用于处理中间内容变化的情况:

要替换的代码:
┌─────────────────────┐
│ function foo() {    │ ← 首行锚点
│   // old code       │
│   return 1;         │
│ }                   │ ← 尾行锚点
└─────────────────────┘

实际文件中:
┌─────────────────────┐
│ function foo() {    │ ← 首行匹配 ✓
│   // different code │ ← 中间模糊匹配
│   return 2;         │
│ }                   │ ← 尾行匹配 ✓
└─────────────────────┘

流程

  1. 找到首行完全匹配的位置
  2. 向下搜索尾行匹配
  3. 计算中间内容的相似度
  4. 相似度 > 阈值则替换

1.5 tiny-agent 简化实现

我们实现 4 种核心策略:

1. 精确匹配
2. 行 trim 匹配
3. 缩进灵活匹配
4. 首尾锚点匹配

覆盖 80% 的场景。


二、搜索工具如何配合找代码?

2.1 四种搜索工具的分工

工具用途速度精度
glob按文件名找文件最快文件级
grep按内容找位置行级
codesearch语义搜索代码概念级
LSP精确符号跳转符号级

2.2 搜索场景示例

场景:找到 UserService 的所有使用

Step 1: glob "*.ts" → 找到所有 TypeScript 文件
Step 2: grep "UserService" → 找到引用位置
Step 3: read 相关文件 → 查看上下文

场景:理解某个 API 如何工作

Step 1: codesearch "React useState hook" → 找到文档和示例
Step 2: grep "useState" path:src/ → 找到项目中的使用
Step 3: read 具体文件 → 学习用法

2.3 grep 使用示例

# 找函数定义
grep "function fetchUser"

# 找所有 import
grep "import.*from"

# 找 TODO 注释
grep "TODO|FIXME"

三、OpenCode 的高级功能(未实现)

以下是 OpenCode 的功能介绍,tiny-agent 暂未实现。

3.1 Exa API - 为 AI 设计的搜索

Exa 是专为 AI 设计的搜索引擎 API,和 Google 的区别:

传统搜索 (Google)Exa
返回 10 个链接直接返回文本内容
需要再去爬网页直接可用
为人类设计为 AI 设计

OpenCode 用 Exa 实现两个工具:

工具用途示例
websearch通用网络搜索"2024年最好的笔记本"
codesearch代码/文档搜索"Next.js App Router 用法"

3.2 LSP - 语言服务器协议

LSP(Language Server Protocol)是微软发明的协议,IDE 通过它获得智能功能:

┌─────────┐         ┌──────────────────┐
│  编辑器  │ ←LSP协议→ │   语言服务器      │
│ (Cursor) │         │ (ts-server/gopls)│
└─────────┘         └──────────────────┘
LSP 功能用途
诊断检查语法错误
跳转定义精确定位符号
查找引用找所有使用位置
自动补全代码补全建议

OpenCode 怎么用?

写入文件后自动检查错误,如果有语法问题就让 AI 修复:

写入代码 → LSP 检查 → 发现错误 → AI 自动修复

3.3 为什么我们不实现?

功能复杂度需要
websearchExa API Key ($)
codesearchExa API Key ($)
LSP启动语言服务器进程、实现协议通信

LSP 复杂的原因:OpenCode 的 lsp/ 目录有 ~1000 行代码专门处理。

这些是生产级功能,理解核心概念后可以自行添加。


四、bash 工具 - 如何处理危险命令?

4.1 OpenCode 的命令解析

OpenCode 使用 Tree-sitter 解析 bash 命令:

git commit -m "fix" && rm -rf ./temp

解析为:

[
  { "command": "git", "args": ["commit", "-m", "fix"] },
  { "command": "rm", "args": ["-rf", "./temp"] }
]

4.2 权限分级

命令类型权限级别示例
只读命令自动允许ls, cat, git status
项目内写提示确认rm ./temp, git commit
项目外操作严格确认rm /tmp/xxx
危险命令拒绝执行rm -rf /

4.3 tiny-agent 简化实现

我们使用简单的模式匹配:

const dangerousPatterns = [
  /rm\s+-rf\s+\/(?!\w)/,  // rm -rf /
  /mkfs/,                  // 格式化磁盘
  /dd\s+if=.*of=\/dev/,   // 直接写设备
]

生产环境需要更完善的权限系统。


五、工具组合:完整的代码修改流程

用户: "修复 fetchUser 函数的空指针问题"

Step 1: grep "fetchUser" → 找到定义位置
        结果: src/api/user.ts:23

Step 2: read src/api/user.ts → 查看代码
        发现: 没有 null 检查

Step 3: edit src/api/user.ts → 添加 null 检查
        oldString: "return data.user"
        newString: "return data?.user ?? null"

Step 4: bash "npm test" → 验证修复
        结果: All tests passed ✓

六、总结

工具清单

工具核心能力文件
read读取文件tool/read.ts
write创建/覆盖文件tool/write.ts
edit模糊匹配局部编辑tool/edit.ts
bash执行命令tool/bash.ts
grep正则搜索tool/grep.ts
glob文件查找tool/glob.ts

关键理解

  1. 模糊匹配很重要

    • LLM 输出不精确,需要容错
    • OpenCode 有 9 种匹配策略
    • Levenshtein 距离计算相似度
  2. 搜索工具各有分工

    • glob: 文件级定位
    • grep: 行级定位
    • codesearch: 语义级搜索
    • LSP: 符号级跳转
  3. 外部信息获取

    • websearch: Exa API 网络搜索
    • codesearch: 代码文档搜索
    • webfetch: 直接获取网页
  4. 安全很重要

    • Tree-sitter 解析命令
    • 分级权限控制
    • 危险命令拦截

代码仓库

完整代码:external/tiny-agent/

cd external/tiny-agent
make dev
You: 把 add 函数的返回类型改成 number
AI: [read] 查看文件
    [edit] 修改代码(缩进灵活匹配)
    ✅ 编辑成功