Skip to content

Commit 8cdff80

Browse files
committed
fix(extensions): clarify runtime recovery and config failures
1 parent da027e2 commit 8cdff80

18 files changed

Lines changed: 234 additions & 65 deletions

File tree

docs/architecture/product-architecture.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,8 @@ flowchart LR
260260
稳定决策如下:
261261

262262
- 不启动完整 OpenCode Runtime,也不依赖用户安装 OpenCode CLI;BitFun 实现自己的监督、适配和 Rust 转发层。
263-
固定版本 Bun 只负责脚本执行,依赖按冻结 OpenCode 版本的 npm/Arborist 语义准备。
263+
当前 standalone Tool 子集通过受监督的 Node.js worker 执行且不安装依赖;未来只有冻结的 package plugin 样例证明
264+
确有需要时,才单独裁决 Bun、依赖准备和版本兼容方案。
264265
- 用户全局和项目来源自动发现;低风险内容默认无感应用并显示可撤销摘要,可执行来源首次启用或能力扩大时等待
265266
非阻塞确认。确认前不得 import module、启动 worker、读取凭据或产生直接脚本副作用。
266267
- 激活后的本地 target 默认按 OpenCode 语义运行,允许当前用户通常拥有的文件、网络、进程和环境能力;用户、
@@ -322,10 +323,10 @@ flowchart LR
322323

323324
产品形态由产品组装决定,不由插件配置、单个 Cargo feature 或生态适配器临时决定。
324325

325-
| 产品形态 | 当前 P0 插件能力 | 入口行为 |
326+
| 产品形态 | 当前扩展能力 | 入口行为 |
326327
|---|---|---|
327-
| Desktop / product-full | 生产入口仍直接依赖 `bitfun-core/product-full`;当前没有 managed-plugin 管理或 OpenCode 静态预览的生产 UI/调用方 | 共享代码可编译不等于 Desktop 已消费插件能力 |
328-
| CLI | 入口仍以 `bitfun-core/product-full` 作为执行兼容 owner;只为 BitFun 原生包提供来源审核、启用预览、精确内容确认和停用 | 本地 Agent 与 Peer Host 路径选择 `DeliveryProfile::Cli`,校验必需 Runtime Service 注册并消费同一 Runtime Parts/SDK;SDK 缺口由单一 Core 兼容门面转发。Peer Host 不再构造第二套调度、持久化或事件 owner。部分注册仍是 compatibility marker,不代表实时探活;插件 binding 明确禁用,不执行 OpenCode 插件代码 |
328+
| Desktop / product-full | 生产入口仍依赖 `bitfun-core/product-full` 作为兼容组装层;“外部 AI 应用”设置已消费 OpenCode Command、standalone Tool 和 Subagent 的统一来源快照、审批、冲突选择与诊断 | 仅本地执行域支持当前三条纵向切片;受管 package plugin 仍只有静态预览,不能据设置页接入宣称完整 OpenCode 插件运行时 |
329+
| CLI | 入口仍以 `bitfun-core/product-full` 作为执行兼容 owner;交互式 TUI 已可执行受支持的 Prompt Command,并通过 `/external-tools``/external-agents` 消费与 Desktop 相同的审批、冲突和刷新状态 | 已批准的 standalone Tool 进入现有 Tool Runtime;已批准的外部 Subagent 只支持 fresh single-run。CLI/TUI 不解析生态文件、不启动第二套 worker/Agent owner;非交互入口和 Remote 未接入时不得借本机 TUI 路径代执行 |
329330
| HarmonyOS PC 原生 CLI/TUI | 未来平台目标,当前未实现 | 目标、问题和风险见平台规约;具体适配另立专题,HAP、手机 Remote App 与远端代执行均不替代 |
330331
| HarmonyOS PC GUI | 完整 HarmonyOS PC 支持的另一目标形态,当前未实现 | 与 CLI/TUI 共享稳定能力和 Runtime 语义,但独立设计宿主、界面与发布验证;Web、Remote 或现有 Tauri Desktop 均不能替代 |
331332
| HarmonyOS 手机 Remote App | `src/apps/mobile/harmonyos` 是 phone-only ArkTS 远程入口,不持有本地 Rust Agent Runtime | 保持当前能力并按移动端专题独立演进;本轮不提前设计移动 Runtime/TUI/GUI,也不能据此宣称 HarmonyOS PC 本地能力 |

