Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions docs/architecture/product-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,8 @@ flowchart LR
稳定决策如下:

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

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

| 产品形态 | 当前 P0 插件能力 | 入口行为 |
| 产品形态 | 当前扩展能力 | 入口行为 |
|---|---|---|
| Desktop / product-full | 生产入口仍直接依赖 `bitfun-core/product-full`;当前没有 managed-plugin 管理或 OpenCode 静态预览的生产 UI/调用方 | 共享代码可编译不等于 Desktop 已消费插件能力 |
| 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 插件代码 |
| Desktop / product-full | 生产入口仍依赖 `bitfun-core/product-full` 作为兼容组装层;“外部 AI 应用”设置已消费 OpenCode Command、standalone Tool 和 Subagent 的统一来源快照、审批、冲突选择与诊断 | 仅本地执行域支持当前三条纵向切片;受管 package plugin 仍只有静态预览,不能据设置页接入宣称完整 OpenCode 插件运行时 |
| 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 路径代执行 |
| HarmonyOS PC 原生 CLI/TUI | 未来平台目标,当前未实现 | 目标、问题和风险见平台规约;具体适配另立专题,HAP、手机 Remote App 与远端代执行均不替代 |
| HarmonyOS PC GUI | 完整 HarmonyOS PC 支持的另一目标形态,当前未实现 | 与 CLI/TUI 共享稳定能力和 Runtime 语义,但独立设计宿主、界面与发布验证;Web、Remote 或现有 Tauri Desktop 均不能替代 |
| HarmonyOS 手机 Remote App | `src/apps/mobile/harmonyos` 是 phone-only ArkTS 远程入口,不持有本地 Rust Agent Runtime | 保持当前能力并按移动端专题独立演进;本轮不提前设计移动 Runtime/TUI/GUI,也不能据此宣称 HarmonyOS PC 本地能力 |
Expand Down
20 changes: 20 additions & 0 deletions docs/plans/opencode-extension-compatibility-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,26 @@ PR3 已为现有 Subagent owner 增加独立兼容端口,由 OpenCode adapter
选择与执行仍由现有会话/Subagent owner 决定;adapter 不能替换 BitFun Agent Kernel。外部 agent 当前只支持 fresh
单次调用,前台结果不返回续接入口,历史 external runtime session 的 follow-up 会被类型化拒绝。

### 5.1 已实现路径的稳定性收敛

本轮不新增扩展类型,只修复会误导用户或掩盖真实故障的两处问题,并校正文档事实:

- `NodeScriptToolRuntime` 在共享外部 Tool 运行时首次初始化时解析 Node.js 可执行文件,并在当前进程内持有结果。
本轮保持该生命周期,不增加运行时热替换;首次初始化时未找到 Node.js 后,Desktop 与 TUI 必须明确提示安装或修复后
重启 BitFun。刷新只重新发现来源,不能描述为会重新读取进程 `PATH`。运行时状态不得把尚未实际启动的可执行文件写成“已验证”。
- Subagent owner 读取 BitFun 模型配置失败时必须 fail closed,并生成与“模型不存在”不同的通用诊断。GUI/TUI
提示用户先确认 BitFun 模型设置能够正常读取和保存,再刷新;日志只保留经过脱敏的失败阶段和错误类别。不得用 `AIConfig::default()`
把配置服务异常转换成候选模型不匹配,也不得把原始错误或绝对配置路径投影到普通快照。临时故障期间不得改写已持久化的
审批或同名冲突选择,配置恢复且扩展行为未变化时继续复用原决定。
- 外部 Tool 的首次确认继续明确展示代码来源、工作目录、文件/网络/进程/环境访问,以及“当前用户权限、无 OS
沙箱、子进程可能继续运行”的残余风险。该提示是知情确认,不等于沙箱实现。
- Desktop 与交互式 TUI 使用相同诊断 code 和激活阻断事实,各自负责适合宿主的文案;Remote 继续返回明确不支持,
不读取或执行本机同名来源。上述变化不修改 system prompt,也不新增跨界面渲染契约。

明确延期到独立、由证据驱动的后续工作:OS/容器沙箱和进程树硬限制、worker/prompt 全局预算、运行中 Tool
代次租约、通用 watcher 事件限流、偏好记录压缩、完整 metrics/打点平台。它们分别涉及平台执行、安全控制面、
通用服务或数据保留策略,不能以“稳定性修复”为名并入本轮。

## 6. 暂停条件

出现以下情况时停止扩面并先修复架构:
Expand Down
28 changes: 15 additions & 13 deletions docs/plans/product-architecture-evolution-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
[OpenCode 兼容](opencode-extension-compatibility-plan.md);能力 Provider、SDK 和外部宿主双向集成边界见
[能力装配与宿主集成](../architecture/extensions/capability-runtime-integration-design.md)。专项文档不能用自己的阶段编号扩大本计划范围。

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

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

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

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

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

