Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Model: claude-opus-4-6 (anthropic/claude-opus-4-6) Generated: 2026-04-03 Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 章节: 第12章 — 解剖一个13万行代码的插件 Token Usage: ~120,000 input + ~6,500 output

12.3 工具注入架构

“注册“和“注入“有什么区别?

普通插件给宿主加工具,就像往工具箱里丢几把螺丝刀——告诉系统“有个新工具叫 my_tool“,仅此而已。

OMO 完全不同。它给每个工具配了使用说明书、安全锁、调度器和专属上下文。

graph LR
    subgraph Normal["Normal Plugin"]
        N1["Tool Name"] --> N2["Params"]
        N2 --> N3["Handler Function"]
    end
    subgraph OMO_Style["OMO Injection"]
        O1["Tool Name"] --> O2["Params"]
        O2 --> O3["Handler Function"]
        O3 --- O4["+ BackgroundManager"]
        O3 --- O5["+ ConcurrencyCtrl"]
        O3 --- O6["+ Directory Context"]
        O3 --- O7["+ Skill List"]
        O3 --- O8["+ Disabled List"]
    end
    style Normal fill:#f5f5f5
    style OMO_Style fill:#e8f5e9

**“注册”只告诉宿主“有这个工具“。“注入”**意味着工具被绑定了额外的状态、策略和上下文。


26 个工具全景图

📁 文件说明:src/tools/index.ts 工具创建的总入口。调用各个工具工厂函数,经过特性门控和禁用过滤,返回最终工具列表。

📁 文件说明:plugin/tool-registry.ts 把 OMO 工具转换成 OpenCode SDK 能理解的 ToolDefinition 格式。

graph TD
    Root["OMO Tools ~26"]

    Root --> LSP["LSP Tools x6"]
    Root --> Search["Search Tools x3"]
    Root --> BG["Background Tools x2"]
    Root --> Delegate["Delegation Tools x3"]
    Root --> Session["Session/Cmd Tools x3-4"]
    Root --> Special["Special Tools"]

    LSP --> L1["goto_definition"]
    LSP --> L2["find_references"]
    LSP --> L3["symbols"]
    LSP --> L4["diagnostics"]
    LSP --> L5["prepare_rename"]
    LSP --> L6["rename"]

    Search --> S1["grep"]
    Search --> S2["glob"]
    Search --> S3["ast_grep"]

    BG --> B1["background_output"]
    BG --> B2["background_cancel"]

    Delegate --> D1["task"]
    Delegate --> D2["call_omo_agent"]
    Delegate --> D3["skill"]

    Session --> SS1["skill_mcp"]
    Session --> SS2["slashcommand"]
    Session --> SS3["interactive_bash"]

    Special --> SP1["look_at - optional"]
    Special --> SP2["session tools"]
    Special --> SP3["task system - experimental"]

为什么要了解这些分类? OMO 的多智能体编排能力就靠这些工具支撑。没有 task 就没有“委派子任务“,没有 background_output/cancel 就没有“异步后台执行“。


最关键的工具:task(delegate-task)

📁 文件说明:src/tools/delegate-task/ 目录 包含 delegate-task 工具的全部实现:任务创建、agent 选择、会话管理、模型解析。

task 工具的工厂参数非常多,说明它不是一个简单函数:

flowchart TD
    Factory["createDelegateTask()"] --> P1["BackgroundManager"]
    Factory --> P2["OpenCode Client"]
    Factory --> P3["Current Directory"]
    Factory --> P4["User Categories"]
    Factory --> P5["Git Master Config"]
    Factory --> P6["SJ Model Config"]
    Factory --> P7["Browser Provider"]
    Factory --> P8["Disabled Skills"]
    Factory --> P9["Available Categories"]
    Factory --> P10["Available Skills"]
    Factory --> P11["onSyncSessionCreated"]

完整的执行流程:

flowchart TD
    Call(["Main Agent calls task"]) --> Parse["Parse Arguments"]
    Parse --> Mode{Sync or Async?}

    Mode -->|Async| BG["Enter BG Manager Queue"]
    BG --> CC{Within concurrency limit?}
    CC -->|Yes| Create["Create Session"]
    CC -->|No| Wait["Queue and Wait"]
    Wait --> Create

    Mode -->|Sync| HasSID{Has session_id?}
    HasSID -->|Yes| Resume["Reuse Existing Session"]
    HasSID -->|No| Create

    Create --> Agent["Select Agent"]
    Agent --> Model["Resolve Model + Fallback"]
    Model --> Send["Send Prompt"]
    Resume --> Send
    Send --> Result(["Return Result or Task ID"])