docs/plans/opencode-extension-compatibility-plan.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,25 @@ PR3 已为现有 Subagent owner 增加独立兼容端口,由 OpenCode adapter
245245
选择与执行仍由现有会话/Subagent owner 决定;adapter 不能替换 BitFun Agent Kernel。外部 agent 当前只支持 fresh
246246
单次调用,前台结果不返回续接入口,历史 external runtime session 的 follow-up 会被类型化拒绝。
247247

248+
### 5.1 已实现路径的稳定性收敛
249+
250+
本轮不新增扩展类型,只修复会误导用户或掩盖真实故障的两处问题,并校正文档事实:
251+
252+
- `NodeScriptToolRuntime` 在 BitFun 启动时解析 Node.js 可执行文件并由共享管理器持有。本轮保持该生命周期,不增加
253+
运行时热替换;启动时未找到 Node.js 时,Desktop 与 TUI 必须明确提示安装或修复后重启 BitFun。刷新只重新发现
254+
来源,不能描述为会重新读取进程 `PATH`。运行时状态不得把尚未实际启动的可执行文件写成“已验证”。
255+
- Subagent owner 读取 BitFun 模型配置失败时必须 fail closed,并生成与“模型不存在”不同的通用诊断。GUI/TUI
256+
提示用户先确认 BitFun 模型设置能够正常读取和保存,再刷新;日志保留经过清理的技术原因。不得用 `AIConfig::default()`
257+
把配置服务异常转换成候选模型不匹配,也不得把原始错误或绝对配置路径投影到普通快照。
258+
- 外部 Tool 的首次确认继续明确展示代码来源、工作目录、文件/网络/进程/环境访问,以及“当前用户权限、无 OS
259+
沙箱、子进程可能继续运行”的残余风险。该提示是知情确认,不等于沙箱实现。
260+
- Desktop 与交互式 TUI 使用相同诊断 code 和激活阻断事实,各自负责适合宿主的文案;Remote 继续返回明确不支持,
261+
不读取或执行本机同名来源。上述变化不修改 system prompt,也不新增跨界面渲染契约。
262+
263+
明确延期到独立、由证据驱动的后续工作:OS/容器沙箱和进程树硬限制、worker/prompt 全局预算、运行中 Tool
264+
代次租约、通用 watcher 事件限流、偏好记录压缩、完整 metrics/打点平台。它们分别涉及平台执行、安全控制面、
265+
通用服务或数据保留策略,不能以“稳定性修复”为名并入本轮。
266+
248267
## 6. 暂停条件
249268

250269
出现以下情况时停止扩面并先修复架构:

docs/plans/product-architecture-evolution-plan.md

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
[OpenCode 兼容](opencode-extension-compatibility-plan.md);能力 Provider、SDK 和外部宿主双向集成边界见
88
[能力装配与宿主集成](../architecture/extensions/capability-runtime-integration-design.md)。专项文档不能用自己的阶段编号扩大本计划范围。
99

10-
本轮对照的上游基线为 `b22bbdda7`(2026-07-17);本文所在提交记录
10+
本轮对照的上游基线为 `da027e2e8`(2026-07-18);本文所在提交记录
1111
本轮实现事实。后续事实变化必须随代码显式更新,只有代码、入口消费和对应验证同时成立的项目才标记为完成。
1212

