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.

9 changes: 5 additions & 4 deletions docs/architecture/agent-runtime-deployment-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ flowchart TB
| Session 写入 | BitFun Runtime 的持久化 Session 由 `SessionManager` 管理;同一存储位置中的同一 Session 同时只允许一个本机进程写入,list/view 等只读操作不受影响 |
| 当前 HTTP Server | 只提供 health/info/WebSocket 外壳,未装配 Agent Runtime,因此不取得 workspace ownership;`bootstrap.rs` 仅保持 agent-enabled composition 的一致边界,不由当前入口启动 |
| Shared local IPC | 未发布的本机协议已有 discovery、实例锁、严格握手、Session 控制权、有界事件流和 cleanup;唯一 consumer 是第一方交互式 TUI adapter |
| Shared TUI | `bitfun --shared` / `bitfun chat --shared` 可列出、创建、恢复和重命名当前 Session,读取 transcript,切换当前 Session 的 Agent mode/model,提交/取消 Turn,处理 Permission 和 UserInput;默认仍是 Embedded |
| Shared TUI | `bitfun --shared` / `bitfun chat --shared` 可列出、创建、恢复和重命名当前 Session,读取 transcript,切换当前 Session 的 Agent mode/model,通过 `/reload [skills|instructions]` 刷新声明式上下文,提交/取消 Turn,处理 Permission 和 UserInput;默认仍是 Embedded |
| Shared GUI/Headless/ACP/SDK Host/Remote | 未交付,也不会由 `--shared` 隐式启用;Replay、Observer、Controller transfer、Session delete/fork 同样不在当前协议中 |

