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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions docs/architecture/extensions/external-ai-work-sources-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,19 +274,19 @@ OpenCode Subagent 属于 L2:adapter 只读取声明,不执行外部代码;

| 能力 | OpenCode | Claude Code | Codex | 当前边界 |
|---|---|---|---|---|
| Prompt Command | JSON/JSONC、Markdown 的 prompt-only 安全子集 | legacy `commands/**/*.md` 的 prompt-only 安全子集;Skills 仍由 Skill 归属模块处理 | 没有稳定、独立于 Skills 的声明式 Command 来源,因此不伪造 provider | `$ARGUMENTS`/位置参数可展开;shell、文件动态引用、指定 Agent/模型等未接通语义整体受限,不做部分执行。 |
| Prompt Command | JSON/JSONC、Markdown 的 prompt-only 与静态本地文本文件子集 | legacy `commands/**/*.md` 的同一静态本地文本文件子集;Skills 仍由 Skill 归属模块处理 | 没有稳定、独立于 Skills 的声明式 Command 来源,因此不伪造 provider | `$ARGUMENTS`/位置参数及模板内 workspace 相对 UTF-8 `@file` 可展开;shell、动态/绝对/越界文件、指定 Agent/模型等整体受限。 |
| Subagent | 用户/项目声明的安全子集 | 用户/项目 `agents/**/*.md` 的安全子集 | 用户/项目 `[agents]`、角色文件与安全配置层子集 | prompt、描述、精确模型和可表达工具请求进入既有归属模块;权限、私有 MCP/Hook、推理/并发等没有对应实现的字段会阻止激活。 |
| MCP | 用户/显式目录/项目配置的安全子集 | user/project/local 原生层的安全子集 | 用户与项目 `config.toml` 原生层的安全子集 | 支持可表达的 stdio 与 HTTPS Streamable HTTP;发现不启动 Server,首次激活继续经 BitFun MCP 审批。OAuth、remote executor、per-tool policy 等不完整语义明确降级。 |
| Standalone Tool | 已有单文件 JavaScript 子集 | 无稳定的 runtime-free standalone Tool 来源 | 无稳定的 runtime-free standalone Tool 来源 | TypeScript、package/plugin Tool 与动态工具注册依赖独立 Plugin Host,不在声明式 adapter 中猜测。 |
| Skill | 由现有 Skill 加载模块发现 `.opencode` 等标准根 | 由现有 Skill 加载模块发现 `.claude` 标准根;目录名是调用身份,描述可回退正文首段,`when_to_use` 合入索引,声明参数可做纯文本命名展开 | 由现有 Skill 加载模块发现 `.codex`、`.agents` 标准根;`.codex` 缺少 `name` 时回退目录名 | Skill 的加载、覆盖、模式开关与执行仍由同一个 Skill 模块负责,不复制进外部来源管理模块;未接通的运行时字段整体拒绝。 |
| Skill | 由现有 Skill 加载模块发现 `.opencode` 标准根及 OpenCode 本地配置根 | 由现有 Skill 加载模块发现 `.claude` 标准根;目录名是调用身份,描述可回退正文首段,`when_to_use` 合入索引,声明参数可做纯文本命名展开 | 由现有 Skill 加载模块发现 `.codex`、`.agents` 标准根;`.codex` 缺少 `name` 时回退目录名 | OpenCode V1 `skills.paths`/当前本地字符串数组只经 `bitfun-core/external_sources` 组合边界投影根目录,递归、加载、覆盖、模式开关与执行仍由同一个 Skill 模块负责;URL 不加载。 |
| Hook | 静态目录 | 脱敏目录;同步 command 子集可审阅导入 | 脱敏目录;同步 command 子集可审阅导入 | 仅复制到私有原生快照并由 `AgentHookEngine` 执行;OpenCode、非 command、异步、未知或依赖未观察激活语义的 handler 不导入。 |

生态原生语义由各 adapter 以契约测试固定,不抽象成全局优先级:

- Claude legacy Command 扫描用户与项目 `.claude/commands/**/*.md`,保留 `frontend/component` 到
`/frontend:component` 的原生命名空间;同层重名无效,遵循 Claude Code 当前“personal 覆盖 project”的 Skill/legacy Command
规则,同名 Skill 仅通过有界名称索引遮蔽 Command。
只展开 `$ARGUMENTS`、`$ARGUMENTS[N]` 和 `$N` 纯文本参数;shell、文件引用和改变 Agent、模型、工具或 Hook 的字段整体阻止激活。
展开 `$ARGUMENTS`、`$ARGUMENTS[N]` 和 `$N` 纯文本参数,并允许原模板中的静态 workspace 相对 `@file`;shell、动态/绝对/越界文件引用和改变 Agent、模型、工具或 Hook 的字段整体阻止激活。
- Skill Registry 继续拥有所有根的发现、覆盖、显式加载与刷新,只用既有稳定 source slot 在内部选择格式方言,不向用户
暴露主选择器,也不按路径字符串临时猜测。`.claude` Skill 的调用名固定为目录名;`description` 缺失时取正文首个
非空段落,并与可选 `when_to_use` 合并为最多 1536 个 Unicode 字符的模型索引说明。`arguments` 可为以空白分隔的名称
Expand Down Expand Up @@ -480,8 +480,8 @@ Command;明确缺失且未被标记失败的 Command 是稳定删除。产品
2. 发现 OpenCode 当前支持的用户全局和项目 Command 来源,建立来源限定身份、生态内覆盖关系和聚合清单;
OpenCode 自身定义的项目/用户优先级仍由 adapter 解释,跨 provider 或与 BitFun 本地 Command 的同名冲突进入待选择状态。
3. 支持 `$ARGUMENTS` 与位置参数的 prompt-only 命令在用户显式选择或输入时展开并提交;发现本身不向会话发送内容。
4. 含 `!shell`、`@file`、`{env:...}`、`{file:...}`、`agent`、`model`、`variant` 或 `subtask` 等未接通语义的命令标记为“部分受限”,不做
静默忽略后的部分执行
4. 模板内静态 workspace 相对 `@file` 经有界 UTF-8 读取后原子装配;含 `!shell`、动态/绝对/越界文件引用、`{env:...}`、
`{file:...}`、`agent`、`model`、`variant` 或 `subtask` 等未接通语义的命令标记为“部分受限”,不做静默忽略后的部分执行
5. Desktop 提供统一来源状态、刷新、按执行域抑制/恢复和冲突候选选择;首次 provider 扫描完成前显示中性检查状态,
不把暂时空目录误报为最终空结果;已经选择且内容摘要未变化的冲突退出待处理区。交互式 TUI(ChatMode)使用同一目录列出和执行
Command;跨 provider 候选由现有命令菜单按来源、使用范围和兼容状态展示,并通过内部稳定 candidate ID 选择,同次选择也解析本地同名冲突。发现或确认不阻塞
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,9 @@ OpenCode adapter 在来源发现、解析和审批前不 import module、不读
|---|---|---|---|---|
| Rules / Instructions | 项目/全局 `AGENTS.md`、Claude fallback、`instructions` glob、本地文件、远程 URL | Workspace Instructions 归属模块保存有序来源引用 | 当前实现项目根与 `.opencode` 配置中的本地精确文件/glob;全局与远程 URL 仍是目标 | 无效 JSONC 或 glob 只排除对应配置项;文件 I/O 失败时当前构建不缓存并在下一条消息重试。 |
| Agents / Modes | JSON、Markdown、description、mode、prompt、model、variant、temperature、top_p、steps、deprecated `maxSteps`、deprecated `tools`、permission、disable、options、hidden、color | Agent 归属模块创建兼容定义和使用范围视图 | 当前支持 Subagent 安全子集;首次按行为、来源、模型和工具范围确认,fresh single-run 调用 | primary/mode、permission、variant/options、采样、steps 与续接保持诊断或阻断,不影响其他 Agent。 |
| Skills | `.opencode/.claude/.agents` 项目与用户根、`SKILL.md`、`skills.paths/urls` | Skill 归属模块复用按需加载并补齐规则顺序 | 说明和索引按需加载;URL、脚本或外部依赖按 L2 确认 | URL 或可执行资源失败只降级对应 Skill。 |
| Skills | `.opencode/.claude/.agents` 项目与用户根、`SKILL.md`、`skills.paths/urls` | OpenCode adapter 只由 `bitfun-core/external_sources` 组合并投影有序本地配置根;Skill 归属模块负责有界递归、解析、覆盖与按需加载 | 标准根及 V1 `skills.paths`/当前本地字符串数组可用;项目配置限项目根,用户配置限项目根或用户目录;配置根最多 64 个、每根 512 个 Skill、单文件 256 KiB、可选策略 64 KiB,实际加载再次执行有界非链接读取;配置根在同 scope 覆盖标准 OpenCode 根,但不重排更早的 BitFun/Claude/Codex/Cursor 来源 | URL、下载/缓存、脚本与外部依赖不加载;无效根不影响标准 Skill。 |
| References | `references` / 旧 `reference`,本地 path 或 Git repository/branch/description/hidden | **基础能力缺失**:先补 Workspace Reference 的异步准备与 `@alias` 消费接口 | 本地引用保留相对来源;Git 拉取按 L2 确认并保留缓存/隐藏语义 | 拉取失败不阻止项目,外部目录仍遵守工具权限。 |
| Commands | JSON/JSONC、Markdown、`$ARGUMENTS`、位置参数、`@file`、`!shell`、agent/model/variant/subtask | Prompt Command 专属契约;OpenCode adapter 保留发现、覆盖、解析和参数展开语义,交互式 TUI(ChatMode)只消费中立定义与展开结果 | 当前支持 prompt-only 模板,用户显式选择或输入即确认本次发送;未接通的文件、shell、agent/model/variant/subtask 标为部分受限且不做部分执行 | 已知命令文件无效只回退该命令;稳定删除撤下新调用;目录枚举未知时回退对应目录来源,不能把未知当空目录。 |
| Commands | JSON/JSONC、Markdown、`$ARGUMENTS`、位置参数、`@file`、`!shell`、agent/model/variant/subtask | Prompt Command 专属契约;adapter 提取静态文件引用,Product Assembly 经共享本地文本服务完成有界装配 | prompt-only 与静态 workspace 相对 UTF-8 `@file` 可发送;动态/绝对/越界文件、shell、agent/model/variant/subtask 整体受限 | 任一文件失败则本次调用原子失败;最多 8 文件、单文件 64 KiB、文件总量 128 KiB、最终命令 1 MiB。 |
| MCP | local 的 command/environment/cwd/timeout,remote 的 URL/headers/oauth/timeout,Agent 选择 | MCP 归属模块创建兼容配置视图 | 当前支持 local stdio 和 HTTPS remote 的静态发现、首次/行为变化审批、冲突选择与 workspace 隔离的运行期接纳;C0a 快照导入只复制无 env/cwd 的 local command/args 或无 header/query/fragment 的 HTTPS remote,并保持 disabled | `{env:NAME}` 当前只允许用于运行期兼容来源的 environment/Header 值,不进入 C0a 快照;SSE、OpenCode OAuth client 配置、完整 timeout/Agent 范围与 Remote 执行域保持明确不支持;凭据或网络失败只影响单个 Server。 |
| LSP | command、extensions、env、initialization | LSP 归属模块注册兼容实例 | 首次确认外部进程和使用范围后按文件类型启动 | 自定义 Server 缺少 extensions 或启动失败时只禁用该项。 |
| Formatters | command、environment、extensions、`$FILE` | **基础能力缺失**:先补文件写入后的 Formatter 执行消费点,再做格式转换 | 首次确认命令后执行匹配 Formatter | 超时后标记未格式化,文件写入结果保留。 |
Expand Down Expand Up @@ -258,12 +258,28 @@ OpenCode 会话内核、permission DSL 或 package plugin。Desktop/TUI 摘要
正文,静态 system prompt 也不因该适配而改写。来源 `description` 只进入审批和管理界面;已批准 Agent
进入现有 `<available_agents>` 动态视图时使用 BitFun 生成的稳定摘要,避免只改目录文案就绕过行为重批并改变模型上下文。

