Skip to content

第五章 OmO 插件架构

← 返回目录 | 上一章:工具链与会话模型 | 下一章:OmO Agent 体系 →


本章合并原报告 §6(插件架构)、§10(Hook 与生命周期)、§22(Features 模块与 Hook 完整目录),全面展示 OmO 的结构设计。

5.1 "不改一行代码"的增强哲学

OmO 的核心设计约束是:作为纯插件运行,不修改 Opencode 的任何源代码。这意味着 OmO 所有的能力——12 个 Agent、26 个工具、48 个 Hook、3 个 MCP 服务器——全部通过 Opencode 暴露的 8 个插件接口实现。

这个约束带来了显著的工程优势:

  • 独立升级:Opencode 和 OmO 可以分别更新,不会互相破坏
  • 可选增强:用户可以选择使用或不使用 OmO
  • 清晰边界:出问题时容易定位是平台问题还是插件问题

但也带来了工程挑战:

  • 需要通过有限的 Hook 接口实现复杂的编排逻辑
  • 某些功能(如后台任务)在原生 Opencode 中完全不存在,需要从零构建

5.2 初始化流程

OmO 的入口文件 (src/index.ts) 执行以下初始化序列:

loadConfig()                    ← 加载多层配置(项目/用户/默认)

createManagers()                ← 初始化核心管理器
    ├── BackgroundManager       ← 后台任务调度器
    ├── SessionHistoryManager   ← 会话历史搜索
    ├── McpManager              ← MCP 服务器生命周期
    └── SkillManager            ← Skill 发现与加载

createTools()                   ← 注册 26 个工具

createHooks()                   ← 组装 48 个生命周期 Hook

createPluginInterface()         ← 返回符合 Opencode 插件接口的对象

关键实现细节

  • 配置注入:OmO 通过 config Hook 将自己的 Agent 定义、工具列表、模型绑定全部注入 Opencode 的配置系统。Opencode 在启动时加载插件配置,"认为"这些 Agent 和工具是自己原生的。
  • 工具注入:通过 tool Hook 返回 26 个工具定义,Opencode 的工具注册表会把它们和原生工具一起注册。
  • 消息拦截:通过 chat.messageexperimental.chat.messages.transform Hook 拦截和修改消息流,实现后台任务通知、上下文注入等功能。
  • 事件监听:通过 event Hook 监听 Opencode 的事件流(会话空闲、消息完成等),驱动后台任务轮询和续航机制。

5.3 多层配置系统

OmO 的配置采用三层合并策略:

项目级配置 (.opencode/oh-my-opencode.jsonc)
    ↓ 覆盖
用户级配置 (~/.config/opencode/oh-my-opencode.jsonc)
    ↓ 覆盖
默认配置 (OmO 内置)

合并规则

  • 简单字段:项目级 > 用户级 > 默认(覆盖)
  • Agent/Category:深度合并(可以只覆盖某个 Agent 的模型,保留其他配置)
  • disabled_ 数组*:Set 并集(项目和用户级的禁用列表合并)

配置示例:

jsonc
// .opencode/oh-my-opencode.jsonc
{
  "agents": {
    "sisyphus": {
      "model": "anthropic/claude-opus-4-6"  // 只覆盖模型,保留其他配置
    }
  },
  "categories": {
    "quick": {
      "model": "anthropic/claude-sonnet-4-6"  // 修改 quick 类别的默认模型
    }
  },
  "disabled_agents": ["librarian"],  // 禁用特定 Agent
  "disabled_tools": ["interactive_bash"]  // 禁用特定工具
}

5.4 五层 Hook 架构

OmO 将 48 个 Hook 组织为 5 个层级,每层负责不同的关注点:

层级 1: Session Hooks(23 个)—— 会话生命周期管理
层级 2: Tool-Guard Hooks(12 个)—— 工具执行拦截与增强
层级 3: Transform Hooks(4 个)—— 消息序列变换
层级 4: Continuation Hooks(7 个)—— 任务续航与自动恢复
层级 5: Skill Hooks(2 个)—— Skill 动态加载

5.4.1 Session Hooks(会话层)

这一层处理会话级别的事件和状态管理:

关键 Hook