因此当前交付的是一条窄的、显式启用的 Shared TUI deployment,不是通用本机 Server。具体 `EventQueue` 仍由 Core 产品装配;IPC 只把当前 TUI 必需的强类型操作和事件映射到同一个 Runtime owner,没有事件重放或公开协议承诺。
Expand Down Expand Up @@ -196,19 +196,19 @@ sequenceDiagram
S-->>C: initialized(health + interactive_tui)
C->>S: create or restore Session
S-->>C: Session control + Session facts
C->>S: rename or update current Session
C->>S: rename, update, or reload current Session context
C->>S: submit/cancel Turn or answer Permission/UserInput
S-->>C: Session-filtered authoritative events
else invalid
S-->>C: typed error and close
end
```

当前私有协议(v5)只覆盖 TUI 已有用户旅程需要的窄操作:
当前私有协议(v6)只覆盖 TUI 已有用户旅程需要的窄操作:

| 已支持 | 明确不支持 |
|---|---|
| Health、Session list/create、原子 restore(含 transcript 与 pending Permission)、当前 Session rename、Agent mode/model update | Session delete/fork、跨 workspace attach、transcript 分页、模型目录/默认值和 Agent/Subagent 管理 |
| Health、Session list/create、原子 restore(含 transcript 与 pending Permission)、当前 Session rename、Agent mode/model update、声明式上下文 reload | Session delete/fork、跨 workspace attach、transcript 分页、模型目录/默认值和 Agent/Subagent 管理 |
| Turn submit/cancel | replay、cursor、resume event stream |
| pending/respond Permission、submit UserInput answers | observer、controller transfer、多 Session multiplex |
| 连接断开清理、Session-filtered events | detach/observer/controller transfer、SDK callbacks、GUI/Remote/Peer/ACP/Headless wire |
Expand All @@ -228,6 +228,7 @@ sequenceDiagram
- 一个连接最多控制一个 Session、同时最多提交一个活动 Turn;一个 Session 同时只有一个 controller。create/restore 在完整结果通过大小检查后才原子切换控制权,失败时保留原 Session。活动 Turn 期间不能切换 Session,也不能修改其名称、Agent mode 或 model。
- Submit 使用调用方已有的 `turn_id` 标识不确定结果;若提交超时,返回 `outcome_unknown`、关闭连接并按该 ID 取消。断连取消只有得到确认后才释放 Session 控制权;无法确认时继续隔离该 Session,直到 Runtime 进程退出。
- Session rename 和 Agent mode/model update 复用既有 Runtime 端口和校验,Runtime 对最终更新保持权威并拒绝无效值。它们都是有副作用操作;发送前编码或 frame 上限失败表示请求未执行,连接仍可使用。rename 写入失败时恢复旧 metadata:确认恢复后返回明确失败,无法确认时返回 `outcome_unknown`。Shared Client 在请求写入后响应超时或丢失连接时也返回 `outcome_unknown` 并断开连接。两种情况都不自动重试;用户恢复 Session 并核对当前值后再决定是否重试。模式与模型目录仍是同版本第一方产品事实,不加入 IPC。
- 声明式上下文 reload 只失效当前 Session 的 instructions 缓存,并按目标复用 Skill Registry 刷新;它可在活动 Turn 中执行但不改写该 Turn,generation 保护保证下一条消息重建上下文。它不引入 watcher、热替换或第二套 Runtime owner。
- Shared TUI 的模型选择器复用 Client 已有的只读产品配置来显示同版本模型目录;它只把选中的 model ID 通过 `update current Session model` 交给 Runtime。Client 不持有 Session 写入权,也不通过 IPC 管理模型目录或默认值。
- Agent 事件流 lag/closed 后 fail closed;Permission lag 先从 Runtime 权威 pending 集合重建,重建失败或流关闭时取消当前 Turn 并退出。路由到父 Session 的嵌套 Permission 与 AskUserQuestion 复用现有 TUI 交互,不新增第二套 UI 状态。
- Windows Shared Runtime 在初始化前把自身放入 kill-on-close Job;Unix 仅在应用内优雅退出路径中通过受管子进程组回收后代。Runtime 被 `SIGTERM`、`SIGKILL` 或崩溃直接终止后的 Unix 后代回收不在当前保证内。两者都只负责生命周期,不是安全沙箱。
Expand Down
9 changes: 9 additions & 0 deletions docs/architecture/cache-friendly-message-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,15 @@ What usually breaks reuse:
- explicit prompt-cache invalidation
- context compression, which resets prompt cache after rewriting history

The user-facing `/reload instructions` command intentionally invalidates only
the current Session's `UserContext` cache. The active turn is not rewritten;
workspace instructions are read again when the next message is assembled.
Plain `/reload` combines that operation with the independently owned Skill
Registry refresh, while `/reload skills` leaves `UserContext` intact.
An in-memory generation guard rejects a user-context build that started before
the invalidation from repopulating the cache after it, so active-turn reloads
preserve the same next-message guarantee.

### 6. Conversation history

What it is:
Expand Down
24 changes: 16 additions & 8 deletions docs/architecture/cli-product-line-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,12 +256,12 @@ Headless CLI 和公开 Agent SDK 都调用同一 Agent Runtime API,但交付

| 形态 | 默认部署 | 当前 Shared 范围 |
|---|---|---|
| 交互式 TUI | Embedded | 显式 `--shared` 后支持 Session list/create/restore、transcript、当前 Session rename/Agent mode/model、Turn submit/cancel、Permission 和 UserInput |
| 交互式 TUI | Embedded | 显式 `--shared` 后支持 Session list/create/restore、transcript、当前 Session rename/Agent mode/model、声明式上下文 reload、Turn submit/cancel、Permission 和 UserInput |
| `bitfun exec` / CI | Embedded | 不接受 Shared;保持独立进程、stdout/stderr 和退出码语义 |
| ACP / SDK Host / GUI / Remote / Peer | 各自既有部署 | 不消费 TUI IPC,也不因本开关改变生命周期 |

Shared TUI 不提供 Session delete/fork、模型目录/默认值、Agent/Subagent 管理、MCP/扩展、账号同步、用量、observer、replay 或 controller transfer;对应入口给出明确的 Embedded 恢复建议,不在 Client 进程初始化第二套 Core owner。
Shared 模式的斜杠命令、快捷键帮助和底部提示使用同一能力投影:`/rename <name>` 修改当前 Session 名称;`/agent`、Tab 和 Shift+Tab 只切换当前 Session 的 Agent mode;`/models` 只切换当前 Session 的 model。Embedded 与 Shared 的 `/help` 都从 Action Registry 展示 `/rename <name>`;在 slash menu 中选择它只预填命令并等待用户输入名称。若外部来源使用相同命令名,用户明确选择的 BitFun 命令可完成这一次参数提交,即使偏好保存失败也不会重新弹出来源选择。它们不进入管理页面,也不修改未来 Session 的默认值。其他不支持动作不显示为可执行入口。Session 切换失败保留原控制权;单个连接已有活动 Turn 时拒绝重复提交以及 Session rename/mode/model update;事件订阅失效后当前视图立即失效并要求重启 Shared TUI。
Shared 模式的斜杠命令、快捷键帮助和底部提示使用同一能力投影:`/rename <name>` 修改当前 Session 名称;`/agent`、Tab 和 Shift+Tab 只切换当前 Session 的 Agent mode;`/models` 只切换当前 Session 的 model;`/reload [skills|instructions]` 刷新下一条消息使用的声明式上下文。Embedded 与 Shared 的 `/help` 都从 Action Registry 展示 `/rename <name>` 和 `/reload`;在 slash menu 中选择 rename 只预填命令并等待用户输入名称。若外部来源使用相同命令名,用户明确选择的 BitFun 命令可完成这一次参数提交,即使偏好保存失败也不会重新弹出来源选择。它们不进入管理页面,也不修改未来 Session 的默认值。其他不支持动作不显示为可执行入口。Session 切换失败保留原控制权;单个连接已有活动 Turn 时拒绝重复提交以及 Session rename/mode/model update,但允许 reload 只影响下一条消息;事件订阅失效后当前视图立即失效并要求重启 Shared TUI。

部署差异由 CLI Runtime client 封装。Embedded 以 Rust 类型直接调用 `AgentRuntime`,不初始化 IPC 或执行 JSON 编解码;Shared 将同一业务请求映射为一个有界本机 frame,Client/Server 各自只编码一次,再交给同一 Runtime owner。多 TUI 复用一个 Runtime 进程,连接和队列保持有界,不按 TUI 数量复制 Session owner。详细的 4+1 视图、帧上限和并发边界见
[`agent-runtime-deployment-design.md`](agent-runtime-deployment-design.md)。
Expand Down Expand Up @@ -535,10 +535,14 @@ Hook C0:脱敏发现 -> 精确命令预览 | 指纹确认 -> 原子发布本
规则文件优先复用项目已有文件,不复制出第二份内容。若不同生态规则冲突,导入报告必须展示目标文件、
优先级和冲突段,不能自动拼接。

当前 Workspace Instructions 只消费真实工作区根:本地和 Remote 共用 `WorkspaceFileSystem` 读取,
`AGENTS.override.md` 文件存在时替代同目录 `AGENTS.md`(空文件也不回退),`CLAUDE.md` 继续作为独立来源按既有顺序追加。
运行时尚无稳定的嵌套活动目录事实,因此不声明 root-to-cwd 级联;全局规则、Claude rules/import、OpenCode
`instructions` glob/URL、变化监听和冲突报告也不属于当前实现。
当前 Workspace Instructions 只消费真实工作区根,本地和 Remote 共用同一个解析器与 `WorkspaceFileSystem` 端口。
固定顺序是:`AGENTS.override.md`(存在时替代 `AGENTS.md`,空文件也不回退)、根 `CLAUDE.md` 或
`.claude/CLAUDE.md`、`CLAUDE.local.md`、不带 `paths` front matter 的 `.claude/rules/**/*.md`,最后是项目根与
`.opencode` 中 `opencode.json/jsonc` 的本地 `instructions` 文件或 glob。Claude `@import` 只跟随工作区内文件,
深度上限为 5,并对重复和循环引用去重;所有目录遍历都跳过符号链接。运行时尚无稳定的嵌套活动目录事实,因此
不声明 root-to-cwd 级联。递归扫描跳过 VCS、依赖与构建目录,并对扫描节点、文件数量、单文件和总内容字节设置固定
上限,避免宽 glob 阻塞本地或 Remote 工作区。Claude path-scoped rules、全局规则、OpenCode 远程 URL、变化监听和冲突
报告也不属于当前实现。

现有对 `.claude/.codex/.opencode/.agents` Skill 根的直接发现已经保留来源身份和全局/项目使用范围,并在 GUI/TUI
展示来源和默认覆盖状态,模式配置再展示实际采用项;固定根顺序保持为 Skill Registry 的独立回归契约。
Expand All @@ -554,8 +558,12 @@ Skill Registry 还保留来源资产声明的隐式调用意图:Claude `SKILL.
分组以及 `\$` 转义;缺失的位置参数保留原占位符,模板没有未转义占位符时才追加 `ARGUMENTS:` 段。该展开器只处理
字符串,不执行命令、脚本或动态变量。未携带 `arguments` 的旧工具调用保持原 Skill 正文不变。