OpenCode 本地配置 Skill 根不是新的外部资产生命周期。Adapter 按已实现的本地配置来源顺序累加每份有效文档中的
V1 `skills.paths` 和当前 `skills: string[]`;字段类型错误只拒绝该文档的 Skill 根贡献,不影响同文档 Command 等其他能力。
`skills.urls` 与 HTTP(S) 项不获取;相对路径只从当前本地 workspace 解析,项目配置根必须留在项目内,用户配置根必须
留在项目或当前用户目录内,远程 workspace 的相对根不回退到本机解释。

`bitfun-core/external_sources` 是唯一构造 adapter 并投影本地根事实的组合边界,Skill Registry 不 import 生态 adapter,继续
拥有递归发现、解析、覆盖、模式开关与实际加载。配置项最多保留 64 个;每根扫描深度 16、最多访问 4096 个条目和
2048 个目录、接纳 512 个 `SKILL.md`,单个 Skill 限制 256 KiB,可选 `agents/openai.yaml` 限制 64 KiB。扫描和实际加载都
拒绝符号链接/reparse point;加载时重新校验规范化根及其稳定 source slot,防止目录整体替换改变已发现来源身份。同 scope
内配置根位于标准 OpenCode 根之前,较后的不同配置根覆盖同名 Skill,但不重排更早的 BitFun/Claude/Codex/Cursor 来源。