Hook触发时机功能
session-idle-detector会话空闲时检测父 session 空闲,触发后台任务通知注入
background-task-notifier后台任务完成时将完成通知组装为 system-reminder 消息
ultrawork-detector用户消息包含关键词时检测 "ultrawork"/"ulw" 关键词,激活 Ultrawork 模式
session-type-tracker会话创建/切换时追踪会话类型(主会话/子任务/后台任务)
model-overrideLLM 调用前Ultrawork 模式下覆盖模型为最高能力版本

5.4.2 Tool-Guard Hooks(工具守卫层)

这一层在工具执行前后插入逻辑,实现增强和保护:

Hook触发时机功能
task-delegation-guardTask 工具执行前拦截原生 TaskTool 调用,路由到 OmO 的后台任务系统
lsp-tool-routerLSP 工具执行前将 OmO 的 6 个 LSP 工具路由到 Opencode 的底层 LSP 服务
bash-safety-guardBash 执行前检测危险命令(rm -rf, dd 等),要求确认
tool-output-truncator工具执行后截断过长的工具输出(默认 50K tokens,webfetch 10K)
edit-validation编辑工具执行后验证文件编辑结果,检测潜在问题

task-delegation-guard 是最关键的 Hook——它是 OmO 后台任务系统(BackgroundManager,负责异步任务的排队、并发控制与生命周期管理)与 Opencode 的桥梁。当任何 Agent 调用 task 工具时:

Agent 调用 task(run_in_background=true, ...)

tool.execute.before Hook 拦截

task-delegation-guard 接管:
    ├─ 如果 run_in_background=true → 路由到 BackgroundManager
    ├─ 如果有 category → 解析为 Sisyphus-Junior + 对应模型
    ├─ 如果有 subagent_type → 路由到对应 Agent
    └─ 如果有 session_id → 续接已有会话

返回 task_id 给调用者(不等待完成)

5.4.3 Transform Hooks(消息变换层)

这一层通过 Opencode 的 experimental.chat.messages.transform 接口,在 LLM 调用前变换整个消息序列:

Hook功能
system-prompt-injector将 OmO 的动态系统提示注入到消息序列开头
queue-message-injector将队列消息(后台任务通知等)注入到消息序列末尾
context-recovery上下文窗口溢出时执行多策略恢复
skill-context-injector将已加载 Skill 的指令注入到系统提示中

5.4.4 Continuation Hooks(续航层)

这是 OmO 最有特色的 Hook 层——确保长时间运行的任务不会因为 Agent"忘记"或"放弃"而中断。

Atlas Hook(核心续航器)

Atlas 是一个"任务续航守护者"。当 Sisyphus 完成一轮对话但 Todo 列表中还有未完成的任务时,Atlas 会注入一条系统提醒,强制 Agent 继续工作:

Sisyphus 完成回复 → session 进入 idle 状态

Atlas 检查决策门控:
    ├─ 会话类型是否正确?(只在主会话中工作)
    ├─ 是否有中止信号?(用户手动停止)
    ├─ 连续失败次数?(超过阈值则暂停)
    ├─ 后台任务是否仍在运行?(等待结果)
    ├─ 当前 Agent 是否匹配?(只对 Sisyphus/Atlas 生效)
    ├─ Todo 是否全部完成?
    └─ 冷却时间是否满足?

如果有未完成 Todo → 注入续航提醒:
    "你还有 N 个待办任务未完成。请继续工作。"

Sisyphus 收到提醒 → 继续处理下一个 Todo

Boulder 机制(防无限循环)

"Boulder"(巨石)是 Atlas 的防护机制,用指数退避防止 Agent 陷入无限循环:

首次提醒: 等待 30 秒后注入
第二次: 60 秒
第三次: 120 秒
第四次: 240 秒
第五次: 5 分钟暂停
    → 之后重新评估是否继续

5.4.5 Skill Hooks(技能层)

Hook功能
skill-discovery从多个路径发现 SKILL.md 文件
skill-mcp-lifecycle管理 Skill 内嵌 MCP 服务器的启动/停止

5.5 Features 模块系统

OmO 将大量功能封装为独立的 Feature 模块src/features/),每个模块自包含实现、类型和测试。这是 OmO 代码组织的核心模式——避免"上帝类"(god object),以 19 个聚焦的模块替代。

