Skip to content

Commit 43765f6

Browse files
committed
feat(extensions): add reviewed OpenCode tool hooks
Add recursive slash-command help, canonical OpenCode command shadowing, and reviewed tool.execute before/after hooks across Desktop, TUI, and Peer Host. Share typed errors, recovery actions, and bounded Node worker lifecycle while keeping unsupported runtimes and remote execution fail closed.
1 parent aa2e760 commit 43765f6

76 files changed

Lines changed: 13318 additions & 1929 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/architecture/extensions/capability-runtime-integration-design.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ BitFun 采用“一个能力核心,多种宿主适配”的方向,而不是
6262
|---|---|---|
6363
| `exclusive` | 主 Session Store、最终 Compactor 等只能有一个 active owner 的能力 | 组装时选出一个 Provider;运行时不允许两个实现双写。 |
6464
| `ordered-chain` | Context Transformer、Prompt/Tool Hook、验证器 | 顺序由能力 owner 或生态 adapter 明确;每步校验,失败策略类型化。 |
65-
| `namespace-union` | Tools、Commands、Agents | 先按来源限定身份保留候选,再按名称和作用域解析;同名不静默跨生态覆盖。冲突界面先列 BitFun、再按稳定 provider 身份列其他生态,但展示顺序不自动决定胜者。 |
65+
| `namespace-union` | Tools、Agents、跨独立 provider 的 Commands | 先按来源限定身份保留候选,再按名称和作用域解析;同名不静默跨生态覆盖。冲突界面先列 BitFun、再按稳定 provider 身份列其他生态,但展示顺序不自动决定胜者。 |
66+
| `command-shadowing` | 已按单一生态规则解析的 Prompt Command 与产品内置命令同名 | 沿用来源生态已经形成的覆盖语义;OpenCode Command 使用同一个 `/<name>` 覆盖内置命令。被覆盖的内置操作只在命令菜单以同名来源标签保留,不生成来源类型前缀。 |
6667
| `ordered-namespace` | 现有 Skill 根 | 保留来源限定身份并按 Skill Registry 已发布的根顺序解析同名项;被覆盖项继续可见。来源元数据只用于解释结果,不参与重新排序。 |
6768
| `fallback` | Memory Retriever、模型 Provider、外部服务 | 只对声明为可恢复的错误切换;权限拒绝、取消和副作用不自动 fallback。 |
6869
| `fan-out` | 只读事件 Observer、运维遥测 | Observer 互相隔离;不能阻塞或改变权威业务结果。 |

docs/architecture/extensions/external-ai-work-sources-design.md

Lines changed: 52 additions & 19 deletions
Large diffs are not rendered by default.

docs/architecture/extensions/opencode-config-assets-adapter-design.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -256,12 +256,12 @@ stale selection 并等待重新选择,不能直接执行刚刷新的新内容
256256
后续阶段接通文件引用和 shell 输出时仍按 OpenCode 顺序展开。`!shell` 必须进入脚本执行域,不另建绕过可靠性控制
257257
的同步 shell 路径;展开有期限、取消和输出大小限制,大输出保存后只把引用交给命令模板。
258258

259-
OpenCode 生态内部仍按其规则覆盖同名内置命令,但跨独立 provider 或与 BitFun 本地命令同名时不得静默覆盖。
260-
发生冲突后,兼容视图展示全部来源;交互式 TUI(ChatMode)对本地/单一外部冲突提供 `/builtin:name``/external:name`,对跨
261-
provider 候选提供 `/external:<provider>:<name>`。一次外部候选选择同时解析同名本地命令冲突。选择按候选身份和
262-
`content_version` 形成的冲突指纹持久化,同一指纹只询问一次任一外部候选更新、删除或参与集合变化后指纹变化并
263-
重新询问,即使变化后只剩一个外部或内建候选也不能静默切换实现。持久化只保留每个执行域/命令族的当前指纹和
264-
去重后的曾冲突候选身份,不累计每次内容版本的完整历史。
259+
OpenCode 生态内部仍按其规则覆盖同名内置命令;BitFun 对已解析的单一外部 Command 同样使用 `/<name>` 并覆盖同名内置命令,
260+
不创造来源类型前缀。交互式 TUI(ChatMode)的命令菜单保留同名、标注 BitFun 来源的内置操作,用户从该行选择时仅执行本次
261+
内置操作。跨独立 provider 同名时,兼容视图与 TUI 菜单以相同 `/<name>`、不同来源标签展示全部候选;选择按候选身份和
262+
`content_version` 形成的冲突指纹持久化,同一指纹只询问一次任一外部候选更新、删除或参与集合变化后重新选择。外部候选
263+
移除后同名内置命令立即恢复,不要求额外确认。持久化只保留每个执行域/命令族的当前跨 provider 指纹和必要候选身份,
264+
不累计每次内容版本的完整历史。
265265

