znlgis 博客

GIS开发与技术分享

第七章:核心工具链 Hashline、LSP、AST-Grep 与 Tmux

oh-my-openagent(OmO)配给 Agent 的不是简单的”读 / 写 / sed”三件套,而是一整套IDE 级别的工具链。理解这些工具是怎么工作的,你才能明白为什么 OmO 改代码”能不出错”——以及为什么有些第三方 Agent 工具改完动不动就需要你回滚。

本章涵盖 4 大核心工具体系:

  1. Hashline 编辑——LINE#ID 哈希校验编辑;
  2. LSP 工具集——把 IDE 的语义能力交给 Agent;
  3. AST-Grep 工具——基于语法树的安全搜替;
  4. Tmux 交互式终端——长时存活的终端环境,跑 REPL / TUI / 调试器。

外加 OmO 的 26 个工具速查表。


7.1 Hashline 编辑:消灭”改错行”

7.1.1 Harness 问题

研究者 Can Bölük 在 oh-my-pi / The Harness Problem 中指出:

几乎所有 Edit 工具都没办法给模型一个稳定、可验证的行定位标识……它们都依赖模型一字不差复述刚看到的原文。模型只要写错(这非常常见),用户就会怪罪大模型太蠢。

OpenAI 的 IDE Edit / Anthropic 的 IDE Edit 都有这个问题。模型记住的”原始行”其实并不一定和当前行一致——文件被另一个 Agent 修过、被 Lint 处理过、行号变了……结果就是 patch 打到了错的位置。

7.1.2 Hashline 怎么解决

OmO 借鉴了 Hashline 技术:每行代码读出来时尾部都打上一个绑定内容的哈希码,形如:

11#VK| function hello() {
22#XJ|   return "world";
33#MB| }

格式:<行号><两个字符的 hash>| <内容>

模型修改时必须引用 LINE#ID

edit({
  path: "src/foo.ts",
  edits: [{ line: "22#XJ", new: "  return 'world!';" }]
})

校验流程:

  1. 编辑工具收到 22#XJ
  2. 重新计算第 22 行内容的哈希;
  3. 哈希一致 → 应用;不一致 → 拒绝编辑,返回错误,让模型重读、再编辑。

效果:在 Grok Code Fast 1 上,仅这一改进就把编辑成功率从 6.7% 飙到 68.3%。

7.1.3 配套 Hook

  • hashline-read-enhancer:PostToolUse 钩子,在 read 工具回应里追加 LINE#ID 标记,让模型看到的就是带哈希的视图;
  • hashline-edit-diff-enhancer:PreToolUse + PostToolUse,把编辑前后视图加上 diff 标记,便于模型自检和我们调试;
  • edit-error-recovery:当编辑因哈希不一致失败时,PostToolUse 自动注入”请重读再改”的引导。

7.2 LSP 工具集:把 IDE 交给 Agent

7.2.1 6 个 LSP 工具

工具 描述
lsp_diagnostics 取错误 / 警告(构建前预检)
lsp_prepare_rename 校验某个符号是否可重命名
lsp_rename 在工作区范围内安全重命名符号
lsp_goto_definition 跳到定义
lsp_find_references 找所有引用
lsp_symbols 文件大纲 / 工作区符号搜索

7.2.2 实战用法

# Agent 在改完代码后必须做的最后一步:
lsp_diagnostics(path="src/auth.ts")
# 0 errors, 0 warnings → ok

# Agent 想重命名 logger 为 log:
lsp_prepare_rename(path="src/log.ts", line=12, character=10)
# valid → 然后:
lsp_rename(symbol="logger", newName="log")
# 工作区所有 logger 引用一次性替换

为什么这套很重要:

  • Agent 不再瞎搜瞎改:用 grep 找 logger 会误命中字符串、注释、文档;用 LSP 走的是 AST 级符号引用,精度近 100%
  • Sisyphus-Junior 必须 lsp_diagnostics 通过才算完成:被 Hook 强制要求;
  • 配合 Hashline:先用 LSP 找位置,再用 Hashline 改,几乎不出错。

7.3 AST-Grep:语法树级别的搜替

7.3.1 两个工具

工具 描述
ast_grep_search 基于 AST 的代码模式搜索(25 种语言)
ast_grep_replace 基于 AST 的代码替换

7.3.2 与 grep / sed 的差异

grep "console.log"                # 命中字符串里的 "console.log"、注释里的 console.log、变量名 console_log_x
ast_grep "console.log($A)"        # 只匹配实际的函数调用 console.log(...)
sed -i 's/foo/bar/g' file.ts      # 字符串替换,会乱伤
ast_grep replace 'foo($A)' 'bar($A)' --lang ts   # 只换函数调用 foo(x) → bar(x)

7.3.3 在 OmO 里的角色

  • 大规模重构(”把所有 console.log 替换成 logger.debug“);
  • 模式迁移(”把所有 Class extends React.Component 迁到 functional”);
  • 跨文件批量整理;
  • 与 Skill 配合(git-master 用它做精确的重构提交切片)。

7.4 Tmux 交互式终端

7.4.1 interactive_bash 工具

OmO 提供 interactive_bash 工具,本质是封装了 tmux 子命令——使 Agent 能跑长时存活的交互式进程

# 创建新会话
interactive_bash(tmux_command="new-session -d -s dev-app")