1. 固定稳定版本、官方 custom tool 文档/源码和当前静态预览事实,并增加一个无外部依赖的契约样例;
2. 直接发现官方 `.opencode/tools/` 来源,真实加载该样例的 `execute`,接入现有 Tool Runtime,并验证参数、结果、
ToolContext 身份/路径字段、`abort` 取消、期限、异常和诊断;`metadata`/`ask` 在定义现有 owner 映射前明确不支持;
3. 官方 import 型 tool 或真实 package plugin 首次受阻时,才增加样例需要的依赖解析、loader 和最小 client;
4. Hook 和 TUI contribution 只按真实阻塞样例逐项加入。command/slash/key 复用工作流二的 action registry;toast
必须等待 CLI 拥有类型化状态/通知 owner,不能借用 GUI 本地服务;原始 OpenTUI/Solid renderer 保持不支持。
1. Prompt Command 直接发现标准用户/项目来源,通过统一冲突决策后在交互式 TUI 中提交展开后的 prompt;
2. standalone Tool 只加载受支持的单文件 JavaScript 子集,经来源确认后接入现有 Tool Runtime;
3. Subagent 安全子集经模型、工具和同名冲突确认后接入现有 Subagent owner,仅支持 fresh single-run。

近期先修复已实现路径中的事实偏移和类型化失败:运行时依赖在当前进程首次检查时不可用时给出真实的重启建议;读取 BitFun
模型配置失败时阻止外部 Subagent 激活并显示独立原因,不能伪装成“请求模型不存在”。随后只有官方 import 型 tool、
package plugin、Hook 或 TUI contribution 的真实样例证明当前 owner/契约不足时,才增加对应的最小切片。原始
OpenTUI/Solid renderer、完整 package runtime 和 Remote 执行仍保持不支持。