模块复杂度功能
background-agent高(31 文件,~10k LOC)后台任务生命周期管理、并发控制(5/model)、FIFO 队列、轮询调度——详见后台任务系统
opencode-skill-loader高(33 文件)4 层作用域的 Skill 发现与加载(项目 > opencode > 用户 > 全局),YAML frontmatter 解析
tmux-subagent高(30 文件)tmux 窗格管理、网格规划、会话编排——支持 interactive_bash 工具
mcp-oauth高(18 文件)OAuth 2.0 + PKCE + 动态客户端注册(RFC 7591),为 MCP 远程服务器提供认证
builtin-skills低(17 文件)6 个内置 Skill:git-master、playwright、playwright-cli、agent-browser、dev-browser、frontend-ui-ux
skill-mcp-manager中(12 文件)管理 Skill 内嵌 MCP 服务器的生命周期(启动/停止/连接)
claude-code-plugin-loader中(10 文件).opencode/plugins/ 发现和加载 Claude Code 兼容插件
builtin-commands低(11 文件)内置斜杠命令模板(refactor、init-deep、handoff、start-work 等)
claude-tasks中(7 文件)持久化任务管理(文件存储 + Opencode todo 同步)
claude-code-mcp-loader中(6 文件)加载 .mcp.json 中定义的 Claude Code 兼容 MCP 服务器,支持 ${VAR} 环境变量展开
context-injector中(6 文件)将 AGENTS.md 和 README.md 注入到会话上下文中
run-continuation-state低(5 文件)run 命令的跨会话持久化续航状态
hook-message-injector中(5 文件)通用的系统消息注入框架,供各 Hook 使用
boulder-state低(5 文件)Atlas 巨石(Boulder)续航机制的持久化状态
task-toast-manager中(4 文件)任务进度的 TUI Toast 通知
tool-metadata-store低(3 文件)工具执行元数据缓存(记录工具调用历史供后续分析)
claude-code-session-state低(3 文件)子 Agent 会话状态追踪
claude-code-command-loader低(3 文件).opencode/commands/ 加载自定义命令
claude-code-agent-loader低(3 文件).opencode/agents/ 加载自定义 Agent 定义

Claude Code 兼容层:注意有 5 个 claude-code-* 模块——它们使 OmO 能够加载 Claude Code 格式的插件、MCP 配置、命令和 Agent 定义。这意味着为 Claude Code 编写的扩展可以直接在 Opencode + OmO 中使用。

5.6 Doctor 诊断系统

omo doctor 是一个环境健康检查命令(cli/doctor/,23 个检查文件),分 4 个类别自动检测常见问题:

类别检查项
System二进制文件存在、版本 ≥ 1.0.150、插件已注册、版本匹配
ConfigJSONC 语法有效、Zod Schema 验证通过、模型覆写语法正确
ToolsAST-Grep 可用、注释检查器正常、LSP 服务器可启动、GitHub CLI 可用、MCP 服务器连接正常
Models缓存存在、模型解析成功、Agent/Category 覆写有效、模型可用性

Doctor 的检查并行执行runner.ts),支持三种输出格式:默认(人类可读)、详细(含修复建议)、JSON(机器可读)。这是一个优秀的运维实践——当用户报告问题时,omo doctor 的输出可以快速定位根因。

5.7 配置迁移

shared/migration/index.ts 实现了自动配置迁移:当配置文件中存在过时的键名(如旧版 Agent 名称、废弃的 Hook 名称、过时的模型版本标识)时,系统在加载配置时自动转换为新格式。这让用户无需手动更新配置文件即可升级到新版本。

5.8 Hook 完整目录

第 4 节介绍了 Hook 的五层架构和关键 Hook 的功能。以下是完整的 48+ 个 Hook 分类目录,基于 src/hooks/ 目录的逐文件分析:

5.8.1 Session Hooks(23 个)——会话生命周期

