diff --git a/AGENTS-CN.md b/AGENTS-CN.md
index 040e045b1..6d10cdacb 100644
--- a/AGENTS-CN.md
+++ b/AGENTS-CN.md
@@ -25,7 +25,7 @@ Stable Contracts and Security Control Plane 的边界以
|---|---|---|---|---|---|
| 1 | 接口与入口层 | `src/apps/*`, `src/web-ui`, `src/mobile-web`, `BitFun-Installer`, `tests/e2e`, `src/crates/interfaces` | 产品宿主、命令、UI 入口、协议接口和跨形态测试 | desktop、CLI、server、relay、Web UI、mobile web、installer、E2E、`acp`、`sdk-host` | 最近的本地 `AGENTS.md`;[interfaces](src/crates/interfaces/AGENTS.md) |
| 2 | 产品组装层 | `src/crates/assembly` | 兼容导出、产品能力选择、product-full 接线、adapter/service 注册和生态无关的来源协调 | `core`, `external-sources`, `product-capabilities` | [AGENTS.md](src/crates/assembly/AGENTS.md) |
-| 3 | 适配层 | `src/crates/adapters` | AI/transport/WebDriver 协议 adapter、外部 AI work source adapter(OpenCode/Claude Code/Codex)和外部 provider 转换 | `agent-runtime-ipc`、`ai-adapters`, `opencode-adapter`, `claude-code-adapter`, `codex-adapter`, `static-hook-support`, `transport`, `webdriver` | [AGENTS.md](src/crates/adapters/AGENTS.md) |
+| 3 | 适配层 | `src/crates/adapters` | AI/transport/WebDriver 协议 adapter、外部 AI work source adapter(OpenCode/Claude Code/Codex)和外部 provider 转换 | `agent-runtime-ipc`(仅迁移)、`ai-adapters`, `opencode-adapter`, `claude-code-adapter`, `codex-adapter`, `static-hook-support`, `transport`, `webdriver` | [AGENTS.md](src/crates/adapters/AGENTS.md) |
| 4 | 服务实现层 | `src/crates/services` | 可复用 OS、filesystem、terminal、MCP、remote、git、watch、process、LSP plugin registry、session persistence primitives、network 和 MiniApp runtime IO 实现 | `services-core`, `services-integrations`, `relay-service`, `page-function-runtime`, `terminal` | [AGENTS.md](src/crates/services/AGENTS.md) |
| 5 | 执行原语层 | `src/crates/execution` | 可移植 agent、harness、stream、DeepReview policy/report、插件运行时客户端、typed-service、tool-contract、tool-group 和 tool-execution 构件 | `agent-runtime`, `agent-stream`, `tool-contracts`, `harness`, `plugin-runtime-client`, `runtime-services`, `tool-provider-groups`, `tool-execution`, `tool-call-jsonrepair` | [AGENTS.md](src/crates/execution/AGENTS.md) |
| 6 | 稳定契约与产品领域层 | `src/crates/contracts` | 跨层共享 DTO、事件形状、runtime port、LSP protocol/plugin DTO、产品领域契约和策略 | `core-types`, `events`, `runtime-ports`, `product-domains` | [AGENTS.md](src/crates/contracts/AGENTS.md) |
@@ -191,13 +191,23 @@ await api.invoke('your_command', { request: { ... } });
仓库级拆解规则:
- 不要把 DTO / contract 抽取误判为 runtime owner 已迁移。
-- 产品表面可以有差异;共享稳定 facts 或 ports,不共享 UI、protocol、lifecycle 或平台实现。
+- 产品表面可以有差异;共享稳定 facts 或 ports。只有 Rich Client App Server consumer 等明确版本化的同一产品家族
+ 才共享 protocol;UI、lifecycle 和平台实现仍不共享。
- 迁移 runtime owner 必须有评审过的 port/provider 设计、旧路径兼容、行为等价测试;如果可能改变行为边界,还需要先确认。
涉及 Agent Runtime 部署、多 GUI/TUI/Remote 实例、共享 Session 控制或进程拓扑时,还必须阅读
[`docs/architecture/agent-runtime-deployment-design.md`](docs/architecture/agent-runtime-deployment-design.md)。
-Rust Runtime 或 Node/Bun Plugin Host 不得默认按 Client、workspace、session 或 plugin 分进程;进程边界必须来自真实状态
-owner、execution/security domain、可兼容的安全条件和测量后的容量事实。
+App Server 只存在 Embedded(一个 Client 对一个 Server)与 Shared(同一种 `client_kind` 的多个 Client 对一个
+Server)两种部署。Shared Rust Runtime 或 Node/Bun Plugin Host 不得默认按窗口、workspace、session 或 plugin 分进程;
+进程边界必须来自真实状态 owner、`client_kind`、execution/security domain、可兼容的安全条件和测量后的容量事实。
+
+涉及 Rich Client 前后端分离、Desktop 替换 Electron、VS Code Extension 接入、App Server schema/transport 或第一方 GUI
+进程拓扑时,还必须阅读
+[`docs/architecture/app-server-architecture-design.md`](docs/architecture/app-server-architecture-design.md)。Rich Client(包括交互式
+TUI)的 Embedded 与 Shared 部署共享同一 App Server wire,但领域契约仍归 Runtime/能力 owner。Embedded 只接受一个
+Client;Shared 只接受固定 `client_kind` 的多个 Client,TUI、Tauri Desktop、Electron Desktop、VS Code 和 Web 不得连接
+同一个实例;`client_kind` 表示具体宿主形态,不是宽泛界面类别。网络、租户和运维约束不形成 Hosted 第三形态。
+Headless CLI、ACP、SDK Host 保持独立协议和生命周期边界,不保留第二套 Shared TUI wire 或 handler。
### CLI 产品线护栏
diff --git a/AGENTS.md b/AGENTS.md
index 9b46c7507..c2a0a91e1 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -26,7 +26,7 @@ Keep crate dependencies inside each layer to the smallest set needed.
|---|---|---|---|---|---|
| 1 | Interfaces and entrypoints | `src/apps/*`, `src/web-ui`, `src/mobile-web`, `BitFun-Installer`, `tests/e2e`, `src/crates/interfaces` | Product hosts, commands, UI entrypoints, protocol interfaces, and cross-surface tests | desktop, CLI, server, relay, Web UI, mobile web, installer, E2E, `acp`, `sdk-host` | nearest local `AGENTS.md`; [interfaces](src/crates/interfaces/AGENTS.md) |
| 2 | Product assembly | `src/crates/assembly` | Compatibility exports, product capability selection, product-full wiring, adapter/service registration, and ecosystem-neutral source coordination | `core`, `external-sources`, `product-capabilities` | [AGENTS.md](src/crates/assembly/AGENTS.md) |
-| 3 | Adapters | `src/crates/adapters` | AI/transport/WebDriver protocol adapters, external AI work source adapters (OpenCode/Claude Code/Codex), and external-provider translation | `agent-runtime-ipc`, `ai-adapters`, `opencode-adapter`, `claude-code-adapter`, `codex-adapter`, `static-hook-support`, `transport`, `webdriver` | [AGENTS.md](src/crates/adapters/AGENTS.md) |
+| 3 | Adapters | `src/crates/adapters` | AI/transport/WebDriver protocol adapters, external AI work source adapters (OpenCode/Claude Code/Codex), and external-provider translation | `agent-runtime-ipc` (migration-only), `ai-adapters`, `opencode-adapter`, `claude-code-adapter`, `codex-adapter`, `static-hook-support`, `transport`, `webdriver` | [AGENTS.md](src/crates/adapters/AGENTS.md) |
| 4 | Services | `src/crates/services` | Reusable OS, filesystem, terminal, MCP, remote, git, watch, process, LSP plugin registry, session persistence primitives, MiniApp runtime IO, and network implementations | `services-core`, `services-integrations`, `miniapp-market-service`, `relay-service`, `page-function-runtime`, `terminal` | [AGENTS.md](src/crates/services/AGENTS.md) |
| 5 | Execution primitives | `src/crates/execution` | Portable agent, harness, stream, DeepReview policy/report, plugin runtime client, typed-service, tool-contract, tool-group, and tool-execution building blocks | `agent-runtime`, `agent-stream`, `tool-contracts`, `harness`, `plugin-runtime-client`, `runtime-services`, `tool-provider-groups`, `tool-execution`, `tool-call-jsonrepair` | [AGENTS.md](src/crates/execution/AGENTS.md) |
| 6 | Stable contracts and product domains | `src/crates/contracts` | Shared DTOs, event shapes, runtime ports, LSP protocol/plugin DTOs, and product domain contracts/policies | `core-types`, `events`, `runtime-ports`, `product-domains` | [AGENTS.md](src/crates/contracts/AGENTS.md) |
@@ -203,8 +203,9 @@ details in the nearest module `AGENTS.md`.
Repository-level decomposition rules:
- Do not confuse DTO/contract extraction with runtime owner migration.
-- Product surfaces may diverge; share stable facts or ports, not UI, protocol,
- lifecycle, or platform implementation.
+- Product surfaces may diverge; share stable facts or ports. Share a protocol
+ only inside an explicitly versioned product family such as Rich Client App
+ Server consumers, and never share UI, lifecycle, or platform implementation.
- Moving runtime ownership requires a reviewed port/provider design, old-path
compatibility, behavior equivalence tests, and explicit confirmation when a
behavior boundary could change.
@@ -212,9 +213,25 @@ Repository-level decomposition rules:
For Agent Runtime deployment, multi-GUI/TUI/Remote instances, shared Session
control, or process-topology changes, also read
[`docs/architecture/agent-runtime-deployment-design.md`](docs/architecture/agent-runtime-deployment-design.md).
-Do not key Rust Runtime or Node/Bun Plugin Host processes by client, workspace,
-session, or plugin by default; use the responsible state module, execution and
-security conditions, and measured capacity.
+App Server has only Embedded (one client to one server) and Shared (multiple
+clients of one `client_kind` to one server) deployments. Do not key Shared Rust
+Runtime or Node/Bun Plugin Host processes by window, workspace, session, or
+plugin by default; use the responsible state module, `client_kind`, execution
+and security conditions, and measured capacity.
+
+For Rich Client/backend separation, Desktop-to-Electron replacement, VS Code
+Extension integration, App Server schema/transport, or first-party GUI process
+topology, also read
+[`docs/architecture/app-server-architecture-design.md`](docs/architecture/app-server-architecture-design.md).
+Rich Clients, including interactive TUI, share one App Server wire across
+Embedded and Shared deployments, while domain contracts remain with their
+Runtime/capability owners. An Embedded server accepts exactly one client; a
+Shared server accepts multiple clients of one fixed `client_kind`, so TUI,
+Tauri Desktop, Electron Desktop, VS Code, and Web never connect to the same
+instance. `client_kind` identifies the concrete host form, not a broad UI
+category. Network, tenant, and operational constraints do not create a Hosted
+third deployment. Headless CLI, ACP, and SDK Host keep separate protocol and
+lifecycle boundaries; do not retain a second Shared TUI wire or handler.
### CLI product-line guardrails
diff --git a/docs/architecture/agent-runtime-deployment-design.md b/docs/architecture/agent-runtime-deployment-design.md
index 0cc7db915..e961efed0 100644
--- a/docs/architecture/agent-runtime-deployment-design.md
+++ b/docs/architecture/agent-runtime-deployment-design.md
@@ -1,399 +1,400 @@
# Agent Runtime 部署与多实例边界
-本文定义 Desktop、TUI、Headless CLI、Agent SDK 与本机控制端并存时,BitFun Agent Runtime 的部署、所有权和隔离边界。
+本文定义 Desktop、交互式 TUI、VS Code、Web、Headless CLI、ACP、Agent SDK 与 Remote
+并存时,BitFun Agent Runtime 的最终部署、所有权、并发和隔离边界。
-Agent Runtime 的模块职责见 [`agent-runtime-services-design.md`](agent-runtime-services-design.md),公开 SDK 见
+Agent Runtime 的模块职责见 [`agent-runtime-services-design.md`](agent-runtime-services-design.md),
+Rich Client 协议见 [`app-server-architecture-design.md`](app-server-architecture-design.md),公开 SDK 见
[`agent-sdk-product-architecture.md`](agent-sdk-product-architecture.md),第三方 JS/TS 进程见
[`extensions/plugin-runtime-design.md`](extensions/plugin-runtime-design.md)。
-## 1. 决策与当前状态
+> **状态说明**:第 1-7、9-10 节定义尚未实现的最终架构。第 8 节记录当前生产路径和逐项迁移;
+> 在对应退出条件满足前,`agent-runtime-ipc`、Tauri command 和既有 Server WebSocket 仍按各自
+> 当前合同维护。迁移完成后不得保留第二套 Shared TUI server/wire。
-BitFun 只有一套 Agent Runtime 行为。`Embedded` 和 `Shared` 只描述同一套 Runtime 的物理部署方式,不是两套实现。
+## 1. 最终决策
+
+BitFun 只有一套 Agent Runtime 行为。App Server 只存在 `Embedded` 和 `Shared` 两种部署形态;
+Headless CLI/CI 的进程内 Runtime 调用称为 `Direct Runtime`,不属于 App Server 部署。
```mermaid
flowchart TB
- subgraph "产品入口"
- GUI["Desktop GUI"]
- TUI["TUI / Headless CLI"]
- ACP["ACP"]
- SDK["Agent SDK · SDK Host"]
- Server["Server agent bootstrap"]
+ subgraph RichClients["First-party Rich Clients"]
+ GUI["Tauri / Electron / VS Code / Web"]
+ TUI["Interactive TUI"]
end
- GUI --> Adapter["同级 first-party adapters"]
- TUI --> Adapter
- ACP --> Adapter
- SDK --> Adapter
- Server --> Adapter
- Adapter --> API["Agent Runtime API"]
- API --> Coordinator["ConversationCoordinator"]
- Coordinator --> Owners["Session / Tool / Permission / MCP owners"]
- Coordinator -. "local attach / mutation" .-> Ownership["CoreRuntimeOwnership"]
+ Headless["Headless CLI / CI"]
+ ACP["ACP"]
+ SDK["Agent SDK"]
+ Remote["Server / Remote"]
+
+ GUI --> App["App Server adapter"]
+ TUI --> App
+ Headless --> Direct["Direct Runtime CLI adapter"]
+ ACP --> ACPA["ACP adapter"]
+ SDK --> SDKH["SDK Host adapter"]
+ Remote --> RemoteA["Server / Remote adapter"]
+
+ App --> API["Agent Runtime API"]
+ Direct --> API
+ ACPA --> API
+ SDKH --> API
+ RemoteA --> API
+ API --> Owners["Session / Turn / Tool / Permission / MCP owners"]
```
-当前代码状态必须和目标设计分开阅读:
-
-| 范围 | 当前状态 |
-|---|---|
-| Embedded Desktop GUI | 继续使用 Desktop 事件投影和 Tauri adapter;按实际打开的本机 workspace 延迟取得并持有 Embedded ownership,不增加后台进程 |
-| Embedded TUI/Headless CLI/Peer Host | Session、Turn、Permission 和事件订阅统一通过同一个 Rust Runtime SDK(当前 preview);CLI crate 只保留第一方 adapter 和各形态自己的展示/断流策略 |
-| ACP/SDK Host | 使用同一个 Runtime 事件入口的 session-scoped 订阅;各自协议和进程生命周期保持独立 |
-| Runtime ownership | Desktop、CLI、ACP、SDK Host 和现有 Server agent bootstrap 共用 Core owner;Embedded 取得共享锁,Shared TUI 取得独占锁,同一 workspace 上两种 deployment 互斥 |
-| 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 GUI/Headless/ACP/SDK Host/Remote | 未交付,也不会由 `--shared` 隐式启用;Replay、Observer、Controller transfer、Session delete/fork 同样不在当前协议中 |
+最终决策:
-因此当前交付的是一条窄的、显式启用的 Shared TUI deployment,不是通用本机 Server。具体 `EventQueue` 仍由 Core 产品装配;IPC 只把当前 TUI 必需的强类型操作和事件映射到同一个 Runtime owner,没有事件重放或公开协议承诺。
+1. Tauri、Electron、VS Code、Web 和交互式 TUI 是同一个 Rich Client 协议家族,统一经过
+ App Server。
+2. App Server 只支持 **Embedded** 和 **Shared**。Embedded 是一个 Client 对一个 Server;Shared 是同一种
+ `client_kind` 的多个 Client 对一个 Server。两种形态共享 schema、handler、Runtime API 和行为 conformance suite。
+3. `bitfun --shared` 只选择 Shared App Server instance,不选择另一套 TUI server 或 wire。
+4. Headless CLI/CI 默认 Direct Runtime,保留确定性启动、退出和故障隔离;它不为界面统一承担
+ 子进程和序列化成本。
+5. ACP、SDK Host 和 Server/Remote 保留独立协议与安全边界,但都映射同一 Runtime API 和
+ 行为 owner。
+6. Embedded 的 Client 数量固定为一;Shared 的 Client 数量不直接决定进程数,workspace 仍是 App Server
+ 内部 Runtime context 与 ownership lease 的隔离键。
+7. App Server instance 以产品身份、`client_kind`、数据命名空间、安全域、release channel、协议兼容范围和
+ execution domain 隔离;不同形态 Client 不能连接同一个 Shared instance,也不能在连接后改写实例级产品组装事实。
-## 2. 最少名词
+## 2. 名词与部署模式
| 名词 | 唯一含义 | 不等于 |
|---|---|---|
-| Agent Runtime | 负责 Session、Turn、Tool、MCP、Permission、Hook、事件和持久化行为的既有模块 | 进程名、Server 或 SDK |
-| Embedded deployment | Runtime 与调用入口位于同一 Rust 进程 | 简化版 Runtime |
-| Shared deployment | 同一 Runtime 由一个本机进程承载,多个第一方 Client 通过私有 IPC 使用 | 新 Runtime、公开 Server 或 Agent SDK |
-| Agent SDK Host | 将公开 SDK 合同映射到 Runtime API 的私有进程/adapter | CLI、Shared deployment 或 Plugin Host |
-| Plugin Host | 运行 Node/Bun 和第三方插件代码的受监督子进程 | Agent Runtime 或 Rust IPC client |
+| Agent Runtime | Session、Turn、Tool/MCP、Permission、Hook、Event 和持久化行为 owner | 进程名、Server 或 SDK |
+| Direct Runtime | Runtime 与非 App Server 入口位于同一 Rust 进程 | App Server Embedded 或公开 wire |
+| App Server | Rich Client 的版本化协议 adapter 和可部署 Runtime Host | 领域 owner、公共 SDK 或 Remote API |
+| Embedded App Server | 一个 Client 独占一个 App Server instance,Server 由该 Client Host 私有承载 | Direct Runtime、可发现共享进程或按窗口复制业务状态 |
+| Shared App Server | 同一种 `client_kind` 的多个 Client 连接一个 App Server instance 和 Runtime owner | 跨 TUI/GUI/IDE 混连、公开网络 API 或云同步 |
+| Network/tenant policy | 对 Embedded 或 Shared 的正交认证、授权、租户与 execution-domain 约束 | 第三种 Hosted 部署形态 |
+| SDK Host | 将公开 Agent SDK 合同映射到 Runtime API 的独立 adapter/process | App Server、CLI 或 Shared Runtime |
+| Plugin Host | 运行第三方 Node/Bun 插件代码的受监督进程 | Agent Runtime、App Server 或安全沙箱 |
-`Host` 只表示“一个进程承载某些模块”的内部关系,不新增普通用户必须理解或管理的产品入口。
+`Host` 表示进程承载关系,不要求普通用户理解或手工管理内部二进制。
-## 3. Logical View · Level 1
+## 3. 逻辑和开发视图
+
+### 3.1 单一行为核心
```mermaid
flowchart TB
- subgraph "逻辑层:始终只有一套"
- API["Agent Runtime API"] --> Session["Session / Turn"]
- API --> Permission["Permission"]
- API --> Tool["Tool / MCP"]
- API --> Events["Authoritative events"]
- end
-
- Embedded["Embedded adapter"] --> API
- Shared["Shared local IPC adapter · opt-in TUI"] --> API
+ App["App Server · Embedded / Shared"] --> API["Agent Runtime API"]
+ Direct["Headless Direct Runtime adapter"] --> API
+ ACP["ACP adapter"] --> API
SDK["SDK Host adapter"] --> API
- Remote["Remote adapter"] --> API
-```
-
-复用的是 Runtime API、权威事实和 owner;不复用 renderer、CLI 参数、SDK wire、远程认证或平台窗口生命周期。任何新能力必须先进入既有 Runtime owner,再由需要它的 adapter 映射,禁止在 Shared 路径复制业务实现。
+ Remote["Server / Remote adapter"] --> API
-### 3.1 Embedded 事件交付
-
-```mermaid
-flowchart LR
- Queue["EventQueue"] --> Owner["Core product event queue owner"]
- Owner -->|"injects read-only AgentEventSource"| Runtime["Agent Runtime API"]
- Runtime --> TUI["TUI adapter"]
- Runtime --> Exec["Headless adapter"]
- Runtime --> Peer["Peer fanout adapter"]
- Runtime --> ACP["ACP adapter"]
- Runtime --> SDK["SDK Host adapter"]
+ API --> Session["Session / Turn owner"]
+ API --> Permission["Permission owner"]
+ API --> Tool["Tool / MCP owner"]
+ API --> Events["Authoritative event source"]
```
-- Core product assembly 创建事件 source,并维持旧消费队列的排空 task;第一方产品入口不再获得第二个订阅 API。
-- TUI、Headless CLI 和 Peer Host 只从 `AgentRuntime` 订阅,不能直接持有 Core-specific event source。
-- `bitfun-core` 的旧 event-source/builder API 仅保留为 deprecated 源码兼容 facade;它们委托给同一个 Core owner,不形成第二套运行时或第一方调用路径。
-- 各 adapter 继续拥有自己的失败投影:TUI 标记当前视图不可信,Headless CLI 返回非成功终态,Peer Host 中断其拥有的 turns,ACP 取消 turn 并返回协议错误,SDK Host 终结 Query 并提供 `RestartHost` recovery。
-- 有界 receiver 的 `Lagged` 或 `Closed` 是显式失败;当前没有 cursor/replay 合同,禁止伪装成透明恢复。
-- 这条链路仍全部位于当前 Embedded 进程,不增加 SDK Host、IPC 或后台进程依赖。
-
-## 4. Process View · Level 1
+所有部署复用 Runtime API、权威事实和 owner。任何新能力必须先进入既有 owner,再由需要
+它的 adapter 映射。禁止在 App Server Shared handler、CLI adapter、SDK Host 或 Remote
+route 中复制业务校验和最终状态。
-### 4.1 Runtime ownership
-
-ownership 分成“产品决策”和“文件锁原语”两层;入口不再各自拼 key、目录或锁模式:
+### 3.2 代码依赖
```mermaid
flowchart TB
- Entrypoints["Desktop · CLI · ACP · SDK Host · Server bootstrap"]
- Entrypoints --> Core["CoreRuntimeOwnership
deployment · product identity · process-held lock"]
- Core --> Primitive["services-core::runtime_ownership
canonical key · RAII file lock"]
- Primitive --> E["Embedded · shared lock"]
- Primitive --> S["Shared · exclusive lock"]
+ Rich["Desktop / CLI-TUI / Web Hosts"] --> AppInterface["interfaces/app-server"]
+ Rich --> Transport["adapters/app-server-transport"]
+ AppProcess["apps/app-server"] --> AppInterface
+ AppProcess --> Assembly["assembly"]
+ AppInterface --> Contracts["contracts"]
+ Transport --> Contracts
+ Assembly --> Runtime["execution/agent-runtime"]
+ Assembly --> Services["services"]
+ Runtime --> Contracts
+ Services --> Contracts
```
-```mermaid
-flowchart TD
- Op["Session operation"] --> Read{"read-only view/list?"}
- Read -->|"yes"| NoLock["不取得 ownership"]
- Read -->|"no · attach/mutate/turn"| Remote{"structured remote facts?"}
- Remote -->|"yes"| RemoteHost["由目标 execution host 负责"]
- Remote -->|"no"| Gate["Coordinator → CoreRuntimeOwnership"]
- Gate --> Lock["按 canonical workspace 持有文件锁"]
-```
+- `interfaces/app-server` 拥有 Rich Client schema、typed client facade、版本和 capability
+ negotiation,不拥有 transport 或产品策略;
+- `adapters/app-server-transport` 拥有 in-memory、stdio、Named Pipe、UDS 和 WebSocket
+ 适配,不依赖 Runtime 实现或 `bitfun-core`;
+- App Server 组装根创建唯一 Runtime owner;Embedded 由 Client Host 私有承载,Shared 由可发现的
+ `apps/app-server` 实例承载;
+- Desktop、Electron Main、VS Code Extension Host 和 CLI/TUI Host 负责创建 Embedded 或发现同类 Shared
+ Server,不直接构造 Runtime;
+- Headless CLI/CI 使用独立 Direct Runtime composition,但调用相同 Runtime API;
+- `agent-runtime-ipc` 的 TUI-only operation/server 不是目标模块。可复用的 endpoint、framing、
+ discovery 原语应下沉到 App Server transport,旧 crate 在迁移后删除或改为无协议语义的
+ 内部 transport 实现。
-| 场景 | 行为 | 原因 |
-|---|---|---|
-| 多个 Embedded 进程访问同一 workspace | 共享锁允许并存 | 保持单实例、CI 和隔离测试的既有成本模型 |
-| Shared 与任一 Embedded 访问同一 workspace | 后启动者返回稳定错误码和启动建议 | 防止同一 workspace 同时存在两种 Runtime deployment |
-| Desktop 打开多个 workspace | 首次 attach/write 时逐个取得并持有文件锁 | 不把窗口数、Session 数等同于 Runtime 进程数 |
-| 只读 list/view | 不加锁 | ownership 只管理 Runtime deployment,不扩大成读取权限 |
-| 已解析且带有效 `connection_id` 的 remote workspace | 本机不加锁 | 与 Session storage 的远端判据一致;`host` 提示本身不能绕过本地锁 |
-| 当前只读 HTTP Server | 不创建 Core owner | 没有 Agent Runtime 就没有 ownership 可声明 |
+## 4. 物理部署
-`CoreRuntimeOwnership` 只选择 deployment、产品 identity 并在进程存活期间持有锁;`services-core` 只负责 canonical key 和跨进程锁。二者都不选择 workspace、不启动 Runtime,也不替代 Session 单写、数据库事务、文件冲突控制或安全沙箱。
+### 4.1 部署矩阵
-### 4.2 Session 单写
-
-workspace 可以被多个 Embedded 进程同时打开,但持久化 Session 不能被多个进程同时写入。保护粒度是“实际 Session 存储位置 + Session ID”,不是窗口、TUI 实例或 workspace。
+| 入口 | 默认部署 | 可选部署 | 协议 |
+|---|---|---|---|
+| Tauri Desktop | Embedded App Server | Tauri-only Shared App Server | App Server JSON-RPC |
+| Electron Desktop | Embedded App Server | Electron-only Shared App Server | App Server JSON-RPC |
+| VS Code Extension | Embedded App Server | VS Code-only Shared App Server | App Server JSON-RPC |
+| Interactive TUI | Embedded App Server | `--shared` 连接 TUI-only Shared App Server | App Server JSON-RPC |
+| Browser Web UI | Embedded App Server | Web-only Shared App Server | App Server JSON-RPC over authenticated WebSocket/HTTPS |
+| Headless CLI / CI | Direct Runtime | 无 | Rust Runtime API |
+| ACP | In-process ACP composition | 后续按 ACP 产品要求部署 | ACP wire |
+| Public Agent SDK | Managed SDK Host | 预启动兼容 SDK Host | SDK Host wire |
+| Remote | target-side Runtime Host | 受认证 Remote composition | Server/Remote wire |
+
+Headless CLI/CI 不作为 App Server client,也不接受 `--shared`。若未来需要非交互控制 Shared
+Session,必须另行定义命令入口、调用方角色、stdout/stderr 或 JSON/JSONL、退出码、取消、断线与
+`outcome_unknown` 合同,并通过兼容评审后再修改本矩阵;当前设计不预留半实现路径。
+
+Browser Web UI 不经公网连接用户本机 App Server。Web Backend 承载一个 Web Client 独占的 Embedded 实例,
+或多个 Web Client 使用的 Web-only Shared 实例;两者都使用独立网络认证、方法 allowlist、租户隔离、数据与
+execution domain。网络位置不产生 Hosted 第三形态。
+
+### 4.2 Embedded App Server
```mermaid
flowchart LR
- subgraph W["同一 workspace"]
- A["Session A"]
- B["Session B"]
- end
-
- GUI["GUI 进程"] -->|"写入"| A
- TUI["TUI 进程"] -->|"写入"| B
- CLI["另一个 CLI 进程"] -.->|"写入 A:session_in_use"| A
- View["任意入口的 list / view"] -.->|"只读"| A
- View -.->|"只读"| B
+ Client["One Rich Client"] --> Host["Trusted Client Host"]
+ Host -->|"create + exclusive channel"| App["Embedded App Server"]
+ App --> Runtime["Agent Runtime"]
+ Runtime --> Data["Workspace / Session storage"]
```
-BitFun Runtime Session 只有 `SessionManager` 决定何时开始和结束写入;底层持久化方法复用同一文件锁,不再实现第二套判断。各产品入口只投影同一个 `session_in_use` 事实,不重新判断锁状态:
+Embedded App Server 与一个 Client 一一绑定,由该 Client Host 私有创建和管理,不发布 discovery,也不接受
+第二个连接。实现可以同进程承载,也可以使用只对该 Client 可达的私有子进程;该选择不能改变一对一身份和
+生命周期合同。一个 Host 中若存在多个 renderer 或窗口,它们仍由一个逻辑 Client 汇聚后访问该 Server,不能让
+多个独立 Client identity 借 Embedded 之名共享实例。
-| 入口 | 冲突呈现 | 恢复方式 |
-|---|---|---|
-| Agent SDK / BitFun ACP | 结构化 `session_in_use`;SDK Host 映射为可重试的 `action_required` | 调用方在原实例关闭 Session 后重试 |
-| Embedded / Shared TUI | 明确提示 Session 已在另一实例打开;切换失败时保留当前 Session | 用户关闭另一实例后再次选择;不自动等待或切换 |
-| Desktop / Peer GUI | 历史视图保持只读可见;首次写入显示持久提示和显式“重试”操作 | 用户关闭另一实例后点击重试;不自动提交消息 |
-| Headless `json` | 失败结果带 `error_code=session_in_use`,详细说明进入结果和 stderr | 调用方依据稳定码决定是否重试 |
-| Headless `stream-json` | 复用已有 `SystemError`,`error=session_in_use`、`recoverable=true` | 调用方结束本次非零退出后重新执行 |
-
-Desktop 作为 ACP client 管理的外部 agent Session 不经过该 Runtime owner,不在本节的 Session 单写范围内。`recoverable` 只表示关闭现有 writer 后可以重新调用,不表示自动等待、自动抢占或恢复当前调用。
-
-| 场景 | 行为 |
-|---|---|
-| 同一进程重复 restore 同一 Session | 返回已加载的 Session,不重复取得或释放写入权 |
-| 另一个进程打开同一存储位置中的同一 Session | 立即返回 `session_in_use`;不等待、不自动抢占 |
-| 多个进程打开同一 workspace 中的不同 Session | 允许,各 Session 独立写入 |
-| 多个进程更新同一 Session 列表索引 | 按存储位置串行更新共享索引,不影响不同 Session 文件并行写入 |
-| `.`、`..`、符号链接或 Windows 路径大小写指向同一存储位置 | 视为同一个 Session 存储位置 |
-| 相同 Session ID 位于不同存储位置 | 文件锁相互独立;同一 `SessionManager` 仍按 Session ID 保持唯一绑定,不能同时加载 |
-| Session 存储路径无法解析或错误地指向文件系统根目录 | 在发布内存状态前返回错误,不创建可写 Session |
-| create/restore 在发布到内存前失败、取消或超时 | 临时文件锁随操作释放;后续进程可以重试 |
-| save、cleanup 或 unload 失败 | 已加载 Session 继续持有写入权,避免另一个进程接手不完整状态 |
-| unload 或 delete 成功 | 释放写入权 |
-| 进程崩溃或被强制结束 | 操作系统释放文件锁;残留锁文件本身不代表 Session 仍在使用 |
-| Remote workspace | 在实际 Session 存储所在机器执行同一检查;控制端不得用本机路径替代 |
-
-该机制不增加后台进程、轮询、连接或常驻线程,也不改变 Shared TUI 的连接控制规则。临时 Session 不写入磁盘,因此不参与此检查。
-
-### 4.3 私有本机 IPC
-
-```mermaid
-sequenceDiagram
- participant C as Shared TUI client
- participant D as User-private discovery
- participant S as Shared Runtime process
-
- C->>D: read endpoint + token + identity + protocol
- C->>S: connect via Named Pipe / UDS
- C->>S: initialize(identity, protocol, token)
- alt valid
- 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: submit/cancel Turn or answer Permission/UserInput
- S-->>C: Session-filtered authoritative events
- else invalid
- S-->>C: typed error and close
- end
-```
-
-当前私有协议(v5)只覆盖 TUI 已有用户旅程需要的窄操作:
-
-| 已支持 | 明确不支持 |
-|---|---|
-| Health、Session list/create、原子 restore(含 transcript 与 pending Permission)、当前 Session rename、Agent mode/model update | 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 |
-
-这些操作先满足以下本机 IPC 地基,而不把协议升级为公开 SDK:
-
-- workspace、产品、release channel、用户和协议版本共同生成实例身份;
-- instance lock 而不是 PID/discovery 文件决定唯一 server owner;
-- Windows 使用拒绝远程连接的 Named Pipe;Unix 使用短且由 instance identity 决定的稳定 Domain Socket 名称,权限为 `0600`;
-- discovery 所在目录必须由未来 composition 选择为当前用户私有目录;
-- discovery 通过同目录临时文件原子替换;Unix endpoint 保留原生路径字节,路径过长时在 bind 前返回明确错误;
-- 第一帧必须完成 token、instance identity 和 protocol version 校验;
-- 未认证握手预算为 2 秒;认证后的单次操作、响应写入和断线取消预算为 120 秒,避免坏客户端长期占用连接或 Runtime handler;
-- JSON frame 使用 4-byte 长度前缀;request 在发送前执行 128 KiB 上限(覆盖 TUI 已有的 64 KiB 粘贴输入及类型化信封),response/event 在序列化时执行 8 MiB 上限。超限返回类型化错误,不能进行无界分配;超过该上限的历史 Session 暂由 Embedded TUI 打开,不在本阶段引入分页协议;
-- 未认证连接也计入有界 connection budget,单个客户端不能无限制造 server task;
-- 未知 frame/operation 信封字段、未知 operation、错误身份和不兼容版本 fail closed;复用的 Runtime DTO 按其既有反序列化契约处理字段;
-- 一个连接最多控制一个 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。
-- 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 后代回收不在当前保证内。两者都只负责生命周期,不是安全沙箱。
-- 最后一个连接离开后等待 30 秒再退出;新连接会取消 idle 退出。退出只删除自己发布的 discovery;Unix 下继任 owner 会在持有实例锁后清理同一 identity 的陈旧 socket。
-
-这是一条本机同用户边界,不是沙箱、远程协议或公开兼容承诺。
-
-### 4.4 Serialization、并发与性能
+### 4.3 Shared
```mermaid
flowchart LR
- T1["TUI 1"] --> IPC["有界本机 IPC"]
- T2["TUI 2"] --> IPC
- TN["TUI N"] --> IPC
- IPC --> Runtime["一个 Shared Runtime"]
- Runtime --> Tasks["Tokio tasks"]
- Runtime --> Owner["一个 Session owner"]
+ TUI1["TUI client 1"] --> App["TUI Shared App Server"]
+ TUI2["TUI client 2"] --> App
+ App --> Contexts["Bounded Runtime context registry"]
+ Contexts --> W1["Workspace A context + lease"]
+ Contexts --> W2["Workspace B context + lease"]
+ W1 --> Data["Workspace / Session storage"]
+ W2 --> Data
```
-多个 Shared TUI 复用一个 Runtime 进程。每个连接使用独立异步任务,但连接、命令队列和事件队列都有上限;达到连接上限时暂停接收新连接,慢客户端不能建立无界任务或队列。默认不增加 Runtime 进程池,因为复制 Session 状态、模型连接和缓存会扩大一致性成本。只有经测量证明某类无状态 CPU 工作可独立分片时,才评审额外 worker 进程。
+Shared 与 Embedded 的区别只有:
-| 路径 | 数据边界 | 性能约束 |
-|---|---|---|
-| Embedded | 第一方 adapter 以 Rust 类型直接调用 `AgentRuntime` | 不初始化本机 IPC,不执行 JSON framing、序列化或反序列化 |
-| Shared request | Client 将 operation 编码一次并写入一个长度前缀 frame | 请求保持 128 KiB 上限;业务层只接收类型化 operation |
-| Shared response/event | Server 将结果或事件编码一次后写出 | 响应/事件保持 8 MiB 上限;超限使事件流明确失效,不能无界分配 |
-| Shared receive | 每个方向只有一个严格 transport decode 边界 | 未知信封字段和不兼容版本 fail closed;严格校验可以检查规范化 JSON,但不能把动态 JSON 传入 Runtime owner |
-| 多 TUI | 一个 Runtime、最多 64 个连接;每个 Client 的 command channel 容量为 64、event channel 容量为 256 | request gate 使每个 Client 同时只有一个请求进入 channel;事件落后时失效而非无限缓存 |
+- Shared 有稳定 instance identity、discovery 和多个认证连接;
+- Shared 的 drain 同时考虑 Client、Controller、Observer、活动 Turn、后台任务和 Remote 引用;
+- Shared 必须实施连接/请求/事件 budget、公平调度和慢客户端隔离;
+- Shared 支持同一种 `client_kind` 内的同一 Session 观察和受控写入。
-协议只承载当前交互所需的小型控制请求和既有事件。大 transcript 继续受 frame 上限约束;本阶段不为假设场景增加通用分页、二进制 side channel、压缩或批处理协议。
+Shared 不允许增加专用 method、DTO、事件或 handler。若某能力只适合 Shared,应通过
+capability negotiation 表达可用性,而不是分叉协议。
-## 5. Development and Physical Views · Level 1
+Shared instance 在创建时固定 `client_kind`,discovery key 和 initialize 都必须验证该事实。TUI、Desktop、
+VS Code 与 Web 即使使用相同 schema,也必须连接不同实例;跨形态 Session 接力依赖持久化恢复或显式 handoff,
+不依赖混连同一个 Server。
-### 5.1 Development View
+`client_kind` 按具体宿主形态分配,至少区分 `tauri-desktop`、`electron-desktop`、`vscode`、`tui` 和
+`web`。它不是可由 Client 自报的自由文本,也不能把 Tauri 与 Electron 合并成宽泛的 `desktop` 后共享实例。
-```mermaid
-flowchart TB
- GUI["GUI adapter"] --> API["Agent Runtime API"]
- TUI["TUI adapter"] --> API
- CLI["Headless CLI adapter"] --> API
- SDK["SDK Host adapter"] --> API
- ACP["ACP adapter"] --> API
- Server["Server adapter · when assembled"] --> API
- API --> Coordinator["ConversationCoordinator"]
- Coordinator --> Behavior["single behavior owners"]
-
- GUI -. "composition" .-> Ownership["CoreRuntimeOwnership"]
- TUI -. "Embedded / opt-in Shared" .-> Ownership
- CLI -. "Embedded" .-> Ownership
- SDK -. "Embedded" .-> Ownership
- ACP -. "Embedded" .-> Ownership
- Server -. "only when Runtime is assembled" .-> Ownership
- Ownership -. "injected once" .-> Coordinator
-```
+### 4.4 产品组装与实例隔离
-```mermaid
-flowchart LR
- CLI["apps/cli"] --> Client["CLI Runtime client"]
- Client -->|"Embedded"| Runtime["execution/agent-runtime"]
- Client -->|"Shared only"| IPC["adapters/agent-runtime-ipc"]
- IPC --> Handler["CLI Shared handler"]
- Handler --> Runtime
- Runtime --> Ports["runtime ports / owners"]
-```
+Embedded 与 Shared 使用唯一 App Server Delivery Profile 创建 Runtime;Embedded 由匹配 Client Host 承载,
+Shared 由 `apps/app-server` 或匹配服务端组装根承载。实例启动时固定产品组装结果、`client_kind`、数据命名空间、组织/用户安全域、release channel、
+Runtime Configuration 和 capability 上限;Client 握手只能声明前端与 Host capability,不能重选后端
+profile、产品策略、持久化根或内置扩展。
-CLI adapter 负责命令解析、TUI 状态和错误文案;私有 IPC 只负责本机传输、连接控制和类型映射;Agent Runtime 与 owner 负责 Session 校验、持久化和权威结果。业务代码通过同一个 CLI Runtime client 调用能力,不根据部署形态复制业务分支。
+因此只有同一种 `client_kind` 的多个 Client 可以共享一个兼容实例;Tauri Desktop、Electron Desktop、VS Code、
+TUI 和 Web 之间不得混连。不同产品身份、数据隔离域、安全策略、release channel 或 execution domain
+也必须使用不同实例。Shared 进程键来自 `client_kind` 与这些状态和安全事实,不来自窗口、workspace、
+Session 或 plugin 数量。一个 Shared App Server process
+可以承载多个 workspace,但不能让一个 workspace-bound Runtime object 改绑或跨 workspace 复用。
-- CLI 不依赖 SDK Host,GUI/TUI 也不依赖公开 SDK package。
-- 交互式 TUI 的启动页和会话页复用一个 CLI 私有 Runtime client;Session、Turn、Permission 和事件订阅都使用 Rust Runtime SDK(当前 preview)。该 client 只是第一方 adapter,不是公开 SDK、SDK Host client 或第二套 Runtime。
-- Headless CLI 和 Peer Host 使用同一 Runtime 订阅入口,但分别保留确定性退出与 Peer fanout 语义;共享订阅入口不等于共享 renderer 或产品生命周期。
-- TUI 不是 Server;未来是否连接 Shared deployment 是部署选择,不改变 TUI 的 renderer/键位职责。
-- Agent SDK Host 只服务外部 SDK 合同,不成为第一方 rich-client 的通用底座。
-- Headless CLI 默认继续 Embedded;CI 或测试可保持独立进程和独立 workspace,不承担后台实例成本。
-- Tauri 仍负责窗口和桌面能力;未来它可以管理 Shared process 的启动/重连,但不拥有 Agent Runtime 业务生命周期。
+## 5. Runtime ownership 与 Session 单写
-### 5.2 Physical View
+### 5.1 Workspace ownership
-```mermaid
-flowchart TB
- subgraph Embedded["默认 Embedded"]
- TUI["TUI / Headless / CI"] --> Direct["in-process Agent Runtime"]
- end
- subgraph Shared["显式 --shared"]
- Clients["one or more TUI processes"] -->|"Named Pipe / UDS"| SharedRuntime["Shared Runtime process"]
- end
- Direct --> Data["workspace + Session storage"]
- SharedRuntime --> Data
-```
-
-默认交互式 TUI、Headless CLI 和 CI 保持 Embedded。只有显式 `--shared` 的交互式 TUI 进入 Shared;同一 workspace 的两种部署互斥。多开 TUI 增加 Client 进程和有界连接,不按 Client 数量复制 Runtime、Session owner 或 Plugin Host。
-
-### 5.3 Scenario (+1) · Rename current Session
+`CoreRuntimeOwnership` 仍是本机 Runtime deployment 的权威 gate。目标 App Server 不把当前
+Shared deployment object 从单 workspace 强行改成多 workspace;它在实例内维护有界的 Runtime
+context registry,每个 context 独立绑定一个 workspace 与 lease:
```mermaid
-sequenceDiagram
- participant U as User
- participant T as TUI adapter
- participant C as CLI Runtime client
- participant R as Agent Runtime
-
- U->>T: /rename Auth refactor
- T->>T: trim + require idle Session
- T->>C: rename_session(id, name)
- C->>R: direct call or one Shared frame
- R->>R: validate ownership + persist
- R-->>C: applied / failed / outcome_unknown
- C-->>T: typed result
- T-->>U: update name only after applied
+flowchart TB
+ App["Embedded / Shared App Server"] --> Registry["Runtime context registry"]
+ Registry --> Core["CoreRuntimeOwnership per workspace context"]
+ Roots["Direct CLI · ACP · SDK Host"] --> Core
+ Core --> Primitive["services-core runtime ownership primitive"]
+ NetworkApp["Networked Embedded / Shared"] --> TenantOwner["tenant-scoped ownership provider"]
+ Remote["Remote Runtime Host"] --> RemoteOwner["target-host ownership provider"]
+ Primitive --> Lease["local ownership fact"]
+ TenantOwner --> TenantLease["tenant ownership fact"]
+ RemoteOwner --> RemoteLease["remote ownership fact"]
```
-Embedded 和 Shared 最终调用同一 `AgentRuntime::rename_session`。Runtime 只有在确认旧名称已保留时才返回明确失败;持久化恢复无法确认时,两种部署都返回 `outcome_unknown`。Shared 还会在请求已发送但权威响应丢失时返回该结果并关闭连接。用户恢复 Session、检查当前名称后再决定是否重试。
-
-## 6. 隔离和生命周期原则
-
-实例身份与 ownership key 分工不同:
-
-| 事实 | 用途 |
-|---|---|
-| canonical workspace + product | 防止 Embedded 与 Shared 同时拥有同一工作区 Runtime |
-| workspace + product + release channel + user + protocol | 定位兼容的本机 Shared instance |
-| stable local endpoint + bearer token + owner id | endpoint 定位同一 instance;随机 token 认证本轮 server;owner id 防止旧实例误删新 discovery |
-| 实际 Session 存储位置 + Session ID | 限制持久化 Session 的跨进程并发写入;不由 IPC 协议定义 |
-
-当前 Shared TUI 只有 controller,没有 observer 或 detached Query:一个 Client 关闭不会删除 Session;它会取消仍拥有的活动 Turn,只有取消得到确认才释放 Session 控制权,否则继续隔离该 Session,直到 Runtime 退出。最后一个 Client 关闭后,Runtime 进入 30 秒空闲期;期间重连可继续使用,超时后 Runtime 正常关闭。若未来增加后台任务、observer 或 Remote 引用,必须先扩展 Runtime-aware drain,不能把这些引用塞进当前简单连接计数。
-
-对普通单实例用户,未显式启用 Shared deployment 时不增加后台进程、连接、发现扫描或常驻内存。
-
-## 7. 能力扩展原则
-
-未来每增加一类 Shared 能力,都必须同时满足:
-
-1. 已有明确第一方 consumer 和用户旅程;
-2. 行为由现有 Runtime owner 提供,IPC 只映射 typed request/result/event;
-3. 定义权限、取消、deadline、断线、背压和副作用结果不确定性;
-4. Embedded 与 Shared 使用同一行为 fixture;
-5. 新能力不被顺带发布为 Agent SDK、Remote 或浏览器 API。
-
-Session/Turn、事件恢复、Permission/UserInput、Controller、配置管理和 Remote 应分别通过上述门槛,不能一次性加入一个“全量 Shared API”。
-
-当前 IPC crate 只是一条可删除的预集成边界:
-
-| 约束 | 当前决定 |
-|---|---|
-| 当前 consumer | 仅第一方交互式 TUI adapter;不自动包含 GUI、Headless CLI、Remote 或 SDK Host |
-| 稳定测试合同 | 本机 endpoint、initialize-first、128 KiB request / 8 MiB response-event 上限、连接上限、owner-checked cleanup、原子 Session controller 切换、单连接单活动 Turn、事件流失效后 fail closed、断连取消、30 秒空闲退出 |
-| 当前业务范围 | Session/Turn/transcript、当前 Session name/Agent mode/model、Permission/UserInput 的 TUI 必需子集;任何新增操作都需要真实 consumer 和 owner 等价测试 |
-| 协议地位 | crate 保持 `publish = false`;这是 workspace 内私有协议,不是 Agent SDK 或远程兼容承诺 |
-
-架构守卫只允许 CLI 消费该 crate;IPC 可以复用稳定的 Event、Product Domain 与 Runtime Port DTO,但禁止依赖 Runtime 实现、SDK Host、services、Tauri 或远程网络 transport。
-
-## 8. 与竞品的取舍
-
-| 产品 | 已验证做法 | BitFun 采用 | 不照搬 |
-|---|---|---|---|
-| [OpenCode Server/SDK](https://opencode.ai/docs/server/) | Server-first;类型化 SDK 直接消费 Server API | 一个 Runtime owner 可以服务多个第一方 Client | 不让默认 TUI 承担 HTTP/OpenAPI 编解码,也不把全量 route 固化为私有 Shared wire |
-| [Codex App Server](https://developers.openai.com/codex/app-server/) | App Server 为 rich client 和 remote TUI 提供 JSON-RPC;自动化继续使用 SDK;WebSocket transport 仍是实验性接口 | rich-client 私有协议与公开 SDK 分层,并为 Shared 入口保留有界本机 transport | 不让默认 CLI 依赖 App Server,也不复制其完整 schema 或实验性远程 transport |
-| [Claude Agent SDK](https://code.claude.com/docs/en/agent-sdk/typescript) | Agent loop 由长期运行的 CLI 子进程承载,并提供 `startup()` 预热以减少首次请求成本 | 长期交互可以复用已启动进程,空闲后回收 | 不让第一方 Embedded TUI 为接口统一付出子进程和编解码成本,也不把多 TUI 映射为多个 Runtime |
-
-三种产品说明了不同部署的有效边界:server-first 适合稳定多客户端协议,长期子进程适合语言 SDK,进程内调用适合默认本机交互。BitFun 采用混合部署,不把任何一种形态强制成所有入口的公共底座;当前也没有为了追赶功能表一次性增加 Session/Tool/Permission 超集。
-
-## 9. 不变量
+规则:
+
+- 本机 Embedded、Shared 和 Direct Runtime 使用 `CoreRuntimeOwnership`;服务端 Embedded/Shared 使用 tenant-scoped
+ provider,Remote 在目标 execution host 使用目标侧 provider,任何协议都不能绕过匹配的 ownership;
+- instance/discovery compatibility identity 可以包含 product identity、security domain、execution domain
+ 和协议兼容范围,但它不等于可变 workspace 资源的 ownership collision key;
+- workspace ownership collision key 必须保留当前 canonical workspace + product identity 的冲突等价关系。
+ security/execution domain 只能在其 workspace、持久化根和执行资源已物理隔离时进一步分区,不能仅凭
+ Client 声明或标签让同一现有资源取得第二把互不冲突的锁;
+- 当前 `services-core` key 只有 canonical workspace 与 product identity,当前 Shared owner 只允许一个
+ workspace。增加 registry 或升级 key 格式前必须先扩展 key/context 合同并保留旧行为;滚动迁移期间
+ 新 owner 同时取得旧 collision key 与新 key,直到旧 binary 退出兼容窗口。禁止通过跳过
+ `CoreRuntimeOwnership`、只取得新 key 或复用已绑定 Runtime 来支持第二 workspace;
+- registry 对 context 数量、空闲回收和并发创建有上限;同一 key 的并发 attach 原子复用一个 context,
+ 不同 key 独立取得、持有和释放 lease;最后一个 Client 断开不自动释放仍有 active Turn、Session writer、
+ 后台任务或恢复引用的 context;
+- Remote workspace 的 ownership 位于目标 execution host,本机不得静默取得替代 lease;
+- list/view 等只读操作可以不取得 mutation ownership,但仍需执行身份和访问控制;
+- Shared 与其他可写 Runtime deployment 的互斥由 Core owner 决定,不由 App Server route
+ 或 discovery 文件冒充。
+
+迁移验收必须覆盖:同一实例同时打开第二个本机 workspace、同 key 并发 attach、远程 workspace
+目标侧 ownership、Direct/Embedded/Shared 冲突、最后一个 Client 断开后的有界回收,以及进程重启后的
+ownership 恢复。任一项未通过时,一个 App Server instance 只能暴露一个 workspace。
+
+### 5.2 Session 单写
+
+持久化 Session 的保护粒度是“实际 Session 存储位置 + Session ID”。任何部署中同一 Session
+同时只能有一个权威 writer;Observer 可以读取投影,但不能提交 Turn、Permission 或 metadata。
+
+| 操作 | Controller | Observer |
+|---|---|---|
+| transcript/event view | 是 | 是 |
+| submit/cancel Turn | 是 | 否 |
+| respond Permission/UserInput | 是 | 否 |
+| rename/mode/model update | 是 | 否 |
+| transfer control | 发起或接受 | 接受后成为 Controller |
+
+Controller lease 属于 Runtime-aware App Server session attachment,不属于 transport socket。连接
+断开、重连或 transport 切换时,只有 Runtime 确认活动副作用已结算后才能释放控制权。
+
+## 6. 连接、并发与可靠性
-- 只有一套 Agent Runtime 业务实现;部署差异不能产生第二套 Session、Tool、Permission 或 MCP owner。
-- Client、窗口、Session 或 workspace 数量不会自动等量增加 Runtime 或 Plugin Host 进程。
-- 私有 IPC 不成为公开 SDK、Remote、Peer、HTTP 或浏览器协议。
-- 默认 GUI/TUI/Headless CLI、ACP 与 SDK Host 保持 Embedded;只有交互式 TUI 的显式 `--shared` 选择 Shared。互斥按 `workspace + product` 生效,不再按入口名称缩窄。
-- Account/session cloud sync 仍使用既有 Core compatibility 边界,不属于 Shared Runtime 支持。
-- Remote workspace 的文件、凭据、进程和 Runtime 位于目标执行域,禁止静默回落本机。
-- 未经真实 consumer 验证的接口不进入 wire;当前 wire 只包含表中列出的 Shared TUI 操作。
+### 6.1 初始化和认证
+
+- 第一帧完成协议范围、instance identity、client identity、认证和 Host capability 协商;
+- 第一帧还必须验证 deployment 与实例固定的 `client_kind`;Embedded 拒绝第二个 Client,Shared 拒绝
+ 不同 `client_kind`;
+- 本机 endpoint 使用 Windows Named Pipe 或 Unix Domain Socket,默认拒绝跨用户/远程连接;
+- Web 使用独立网络认证、租户/workspace 授权、Origin/CORS 和 method allowlist;
+- bearer token、凭据和 ownership key 不进入 URL、日志、renderer、事件或 transcript;
+- 未认证连接也计入 connection budget,防止资源耗尽。
+
+### 6.2 有界并发
+
+App Server 必须为以下资源设定可配置且有上限的 budget:
+
+- 总连接和每身份连接数;
+- 每连接并发 request 和 reverse request;
+- command、response 和 event queue;
+- request/response/event frame 大小;
+- 每 Session 活动 Turn、pending Permission/UserInput;
+- 全局模型调用、Tool/MCP 调用和后台任务。
+
+达到上限时返回类型化 `overloaded`、暂停接收或使慢连接失效,不能创建无界 task、channel
+或序列化缓冲。公平调度至少隔离不同 Client 和 Session,不能让一个慢 Observer 阻塞 Runtime
+或其他 Controller。
+
+### 6.3 取消和不确定结果
+
+- 请求 deadline 和 Client cancel 映射到 Runtime 既有取消树;
+- Client 断开不删除 Session,也不默认终止无关后台任务;
+- Controller 断开时请求取消其活动 Turn,只有得到权威结算后才释放 lease;
+- 请求发送前失败表示未执行;发送后响应丢失的副作用返回 `outcome_unknown`;
+- `outcome_unknown` 不自动重试,Client 重新读取权威状态或使用幂等 operation ID;
+- 无法确认取消结果时隔离 Session writer,直到 Runtime 恢复或退出。
+
+### 6.4 事件恢复
+
+- Runtime 提供唯一权威事件源,adapter 只做过滤、投影和脱敏;
+- event queue 有界,`Lagged`/`Closed` 是显式失效;
+- 首个稳定 Shared 版本必须提供 snapshot + cursor/resume,或明确以 snapshot 后新流恢复;
+- 不能把丢失事件伪装成透明成功;Permission/UserInput pending 集合必须可从 Runtime 权威状态重建;
+- event identity 在 Embedded/Shared 和各 `client_kind` 间保持一致,但这不允许跨类型混连实例。
+
+### 6.5 Runtime-aware drain
+
+App Server 退出不能只按 TCP/socket 连接数决定。Drain 至少考虑:
+
+- 已认证 Client 与重连 grace period;
+- Controller/Observer attachments;
+- 活动 Turn、Tool/MCP、Permission/UserInput;
+- Cron、长期任务和其他后台引用;
+- Remote 控制或恢复引用;
+- 持久化 flush、Plugin Host 与工具进程回收。
+
+Embedded 随唯一 Host 退出进入有界 drain;Shared 使用独立 idle policy。两者最终
+调用同一个 Runtime shutdown coordinator。
+
+## 7. Host capability 与 Remote
+
+App Server 通过初始化协商 Host capability。窗口、文件选择、剪贴板、终端窗口展示、截图和 Computer
+Use 等界面宿主操作以 reverse request 发送到当前操作绑定的可信 Host,不按“任意已连接 Client”
+广播。
+
+- capability route 绑定 client identity、operation、deadline 和 execution domain;
+- Observer 不能通过 Host capability 绕过 Controller 或 Permission owner;
+- capability 缺失返回类型化 `unsupported`;
+- PTY、Shell、命令执行、进程生命周期和取消属于 Runtime Services,不是 Host capability;
+- Remote workspace 的文件、终端执行、凭据、进程和 Runtime 在目标 host 执行;
+- 本机 App Server transport 不自动成为 Remote transport,Remote 复用业务 DTO 但保留认证、
+ 网络恢复和租户隔离合同。
+
+## 8. 迁移与删除
+
+当前实现只提供迁移证据,不决定最终模块边界:
+
+- 交互式 TUI 当前默认使用 legacy in-process Runtime,显式 `--shared` 使用 `agent-runtime-ipc`;
+- 当前 Shared owner 在创建时绑定一个 workspace,第二 workspace 返回
+ `shared_runtime_workspace_mismatch`;
+- 当前 ownership key 只包含 canonical workspace 与 product identity,尚无 security/execution domain;
+- App Server assembly、transport、backend profile 和多 workspace registry 均未创建。
+
+1. 将 Shared TUI 已验证的 controller lease、认证、framing 上限、断连取消、事件失效、
+ `outcome_unknown` 和 cleanup fixture 提升为 App Server conformance tests;
+2. App Server 首先完成 Session/Turn/Permission/UserInput 纵向切片,并让 Desktop 和交互式
+ TUI 使用同一 typed client;
+3. 默认 TUI 创建独占 Embedded App Server,`--shared` 连接 TUI-only Shared App Server;
+4. 把真正通用的 Named Pipe/UDS、discovery 和有界 framing 原语迁入
+ `app-server-transport`;
+5. 删除 `agent-runtime-ipc` 的 TUI-specific operation、handler、server 和协议测试;
+6. 删除旧 Tauri 业务 command、私有 WebSocket 信封和重复事件映射前,使用共同 fixture
+ 证明行为等价并保留有界回滚期;
+7. Headless CLI/CI、ACP 和 SDK Host 不在本迁移中绕行 App Server;Headless `--shared` 继续拒绝。
+
+迁移结束的删除条件是:仓库内不存在第二套第一方 Rich Client Session/Turn/Permission
+wire、第二个 Shared server 入口或按 TUI/GUI 分叉的 App Server handler。
+
+## 9. 验收门槛
+
+最终部署架构至少通过:
+
+1. Tauri、Electron/VS Code 样例和交互式 TUI 使用同一 schema、typed client 和 handler;
+2. Embedded 与 Shared 使用同一行为 fixture,只有承载、连接数和 discovery fixture 不同;
+3. TUI `--shared` 不引用独立 Shared TUI operation/server;
+4. Controller/Observer、control transfer、断连取消和 Session 单写有并发测试;
+5. 多 workspace registry 覆盖第二 workspace、远程域、并发 attach、Direct/Embedded/Shared 冲突、旧新 key
+ 混合版本冲突、断连回收和重启恢复;
+6. request/event budget、慢 Client 隔离、公平调度和 overload 有压力测试;
+7. `outcome_unknown`、幂等 operation、snapshot/cursor 恢复有故障注入测试;
+8. Runtime-aware drain 覆盖活动 Turn、后台任务、Remote 引用和进程树回收;
+9. Embedded 单连接拒绝、Shared `client_kind` 隔离、本机认证、Web 认证、Host capability route 和 Remote execution domain 有安全测试;
+10. Headless CLI/CI 的 Direct Runtime 启动、退出和性能不因 App Server 迁移退化;
+11. 旧 Shared TUI wire、旧 Tauri 业务桥和重复 WebSocket schema 有明确删除证据。
+
+## 10. 不变量
+
+- 只有一套 Agent Runtime 行为 owner;
+- 所有第一方 Rich Client,包括交互式 TUI,只使用 App Server wire;
+- App Server 只存在 Embedded 与 Shared;网络、租户和运维约束不形成 Hosted 第三形态;
+- Embedded 恰好一个 Client 对一个 Server;Shared 多个 Client 对一个 Server,但固定一个 `client_kind`;
+- 不存在长期 Shared TUI server、Shared GUI server 或按前端分叉的 Runtime API;
+- Headless CLI/CI 默认 Direct Runtime;ACP、SDK Host 和 Remote 保留独立协议边界;
+- App Server、SDK Host、Plugin Host 和 Remote Host 是不同进程职责;
+- workspace ownership、Session 单写、权限、取消和审计始终由既有 owner 决定;
+- Shared 中 Client、窗口、workspace、Session 或 plugin 数量不自动等量增加 App Server/Plugin Host 进程;
+ App Server 内每个 workspace 仍有独立 Runtime context 和 ownership lease;
+- Remote workspace 不静默回落本机;
+- 未有真实 consumer、失败语义和验证的 method/capability 不进入稳定协议。
diff --git a/docs/architecture/agent-runtime-services-design.md b/docs/architecture/agent-runtime-services-design.md
index 645755e77..ccb9d77c8 100644
--- a/docs/architecture/agent-runtime-services-design.md
+++ b/docs/architecture/agent-runtime-services-design.md
@@ -9,8 +9,9 @@ CLI Agent 体验边界见 [`cli-product-line-design.md`](cli-product-line-design
多宿主 adapter 的状态、权限、并发和兼容边界见
[`capability-runtime-integration-design.md`](extensions/capability-runtime-integration-design.md);公开 BitFun Agent SDK 的
用户心智、SDK Host、Headless CLI/ACP/Server 关系、竞品基线和能力发布门槛见
-[`agent-sdk-product-architecture.md`](agent-sdk-product-architecture.md);第一方 GUI/TUI/Remote 多实例、Headless CLI Embedded、
-Shared Agent Runtime 与 Plugin Host 的进程关系见
+[`agent-sdk-product-architecture.md`](agent-sdk-product-architecture.md);第一方 Rich Client(包括交互式 TUI)的统一协议见
+[`app-server-architecture-design.md`](app-server-architecture-design.md);Embedded/Shared App Server、Headless Direct Runtime、
+Remote 与 Plugin Host 的进程关系见
[`agent-runtime-deployment-design.md`](agent-runtime-deployment-design.md)。
本文中的接口片段只说明依赖方向和职责,不自动构成当前 API 或实施承诺。当前接口名称、字段和消费方以代码为准;
@@ -744,8 +745,10 @@ Core 的 Network、Git 和 MCP Catalog 当前仍含兼容 marker,因此该诊
但完整持久化历史回放、模型/模式目录与提供方配置和 MCP 仍走单一 Core 兼容接口;会话模型/模式写入通过 Agent Runtime API 回到同一 Core 归属模块。ACP stdio、连接和协议转换仍在
`interfaces/acp`。Desktop 复用同一 Core owner 构造一个窄口径 Rust Runtime SDK,主界面的轮次提交/取消、工具确认/拒绝和
用户问题回答与会话模型更新已通过 Rust Runtime SDK;会话 CRUD/恢复视图、MCP、MiniApp、Cron、远程连接、Tauri 窗口与平台资源
-仍保留在 Desktop/Core 兼容入口。Server 仅提供健康检查、信息与 ping 路由。未接入入口的 profile、枚举分支和
-单元测试仍不能证明对应产品形态可用。
+仍保留在 Desktop/Core 兼容入口。Server 提供健康检查、信息与 ping,以及不启动 Agent Runtime 的窄
+detached-dispatch controller/observer 路由;该 loopback WebSocket 控制面会使用已保存的 SSH connection
+执行 install、submit、cancel、answer、append 等可变操作,不等于完整 Server profile 或独立产品组装。
+未接入入口的 profile、枚举分支和单元测试仍不能证明对应产品形态可用。
Desktop 与 CLI Peer Host 还各自注入同一个 Core-backed `LocalWorkspaceSnapshotPort` 契约。它是两个本地宿主之间的内部 owner 边界,
不是公开 Agent SDK、Agent Runtime API 的通用能力、完整 Desktop profile、跨宿主远程能力或通用 checkpoint/rewind API。Core 继续持有 `SnapshotManager`、工具拦截、
diff --git a/docs/architecture/agent-sdk-product-architecture.md b/docs/architecture/agent-sdk-product-architecture.md
index 6d046d3ee..a809e314c 100644
--- a/docs/architecture/agent-sdk-product-architecture.md
+++ b/docs/architecture/agent-sdk-product-architecture.md
@@ -7,7 +7,9 @@
[`cli-product-line-design.md`](cli-product-line-design.md) 定义;扩展能力导入和宿主适配由
[`capability-runtime-integration-design.md`](extensions/capability-runtime-integration-design.md) 定义;多个第一方界面与 SDK/CLI
并存时的 Runtime 部署、共享和进程隔离由
-[`agent-runtime-deployment-design.md`](agent-runtime-deployment-design.md) 定义。
+[`agent-runtime-deployment-design.md`](agent-runtime-deployment-design.md) 定义;Tauri、Electron、VS Code Extension、Web 等
+第一方 Rich Client 的统一协议由
+[`app-server-architecture-design.md`](app-server-architecture-design.md) 定义。
本文只记录长期产品心智、架构边界和发布门槛。当前代码中的
`agent-runtime::sdk` 是供 BitFun 内部入口和受控 Rust 嵌入使用的低层 Rust Runtime SDK;
@@ -21,7 +23,7 @@ BitFun 不选择“复制 Claude”“复制 OpenCode”或“复制 Codex”中
| 问题 | 采用的成熟做法 | BitFun 决策 |
|---|---|---|
| 用户如何运行 Agent | Claude Agent SDK 的 Agent、Session、消息流、Tool、MCP、Permission、Hook 心智 | 公开 API 使用行业常见 Agent 概念,不暴露内部端口、协议和 Product Assembly |
-| 如何让多个产品入口共享能力 | OpenCode 的 Server/Core 多客户端模式,Codex App Server 的 rich-client 边界 | 所有入口调用同一 Agent Runtime API;入口是同级 adapter,不相互依赖 |
+| 如何让多个产品入口共享能力 | OpenCode 的 Server/Core 多客户端模式,Codex App Server 的 rich-client 边界 | 所有入口调用同一 Agent Runtime API;GUI/Web/交互式 TUI 共享 App Server wire,SDK/ACP/Headless CLI 保持同级独立 adapter |
| SDK 如何保持简洁 | Codex SDK 的精选 Thread/Turn 用例,而不是全量管理 API | 公开 SDK 只提供 Agent 应用所需的高层用例,不直接镜像内部或 Server 全部路由 |
| 本地 Runtime 如何交付 | Claude/Copilot SDK 管理匹配原生 runtime,Codex App Server 的握手与 schema 纪律 | SDK 默认管理匹配的本地 `bitfun-sdk-host`;用户不需要安装 CLI |
| 多语言如何一致 | Copilot SDK 的单协议、多语言包、协议版本范围和 codegen drift check | Python/TypeScript 是同一 SDK 的语言绑定,共用一个 Host 协议和一致性套件 |
@@ -30,7 +32,7 @@ BitFun 不选择“复制 Claude”“复制 OpenCode”或“复制 Codex”中
一句话定义:
> BitFun Agent SDK 是同一 BitFun Agent Runtime 面向应用开发者的公开开发接口;它不是新的 Runtime,
-> 不是 CLI/Server 的别名,也不是 GUI/TUI 的底层依赖。
+> 不是 CLI/Server/App Server 的别名,也不是 GUI/TUI 的底层依赖。
最终只向普通用户和外部开发者呈现三种产品选择:
@@ -61,7 +63,7 @@ Codex 代码基线为
| Runtime 交付 | Python/TS 包携带原生 Claude Code binary | SDK 可启动 PATH 中的 Server,也可连接已有 Server | TS SDK 包装 CLI JSONL;App Server 提供更完整协议 | SDK 通过 JSON-RPC 管理 CLI server;部分语言包携带 CLI | 安装 SDK 后应得到匹配 Host,但 CLI 与 SDK Host 不能混为一个产品 |
| 能力深度 | 内置 Tool、MCP、Hook、权限、Subagent、Skill、Plugin、Session、用量 | Project/Session/File/TUI/MCP/Provider 等广泛 Server API | SDK 精简;App Server 有审批、动态工具、事件、配置和稳定/实验分层 | Session、工具、Hook、权限、事件等经协议开放 | GA 能力下限参考 Claude,协议纪律参考 Codex/Copilot |
| 生态发展 | 官方 Python/TS SDK 和完整能力文档;生态围绕 Claude Code 配置与插件 | 开源 Core/Server、Provider/Plugin 生态及 TUI/Web/Desktop/IDE 多客户端 | 开源 Runtime/App Server 快速演进;TS SDK 走 CLI JSONL,Python SDK 绑定匹配 Runtime/App Server | 六种语言包、统一协议和各语言 registry | 首版聚焦 Python/TS,但合同从第一天按可增加语言设计;不把某一语言实现当规范 |
-| 多客户端/UI | SDK 示例为主,官方不提供通用 UI SDK | TUI/Web/Desktop/IDE 共享 Server;SDK 可控制 TUI | App、CLI、SDK 分层;App Server 面向 rich client | 面向各语言应用,无统一组件层 | BitFun 第一方界面直接用 Runtime API,外部 UI 经开发者后端使用 SDK |
+| 多客户端/UI | SDK 示例为主,官方不提供通用 UI SDK | TUI/Web/Desktop/IDE 共享 Server;SDK 可控制 TUI | App、CLI、SDK 分层;App Server 面向 rich client | 面向各语言应用,无统一组件层 | BitFun Rich Client 经 App Server、其他第一方入口经各自 adapter 使用 Runtime API;外部 UI 经开发者后端使用 SDK |
| 多语言 | Python/TypeScript,部分能力存在语言时差 | 官方主要 JS/TS,OpenAPI 可生成其他客户端 | TS 与 Python 当前底层形态不同 | TS/Python/Go/.NET/Java/Rust,共用协议版本 | 不能让 Python/TS 各写一套 transport 和行为 |
| 可定制程度 | callback、Tool、Hook、MCP、Agent/Skill/Plugin 配置 | Server 全资源控制和插件生态,最开放 | 精选 SDK 较克制,App Server 更底层 | 多语言自定义 Tool/Hook | 公开 API 保持精选;高级资源管理通过明确 capability 增量开放 |
| 发布渠道 | npm、PyPI,包内携带 binary | npm SDK;Server 由 OpenCode 安装提供 | npm SDK、PyPI SDK/Runtime、Codex CLI | npm、PyPI、NuGet、Go module、Maven、crates.io | 语言包走原生 registry;Host 版本必须与 SDK 可验证匹配 |
@@ -161,6 +163,7 @@ flowchart TB
| 层次 | 使用者 | 状态与职责 |
|---|---|---|
| Agent Runtime API | BitFun 各产品 adapter | 唯一 Agent loop 与应用用例边界;不是语言包 |
+| Rich Client App Server | Tauri/Electron/VS Code/Web | 第一方交互界面的版本化 wire;不是公开 Agent SDK |
| Rust Runtime SDK | BitFun 内部入口、受控 Rust 嵌入 | 当前 preview;不等于公开产品 |
| BitFun Agent SDK | Python/TypeScript 应用开发者 | 一个公开产品、多个语言绑定;尚未交付 |
@@ -172,12 +175,12 @@ Python SDK、TypeScript SDK、managed Host 和连接预启动 Host 不是四种
```mermaid
flowchart TB
- GUI["GUI / TUI"] --> UIA["UI adapter"]
+ GUI["Tauri / Electron / VS Code / Web / Interactive TUI"] --> App["Rich Client App Server"]
CLI["bitfun exec"] --> CLIA["CLI adapter"]
SDK["Agent SDK"] --> SDKA["SDK Host"]
ACP["ACP"] --> ACPA["ACP adapter"]
Server["Server / Remote"] --> RemoteA["Server / Remote adapter"]
- UIA --> API["Runtime API"]
+ App --> API["Runtime API"]
CLIA --> API
SDKA --> API
ACPA --> API["Runtime API"]
@@ -191,23 +194,27 @@ flowchart TB
### 4.2 互操作入口
-上图中的 ACP、Server/Remote 和 SDK Host 都是同级 adapter;虚线只表示第一方进程装配 ownership,不表示某个入口依赖另一个入口。
+上图中的 App Server、Headless CLI、ACP、Server/Remote 和 SDK Host 都是 Runtime API 之上的同级 adapter;虚线只表示第一方进程
+装配 ownership,不表示 SDK Host 或 ACP 依赖 App Server。
上图固定四条架构结论:
-- GUI/TUI/CLI 同样使用 Query、MCP、Permission 和 Hook,但它们直接经过各自 adapter 调用共享 Runtime API,
- 不依赖 Python/TypeScript SDK,也不依赖 SDK Host。
+- Tauri/Electron/VS Code/Web/交互式 TUI 等 Rich Client 经 App Server 调用共享 Runtime API;Headless CLI 经过自己的
+ Direct Runtime adapter。它们都不依赖 Python/TypeScript SDK,也不依赖 SDK Host。
- SDK Host 是跨进程/跨语言 adapter,不拥有 Session、Tool、MCP、Permission、Hook 或 Event 状态。
-- 各入口共享业务事实和 owner,不共享 renderer、命令行参数、wire protocol 或平台生命周期。
+- Rich Client 的 Embedded 与 Shared deployment 共用 App Server wire;每个 Shared instance 固定一种 `client_kind`。
+ SDK Host 和 ACP 保持各自 wire,Headless CLI 默认 Direct Runtime。所有入口共享业务事实和 owner,不共享 renderer、
+ 命令行参数或平台生命周期。
- 增加 SDK 不得让 CLI、GUI/TUI 或 Server 的底层依赖变深;它只增加一个同级入口。
-该图表达逻辑依赖,不要求所有入口位于同一进程。目标部署中,GUI/TUI/本机 Remote 可以连接第一方 Shared Agent Runtime;
-一次性 Headless CLI 继续 Embedded;公开 SDK 默认连接私有 SDK Host。Shared Agent Runtime process 和 SDK Host 都是 Rust 产品进程,
-与运行第三方 JS/TS 的 Node/Bun Plugin Host 不同;三者不能共享名称或业务归属。
+该图表达逻辑依赖,不要求所有入口位于同一进程。目标部署中,Rich Client Host 创建独占 Embedded 或连接匹配
+`client_kind` 的 Shared App Server;交互式 TUI 的 `--shared` 与 GUI/IDE Shared 复用 schema/handler,但连接不同实例,
+不存在独立 TUI wire。一次性 Headless CLI 继续 Direct Runtime,公开 SDK 默认连接私有 SDK Host。App Server 承载单元和 SDK Host
+process 都由 Rust 实现,但合同和生命周期不同;它们与运行
+第三方 JS/TS 的 Node/Bun Plugin Host 也不能共享名称或业务归属。
-当前代码已经交付显式启用的 Shared TUI 最小切片,包含本机 IPC、身份、握手、Session/Turn、当前 Session 的 name/Agent mode/model、Permission/UserInput、
-ownership 和生命周期治理;GUI、Headless CLI、ACP、SDK Host、Server/Remote 仍没有 Shared consumer。该图中的多入口逻辑复用是
-当前事实,除 Shared TUI 外的跨进程 Shared deployment 仍是目标架构。
+当前 Shared TUI IPC 的身份、握手、Session/Turn、Permission/UserInput、ownership 和生命周期实现只作为 App Server
+Shared conformance 的迁移证据;最终由统一 App Server 替代并删除独立 wire/server。
### 4.3 各形态能做什么
@@ -233,7 +240,7 @@ flowchart LR
API --> Runtime["Single Agent Runtime and owners"]
```
-本图只放大 SDK 特有的跨进程路径;GUI/TUI、CLI、ACP 和 Server 的同级 adapter 关系以第 4 节产品视图为准,
+本图只放大 SDK 特有的跨进程路径;App Server、Headless CLI、ACP 和 Server 的同级 adapter 关系以第 4 节产品视图为准,
不在这里再次折叠或定义。
依赖约束:
@@ -241,7 +248,8 @@ flowchart LR
| 组件 | 必须 | 禁止 |
|---|---|---|
| `bitfun` CLI | 依赖共享 Runtime/Application 能力 | 依赖 SDK Host app、SDK protocol 或公开语言包 |
-| GUI/TUI | 依赖共享应用用例和各自平台 adapter | 经公开 SDK 绕行 Runtime;共享 renderer/protocol |
+| Rich Client GUI | 依赖 App Server typed client 和各自可信 Host | 经公开 SDK 绕行 Runtime;把平台对象或 App Server token 交给 renderer |
+| Interactive TUI | 依赖 App Server typed client 和 CLI/TUI Host | 禁止经公开 SDK/SDK Host 绕行 Runtime;禁止另建 Shared TUI wire |
| `bitfun-sdk-host` | 独立组装入口,选择 SDK profile | 依赖 CLI crate;成为第二个 Server 或 Runtime |
| SDK Host adapter | 协议、能力协商、连接/Query 资源清理责任和 DTO 转换 | stdin/stdout 入口、Agent 业务状态、Tool/MCP 注册表 |
| Python/TypeScript SDK | 管理或连接匹配 Host,提供一致公开 API | 要求用户安装 `bitfun` CLI;暴露内部 wire DTO |
@@ -472,9 +480,11 @@ CLI 和 SDK 共享能力事实,但不是上下层关系:
因此:
- CLI 不默认依赖 SDK Host,也不通过 SDK package 运行。
-- CLI、ACP、Desktop 与 SDK Host 只共享 Core ownership 和 Runtime 行为 owner;共享这些内部 owner 不构成产品依赖,也不新增第二种 SDK。
-- 一次性 `bitfun exec` 默认使用 Embedded Runtime;只有恢复或控制 Shared Agent Runtime 中的共享 Session 时,才使用第一方
- client adapter attach,且不经过 SDK Host。
+- Headless CLI、ACP、App Server/Desktop/TUI 与 SDK Host 只共享 Core ownership 和 Runtime 行为 owner;共享这些内部 owner 不构成产品依赖,
+ 也不新增第二种 SDK。SDK Host 不依赖 App Server schema 或 handler。
+- 一次性 `bitfun exec` 只使用 Direct Runtime,不作为 App Server client;当前 `--shared` 只允许交互式 TUI。
+ 若未来需要非交互控制 Shared Session,必须单独版本化命令、角色、输出、退出码、取消和断线合同,不能从
+ App Server 或 SDK Host 的存在推导支持。
- SDK 不解析 CLI `stream-json` 作为正式双向协议。
- 普通脚本/CI 不需要为了“架构统一”改写成 SDK;复杂生产自动化才选择 SDK。
- 两者使用共同的行为样例验证相同配置、权限和 Tool 结果,但 flags、事件格式和传输方式可以不同。
@@ -651,7 +661,7 @@ GA 必须同时满足:
- TypeScript 和 Python 至少各有一个仓库外真实消费者,并通过同一 conformance suite。
- SDK/Host 安装、升级、版本不匹配、崩溃、取消和完整进程树回收通过 Windows/macOS/Linux 验证。
- Session resume/fork、structured output、usage、Tool/MCP/Permission/Hook/UserInput callback 有端到端样例。
-- CLI 与 SDK 共同 fixture 证明业务事实一致,但 CLI 仍不依赖 SDK Host。
+- Headless CLI、App Server 与 SDK 共同 fixture 证明业务事实一致,但 Headless CLI 和交互式 TUI 都不依赖 SDK Host。
- schema drift、stable/experimental、capability negotiation、错误码和兼容矩阵进入发布门禁。
- API 参考、快速开始、迁移说明、安全模型和外部 UI 参考架构完整。
@@ -660,7 +670,7 @@ GA 必须同时满足:
- 不提供 Claude Agent SDK 的 import-compatible 或 source-compatible 替换包。
- 不发布多个互不兼容的“本地 SDK”“远程 SDK”“UI SDK”。
- 不让 CLI、GUI/TUI、ACP 或 Server 依赖公开 Python/TypeScript SDK 或 SDK Host。
-- 不把 `stream-json`、ACP 或 HTTP Server 全量路由冒充正式 Agent SDK。
+- 不把 App Server typed client 称为公开 Agent SDK,也不把 `stream-json`、ACP、App Server 或 HTTP Server 全量路由冒充正式 Agent SDK。
- 不发布 BitFun 第一方 React UI 作为稳定 SDK ABI。
- 不把 OpenCode/Claude/Codex 原始插件对象、Hook payload 或配置类型带入 Runtime 公共合同。
- 不在没有真实消费者、owner 和失败语义时建立通用工作流、HookBus、远程 SDK transport 或公共 Capability SDK。
diff --git a/docs/architecture/app-server-architecture-design.md b/docs/architecture/app-server-architecture-design.md
new file mode 100644
index 000000000..94673e80f
--- /dev/null
+++ b/docs/architecture/app-server-architecture-design.md
@@ -0,0 +1,546 @@
+# BitFun App Server 架构设计
+
+本文定义 BitFun 面向第一方 Rich Client 的统一后端协议边界。它服务于 Desktop GUI、
+Electron、VS Code Extension、Web UI、交互式 TUI 和未来其他交互式客户端,使前端框架可以替换、前后端
+可以独立演进,同时保持产品逻辑、状态所有权和平台能力边界不变。
+
+本文是 [`product-architecture.md`](product-architecture.md) 的专题展开;Agent Runtime 的
+Direct Runtime、Embedded App Server 与 Shared App Server 所有权和进程约束以
+[`agent-runtime-deployment-design.md`](agent-runtime-deployment-design.md) 为准;公开 Agent SDK
+与 SDK Host 的独立产品合同以
+[`agent-sdk-product-architecture.md`](agent-sdk-product-architecture.md) 为准。发生冲突时以上位
+文档为准。
+
+> **规范范围**:第 3-7、9-10 节描述尚未实现的目标架构,不是当前仓库状态。当前生产路径和
+> 迁移退出条件集中在第 8 节;在对应纵向切片完成验收前,Tauri command、legacy in-process TUI 和
+> `agent-runtime-ipc` Shared TUI 仍是有效生产边界。
+
+## 1. 决策摘要
+
+BitFun 采用 **Rich Client App Server + 两种部署形态**:
+
+1. Tauri Desktop、Electron、VS Code Extension、Web UI、交互式 TUI 和未来第一方 Rich Client 共享一份
+ 版本化 App Server 协议和生成的 typed client。
+2. App Server 是协议组合与交付边界,不是 Session、Permission、Git、MCP、Config、
+ Workspace 等领域行为的 owner。权威 DTO、策略和状态继续位于 Runtime API、
+ `contracts/*` 与对应能力归属模块。
+3. App Server 只定义 **Embedded** 与 **Shared** 两种部署形态。Embedded 是一个 Client 独占一个
+ App Server;Shared 是同一种 `client_kind` 的多个 Client 连接一个 App Server。两种形态不改变
+ schema、handler、错误、事件或业务语义。
+4. Headless CLI/CI 默认保留 Direct Runtime;公开 SDK 保留独立 SDK Host 合同;ACP
+ 保留 ACP 协议 adapter;它们不为了界面协议统一而依赖 App Server。
+5. Tauri、Electron、VS Code 等 Host 保留窗口、菜单、剪贴板、文件选择、终端界面、截图和
+ Computer Use 等界面宿主职责。PTY、Shell、命令执行与进程生命周期属于目标 workspace 的
+ Runtime Services,不是 Host reverse request。
+6. Shared Agent Runtime 是 App Server 的一种目标部署模式,不是第二套 server。Controller、Observer、取消、
+ 背压、重放、公平调度和 Runtime-aware drain 属于统一 App Server 合同的多客户端部分。
+7. App Server 使用唯一的独立后端 profile `AppServer`。运行位置、网络暴露、tenant、数据与 execution
+ domain 通过组装输入和安全策略收窄能力,不形成第三种部署形态;当前代码尚未提供该 profile,不能用
+ Desktop、CLI、Server 或 Web profile 代替。
+8. 每个 App Server instance 固定一个产品身份、`client_kind`、数据命名空间、release channel、安全域与后端 profile。
+ Client 只能协商自身展示能力与 Host capability,不能通过握手改变 Server 的产品策略或能力上限。
+9. Browser Web UI 的 Web Backend 按场景承载 Embedded 或 Web-only Shared App Server。服务端运行必须增加
+ 网络认证、租户隔离、方法 allowlist、数据与 execution domain 约束,但不得因此命名为 Hosted 第三形态。
+
+一句话定义:
+
+> BitFun App Server 是第一方 Rich Client(包括交互式 TUI)面向同一 Agent Runtime 和产品能力的版本化
+> JSON-RPC 协议 adapter;它不是新的 Runtime、公共 Agent SDK、通用 Remote API,也不是
+> 所有产品入口必须经过的内部总线。
+
+## 2. 背景与目标
+
+### 2.1 要解决的问题
+
+当前 Desktop 前端通过大量 Tauri commands 和事件消费后端能力。即使 command 后面的
+产品逻辑已经平台无关,前端仍了解 Tauri invoke、事件命名和宿主 DTO。直接替换为
+Electron 或新增 VS Code Extension 时,需要重新建立一套 Electron IPC 或 Extension Host
+消息层,并容易复制服务调度、错误映射和事件投影。
+
+Rich Client App Server 解决以下问题:
+
+- 前端不依赖 Tauri、Rust 内部类型或 `bitfun-core` 句柄;
+- Tauri、Electron、VS Code 和 Web 复用相同的产品操作与事件协议;
+- Rust schema 生成 TypeScript client/type,减少手写 DTO 漂移;
+- 后端可独立启动、测试、诊断和演进;
+- 同一业务行为只由既有 owner 实现一次,各 Host 只保留平台适配。
+
+### 2.2 设计目标
+
+1. **可替换前端**:替换 Tauri 为 Electron 或增加 VS Code Extension 时,不复制 Runtime、
+ Session、Permission、Git、MCP、Config 或 Workspace 行为。
+2. **明确的实例关系**:Embedded 保持一对一生命周期,Shared 提供同类 Client 的多连接与独立恢复。
+3. **一份 Rich Client wire**:Rich Client 共享 JSON-RPC method、错误、事件和版本协商。
+4. **领域所有权不迁移**:App Server 映射既有 Runtime API 和能力接口,不创建第二套行为。
+5. **宿主能力显式化**:不同前端通过 capability negotiation 表达平台能力,不假设功能齐全。
+6. **远程默认关闭**:本机协议不因存在 WebSocket transport 自动成为远程或公网 API。
+
+### 2.3 非目标
+
+- 不把所有 Tauri command 原样转换为 JSON-RPC method;
+- 不让 Headless CLI、CI、ACP 或 SDK Host 强制绕行 App Server;交互式 TUI 不属于该例外;
+- 不用 App Server schema 取代 `contracts/*` 或领域 owner;
+- 不把公开 SDK API 设计成 App Server 全量路由镜像;
+- 不另建 Shared TUI wire、Shared GUI wire 或按客户端类型分叉的 App Server schema;Shared 实例仍按
+ `client_kind` 隔离,不能用统一 schema 推导跨类型混连;
+- 不保留 `Per-Client Managed` 或 `Hosted App Server` 作为第三种部署形态;
+- 不以 App Server 的本机共享部署宣称已经支持 Remote 或公网协议;
+- 不把 Tauri/Electron/VS Code 的 renderer、主题、快捷键或窗口状态放入协议;
+- 不让浏览器 renderer、Electron renderer 或 VS Code Webview 持有本机启动令牌和系统凭据。
+
+## 3. 逻辑架构
+
+### 3.1 总体视图
+
+```mermaid
+flowchart TB
+ subgraph RichClients["First-party Rich Clients"]
+ Tauri["Tauri Desktop"]
+ Electron["Electron Desktop"]
+ VSCode["VS Code Extension"]
+ Web["Web UI"]
+ TUI["Interactive TUI"]
+ end
+
+ subgraph TrustedHosts["Trusted Client Hosts"]
+ TauriHost["Tauri Host"]
+ ElectronHost["Electron Main"]
+ VSCodeHost["Extension Host"]
+ WebBackend["Authenticated Web Backend"]
+ TUIHost["CLI/TUI Host"]
+ end
+
+ subgraph AppServer["App Server protocol adapter"]
+ Schema["Versioned JSON-RPC schema"]
+ Client["Generated / typed clients"]
+ Handler["Request, event and host-capability mapping"]
+ end
+
+ RuntimeAPI["Agent Runtime API and capability interfaces"]
+ Owners["Session / Permission / Git / MCP / Config / Workspace owners"]
+ Platform["OS and host capabilities"]
+
+ Tauri --> TauriHost
+ Electron --> ElectronHost
+ VSCode --> VSCodeHost
+ Web --> WebBackend
+ TUI --> TUIHost
+ TrustedHosts --> Client
+ Client --> Schema --> Handler
+ Handler --> RuntimeAPI --> Owners
+ Handler -. "negotiated reverse request" .-> TrustedHosts
+ TrustedHosts --> Platform
+```
+
+Rich Client 共享的是协议和 typed client。Tauri Host、Electron Main、VS Code Extension
+Host、Web Backend 与 CLI/TUI Host 仍是不同的可信边界,负责启动、认证、连接和平台能力。Renderer 或
+Webview 不直接管理 App Server 实例,也不直接持有认证材料。
+
+### 3.2 所有权边界
+
+| 边界 | 拥有 | 不拥有 |
+|---|---|---|
+| 领域 owner / Runtime API | 业务 DTO、校验、状态、权限、取消、审计和持久化语义 | JSON-RPC method、连接、窗口或 WebSocket |
+| App Server schema | method 名、wire 投影、错误信封、通知、协议版本和 capability negotiation | 领域状态、产品策略、具体 OS 服务和公开 SDK API |
+| App Server handler | 调用上下文校验、DTO 映射、deadline/cancel 转换、事件过滤和反向请求协调 | 重复业务校验、第二份权威状态和平台句柄 |
+| Client Host | App Server 生命周期、认证材料、renderer 隔离和平台 capability | Agent Session/Permission 权威状态 |
+| Rich Client UI | 渲染、交互状态和产品工作流 | Runtime 句柄、凭据、进程生命周期和协议 owner |
+
+`schema.rs` 可以是 **Rich Client JSON-RPC schema** 的单一来源,但不是全部后端领域契约
+的单一来源。Schema 应引用、包装或生成自稳定领域 DTO;只有 wire 特有字段,例如
+`request_id`、`operation_id`、协议版本和客户端 capability,才由 App Server 定义。
+
+### 3.3 与其他入口的关系
+
+```mermaid
+flowchart LR
+ Rich["Tauri / Electron / VS Code / Web / Interactive TUI"] --> App["App Server adapter"]
+ Headless["Headless CLI / CI"] --> CLIAdapter["CLI adapter"]
+ ACP["ACP client"] --> ACPAdapter["ACP adapter"]
+ SDK["Public Agent SDK"] --> SDKHost["SDK Host adapter"]
+
+ App --> API["Agent Runtime API"]
+ CLIAdapter --> API
+ ACPAdapter --> API
+ SDKHost --> API
+```
+
+- Rich Client(包括交互式 TUI)经 App Server 共享 wire;
+- Headless CLI/CI 继续进程内强类型调用,以保留启动成本、确定性退出和故障隔离;
+- ACP 和 SDK Host 映射各自独立、版本化的外部合同;它们可以共享领域 DTO 和行为 fixture,
+ 但不依赖 App Server handler 或 Rich Client wire。
+
+## 4. 协议设计
+
+### 4.1 JSON-RPC 与版本
+
+协议使用正规 JSON-RPC 2.0。方法采用 `domain/verb` 命名,例如
+`session/create`、`turn/submit` 和 `git/getStatus`。协议分为三层版本事实:
+
+1. **App Server protocol range**:method、wire DTO、错误、事件和 capability;
+2. **Runtime capability version**:Session、Tool、Permission 等业务语义;
+3. **Client release version**:Tauri/Electron/VS Code/Web 自身版本。
+
+初始化必须在任何业务请求前完成:
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "initialize",
+ "params": {
+ "instanceIdentity": "opaque-instance-id",
+ "deployment": "shared",
+ "authentication": { "scheme": "localBearer", "credential": "" },
+ "client": {
+ "id": "opaque-client-id",
+ "kind": "vscode",
+ "version": "1.2.0"
+ },
+ "protocol": { "min": 1, "max": 1 },
+ "capabilities": {
+ "filePicker": true,
+ "clipboard": true,
+ "terminalPresentation": true,
+ "desktopCapture": false
+ }
+ }
+}
+```
+
+Server 返回选定版本、固定的 deployment/client kind、Runtime capability、Host requirement、消息大小和并发上限。未知
+字段、未知 method 和不兼容版本按稳定规则 fail closed;stable 与 experimental method
+必须显式分层,不能仅靠文档约定。
+
+本机认证合同:
+
+- Embedded 凭据由唯一可信 Host 在创建实例时直接注入,不发布 discovery record,也不接受第二个
+ client identity;Shared token、instance identity 与固定 `client_kind` 由私有 discovery record 提供。凭据只对一个 instance、用户安全域、
+ protocol range 和有限有效期有效,不进入 renderer、命令行、URL、日志或普通事件;
+- Server 依次校验 frame/JSON 结构、initialize-first、instance identity、凭据、client identity、
+ deployment、`client_kind` 和 protocol range,最后才分配业务队列、attachment 或 Runtime context;
+ Embedded 对第二个 Client fail closed,Shared 对不同 `client_kind` fail closed;失败不能泄露哪一项实例事实匹配;
+- Host 重启、显式登出、权限或安全域变化时轮换并撤销旧凭据。Shared discovery 只有 owner 可以替换或清理,
+ 旧 instance 必须拒绝新凭据,新的 instance 必须拒绝旧凭据;
+- 未认证连接也计入很小的连接与握手 budget。连续失败按 endpoint/OS peer 限速并在上限后关闭,
+ 但日志只记录脱敏原因码;错误 token、错误 instance、过期/撤销 token 和重复失败是协议必测项;
+- 经网络暴露的 Embedded 或 Shared App Server 由 Web Backend 校验用户、tenant、workspace 和 method
+ scope,再向 App Server 注入不可由浏览器覆盖的认证上下文;网络认证是正交安全层,不新增部署形态。
+
+### 4.2 消息方向
+
+| 方向 | 类型 | 示例 |
+|---|---|---|
+| Client -> Server | Request | Session、Turn、Git、Config 查询或操作 |
+| Server -> Client | Response | 类型化结果或稳定错误信封 |
+| Server -> Client | Notification | Agent 事件、状态失效、诊断和 capability 变化 |
+| Server -> Client | Reverse request | 文件选择、用户输入、宿主确认、终端界面展示等已协商能力 |
+| Client -> Server | Reverse response | Host capability 的结果、拒绝或取消 |
+
+Permission owner 保留最终决定权。GUI 点击、SDK callback 或 Host reverse response 都只是
+输入,不能直接改写权限状态或扩大产品/组织策略。
+
+### 4.3 错误和副作用
+
+稳定错误至少包含:
+
+- `code`、`stage`、`retryable`、`message`;
+- `operation_id` 和可选 `session_id` / `turn_id`;
+- `action_required` 或类型化 `unsupported` 原因;
+- 对已发送但结果未知的副作用返回 `outcome_unknown`。
+
+创建、删除、重命名、配置写入、Git 写操作和 Turn 提交不得在响应丢失后自动重试。
+客户端必须通过幂等 operation ID 或重新读取权威状态后再决定下一步。
+
+### 4.4 事件、取消与背压
+
+- 请求有 deadline,取消沿 Runtime 既有取消树传播;断开连接不自动等于删除 Session;
+- request、response、notification 和 reverse request 队列必须有界;
+- `Lagged` 或 `Closed` 是显式状态失效,不能伪装成透明恢复;
+- 在事件 cursor/replay 交付前,重连只能重新查询权威快照,不能声称无缝续流;
+- 事件按连接身份、Session attachment 和方法 capability 过滤;
+- 多客户端共享前必须定义 Controller、Observer、审批竞争和 controller transfer。
+
+现有 Shared TUI IPC 的 controller lease、断连取消、有界 framing 和 `outcome_unknown`
+语义必须迁入统一 App Server 合同。迁移完成后删除旧 wire/server,不保留两套长期协议。
+
+## 5. Transport 与部署
+
+### 5.1 Transport 选择
+
+Transport 由可信 Host 选择,schema 不感知具体实现:
+
+| 场景 | Transport | 约束 |
+|---|---|---|
+| 测试和迁移 | in-memory pair | 使用相同 handler;不作为进程分离证明 |
+| Embedded App Server | in-process channel、私有 stdio 或私有 Pipe/UDS | 一个 Client 独占一个 Server;无 discovery,拒绝第二连接 |
+| 本机 Shared App Server | Windows Named Pipe / Unix Domain Socket | 私有 endpoint、认证握手、有界 framing、固定 `client_kind` |
+| 服务端 Embedded/Shared | authenticated WebSocket/HTTPS | 独立网络认证、授权、Origin/CORS、租户与方法 allowlist |
+| 远程 Rich Client | 暂不默认支持 | 必须经过 Server/Remote 安全设计评审 |
+
+Transport adapter 位于 adapters 层;App Server interface 只依赖抽象连接和类型化消息。
+不得因为实现了 WebSocket helper 就自动暴露完整本机 schema。
+
+### 5.2 两种目标拓扑
+
+```mermaid
+flowchart LR
+ Client["One Rich Client"] --> Host["Trusted Client Host"]
+ Host --> Choice{"deployment selection"}
+ Choice -->|"Embedded"| Embedded["Exclusive Embedded App Server"]
+ SameKind["Clients of one client_kind"] --> Shared["Shared App Server"]
+ Choice -->|"Shared"| Shared
+ Embedded --> Runtime["Agent Runtime + assembled services"]
+ Shared --> Runtime2["Agent Runtime + assembled services"]
+ Runtime --> Data["Workspace and Session storage"]
+ Runtime2 --> Data
+```
+
+`Embedded` 和 `Shared` 使用同一个 App Server schema、handler 和 conformance suite:
+
+| 模式 | 实例关系 | 适用场景 |
+|---|---|---|
+| Embedded | 一个 Client 独占一个 App Server 实例 | 默认单 Client 工作流、由 Client Host 私有创建和管理 |
+| Shared | 同一种 `client_kind` 的多个 Client 连接一个 App Server 实例 | 多个 TUI、Tauri Desktop、Electron Desktop、VS Code 或 Web 同类 Client 的协作与连续运行 |
+
+部署选择只决定承载方式、discovery、连接数量和 drain 条件。不得按模式复制 method、handler、
+领域 DTO 或 Runtime owner。Shared 模式必须完成 Controller/Observer、事件恢复、公平调度、审批竞争和
+Runtime-aware drain;Embedded 使用同一逻辑协议合同,只可因单连接事实简化运行时状态。
+
+不同 `client_kind` 不得连接同一 Shared instance。例如 TUI、Desktop、VS Code 和 Web 必须分别发现或创建
+自己的 Shared instance;跨形态接力通过持久化 Session、显式 handoff 或其他领域合同完成,不通过混连同一 Server。
+Browser Web UI 也只在 Embedded/Web-only Shared 两种形态中选择,本机超集不能因 wire 相同而自动发布到网络。
+
+### 5.3 生命周期与身份
+
+- Host 使用产品身份、数据命名空间、release channel、当前用户和协议范围定位兼容 binary 与 instance;
+- 业务 payload 前必须完成双向版本校验和本机认证;token 不进入日志、URL 或 renderer;
+- Host 负责选择 Embedded/Shared、创建或发现实例、健康检查、崩溃提示和有界重启,Runtime 负责 Session/Turn 生命周期;
+- Embedded 的身份和生命周期绑定唯一 Client Host,可同进程或私有子进程承载;Shared 使用独立 idle policy;
+- 服务端 orchestrator 可以创建 Embedded 或 Shared 实例并绑定 tenant、数据与 execution domain;浏览器身份不能选择或覆盖这些实例事实;
+- App Server 退出必须执行 Runtime-aware drain,不能只按连接计数推导;
+- workspace ownership 和 Session 单写继续使用现有 Core owner,不进入普通 wire;
+- Remote workspace 的文件、进程、凭据和 Runtime 必须位于目标 execution domain,禁止
+ 静默回落本机。
+
+### 5.4 产品组装与共享兼容性
+
+App Server 是后端产品组装根。目标产品能力系统增加唯一的 `AppServer` profile,不得由现有 `Desktop`、
+`Cli`、`Server` 或 `Web` profile 拼接冒充。具体运行环境再通过受信组装输入选择本机或 tenant-scoped provider;
+服务端环境默认不包含用户机器的 filesystem、process、credential、Computer Use 或本机 plugin runtime。
+这些 capability 与安全差异不改变 Embedded/Shared 两种实例关系。
+
+实例启动时消费唯一后端 profile、已验证的产品组装结果和 Runtime Configuration,之后这些实例级事实不可由
+任一 Client 改写。Desktop、TUI、VS Code 和 Web 的宿主形态只影响前端布局、renderer 生命周期和可提供的
+Host capability,不形成不同的领域语义。
+
+`client_kind` 标识具体宿主形态,而不是宽泛界面类别。至少区分 `tauri-desktop`、`electron-desktop`、
+`vscode`、`tui` 和 `web`;只有值完全相同的 Client 才能连接同一 Shared instance。新增 Client 形态必须
+分配新值并独立验证,不得仅因复用 Desktop 布局或 App Server schema 就沿用其他形态的值。
+
+Shared discovery key 至少包含产品身份、`client_kind`、数据命名空间、用户/组织安全域、release channel、协议兼容范围和 execution
+domain。只有这些事实兼容且 `client_kind` 完全相同的 Client 才能连接同一 Shared instance。不同客户端形态、品牌、数据隔离域、组织策略或不兼容 release
+channel 必须使用不同实例;禁止先连接再通过 Client 参数切换 Server identity、插件策略、权限上限或持久化根。
+
+连接握手可以协商 Client 类型、release version、语言、展示 capability、Host capability,以及 Server 已组装能力的
+只读可用性和类型化降级原因。它不能协商产品身份、数据根、组织安全策略、内置扩展集合或 Server capability 上限;
+这些都是实例创建事实。
+
+method/capability 的可用性由三个独立集合共同收窄,不能只靠 UI 隐藏或单层 capability negotiation:
+
+1. **Backend assembly**:该 `AppServer` profile 与运行环境实际装配的 Runtime 和 service capabilities;
+2. **Host capabilities**:仅当 operation 需要 reverse request 时,当前认证 Client 可提供的文件选择、
+ 剪贴板、窗口、终端展示等反向能力;
+3. **Connection method allowlist**:当前身份、tenant/workspace scope 和协议版本允许调用的方法。
+
+这三个集合不是完整授权公式。每次 operation 仍必须由 Server 解析且 Client 不可覆盖的 identity、tenant、
+workspace/resource ownership 和 operation scope 建立授权上下文,再交给 Runtime Permission owner、组织/用户
+策略与 operation-specific policy 作最终裁决并记录审计。已装配且在 method allowlist 中,只表示请求可以进入
+该裁决流程,不表示请求已经获准;不需要 reverse request 的普通 Runtime method 也不受 Host capability
+可用性虚假限制。
+
+本机与服务端运行环境至少各有 allow/deny fixture;服务端必须证明未装配或拒绝本机文件、进程、凭据、原生插件
+和 Computer Use 能力,本机也不能因 Host 声明某能力就绕过 backend plan 或 connection allowlist。
+
+## 6. 平台能力边界
+
+现有 Desktop commands 需要按所有权分类,而不是机械迁移:
+
+| 类型 | 处理方式 |
+|---|---|
+| Session、Turn、Permission、Git、MCP、Config、Workspace 等产品能力 | 通过 App Server 映射既有 Runtime/能力接口 |
+| 窗口、托盘、菜单、更新、原生对话框 | 留在 Tauri/Electron/VS Code Host |
+| 文件选择、剪贴板、终端窗口打开/聚焦/展示、截图、Computer Use 界面操作 | 经协商后的 Host capability/reverse request |
+| PTY、Shell、命令执行、子进程、取消和回收 | 由 workspace execution domain 中的 Runtime Services 执行;不发送回 Client Host |
+| 只适用于特定 Host 的能力 | 返回类型化 `unsupported`,UI 据此隐藏或禁用 |
+
+Host capability 必须声明输入、结果、权限、deadline、取消和失效语义。App Server 不得
+直接持有 `tauri::AppHandle`、Electron 对象、VS Code API 对象或原始 OS 窗口句柄。
+命令请求必须携带由 Server 解析且 Client 不可覆盖的 workspace/execution-domain identity,并沿该域的
+权限、审计、取消和资源预算执行。远程 workspace 缺少目标 terminal provider 时返回 `unsupported`,禁止
+回落到运行 GUI/TUI 的控制端机器。
+
+## 7. 模块与依赖
+
+目标代码组织:
+
+```text
+src/crates/interfaces/app-server
+ Rich Client schema、typed Rust client、抽象 handler contract、版本与 capability negotiation
+
+src/crates/adapters/app-server-transport
+ in-memory、stdio、Named Pipe、UDS、WebSocket transport adapter
+
+src/apps/app-server
+ Shared App Server 独立进程入口、产品组装、生命周期、日志与诊断
+
+src/apps/desktop
+ Tauri Host、Embedded App Server 私有承载、同类 Shared discovery、Desktop capabilities
+
+src/apps/server
+ 服务端 Embedded/Web-only Shared App Server 承载、WebSocket/HTTP 暴露、网络认证、租户/远程策略和 capability allowlist
+
+src/crates/contracts/*
+ 领域 DTO、事件事实、稳定错误与 Runtime ports
+```
+
+依赖方向:
+
+```mermaid
+flowchart TB
+ Hosts["apps/desktop · apps/server · apps/app-server"] --> Interface["interfaces/app-server"]
+ Hosts --> Transport["adapters/app-server-transport"]
+ Interface --> Contracts["contracts"]
+ Transport --> Contracts
+ AppRoots["apps/app-server · apps/server"] --> Assembly["assembly / Runtime API"]
+ AppRoots --> Interface
+ Assembly --> Execution["execution"]
+ Assembly --> Services["services"]
+ Execution --> Contracts
+ Services --> Contracts
+```
+
+约束:
+
+- App Server interface 不依赖 `src/apps/*`;
+- App Server interface 只通过 `contracts` 中的稳定 DTO/ports 描述 handler contract,不依赖具体
+ Assembly、Runtime 或 service 实现;
+- transport adapter 不依赖 `bitfun-core`、Tauri、SDK Host 或 Runtime 实现;
+- Embedded Client Host、`apps/app-server` Shared 入口与服务端 `apps/server` 组装根把 Assembly/Runtime API provider
+ 注入 handler contract;
+ 具体 handler wiring 不进入客户端共享的 interface crate,也不直接构造 OS service;
+- `interfaces/sdk-host` 继续保持独立,不依赖 App Server 或 `bitfun-core`;
+- ACP adapter 不经 App Server 做 ACP -> JSON-RPC -> Runtime 的双重协议转换;
+- Web 生成类型只暴露该 Host allowlist 中真实可用的 method,不把本机超集自动发布到网络。
+
+## 8. 非规范迁移说明
+
+### 8.1 迁移来源
+
+| 范围 | 当前状态 |
+|---|---|
+| Desktop | Tauri command/event adapter 直接消费 Core/Runtime 能力 |
+| Server Host | Health、Info 与 SSH-backed detached dispatch controller/observer 外壳;不启动 Agent Runtime |
+| Server WebSocket | 当前仅绑定 loopback,无连接认证;只有请求携带 `Origin` 时才校验 allowlist,缺失 `Origin` 会放行。既有 `type=request/response/event` 私有信封暴露 install、submit、cancel、answer、append 等可变 dispatch,不是正规 JSON-RPC 2.0 |
+| App Server crate/process | 尚未创建 |
+| Shared TUI | 当前私有 IPC 是迁移来源;目标改为 App Server Shared deployment 并删除独立 wire/server |
+| Headless CLI / CI | Direct Runtime;当前明确拒绝非交互 `--shared`,本迁移不改变该合同 |
+| Runtime ownership | 当前 Shared owner 绑定单一 workspace;目标多 workspace registry 尚未实现 |
+| Product capabilities | 当前没有 App Server backend profile;Desktop/CLI/Server/Web profile 不能代替 |
+| ACP / SDK Host | 各自协议 adapter 与生命周期保持独立 |
+
+迁移映射与退出条件:
+
+| 当前模块/合同 | 目标位置 | 退出或调整条件 |
+|---|---|---|
+| Tauri business command/event | App Server method/event 或保留为 Host-only command | 对应纵向切片行为等价、Remote/network policy 明确、Desktop dogfood 与有界回滚通过 |
+| `agent-runtime-ipc` operation/handler/server | App Server schema/handler | TUI 改用 typed client,controller/cancel/backpressure/`outcome_unknown` fixture 全部通过 |
+| Named Pipe/UDS、discovery、framing | `app-server-transport` 内部原语 | 证明协议中立;保留认证、frame、queue、deadline 和 cleanup 限制或记录经测量的变更 |
+| 单 workspace Shared ownership | App Server Runtime context registry + per-workspace `CoreRuntimeOwnership` | 第二 workspace、并发 attach、Remote、冲突、断连回收和重启恢复测试通过 |
+| Desktop/CLI capability profile | 唯一 `AppServer` backend profile + 环境安全策略 | 本机/服务端 allow/deny、tenant/data/execution-domain 隔离通过,禁止用旧 profile 临时代替 |
+| 既有 Server WebSocket envelope | allowlisted App Server network exposure,或保留独立 Server/Remote wire | 网络认证、Origin/CORS、tenant/workspace scope 和方法 allowlist 通过;不得直接发布本机超集 |
+
+当前 Server WebSocket 的安全边界是 loopback bind,而不是连接认证或只读 Observer。它会使用 Server Host
+已加载的 SSH connection 执行可变 detached dispatch;在 OS peer/身份认证、workspace/target scope、方法
+allowlist 和拒绝测试完成前,不得放宽 loopback bind,也不得把该 envelope 复用为网络 App Server
+或远程入口。
+
+在最后一个旧 consumer 退出前,`agent-runtime-ipc` 继续遵守其局部 `AGENTS.md` 中的完整当前生产
+合同。迁移不得以“旧协议最终会删除”为由提前放宽认证、大小、连接、operation、idle 或 cleanup 限制。
+
+### 8.2 迁移阶段
+
+#### 阶段 A:合同归属与首个纵向切片
+
+1. 选择 Session create/list/restore、Turn submit/cancel、事件和 Permission 作为首个完整旅程;
+2. 将共享业务 DTO 和错误放入现有 contracts/Runtime owner,而不是 App Server 私有 DTO;
+3. 建立 schema codegen、drift check、stable/experimental 和 capability negotiation;
+4. 使用 in-memory pair 完成 handler/typed client 行为 fixture;
+5. 保留既有 Tauri 路径作为兼容回退,证明结果和副作用等价。
+
+#### 阶段 B:Desktop dogfood
+
+1. Desktop 的目标纵向切片改用 AppServerClient;
+2. 窗口和平台 command 保留在 Tauri Host;
+3. Permission/UserInput 与文件选择建立 reverse request;
+4. 测量启动、首 token、事件吞吐、内存和取消延迟;
+5. 达到行为与性能门槛后逐域迁移,不按 command 数量批量搬运。
+
+#### 阶段 C:Embedded 承载
+
+1. 增加可嵌入的 App Server 组装入口与私有 transport;
+2. 实现版本匹配、唯一 Client 身份、drain 和崩溃恢复;
+3. Desktop 使用一个 Client 对一个 Embedded App Server;
+4. 删除对应旧 Tauri 业务桥前,保留端到端兼容测试和回滚开关。
+
+#### 阶段 D:交互式 TUI 收敛
+
+1. CLI/TUI Host 使用与 Desktop 相同的 AppServerClient 和本机 transport;
+2. 默认交互式 TUI 使用独占 Embedded 实例,`--shared` 连接 TUI-only Shared 实例;
+3. 将当前 Shared TUI 的 controller lease、取消、背压、`outcome_unknown` 和 idle cleanup 合同迁入 App Server;
+4. 使用同一 fixture 验证旧 Shared TUI 与 App Server Shared 模式行为等价;
+5. 删除 `agent-runtime-ipc` 的独立 operation、framing、server 和 discovery 实现,或将真正通用的本机原语下沉为
+ App Server transport 内部实现,不保留第二套协议入口。
+
+#### 阶段 E:新增 Rich Client
+
+1. Electron Main 或 VS Code Extension Host 创建匹配 Embedded App Server,或发现完全相同 `client_kind` 的 Shared instance;
+2. Renderer/Webview 复用生成的 client API,但只经可信 Host 访问;
+3. 每个新 Host 提交 capability、权限、生命周期、安装升级和远程 workspace 验证;
+4. Web 接入另行完成网络认证与方法 allowlist,不能复用本机信任假设;每种新 Client 只能连接自身
+ `client_kind` 的 Shared instance。
+
+#### 阶段 F:同形态 Shared Rich Client
+
+分别为 TUI、Desktop、VS Code 和 Web 验证 Shared 模式。同一 Shared App Server 只接受一个固定
+`client_kind`;不同形态即使协议兼容也必须使用不同实例。每种 Shared 形态都必须完成 Controller/Observer、
+事件恢复、公平调度、Runtime-aware drain、Host capability 路由和客户端身份审计。
+
+## 9. 验收门槛
+
+每个迁移切片至少证明:
+
+1. Runtime/领域 owner 未迁移,旧入口和 App Server 路径共享行为 fixture;
+2. schema 生成可重复,Rust/TypeScript drift check 通过;
+3. 请求、响应、事件和 reverse request 都有大小、队列、deadline 和取消上限;
+4. 副作用具有 operation ID、明确失败与 `outcome_unknown` 语义;
+5. Host capability 缺失返回类型化 `unsupported`,不静默调用本机替代能力;
+6. 本机认证材料不进入 renderer、URL、日志、Session transcript 或普通事件;
+7. 服务端 Embedded/Shared 覆盖网络认证、tenant/data 隔离、方法 allowlist、跨租户拒绝和 Runtime-aware drain;
+8. Remote workspace 行为在目标 execution domain 验证;
+9. Desktop 与交互式 TUI 至少覆盖启动、Session 恢复、Turn、Permission/UserInput、取消、重连和退出;
+10. 性能基线覆盖冷启动、首 token、流式事件吞吐、CPU、内存和大 transcript;
+11. 删除旧 adapter 前有兼容期限、回滚方式和生产 consumer 证据。
+
+## 10. 不变量
+
+- 只有一套 Agent Runtime 行为 owner;
+- App Server 不拥有 Session、Tool、MCP、Permission、Hook、Event、Git 或 Workspace 状态;
+- Rich Client 只有一套 App Server wire;App Server 只存在 Embedded 与 Shared 两种部署形态,不得分叉协议或业务 handler;
+- Embedded 恰好一个 Client 对一个 Server;Shared 多个 Client 对一个 Server,但一个实例只接受一种 `client_kind`;
+- SDK Host wire 和 ACP wire 与 App Server 合同独立;Headless CLI/CI 是 Direct Runtime 调用而不是 App Server Embedded;
+- Headless CLI/CI 不因 GUI 解耦增加后台进程或序列化成本;
+- 平台能力留在真实 Host,凭据和执行发生在正确 execution domain;
+- 未经过认证、授权和远程策略评审的本机 method 不暴露到 WebSocket/HTTP;
+- 多客户端共享必须在统一 App Server 合同中交付 Controller、背压、恢复和生命周期语义;
+- 未有真实 consumer 的 method、transport 或 capability 不进入稳定协议。
diff --git a/docs/architecture/cli-product-line-design.md b/docs/architecture/cli-product-line-design.md
index 2ad4496d3..10771773d 100644
--- a/docs/architecture/cli-product-line-design.md
+++ b/docs/architecture/cli-product-line-design.md
@@ -11,8 +11,9 @@ CLI/TUI 的目标、问题和风险规约见 [`platform-portability-design.md`](
CLI 产品入口、配置兼容、TUI 布局消费和 CLI Agent 体验,不重复定义这些文档中的通用契约或内部 ABI。公开
BitFun Agent SDK 与 Headless CLI 的产品选择、能力一致性和 SDK Host 边界见
[`agent-sdk-product-architecture.md`](agent-sdk-product-architecture.md);多个 GUI/TUI/Remote/CLI 实例并存时,交互式 TUI
-连接 Shared Agent Runtime、一次性 CLI 保留 Embedded 的部署边界见
-[`agent-runtime-deployment-design.md`](agent-runtime-deployment-design.md)。
+经 App Server 使用 Embedded/TUI-only Shared、一次性 CLI 保留 Direct Runtime 的部署边界见
+[`agent-runtime-deployment-design.md`](agent-runtime-deployment-design.md);统一 Rich Client wire 见
+[`app-server-architecture-design.md`](app-server-architecture-design.md)。
OpenCode 的完整扩展矩阵、配置资产、插件执行和 TUI Plugin 映射分别见
[`opencode-extension-compatibility.md`](extensions/opencode-extension-compatibility.md)、
[`opencode-config-assets-adapter-design.md`](extensions/opencode-config-assets-adapter-design.md)、
@@ -252,18 +253,25 @@ Headless CLI 和公开 Agent SDK 都调用同一 Agent Runtime API,但交付
- 两者的能力对照、共同 fixture 和等价门槛以
[Agent SDK 产品与宿主架构第 9 节](agent-sdk-product-architecture.md#9-headless-cli-与-agent-sdk)为唯一事实源。
-交互式 TUI 另有一个显式部署选项:`bitfun --shared` 或 `bitfun chat --shared`。它通过 CLI 私有本机 IPC adapter 连接同一 Agent Runtime,不经过 SDK Host,也不改变 Headless CLI 或公开 SDK 的协议。当前范围如下:
+交互式 TUI 是 Rich Client App Server consumer,不经过 SDK Host。默认创建一个 Client 独占的 Embedded App Server;
+`bitfun --shared` 或 `bitfun chat --shared` 连接 TUI-only Shared App Server。两种部署使用相同 schema、typed client、handler、
+错误和事件,只改变 instance discovery、连接和生命周期;Headless CLI 与公开 SDK 的协议不变。
-| 形态 | 默认部署 | 当前 Shared 范围 |
+| 形态 | 默认部署 | 可选部署 |
|---|---|---|
-| 交互式 TUI | Embedded | 显式 `--shared` 后支持 Session list/create/restore、transcript、当前 Session rename/Agent mode/model、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 ` 修改当前 Session 名称;`/agent`、Tab 和 Shift+Tab 只切换当前 Session 的 Agent mode;`/models` 只切换当前 Session 的 model。Embedded 与 Shared 的 `/help` 都从 Action Registry 展示 `/rename `;在 slash menu 中选择它只预填命令并等待用户输入名称。若外部来源使用相同命令名,用户明确选择的 BitFun 命令可完成这一次参数提交,即使偏好保存失败也不会重新弹出来源选择。它们不进入管理页面,也不修改未来 Session 的默认值。其他不支持动作不显示为可执行入口。Session 切换失败保留原控制权;单个连接已有活动 Turn 时拒绝重复提交以及 Session rename/mode/model update;事件订阅失效后当前视图立即失效并要求重启 Shared TUI。
-
-部署差异由 CLI Runtime client 封装。Embedded 以 Rust 类型直接调用 `AgentRuntime`,不初始化 IPC 或执行 JSON 编解码;Shared 将同一业务请求映射为一个有界本机 frame,Client/Server 各自只编码一次,再交给同一 Runtime owner。多 TUI 复用一个 Runtime 进程,连接和队列保持有界,不按 TUI 数量复制 Session owner。详细的 4+1 视图、帧上限和并发边界见
+| 交互式 TUI | Embedded App Server | 显式 `--shared` 后连接 TUI-only Shared App Server;不与 GUI/IDE 混连 |
+| `bitfun exec` / CI | Direct Runtime | 不作为 App Server client;保持独立进程、stdout/stderr 和退出码语义 |
+| GUI / VS Code | Embedded App Server | 各自只能连接对应 `client_kind` 的 Shared App Server |
+| ACP / SDK Host / Remote / Peer | 各自既有部署 | 不因 TUI 开关改变协议或生命周期 |
+
+交互式 TUI 的可用操作由统一 App Server capability negotiation 和产品能力决定,不建立 TUI-only operation budget。
+斜杠命令、快捷键帮助和底部提示消费同一 capability projection;不支持动作不显示为可执行入口。Session
+切换失败保留原控制权;同一 Controller 已有活动 Turn 时按 Runtime 策略拒绝或排队冲突更新;事件流失效后使用
+App Server snapshot/cursor 恢复,无法恢复时明确使当前视图失效。
+
+交互式 TUI 的部署差异由 AppServerClient 封装;Embedded 与 Shared 都执行同一 JSON-RPC contract。Headless
+Direct Runtime 以 Rust 类型直接调用 `AgentRuntime`。多个 TUI 可以复用一个 TUI-only Shared App Server,连接和队列保持
+有界,不按 TUI Client 数量复制 Session owner;GUI/IDE 使用各自实例。详细的进程、并发和恢复边界见
[`agent-runtime-deployment-design.md`](agent-runtime-deployment-design.md)。
#### 管理与诊断
@@ -301,8 +309,9 @@ TUI renderer、实验性接口和完整外部 Server 协议按总矩阵明确降
| 层/模块 | 负责 | 不负责 |
|---|---|---|
| `src/apps/cli` | Clap 入口、TUI 状态/渲染、终端事件、入口本地设置、命令展示与结构化输出 | 会话状态机、工具执行、权限裁决、插件内部 ABI、品牌能力真值 |
-| CLI Runtime client | 屏蔽 Embedded/Shared 部署差异,将 CLI 的类型化调用映射到进程内 Runtime 或私有本机 IPC | 实现 Session 业务规则、暴露公开 SDK 或在两种部署中复制行为 |
-| `adapters/agent-runtime-ipc` | Shared TUI 的私有本机 transport、严格握手、frame 上限、连接控制和封闭 operation 映射 | 服务 Embedded、公开协议、Remote transport 或 Runtime 业务 owner |
+| AppServerClient | 为交互式 TUI 屏蔽 Embedded/Shared 部署差异,消费统一 schema、事件、错误和 capability | 实现 Session 业务规则、依赖 SDK Host 或分叉 TUI-only wire |
+| Headless Runtime client | 为 `exec`/CI 提供 Direct Runtime API | attach Shared App Server、改变 stdout/exit contract、默认启动后台进程或复制 Rich Client handler |
+| `adapters/app-server-transport` | App Server 的本机/stdio/WebSocket transport、严格握手、frame 上限和连接控制 | Runtime 业务 owner、TUI-only operation 或公开 SDK API |
| `assembly/product-capabilities` | Delivery Profile、Product Capability 计划、静态 eligibility、服务需求和组装计划 | 品牌资源读取、动态可用性、用户配置、UI 状态、具体服务创建 |
| 产品构建期校验 | 校验产品定义、品牌资源、TUI 布局选择和内置扩展版本,输出产品组装结果 | 创建运行时服务、实现终端行为或保存用户配置 |
| Product Assembly | 读取产品组装结果中本次 CLI 需要的字段,选择能力/服务/扩展,构建 Runtime Parts | 读取原始品牌资源、实现 Agent/Tool/插件适配器/终端行为或运行构建脚本 |
@@ -317,20 +326,22 @@ TUI renderer、实验性接口和完整外部 Server 协议按总矩阵明确降
```mermaid
flowchart LR
Exec["bitfun exec"] --> Choice{"Session"}
- Choice -->|"new / free"| Embedded["Embedded"]
+ Choice -->|"new / free"| Direct["Direct Runtime"]
Choice -->|"already owned"| Reject["typed occupied error"]
TUI["bitfun chat"] --> Deploy{"deployment"}
- Deploy -->|"default"| EmbeddedTui["Embedded"]
- Deploy -->|"--shared"| SharedTui["private local IPC"]
- SharedTui --> Runtime["one Shared Runtime owner"]
+ Deploy -->|"default"| Embedded["Embedded App Server"]
+ Deploy -->|"--shared"| Shared["TUI-only Shared App Server"]
+ Embedded --> Runtime1["Agent Runtime owner"]
+ Shared --> Runtime2["one Shared Runtime owner"]
```
-Embedded 只意味着 Runtime 与 CLI 同进程,不意味着绕过持久化单写规则。新 Session 取得自己的写入权;恢复既有 Session 时,
-CLI 必须先取得该 Session 的写入权。如果 Shared Agent Runtime 或另一个 `exec` 已持有,Headless CLI 返回明确的
-“Session 已占用”;它不会自动切换部署。只有用户显式选择 `--shared` 的交互式 TUI 才连接 Shared Runtime,且同一 Session 同时只有一个 controller。
+Direct Runtime 只意味着 Runtime 与 Headless CLI 同进程,不意味着绕过持久化单写规则。新 Session 取得自己的写入权;恢复既有 Session 时,
+CLI 必须先取得该 Session 的写入权。如果 Shared App Server 或另一个 `exec` 已持有,Headless CLI 返回明确的
+“Session 已占用”;它不会自动切换部署。交互式 TUI 始终使用 App Server,`--shared` 只选择 Shared instance;
+同一 Session 同时只有一个 controller,但可以有多个 observer。
-CLI/TUI 的会话创建、列出、删除、恢复和历史转录读取通过 Rust Runtime SDK 的类型化端口完成;TUI 只把
+Headless CLI 的会话操作通过 Rust Runtime SDK 的类型化端口完成;交互式 TUI 通过 AppServerClient 消费同一领域事实,并只把
`SessionTranscript` 转换为本地渲染状态,不再消费 Core `Message`。Peer Host 的对话提交、精确取消、基础会话控制、thread-goal 查询、会话模型更新和
工具确认/拒绝通过 Agent Runtime API 回到 Core owner;本地会话分支通过显式本地范围的内部端口完成,携带远程身份的请求返回类型化
`NotAvailable`,本轮不扩展远程分支。TUI 用量卡片通过固定语义的完成态本地命令轮次端口持久化,不暴露通用 transcript writer。
diff --git a/docs/architecture/extensions/plugin-runtime-design.md b/docs/architecture/extensions/plugin-runtime-design.md
index bcaada2a7..12e267240 100644
--- a/docs/architecture/extensions/plugin-runtime-design.md
+++ b/docs/architecture/extensions/plugin-runtime-design.md
@@ -77,7 +77,8 @@ flowchart TD
workspace、session、插件和贡献数量都不是默认进程键。一个 Plugin Host 可以承载多个来源、多个
workspace 的逻辑实例和多个 session 的调用;这些身份必须随请求显式传递,进程内状态仍按生态的真实语义分区。
-因此 Shared Agent Runtime 中多个 GUI/TUI/Remote Client 不会各自创建 Plugin Host;一次性 Embedded CLI、私有 SDK Host 和
+因此同一 `client_kind` 的 Shared Agent Runtime 中多个 Client 不会各自创建 Plugin Host;不同 GUI/TUI/Remote
+形态不连接同一个 Shared App Server。一次性 Direct Runtime CLI、私有 SDK Host 和
目标机器 Runtime 则各自只管理自己的子进程树,不跨 Rust 进程或 execution domain 共享模块实例。
容量压力本身不直接创建进程。只有测量证明单进程队列不足,并且待拆调用同时满足“无共享模块状态、无顺序 Hook
diff --git a/docs/architecture/product-architecture.md b/docs/architecture/product-architecture.md
index 707917bc7..e99ce1114 100644
--- a/docs/architecture/product-architecture.md
+++ b/docs/architecture/product-architecture.md
@@ -19,9 +19,13 @@
Headless CLI 与各产品入口的统一心智见
[`agent-sdk-product-architecture.md`](agent-sdk-product-architecture.md);多个 GUI/TUI/Remote/CLI/SDK 实例共存时的 Agent Runtime 部署、
状态共享、隔离、容量与 Plugin Host 关系见
-[`agent-runtime-deployment-design.md`](agent-runtime-deployment-design.md)。详细设计与本文件冲突时,以本文件为准。
+[`agent-runtime-deployment-design.md`](agent-runtime-deployment-design.md);Tauri、Electron、VS Code Extension、Web 等第一方
+Rich Client 的统一后端协议与迁移边界见
+[`app-server-architecture-design.md`](app-server-architecture-design.md)。详细设计与本文件冲突时,以本文件为准。
-本文件只约束稳定边界,不记录单次 PR 进度,也不把未来可能支持的生态能力提前声明为公开接口。
+本文件的原则和目标视图约束稳定边界,不记录单次 PR 进度,也不把未来可能支持的生态能力提前声明为公开接口。
+为避免把设计目标误作仓库事实,第 2.2 节先给出当前 Development View,再给出明确标记的目标增量;
+第 4.1 和第 6 节同样分别标注当前与目标调用链。
## 1. 架构目标
@@ -36,8 +40,9 @@ BitFun 同时面向桌面 GUI、TUI/CLI、Web、ACP、Server、Remote、SDK 和
4. **OpenCode 是兼容目标,不是内部模型**:适配层尽量保持 OpenCode plugin、hook、custom tool、TUI plugin、
Client、配置和加载顺序的外部可观察行为,但这些类型不能反向成为 BitFun 智能体、配置或界面的内部数据模型。
5. **公开接口有预算**:新增公开 DTO、trait、模块或入口必须同时具备归属模块、真实消费方、版本策略、验证方式和删除条件。
-6. **入口形态受宿主约束**:TUI、GUI、Web、Headless CLI 和公开 SDK adapter 共享 Agent Runtime API
- 用例、能力服务接口和只读视图,不共享公开语言包、传输、渲染句柄、主题键、键位模型或界面状态;
+6. **入口形态受宿主约束**:各入口共享 Agent Runtime API 用例、能力服务接口和只读视图;Tauri、Electron、
+ VS Code Extension 与 Web 等第一方 Rich Client 可以共享版本化 App Server wire,但不共享渲染句柄、主题键、
+ 键位模型、界面状态或平台生命周期。交互式 TUI 也属于 Rich Client;Headless CLI、ACP 和公开 SDK 仍保留各自边界;
插件界面贡献必须先声明目标入口形态,再由对应宿主适配。
7. **产品定制先解析,运行时扩展后加载**:产品身份、能力上限和 GUI/TUI 布局选择在构建/组装期解析;用户配置和插件只能在该上限内扩展,不能反向改写产品事实。
8. **平台差异留在入口和具体能力实现**:target 只选择 ABI,feature 只控制确实可选的依赖;共享内核不按平台
@@ -62,8 +67,10 @@ BitFun 同时面向桌面 GUI、TUI/CLI、Web、ACP、Server、Remote、SDK 和
13. **一个 Agent Runtime,多种交付形态**:GUI、TUI、Headless CLI、公开 SDK、ACP 与 Server/Remote 都是
同一 Agent Runtime 的 adapter。Query、Session、Tool/MCP、Permission、Hook、Event/Usage 只有一个行为
归属模块;公开 SDK 不成为内部入口的依赖,ACP 和 Headless CLI 也不成为完整 SDK 的别名。目标部署中,第一方
- GUI/TUI/本机 Remote 可以共享 Agent Runtime,一次性 Headless CLI 保留 Embedded,公开 SDK 默认使用私有 SDK Host;
- 这些 Rust 部署都只通过 `PluginRuntimeClient` 和 services 归属模块管理自己的 Node/Bun Plugin Host 子进程。
+ Rich Client(GUI、Web、交互式 TUI)经 App Server 协议访问 Runtime,并可在相同 `client_kind` 内通过 Shared
+ deployment 共享 Agent Runtime;不同形态 Client 不连接同一个 Shared Server。一次性
+ Headless CLI 保留 Direct Runtime,公开 SDK 默认使用私有 SDK Host;这些 Rust 部署都只通过
+ `PluginRuntimeClient` 和 services 归属模块管理自己的 Node/Bun Plugin Host 子进程。
调用路径长度只作为工程成本处理,不作为独立架构目标。允许保留承担兼容隔离、只读视图或能力选择职责的中间层;不允许为了兼容而长期暴露没有消费方的抽象接口。
@@ -71,12 +78,12 @@ BitFun 同时面向桌面 GUI、TUI/CLI、Web、ACP、Server、Remote、SDK 和
4+1 视图分别描述系统职责、代码组织、运行协作、部署边界和关键场景,避免把逻辑模块、crate、进程和调用链混在同一张图中。分类沿用 [Kruchten 4+1](https://www3.software.ibm.com/ibmdl/pub/software/rational/web/whitepapers/2003/Pbk4p1.pdf),图的层级、动态协作和部署节点表达参考 [C4](https://c4model.com/diagrams) 以及 arc42 的 [Building Block](https://docs.arc42.org/section-5/)、[Runtime](https://docs.arc42.org/section-6/) 和 [Deployment](https://docs.arc42.org/section-7/) 视图;这些方法只提供视角和表达规则,不替代 BitFun 的真实 owner 与代码边界。
-Level 0 展示系统级主要边界和依赖方向;Level 1 再按 Level 0 的模块或范围展开。每张图必须能独立说明范围和图例,关系使用明确方向或协议,逻辑模块、crate、运行任务和部署实例不要求一一对应。Agent Runtime 的 Embedded/Shared 逻辑、开发、进程、物理和场景视图集中在
+Level 0 展示系统级主要边界和依赖方向;Level 1 再按 Level 0 的模块或范围展开。每张图必须能独立说明范围和图例,关系使用明确方向或协议,逻辑模块、crate、运行任务和部署实例不要求一一对应。App Server 的 Embedded/Shared 与 Headless Direct Runtime 逻辑、开发、进程、物理和场景视图集中在
[`agent-runtime-deployment-design.md`](agent-runtime-deployment-design.md),本文件不重复其连接和性能细节。
### 2.1 Logical View · Level 0
-Logical View 只表达当前系统的职责模块与依赖方向,不表达 crate 归属或进程位置。
+Logical View 只表达目标系统的职责模块与依赖方向,不表达 crate 归属或进程位置。
```mermaid
%%{init: {"theme":"base","flowchart":{"curve":"basis","nodeSpacing":28,"rankSpacing":34},"themeVariables":{"fontFamily":"Inter, ui-sans-serif, system-ui","primaryColor":"#ffffff","primaryTextColor":"#171717","primaryBorderColor":"#737373","lineColor":"#525252","secondaryColor":"#fafafa","tertiaryColor":"#ffffff","clusterBkg":"#ffffff","clusterBorder":"#a3a3a3"}}}%%
@@ -191,6 +198,12 @@ flowchart TB
Development View 展示仓库的静态代码组织。层间依赖只允许向下,可跨过中间层,但不能反向依赖上层;图中子项表示主要 crate 家族或产品入口,不等同于 Logical View 的职责模块。
+#### 当前仓库快照
+
+当前不存在 `src/apps/app-server`、`src/crates/interfaces/app-server` 或
+`src/crates/adapters/app-server-transport`。当前 Shared TUI 生产路径仍由
+`src/crates/adapters/agent-runtime-ipc` 提供;它在目标纵向切片完成前按现有生产合同维护。
+
```mermaid
flowchart TB
subgraph AppsLayer[" "]
@@ -205,7 +218,7 @@ flowchart TB
subgraph AdaptersLayer[" "]
direction LR
- AdaptersTitle["3 · Adapters"] ~~~ RuntimeIPC["Runtime IPC"] ~~~ ModelAdapters["Model Adapters"] ~~~ SourceAdapters["Source Adapters"] ~~~ Transport["Transport"] ~~~ WebDriver["WebDriver"]
+ AdaptersTitle["3 · Adapters"] ~~~ RuntimeIpc["Agent Runtime IPC · current Shared TUI"] ~~~ ModelAdapters["Model Adapters"] ~~~ SourceAdapters["Source Adapters"] ~~~ Transport["Transport"] ~~~ WebDriver["WebDriver"]
end
subgraph ServicesLayer[" "]
@@ -228,7 +241,7 @@ flowchart TB
classDef header fill:#fafafa,stroke:#404040,stroke-width:1.6px,color:#171717;
classDef module fill:#ffffff,stroke:#737373,stroke-width:1.3px,color:#171717;
class AppsTitle,AssemblyTitle,AdaptersTitle,ServicesTitle,ExecutionTitle,ContractsTitle header;
- class Desktop,CLI,Server,Relay,WebUI,MobileUI,ACP,SDKHost,CoreAssembly,ExternalSources,ProductCaps,RuntimeIPC,ModelAdapters,SourceAdapters,Transport,WebDriver,CoreServices,Integrations,MiniAppMarket,RelayService,Terminal,PageRuntime,AgentRuntime,AgentStream,ToolRuntime,PluginClient,Harness,RuntimeServices,CoreTypes,Events,RuntimePorts,ProductDomains module;
+ class Desktop,CLI,Server,Relay,WebUI,MobileUI,ACP,SDKHost,CoreAssembly,ExternalSources,ProductCaps,RuntimeIpc,ModelAdapters,SourceAdapters,Transport,WebDriver,CoreServices,Integrations,MiniAppMarket,RelayService,Terminal,PageRuntime,AgentRuntime,AgentStream,ToolRuntime,PluginClient,Harness,RuntimeServices,CoreTypes,Events,RuntimePorts,ProductDomains module;
style AppsLayer fill:#ffffff,stroke:#a3a3a3;
style AssemblyLayer fill:#ffffff,stroke:#a3a3a3;
style AdaptersLayer fill:#ffffff,stroke:#a3a3a3;
@@ -248,11 +261,22 @@ flowchart TB
| Execution | `execution/*` | Agent Core、Extensions、Service Ports |
| Contracts | `contracts/*` | Stable Contracts、Security Control、Service Ports |
-Assembly 是唯一组装根,只选择下层能力和实现,不能反向依赖 app。每个生态 adapter 独立保留外部格式和顺序语义,再映射到 BitFun owner;生态 adapter 之间不能形成兄弟依赖。
+当前 Product Assembly 是唯一能力选择与 wiring 机制;Desktop、CLI、ACP 和 SDK Host 按已接入程度消费其结果。
+每个生态 adapter 独立保留外部格式和顺序语义,再映射到 BitFun owner;生态 adapter 之间不能形成兄弟依赖。
+
+#### 目标增量(尚未实现)
+
+目标在 Apps & Interfaces 增加 `apps/app-server` 与 `interfaces/app-server`,在 Adapters 增加
+`app-server-transport`,并在 Product Capabilities 增加唯一的 App Server backend profile;本机、服务端、
+网络和 tenant 安全策略是该 profile 的受信组装输入,不形成新部署形态。
+这些目标模块不能出现在“当前仓库快照”中,也不能在有生产 consumer 前建立占位 crate。迁移完成后删除
+`agent-runtime-ipc` 的独立 wire/server;详细模块和退出门槛见
+[`app-server-architecture-design.md`](app-server-architecture-design.md#8-非规范迁移说明)。
### 2.3 Process View · Level 0
-Process View 展示当前 Agent Runtime 内的异步任务、流和取消传播;Embedded 与 Shared 复用同一任务结构。本视图不描述具体部署环境,也不把一次用户场景误作进程结构。
+Process View 展示目标 Agent Runtime 内的异步任务、流和取消传播;App Server Embedded/Shared 与 Direct Runtime
+复用同一任务结构。本视图不描述具体部署环境,也不把一次用户场景误作进程结构。
```mermaid
flowchart LR
@@ -297,28 +321,39 @@ flowchart LR
### 2.4 Physical View · Level 0
-Physical View 展示当前可执行单元到设备、主机和存储的映射。Desktop、CLI、ACP 和 SDK Host 使用 Embedded Runtime;交互式 TUI 可以显式连接 Shared Runtime。当前 Web Server 和 Relay Server 都不承载 Agent Runtime。
+Physical View 展示**最终目标(尚未实现)**中可执行单元到设备、主机和存储的映射。第一方 Rich Client 经 App Server
+使用 Runtime;Headless CLI/CI、ACP 和 SDK Host 保留各自部署与协议。Relay 只承担账户、同步和控制转发,
+不能冒充 App Server 或 Runtime owner。
```mermaid
flowchart LR
subgraph LocalHost["Local Host"]
direction TB
- subgraph EmbeddedNodes["Embedded"]
+ subgraph ClientHosts["Trusted Rich Client Hosts"]
direction LR
- DesktopApp["Desktop App"] ~~~ CLIApp["CLI App"] ~~~ ACPApp["ACP"] ~~~ SDKHost["SDK Host"]
+ TauriHost["Tauri Host"] ~~~ ElectronHost["Electron Host"] ~~~ IDEHost["VS Code Extension Host"] ~~~ TUIHost["CLI / TUI Host"]
end
- SharedRuntime["Shared Runtime"]
+ DesktopApp["Tauri App Server · Embedded or Tauri-only Shared"]
+ ElectronApp["Electron App Server · Embedded or Electron-only Shared"]
+ IDEApp["VS Code App Server · Embedded or VS Code-only Shared"]
+ TUIApp["TUI App Server · Embedded or TUI-only Shared"]
+ DirectCLI["Headless CLI / CI · Direct Runtime"]
+ ACPApp["ACP · in-process composition"]
+ SDKHost["SDK Host"]
WorkspaceData["Workspace Data"]
ToolProcesses["Tool Processes"]
end
- subgraph UserDevice["Client Device"]
+ subgraph NetworkClients["Authenticated Network Clients"]
direction TB
WebClient["Web Client"]
MobileClient["Mobile Client"]
end
- WebServer["Web Server"]
+ WebBackend["Authenticated Web Backend"]
+ WebApp["Web App Server · Embedded or Web-only Shared"]
+ ServerData["Tenant Workspace / Session Data"]
+ ServerTools["Server Tool / Plugin Processes"]
subgraph RelayHost["Relay Node"]
direction TB
@@ -328,52 +363,83 @@ flowchart LR
end
AIProviders["AI Providers"]
- RemoteHosts["Remote Hosts"]
-
- WebClient -->|WebSocket| WebServer
+ RemoteRuntime["Target-side Remote Runtime Host"]
+
+ TauriHost -->|App Server protocol| DesktopApp
+ ElectronHost -->|App Server protocol| ElectronApp
+ IDEHost -->|App Server protocol| IDEApp
+ TUIHost -->|App Server protocol| TUIApp
+ WebClient -->|HTTPS / WebSocket| WebBackend
+ WebBackend -->|Authenticated App Server protocol| WebApp
+ WebApp --> ServerData
+ WebApp -->|spawn| ServerTools
+ WebApp -->|HTTPS| AIProviders
MobileClient -->|HTTPS| RelayServer
- DesktopApp <-->|WebSocket| RelayServer
- CLIApp <-->|WebSocket| RelayServer
- CLIApp -.->|Local IPC| SharedRuntime
+ TauriHost <-->|Authenticated control / sync| RelayServer
+ ElectronHost <-->|Authenticated control / sync| RelayServer
+ TUIHost <-->|Authenticated control / sync| RelayServer
RelayServer --> RelayDB
RelayServer --> AssetStore
- EmbeddedNodes --> WorkspaceData
- SharedRuntime --> WorkspaceData
- EmbeddedNodes -->|spawn| ToolProcesses
- SharedRuntime -->|spawn| ToolProcesses
- EmbeddedNodes -->|HTTPS| AIProviders
- SharedRuntime -->|HTTPS| AIProviders
- DesktopApp -->|SSH| RemoteHosts
+ DesktopApp --> WorkspaceData
+ ElectronApp --> WorkspaceData
+ IDEApp --> WorkspaceData
+ TUIApp --> WorkspaceData
+ DirectCLI --> WorkspaceData
+ ACPApp --> WorkspaceData
+ SDKHost --> WorkspaceData
+ DesktopApp -->|spawn| ToolProcesses
+ ElectronApp -->|spawn| ToolProcesses
+ IDEApp -->|spawn| ToolProcesses
+ TUIApp -->|spawn| ToolProcesses
+ DirectCLI -->|spawn| ToolProcesses
+ ACPApp -->|spawn| ToolProcesses
+ SDKHost -->|spawn| ToolProcesses
+ DesktopApp -->|HTTPS| AIProviders
+ ElectronApp -->|HTTPS| AIProviders
+ IDEApp -->|HTTPS| AIProviders
+ TUIApp -->|HTTPS| AIProviders
+ DirectCLI -->|HTTPS| AIProviders
+ ACPApp -->|HTTPS| AIProviders
+ SDKHost -->|HTTPS| AIProviders
+ DesktopApp -->|Remote adapter| RemoteRuntime
+ ElectronApp -->|Remote adapter| RemoteRuntime
+ IDEApp -->|Remote adapter| RemoteRuntime
+ TUIApp -->|Remote adapter| RemoteRuntime
classDef unit fill:#ffffff,stroke:#737373,stroke-width:1.3px,color:#171717;
- class DesktopApp,CLIApp,ACPApp,SDKHost,SharedRuntime,WorkspaceData,ToolProcesses,WebClient,MobileClient,WebServer,RelayServer,RelayDB,AssetStore,AIProviders,RemoteHosts unit;
+ class TauriHost,ElectronHost,IDEHost,TUIHost,DesktopApp,ElectronApp,IDEApp,TUIApp,DirectCLI,ACPApp,SDKHost,WorkspaceData,ToolProcesses,WebClient,MobileClient,WebBackend,WebApp,ServerData,ServerTools,RelayServer,RelayDB,AssetStore,AIProviders,RemoteRuntime unit;
style LocalHost fill:#ffffff,stroke:#737373;
- style EmbeddedNodes fill:#ffffff,stroke:#a3a3a3;
- style UserDevice fill:#ffffff,stroke:#a3a3a3;
+ style ClientHosts fill:#ffffff,stroke:#a3a3a3;
+ style NetworkClients fill:#ffffff,stroke:#a3a3a3;
style RelayHost fill:#ffffff,stroke:#737373;
```
-实线表示主要协议、存储访问或进程创建,虚线表示显式启用的 Shared TUI 本机连接。Relay DB 只在账户模式启用,Asset Store 的具体实现由部署配置选择。完整 package plugin 尚未形成生产闭环,因此不把规划中的 Plugin Host 画成当前部署实例。
+Embedded 与 Shared 复用 App Server schema、handler 和行为 fixture。每个 Shared instance 固定一个
+`client_kind`,Desktop、VS Code、TUI 与 Web 不混连。服务端运行使用独立网络认证、方法 allowlist、租户隔离、
+数据和 execution domain,但不形成 Hosted 第三形态。Relay DB 和 Asset Store 由账户/同步部署选择;Remote Runtime
+位于目标 execution domain,本机 App Server 不取得其 workspace lease。
| Deployment unit | Main contents |
|---|---|
-| Desktop App | Web UI、Tauri Host、embedded Agent Runtime |
-| CLI App | TUI、Headless、Peer;默认 Embedded,可显式使用 Shared TUI |
-| Shared Runtime | 私有本机 IPC;当前只有交互式 TUI consumer |
-| ACP | Embedded Agent Runtime、ACP 协议生命周期 |
-| SDK Host | 私有跨进程 adapter;公开 SDK 产品尚未交付 |
-| Web Server | Health、Info、WebSocket 外壳;不包含 Agent Runtime |
-| Relay Server | WebSocket/HTTP bridge、账户与同步;不包含 Agent Runtime |
+| Rich Client Host | Tauri/Electron/VS Code/TUI/Web 的宿主生命周期、认证和平台 capability;不拥有 Runtime 状态 |
+| App Server | 第一方 Rich Client 协议、产品组装根与有界 Runtime context registry;每个 workspace context 独立持有 ownership lease |
+| Headless CLI / CI | Direct Runtime、结构化输出、退出码与一次性生命周期 |
+| ACP | ACP adapter、独立协议生命周期和匹配的 Runtime composition |
+| SDK Host | 公开 Agent SDK 的独立 adapter/process;不复用 App Server wire |
+| Web Backend | 网络认证、授权、Origin/CORS、方法 allowlist 与 App Server 网络暴露 |
+| Networked App Server | Embedded 或 Web-only Shared 实例的网络暴露、租户隔离和 workspace/session ownership |
+| Relay Server | 账户、同步和控制转发;不成为 Agent Runtime 或 App Server owner |
+| Remote Runtime Host | 在目标 execution domain 持有 workspace、凭据、进程和 Runtime ownership |
### 2.5 Scenarios (+1) · Level 0
-Scenarios 选择少量具有架构意义的当前路径来校验前四个视图,不穷举产品功能,也不重复 Process View 的任务调度细节。
+Scenarios 选择少量具有架构意义的目标路径来校验前四个视图,不穷举产品功能,也不重复 Process View 的任务调度细节。
```mermaid
flowchart TB
subgraph InteractiveTurn["Chat Turn"]
direction LR
- TurnUser["User"] --> TurnHost["Product Host"] --> TurnCore["Agent Core"] --> TurnProvider["AI Provider"] --> TurnResponse["Response"]
+ TurnUser["User"] --> TurnHost["Rich Client Host"] --> TurnApp["App Server"] --> TurnCore["Agent Core"] --> TurnProvider["AI Provider"] --> TurnResponse["Response"]
end
subgraph ToolExecution["Tool Run"]
@@ -388,24 +454,27 @@ flowchart TB
subgraph RemoteControl["Remote Turn"]
direction LR
- RemoteClient["Mobile Client"] --> RemoteRelay["Relay Server"] --> RemoteDesktop["Desktop Host"] --> RemoteAPI["Runtime API"] --> RemoteCore["Agent Core"]
+ RemoteClient["Mobile Client"] --> RemoteRelay["Relay Server"] --> RemoteDesktop["Target Execution Host"] --> RemoteAPI["Runtime API"] --> RemoteCore["Agent Core"]
end
InteractiveTurn ~~~ ToolExecution ~~~ SourceDiscovery ~~~ RemoteControl
classDef step fill:#ffffff,stroke:#737373,stroke-width:1.3px,color:#171717;
- class TurnUser,TurnHost,TurnCore,TurnProvider,TurnResponse,ToolCore,ToolRuntime,ToolPorts,PlatformResource,ToolResult,SourceRoots,SourceAdapters,ControlPlane,SourceHost,RemoteClient,RemoteRelay,RemoteDesktop,RemoteAPI,RemoteCore step;
+ class TurnUser,TurnHost,TurnApp,TurnCore,TurnProvider,TurnResponse,ToolCore,ToolRuntime,ToolPorts,PlatformResource,ToolResult,SourceRoots,SourceAdapters,ControlPlane,SourceHost,RemoteClient,RemoteRelay,RemoteDesktop,RemoteAPI,RemoteCore step;
style InteractiveTurn fill:#ffffff,stroke:#a3a3a3;
style ToolExecution fill:#ffffff,stroke:#a3a3a3;
style SourceDiscovery fill:#ffffff,stroke:#a3a3a3;
style RemoteControl fill:#ffffff,stroke:#a3a3a3;
```
-四条路径分别覆盖核心对话、内置工具、运行时无关的外部来源发现,以及经 Relay 回到 Desktop owner 的远程控制。Source Scan 的发现与控制事实由 `ExternalSourceControlPlane` 统一持有,adapter 不成为第二个业务 owner。完整 package plugin、公开 SDK 产品和 HarmonyOS 不在当前生产闭环中,因此不作为 Level 0 场景。
+四条路径分别覆盖 Rich Client 对话、内置工具、运行时无关的外部来源发现,以及经 Relay 回到目标 execution
+host 的远程控制。Source Scan 的发现与控制事实由 `ExternalSourceControlPlane` 统一持有,adapter 不成为第二个业务 owner。
## 3. 接口边界
-BitFun 只保留四个稳定接口边界;工具、事件和权限作为归属子接口被复用,不在插件层重复定义。本文使用“接口”描述可被调用或依赖的能力面;只有描述跨进程消息封装、结构化 schema、序列化对象或强兼容约束时才使用“契约”;只读状态视图表示从权威状态派生出的查询结果。
+BitFun 只保留四个稳定能力接口边界;工具、事件和权限作为归属子接口被复用,不在插件层重复定义。Rich Client App Server
+是 Agent Runtime API 之上的版本化宿主通信契约,不新增第五个业务能力 owner。本文使用“接口”描述可被调用或依赖的能力面;
+只有描述跨进程消息封装、结构化 schema、序列化对象或强兼容约束时才使用“契约”;只读状态视图表示从权威状态派生出的查询结果。
| 接口边界 | 谁使用 | 提供 | 不包含 |
|---|---|---|---|
@@ -458,16 +527,17 @@ client 或未来 CLI/HarmonyOS 计划,不能证明同名 Rust transport adapte
### 3.2 宿主通信契约与 Tauri 薄适配
前后端契约按能力语义归属,不按 Tauri command 名称归属。稳定的请求、响应、状态事实和类型化错误放在对应
-`contracts/*`、Agent Runtime API 或能力归属模块;Tauri、HTTP/WebSocket、CLI/TUI、ACP 与公开 SDK
-Host adapter 只负责把各自协议映射到
-这些类型。该规则降低框架耦合,但不要求把每个 Desktop DTO 都搬进共享 crate。
+`contracts/*`、Agent Runtime API 或能力归属模块。Tauri、Electron、VS Code Extension、Web 与交互式 TUI 等第一方 Rich Client
+经版本化 App Server schema 消费这些事实;Headless CLI、ACP、Server/Remote 与公开 SDK Host adapter 仍按各自交付合同映射。
+该规则降低框架耦合,但不要求把每个 Desktop DTO 都搬进共享 crate,也不允许 App Server schema 反向成为领域 owner。
| 层 | 允许 | 禁止 |
|---|---|---|
| 能力归属模块 / Agent Runtime API | 字段明确的请求和响应、状态事实、权限/取消规则、与框架无关的用例方法 | `tauri::State`、`AppHandle`、窗口/菜单对象、command 宏、HTTP/WebSocket/ACP/SDK Host 消息结构 |
-| Desktop Tauri adapter | 读取宿主状态、构造稳定请求、调用对应 Agent Runtime API 或归属模块接口、把明确错误转换为 Desktop 协议、投递桌面事件 | 复制业务校验、持有第二份权威状态、把 Tauri 类型传入下层 |
+| Rich Client App Server | 组合版本化 JSON-RPC method、wire 投影、事件、错误、Host capability 与协议协商 | 领域行为 owner、公开 SDK 全量镜像、平台句柄或未经授权的远程能力面 |
+| Tauri / Electron / VS Code Host | 创建 Embedded 或发现完全相同 `client_kind` 的 Shared App Server,提供认证、窗口、剪贴板、文件选择等协商后平台能力 | 复制业务校验、持有第二份权威状态、把平台对象传入下层 |
| Server / Remote adapter | 路由鉴权、协议消息、连接生命周期、流量控制与取消转换 | 为同一能力另建业务含义不同的 DTO 或 handler |
-| GUI / TUI 消费方 | 依赖入口侧 API interface、稳定读模型或 Agent Runtime API;各自保留渲染状态 | 依赖公开 Python/TypeScript SDK、直接持有平台句柄,或让 React/TUI 状态成为后端契约 |
+| GUI / 交互式 TUI 消费方 | 依赖 App Server typed client 并各自保留渲染状态 | 依赖公开 Python/TypeScript SDK、直接持有平台句柄,或让 React/TUI 状态成为后端契约 |
本文其他章节和历史设计中出现的“Runtime SDK”,如果指 `agent-runtime::sdk`,统一称为
**Rust Runtime SDK(当前 preview)**;它是共享 **Agent Runtime API** 的当前 Rust 入口。只有
@@ -475,10 +545,15 @@ Host adapter 只负责把各自协议映射到
**BitFun Agent SDK**,其跨进程适配器称为 **SDK Host**。该术语区分不要求机械重命名现有 crate/module,但禁止用
Rust preview 的存在证明公开 SDK 已交付。
-第一方多实例目标称为 **Shared Agent Runtime deployment**。承载它的 Rust 进程与 SDK Host、Plugin Host、Server/Relay 和 Remote
-execution Host 都是不同职责;其部署与进程生命周期以
+第一方多实例目标称为 **Shared Agent Runtime deployment**,由 App Server 的 Shared 模式承载,不新增 Shared TUI/GUI server。
+每个 Shared instance 固定一种 `client_kind`;TUI、Desktop、VS Code 和 Web 可以复用 schema/handler,但不能混连同一实例。
+该 Rust 进程与 SDK Host、Plugin Host、Server/Relay 和 Remote execution Host 都是不同职责;其部署与进程生命周期以
[`agent-runtime-deployment-design.md`](agent-runtime-deployment-design.md) 为准。
+面向 Tauri、Electron、VS Code Extension、Web 与交互式 TUI 的统一后端协议称为 **Rich Client App Server**。它以同一
+schema/handler 只支持 Embedded 与 Shared deployment;其 Host capability、安全、版本和迁移边界以
+[`app-server-architecture-design.md`](app-server-architecture-design.md) 为准。
+
Rust 与 TypeScript 的字段一致性以能力所有者的 DTO 为事实源,不以 Tauri command 参数为事实源。单宿主阶段由
前端基础设施层维护对应接口,并用序列化契约测试锁定字段命名、可选字段和错误形状;达到独立版本化门槛后,才使用
不依赖 Tauri 的 JSON Schema 或类型生成任务输出只读 TypeScript 类型。生成结果只同步数据形状,不承载权限、重试或
@@ -515,22 +590,45 @@ Desktop command 使用的序列化对象继续留在 `src/apps/desktop`;即使
## 4. 运行协作细节
-本节在 Process View Level 0 之下展开产品入口、插件调用和平台能力的当前调用链;这些图描述组件协作,不构成新的 4+1 视图。
+本节在 Process View Level 0 之下展开产品入口、插件调用和平台能力的协作链;每张图明确标注当前或目标,
+不构成新的 4+1 视图。
### 4.1 产品入口
+当前生产调用链:
+
```mermaid
flowchart LR
- Products["GUI · TUI · CLI · Web"] --> Adapter["入口适配器"]
+ Desktop["Tauri Desktop"] --> Tauri["Tauri command/event adapters"] --> API["Runtime API / Core compatibility"]
+ TUI["Interactive TUI · default"] --> LegacyInProcess["legacy in-process Runtime client"] --> API
+ SharedTUI["Interactive TUI · --shared"] --> Legacy["agent-runtime-ipc"] --> API
+ Headless["Headless CLI / CI"] --> LegacyInProcess
+ ACP["ACP"] --> ACPAdapter["ACP adapter"] --> API
+```
+
+当前 `CliAgentRuntimeBackend` 只有 in-process 与 Shared IPC 两种实现;App Server assembly、typed client
+与 transport 尚未创建,Desktop 也仍使用 Tauri 路径。
+
+目标调用链(尚未实现):
+
+```mermaid
+flowchart LR
+ Rich["Tauri · Electron · VS Code · Web · Interactive TUI"] --> AppServer["Rich Client App Server"]
+ Products["Headless CLI"] --> Adapter["入口适配器"]
Protocol["ACP · Server · Remote"] --> Adapter
SDK["Agent SDK"] --> SDKHost["SDK Host"]
+ AppServer --> API["Runtime API"]
Adapter --> API["Runtime API"]
SDKHost --> API
API --> Runtime["共享 Runtime"]
Assembly["产品组装"] -. "选择" .-> Runtime
```
-入口 adapter 消费同一 Runtime API,部署选择不能进入业务 owner:Embedded 使用进程内强类型调用;Shared 或 SDK Host 才在各自私有 adapter 中执行 transport 封装。GUI、TUI、Headless CLI、ACP 和 SDK 不共享 wire、renderer 或生命周期,也不得为了统一接口而让默认 Embedded 路径承担序列化成本。
+入口最终消费同一 Runtime API,部署选择不能进入业务 owner。第一方 Rich Client(包括交互式 TUI)共享版本化 App Server
+wire。Embedded 与 Shared 使用同一个 schema 和 handler;Shared instance 按 `client_kind` 隔离。服务端组装根、网络安全和
+租户边界是正交约束,不形成 Hosted 第三形态。部署差异不能进入领域 owner。
+Headless CLI、ACP 与 SDK Host 不因 Rich Client 协议统一而共享 wire、renderer 或生命周期;Headless CLI/CI 默认 Direct Runtime,
+不承担无收益的后台进程和序列化成本。目标架构不保留第二套 Shared TUI server/wire。
### 4.2 插件调用
@@ -560,7 +658,8 @@ flowchart LR
关键规则:
-- 产品入口先经过自己的 adapter,再消费 Agent Runtime API 和只读视图;公开 SDK 只多一层 SDK Host 跨进程适配。
+- Rich Client 先经过 App Server adapter,其他产品入口经过自己的 adapter,再消费 Agent Runtime API 和只读视图;
+ 公开 SDK 只多一层 SDK Host 跨进程适配。
Agent Runtime API 是一组小而明确的用例接口,不是必须实例化的总入口;adapter 可以调用对应归属模块的少量接口,
但不能访问内部状态、绕过既有编排或复制业务规则。任何入口都不直接调用 Plugin Host。
- 插件只进入扩展贡献接口,不直接写内核状态、工具结果、权限结果或审计事实。
@@ -700,6 +799,11 @@ flowchart LR
也不执行产品定义中携带的任意脚本。
- Product Assembly 只消费产品组装结果和调用方唯一传入的 Delivery Profile;不读取原始品牌资源,
不运行构建脚本,也不从产品定义再次选择 Delivery。
+- 目标 App Server 使用唯一独立后端 Delivery Profile。App Server instance 在启动时固定产品身份、`client_kind`、数据命名空间、
+ 安全域、release channel、Runtime Configuration 和 capability 上限;连接的 Desktop/TUI/VS Code/Web Host
+ 不能用自身 profile 改写这些实例事实。
+- Shared App Server 只接受 `client_kind`、产品身份、数据命名空间、安全域、release channel、协议范围和 execution domain
+ 兼容的 Client;窗口、workspace、Session 或 plugin 数量不构成默认实例键,不同 `client_kind` 必须使用不同实例。
- GUI 与 TUI 布局由对应宿主独立校验,只共享产品身份、Capability ID、品牌资源索引和策略引用,不共享布局、
组件、主题键、键位或渲染状态。
- 布局选择只能引用宿主已注册的稳定 ID;品牌生成和校验继续使用仓库现有构建流程,不新增通用脚本运行时。
@@ -712,55 +816,39 @@ flowchart LR
产品形态由产品组装决定,不由插件配置、单个 Cargo feature 或生态适配器临时决定。
-当前本机入口组装:
+当前入口组装仍以 Desktop/CLI 的既有 profile 和 compatibility composition 为准;当前
+`DeliveryProfile` 没有 App Server 变体,不能把下图当作已接入能力。
-```mermaid
-flowchart TB
- Desktop["Desktop"] --> Full["product-full"]
- CLI["CLI / TUI"] --> Full
- ACP["ACP"] --> Parts["Runtime Parts"]
- SDKHost["SDK Host"] --> Parts
- ServerBootstrap["Server agent bootstrap · dormant"] --> Full
-
- Full --> Coordinator["ConversationCoordinator"]
- Parts --> Coordinator
- Ownership["CoreRuntimeOwnership"] -. "first-party composition injects once" .-> Coordinator
-```
-
-当前公开 HTTP Server 不调用 agent bootstrap,因此不创建 Runtime 或 workspace ownership;图中的 Server 节点只记录已有 agent-enabled composition 边界,不能据此宣称 Server Agent API 已交付。
-
-当前 Peer 运行连接:
+目标入口组装(尚未实现):
```mermaid
-flowchart LR
- Peer["Peer UI"] --> Host["Peer Host"]
-```
-
-尚未交付的公开 SDK 路径:
-
-```mermaid
-flowchart LR
- SDK["Public SDK"] -.-> Host["SDK Host"]
+flowchart TB
+ Rich["Desktop / TUI / VS Code / Web Host"] --> AppClient["App Server typed client"]
+ AppClient --> App["App Server · unique backend profile"]
+ Headless["Headless CLI / CI"] --> Direct["Direct Runtime composition"]
+ ACP["ACP"] --> ACPParts["ACP composition"]
+ SDKHost["SDK Host"] --> SDKParts["SDK composition"]
+
+ App --> RuntimeAPI["Agent Runtime API"]
+ Direct --> RuntimeAPI
+ ACPParts --> RuntimeAPI
+ SDKParts --> RuntimeAPI
+ RuntimeAPI --> Coordinator["Runtime owners"]
```
-| 当前入口 | 已有能力 | 明确边界 |
-|---|---|---|
-| Desktop | 使用 `product-full`;显示外部来源、审批、冲突、诊断和 Host 能力 | 可执行能力在事实所在 Host 运行;Safe Mode 只阻止新调用,不改来源、不取消正在运行的调用 |
-| CLI / TUI | 使用 `product-full`;提供 `/extensions`、统一 `/hooks`(旧 `/hooks_external` 为别名)、`/tools` 和 `/agents`;Claude Code/Codex 命令 Hook 可经显式审阅复制为原生层 | 生态解析仍在适配器,不启动第二套 Agent Runtime;OpenCode Hook 仍只静态发现;远程能力未接入时不回退本机 |
-| ACP | 使用 `DeliveryProfile::Acp` 和 Runtime Parts | load 成功后才发布活动状态;close 排空后再卸载;完整历史和配置仍由 Core/ACP 管理 |
-| Peer / Server | Server 提供 control/catalog;Peer Host 执行真实工作区操作;当前 HTTP Server 不装配 Agent Runtime | 控制端不替远端发现或执行;旧 Host 明确降级,SSH Remote 未接入时返回不支持;只读 Server 不声明 Runtime ownership |
-| Web / Mobile Web | 依赖现有后端入口 | 不持有插件执行单元,也不能据空 profile 宣称独立能力 |
-| HarmonyOS 手机 Remote | phone-only ArkTS 远程入口 | 不等于 HarmonyOS PC 本地 Runtime、CLI/TUI 或 GUI |
-
-| 目标形态 | 当前状态 | 设计边界 |
+| 目标入口 | 组装与协议 | 明确边界 |
|---|---|---|
-| HarmonyOS PC CLI/TUI | 未实现 | HAP、手机 Remote App 和远端代执行均不能替代 |
-| HarmonyOS PC GUI | 未实现 | 与 CLI/TUI 共享 Runtime 语义,但独立验证宿主、界面和发布 |
-| Public Agent SDK | Python/TypeScript 尚未交付;Rust Runtime SDK 是内部 preview | 一个 `AgentClient`、多个语言绑定;SDK Host 不依赖或冒充 CLI |
-
-Shared Agent Runtime 是第一方多实例的目标部署,不是上表新增的当前产品形态。当前文档中表示“事实实际所在位置”的泛称 Host
-可能仍指 Desktop 进程、Peer、Server 或 Remote execution host,不能据此推断 Shared deployment、多 Client Session 单写或
-跨进程重连已经交付;完成条件以
+| Tauri Desktop / Electron Desktop | App Server typed client;默认 Embedded;分别只能连接 Tauri-only / Electron-only Shared instance | 两种 Desktop Host 也不混连;Host 保留平台 capability 和界面状态 |
+| VS Code / Interactive TUI | App Server typed client;默认 Embedded,可连接自身 `client_kind` 的 Shared instance | 不与 Desktop/Web 混连同一 Shared Server |
+| Browser Web UI | 经认证 Web Backend 暴露 Embedded 或 Web-only Shared App Server | 网络方法 allowlist 与本机超集分离;浏览器不持有本机凭据 |
+| Headless CLI / CI | Direct Runtime;不作为 App Server client | `--shared` 仅属于交互式 TUI;未来非交互 attach 需独立稳定合同 |
+| ACP | 独立 ACP composition 和 wire | 不经 App Server 双重转换,不冒充公开 SDK |
+| Public Agent SDK | 独立 SDK Host composition 和 wire | 一个 `AgentClient`、多个语言绑定;SDK Host 不依赖或冒充 CLI/App Server |
+| Peer / Relay / Remote | Relay 负责账户、同步和控制转发;目标 execution host 持有 Runtime ownership | 控制端不替目标 host 发现或执行;能力不可用时类型化降级,不静默回落本机 |
+| HarmonyOS PC | 本地 CLI/TUI 与 GUI 分别作为匹配 Host 接入 Runtime/App Server | HAP、手机 Remote App 和远端代执行均不能替代本地产品形态 |
+
+App Server、SDK Host、ACP 和 Headless Direct Runtime composition 共享 Runtime API 与行为 fixture,但不共享 wire、
+进程生命周期或安全边界。Shared Agent Runtime 只由 App Server Shared deployment 承载,完成条件以
[`agent-runtime-deployment-design.md`](agent-runtime-deployment-design.md) 为准。
对外一级状态统一使用[外部 AI 工作内容设计](extensions/external-ai-work-sources-design.md#7-状态与提示规则)定义的
diff --git a/docs/architecture/product-customization-blueprint.md b/docs/architecture/product-customization-blueprint.md
index 73b7cf829..bc5f97c37 100644
--- a/docs/architecture/product-customization-blueprint.md
+++ b/docs/architecture/product-customization-blueprint.md
@@ -115,6 +115,14 @@ flowchart LR
3. 计算实际包含的产品能力,验证依赖、互斥项和平台要求。
4. GUI 或 TUI 交付只解析自己对应的布局选择;无界面交付不接收界面配置。
5. 解析内置扩展的固定版本、内容摘要、必要性和不可用时的产品行为。
+
+目标 App Server 是独立后端交付形态。它只消费后端所需的产品身份、数据命名空间、release channel、能力上限、
+默认策略引用和内置扩展事实,不消费 GUI/TUI 布局。Desktop、Electron、VS Code、Web 和 TUI Host 的布局选择仍由各自
+构建/宿主校验;连接自身 `client_kind` 的 Shared App Server 时,这些 Client 不能把自身布局或 Delivery Profile 注入 Server 组装。
+
+Shared discovery 只允许 `client_kind`、产品身份、数据命名空间、用户/组织安全域、release channel、协议兼容范围和 execution
+domain 相容的 Client 复用实例。不同 Client 形态、品牌或数据隔离域必须启动不同实例,不能依靠运行时切换
+客户端类型、品牌、数据根或产品策略。
6. 输出产品组装结果,供打包、签名和运行时启动使用。
交付形态与目标平台保持互不影响。HarmonyOS PC 原生 TUI 仍是 `CLI` 交付,不把 HAP 或手机 Remote App 写入 CLI
diff --git a/docs/plans/core-decomposition-plan.md b/docs/plans/core-decomposition-plan.md
index 73478da21..6a6412bea 100644
--- a/docs/plans/core-decomposition-plan.md
+++ b/docs/plans/core-decomposition-plan.md
@@ -23,7 +23,7 @@
|---|---|---|
| 产品能力组装 | `DeliveryProfile`、`ProductAssembler`、能力计划、服务可用性和测试已存在 | 这些是可测试的 assembly facts,不代表产品入口已接入 |
| CLI / Desktop / ACP | 三者仍按需启用 `bitfun-core/product-full`;CLI 与 ACP 已分别提交对应 `DeliveryProfile` 并消费 Runtime Parts/SDK,Desktop 主交互已消费由现有 owner 构造的窄口径 SDK 接口 | 三个入口均复用单一 Core owner;完整 Desktop profile 和剩余兼容操作仍需逐项迁移 |
-| Server | 当前生产路由只形成 health/info/ping 基线 | 没有插件状态或独立产品组装完整流程 |
+| Server | 当前生产路由包含 health/info/ping,以及 loopback WebSocket 上不启动 Agent Runtime 的 SSH-backed detached-dispatch controller/observer 操作 | 已有窄可变控制面,但没有完整 Server profile、插件状态或独立产品组装流程 |
| Server / Remote / Web / Mobile Web / SDK profile | 当前为空计划、未接入入口或仅有 preview 测试 | 不得据枚举值宣称产品能力已交付 |
| Agent Runtime SDK | 已有无 `bitfun-core` 依赖的 v2 preview 接口和 smoke test | 发布边界仍需真实嵌入方证明 |
| 插件运行时 | 现有路径只覆盖 BitFun 原生包和 OpenCode custom tool 静态名称预览 | 不能据通用消息结构或静态候选扩张稳定 ABI |
@@ -95,7 +95,9 @@ CLI-P0 整体退出条件尚未满足;真实供应商审批流、OS 级终端
### 4.4 最后晋级 Server、Remote 与 SDK
-- Server 先从现有 health/info/ping 基线选择一个真实 API 消费方,不预建完整产品 surface。
+- Server 后续切片从现有 health/info/ping 与窄 detached-dispatch 控制面选择真实产品 API 消费方;不得把该
+ loopback、无连接认证的 SSH-backed WebSocket envelope 当作完整产品 surface、网络 App Server 或远程入口;
+ 网络暴露不形成 Hosted 第三部署形态。
- Remote 必须在实际工作区执行域完成能力协商,不以本地 provider 代替。
- SDK 只有在外部或仓库内独立嵌入方无需 `bitfun-core/product-full` 即可完成最小 session/turn/event 流程后,才从 preview 晋级。
- 空 capability plan、disabled stub 和单元测试用于保护降级,不构成产品完成证据。
diff --git a/src/apps/cli/AGENTS.md b/src/apps/cli/AGENTS.md
index b185da02e..e656d4def 100644
--- a/src/apps/cli/AGENTS.md
+++ b/src/apps/cli/AGENTS.md
@@ -3,7 +3,9 @@
Scope: this guide applies to `src/apps/cli`.
Read [`docs/architecture/cli-product-line-design.md`](../../../docs/architecture/cli-product-line-design.md),
-[`docs/architecture/product-architecture.md`](../../../docs/architecture/product-architecture.md), and
+[`docs/architecture/product-architecture.md`](../../../docs/architecture/product-architecture.md),
+[`docs/architecture/app-server-architecture-design.md`](../../../docs/architecture/app-server-architecture-design.md),
+[`docs/architecture/agent-runtime-deployment-design.md`](../../../docs/architecture/agent-runtime-deployment-design.md), and
[`docs/architecture/product-customization-blueprint.md`](../../../docs/architecture/product-customization-blueprint.md)
before product-definition, TUI layout, branding, packaging, runtime, or plugin architecture changes.
@@ -18,6 +20,15 @@ before product-definition, TUI layout, branding, packaging, runtime, or plugin a
Desktop+CLI share one `device_id`; last AuthConnect wins.
- Shared session, turn, task, tool, permission, context, checkpoint, Subagent,
Harness, MCP, plugin, and capability facts belong to their runtime owners.
+- Interactive TUI is a Rich Client and must use `AppServerClient` in the target
+ architecture. Embedded and `--shared` deployments use one App Server wire;
+ the Embedded server is exclusive to one TUI client, and the Shared server is
+ TUI-only. Do not add operations or consumers to the legacy
+ `agent-runtime-ipc` protocol.
+- Headless CLI/CI remains Direct Runtime by default and must keep its stdout/stderr,
+ exit-code, startup, and lifecycle contract separate from interactive TUI. It
+ is not an App Server client; `--shared` remains interactive-TUI-only unless a
+ separate reviewed non-interactive contract is implemented.
- Existing `bitfun-core/product-full` compatibility paths may remain during a
reviewed migration. Do not add new concrete managers, global mutable services,
or CLI-only copies of shared product behavior.
diff --git a/src/crates/adapters/AGENTS-CN.md b/src/crates/adapters/AGENTS-CN.md
index 29deb4ee8..77d240e6f 100644
--- a/src/crates/adapters/AGENTS-CN.md
+++ b/src/crates/adapters/AGENTS-CN.md
@@ -8,7 +8,7 @@
| Crate | 职责 | 本地文档 |
|---|---|---|
-| `agent-runtime-ipc` | 不发布的私有本机 IPC adapter,为可选的第一方 Shared TUI Runtime 提供封闭交互操作 | [AGENTS.md](agent-runtime-ipc/AGENTS.md) |
+| `agent-runtime-ipc` | 旧 Shared TUI IPC,冻结并迁移到统一 App Server wire;禁止新增 operation 或 consumer | [AGENTS.md](agent-runtime-ipc/AGENTS.md) |
| `ai-adapters` | AI provider 请求/响应 adapter 与 stream protocol glue | [AGENTS.md](ai-adapters/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) |
diff --git a/src/crates/adapters/AGENTS.md b/src/crates/adapters/AGENTS.md
index 8e9f17533..3db8a91c5 100644
--- a/src/crates/adapters/AGENTS.md
+++ b/src/crates/adapters/AGENTS.md
@@ -11,7 +11,7 @@ services.
| Crate | Responsibility | Local doc |
|---|---|---|
-| `agent-runtime-ipc` | Non-published private local IPC adapter for the opt-in first-party Shared TUI Runtime; closed interactive operations only | [AGENTS.md](agent-runtime-ipc/AGENTS.md) |
+| `agent-runtime-ipc` | Legacy Shared TUI IPC, frozen for migration to the unified App Server wire; no new operations or consumers | [AGENTS.md](agent-runtime-ipc/AGENTS.md) |
| `ai-adapters` | AI provider request/response adapters and stream protocol glue | [AGENTS.md](ai-adapters/AGENTS.md) |
| `opencode-adapter` | OpenCode source semantics for the live Command, standalone Tool, Subagent, MCP, and static Hook providers; managed-package static preview | [AGENTS.md](opencode-adapter/AGENTS.md) |
| `claude-code-adapter` | Runtime-free Claude Code Command, Subagent, MCP, and Hook source semantics with redacted projection | [AGENTS.md](claude-code-adapter/AGENTS.md) |
diff --git a/src/crates/adapters/agent-runtime-ipc/AGENTS-CN.md b/src/crates/adapters/agent-runtime-ipc/AGENTS-CN.md
index 7f5a54515..77ff0f37e 100644
--- a/src/crates/adapters/agent-runtime-ipc/AGENTS-CN.md
+++ b/src/crates/adapters/agent-runtime-ipc/AGENTS-CN.md
@@ -1,25 +1,54 @@
**中文** | [English](AGENTS.md)
-# Agent Runtime IPC
+# Agent Runtime IPC 迁移指南
范围:`src/crates/adapters/agent-runtime-ipc`。
-该 crate 不发布,是第一方 Shared TUI adapter 使用的私有本机协议。它提供 discovery、单实例锁、有界 framing、认证初始化、封闭的交互操作集、Session controller lease、事件传递、连接上限和 cleanup;它不是公开 SDK、远程协议、service layer 或 Runtime owner。
-
-## 预集成约束
-
-- 唯一 consumer 是 `src/apps/cli` 中的第一方交互式 TUI adapter;不自动包含 GUI、Remote、Peer、ACP、Headless CLI 或 SDK Host。
-- 稳定测试合同包括本机 endpoint、严格 initialize-first、分离的握手/请求 deadline、128 KiB 请求与 8 MiB 响应/事件上限、有界连接、每个 Session 一个 controller、断线取消、30 秒空闲退出和 owner-checked discovery cleanup。
-- consumer 必须复用既有 Agent Runtime owners,并证明 Embedded/Shared 行为等价,不能依赖 SDK Host。
-
-## 边界
-
-- 只导出 CLI adapter 实际使用的 workspace-private API,且 crate 不得发布,也不得把 wire 作为 SDK 合同。
-- 封闭 operation 范围为 Health、Session list/create/restore(restore 结果包含 transcript)、当前 Session rename 和 Agent mode/model update、Turn submit/cancel、pending/respond Permission 和 UserInput answers。断连 cleanup 属于内部生命周期,不是 detach operation。模型目录和默认值仍是 wire 之外的产品配置;禁止顺带加入 delete、fork、replay、observer、controller transfer、Tool/MCP/Hook 管理或其他产品配置。
-- 可以复用稳定 Event、Product Domain 和 Runtime Port DTO。禁止依赖 `bitfun-core`、Agent Runtime 实现、SDK Host、services、Tauri、terminal、tool runtime 或远程 transport。
-- 只使用 Windows Named Pipe 或 Unix Domain Socket;禁止 TCP、HTTP、WebSocket、浏览器访问或远程 fallback。
-- 这是本机同用户隔离,不是沙箱。未来产品 composition 必须提供当前用户私有 runtime 目录。
-- Embedded 调用方必须继续以强类型直接调用 Agent Runtime,不能初始化本 transport。Shared 的 request、response 和 event frame 在写出前只编码一次;不能为了吞吐量削弱严格解码、未知字段拒绝、frame 上限、有界队列和背压。
+该 crate 是旧 Shared TUI 私有协议,只用于迁移,不是目标架构边界。最终架构中,交互式
+TUI、Desktop、Electron、VS Code 与 Web 的 Embedded/Shared 部署统一使用 App Server
+wire,但 Shared 实例按 `client_kind` 隔离,这些 Client 形态不连接同一个实例。修改前阅读
+[`docs/architecture/app-server-architecture-design.md`](../../../../docs/architecture/app-server-architecture-design.md)
+和
+[`docs/architecture/agent-runtime-deployment-design.md`](../../../../docs/architecture/agent-runtime-deployment-design.md)。
+
+## 迁移规则
+
+- 禁止向旧协议新增 operation、consumer、公开导出、transport 或产品能力。
+- App Server 纵向切片完成前,只允许为兼容和回归修复保持当前行为。
+- 删除旧实现前,将 controller lease、认证、frame 上限、断连取消、事件失效、
+ `outcome_unknown` 和 cleanup 提升为 App Server conformance tests。
+- 只有真正与协议无关的 Named Pipe/UDS、discovery、framing 或 budget 原语可以迁入 App
+ Server transport adapter;不得上移 TUI-specific operation envelope 或 handler。
+- 交互式 TUI 必须迁移到 `AppServerClient`:默认使用独占 Embedded App Server,
+ `--shared` 连接 TUI-only Shared App Server。
+- 旧 consumer 删除后,删除本 crate;或将其缩减为 App Server 内部 transport 实现,不再
+ 拥有独立 wire 语义。
+
+## 当前生产合同
+
+在最后一个 Shared TUI consumer 迁移并满足删除门槛前,该协议虽不是目标边界,仍是生产合同:
+
+- 唯一 consumer 是 `src/apps/cli` 中的第一方交互式 TUI adapter;GUI、Remote、Peer、ACP、
+ Headless CLI 和 SDK Host 都不是 consumer。
+- 只使用本机 Windows Named Pipe 或 Unix Domain Socket。Windows 当前拒绝远程 Client 并要求 bearer
+ 握手,但代码尚未显式安装仅 owner 可访问的 pipe DACL,也未校验 peer SID;完成实现和跨用户拒绝测试前
+ 不得宣称同用户隔离。Unix 保持仅 owner 可访问的 discovery/socket 权限。禁止 TCP、HTTP、WebSocket、
+ 浏览器访问或远程 fallback;本机 transport 加认证不是沙箱。
+- 第一帧必须是 initialize,并分离握手/request deadline。初始化校验协议版本、instance identity、
+ bearer token、client ID 和 client version;token 与 discovery secret 必须脱敏。错误 token、错误
+ instance、版本不匹配、初始化前请求和未认证连接耗尽仍是拒绝测试。
+- 拒绝未知字段与 operation。请求 frame 上限为 128 KiB,响应/事件 frame 上限为 8 MiB;连接、
+ 队列、pending request 和序列化缓冲必须有界并实施背压。
+- 封闭 operation 范围为 Health、Session list/create/restore(含 transcript)、当前 Session rename
+ 与 Agent mode/model update、Turn submit/cancel、pending/respond Permission 和 UserInput answers。
+ 禁止加入 delete、fork、replay、Observer、controller transfer、Tool/MCP/Hook 管理或产品配置。
+- 保持每个 Session 一个 Controller、每个连接一个 active Turn,以及断连取消、`outcome_unknown`、
+ 事件流粘性失效、30 秒空闲退出和 owner-checked discovery cleanup。
+- 旧的进程内调用方与 Headless Direct Runtime 调用方继续强类型直调 Agent Runtime,不初始化本 transport。
+ Shared frame 写出前只编码一次;吞吐优化不得放宽严格解码、边界或背压。
+
+只有等价 App Server 限制具备测量依据、conformance/overload 测试和明确兼容性决策后,迁移才可调整
+某个限制;在此之前原值保持不变。
## 验证
diff --git a/src/crates/adapters/agent-runtime-ipc/AGENTS.md b/src/crates/adapters/agent-runtime-ipc/AGENTS.md
index 3a5c3e17f..ac7528410 100644
--- a/src/crates/adapters/agent-runtime-ipc/AGENTS.md
+++ b/src/crates/adapters/agent-runtime-ipc/AGENTS.md
@@ -1,43 +1,76 @@
[中文](AGENTS-CN.md) | **English**
-# Agent Runtime IPC
+# Agent Runtime IPC Migration
Scope: `src/crates/adapters/agent-runtime-ipc`.
-This non-published crate is the private local protocol used by the first-party Shared TUI adapter.
-It provides discovery, one-instance locking, bounded framing, authenticated initialization, a closed interactive operation set,
-session controller leases, event delivery, connection bounds, and cleanup. It is not a public SDK, remote protocol, service layer, or Runtime owner.
-
-## Pre-integration contract
-
-- Only consumer: the first-party interactive TUI adapter in `src/apps/cli`.
- GUI, Remote, Peer, ACP, Headless CLI, and SDK Host are not implied consumers.
-- Stable test contract: platform-local endpoint, strict initialize-first handshake, separate handshake/request deadlines,
- 128 KiB request and 8 MiB response/event limits, bounded connections, one controller per Session, one active Turn per connection,
- disconnect cancellation, sticky event-stream invalidation, 30-second idle exit, and owner-checked discovery cleanup.
-- Integration check: the consumer must reuse existing Agent Runtime owners and
- prove Embedded/Shared behavior equivalence without depending on SDK Host.
-
-## Boundaries
-
-- Export only the exact workspace-private API needed by the CLI adapter. Do not
- publish this crate or expose its wire as an SDK contract.
-- The closed operation budget is Health, Session list/create/restore (including transcript), current-Session rename and Agent mode/model update,
- Turn submit/cancel, pending/respond Permission, and UserInput answers. Disconnect cleanup is internal lifecycle, not a detach operation.
- Model catalogs and defaults remain product configuration outside this wire. Do not add delete, fork, replay, observer,
- controller transfer, Tool/MCP/Hook management, or other product configuration incidentally.
-- Stable Event, Product Domain, and Runtime Port DTOs may be reused. Do not
- depend on `bitfun-core`, Agent Runtime implementations, SDK Host, services,
- Tauri, terminal, tool runtime, or remote transports.
-- Use only Windows Named Pipes or Unix Domain Sockets. Do not add TCP, HTTP,
- WebSocket, browser access, or remote fallback.
-- Treat this as same-user local isolation, not a sandbox. Product composition
- must supply a user-private runtime directory.
-- Embedded callers must continue to invoke the typed Agent Runtime directly and
- must not initialize this transport. Shared outgoing request, response, and
- event frames are encoded once before write; strict decoding, unknown-field
- rejection, frame limits, bounded queues, and backpressure must not be weakened
- for throughput.
+This crate is the legacy private Shared TUI protocol. It is migration-only and
+is not a target architecture boundary. The final architecture uses one App
+Server wire for interactive TUI, Desktop, Electron, VS Code, and Web across
+Embedded and Shared deployments. Shared instances are isolated by
+`client_kind`; those client forms never connect to one instance. Read
+[`docs/architecture/app-server-architecture-design.md`](../../../../docs/architecture/app-server-architecture-design.md)
+and
+[`docs/architecture/agent-runtime-deployment-design.md`](../../../../docs/architecture/agent-runtime-deployment-design.md).
+
+## Migration Rules
+
+- Do not add operations, consumers, public exports, transports, or product
+ capabilities to this protocol.
+- Preserve current behavior only for compatibility and regression fixes while
+ the App Server vertical slice is incomplete.
+- Promote controller leases, authentication, frame bounds, disconnect
+ cancellation, event invalidation, `outcome_unknown`, and cleanup into App
+ Server conformance tests before removing their old implementations.
+- Move only genuinely protocol-neutral Named Pipe/UDS, discovery, framing, or
+ budget primitives into the App Server transport adapter. Do not carry the
+ TUI-specific operation envelope or handler upward.
+- Interactive TUI must migrate to `AppServerClient`: default TUI uses an
+ exclusive Embedded App Server and `--shared` connects a TUI-only Shared App
+ Server.
+- Remove this crate, or reduce it to an App Server-internal transport
+ implementation with no independent wire semantics, once the old consumer is
+ gone.
+
+## Current Production Contract
+
+Until the last Shared TUI consumer migrates and the deletion gates pass, this
+remains a production contract even though it is not a target boundary:
+
+- The only consumer is the first-party interactive TUI adapter in
+ `src/apps/cli`. GUI, Remote, Peer, ACP, Headless CLI, and SDK Host are not
+ consumers.
+- Use only a local Windows Named Pipe or Unix Domain Socket. Windows rejects
+ remote clients and requires the bearer handshake, but the current code does
+ not explicitly install an owner-only pipe DACL or verify the peer SID; do not
+ claim same-user isolation until that is implemented and tested. Unix keeps
+ owner-only discovery/socket permissions. Do not add TCP, HTTP, WebSocket,
+ browser access, or remote fallback; local transport plus authentication is
+ not a sandbox.
+- Require initialize as the first frame and use separate handshake/request
+ deadlines. Initialization validates protocol version, instance identity,
+ bearer token, client ID, and client version; token and discovery secrets stay
+ redacted. Invalid token, wrong instance, protocol mismatch, pre-initialize
+ requests, and unauthenticated connection exhaustion remain rejection tests.
+- Reject unknown fields and operations. Request frames are limited to 128 KiB;
+ response/event frames are limited to 8 MiB. Connections, queues, pending
+ requests, and serialized buffers remain bounded and backpressured.
+- The closed operation budget is Health; Session list/create/restore including
+ transcript; current-Session rename and Agent mode/model update; Turn
+ submit/cancel; pending/respond Permission; and UserInput answers. Do not add
+ delete, fork, replay, Observer, controller transfer, Tool/MCP/Hook management,
+ or product configuration.
+- Keep one Controller per Session and one active Turn per connection. Preserve
+ disconnect cancellation, `outcome_unknown`, sticky event-stream invalidation,
+ 30-second idle exit, and owner-checked discovery cleanup.
+- Legacy in-process and Headless Direct Runtime callers continue to invoke the
+ typed Agent Runtime directly and do not initialize this transport. Shared
+ frames are encoded once before write; throughput work must not relax strict
+ decoding, bounds, or backpressure.
+
+Migration may change a limit only after the equivalent App Server limit has a
+measured rationale, conformance and overload tests, and an explicit compatibility
+decision. Until then, carry the current value forward unchanged.
## Verification