工具实际加载并取得有效定义和 `execute` 后才能显示为可用。静态名称、可解析模块或进程启动成功都不等于工具
可调用。Remote 和 HarmonyOS PC 原生 CLI/TUI 未通过同一冻结样例前必须明确不支持,不能借 Desktop 代执行;
Expand Down Expand Up @@ -138,8 +140,8 @@ native/translated/degraded;未实现能力保持 unsupported/experimental;
| 工作 | 必须等待 | 可以并行 |
|---|---|---|
| Relay 共享 owner / 反向边修复 | 已完成;embedded 宿主归位待后续 | OpenCode fixture |
| CLI action/快捷键 | 当前 CLI 行为和配置 fixture | OpenCode standalone tool、入口 API 迁移 |
| OpenCode standalone tool | OpenCode adapter 内的单一 source resolver、冻结版本/样例 | CLI action |
| CLI action/快捷键 | 当前 CLI 行为和配置 fixture | OpenCode 已实现切片收敛、入口 API 迁移 |
| OpenCode 已实现切片收敛 | Command/Tool/Subagent 三条生产路径和聚焦 fixture | CLI action、入口迁移 |
| OpenCode package/Hook/TUI | 前一切片稳定且有真实阻塞样例;TUI action 另等 action registry | 入口迁移 |
| Desktop 主交互迁移 | 已完成窄口径 SDK 门面接入;完整 Desktop profile 与剩余入口需分别证明服务可用和行为等价 | ACP 与其他非扩展架构工作 |
| 一个能力对外复用 | 现有能力 owner、具名试点/用例/验收 owner、冻结宿主版本和最小权限/取消语义 | OpenCode standalone tool、单入口迁移 |
Expand All @@ -154,7 +156,7 @@ native/translated/degraded;未实现能力保持 unsupported/experimental;
| Cargo 方向 | metadata fixture 覆盖各 dependency kind;已知债务只能减少 |
| Relay | standalone/embedded 启动、路由、关闭和错误等价 |
| CLI action | 无配置/旧配置/冲突配置、真实输入 dispatch、Help/Palette/Slash 一致、终端恢复 |
| OpenCode tool | 冻结无外部依赖契约样例的 load/execute/context/cancel/timeout/error 端到端;静态预览不会进入工具集合 |
| OpenCode 扩展 | Command 展开与冲突、Tool 的 load/execute/cancel/timeout、Subagent 的配置/模型/工具/Generation 失败语义;静态预览不会进入可调用集合 |
| HarmonyOS PC | 本计划只检查平台规约没有被实现文档提前展开;各专题启动后独立定义验证。HAP、`hdc shell`、移动 Remote App 与远端代执行不替代 |
| 入口迁移 | 单入口生产消费、行为等价、旧转发删除和 focused test |
| 能力对外复用 | 一个外部消费者的注册/安装、启停、请求/结果、权限、取消、Generation、事件损失、宿主降级、卸载和恢复端到端验证 |
Expand Down
9 changes: 7 additions & 2 deletions src/apps/cli/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,13 @@ before product-definition, TUI layout, branding, packaging, runtime, or plugin a
external-source approval, conflict, Tool Runtime, and script-worker owners.
CLI/TUI consumes typed snapshots and actions; it must not import modules,
spawn tool workers, bypass a pending decision, or implement a second approval
store. TypeScript, dependency loading, package plugins, hooks, and subagents
remain non-executable until their own reviewed capability slice lands.
store. TypeScript, dependency loading, package plugins, and hooks remain
non-executable until their own reviewed capability slice lands.
- OpenCode external subagents may execute only through the shared source
decision and existing Subagent owner. TUI consumes typed summaries and
generation-checked actions; it must not parse agent files, inject source
prompts directly, invent model fallbacks, or offer follow-up for the current
fresh single-run compatibility slice.
- The managed-package OpenCode adapter remains a static-preview path. Other
OpenCode plugin capabilities, Codex, and Claude remain import/reference sources
unless their own reviewed adapter design explicitly changes. Never copy
Expand Down
9 changes: 7 additions & 2 deletions src/apps/cli/src/modes/chat/external_review.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ fn external_tool_next_step(activation: &ExternalToolActivationState) -> &'static
"Change the code to a single JavaScript file supported by BitFun, then refresh."
}
ExternalToolActivationState::RuntimeUnavailable { .. } => {
"Restore the required JavaScript environment, then refresh."
"Please install or repair Node.js, then restart BitFun."
}
ExternalToolActivationState::LoadFailed { .. } => {
"Refresh to retry. If it still fails, fix the source code or keep these tools disabled."
Expand Down Expand Up @@ -895,7 +895,12 @@ fn external_agent_diagnostic_lines(
blocks_activation: bool,
indent: &str,
) -> Vec<String> {
let (reason, next_step) = if code.contains("model_unavailable") {
let (reason, next_step) = if code.contains("configuration_unavailable") {
(
"BitFun could not read its model settings.",
"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.",
)
} else if code.contains("model_unavailable") {
(
"The requested model is not available in BitFun.",
"Choose an available model in the source application, or set a fixed Sub-Agent model in BitFun, then refresh.",
Expand Down
23 changes: 23 additions & 0 deletions src/apps/cli/src/modes/chat/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,19 @@ mod tests {
assert!(!summary.contains("PR2"));
}

#[test]
fn external_tool_runtime_recovery_explains_that_bitfun_must_restart() {
let mut snapshot = external_tool_review_snapshot();
snapshot.tools[0].activation = ExternalToolActivationState::RuntimeUnavailable {
reason: "BitFun could not find Node.js for external tools".to_string(),
};

let summary = external_tool_review_text(Some(&snapshot));
assert!(summary.contains("install or repair Node.js, then restart BitFun"));
assert!(!summary.contains("environment, then refresh"));
assert!(!summary.contains("when BitFun started"));
}

#[test]
fn external_tool_review_commands_resolve_indices_to_stable_keys() {
let snapshot = external_tool_review_snapshot();
Expand Down Expand Up @@ -877,5 +890,15 @@ mod tests {
external_agent_diagnostic_lines("opencode_agent_definition_type_invalid", true, "")
.join(" ");
assert!(invalid.contains("invalid or missing required value"));

let config = external_agent_diagnostic_lines(
"external_subagent.configuration_unavailable",
true,
"",
)
.join(" ");
assert!(config.contains("could not read its model settings"));
assert!(config.contains("can read and save its settings"));
assert!(!config.contains("requested model is not available"));
}
}
2 changes: 1 addition & 1 deletion src/crates/adapters/AGENTS-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
| Crate | 职责 | 本地文档 |
|---|---|---|
| `ai-adapters` | AI provider 请求/响应 adapter 与 stream protocol glue | [AGENTS.md](ai-adapters/AGENTS.md) |
| `opencode-adapter` | 当前 OpenCode 静态来源探测与诊断;目标为来源协调器和生态适配器 | [AGENTS.md](opencode-adapter/AGENTS.md) |
| `opencode-adapter` | OpenCode Command、standalone Tool 和 Subagent 实时 provider 的生态语义;受管包静态预览 | [AGENTS.md](opencode-adapter/AGENTS.md) |
| `transport` | Event transport emitter 与宿主 transport adapter | [AGENTS.md](transport/AGENTS.md) |
| `webdriver` | Embedded WebDriver protocol 与浏览器自动化 adapter | [AGENTS.md](webdriver/AGENTS.md) |

Expand Down
2 changes: 1 addition & 1 deletion src/crates/adapters/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ services.
| Crate | Responsibility | Local doc |
|---|---|---|
| `ai-adapters` | AI provider request/response adapters and stream protocol glue | [AGENTS.md](ai-adapters/AGENTS.md) |
| `opencode-adapter` | Current static OpenCode source inspection/diagnostics; target source coordinator and ecosystem adapter | [AGENTS.md](opencode-adapter/AGENTS.md) |
| `opencode-adapter` | OpenCode source semantics for the live Command, standalone Tool, and Subagent providers; managed-package static preview | [AGENTS.md](opencode-adapter/AGENTS.md) |
| `transport` | Event transport emitters and host transport adapters | [AGENTS.md](transport/AGENTS.md) |
| `webdriver` | Embedded WebDriver protocol and browser automation adapter | [AGENTS.md](webdriver/AGENTS.md) |

Expand Down
Loading
Loading