### 5.3 Commands

当前 Prompt Command 子集只展开 `$ARGUMENTS` 与 `$1`、`$2` 等位置参数。OpenCode adapter 负责参数拆分、替换顺序和未使用参数追加,
Prompt Command 归属模块只接收最终可发送文本;产品 core 不按生态 ID 解释模板。包含 `@file`、`!shell`、
`{env:...}`、`{file:...}`、agent/model/variant/subtask 的命令仍进入目录,但整体标为“部分受限”,不能解析凭据或
删除不支持的部分后继续发送。
当前 Prompt Command 子集展开 `$ARGUMENTS` 与 `$1`、`$2` 等位置参数,并支持模板中可静态确认的 workspace 相对 UTF-8
`@file`。OpenCode adapter 只从原模板提取引用,不扫描用户参数;Product Assembly 在 stale/冲突校验后通过共享本地文本服务
原子读取并追加内容。动态占位、绝对/`~`/URL/越界路径仍进入目录但整体受限。包含 `!shell`、`{env:...}`、`{file:...}`、
agent/model/variant/subtask 的命令同样保持受限,不能删除不支持的部分后继续发送。

每次调用最多接纳 8 个不同文件,单文件 64 KiB、文件总量 128 KiB、最终命令 1 MiB。共享服务对每级路径执行
workspace 规范化包含校验并拒绝符号链接/reparse point;任一引用缺失、越界、超限或不是 UTF-8 时整次调用失败,不返回
部分装配结果。Adapter 在分配参数展开结果前先执行保守上界检查,Product Assembly 再按实际最终长度复核。规范化后再打开
仍存在同一用户并发替换文件的本地 TOCTOU 窗口;读取始终受大小限制,且不会因此放宽到任意宿主机绝对路径。

Markdown front matter 的 `description`、`agent`、`model`、`variant`、`subtask` 按当前 OpenCode schema 校验;
已知字段类型错误使该命令不可用,不能当作缺省值继续执行。初次 YAML 解析失败时,adapter 按 OpenCode 当前规则将
Expand All @@ -274,7 +290,7 @@ provider 的模板正文总量限制为 8 MiB;超过限制进入明确诊断
正文不进入 IPC。执行前以来源限定命令 ID 和命令内容版本校验当前菜单项;若文件在菜单展示后更新,旧菜单项必须返回
stale selection 并等待重新选择,不能直接执行刚刷新的新内容。

后续阶段接通文件引用和 shell 输出时仍按 OpenCode 顺序展开。`!shell` 必须进入脚本执行域,不另建绕过可靠性控制
后续阶段接通 shell 输出时仍按 OpenCode 顺序展开。`!shell` 必须进入脚本执行域,不另建绕过可靠性控制
的同步 shell 路径;展开有期限、取消和输出大小限制,大输出保存后只把引用交给命令模板。