这项能力不新增导入记录、来源图、后台 watcher 或第二套刷新生命周期。工作区查询继续按现有 Registry 路径扫描,用户
缓存继续使用已有刷新入口,CLI 的 `/reload-skills` 仍是明确的手动刷新方式;运行期不承诺对所有来源做文件监听或热重载。
这项能力不新增导入记录、来源图、后台 watcher 或第二套刷新生命周期。用户只需要一个手动入口:`/reload` 同时刷新
Skill Registry 并失效当前 Session 的 Workspace Instructions 缓存;`/reload skills` 与 `/reload instructions` 用于只刷新
一类内容。Desktop、Embedded CLI 与 Shared TUI 共用同一 core 协调入口,但 Skill Registry 刷新和 Session
`UserContext` 缓存失效仍由各自既有 owner 完成。指令变更从下一条消息开始生效;运行期不承诺文件监听或当前生成中的
消息热替换。缓存 generation 会拒绝活动 Turn 在失效之后写回的旧构建结果;旧 `/reload-skills` 输入仅作为隐藏兼容别名
映射到 `/reload skills`,不增加第二个命令入口。
本切片也不实现 `allowed-tools`、`context`、`fork`、`agent`、`model`、命名参数、动态 shell/runtime 变量、URL、祖先目录
级联、插件 Runtime 或 OpenCode 复杂 Hook。后续只有在存在稳定消费方和独立安全边界时才扩展这些语义。

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ OpenCode adapter 在来源发现、解析和审批前不 import module、不读