Hook功能
context-window-monitor监控上下文窗口使用率,触发预防性压缩
preemptive-compaction在上下文窗口接近上限时主动执行消息压缩
preemptive-compaction-degradation-monitor监控压缩后模型能力是否退化
preemptive-compaction-no-text-tail压缩时去除尾部无意义文本
think-mode根据任务复杂度动态调整模型思维深度
ralph-loop自引用开发循环(14 文件,~1687 LOC)
model-fallbackProvider 级别模型降级链
runtime-fallback实时错误捕获与自动重试
anthropic-context-window-limit-recoveryAnthropic 特定的上下文窗口溢出恢复
anthropic-effort调整 Anthropic 模型的 effort 级别
no-sisyphus-gpt限制 Sisyphus 不使用 GPT 系列模型
no-hephaestus-non-gpt限制 Hephaestus 仅使用 GPT 兼容模型
session-recovery会话崩溃后的恢复机制
session-notification会话状态通知(7 个辅助文件:内容、格式化、调度、发送等)
background-notification后台任务完成通知注入
auto-update-checker插件更新检查与通知
non-interactive-env非交互环境(如 CI)的特殊处理
openclawOpenClaw 集成
legacy-plugin-toast旧版插件迁移提示
start-work工作会话启动(与 Prometheus 规划器配合)
empty-task-response-detector检测并处理空任务响应
session-todo-status追踪会话中的 Todo 完成状态
agent-usage-reminder提醒 Agent 使用特定模式

5.8.2 Tool-Guard Hooks(12 个)——工具执行拦截与增强

Hook功能
comment-checker检测并阻止 AI 生成的代码注释污染
rules-injector.sisyphus/rules/ 目录中的规则文件注入到上下文
write-existing-file-guard防止意外覆盖已有文件(要求先 read 才能 write)
bash-file-read-guard阻止通过 bash 命令读取文件(强制使用 read 工具)
hashline-read-enhancer为文件内容添加行哈希锚点
hashline-edit-diff-enhancer增强编辑操作的 diff 显示
json-error-recoveryJSON 解析错误的自动恢复
edit-error-recovery文件编辑错误的自动恢复(如 oldString 未找到时的重试策略)
tool-output-truncator截断过长的工具输出(默认 50K tokens)
question-label-truncator截断 question 工具中过长的选项标签
read-image-resizer缩小读取的图片尺寸以节省 token
webfetch-redirect-guard防止 webfetch 陷入重定向循环

5.8.3 Transform Hooks(4 个)——消息序列变换

Hook功能
claude-code-hooksClaude Code 兼容的会话管理 Hook
keyword-detector检测用户消息中的关键词(如 "ultrawork"/"ulw")
context-injector将 AGENTS.md、README.md 等上下文注入到消息序列
thinking-block-validator验证和规范化模型的 thinking block

5.8.4 Continuation Hooks(7 个)——任务续航与自动恢复

Hook功能
todo-continuation-enforcer当 Todo 列表存在未完成项时强制续航
atlasAtlas 核心续航器——详见本章第 4.4 节
stop-continuation-guard响应 /stop-continuation 命令,终止所有续航机制
compaction-context-injector压缩后向上下文注入必要的恢复信息
compaction-todo-preserver压缩时保留 Todo 列表不被裁剪
delegate-task-retry委派任务失败时的自动重试
task-reminder提醒 Agent 存在待处理的任务

5.8.5 Skill Hooks(2 个)——技能动态加载

Hook功能
category-skill-reminder在委派时提醒 Agent 加载匹配的 Skill
auto-slash-command自动检测并执行斜杠命令

5.8.6 其他辅助 Hooks

Hook功能
unstable-agent-babysitter监控不稳定的 Agent 行为,防止失控
sisyphus-junior-notepadSisyphus Junior 的临时记事本功能
tasks-todowrite-disabler在 task 子 Agent 中禁用 TodoWrite 工具
todo-description-override覆写 Todo 项的描述内容
task-resume-info提供任务恢复所需的上下文信息
prometheus-md-only限制 Prometheus 规划器仅输出 Markdown
interactive-bash-session管理 tmux 交互式终端会话的生命周期

设计哲学:48 个 Hook 可能看起来数量庞大,但这正是 OmO 的设计精髓——每个 Hook 只做一件事(单一职责),可以独立启用/禁用(通过配置的 disabled_hooks 数组),也可以独立测试。相比一个巨大的"do everything"中间件,这种细粒度 Hook 架构提供了更好的可维护性和可调试性。


← 返回目录 | 上一章:工具链与会话模型 | 下一章:OmO Agent 体系 →