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/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,删除未被控制的空闲非当前 Session,通过 `/fork` 从完整历史或选中提示词之前创建分支,重命名当前 Session,读取 transcript,切换当前 Session 的 Agent mode/model,通过 `/reload [skills|instructions]` 刷新声明式上下文,通过 `/compact` 或 `/summarize` 压缩当前 Session 上下文,提交/取消 Turn,处理 Permission 和 UserInput;默认仍是 Embedded |
| Shared TUI | `bitfun --shared` / `bitfun chat --shared` 可列出、创建、恢复 Session,删除未被控制的空闲非当前 Session,通过 `/fork` 从完整历史或选中提示词之前创建分支,重命名当前 Session,读取 transcript,切换当前 Session 的 Agent mode/model,通过 `/reload [skills|instructions]` 刷新声明式上下文,通过 `/compact` 或 `/summarize` 压缩当前 Session 上下文,在 Turn 空闲时通过 `/diff` 读取 Runtime 绑定工作区的只读差异,提交/取消 Turn,处理 Permission 和 UserInput;默认仍是 Embedded |
| Shared GUI/Headless/ACP/SDK Host/Remote | 未交付,也不会由 `--shared` 隐式启用;Replay、Observer、通用 Controller transfer 和 Session archive 同样不在当前协议中 |