1313
## 1. 裁决原则
@@ -30,7 +30,7 @@
3030
| 编译依赖 | `assembly/core -> apps/relay-server` 已移除;通用检查覆盖 normal/build/dev 依赖及 optional/target 变体 | 后续反向依赖和未知 crate 层级直接失败 |
3131
| 公开面 | `bitfun-core` 仍有迁移期 re-export;CLI 只完成部分 Runtime SDK 接入 | 按入口逐项迁移,不做全仓逐 symbol 台账或批量删除 |
3232
| CLI/TUI | `ShortcutsConfig` 已加载但真实按键分发仍硬编码;Slash、Palette、帮助和执行不是同一来源 | 先统一宿主 action 声明和键位解析,不重写 renderer |
33-
| OpenCode | 只有来源确认和静态工具名预览,没有 JS/TS `execute` 或真实工具注册 | 先做一个无外部依赖、遵循官方公开契约的 standalone custom tool 端到端样例 |
33+
| OpenCode | Prompt Command、受支持的单文件 JavaScript Tool 和 Subagent 安全子集已分别通过能力专属 provider 接入;受管 package plugin 仍只有静态预览 | 先收敛三条已交付路径的诊断、运行时提示和配置失败语义,再按真实阻塞样例评估下一能力切片 |
3434
| HarmonyOS PC | 未来平台目标,当前未实现 | 目标、问题、风险和旧设计闭环见平台规约;具体工作后续分别立项 |
3535
| 入口迁移 | CLI 已消费 Runtime Parts;Desktop 主交互消费由现有 owner 构造的窄口径 Runtime SDK 门面,完整 Desktop Runtime Parts 尚未组装;CLI/ACP/Desktop 仍按需保留 `bitfun-core/product-full` 兼容 owner | 保持单一 owner,按真实端口逐项迁移,不批量删除兼容门面或用桩服务提前声明能力 |
3636

@@ -82,16 +82,18 @@ Help/dispatch 元数据;终端异常路径仍能恢复。
8282
[HarmonyOS PC 平台规约](../architecture/platform-portability-design.md);具体工作后续分别立项,现有手机 Remote
8383
App 保持不变。
8484

85-
## 6. 工作流四:OpenCode 从一个真实工具开始
85+
## 6. 工作流四:OpenCode 纵向切片与稳定性收敛
8686

87-
执行顺序由[OpenCode 兼容计划](opencode-extension-compatibility-plan.md)定义:
87+
执行顺序由[OpenCode 兼容计划](opencode-extension-compatibility-plan.md)定义。当前已经完成三个互相隔离的纵向切片
8888

89-
1. 固定稳定版本、官方 custom tool 文档/源码和当前静态预览事实,并增加一个无外部依赖的契约样例;
90-
2. 直接发现官方 `.opencode/tools/` 来源,真实加载该样例的 `execute`,接入现有 Tool Runtime,并验证参数、结果、
91-
ToolContext 身份/路径字段、`abort` 取消、期限、异常和诊断;`metadata`/`ask` 在定义现有 owner 映射前明确不支持;
92-
3. 官方 import 型 tool 或真实 package plugin 首次受阻时,才增加样例需要的依赖解析、loader 和最小 client;
93-
4. Hook 和 TUI contribution 只按真实阻塞样例逐项加入。command/slash/key 复用工作流二的 action registry;toast
94-
必须等待 CLI 拥有类型化状态/通知 owner,不能借用 GUI 本地服务;原始 OpenTUI/Solid renderer 保持不支持。
89+
1. Prompt Command 直接发现标准用户/项目来源,通过统一冲突决策后在交互式 TUI 中提交展开后的 prompt;
90+
2. standalone Tool 只加载受支持的单文件 JavaScript 子集,经来源确认后接入现有 Tool Runtime;
91+
3. Subagent 安全子集经模型、工具和同名冲突确认后接入现有 Subagent owner,仅支持 fresh single-run。
92+
93+
近期先修复已实现路径中的事实偏移和类型化失败:运行时依赖在启动时不可用时给出真实的重启建议;读取 BitFun
94+
模型配置失败时阻止外部 Subagent 激活并显示独立原因,不能伪装成“请求模型不存在”。随后只有官方 import 型 tool、
95+
package plugin、Hook 或 TUI contribution 的真实样例证明当前 owner/契约不足时,才增加对应的最小切片。原始
96+
OpenTUI/Solid renderer、完整 package runtime 和 Remote 执行仍保持不支持。
9597