| 资产 | OpenCode 输入 | BitFun 归属模块 / 适配方式 | 默认行为 | 降级条件 |
|---|---|---|---|---|
| Rules / Instructions | 项目/全局 `AGENTS.md`、Claude fallback、`instructions` glob、本地文件、远程 URL | Workspace Instructions 归属模块保存有序来源引用 | 本地内容按 L1 合并并保留来源;主动获取远程 URL 前确认 | 远程或单文件失败只排除该来源。 |
| 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。 |
| References | `references` / 旧 `reference`,本地 path 或 Git repository/branch/description/hidden | **基础能力缺失**:先补 Workspace Reference 的异步准备与 `@alias` 消费接口 | 本地引用保留相对来源;Git 拉取按 L2 确认并保留缓存/隐藏语义 | 拉取失败不阻止项目,外部目录仍遵守工具权限。 |
Expand All @@ -217,6 +217,12 @@ OpenCode adapter 在来源发现、解析和审批前不 import module、不读
规则内容尽量原地引用,不复制成第二份文件。组合结果保留原始段落来源和顺序。OpenCode 与 BitFun 原生规则
同时存在时,配置视图展示实际进入模型的顺序;不能把冲突文本自动改写成“合并后的真相”。

当前 runtime-free 子集不建立通用配置来源图:Workspace Instructions owner 在每个 Session 首次需要 user context 时读取
项目根 `opencode.json`、`opencode.jsonc`、`.opencode/opencode.json` 和 `.opencode/opencode.jsonc` 中的
`instructions` 数组,只接受工作区内相对精确文件与 glob,确定性排序后追加到既有 `AGENTS`/Claude 来源之后。
绝对路径、`~`、越出工作区的路径、符号链接和 URL 都不会加载。文件变更不启动 watcher;用户通过统一的
`/reload instructions`(或默认 `/reload`)失效当前 Session 的 `UserContext` 缓存,下一条消息重新读取。

### 5.2 Agents、Modes 与 Skills

兼容定义进入现有 Agent 归属模块,而不是新建 OpenCode Agent Runtime。当前已实现范围按是否能保持行为等价划分:
Expand Down
Loading