# 给会话发按键
interactive_bash(tmux_command="send-keys -t dev-app 'vim main.py' Enter")

# 抓取屏幕输出
interactive_bash(tmux_command="capture-pane -p -t dev-app")

注意:

  • 命令是 tmux 子命令,不要带 tmux 前缀;
  • 适合 vim / htop / pudb / GDB / mysql shell / Python REPL 这种 TUI 应用;
  • 一次性命令该用普通 bash 加 & 后台跑。

7.4.2 多 Agent Tmux 集成

如果你打开 tmux.enabled = true,OmO 的后台 Agent 会真的开新 tmux pane 在你眼前跑:

{
  "tmux": {
    "enabled": true,
    "layout": "main-vertical"
  }
}

效果:

  • 后台 Agent 在新 pane 出现;
  • 实时观察各 Agent 输出;
  • 完成后自动清理;
  • 稳定的 Agent 顺序:Sisyphus(1)、Hephaestus(2)、Prometheus(3)、Atlas(4) 是固定序号,剩下按字母序——避免无意义的顺序漂移。

7.5 OmO 工具地图:26 个工具

按用途归组:

7.5.1 代码搜索

工具 描述
grep 内容搜索(正则)
glob 文件名模式匹配

7.5.2 编辑

工具 描述
edit Hashline LINE#ID 哈希校验编辑

7.5.3 LSP(IDE 能力)

工具 描述
lsp_diagnostics 错误 / 警告
lsp_prepare_rename 重命名校验
lsp_rename 重命名
lsp_goto_definition 跳定义
lsp_find_references 找引用
lsp_symbols 文件大纲 / 工作区符号

7.5.4 AST-Grep

工具 描述
ast_grep_search AST 模式搜索
ast_grep_replace AST 替换

7.5.5 委派

工具 描述
call_omo_agent 调用 explore / librarian / oracle / multimodal-looker,支持 run_in_background
task 按 Category 委派 / 直接 subagent_type 委派
background_output 取后台任务结果
background_cancel 取消后台任务

7.5.6 视觉

工具 描述
look_at 通过 Multimodal-Looker 分析 PDF / 图片 / 图表

7.5.7 Skill

工具 描述
skill 按名加载 Skill / 执行斜杠命令,注入上下文化指令
skill_mcp 调用 Skill 内嵌 MCP 操作

7.5.8 会话

工具 描述
session_list 列所有 OpenCode 会话
session_read 读会话消息 / 历史
session_search 全文搜索
session_info 会话元数据 + 统计

7.5.9 任务系统(experimental.task_system: true)

工具 描述
task_create 创建任务(自动生成 ID)
task_get 取任务
task_list 列所有活跃任务
task_update 更新任务

任务对象有 subject / status / blocks / blockedBy / owner / metadata / threadID 等字段。空 blockedBy 的任务并行执行;有依赖关系的任务自动等待 blockers 完成。

存储在 .sisyphus/tasks/ 目录,重启不丢——这是它和 TodoWrite 的主要区别(TodoWrite 是会话内存,关掉就没)。

7.5.10 交互式终端

工具 描述
interactive_bash tmux 封装,TUI / 持久会话

7.6 工具与 Hook 的协同

工具不是孤立工作的,OmO 给每个工具都配了 Pre/Post Hook 加固:

工具类 关键 Hook
edit / write write-existing-file-guard(防覆盖)、hashline-edit-diff-enhanceredit-error-recoverycomment-checker
read directory-agents-injectordirectory-readme-injectorrules-injectorhashline-read-enhancer
grep / glob / lsp / ast-grep tool-output-truncator(动态根据上下文窗口截断)
task / call_omo_agent delegate-task-retryempty-task-response-detectortask-resume-infocategory-skill-reminder
interactive_bash interactive-bash-session(管理 tmux 会话)

7.7 一个真实的”工具链协同”场景

任务:”给 src/auth.ts 添加 OAuth Refresh 逻辑,然后切原子提交”。

Sisyphus
 ├─ call_omo_agent(librarian, run_in_background=true)
 │      → 查 OAuth 2.1 的 refresh_token 标准
 ├─ call_omo_agent(explore, run_in_background=true)
 │      → grep 现有 fetchAccessToken 模式
 ├─ task(category="deep", prompt="实现 refreshToken / 测试 / 集成", load_skills=[])
 │      ↓
 │  Sisyphus-Junior
 │   ├─ read src/auth.ts → 看到带 LINE#ID 的视图(hashline-read-enhancer)
 │   ├─ lsp_symbols → 文件大纲
 │   ├─ lsp_find_references("fetchAccessToken")
 │   ├─ edit (Hashline) → 改 src/auth.ts
 │   ├─ write src/auth.refresh.test.ts
 │   ├─ lsp_diagnostics(path) → 0 errors
 │   ├─ bash "npm test" → 通过
 │   └─ comment-checker 提示删了 3 条冗余 AI 注释
 └─ skill("git-master") → 把改动切成 2 个原子提交

整个过程:Hashline 保证编辑不写错行;LSP 保证语义正确;AST-Grep 在大规模重构时上场;Tmux 在你想要看 vim / 调试器时给 Agent 长存的终端;Hooks 全程偷偷把质量警卫加上。


下一章我们要讲 OmO 的”操作系统”:Hooks 与 MCP 系统。这是把上面所有看似零散的工具粘合成一个稳健流水线的关键。