9698
工具实际加载并取得有效定义和 `execute` 后才能显示为可用。静态名称、可解析模块或进程启动成功都不等于工具
9799
可调用。Remote 和 HarmonyOS PC 原生 CLI/TUI 未通过同一冻结样例前必须明确不支持,不能借 Desktop 代执行;
@@ -138,8 +140,8 @@ native/translated/degraded;未实现能力保持 unsupported/experimental;
138140
| 工作 | 必须等待 | 可以并行 |
139141
|---|---|---|
140142
| Relay 共享 owner / 反向边修复 | 已完成;embedded 宿主归位待后续 | OpenCode fixture |
141-
| CLI action/快捷键 | 当前 CLI 行为和配置 fixture | OpenCode standalone tool、入口 API 迁移 |
142-
| OpenCode standalone tool | OpenCode adapter 内的单一 source resolver、冻结版本/样例 | CLI action |
143+
| CLI action/快捷键 | 当前 CLI 行为和配置 fixture | OpenCode 已实现切片收敛、入口 API 迁移 |
144+
| OpenCode 已实现切片收敛 | Command/Tool/Subagent 三条生产路径和聚焦 fixture | CLI action、入口迁移 |
143145
| OpenCode package/Hook/TUI | 前一切片稳定且有真实阻塞样例;TUI action 另等 action registry | 入口迁移 |
144146
| Desktop 主交互迁移 | 已完成窄口径 SDK 门面接入;完整 Desktop profile 与剩余入口需分别证明服务可用和行为等价 | ACP 与其他非扩展架构工作 |
145147
| 一个能力对外复用 | 现有能力 owner、具名试点/用例/验收 owner、冻结宿主版本和最小权限/取消语义 | OpenCode standalone tool、单入口迁移 |
@@ -154,7 +156,7 @@ native/translated/degraded;未实现能力保持 unsupported/experimental;
154156
| Cargo 方向 | metadata fixture 覆盖各 dependency kind;已知债务只能减少 |
155157
| Relay | standalone/embedded 启动、路由、关闭和错误等价 |
156158
| CLI action | 无配置/旧配置/冲突配置、真实输入 dispatch、Help/Palette/Slash 一致、终端恢复 |
157-
| OpenCode tool | 冻结无外部依赖契约样例的 load/execute/context/cancel/timeout/error 端到端;静态预览不会进入工具集合 |
159+
| OpenCode 扩展 | Command 展开与冲突、Tool 的 load/execute/cancel/timeout、Subagent 的配置/模型/工具/Generation 失败语义;静态预览不会进入可调用集合 |
158160
| HarmonyOS PC | 本计划只检查平台规约没有被实现文档提前展开;各专题启动后独立定义验证。HAP、`hdc shell`、移动 Remote App 与远端代执行不替代 |
159161
| 入口迁移 | 单入口生产消费、行为等价、旧转发删除和 focused test |
160162
| 能力对外复用 | 一个外部消费者的注册/安装、启停、请求/结果、权限、取消、Generation、事件损失、宿主降级、卸载和恢复端到端验证 |

src/apps/cli/AGENTS.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,13 @@ before product-definition, TUI layout, branding, packaging, runtime, or plugin a
4646
external-source approval, conflict, Tool Runtime, and script-worker owners.
4747
CLI/TUI consumes typed snapshots and actions; it must not import modules,
4848
spawn tool workers, bypass a pending decision, or implement a second approval
49-
store. TypeScript, dependency loading, package plugins, hooks, and subagents
50-
remain non-executable until their own reviewed capability slice lands.
49+
store. TypeScript, dependency loading, package plugins, and hooks remain
50+
non-executable until their own reviewed capability slice lands.
51+
- OpenCode external subagents may execute only through the shared source
52+
decision and existing Subagent owner. TUI consumes typed summaries and
53+
generation-checked actions; it must not parse agent files, inject source
54+
prompts directly, invent model fallbacks, or offer follow-up for the current
55+
fresh single-run compatibility slice.
5156
- The managed-package OpenCode adapter remains a static-preview path. Other
5257
OpenCode plugin capabilities, Codex, and Claude remain import/reference sources
5358
unless their own reviewed adapter design explicitly changes. Never copy