266266
### 5.4 MCP、LSP 与 Formatter
267267

docs/architecture/extensions/opencode-extension-compatibility.md

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,18 @@ OpenCode,和 OpenCode 配置/插件进入 BitFun 是两个独立验收方向
6767
非阻塞摘要;可执行内容在首次启用或能力扩大时等待来源/target 级确认,但不阻塞项目和无关会话。
6868
- 设置中的统一外部来源视图负责解释全局/项目作用域、当前支持范围、待处理项和变更结果;显式导入只是把
6969
非执行内容转为 BitFun 原生配置的可选快照,不是 OpenCode 项目可用或插件执行的前置条件。
70-
- Desktop、TUI、Peer Host 与只读 Server 使用同一版本化控制 DTO。控制面只共享正交生命周期、Host 能力、恢复动作、
70+
- Desktop、TUI、Peer Host 与只读 Server 使用同一版本化来源控制 DTO。控制面只共享正交生命周期、Host 能力、恢复动作、
7171
`Refresh/SetSourceEnabled/SetSafeMode`,不携带 OpenCode 私有 payload;审批和冲突仍归 Tool/Subagent/MCP 等能力 owner。
72-
- 第一条执行闭环已覆盖官方复数目录和源码验证过的单数目录中的受支持单文件 `.js` standalone tool;`.ts`、模块依赖、
73-
package plugin、完整配置、Hook 和 TUI target 仍只识别或延后。当前范围和完整兼容目标必须分别表达,不能用
74-
一个 JS fixture 宣称 OpenCode runtime 完整兼容。
75-
- 当前 standalone Tool 使用本机 Node.js 验证受限 JS 子集,并在 Desktop 与交互式 TUI(ChatMode)显示运行时和无 OS 沙箱边界;
72+
任意代码 Hook 使用与其审核、信任和单 Hook 启停语义匹配的并行 Hook v1 DTO;Desktop、交互式 TUI 与 Peer Host
73+
共享该契约和类型化异常,不把 Hook 特有字段塞回通用来源对象,也不让宿主自行派生第二套生命周期。
74+
- standalone Tool 闭环已覆盖官方复数目录和源码验证过的单数目录中的受支持单文件 `.js`;首个 Hook 闭环只发现
75+
用户/项目/legacy/显式 OpenCode `plugin`/`plugins` 目录中的直接单文件,并仅对逐内容版本审核和信任的 `.js`
76+
执行 `tool.execute.before/after``.ts` 保持可见但不执行;模块 import、包依赖、配置中的 package plugin、其他 Hook、
77+
完整配置和 TUI target 仍延后。当前范围和完整兼容目标必须分别表达,不能用单文件 fixture 宣称 OpenCode runtime 完整兼容。
78+
- 当前 standalone Tool 与 Reviewed Tool Hook 使用本机 Node.js 验证受限 JS 子集,并在 Desktop 与交互式 TUI(ChatMode)显示运行时和无 OS 沙箱边界;
7679
脚本 worker 与 local stdio MCP 已共享跨平台进程树回收。OpenCode v2 的 Node SEA 前瞻证明 Node 是可行执行路线,但其
77-
Bun 编译路径仍存在;BitFun 后续 TypeScript/Zod、`$` 与包依赖必须按冻结样例选择运行时 adapter,不能提前把 Bun 或 Node 固化进 Host ABI。HarmonyOS PC 原生 CLI/TUI 必须按
80+
Bun 编译路径仍存在;Reviewed Tool Hook 固定要求系统 Node.js `>= 22.12.0`,不提供 Bun fallback。BitFun 后续
81+
TypeScript/Zod、`$` 与包依赖必须按冻结样例选择运行时 adapter,不能把当前 Node 实现固化进 Host ABI。HarmonyOS PC 原生 CLI/TUI 必须按
7882
[平台专题](../platform-portability-design.md)独立取证,不包含 HarmonyOS 手机 Remote App。
7983
- 扩展调用必须有期限、取消、有界队列、大小检查和可观察的崩溃降级;更细的权限、沙箱和组织策略沿用现有控制点并延期
8084
单独设计,不在首条闭环扩大接口。
@@ -85,9 +89,9 @@ OpenCode,和 OpenCode 配置/插件进入 BitFun 是两个独立验收方向
8589
| 优先级 | 可观察结果 | 暂不绑定的工作 |
8690
|---|---|---|
8791
| OC-E0 | 固定版本、官方 custom tool 契约、受支持单文件 fixture、当前静态预览明确显示“未执行” | 全量配置导入 |
88-
| OC-E1 | 上述 fixture 的真实 `execute` 进入现有 Tool Runtime,支持身份/路径字段、合作式与硬取消,并在 Desktop/交互式 TUI(ChatMode)完成非阻塞审批和冲突选择 | `metadata`/`ask`、依赖型样例、package plugin、Hook、TUI 插件 API |
92+
| OC-E1 | 上述 fixture 的真实 `execute` 进入现有 Tool Runtime,支持身份/路径字段、合作式与硬取消,并在 Desktop/交互式 TUI(ChatMode)完成非阻塞审批和冲突选择 | `metadata`/`ask`、依赖型样例、package plugin、TUI 插件 API |
8993
| OC-E2 | 一个真实 package plugin,仅实现其需要的 loader 和最小 client/context | 全部 loader fallback 和 Client API |
90-
| OC-E3 | 按阻塞样例加入 Hook;TUI 先接 command/slash/key,toast 需先有 CLI 类型化状态/通知 owner | 原始 renderer、Server、Remote、连接器 |
94+
| OC-E3(部分交付) | Reviewed local `.js``tool.execute.before/after` 已按原顺序进入 Tool Pipeline,并由 Tool owner 终检;Desktop、`/hooks` 和 Peer Host 共用审核/信任/启停/恢复契约 | package plugin、其他 Hook、TUI 插件 API、原始 renderer、Server、SSH Remote、连接器 |
9195

