11 · Integrations 与 Plugins¶
Herdr 有两套“扩展”机制,但目标完全不同:Integration 让外部 Agent 更好地向 Herdr 报告自身;Plugin 让用户给 Herdr 增加动作、事件命令和工具 pane。 把二者分开,才能理解为什么前者大量编辑 Agent 配置,后者有 manifest/registry/runtime。
11.1 对照表¶
| 维度 | Integration | Plugin |
|---|---|---|
| 扩展谁 | 外部 AI Agent | Herdr 工作流/UI |
| 安装动作 | 写 hook/extension/script、编辑 Agent config | link 一个含 herdr-plugin.toml 的目录 |
| 主要数据流 | Agent lifecycle → Herdr API | Herdr context/event → 外部 command/pane |
| 状态影响 | Agent session/state authority | action/log/pane,不直接成为 Agent 权威 |
| 更新判断 | 内嵌 asset version marker | plugin manifest version/min Herdr version |
| 风险 | 改用户已有 Agent 配置 | 执行用户信任的外部命令 |
11.2 Integration 目标版图¶
固定快照的 IntegrationTarget 有 16 个:
Pi, Omp, Claude, Codex, Copilot, Devin, Droid, Kimi,
OpenCode, Kilo, Hermes, QoderCLI, Cursor, MastraCode,
Antigravity CLI, Grok
平台可用性、命令别名和安装目录发现集中在 src/integration/registry.rs。例如 Cursor 使用 cursor-agent,Antigravity CLI 使用 agy,Kilo 可能有多个命令名。
11.3 为什么每个 Agent 都要定制安装器¶
Agent 的扩展模型不同:
- 某些读取
settings.json的 hooks; - 某些读取
hooks.json/ TOML; - Pi/OMP 使用 TypeScript extension;
- OpenCode/Kilo 使用 JavaScript plugin;
- Hermes 使用 Python plugin manifest;
- 不同事件名表达 start/stop/blocked/session replacement;
- Windows 需要 PowerShell 资产和可执行处理差异。
因此 src/integration/targets.rs 不是一个通用“复制 hook.sh”循环,而是每个目标的显式 install/uninstall 流程,共享底层安全 helper。
11.4 Bundled assets 与版本标记¶
脚本/插件资产通过 include_str! 编进 Herdr 二进制,位于 src/integration/assets/。好处是:
- 离线安装,不依赖运行时网络;
- 资产与可执行文件版本一起发布;
- updater/handoff 后可判断已安装版本是否 outdated;
- 集成测试可以直接运行同一资产。
安装内容包含 Herdr ownership/version marker。状态检查可区分 not installed / current / outdated,而不是只看文件是否存在。
11.5 配置编辑必须保留用户内容¶
安装 Claude/Codex 等 integration 时,需要更新用户已有 JSON/TOML。安全要求:
- 解析现有配置,解析失败则停止,不覆盖;
- 只增删 Herdr 所拥有的命令/命名块;
- 安装幂等:重复运行不产生重复 hook;
- 卸载只删除能证明属于 Herdr 的条目;
- 保留用户顺序/未知字段的程度以各格式能力为准;
- 写回前验证生成结构;
- 需要时清理明确识别的 legacy 资产。
例如卸载不能“删除所有 PermissionRequest hooks”;那会破坏用户其他工具。源码中的 src/integration/config_edit.rs 用命令路径、marker 和命名 block 精确定位 Herdr-owned 项。
11.6 Integration 的运行数据流¶
sequenceDiagram
participant A as Agent hook/extension
participant Env as HERDR_* context
participant API as Herdr local API
participant T as TerminalState
participant E as EventHub/UI
A->>Env: read pane/session/socket context
A->>API: pane.report_agent/session/metadata
API->>T: validate identity/source/sequence
T->>T: arbitrate hook vs screen evidence
T-->>E: publish only effective changes
Hook 需要知道自己属于哪个 Herdr pane/terminal/session。上下文通过受控环境变量/启动环境注入,报告仍由 API 验证,不能因为请求来自本地脚本就跳过 identity 和 sequence。
11.7 完整 lifecycle 与 session-only¶
不同 Agent 暴露的事件能力不同:
- 有 start/stop/blocked/session replace 的 integration 可以成为 full-lifecycle authority;
- 只知道 session id 的 integration 主要帮助 native resume,状态继续用 screen detection;
- 没有明确 blocked 事件时,不能用一个泛化 post-tool hook猜测 Idle;
- process exit 会终止该 authority generation。
这也是 integration_target_available 与“状态权威能力”不能混成一个 bool 的原因:能安装不代表能完整报告。
11.8 Plugin manifest¶
Plugin 从本地目录的 herdr-plugin.toml 加载。固定测试 fixture 展示最小形状:
id = "example.smoke"
name = "Smoke Plugin"
version = "0.1.0"
min_herdr_version = "0.6.10"
platforms = ["linux", "macos", "windows"]
[[actions]]
id = "workspace-list"
title = "List workspaces"
contexts = ["workspace"]
command = ["herdr", "workspace", "list"]
[[events]]
on = "worktree.created"
command = ["herdr", "plugin", "log", "list", "--plugin", "example.smoke"]
[[panes]]
id = "board"
title = "Board"
placement = "overlay"
command = ["herdr", "workspace", "list"]
原 fixture 见 tests/fixtures/plugin-smoke/herdr-plugin.toml。
11.9 Manifest 六类入口¶
| section | 何时运行 | 用途 |
|---|---|---|
build |
link/update 时按平台 | 编译/准备插件资产 |
startup |
server/plugin startup | 启动伴随进程或准备环境 |
actions |
用户/API 显式 invoke | 上下文动作 |
events |
允许的 Herdr 事件发生 | 低频自动化 hook |
panes |
用户打开工具 pane | dashboard、日志、辅助 TUI |
link_handlers |
匹配终端中的 link/pattern | 把链接映射到 action |
每类 entry 都可声明 platforms,command 使用 argv 数组而不是默认 shell 字符串,减少 quoting 注入和跨平台歧义。
11.10 Manifest 验证¶
加载器在 src/app/api/plugins/manifest.rs 中验证:
- plugin/action/pane/link handler ID 格式和长度;
- name/version/command 非空;
min_herdr_version;- platform 值只允许 linux/macos/windows;
- action id 在 plugin 内唯一;
- event kind 在允许集合;
- pane placement 与 width/height 组合合法;
- link handler pattern/action 引用有效;
- canonical manifest/root 路径。
验证后转成 API schema 中的 InstalledPluginInfo 等公开类型,避免 runtime 到处处理半合法 raw TOML。
11.11 Pane placement¶
PluginPanePlacement 有五种:
| placement | 行为 |
|---|---|
overlay |
覆盖当前 UI 的全尺寸/受控层 |
popup |
有 width/height 的浮层 |
split |
在目标 pane 旁插入 BSP split |
tab |
新建 tab 承载工具进程 |
zoomed |
以 zoomed pane 打开并聚焦 |
只有 popup 接受 width/height;split 需要 direction/target;zoomed 通常强制 focus。打开失败必须回滚已创建的 layout/pane/runtime,复用第 4、5 章的补偿事务边界。
11.12 Action 上下文与命名空间¶
Plugin action 的外部身份必须带 plugin id,例如逻辑上的:
否则两个插件都定义 open 时无法解析。invoke 时 Herdr 构造受控 context/env,可能包含:
- plugin root/id/version;
- 当前 workspace/tab/pane public id;
- cwd/repo/worktree;
- Herdr session/API socket;
- manifest 声明和调用方额外 env(经过验证)。
Action command 是外部进程,失败应记录 exit/status/log,不应 panic server。
11.13 Plugin registry 的读写策略¶
全局 registry 记录 linked manifest path、source、enabled 等。它使用 lock + temp/rename 管理并发和原子写。
一个细致的策略是:
- 启动读取可宽容:坏 registry 不应阻止 Herdr 启动,可警告并跳过;
- 显式 mutation 前严格读取:用户执行 link/unlink/enable 时,若原文件坏,必须停止,不能把“宽容读出的空列表”写回覆盖证据;
- 每次加载重解析 manifest:路径下内容可更新;
- 保留 registry 的 enabled/source:manifest 自身不拥有用户开关。
实现位于 src/persist/plugin_registry.rs。这是一种很实用的“可用性读 vs 破坏性写”差异化严格度。
11.14 Event hook 的隔离¶
Plugin event command 以 detached/background 方式运行,日志有界保存。运行时必须避免:
- 阻塞 App event loop 等 child;
- 一个 hook 失败阻断其他插件;
- 无限 stdout/stderr 占内存;
- 高频 event 触发进程风暴;
- plugin 产生相同事件形成无界反馈;
- server shutdown 遗留失控 child(按 startup/event 语义区分)。
因此允许的 event 集合会排除 output/scroll 等高频种类,runtime 只把完成结果/日志摘要送回主循环。
11.15 信任模型¶
Plugin 是本地代码执行扩展,不是强沙箱:manifest command 可以读取用户权限可访问的文件。Herdr 能做的是:
- 只运行用户显式 link/enable 的目录;
- 展示 canonical source path 和命令;
- 不经 shell 解释 argv;
- 严格校验 manifest;
- 约束 Herdr 注入的上下文;
- 以进程/日志/事件隔离保护 server 可用性。
这与“远程市场安装后安全运行不受信代码”是不同产品。如果未来引入远程来源,需要签名、权限声明或 sandbox 等额外层,不能把当前本地信任模型误当供应链安全。
11.16 测试版图¶
- integration config edit 单测:保留未知用户项、幂等、精确卸载、legacy migration;
- bundled JS/TS asset 用 Bun 测试真实 lifecycle payload;
- plugin manifest 表驱动测试:ID、platform、placement、version、command;
- CLI/API plugin 集成测试:link/list/enable/action/log/pane;
- Live Handoff 测试:plugin registry/伴随行为跨 server replacement;
- 三平台 fixture:路径、PowerShell/shell、可执行权限差异。
11.17 本章结论¶
- Integration 是 Agent 观测适配层,Plugin 是 Herdr 工作流扩展层;
- 修改用户配置必须以 ownership marker 做可逆、幂等编辑;
- hook authority 取决于 lifecycle 完整度,不取决于是否安装;
- Plugin manifest 先完整验证,再转成 runtime 可依赖的 typed model;
- 外部命令要隔离、日志有界,高频事件不能直接映射为进程 spawn;
- 宽容启动读取不能演变成破坏性写回。
下一章回到 Herdr 的核心工作流:一个 Agent 一个 Git worktree。我们会看 Git 命令如何从 UI/API 移出主循环,operation id 怎样拒绝乱序结果,强制删除又如何证明目标确实属于该 repo。