为什么 task 这么关键? OMO 的多智能体编排复用了宿主的 session 机制。一个子任务就是一个新的 OpenCode session,拥有独立消息历史和工具链路。不修改宿主核心即可实现多智能体。


闭包绑定——每个工具背后的隐藏装备

💡 什么是闭包绑定? 创建函数时让它“记住“周围的变量。function makeCounter(start) { let n = start; return () => n++ }——返回的函数“记住“了 n。OMO 让每个工具“记住“创建时的上下文。

flowchart LR
    subgraph BG_Tools["background_output / cancel"]
        BG_Bind["Bound to: BackgroundManager instance"]
    end
    subgraph Agent_Tool["call_omo_agent"]
        AG_Bind["Bound to: disabled agents + OC client"]
    end
    subgraph Skill_Tool["skill"]
        SK_Bind["Bound to: merged skills + MCP manager"]
    end
    subgraph Task_Tool["task"]
        TK_Bind["Bound to: 11 parameters<br/>Full delegation gateway"]
    end
工具绑定了什么效果
background_output/cancelBackgroundManager直接操作任务管理器
call_omo_agent禁用 agent 列表 + client自动过滤禁用 agent
skill合并技能列表 + MCP manager知道哪些 skill 可用
task11 个参数完整委派网关

并发控制

当主智能体同时委派多个后台任务时,不做限制会打满 API 配额。

📁 文件说明:src/features/background-agent/concurrency.ts 按 “model → provider → default” 三层优先级控制并发数量。

flowchart TD
    Task(["New Task"]) --> Key["Compute Concurrency Key<br/>e.g. anthropic/claude-sonnet"]
    Key --> Check{count < limit?}
    Check -->|Yes| Run["Start - count++"]
    Check -->|No| Queue["Wait in Queue"]
    Run --> Done["Task Complete"]
    Done --> Release["Release Slot"]
    Release --> Waiter{Queue has waiter?}
    Waiter -->|Yes| Handoff["Direct Handoff to Next"]
    Waiter -->|No| Decrease["count--"]

三层限额查找

flowchart LR
    L1["Model Limit<br/>e.g. claude-sonnet: 3"] -->|miss| L2["Provider Limit<br/>e.g. anthropic: 8"]
    L2 -->|miss| L3["Default Limit<br/>= 5"]

“OMO 默认每个模型/provider 5 个并发后台任务”——这个 5 就是代码里的默认值。


特性门控:不是所有工具都默认存在

OMO 在注册阶段就根据配置裁剪工具面:

flowchart TD
    All["All Possible Tools"] --> G1{multimodal enabled?}
    G1 -->|No| Skip1["Skip look_at"]
    G1 -->|Yes| Keep1["Register look_at"]

    All --> G2{experimental task system?}
    G2 -->|No| Skip2["Skip task_create etc"]
    G2 -->|Yes| Keep2["Register task tools"]

    All --> G3{hashline edit?}
    G3 -->|No| Skip3["Keep default edit"]
    G3 -->|Yes| Keep3["Override with hashline"]

    Keep1 & Keep2 & Keep3 --> Filter["filterDisabledTools()"]
    Skip1 & Skip2 & Skip3 --> Filter
    Filter --> Final["Final Tool List"]

为什么这样设计? 工具数量影响模型选择空间。太多工具让模型更容易选错。通过门控确保模型只看到真正有用的工具。

最后一层保险:filterDisabledTools(allTools, pluginConfig.disabled_tools)。即使是 OMO 自己的工具也可以通过配置禁用。整个工具层策略驱动,没有什么“不可关闭“。


从架构角度看:工具层 = ACI

OMO 的工具层本质上是 ACI(Agent-Computer Interface)——模型通过工具与外部世界交互。

graph LR
    Model["AI Model"] -->|"calls"| ACI["ACI Layer<br/>OMO Tool System"]
    ACI -->|"context"| CTX["Environment Context"]
    ACI -->|"permissions"| PERM["Access Control"]
    ACI -->|"queuing"| Q["Task Queue"]
    ACI -->|"sessions"| S["Session Management"]
    ACI -->|"concurrency"| C["Rate Limiting"]

看起来像工具集合,实际更像一个小型执行平台。


本节要点

  • “注入” ≠ “注册”:OMO 工具绑定了管理器、上下文、策略
  • 26 个工具分 6 类:LSP、搜索、后台、委派、会话命令、特殊
  • task 是核心:复用 OpenCode session 机制实现子任务委派
  • 并发控制三层限额:model → provider → default(5)
  • 特性门控裁剪工具面:功能没开的工具根本不注册
  • 策略驱动:任何工具都可以通过配置禁用