9296
## 3. 能力矩阵
9397

@@ -131,7 +135,7 @@ OpenCode,和 OpenCode 配置/插件进入 BitFun 是两个独立验收方向
131135
| `.opencode/tools/*.js` | 补基础能力 | 受支持单文件子集已接入 Tool Runtime | 可完整适配 | OC-R2 | 当前 Node worker 支持基础 schema、默认值、字符串结果、取消/超时/撤下;完整 Zod、模块依赖、`metadata`/`ask` 和附件结果继续走类型化进程通信扩展 | [工具加载](opencode-plugin-runtime-adapter-design.md#5-工具与插件加载) |
132136
| `.opencode/tools/*.ts` | 补基础能力 | 已识别,执行不支持 | 可完整适配 | OC-R2 | 当前静态显示不 import;后续由冻结样例选择 Node 转译或 Bun/TypeScript worker,保留真实 schema 与 execute,不在 Rust 猜测 TS 语义 | [工具加载](opencode-plugin-runtime-adapter-design.md#5-工具与插件加载) |
133137
| 插件 `tool` map | 补基础能力 + 补扩展接口 | 未实现 | 可完整适配 | OC-R2 | 运行插件工厂,按同一双表示注册真实工具,并接到 Tool 归属模块 | [工具加载](opencode-plugin-runtime-adapter-design.md#5-工具与插件加载) |
134-
| 项目与用户目录插件 | 补基础能力 | 未实现 | 可完整适配 | OC-R2 | 直接发现本地 JS/TS 模块,不要求 BitFun 专用清单;来源/target 确认后由隔离候选加载 | [服务插件](opencode-plugin-runtime-adapter-design.md#52-服务插件) |
138+
| 项目与用户目录插件 | 补基础能力 | 部分实现:仅 Reviewed Tool Hook 直接单文件 | 可完整适配 | OC-R2 | 当前只发现直接 `.js/.ts``.js` 在逐文件审核后由候选 worker 加载,`.ts` 仅显示不执行;一般 package plugin、import 与依赖仍未实现 | [服务插件](opencode-plugin-runtime-adapter-design.md#52-服务插件) |
135139
| 配置中的软件包插件 | 补基础能力 | 未实现 | 可完整适配 | OC-R2 | 来源/target 确认后用 npm 配置、Arborist、package-lock 和 `ignoreScripts: true` 准备依赖,再由与冻结插件样例匹配的 Node/Bun adapter 加载 | [服务插件](opencode-plugin-runtime-adapter-design.md#52-服务插件) |
136140
| 全局插件加载 | 补基础能力 | 未实现 | 可完整适配 | OC-R2 | 自动发现全局配置和 ConfigPaths 全局目录,并按完整来源图生成 `plugin_origins`;首次可执行启用按来源/target 确认,决定只提示一次且可按项目覆盖 | [服务插件](opencode-plugin-runtime-adapter-design.md#52-服务插件) |
137141
| `package.json`、入口与依赖 | 补基础能力 | 未实现 | 可主要适配 | OC-R2 | 复现 server target、入口回退、`engines.opencode`、npm 配置和锁文件;原生模块失败只影响对应插件 | [来源与执行版本](opencode-plugin-runtime-adapter-design.md#4-来源与执行版本) |
@@ -140,7 +144,7 @@ OpenCode,和 OpenCode 配置/插件进入 BitFun 是两个独立验收方向
140144
| `client` | 补扩展接口 | 未实现 | 可主要适配 | OC-R2 | 提供版本化插件客户端门面,按方法转发到现有 BitFun 归属模块 | [兼容门面](opencode-plugin-runtime-adapter-design.md#7-opencode-兼容门面) |
141145
| `serverUrl` | 补扩展接口 | 未实现 | 可主要适配 | OC-R2 | 在 worker 执行域提供真实回环服务,只实现插件所需的版本化路由 | [兼容门面](opencode-plugin-runtime-adapter-design.md#7-opencode-兼容门面) |
142146
| `$` 与脚本环境 | 补基础能力 | 未实现 | 可完整适配 | OC-R2 | 只有需要 OpenCode/Bun `$` 的冻结样例才启用 Bun-compatible adapter;Node 路径不能伪造等价语义。受限模式依赖真实 OS/容器边界,无法落实时停用 target | [默认策略](opencode-plugin-runtime-adapter-design.md#3-默认策略与可调权限) |
143-
| 加载、停用、更新与崩溃恢复 | 补基础能力 | standalone Tool fail-closed 已实现 | 可主要适配 | OC-R2 | 已有来源限定 target、后台重载、删除撤下与 worker 终止;精确物化旧版本、健康旧进程保留和退避恢复仍待完整 Host | [生命周期](opencode-plugin-runtime-adapter-design.md#9-生命周期与能力暴露) |
147+
| 加载、停用、更新与崩溃恢复 | 补基础能力 | standalone Tool 与 Reviewed Tool Hook 的 fail-closed 子集已实现 | 可主要适配 | OC-R2 | 已有来源限定 target、后台重载、删除/停用撤下、Hook 调用准入排空和 worker 终止;精确物化旧版本、健康旧进程保留和退避恢复仍待完整 Host | [生命周期](opencode-plugin-runtime-adapter-design.md#9-生命周期与能力暴露) |
144148
| 跨插件进程全局共享 | 明确降级 | 未实现 | 明确降级 | OC-R2 | 每 target 使用独立可终止进程;不承诺 `globalThis`、进程环境或模块单例的未文档化共享 | [故障域](opencode-plugin-runtime-adapter-design.md#81-故障域) |
145149

146150
本类整体风险是第三方代码副作用、依赖安装失败、Hook 顺序漂移和 worker 失控。默认权限可以开放,但执行隔离、超时、取消、队列上限、结果大小和故障恢复必须始终启用。
@@ -149,7 +153,7 @@ OpenCode,和 OpenCode 配置/插件进入 BitFun 是两个独立验收方向
149153

150154
| Hook | BitFun 差异 | 当前状态 | 目标可实现性 | 成熟度依赖(非执行顺序) | BitFun 需要完成的工作 |
151155
|---|---|---|---|---|---|
152-
| `dispose` | 直接桥接 | 未实现 | 可完整适配 | OC-R3 | 调用清理并设置期限;超时回收 worker。 |
156+
| `dispose` | 直接桥接 | 部分实现:Reviewed Tool Hook source | 可完整适配 | OC-R3 | 当前来源停用、全部 Hook 停用、Safe Mode、更新和撤下先停止新准入,排空有界在途调用,再请求 `dispose`超时回收 worker;一般 package plugin lifecycle 未实现|
153157
| `event` | 补扩展接口 | 未实现 | 可完整适配 | OC-R3 | 提供版本化事件代理并隔离插件异常。 |
154158
| `config` | 补扩展接口 + 融合现有能力 | 未实现 | 可完整适配 | OC-R3 | 按插件顺序变换,最后由 Config 归属模块校验提交。 |
155159
| `tool` | 补基础能力 + 补扩展接口 | 未实现 | 可完整适配 | OC-R2 | 注册真实工具定义与执行函数。 |
@@ -160,9 +164,9 @@ OpenCode,和 OpenCode 配置/插件进入 BitFun 是两个独立验收方向
160164
| `chat.headers` | 补扩展接口 | 未实现 | 可完整适配 | OC-R3 | 依次变换请求头,敏感值不进入日志。 |
161165
| `permission.ask` | 融合现有能力 | 未实现 | 可主要适配 | OC-R3 | 默认保留 allow/deny/ask 语义;用户或组织策略可收紧。 |
162166
| `command.execute.before` | 补扩展接口 | 未实现 | 可完整适配 | OC-R3 | 在命令执行前依次变换消息 parts。 |
163-
| `tool.execute.before` | 补扩展接口 | 未实现 | 可完整适配 | OC-R3 | 变换最终参数,随后重做 schema 和权限判断|
167+
| `tool.execute.before` | 补扩展接口 | 部分实现:Reviewed local `.js` | 可完整适配 | OC-R3 | 按 OpenCode 来源和导出顺序串行变换参数;冻结最终参数指纹后由 Tool owner 重做结构校验、workspace route 与权限判断,retry 不重复运行 Before|
164168
| `shell.env` | 补扩展接口 | 未实现 | 可完整适配 | OC-R3 | 在实际执行域构造环境变量。 |
165-
| `tool.execute.after` | 补扩展接口 | 未实现 | 可完整适配 | OC-R3 | 依次变换 title、output、metadata,保留原始结果引用|
169+
| `tool.execute.after` | 补扩展接口 | 部分实现:仅模型可见 output | 可完整适配 | OC-R3 | 当前按固定 lease 顺序变换模型可见结果;原始 Tool 结果和审计事实不回写,`title`/`metadata` 尚未开放|
166170
| `tool.definition` | 补扩展接口 + 融合现有能力 | 未实现 | 可完整适配 | OC-R3 | 变换模型可见 JSON Schema;真实执行继续使用 worker 中原始 Zod 校验,保持 OpenCode 双表示语义。 |
167171

168172
Hook 的共同风险是把变换误做成通知、并行调用破坏顺序或插件写入非法状态。所有 Hook 都走类型化调用、顺序执行和归属模块终检;具体调用协议见[服务插件运行时设计](opencode-plugin-runtime-adapter-design.md#6-钩子适配与权威提交)
@@ -341,7 +345,8 @@ worker。授权在准备前、准备后 import 前、load 后注册前和每次
341345
6. 低风险内容的自动应用可撤销;首次启用和 import 前执行包络扩大不会在确认前产生副作用;import 后动态贡献
342346
扩大不会在确认前注册,并明确候选 import 的直接副作用不可撤销。等待确认不阻塞项目。
343347

344-
阶段状态必须按切片独立表达:OC-E1 完成只代表 standalone tool 闭环,不暗示 package plugin、Hook、TUI、Server
345-
或 Remote 已完成。矩阵中未立项项保持“未实现/暂不承诺”,不能阻塞已闭环能力,也不能被后者冒充。
348+
阶段状态必须按切片独立表达:OC-E1 完成只代表 standalone tool 闭环;OC-E3 的当前部分交付只代表 Reviewed local
349+
Tool Before/After Hook,不暗示 package plugin、其他 Hook、TUI 插件、Server 或 Remote 已完成。矩阵中未立项项保持
350+
“未实现/暂不承诺”,不能阻塞已闭环能力,也不能被后者冒充。
346351

347352
阶段交付和退出标准见[粗粒度计划](../../plans/opencode-extension-compatibility-plan.md)

0 commit comments

Comments
 (0)