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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions docs/comparison/qwen-code-daemon-design/01-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
- **心智简单**:daemon ↔ session 两层(无中间抽象)

**两种部署**:
- **Mode B** `qwen serve` — 当前主线:headless HTTP front,所有 client 通过 HTTP/SSE 接入同一 daemon runtime。
- **Mode B** `qwen serve` — 当前主线:headless HTTP front,优先服务 remote web chat + web terminal;native local TUI 保持 direct runtime,channel / IDE 继续现有 `--acp` 路径
- **Mode A** `qwen --serve` — 2026-05-15 后暂停推进;作为 parking lot 保留,待 Mode B event/control/client contract 稳定后再评估。

**主线 scope**:daemon building block + 协议表面锁定(Stage 2 后)。多 tenant / 跨 daemon process 路由 / SaaS 部署属 **External Reference Architecture**(外部商业平台实施)。
Expand All @@ -36,7 +36,7 @@
|---|---|---|
| **Daemon process** | `qwen serve` HTTP front 进程;启动时绑定 cwd = 单 workspace;持 Express 5 server + EventBus + 1 个内嵌 `qwen --acp` child | `packages/cli/src/serve/server.ts` |
| **Session** | ACP `Session` 实例(`QwenAgent.sessions: Map<sessionId, Session>` 内一条);持 transcript / FileReadCache / PermissionManager | `packages/cli/src/acp-integration/session/Session.ts` |
| **Daemon client / adapter** | TUI / channel / web / IDE / JSONL 等 client 通过 `DaemonClient` / `DaemonSessionClient` + typed event reducer 接入,不直接订阅内存 EventBus | 详 [§02 §8](./02-architectural-decisions.md#8-server--client--runtime-boundary2026-05-18) |
| **Daemon client / adapter** | remote web chat / web terminal / future channel / future IDE / JSONL 等 client 通过 `DaemonClient` / `DaemonSessionClient` + typed event reducer 接入,不直接订阅内存 EventBus;native local TUI 保持 direct runtime,但可复用 shared render core | 详 [§02 §8](./02-architectural-decisions.md#8-server--client--runtime-boundary2026-05-18) |
| **Runtime worker** | 真正执行 tool / shell / MCP / skills / LSP / file operations 的 runtime;当前是 `qwen --acp` child,未来可替换 sandbox runner | 详 [§02 §8](./02-architectural-decisions.md#runtime-worker--sandbox-runner-boundary) |

**核心约束**:
Expand Down Expand Up @@ -84,7 +84,7 @@ client adapters / output sinks
→ runtime worker / sandbox runner
```

TUI / web terminal / channel / IDE / JSONL / stream-json 都应成为 daemon-native consumers:消费 typed events + shared reducer,再投影到各自 UI 或输出格式。PTY proxy 只保留为兼容 / demo / debug fallback。remote-control 是 control overlay,不再拥有独立 runtime / event protocol。详 [§02 §8](./02-architectural-decisions.md#8-server--client--runtime-boundary2026-05-18)。
remote web chat / web terminal / JSONL / stream-json 优先成为 daemon-native consumers:消费 typed events + shared reducer,再投影到各自 UI 或输出格式。channel / IDE 后续若迁移也复用同一 contract。native TUI 复用 shared render core 但保持 direct runtime。PTY proxy 只保留为兼容 / demo / debug fallback。remote-control 是 control overlay,不再拥有独立 runtime / event protocol。详 [§02 §8](./02-architectural-decisions.md#8-server--client--runtime-boundary2026-05-18)。

External Reference Architecture 提供 orchestrator 层(详 [§06 §五 External Reference Architecture](./06-roadmap.md))。

Expand All @@ -94,12 +94,12 @@ External Reference Architecture 提供 orchestrator 层(详 [§06 §五 Extern

| 模式 | 启动命令 | TUI | 适用场景 |
|---|---|---|---|
| **Mode B: Headless + HttpServer** | `qwen serve [--port N]` | ❌ | 当前主线:服务器 / 容器 / 远端机器 / K8s pod / 所有 client 的统一 runtime |
| **Mode B: Headless + HttpServer** | `qwen serve [--port N]` | ❌ | 当前主线:服务器 / 容器 / 远端机器 / K8s pod / remote web chat + web terminal runtime |
| **Mode A: CLI + HttpServer** | `qwen --serve [--port N]` | ✅ 本地 | 暂停推进;作为 parking lot 保留 |

**当前 client 边界**:TUI / channels / web / IDE 直接对接 `qwen serve` HTTP server;`GET /session/:id/events` 是 daemon 内部 EventBus 的 SSE projection。外部 client 不直接 import / subscribe 内存 EventBus。
**当前 daemon client 边界**:remote web chat / web terminal 直接对接 `qwen serve` HTTP server;`GET /session/:id/events` 是 daemon 内部 EventBus 的 SSE projection。外部 client 不直接 import / subscribe 内存 EventBus。native TUI / channel / IDE 当前默认链路不变

**Mode B 远端 client 是 "thin shell"**(Stage 1)——只能渲染 wire 流,daemon-side state dialogs(`/memory` / `/mcp` / `/agents` 等)不可用。Stage 1.5c daemon-side state CRUD 补齐后,TUI / channels / web / IDE 才能成为完整 client。详 [§04](./04-deployment-and-client.md)。
**Mode B 远端 client 是 "thin shell"**(Stage 1)——只能渲染 wire 流,daemon-side state dialogs(`/memory` / `/mcp` / `/agents` 等)不可用。Stage 1.5c daemon-side state CRUD 补齐后,remote web chat / web terminal 才能成为完整 client。详 [§04](./04-deployment-and-client.md)。

### 三·一 Deployment forms(来自 chiga0 [#3803 comment 4476174099](https://github.com/QwenLM/qwen-code/issues/3803#issuecomment-4476174099),2026-05-18)

Expand Down Expand Up @@ -146,9 +146,9 @@ Mode B 之下进一步区分**3 种 deployment form**,钉死 daemon host 与 w
| **Stage 1.5a must-haves** **(P0)** | chiga0 10 must-haves 剩 9 项 — Mode B 生产 blocker(loadSession HTTP / pair tokens / sessionScope override)| ~2 周(9 PRs 可并行)|
| **Stage 1.5c** **(P0)** | daemon-side state CRUD 8 routes — Mode B 远端 client 摆脱 thin shell | ~3-5d |
| **Stage 1.5-prereq** **(P1)** | chiga0 6 architecture findings — lift `AcpChannel` / `EventBus` / `PermissionMediator` 到 `@qwen-code/acp-bridge` | ~1-2 周 |
| **Stage 1.5-client adapters** **(P1 behind flag)** | TUI / channels / web/debug / IDE 接入 Mode B daemon;默认切换必须等 P0/P1 | ~2-3 周 |
| **Stage 1.5-client/render** **(P1 / POC 并行)** | remote web chat + web terminal 技术 POC;抽 shared client/render core;channel / IDE 后置;native TUI 保持 direct | ~1-2 周 POC,可与 P0 并行 |
| **Stage 1.5b** Mode A **(P2 推迟)** | Mode A `qwen --serve` flag — [Issue #4156](https://github.com/QwenLM/qwen-code/issues/4156);A1 [PR#4160](https://github.com/QwenLM/qwen-code/pull/4160) ✅ MERGED;**推迟到 1.5c 后**(Mode A 价值依赖 1.5c)| ~5-6d |
| **Stage 1.5-remote-control** **(P2 后置)** | [PR#3929](https://github.com/QwenLM/qwen-code/pull/3929) / [#3930](https://github.com/QwenLM/qwen-code/pull/3930) / [#3931](https://github.com/QwenLM/qwen-code/pull/3931) 后续作为 daemon facade | 待 primary clients 收敛 |
| **Stage 1.5-remote-control** **(P2 后置)** | [PR#3929](https://github.com/QwenLM/qwen-code/pull/3929) / [#3930](https://github.com/QwenLM/qwen-code/pull/3930) / [#3931](https://github.com/QwenLM/qwen-code/pull/3931) 后续作为 daemon facade | 待 remote web contract 稳定 |
| **Stage 2** | 协议补齐(WebSocket / mDNS / OpenAPI / Prometheus / `/ext` + Reverse RPC 5 类 Client Capability)| ~3-4 周(拆 2a-2d)|
| **Stage 2e** | 可选 native in-process(去 `qwen --acp` child)| ~1-2 周 |

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
| **Session** | daemon 内嵌 `qwen --acp` child 的 `QwenAgent.sessions: Map` 内一条 |
| **Daemon server** | HTTP/SSE API + auth + session lifecycle + EventBus projection + control-plane routes;当前在 `packages/cli/src/serve` |
| **Daemon client SDK** | `DaemonClient` / `DaemonSessionClient` + typed event schema + reducer + reconnect / heartbeat / capability negotiation |
| **Client adapter** | TUI / channel / web / IDE / JSONL / stream-json / dual-output 等渲染或输出层;只消费 daemon client SDK / protocol surface |
| **Client adapter** | remote web chat / web terminal / future channel / future IDE / JSONL / stream-json / dual-output 等渲染或输出层;只消费 daemon client SDK / protocol surface。native TUI 保持 direct runtime,但可复用 source-independent render core |
| **Runtime worker** | 真正执行 model/tool/shell/MCP/skills/LSP/file operations 的 runtime;当前是 `qwen serve → qwen --acp child`,未来可替换为 sandbox runner |
| **Control overlay** | remote-control / channel / web/mobile ingress;只作为 daemon facade,不拥有独立 runtime protocol |

Expand Down Expand Up @@ -175,7 +175,7 @@ OpenCode default 是 1 daemon 多 workspace(`Map<workspace, Instance>` ALS in-

### 重复 spawn 代价

同 user 同 workspace N session 当前会有 N 套 MCP children。多 workspace 同 user = M daemon × N session × MCP sets。单 MCP ~50-200MB,若未来 TUI / channels / IDE 大量并发 session,MCP pool/proxy 会变成 Stage 2/2e 的资源优化项。
同 user 同 workspace N session 当前会有 N 套 MCP children。多 workspace 同 user = M daemon × N session × MCP sets。单 MCP ~50-200MB,若 remote web chat / web terminal 或未来 channel / IDE daemon 化带来大量并发 session,MCP pool/proxy 会变成 Stage 2/2e 的资源优化项。

---

Expand Down Expand Up @@ -278,17 +278,17 @@ ACP 协议本身就是"client → agent → 同步 response"语义,不允许

| 模式 | 启动命令 | TUI | 适用场景 |
|---|---|---|---|
| **Mode B: Headless + HttpServer** | `qwen serve [--port N]` | ❌ | 当前主线:服务器 / 容器 / 远端机器 / K8s pod / 所有 client 的统一 runtime |
| **Mode B: Headless + HttpServer** | `qwen serve [--port N]` | ❌ | 当前主线:服务器 / 容器 / 远端机器 / K8s pod / remote web chat + web terminal runtime |
| **Mode A: CLI + HttpServer** | `qwen --serve [--port N]` | ✅ 本地 | 暂停推进;待 Mode B contract 稳定后再评估 |

当前 client 直接边界是 HTTP server:TUI / channels / web / IDE 通过 `DaemonSessionClient` 调用 `POST /session/:id/*`,通过 `GET /session/:id/events` 消费 SSE。EventBus 是 daemon 内部 fan-out primitive;`EventBus lift` 指抽出 typed event contract / reducer / server-side primitive,不是让外部 client 直接 subscribe 内存对象。
当前 daemon client 直接边界是 HTTP server:remote web chat / web terminal 通过 `DaemonSessionClient` 调用 `POST /session/:id/*`,通过 `GET /session/:id/events` 消费 SSE。EventBus 是 daemon 内部 fan-out primitive;`EventBus lift` 指抽出 typed event contract / reducer / server-side primitive,不是让外部 client 直接 subscribe 内存对象。native TUI / channel / IDE 默认链路暂不迁移

### 依据

1. **PR#3889 已实现 Mode B**(Stage 1 ✅ MERGED 2026-05-13)。
2. **PR#4113 已把 Mode B 边界收紧到 1 daemon = 1 workspace**(✅ MERGED 2026-05-15)。
3. **TUI / channels / web / IDE 是 primary clients**,应先统一到 daemon HTTP/SSE + typed event contract。
4. **remote-control 后置**,等 primary clients 收敛后再作为 daemon facade 复用同一 contract。
3. **remote web chat / web terminal 是 primary daemon clients**,应先验证 daemon HTTP/SSE + typed event contract。
4. **remote-control / channel / IDE daemon migration 后置**,等 remote web contract 收敛后再复用同一 contract。
5. **Mode A 暂停**,避免在 event/control/client contract 稳定前引入第二条 in-process 暴露路径。

### TUI 在多 session daemon 下的语义
Expand All @@ -297,15 +297,15 @@ ACP 协议本身就是"client → agent → 同步 response"语义,不允许

- **本地单用户 `qwen` TUI = 传统单进程 in-process direct call**,**永远不走网络**(local default 永久路径,最高优先级 UX)。详下方 🌟 设计原则。
- **Mode B TUI adapter**([PR#4266](https://github.com/QwenLM/qwen-code/pull/4266) `--experimental-daemon-tui`)= **opt-in advanced**,仅 multi-client 协作场景。**永远 behind flag,不进入 default migration**。
- **channels / web / IDE / remote TUI** 通过 `DaemonSessionClient` 接入——它们本来就是跨进程 client,daemon 是它们唯一可行路径
- **remote web chat / web terminal** 先通过 `DaemonSessionClient` 接入,作为当前 daemon 技术 POC 主场景;channel / IDE 继续现有 `--acp` 路径,daemon 化后置评估
- **daemon-side control-plane parity** 落地后,跨进程 remote clients 才能覆盖 memory / MCP / skills / tools / agents / auth / provider / context 等状态。
- **Mode A** 保留为 parking lot;如未来要支持 "本地多 client 协作"(IDE + TUI 同 session live collaboration),**Mode A in-process TUI + 内嵌 HTTP server 可能比 Mode B + TUI adapter 更合适**——in-process TUI 保留零网络体验,HTTP server 仅服务其他 client。待 chiga0 auto-daemon UX 工程债重新评估时一并 revisit。

### 🌟 设计原则(2026-05-18 确认)— 不要为你不需要的东西付费

**本地单用户 TUI 是 daemon 项目最高优先级 UX**。任何 default migration 设计**不可破坏**这个体验。

| 维度 | 本地单用户 TUI **必须** in-process(永远)| 跨进程 client (IDE / channel / web / remote TUI) 走 daemon |
| 维度 | 本地单用户 TUI **必须** in-process(永远)| remote web chat / web terminal 走 daemon |
|---|---|---|
| 启动延迟 | 直起 Ink (~0 网络) | ~50-200ms loopback HTTP handshake 可接受 |
| 进程数 | 1 binary | 2+ (daemon + client) 必然 |
Expand All @@ -318,7 +318,7 @@ ACP 协议本身就是"client → agent → 同步 response"语义,不允许
**因此**:
- ❌ "Local-Local 用户 TUI 通过 loopback `qwen serve`" **不能成为现有用户默认迁移目标**(与 §04 §六 deployment shapes table 早期措辞冲突,已修正)
- ❌ chiga0 #3803 comment 4476174099 的 "auto-daemon UX" 草图(`qwen → discover daemon → if absent auto-start → attach TUI`)**仅适用于用户主动选 multi-client 协作场景**,不适合作 local default
- ✅ Wave 5 PR 26 `flag-gated daemon client adapters` **scope 收紧**:仅 channel / web / IDE default 切换,**TUI default 不切换**
- ✅ Wave 5 PR 26 **scope 再收紧**:先做 remote web chat / web terminal 技术 POC + shared render/client core;channel / IDE daemon 化后置,**TUI default 不切换**

---

Expand All @@ -332,7 +332,8 @@ Mode B 终态架构按三层逻辑边界收敛:

```text
client adapters / output sinks
TUI / channel / web chat / web terminal / IDE / JSONL / stream-json
remote web chat / web terminal / future channel / future IDE / JSONL / stream-json
native TUI shares render core but stays direct runtime
↓ depend on
daemon client/protocol layer
DaemonClient / DaemonSessionClient / typed event schema / reducer
Expand Down Expand Up @@ -364,9 +365,9 @@ runtime worker / sandbox runner
typed event schema, reducers, reconnect, heartbeat, capability negotiation

@qwen-code/daemon-adapters-*
tui adapter
channel adapter
ide/web adapter
web chat adapter
web terminal adapter
optional channel / IDE adapters after daemon stabilization
jsonl / stream-json / dual-output sinks
```

Expand All @@ -375,13 +376,14 @@ runtime worker / sandbox runner
| 约束 | 含义 |
|---|---|
| Server 不依赖 adapters | `serve` / daemon server 不能 import TUI / IDE / channel renderer |
| Adapters 只依赖 client/protocol | TUI / channel / web / IDE 不可直接拿 `HttpAcpBridge` / EventBus 内部对象 |
| Adapters 只依赖 client/protocol | remote web chat / web terminal / future channel / future IDE 不可直接拿 `HttpAcpBridge` / EventBus 内部对象 |
| Render core source-independent | native streamJson 与 daemon events 可投影到同一 view model,但 native TUI 不因此改走 daemon transport |
| Reducer / typed events 在 client/protocol 层 | 不能散落在 `packages/cli/src/serve` 或某个 adapter 私有实现里 |
| Output sinks 也是 adapter | JSONL / stream-json / dual-output 走同一 typed event stream,不再各自驱动 runtime |

### Daemon-native renderer 是目标形态

TUI adapter、web terminalweb chatIDE panelchannel cards 都应消费同一 typed daemon event contract:
web terminal / web chat 是第一优先的 daemon-native renderer;future IDE panel / channel cards 如后续迁移,也应消费同一 typed daemon event contract。native TUI 复用 render/view-model core,但不改走 daemon transport

```text
daemon SSE event
Expand Down Expand Up @@ -441,11 +443,11 @@ remote-control 后续不得重新拥有 runtime、event log 或 worker server。
这条架构决策不要求当前 PR 立即重构实现,但会改变后续 PR 的验收标准:

1. `DaemonSessionClient` 继续作为 client adapter 的唯一 session 级入口。
2. typed event schema + reducer 必须逐步成为 TUI / web / IDE / channel / JSONL / stream-json 的共享消费面。
3. TUI / web terminal wire-up 应做 daemon-native renderer,而不是 PTY proxy 默认路径。
4. channel / remote-control 只能做 daemon facade / ingress overlay,不可 fork runtime/event protocol。
2. typed event schema + reducer 必须优先成为 remote web chat / web terminal / JSONL / stream-json 的共享消费面,后续 channel / IDE 如迁移也复用
3. web terminal wire-up 应做 daemon-native renderer,而不是 PTY proxy 默认路径;native TUI 保持 direct runtime
4. channel / IDE / remote-control 如后续接 daemon,只能做 daemon facade / ingress overlay,不可 fork runtime/event protocol。
5. sandbox / runtime worker 抽象应在 Wave 5/Stage 2 后续设计中预留 failure isolation 和 runtime locality diagnostics。
6. 所有 client PR 必须 behind flag / default off,且声明验证的 deployment shape 和 locality 假设(详 [§04](./04-deployment-and-client.md#deployment-shape-matrixclientruntime-lens2026-05-18))。
6. 所有 daemon client PR 必须 explicit entrypoint / default off,且声明验证的 deployment shape 和 locality 假设(详 [§04](./04-deployment-and-client.md#deployment-shape-matrixclientruntime-lens2026-05-18))。

---

Expand All @@ -459,7 +461,7 @@ remote-control 后续不得重新拥有 runtime、event log 或 worker server。
| 4 | FileReadCache 共享 | **per-session 严格私有**(同 daemon N session 各自实例不共享;跨 daemon 自然独立)+ PR#3774 prior-read 守卫 + PR#3810 5 路径 invalidation | PR#3717 / PR#3774 / PR#3810 |
| 5 | Permission flow | 复用 PR#3723 + daemon 第 4 mode + SSE permission_request | PR#3723 evaluatePermissionFlow() |
| 6 | 多 client 并发 | **同 session prompt 串行(FIFO)+ 事件 fan-out + 任何 client 可应答 permission** | PR#3889 commit `ca996ecb5`(FIFO + no-poison)+ ACP 协议语义 + EventBus subscriber set |
| 7 | 部署模式 | **Mode B mainline;Mode A parking lot** | 2026-05-15 决策:优先 TUI / channels / web / IDE 接入 Mode B;remote-control 后置 |
| 7 | 部署模式 | **Mode B mainline;Mode A parking lot** | 2026-05-19 决策:优先 remote web chat / web terminal 技术 POC;native TUI direct;channel / IDE / remote-control 后置 |
| 8 | Server / client / runtime boundary | **server control plane / daemon client-protocol / adapters / runtime worker 分层**;daemon-native renderer 为目标;remote-control 只是 control overlay | 2026-05-18 deployment/package/runtime comments;§04 deployment shape matrix;§06 deployment + package contract |

---
Expand Down
Loading