OpenCode 生态内部仍按其规则覆盖同名内置命令,但跨独立 provider 或与 BitFun 本地命令同名时不得静默覆盖。
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,9 @@ OpenCode,和 OpenCode 配置/插件进入 BitFun 是两个独立验收方向
| 独立 `tui.json/jsonc` | 融合现有能力 + 转换参数 | 未实现 | 可完整适配 | OC-R1 | 按 global、`OPENCODE_TUI_CONFIG`、project、`.opencode` 独立顺序加载,不能复用主配置优先级 | [TUI 来源](opencode-config-assets-adapter-design.md#32-tui-独立来源顺序) |
| Rules / Instructions | 转换参数 | 部分实现:项目本地文件与 glob | 可完整适配 | OC-R1 | 当前由 Workspace Instructions owner 读取项目 `instructions` 的精确文件和 glob;全局、远程 URL、完整来源合并与变化监听仍未实现 | [声明式资产](opencode-config-assets-adapter-design.md#5-声明式资产映射) |
| Agents / Modes | 融合现有能力 + 转换参数 | 部分实现:Subagent 安全子集 | 可主要适配 | OC-R1 | 已支持全局/项目 Markdown、JSON/JSONC 的 subagent/all、prompt、description、disable/hidden、精确模型与工具映射,并接入审批、冲突、更新、撤下和 fresh single-run Task;primary/mode、permission、variant/options、采样与续接明确降级 | [Agents 与 Skills](opencode-config-assets-adapter-design.md#52-agentsmodes-与-skills) |
| Skills | 转换参数 | 部分实现:现有 Registry 发现与来源/覆盖展示 | 可完整适配 | OC-R2 | 已沿用现有根顺序发现 `.opencode` 等用户/项目 Skill,并在 GUI/TUI 展示来源、使用范围和覆盖结果;尚未复现 OpenCode 按需加载、完整配置合并及 allow/deny/ask 顺序,也未并入外部来源策略模块 | [Agents 与 Skills](opencode-config-assets-adapter-design.md#52-agentsmodes-与-skills) |
| Skills | 转换参数 | 部分实现:标准根与本地配置根 | 可完整适配 | OC-R2 | 现有 Registry 除标准用户/项目根外,也通过 `bitfun-core/external_sources` 组合边界按 OpenCode 配置来源顺序累加 V1 `skills.paths` 与当前迁移后的本地字符串数组;仅接受项目根/用户目录内的本地目录并做有界递归发现。同 scope 配置根覆盖标准 OpenCode 根,但不重排更早的 BitFun/Claude/Codex/Cursor 来源。URL、下载/缓存、完整 allow/deny/ask 顺序及外部来源策略仍未实现 | [Agents 与 Skills](opencode-config-assets-adapter-design.md#52-agentsmodes-与-skills) |
| References | 补基础能力 + 转换参数 | 未实现 | 可主要适配 | OC-R2 | R1 解析;R2 支持本地目录和 Git repository/branch/description/hidden,异步准备并接入 `@alias` | [声明式资产](opencode-config-assets-adapter-design.md#5-声明式资产映射) |
| Commands | 补扩展接口 + 转换参数 | 部分实现:prompt-only 子集 | 可完整适配 | OC-R2 | 已支持全局/项目 JSON、JSONC、Markdown 命令、`$ARGUMENTS` 与位置参数,并接入动态命令目录、运行时刷新和显式冲突选择;`@file`、shell、Agent/model/variant/subtask 保持受限且不做部分执行 | [Commands](opencode-config-assets-adapter-design.md#53-commands) |
| Commands | 补扩展接口 + 转换参数 | 部分实现:prompt-only + 本地文本文件子集 | 可完整适配 | OC-R2 | 已支持全局/项目 JSON、JSONC、Markdown 命令、参数展开、动态目录、刷新和显式冲突选择;模板中的静态 workspace 相对 `@file` 可在调用时有界读取,动态/绝对/越界文件引用、shell、Agent/model/variant/subtask 保持受限且不做部分执行 | [Commands](opencode-config-assets-adapter-design.md#53-commands) |
| Models / Providers 配置 | 融合现有能力 | 未实现 | 可主要适配 | OC-R1 | 静态字段进入模型归属模块;动态模型、鉴权和请求头交给插件运行时 | [声明式资产](opencode-config-assets-adapter-design.md#5-声明式资产映射) |
| MCP | 转换参数 | 部分实现:local stdio 与 HTTPS remote | 可完整适配 | OC-R2 | 已接入发现、审批、冲突、workspace 隔离、更新和启动反馈;SSE、OAuth、完整 timeout/Agent 范围仍不支持;Remote 不回退本机实例 | [MCP、LSP 与 Formatter](opencode-config-assets-adapter-design.md#54-mcplsp-与-formatter) |
| LSP | 转换参数 | 未实现 | 可完整适配 | OC-R2 | R1 解析;R2 转换 command、extensions、env 和 initialization 并由 LSP 归属模块启动 | [MCP、LSP 与 Formatter](opencode-config-assets-adapter-design.md#54-mcplsp-与-formatter) |
Expand Down
Loading