src/apps/cli/src/modes/chat/external_review.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ fn external_tool_next_step(activation: &ExternalToolActivationState) -> &'static
283283
"Change the code to a single JavaScript file supported by BitFun, then refresh."
284284
}
285285
ExternalToolActivationState::RuntimeUnavailable { .. } => {
286-
"Restore the required JavaScript environment, then refresh."
286+
"Please install or repair Node.js, then restart BitFun."
287287
}
288288
ExternalToolActivationState::LoadFailed { .. } => {
289289
"Refresh to retry. If it still fails, fix the source code or keep these tools disabled."
@@ -895,7 +895,12 @@ fn external_agent_diagnostic_lines(
895895
blocks_activation: bool,
896896
indent: &str,
897897
) -> Vec<String> {
898-
let (reason, next_step) = if code.contains("model_unavailable") {
898+
let (reason, next_step) = if code.contains("configuration_unavailable") {
899+
(
900+
"BitFun could not read its model settings.",
901+
"Open BitFun model settings and confirm they load. If not, restart BitFun. If the problem continues, check that BitFun can read and save its settings; then refresh.",
902+
)
903+
} else if code.contains("model_unavailable") {
899904
(
900905
"The requested model is not available in BitFun.",
901906
"Choose an available model in the source application, or set a fixed Sub-Agent model in BitFun, then refresh.",

src/apps/cli/src/modes/chat/tests.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,18 @@ mod tests {
228228
assert!(!summary.contains("PR2"));
229229
}
230230

231+
#[test]
232+
fn external_tool_runtime_recovery_explains_that_bitfun_must_restart() {
233+
let mut snapshot = external_tool_review_snapshot();
234+
snapshot.tools[0].activation = ExternalToolActivationState::RuntimeUnavailable {
235+
reason: "Node.js was not found when BitFun started".to_string(),
236+
};
237+
238+
let summary = external_tool_review_text(Some(&snapshot));
239+
assert!(summary.contains("install or repair Node.js, then restart BitFun"));
240+
assert!(!summary.contains("environment, then refresh"));
241+
}
242+
231243
#[test]
232244
fn external_tool_review_commands_resolve_indices_to_stable_keys() {
233245
let snapshot = external_tool_review_snapshot();
@@ -877,5 +889,15 @@ mod tests {
877889
external_agent_diagnostic_lines("opencode_agent_definition_type_invalid", true, "")
878890
.join(" ");
879891
assert!(invalid.contains("invalid or missing required value"));
892+
893+
let config = external_agent_diagnostic_lines(
894+
"external_subagent.configuration_unavailable",
895+
true,
896+
"",
897+
)
898+
.join(" ");
899+
assert!(config.contains("could not read its model settings"));
900+
assert!(config.contains("can read and save its settings"));
901+
assert!(!config.contains("requested model is not available"));
880902
}
881903
}

src/crates/adapters/AGENTS-CN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
| Crate | 职责 | 本地文档 |
1010
|---|---|---|
1111
| `ai-adapters` | AI provider 请求/响应 adapter 与 stream protocol glue | [AGENTS.md](ai-adapters/AGENTS.md) |
12-
| `opencode-adapter` | 当前 OpenCode 静态来源探测与诊断;目标为来源协调器和生态适配器 | [AGENTS.md](opencode-adapter/AGENTS.md) |
12+
| `opencode-adapter` | OpenCode Command、standalone Tool 和 Subagent 实时 provider 的生态语义;受管包静态预览 | [AGENTS.md](opencode-adapter/AGENTS.md) |
1313
| `transport` | Event transport emitter 与宿主 transport adapter | [AGENTS.md](transport/AGENTS.md) |
1414
| `webdriver` | Embedded WebDriver protocol 与浏览器自动化 adapter | [AGENTS.md](webdriver/AGENTS.md) |
1515

src/crates/adapters/AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ services.
1212
| Crate | Responsibility | Local doc |
1313
|---|---|---|
1414
| `ai-adapters` | AI provider request/response adapters and stream protocol glue | [AGENTS.md](ai-adapters/AGENTS.md) |
15-
| `opencode-adapter` | Current static OpenCode source inspection/diagnostics; target source coordinator and ecosystem adapter | [AGENTS.md](opencode-adapter/AGENTS.md) |
15+
| `opencode-adapter` | OpenCode source semantics for the live Command, standalone Tool, and Subagent providers; managed-package static preview | [AGENTS.md](opencode-adapter/AGENTS.md) |
1616
| `transport` | Event transport emitters and host transport adapters | [AGENTS.md](transport/AGENTS.md) |
1717
| `webdriver` | Embedded WebDriver protocol and browser automation adapter | [AGENTS.md](webdriver/AGENTS.md) |
1818

0 commit comments

Comments
 (0)