因此当前交付的是一条窄的、显式启用的 Shared TUI deployment,不是通用本机 Server。具体 `EventQueue` 仍由 Core 产品装配;IPC 只把当前 TUI 必需的强类型操作和事件映射到同一个 Runtime owner,没有事件重放或公开协议承诺。
Expand Down Expand Up @@ -207,13 +207,13 @@ sequenceDiagram
end
```

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

| 已支持 | 明确不支持 |
|---|---|
| Health、Session list/create、原子 restore(含 transcript 与 pending Permission)、删除未被控制的空闲 Session、当前 Session fork(含 transcript)、rename、Agent mode/model update、声明式上下文 reload | Session archive、跨 workspace attach、transcript 分页、模型目录/默认值和 Agent/Subagent 管理 |
| Turn submit/cancel、当前 Session 手动 context compaction | replay、cursor、resume event stream |
| pending/respond Permission、submit UserInput answers | observer、通用 controller transfer、多 Session multiplex |
| pending/respond Permission、submit UserInput answers、只读 workspace diff | observer、通用 controller transfer、多 Session multiplex |
| 连接断开清理、Session-filtered events | detach/observer/通用 controller transfer、SDK callbacks、GUI/Remote/Peer/ACP/Headless wire |

这些操作先满足以下本机 IPC 地基,而不把协议升级为公开 SDK:
Expand All @@ -229,6 +229,7 @@ sequenceDiagram
- 未认证连接也计入有界 connection budget,单个客户端不能无限制造 server task;
- 未知 frame/operation 信封字段、未知 operation、错误身份和不兼容版本 fail closed;复用的 Runtime DTO 按其既有反序列化契约处理字段;
- v10 增加两个只读、current-controller 限定的工作区引用 operation:按当前 Session 搜索文件/目录,以及按 user message ID 读取已持久化的结构化引用。两者复用 Agent Runtime 的 workspace-reference port,不赋予 IPC adapter 文件系统或 Session 持久化所有权,也不扩展为 Remote 或公开 SDK 协议。
- v11 增加无请求体、无 Session lease 的只读 workspace diff operation。它只在当前连接没有活动 Turn 时查询 Runtime 启动时绑定的 canonical workspace,避免单连接请求排序阻塞流事件或 Turn 控制,并返回 Runtime Port DTO;Git 行为仍由 `services-integrations` provider 持有。文本 patch 总量限制为 3 MiB,为 JSON 转义和 envelope 预留既有 8 MiB response frame 的空间;该 operation 不隐式获得 stage/reset/commit、Remote 或公开 SDK 能力。
- 一个连接最多控制一个 Session、同时最多提交一个活动 Turn;一个 Session 同时只有一个 controller。create/restore/fork 在完整结果通过大小检查后才原子切换控制权,失败时保留原 Session。fork 只接受当前 controller 的空闲 Session;无选中 Turn 时复制到最新持久化 Turn,指定 `before_turn_id` 时只复制该 Turn 之前的历史。活动 Turn 期间不能切换或 fork Session,也不能修改其名称、Agent mode 或 model;删除只作用于非当前且未被任何连接控制的 Session。
- Submit 与手动 context compaction 都使用调用方已有的 `turn_id` 标识不确定结果;若操作超时,返回 `outcome_unknown`、关闭连接并按该 ID 取消。手动 compaction 要求当前 controller 且 Session 空闲,由 Core 通过与普通对话 Turn 共用的原子准入路径创建一个可审计 maintenance Turn,并在取得所有权后读取压缩上下文:planning 阶段允许取消,atomic commit 开始后忽略晚到取消并保持 Processing 直至终态持久化完成。maintenance Turn 保留在权威 transcript 中但不进入模型上下文,live/restored payload 使用同一 compression ID 和 `applied` 事实;commit 后的持久化故障发布明确失败终态而不是遗留 Processing。断连取消只有得到确认后才释放 Session 控制权;无法确认时继续隔离该 Session,直到 Runtime 进程退出。
- Session delete/rename 和 Agent mode/model update 复用既有 Runtime 端口和校验,Runtime 对最终结果保持权威并拒绝无效目标。它们都是有副作用操作;发送前编码或 frame 上限失败表示请求未执行,连接仍可使用。rename 写入失败时恢复旧 metadata:确认恢复后返回明确失败,无法确认时返回 `outcome_unknown`。Shared Client 在请求写入后响应超时或丢失连接时也返回 `outcome_unknown` 并断开连接。两种情况都不自动重试:rename 由用户恢复 Session 并核对当前值;delete 由用户重新打开 `/sessions` 核对目标是否仍存在。模式与模型目录仍是同版本第一方产品事实,不加入 IPC。
Expand Down Expand Up @@ -262,7 +263,7 @@ flowchart LR
| Shared receive | 每个方向只有一个严格 transport decode 边界 | 未知信封字段和不兼容版本 fail closed;严格校验可以检查规范化 JSON,但不能把动态 JSON 传入 Runtime owner |
| 多 TUI | 一个 Runtime、最多 64 个连接;每个 Client 的 command channel 容量为 64、event channel 容量为 256 | request gate 使每个 Client 同时只有一个请求进入 channel;事件落后时失效而非无限缓存 |

协议只承载当前交互所需的小型控制请求和既有事件。大 transcript 继续受 frame 上限约束;本阶段不为假设场景增加通用分页、二进制 side channel、压缩或批处理协议。
协议只承载当前交互所需的小型控制请求、受 3 MiB 文本上限保护的 workspace diff 快照和既有事件。大 transcript 继续受 frame 上限约束;本阶段不为假设场景增加通用分页、二进制 side channel、压缩或批处理协议。

## 5. Development and Physical Views · Level 1

Expand Down
6 changes: 4 additions & 2 deletions docs/architecture/cli-product-line-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ BitFun CLI 应成为可独立安装和发布的 Agent 产品,而不是 Desktop

当前主线已经具备以下基础:

- 交互式 TUI、Markdown/代码/Diff/工具卡片、主题、模型/Agent/MCP/Skill/Subagent/Session 选择;权限请求默认询问,
- 交互式 TUI、Markdown/代码/Diff/工具卡片、主题、模型/Agent/MCP/Skill/Subagent/Session 选择;OpenCode 对齐的 `/diff` 通过 Runtime Git port 查看当前工作区 staged、unstaged 与 untracked 的 `HEAD` 相对差异;权限请求默认询问,
提供 `Allow once / Allow always / Reject`,其中 `Allow always` 只对当前运行上下文中的同名工具有效。
- `exec` 支持 stdin、会话恢复/分叉、Patch 输出和 `text/json/stream-json`。非交互执行默认拒绝权限请求,
显式 `--auto` 才在本次调用内自动批准;兼容参数 `--confirm` 隐藏并映射到安全默认值。`Ctrl+C` 会请求取消
Expand Down Expand Up @@ -258,13 +258,15 @@ Headless CLI 和公开 Agent SDK 都调用同一 Agent Runtime API,但交付

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

Shared TUI 不提供 Session archive、模型目录/默认值、Agent/Subagent 管理、MCP/扩展、账号同步、用量、observer、replay 或通用 controller transfer;对应入口给出明确的 Embedded 恢复建议,不在 Client 进程初始化第二套 Core owner。
Shared 模式的斜杠命令、快捷键帮助和底部提示使用同一能力投影:OpenCode 对齐的 `/fork` 以 `Full session` 或历史用户提示词选择分支边界;选择提示词时 fork 只复制该 Turn 之前的历史,并把提示词放回 composer 而不自动发送。`/rename <name>` 修改当前 Session 名称;`/agent`、Tab 和 Shift+Tab 只切换当前 Session 的 Agent mode;`/models` 只切换当前 Session 的 model;`/reload [skills|instructions]` 刷新下一条消息使用的声明式上下文;OpenCode 对齐的 `/compact` 及其 `/summarize` alias 以一个可取消的 maintenance Turn 压缩当前 Session 上下文,不增加自创命令或快捷键。该 Turn 与普通对话共用 Session 原子准入,取得所有权后再读取待压缩上下文;权威 transcript 保留完整 tool payload,但重建模型上下文时排除该 maintenance Turn。Embedded 与 Shared 的 `/help` 都从 Action Registry 展示这些入口;在 slash menu 中选择 rename 只预填命令并等待用户输入名称。若外部来源使用相同命令名,用户明确选择的 BitFun 命令可完成这一次参数提交,即使偏好保存失败也不会重新弹出来源选择。它们不进入管理页面,也不修改未来 Session 的默认值。其他不支持动作不显示为可执行入口。Session 切换或 fork 失败保留原控制权;Shared fork 只有在新 Session 与 transcript 的响应可编码后才原子转移 controller。单个连接已有活动 Turn 时拒绝重复提交、fork、manual compaction 以及 Session rename/mode/model update,但允许 reload 只影响下一条消息;事件订阅失效后当前视图立即失效并要求重启 Shared TUI。

`/diff` 只使用 OpenCode 已有命令名,不增加 alias 或全局快捷键,并且只在当前 Turn 空闲时进入。查看器以 `n`/`p` 切换文件、`]`/`[` 跳转 hunk,并保留方向键和 PageUp/PageDown 滚动;窄屏隐藏文件栏但保留当前 patch。TUI 只持有快照和导航状态,Git 仓库发现、差异计算及 staged/unstaged/untracked 事实由 `services-integrations` 中的 Runtime provider 负责。补丁与 OpenCode working-tree 视图一致,是 `HEAD` 到当前工作树的单一净补丁;staged/unstaged/untracked 仅作为文件状态展示,不在本阶段引入分区补丁或 source switch,相互抵消时仍保留文件和状态。冲突文件保留 `U` 状态并显示明确占位,不把 libgit2 的不完整两路投影伪装成三路冲突内容。Embedded 与 Shared 调用同一个 `AgentRuntime::workspace_diff`;TUI 仅在 Session execution workspace 与 Runtime 绑定的 project workspace 相同时调用,其他 worktree 与 Remote Session 明确返回不支持,避免显示错误的本地工作区事实。Shared 的无请求体只读 operation 不取得 Session lease,但要求连接没有活动 Turn,加载期间同一 Shared 客户端不再发起其他 Runtime 请求。单文件文本 diff 上限 1 MiB、总文本 diff 上限 3 MiB、文件数上限 256,超限和二进制文件显示明确占位。该入口不包含 refresh watcher、split diff、stage/reset/commit、变更归因、Remote 或 Relay 映射。

OpenCode 对齐的 `/undo` 与 `/redo` 只提供这两个命令名,不增加 alias、快捷键或通用 checkpoint API。Core 以持久化的 staged boundary 同步裁剪可见 transcript、模型上下文和该边界后的受跟踪工作区改动;`/undo` 把被撤销的用户提示词放回 composer,连续调用可继续向前,`/redo` 逐级恢复直到清除 boundary,usage 与 fork 也只读取该 boundary 前的可见事实。活动 Turn 必须先由 scheduler 完成取消和 drain,失败时不写入 boundary;Shared 仍要求 current controller,并以 Runtime 返回的权威 transcript 更新 TUI。暂存期间提交新提示词或执行既有本地 snapshot accept/reject/rollback mutation,会先进入可恢复的 committing 阶段,永久删除隐藏后缀再建立新分支;同一阶段的 snapshot record 被拒绝,避免追加到隐藏历史。崩溃恢复会按持久化阶段重放 workspace/context 对齐或完成提交;跨文件系统与 Session 存储不宣称原子事务,部分失败返回 `outcome_unknown` 并要求恢复 Session 后检查。该能力当前只支持本地工作区,Remote 在任何回退写入前返回 `NotAvailable`。

部署差异由 CLI Runtime client 封装。Embedded 以 Rust 类型直接调用 `AgentRuntime`,不初始化 IPC 或执行 JSON 编解码;Shared 将同一业务请求映射为一个有界本机 frame,Client/Server 各自只编码一次,再交给同一 Runtime owner。多 TUI 复用一个 Runtime 进程,连接和队列保持有界,不按 TUI 数量复制 Session owner。详细的 4+1 视图、帧上限和并发边界见
Expand Down
4 changes: 2 additions & 2 deletions scripts/core-boundaries/rules/feature-rules.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export const optionalDependencyFeatureOwnerRules = [
{ depName: 'anyhow', ownerFeatures: ['browser-control', 'debug-log', 'mcp', 'remote-connect', 'remote-ssh', 'remote-ssh-concrete'] },
{
depName: 'async-trait',
ownerFeatures: ['mcp', 'remote-connect', 'remote-ssh', 'remote-ssh-concrete', 'review-platform', 'script-tool-runtime', 'speech', 'workspace-search'],
ownerFeatures: ['git', 'mcp', 'remote-connect', 'remote-ssh', 'remote-ssh-concrete', 'review-platform', 'script-tool-runtime', 'speech', 'workspace-search'],
},
{
depName: 'base64',
Expand All @@ -72,7 +72,7 @@ export const optionalDependencyFeatureOwnerRules = [
{ depName: 'bitfun-agent-runtime', ownerFeatures: ['deep-research', 'hook-import'] },
{ depName: 'bitfun-core-types', ownerFeatures: ['speech'] },
{ depName: 'bitfun-product-domains', ownerFeatures: ['canvas-runtime', 'function-agents', 'hook-import', 'miniapp-runtime', 'plugin-source'] },
{ depName: 'bitfun-runtime-ports', ownerFeatures: ['remote-connect', 'remote-ssh', 'remote-ssh-concrete', 'script-tool-runtime'] },
{ depName: 'bitfun-runtime-ports', ownerFeatures: ['git', 'remote-connect', 'remote-ssh', 'remote-ssh-concrete', 'script-tool-runtime'] },
{
depName: 'bitfun-services-core',
ownerFeatures: ['browser-control', 'git', 'hook-import', 'mcp', 'miniapp-runtime', 'process-tree', 'remote-connect', 'remote-ssh-concrete', 'review-platform', 'workspace-search'],
Expand Down
2 changes: 1 addition & 1 deletion scripts/core-boundaries/rules/source/forbidden-rules.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const forbiddenContentRules = [
reason: 'agent-runtime-ipc operation scope is frozen to the reviewed Shared TUI slice',
patterns: [
{
regex: /^\s+(?!(?:Health|ListSessions|CreateSession|RestoreSession|DeleteSession|ForkSession|RenameSession|UpdateSessionMode|UpdateSessionModel|ReloadSessionContext|CompactSession|UndoSession|RedoSession|SearchWorkspaceReferences|WorkspaceReferencesForMessage|SubmitTurn|CancelTurn|PendingPermissions|RespondPermission|SubmitUserAnswers|Unit|Sessions|SessionCreated|SessionRestored|SessionForked|SessionReverted|WorkspaceReferenceSearch|WorkspaceReferences|TurnAccepted|TurnCancelled|None|CurrentController|AttachExisting|UncontrolledTarget|Self|RuntimeIpcSessionRequirement|RuntimeIpcOperationRules|RuntimeSessionForkRequest|AgentContextReloadRequest|AgentDialogTurnRequest|AgentMessageWorkspaceReferencesRequest|AgentSessionCompactionRequest|AgentSessionCreateRequest|AgentSessionCreateResult|AgentSessionListRequest|AgentSessionModeUpdateRequest|AgentSessionModelUpdateRequest|AgentSessionRevertRequest|AgentSessionRevertResult|AgentSessionSummary|AgentTurnCancellationRequest|AgentTurnCancellationResult|AgentWorkspaceReference|AgentWorkspaceReferenceSearchRequest|AgentWorkspaceReferenceSearchResult|SessionTranscript)\b)[A-Z][A-Za-z0-9_]*\b/,
regex: /^\s+(?!(?:Health|ListSessions|CreateSession|RestoreSession|DeleteSession|ForkSession|RenameSession|UpdateSessionMode|UpdateSessionModel|ReloadSessionContext|CompactSession|UndoSession|RedoSession|SearchWorkspaceReferences|WorkspaceReferencesForMessage|WorkspaceDiff|SubmitTurn|CancelTurn|PendingPermissions|RespondPermission|SubmitUserAnswers|Unit|Sessions|SessionCreated|SessionRestored|SessionForked|SessionReverted|WorkspaceReferenceSearch|WorkspaceReferences|TurnAccepted|TurnCancelled|None|CurrentController|AttachExisting|UncontrolledTarget|Self|RuntimeIpcSessionRequirement|RuntimeIpcOperationRules|RuntimeSessionForkRequest|AgentContextReloadRequest|AgentDialogTurnRequest|AgentMessageWorkspaceReferencesRequest|AgentSessionCompactionRequest|AgentSessionCreateRequest|AgentSessionCreateResult|AgentSessionListRequest|AgentSessionModeUpdateRequest|AgentSessionModelUpdateRequest|AgentSessionRevertRequest|AgentSessionRevertResult|AgentSessionSummary|AgentTurnCancellationRequest|AgentTurnCancellationResult|AgentWorkspaceReference|AgentWorkspaceReferenceSearchRequest|AgentWorkspaceReferenceSearchResult|SessionTranscript|WorkspaceDiffSnapshot)\b)[A-Z][A-Za-z0-9_]*\b/,
message:
'agent-runtime-ipc may not add archive, replay, observer, general controller-transfer, or other operations beyond the reviewed Shared TUI slice',
},
Expand Down
Loading
Loading