diff --git a/docs/comparison/qwen-code-daemon-design/01-overview.md b/docs/comparison/qwen-code-daemon-design/01-overview.md index 7f0d99b..c28ba39 100644 --- a/docs/comparison/qwen-code-daemon-design/01-overview.md +++ b/docs/comparison/qwen-code-daemon-design/01-overview.md @@ -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**(外部商业平台实施)。 @@ -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` 内一条);持 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) | **核心约束**: @@ -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))。 @@ -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) @@ -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 周 | diff --git a/docs/comparison/qwen-code-daemon-design/02-architectural-decisions.md b/docs/comparison/qwen-code-daemon-design/02-architectural-decisions.md index 5661640..ce24ea7 100644 --- a/docs/comparison/qwen-code-daemon-design/02-architectural-decisions.md +++ b/docs/comparison/qwen-code-daemon-design/02-architectural-decisions.md @@ -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 | @@ -175,7 +175,7 @@ OpenCode default 是 1 daemon 多 workspace(`Map` 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 的资源优化项。 --- @@ -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 下的语义 @@ -297,7 +297,7 @@ 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。 @@ -305,7 +305,7 @@ ACP 协议本身就是"client → agent → 同步 response"语义,不允许 **本地单用户 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) 必然 | @@ -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 不切换** --- @@ -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 @@ -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 ``` @@ -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 terminal、web chat、IDE panel、channel 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 @@ -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))。 --- @@ -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 | --- diff --git a/docs/comparison/qwen-code-daemon-design/04-deployment-and-client.md b/docs/comparison/qwen-code-daemon-design/04-deployment-and-client.md index 7fb471a..6311f56 100644 --- a/docs/comparison/qwen-code-daemon-design/04-deployment-and-client.md +++ b/docs/comparison/qwen-code-daemon-design/04-deployment-and-client.md @@ -4,7 +4,7 @@ ## TL;DR -**2026-05-15 更新**:先忽略 Mode A(`qwen --serve`),以 **Mode B `qwen serve`** 作为唯一主线。TUI / channels / web / IDE 都应作为 daemon HTTP/SSE client 接入;EventBus 是 daemon 内部 fan-out primitive,client 共享的是 typed event contract + reducer + `DaemonSessionClient`,不是直接订阅内存 EventBus。 +**2026-05-19 更新**:先忽略 Mode A(`qwen --serve`),以 **Mode B `qwen serve`** 作为 remote web chat + web terminal runtime 主线。native local TUI 永久 direct;channel / IDE 继续 `--acp`,daemon 化后置。EventBus 是 daemon 内部 fan-out primitive,daemon clients 共享的是 typed event contract + reducer + `DaemonSessionClient`,不是直接订阅内存 EventBus。 **多 client 协调**(P1 拓扑):subscriber 协议 + liveness(15s SSE heartbeat + TCP RST 即时剔除)+ active typer 提示 + takeover + first-responder permission。 @@ -16,7 +16,7 @@ | 模式 | 启动命令 | TUI | 适用场景 | |---|---|---|---| -| **Mode B: Headless + HttpServer** | `qwen serve [--port N]` | ❌ | 当前主线:服务器 / 容器 / 远端机器 / 所有 client 的统一 runtime | +| **Mode B: Headless + HttpServer** | `qwen serve [--port N]` | ❌ | 当前主线:服务器 / 容器 / 远端机器 / remote web chat + web terminal runtime | | **Mode A: CLI + HttpServer** | `qwen --serve [--port N]` | ✅ 本地 | 暂停推进;parking lot | 当前主线只有 Mode B。详 [§02 §7](./02-architectural-decisions.md#7-部署模式--mode-b-mainline--mode-a-parking-lot)。 @@ -39,7 +39,7 @@ > > **走 daemon 的场景仅限**:远端 client / 跨进程多 client 协作(IDE + TUI 同 session live collaboration)/ channel bot / web BFF。本地单用户 TUI **永远不被强制套上 HTTP 包袱**。 > -> [PR#4266](https://github.com/QwenLM/qwen-code/pull/4266) `--experimental-daemon-tui` 是 **opt-in advanced 路径**(用户主动选 multi-client 协作时),**永远 behind flag,不进入 default migration**。Wave 5 PR 26 `flag-gated daemon client adapters` 默认覆盖 channel / web / IDE,**不含 TUI default 切换**。Mode A `qwen --serve`(TUI super-client + 内嵌 HTTP server)可能比 Mode B + TUI adapter 更适合 "本地多 client 协作" —— 待 chiga0 `auto-daemon UX` 工程债重新评估时一并 revisit。 +> [PR#4266](https://github.com/QwenLM/qwen-code/pull/4266) `--experimental-daemon-tui` 是 **opt-in advanced 路径**(用户主动选 multi-client 协作时),**永远 behind flag,不进入 default migration**。Wave 5 PR 26 现在应优先收敛为 **remote web chat + web terminal 技术 POC + shared render/client core**;channel / IDE daemon 化后置。Mode A `qwen --serve`(TUI super-client + 内嵌 HTTP server)可能比 Mode B + TUI adapter 更适合 "本地多 client 协作" —— 待 chiga0 `auto-daemon UX` 工程债重新评估时一并 revisit。 ### Client 接入顺序 @@ -47,10 +47,11 @@ | 顺序 | Client | 适配方向 | |---|---|---| -| 第一波 | TUI | attach-to-daemon render target;HTTP/SSE + shared reducer — 实施 spike 详 [PR#4202](https://github.com/QwenLM/qwen-code/pull/4202) `feat(tui): add daemon adapter spike` (+864 LOC) | -| 第一波 | channels | 新 daemon transport,保留 channel routing — 实施 spike 详 [PR#4203](https://github.com/QwenLM/qwen-code/pull/4203) `feat(channel): add daemon bridge spike` (+813 LOC) | -| 第一波 | web/debug | [PR#4132](https://github.com/QwenLM/qwen-code/pull/4132) `/demo` 作为最薄验证面 + [PR#4203](https://github.com/QwenLM/qwen-code/pull/4203) channel/web BFF 共用安全边界 | -| 第二波 | IDE | daemon transport behind flag — 实施 spike 详 [PR#4199](https://github.com/QwenLM/qwen-code/pull/4199) `feat(ide): add daemon connection spike` | +| 第一波 | remote web chat | BFF / browser UI 消费 daemon HTTP/SSE typed events;验证真实 prompt streaming、permission、cancel/model、reconnect、auth/token 边界 | +| 第一波 | web terminal | daemon-native renderer;复用 shared terminal render core / view model;不以 PTY proxy 作为主线 | +| 参考 | TUI | [PR#4202](https://github.com/QwenLM/qwen-code/pull/4202) 和 [PR#4266](https://github.com/QwenLM/qwen-code/pull/4266) 仅作 default-off spike / future multi-client 参考;native TUI 默认不迁 | +| 后置 | channels | [PR#4203](https://github.com/QwenLM/qwen-code/pull/4203) 仅作 server-side bridge spike;默认继续 `--acp` | +| 后置 | IDE | [PR#4199](https://github.com/QwenLM/qwen-code/pull/4199) 仅作 daemon connection spike;默认继续 `--acp` | | 并行 | JSONL / stream-json / dual-output | daemon event sinks | | P2 deferred | remote-control | 后置;作为 daemon facade / control overlay,不意味着 daemon 必须远端 | @@ -138,7 +139,7 @@ QWEN_DAEMON_WORKSPACE=/repo ## 二、TUI / client 边界 -Stage 1 的 Mode B client 只能覆盖 conversation 主链路。要让 TUI / channels / web / IDE 成为完整 client,需要先补 P0 的 production must-haves 与 daemon-side control-plane parity,再补 P1 typed event contract / bridge primitives;client adapters 只能先 behind flag。 +Stage 1 的 Mode B client 只能覆盖 conversation 主链路。remote web chat / web terminal 可以先做技术 POC,用真实体验反向暴露缺口;要 production-ready,需要先补 P0 的 production must-haves 与 daemon-side control-plane parity,再补 P1 typed event contract / bridge primitives。native TUI、channel、IDE 默认链路暂不迁移。 ### TUI 形态 4 种 @@ -153,7 +154,7 @@ Stage 1 的 Mode B client 只能覆盖 conversation 主链路。要让 TUI / cha > > 本地单用户 TUI **不需要** loopback HTTP / port / token / discovery / lifecycle / control-plane parity wire 化,**就不应该被强加这些代价**。`qwen` 默认是 daemon 项目里**最高优先级的用户体验**,任何 default migration 设计都不可破坏这个 UX。 > -> 走 daemon convergence 的 client(channel / web / IDE / remote TUI)是**主动选择跨进程协作**的场景;本地单用户 TUI **不在此列**。 +> 走 daemon convergence 的第一优先 client 是 remote web chat / web terminal;channel / IDE / remote TUI 属于后续主动选择跨进程协作的场景;本地单用户 TUI **不在此列**。 ### TUI 与 wire 的边界 — 9 项 dialogs 真实成本 @@ -308,15 +309,15 @@ T=25 Alice 笔记本醒来重连 → daemon 通知 "Bob 接管了" |---|---|---|---|---|---| | **1. Local - Local (本地单用户 TUI)** 🌟 | **本地 `qwen` TUI = in-process direct call**(永远不走网络)| 不存在 daemon | 本地 | **零网络栈代价**;本地 TUI 不参与 daemon convergence(详 [§04 §一 设计原则](#mode-b-拓扑核心特征) + [§02 §7](./02-architectural-decisions.md#7-部署模式--mode-b-mainline--mode-a-parking-lot))| **永久 default UX,最高优先级** | | **1b. Local - Local (multi-client 协作)** | IDE / local web / channel adapter(**TUI 不在此列**)| 本机 loopback `qwen serve` | 本机 | auto-daemon discovery / loopback auth / lifecycle / port+token+logs;control-plane parity | 跨进程多 client 协作场景;TUI 默认 in-process 不切换 | -| **2. Web chat / web terminal - Remote** | browser UI | remote devbox / pod | remote volume | gateway/auth/CORS;SSE reconnect;runtime diagnostics;web terminal 走 daemon-native renderer,PTY proxy 仅 fallback | cloud/devbox P1 | -| **3. Local IDE - Local daemon** | IDE extension | 本机 loopback daemon | IDE 当前 workspace | IDE 启动/发现 daemon;workspace mismatch preflight;editor context 显式传入;path identity 共享 | P1 early dogfood | +| **2. Web chat / web terminal - Remote** | browser UI | remote devbox / pod | remote volume | gateway/auth/CORS;SSE reconnect;runtime diagnostics;web terminal 走 daemon-native renderer,PTY proxy 仅 fallback | **第一优先技术 POC,可与 P0 并行** | +| **3. Local IDE - Local daemon** | IDE extension | 本机 loopback daemon | IDE 当前 workspace | IDE 启动/发现 daemon;workspace mismatch preflight;editor context 显式传入;path identity 共享 | 后置评估;默认继续 `--acp` | | **4. Local TUI - Remote** | 本地 terminal renderer | remote daemon/runtime | remote workspace | TUI 明示 remote label/path/auth;local cwd 非 runtime cwd;path mapping / client capability reverse RPC;latency coalescing | P1 after TUI adapter quality | -| **5. Channel + daemon** | IM/channel backend adapter | local 或 remote daemon | daemon-bound workspace | user/group/thread → session routing;identity mapping;permission cards;dedupe;长任务通知 | P1 behind flag | +| **5. Channel + daemon** | IM/channel backend adapter | local 或 remote daemon | daemon-bound workspace | user/group/thread → session routing;identity mapping;permission cards;dedupe;长任务通知 | 后置评估;默认继续 `--acp` | | **6. Remote-control overlay** | web/mobile/channel control surface | local daemon + bridge 或 remote daemon + gateway | local workstation 或 remote devbox | pairing/revoke;outbound bridge;audit;不 fork runtime/protocol | P2 after client contract stabilizes | #### Web terminal:daemon-native renderer,不是 PTY proxy 主线 -Web chat 和 web terminal 都应消费 daemon typed events / reducer。差异只在 UI 呈现:chat UI 用 DOM chat renderer,web terminal 用 terminal-like renderer。TUI adapter 已经是在做 Ink/terminal 版的 **daemon-native renderer**;web terminal 应复用同一 contract。 +Web chat 和 web terminal 都应消费 daemon typed events / reducer。差异只在 UI 呈现:chat UI 用 DOM chat renderer,web terminal 用 terminal-like renderer。shared terminal render core 应让 native TUI direct streamJson 与 web terminal daemon events 复用 view model / Ink->ANSI 投影,但 native TUI 不因此改走 daemon transport。 PTY proxy 仍可作为兼容 / demo / debug fallback,但不能成为目标架构:它代理 terminal bytes,会重新耦合进程生命周期,并绕开 typed event / reducer convergence。 @@ -489,7 +490,7 @@ Laptop Remote workstation ## 七、与 PR#3929-3931 (remote-control stack) 的关系 -2026-05-15 决策后,remote-control 优先级后置。它仍然可以作为 mobile/browser/channel control overlay 存在,但不应继续拥有 parallel runtime / event log / worker server。正确方向是等 TUI / channels / web / IDE 先收敛到 Mode B daemon contract 后,remote-control 再复用同一 `DaemonSessionClient` + HTTP/SSE typed event contract。 +2026-05-19 决策后,remote-control 优先级后置。它仍然可以作为 mobile/browser/channel control overlay 存在,但不应继续拥有 parallel runtime / event log / worker server。正确方向是先验证 remote web chat / web terminal 的 Mode B daemon contract,remote-control 后续再复用同一 `DaemonSessionClient` + HTTP/SSE typed event contract。 **重要澄清(2026-05-18)**:remote-control 不要求 daemon 必须在远端。它至少有两种有效部署形态: @@ -512,7 +513,7 @@ PR#3929-3931 当前仍是 draft / changes requested。简表: | Mobile / browser UI | 先由 web/debug + IDE/TUI adapters 定 contract | ✅ 自带最小化 mobile/browser UI(PR#3930 +2564 行)| | Pairing token + LAN URL | ❌ 仅 bearer token | ✅ 一次性 pairing token + LAN URL 报告 | | Capability 反向 RPC(5 类)| ✅ editor / clipboard / browser / notification / file_picker | ❌ 无反向 RPC——permission approve/deny 通过 stream-json 直接路由 | -| 2026-05-15 处理 | 主线;优先 TUI / channels / web / IDE | 后置;未来应改为 daemon facade | +| 2026-05-19 处理 | 主线先验证 remote web chat / web terminal | 后置;未来应改为 daemon facade | --- diff --git a/docs/comparison/qwen-code-daemon-design/06-roadmap.md b/docs/comparison/qwen-code-daemon-design/06-roadmap.md index cc72055..b9ecdc9 100644 --- a/docs/comparison/qwen-code-daemon-design/06-roadmap.md +++ b/docs/comparison/qwen-code-daemon-design/06-roadmap.md @@ -4,7 +4,7 @@ ## TL;DR -**2026-05-15 roadmap reset**:先忽略 Mode A(`qwen --serve`),以 **Mode B:`qwen serve` headless daemon** 作为唯一主线。Stage 1 ✅ MERGED 2026-05-13(PR#3889)→ Stage 1.5a ✅ MERGED 2026-05-15(PR#4113,1 daemon = 1 workspace)→ Stage 1.5 继续做 Mode B event/control/client convergence。执行优先级对齐 upstream 最新 roadmap:**P0 = 9 个 production must-haves + daemon-side state CRUD**;client adapters 先 behind flag,默认切换必须等 P0/P1 基础完成;remote-control / Mode A 后置。Stage 2 做协议和生态补齐。**Stage 2 后协议表面锁定**——后续不扩展 wire 协议;平台层(orchestrator / 多租户 / sandbox / SaaS)由 External Reference Architecture 实施。 +**2026-05-19 roadmap update**:先忽略 Mode A(`qwen --serve`),以 **Mode B:`qwen serve` headless daemon** 作为 remote web chat + web terminal 的底层 runtime 主线。P0 仍是 production must-haves + daemon-side state CRUD;同时把 remote web chat + web terminal 技术 POC 提前,可与 P0 并行启动,用真实 web UX 反向暴露 contract 缺口。production-ready 仍要等 P0/P1 contract / bridge / security / release hardening 收口。native local TUI 永久 direct runtime;channel / IDE 继续 `--acp`,daemon 化后置;remote-control / Mode A 后置。Stage 2 做协议和生态补齐。**Stage 2 后协议表面锁定**——后续不扩展 wire 协议;平台层(orchestrator / 多租户 / sandbox / SaaS)由 External Reference Architecture 实施。 **与竞品定位**:qwen-code daemon = building block + Unix-style 可组合;OpenCode 走端到端 SaaS;Anthropic Managed Agents 是托管服务。详 §五 / §六。 @@ -20,7 +20,7 @@ qwen-code 主线 1.5a must-haves/P0 ███ identity + lifecycle + reliability must-haves(~1-2w) Stage 1.5c/P0 ███ daemon-side control-plane parity / state CRUD(~1-2w) 1.5-prereq/P1 ███ typed event contract + shared DaemonSessionClient(~1w) - client adapters/P1 █████ primary clients behind flag: TUI / channels / web / IDE(~2-3w) + web POC/P1 █████ remote web chat + web terminal POC + shared render/client core(~1-2w,并行 P0) remote-control/P2 ▒▒▒ remote-control revisit(后置,复用 daemon facade) Stage 1.5b/P2 ▒▒▒ Mode A revisit(后置) Stage 2 ████████ 2a-2d(~3-4w) @@ -114,7 +114,7 @@ capability registry → DaemonSessionClient → typed events | **2.5** Reliability + session lifecycle closure | client heartbeat + SSE replay sizing + slow-client warnings + session metadata/close-delete lifecycle | PR 9-11 — ✅ **3/3 MERGED**:PR 9 [#4235](https://github.com/QwenLM/qwen-code/pull/4235) + PR 10 [#4237](https://github.com/QwenLM/qwen-code/pull/4237) + PR 11 [#4240](https://github.com/QwenLM/qwen-code/pull/4240) 2026-05-17 | 1.5a #4 reliability + #2 lifecycle closure | | **3** Read-only control plane + diagnostics | read-only status routes + preflight/env diagnostics + MCP guardrails (measurement, not full pool) | PR 12-14 — ✅ **3/3 + PR 14b 全 MERGED**:PR 12 [#4241](https://github.com/QwenLM/qwen-code/pull/4241) + PR 13 [#4251](https://github.com/QwenLM/qwen-code/pull/4251) 2026-05-17 + PR 14 [#4247](https://github.com/QwenLM/qwen-code/pull/4247) 2026-05-18 + follow-up PR 14b [#4271](https://github.com/QwenLM/qwen-code/pull/4271) 2026-05-18 17:06 | 1.5c read-only + chiga0 diagnostics | | **4** Auth-gated mutation/control routes | **mutation gating helper** + memory/agents CRUD + approval/tools/init/MCP-restart + FileSystemService 边界 + safe file read + file write/edit + auth device-flow | PR 15-21 — ✅ **7/7 完整 MERGED** 🎉:PR 15/16/17/18/19/20/21 全合 (#4236/#4249/#4282/#4250/#4269/#4280/#4255) | 1.5c CRUD + 文件 routes | -| **5** Architecture extraction + output sinks + full multi-client security | bridge primitives extraction + real MCP shared pool (config-hash keyed) + pairing revocation + full PermissionMediator + 独立 output sinks + flag-gated client adapters | PR 22-26 — ✅ PR 22a [#4295](https://github.com/QwenLM/qwen-code/pull/4295) MERGED + ✅ PR 22b/1 [#4298](https://github.com/QwenLM/qwen-code/pull/4298) MERGED + ✅ PR 22b/2 [#4304](https://github.com/QwenLM/qwen-code/pull/4304) MERGED design slice + ⏳ PR 22b/3 待开 mechanical bulk lift(**PR 22 拆 4 阶段 3/4 MERGED**);PR 23/24/25/26 ⏳ | 1.5-prereq full + 1.5a #3 full + adapter migration | +| **5** Architecture extraction + output sinks + full multi-client security | bridge primitives extraction + real MCP shared pool (config-hash keyed) + pairing revocation + full PermissionMediator + 独立 output sinks + remote web chat / web terminal POC + shared render/client core | PR 22-26 — ✅ PR 22a [#4295](https://github.com/QwenLM/qwen-code/pull/4295) MERGED + ✅ PR 22b/1 [#4298](https://github.com/QwenLM/qwen-code/pull/4298) MERGED + ✅ PR 22b/2 [#4304](https://github.com/QwenLM/qwen-code/pull/4304) MERGED design slice + ⏳ PR 22b/3 待开 mechanical bulk lift(**PR 22 拆 4 阶段 3/4 MERGED**);PR 23/24/25/26 ⏳ | 1.5-prereq full + 1.5a #3 full + web client/render POC | | **6** Release hardening + v0.16 | alpha release docs + npm alpha publish + **production token defaults** (`~/.qwen/serve/instances/--/token`) + deployment refs + v0.16 release | PR 27-31 | Stage 2 + release | ### Wave 1 — Protocol foundation(无依赖,可立即开始) @@ -138,7 +138,7 @@ capability registry → DaemonSessionClient → typed events #### Stage 1 / 2 adapter wire-up + experimental flag-gated (chiga0, 2026-05-18) -> chiga0 把 adapter migration 工作进一步拆 **3 adapter × 3 stage = 9 PR**。Stage 0 spike 是 protocol primitive(已 ✅ 3/3),Stage 1 是 developer harness(reviewer 手验 + 不替换 production path),Stage 2 是 experimental flag-gated(真接入 production 渲染链,behind `--experimental-daemon-tui` / `qwen-code.experimentalDaemonIde` flag)。 +> chiga0 已合入的 3 个 adapter Stage 0 PR(channel / IDE / TUI)现在只作为 **default-off spike / future migration 参考**。2026-05-19 之后不继续把 3 adapter × 3 stage 当作主线推进;主线改为 remote web chat / web terminal POC + shared render/client core。 | Stage | PR | 内容 | 状态 | |---|---|---|---| @@ -204,7 +204,7 @@ chiga0 设计哲学(每 PR 反复出现):**existing default path remains u | **PR 23** `feat(mcp): shared MCP transport/process pool` | 真共享 pool,keyed by canonical workspace + server **config hash** + auth/env/runtime inputs;lifecycle/refcount tests(依赖 PR 22, 14)| ⏳ | | **PR 24** `feat(security): client pairing revocation + PermissionMediator` | pair tokens + revocation API + audit log + 4 policy strategies(first-responder / designated / consensus / local-only)(依赖 PR 8, 22)| ⏳ | | **PR 25** `refactor(output): daemon-compatible output sinks` | JSONL / stream-json / dual-output behavior 移到 protocol/output sink 边界后;让 CLI + daemon client 共享 event semantics 而不是 duplicate terminal-specific logic(依赖 PR 4, 22)—— PR#4226 doudouOUC 平行 reducer 实现可拆这里提前 | ⏳ | -| **PR 26** `feat(adapters): flag-gated daemon client adapters` | 开始 TUI / channels / web-debug / IDE adapter migration behind flag,用 `DaemonSessionClient`;如 ownership/review size 需要可按 adapter 拆分;3 bonus spike [PR#4202](https://github.com/QwenLM/qwen-code/pull/4202) / [PR#4203](https://github.com/QwenLM/qwen-code/pull/4203) / [PR#4199](https://github.com/QwenLM/qwen-code/pull/4199) 已铺路(依赖 PR 3, 4, 25)| ⏳ | +| **PR 26** `feat(web): daemon web clients + render-core extraction` | remote web chat / web terminal 接入 `DaemonSessionClient`;抽取 source adapter / view model / terminal render core,让 native TUI direct streamJson 与 web terminal daemon events 复用渲染核心。PR#4202 / #4203 / #4199 仅作 default-off spike 参考;不要求 TUI/channel/IDE 默认迁移(依赖 PR 3, 4, 25)| ⏳ | #### PR 22b/1 ([#4298](https://github.com/QwenLM/qwen-code/pull/4298)) 工程明细 @@ -311,14 +311,14 @@ chiga0 设计哲学(每 PR 反复出现):**existing default path remains u | 何时 npm alpha publish? | Wave 1 + 足够的 Wave 2 后 + release docs ready;不阻塞所有 control-plane routes | | Loopback 默认 token? | v0.15 alpha 保持现状 + 加 `--require-auth`(PR 15);v0.16 改 token-by-default + SDK auto-discovery + explicit opt-out | | Token instance path? | `~/.qwen/serve/instances/--/token`(多 daemon 共存)+ PID metadata(替代 port-only 路径)| -| 如何 align PR#3929-3931 remote-control? | 等 primary clients 稳定后改为 daemon facade / control overlay;同时承认 **local daemon + remote-control relay** 和 **remote daemon + gateway** 两种形态,避免 parallel runtime/protocol fork | +| 如何 align PR#3929-3931 remote-control? | 等 remote web chat / web terminal contract 稳定后改为 daemon facade / control overlay;同时承认 **local daemon + remote-control relay** 和 **remote daemon + gateway** 两种形态,避免 parallel runtime/protocol fork | | Worktree 交互? | `boundWorkspace` 仍是 boot-time daemon workspace;file routes 默认 bound-workspace safety;worktree-specific 行为必须显式,不是隐式 `process.chdir()` | --- ### 三·二 Deployment + package contract (chiga0 #3803 comment 2026-05-18) -来源:chiga0 [Issue #3803 comment 4476174099](https://github.com/QwenLM/qwen-code/issues/3803#issuecomment-4476174099) + [comment 4476318030](https://github.com/QwenLM/qwen-code/issues/3803#issuecomment-4476318030) (GPT-5 Codex 协助生成),**在 Wave 4 收尾、Wave 5 adapter migration 真要默认切换前,提议钉死 deployment / package / renderer / remote-control 契约**: +来源:chiga0 [Issue #3803 comment 4476174099](https://github.com/QwenLM/qwen-code/issues/3803#issuecomment-4476174099) + [comment 4476318030](https://github.com/QwenLM/qwen-code/issues/3803#issuecomment-4476318030) (GPT-5 Codex 协助生成),2026-05-19 修订为:**在 Wave 5 web/client-render POC 开始前,钉死 deployment / package / renderer / remote-control 契约**。旧的“所有 client 默认迁 daemon”口径不再作为主线。 #### 1. Deployment forms 3 类(详 [§01 §三·一](./01-overview.md#三一-deployment-forms来自-chiga0-3803-comment-4476174099-2026-05-18)) @@ -414,9 +414,9 @@ daemon 保 **control plane / session-event coordinator**,sandbox/runtime worke #### 5. Client default migration gate(3-condition checklist) -> ⚠️ **TUI default 永远不切换**([§02 §7 设计原则](./02-architectural-decisions.md#7-部署模式--mode-b-mainline--mode-a-parking-lot))。本 gate **仅适用 channel / web / IDE** 三类跨进程 client。 +> ⚠️ **TUI default 永远不切换**([§02 §7 设计原则](./02-architectural-decisions.md#7-部署模式--mode-b-mainline--mode-a-parking-lot))。当前 gate **优先适用 remote web chat / web terminal**;channel / IDE daemon migration 后置。 -channel / web / IDE default 切换到 daemon-backed 必须等: +remote web chat / web terminal 从 technical POC 进入 production-ready 必须等: 1. **control-plane parity** —— 跨进程 client 所需 mutating route 在 daemon API 全 wire 化(详 [§04 §二 9 项 dialog](./04-deployment-and-client.md)) 2. **reducer / adapter quality** —— typed event 消费器稳定 + 无 raw event spam @@ -425,7 +425,7 @@ channel / web / IDE default 切换到 daemon-backed 必须等: **当前 PR#4266 / PR#4267 draft 不冲突这条 gate** —— PR#4266 (TUI experimental) 是 **opt-in advanced 永远 behind flag,不进入 default migration**(见 [PR#4266 reply 4483046985](https://github.com/QwenLM/qwen-code/pull/4266#issuecomment-4483046985));PR#4267 (IDE experimental) 是合规 behind-flag experiment for default migration。 -**Wave 5 PR 26 scope 显式收紧**:仅 channel / web / IDE default 切换,**TUI default 不切换**(见 [#4175 reply 4483033542](https://github.com/QwenLM/qwen-code/issues/4175#issuecomment-4483033542))。 +**Wave 5 PR 26 scope 显式收紧**:先做 remote web chat / web terminal + shared render/client core,**TUI default 不切换,channel / IDE 后置**(见 [#4175 reply 4479698986](https://github.com/QwenLM/qwen-code/issues/4175#issuecomment-4479698986))。 #### 6. 文档更新建议(chiga0 list) @@ -463,7 +463,7 @@ channel / web / IDE default 切换到 daemon-backed 必须等: | **P0** | **1.5a must-haves** | chiga0 10 must-haves 剩 9 项(生产 blocker)| ~2 周(9 PRs 可并行)| | **P0** | **1.5c** | daemon-side state CRUD 8 routes(Mode B 远端 client 摆脱 thin shell)| ~3-5d | | **P1** | **1.5-prereq** | chiga0 6 architecture refactor findings(lift `AcpChannel` / `EventBus` / `PermissionMediator` 到 `@qwen-code/acp-bridge`)| ~1-2 周 | -| **P1** | **client adapters** | TUI / channels / web/debug / IDE 通过 `DaemonSessionClient` behind flag 接入 Mode B;默认切换必须等 P0/P1 | ~2-3 周,可与 P0/P1 试点并行 | +| **P1 / POC** | **client/render** | remote web chat + web terminal 通过 `DaemonSessionClient` 验证 Mode B;抽 shared render/client core;channel / IDE 后置;native TUI direct | ~1-2 周技术 POC,可与 P0 并行 | | **P2** | **remote-control revisit** | [#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 | 后置 | | **P2** | **1.5b Mode A** | Mode A `qwen --serve` flag — [Issue #4156](https://github.com/QwenLM/qwen-code/issues/4156) doudouOUC 3-phase plan;A1 [PR#4160](https://github.com/QwenLM/qwen-code/pull/4160) ✅ MERGED;剩余 ~5-6d **推迟到 P0 完成后** | ~5-6d | | **合计**(按 P0 → P1 → P2 顺序)| | | **~4 周 + Mode A 1 周** | @@ -488,23 +488,25 @@ Week 2 Week 3 ├─ 1.5-prereq merge → Stage 2 协议层准备就绪 -├─ TUI / channels / web/debug / IDE behind-flag adapters 试点 +├─ remote web chat / web terminal 技术 POC + shared render/client core 试点 └─ 1.5b Mode A 启动(Issue #4156 A0/A2/A3 + Phase B/C) Week 4 └─ 1.5b Mode A merge + 部署生态(Dockerfile / systemd / k8s manifest) ``` -### Mode B client convergence 补充 +### Mode B remote web convergence 补充 -client 统一接入不是让外部 client 直接 import daemon 内存里的 `EventBus`,而是稳定 HTTP/SSE 边界上的 typed event contract、shared reducer 和 `DaemonSessionClient`: +remote web chat / web terminal 先接入 daemon,不是让外部 client 直接 import daemon 内存里的 `EventBus`,而是稳定 HTTP/SSE 边界上的 typed event contract、shared reducer 和 `DaemonSessionClient`。native local TUI 继续直连本机 runtime;channel / IDE 继续走现有 ACP,daemon 化迁移后置。 ```text qwen serve -> HTTP/SSE API -> internal EventBus fan-out -> typed event contract + DaemonSessionClient - -> TUI / channels / web / IDE adapters + -> remote web chat / web terminal adapters + -> shared render/client core + -> future channel / IDE daemon adapters if later approved -> JSONL / stream-json / dual-output sinks -> remote-control later as daemon facade ``` @@ -517,7 +519,7 @@ Stage 1.5 不是一次性 rewrite,而是 **逐步测试、逐步迁移**。每 |---|---| | 单 PR 可合入 | 每个 PR 自带完整测试,合入后 main 仍可发布 | | 向后兼容 | 不移除现有 route / event 字段 / CLI 行为;新增字段必须 additive + optional | -| 默认不切换 | TUI / channels / IDE 先 behind flag 或 adapter 双栈;默认仍走现有路径,直到验证完成 | +| 默认不切换 | native TUI / channels / IDE 保持现有默认路径;remote web chat / web terminal 使用显式入口做技术 POC,直到 daemon web contract 验证完成 | | serve 不破坏 | `qwen serve` Stage 1 routes 和 SDK 行为保持可用;新能力通过 capabilities feature tag 暴露 | | 渐进迁移 | P0 must-haves / state CRUD / typed contract 可并行;client 先 behind flag 试点,再扩大默认面 | | 可回滚 | 每个 client adapter 都能独立关闭,不影响其他 client 和 daemon | @@ -556,7 +558,7 @@ Mode A 价值是 "本地 TUI super-client + 远端 client 同时接入同 daemon } ``` -要让 TUI / channels / web / IDE 真正统一接入,不是让它们直接 import daemon 里的 `EventBus` 对象,而是把它背后的 **event contract** 稳定下来。Mode B 下外部 client 的直接边界仍然是 HTTP server: +要让 remote web chat / web terminal 可靠接入,并为后续 channel / IDE daemon 化保留余地,不是让它们直接 import daemon 里的 `EventBus` 对象,而是把它背后的 **event contract** 稳定下来。Mode B 下 daemon client 的直接边界仍然是 HTTP server: ```text client @@ -571,14 +573,14 @@ client | 工作项 | 目标 | |---|---| | typed `SessionEvent` / `ControlEvent` | 把 `data: unknown` 收敛为 discriminated union | -| shared `DaemonSessionClient` | SDK / TUI / channels / IDE 共用 HTTP/SSE client | +| shared `DaemonSessionClient` | SDK / remote web chat / web terminal / future daemon clients 共用 HTTP/SSE client | | `AcpChannel` / transport primitive | 把 child stdio、in-memory channel、daemon HTTP transport 的 bridge 边界拆清 | | `PermissionMediator` | 统一 daemon first-responder、channels、stream-json / non-interactive 的 permission 策略 | | Event reducer | 从 daemon events 构建 client view-model,避免每个 client 自己拼状态 | | output sinks | JSONL / stream-json / dual-output 变成同一 event stream 的 sink | | capability negotiation | `/capabilities` 增加 `protocol_versions` / feature registry,client 可按能力降级 | -这一步是所有 client 默认切换的前置;可以与 P0 must-haves / state CRUD 并行启动,不需要等 Mode A。 +这一步是 remote web chat / web terminal 进入 production-ready 的前置;可以与 P0 must-haves / state CRUD 并行启动,不需要等 Mode A。channel / IDE 后续若评估 daemon migration,也复用同一 contract。 **兼容性要求**: @@ -587,20 +589,22 @@ client - 新 capability 字段必须 optional,旧 daemon / 新 client、旧 client / 新 daemon 都能工作。 - Event reducer 必须只消费已有事件,不能要求 daemon 立即新增全量 state event。 -### Client adapters — Primary clients(优先 TUI / channels / web / IDE) +### Client/render — Primary daemon clients(优先 remote web chat / web terminal) -目标是让现有 client 不再各自拥有一条 parallel runtime,而是接到同一个 Mode B daemon: +当前目标是先让 remote web chat / web terminal 验证 daemon 技术方案,native local TUI、channel、IDE 默认链路暂不迁移: | Client | 当前状态 | Mode B 适配方向 | 接入顺序 | |---|---|---|---| -| **TUI** | 走内部 Ink / `useGeminiStream` 路径 | 新增 attach-to-daemon render target;用 shared reducer 渲染 daemon `SessionEvent`;本地 TUI 不再拥有 runtime | 第一波 behind flag | -| **channels** | `packages/channels/base/AcpBridge.ts` 自己 spawn `qwen --acp` | 新增 daemon transport;保留 channel routing,但 prompt/event/cancel/model 走 `DaemonSessionClient` | 第一波 behind flag | +| **remote web chat** | 仍缺 production web client | 显式入口 / BFF 消费 daemon HTTP/SSE;验证 auth、session identity、permission、state CRUD、streaming UX | 第一优先 POC | +| **web terminal** | 仍缺 production web terminal | 复用 shared render core / Ink->ANSI 投影,在浏览器 terminal 中消费 daemon events;不走 PTY proxy 作为主线 | 第一优先 POC | +| **native local TUI** | 走内部 Ink / `useGeminiStream` 路径 | 保持直接链路;只抽 shared render core,避免为本机 TUI 增加 localhost HTTP/SSE 损耗 | 不默认迁移 | +| **channels** | `packages/channels/base/AcpBridge.ts` 自己 spawn `qwen --acp` | 继续 ACP;daemon transport 只保留为 future behind-flag reference | 后置 | +| **IDE** | VSCode companion 直接 spawn `qwen --acp` | 继续 ACP;daemon transport 只保留为 future behind-flag reference | 后置 | | **web/debug** | [PR#4132](https://github.com/QwenLM/qwen-code/pull/4132) `/demo` ✅ **MERGED 2026-05-18 08:31** (jifeng, 4 天 24 reviews) | 作为最薄 POST+SSE client 验证面,已 ship;XSS 修把威胁模型扩到 daemon-emitted poisoned events | 已 ship | -| **IDE** | VSCode companion 直接 spawn `qwen --acp` | 新增 daemon transport behind flag;先覆盖 session create/prompt/events/cancel/model,再补 file/context/control routes | 第二波 behind flag | | JSONL / stream-json / dual-output | CLI 内部 adapter | 变成 daemon event sinks;不再驱动 runtime,只消费 typed events | 与 contract 并行 | | remote-control | [#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) draft stack | **后置**;等上述 clients 收敛后作为 daemon facade 复用同一 contract | P2 deferred | -适配可以先 behind flag 开始;默认切换需要等 P0 的 1.5a must-haves / 1.5c state CRUD,以及 P1 的 1.5-prereq contract / bridge primitive 完成。 +web 适配应先以 explicit entrypoint / behind flag 做 technical POC,优先验证 remote web chat + web terminal 这条主场景是否能跑通。POC 可以和 P0 的 1.5a must-haves / 1.5c state CRUD 并行推进;production-ready 才需要等 P0/P1 contract、bridge primitive、state CRUD 和 release hardening 收口。native TUI/channel/IDE 默认链路不受该 gate 影响,channel / IDE daemon migration 后置。 **每个 client 的合入策略**: @@ -673,8 +677,8 @@ Stage 1 的主链路已经可用:prompt / events / cancel / model / permission remote-control 仍然有价值,但优先级后置。原因: - 当前 [#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) 是 draft / changes requested,且包含 parallel worker/WebSocket/runtime 路线。 -- 今天的 Mode B 决策要求所有 client 先收敛到 daemon HTTP/SSE API,并消费同一套 EventBus-backed typed event contract。 -- TUI / channels / web / IDE 是基础 client 面,先完成它们能反过来定义 remote-control 应复用的 contract。 +- 今天的 Mode B 决策把 daemon 技术验证优先级收敛到 remote web chat / web terminal,并要求它们消费同一套 EventBus-backed typed event contract。 +- native TUI、channels、IDE 默认路径先保持不变;remote-control 应等 remote web contract 稳定后复用 daemon facade,而不是另起 parallel runtime/protocol。 后续 remote-control 应该降级为: @@ -849,7 +853,7 @@ Anthropic Managed Agents 的内部模型很可能是 per-session container/proce - **自托管 vs 云托管**:Qwen 走 building block 路线;Anthropic 提供托管服务 - **IM 多渠道生态**:Qwen 通过 `packages/channels/` + IM 路由原生支持 Telegram / 微信 / 钉钉 / Slack;Anthropic 只暴露 API - **Java SDK 直连**:Qwen 唯一有 Java acp-sdk,daemon 后跨语言更顺 -- **Background tasks 4 kinds 跨 client 可见**:Qwen kind framework(PR#3836)能在 daemon 模式下让所有 client 看到所有后台任务(agent/shell/monitor/dream) +- **Background tasks 4 kinds 跨 daemon-capable client 可见**:Qwen kind framework(PR#3836)能在 daemon 模式下让 remote web chat / web terminal 以及未来 daemon clients 看到所有后台任务(agent/shell/monitor/dream) --- diff --git a/docs/comparison/qwen-code-daemon-design/README.md b/docs/comparison/qwen-code-daemon-design/README.md index eec387a..07ab2df 100644 --- a/docs/comparison/qwen-code-daemon-design/README.md +++ b/docs/comparison/qwen-code-daemon-design/README.md @@ -4,7 +4,7 @@ ## 一、TL;DR -> **2026-05-15 决策更新**:先忽略 Mode A(`qwen --serve`)。后续 roadmap 以 **Mode B:`qwen serve` headless daemon 作为底层 runtime** 为主线;Mode A 暂停在 [Issue #4156](https://github.com/QwenLM/qwen-code/issues/4156) 里作为 parking lot,已合并的 [PR#4160](https://github.com/QwenLM/qwen-code/pull/4160) 仅作为可复用 in-memory channel primitive 记录。 +> **2026-05-19 决策更新**:先忽略 Mode A(`qwen --serve`)。roadmap 以 **Mode B:`qwen serve` headless daemon 作为 remote web chat + web terminal 的底层 runtime** 为主线;native local TUI 永久保持 direct runtime / streamJson / Ink 路径;channel / IDE 继续走现有 `--acp`,daemon 化后置评估。remote web chat + web terminal 技术 POC 优先级上调,可与 P0 must-haves / state CRUD 并行启动,但 production-ready 仍要等 P0/P1 contract 收口。 ``` ACP NDJSON 协议 → HTTP+SSE daemon @@ -24,7 +24,7 @@ ACP NDJSON 协议 → HTTP+SSE daemon | 模式 | 命令 | TUI | 适用场景 | |---|---|:---:|---| -| **Mode B** | `qwen serve [--port N]` | ❌ | **当前主线**:服务器 / 容器 / 远端机器 / K8s pod / 所有 client 的统一 runtime | +| **Mode B** | `qwen serve [--port N]` | ❌ | **当前主线**:服务器 / 容器 / 远端机器 / K8s pod / remote web chat + web terminal runtime | | **Mode A** | `qwen --serve [--port N]` | ✅ 本地渲染 | **暂停推进**:待 Mode B HTTP/SSE event contract / control-plane / client identity 稳定后再评估 | **当前状态**: @@ -75,8 +75,8 @@ ACP NDJSON 协议 → HTTP+SSE daemon - ⚠️ Bonus Stage 1 wire-up 调整: [PR#4260](https://github.com/QwenLM/qwen-code/pull/4260) TUI + [PR#4263](https://github.com/QwenLM/qwen-code/pull/4263) IDE **CLOSED 06:59** (Stage 2 直接覆盖); [PR#4261](https://github.com/QwenLM/qwen-code/pull/4261) channel `--daemon-url` 仍 draft (channel 无 Stage 2) - 🔧 Bonus Stage 2 experimental flag-gated 2 PR draft: [PR#4266](https://github.com/QwenLM/qwen-code/pull/4266) `--experimental-daemon-tui` / [PR#4267](https://github.com/QwenLM/qwen-code/pull/4267) `qwen-code.experimentalDaemonIde` (chiga0, 2026-05-18 05:06 起; channel stage 2 待开) - ✅ [PR#4132](https://github.com/QwenLM/qwen-code/pull/4132) `/demo` debug page (jifeng) **MERGED 2026-05-18 08:31** —— 4 天 24 reviews 终于合,daemon 项目 OPEN 最长 PR;XSS 修 (daemon-emitted poisoned events 威胁模型) + rebase 过 #4247/4250/4251 冲突 -- 🧭 [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) remote-control stack 仍 OPEN draft / changes requested;**优先级后置**,等 TUI / channels / web / IDE 先完成 Mode B client 适配后,再重定向为 daemon HTTP/SSE facade -- ⏳ Stage 1.5 剩余主线:P0 production must-haves + daemon-side state CRUD,P1 typed event contract / bridge primitives + client adapters behind flag,P2 remote-control / Mode A revisit(详 [§06 Roadmap](./06-roadmap.md)) +- 🧭 [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) remote-control stack 仍 OPEN draft / changes requested;**优先级后置**,等 remote web chat / web terminal contract 验证后,再重定向为 daemon HTTP/SSE facade +- ⏳ Stage 1.5 剩余主线:P0 production must-haves + daemon-side state CRUD,P1 typed event contract / bridge primitives + remote web chat / web terminal 技术 POC,P2 remote-control / channel / IDE daemon migration / Mode A revisit(详 [§06 Roadmap](./06-roadmap.md)) ## 二、6 章总览 @@ -85,7 +85,7 @@ ACP NDJSON 协议 → HTTP+SSE daemon | **01** | [Overview](./01-overview.md) | TL;DR + 2 层术语 + 架构图 + Mode B 主线 + 资源经济性 + Stage 进展 + 阅读指南 | | **02** | [Architectural Decisions](./02-architectural-decisions.md) | 8 决策:session 共享 P1/P2 / 1 daemon = 1 workspace × N session / MCP 生命周期 / FileReadCache / Permission flow / 多 client 并发 / Mode B mainline / server-client-runtime boundary | | **03** | [HTTP API & Protocol](./03-http-api.md) | Route table(`/workspace/*` 单 workspace 路由)+ ACP wire 4 层兼容性矩阵 + SSE + Last-Event-ID + 双向 RPC 异步化 + Capability negotiation | -| **04** | [Deployment & Client](./04-deployment-and-client.md) | Mode B client convergence + deployment shape matrix + TUI / channels / web / IDE 适配边界 + daemon-native renderer + remote-control overlay | +| **04** | [Deployment & Client](./04-deployment-and-client.md) | Mode B remote web chat / web terminal convergence + deployment shape matrix + native TUI direct / channel+IDE ACP 边界 + daemon-native web terminal renderer + remote-control overlay | | **05** | [Security & Permission](./05-permission-auth.md) | Bearer + Host allowlist + 0.0.0.0 拒绝 / PR#3723 4-mode evaluatePermissionFlow / first-responder vote + per-session 隔离 / Multi-tenant = 1 daemon 1 tenant OS 进程级隔离 | | **06** | [Roadmap & Ecosystem](./06-roadmap.md) | Timeline + Stage 1 audit + Stage 1.5 + chiga0 10 must-haves + 6 architecture findings + Stage 2 + External Reference Architecture + vs OpenCode + vs Anthropic | @@ -127,7 +127,7 @@ ACP NDJSON 协议 → HTTP+SSE daemon ### Stage 进展(at 2026-05-15) -**合入原则**:Stage 拆分必须逐步迁移。每个 PR 都要可单独合入、向后兼容、默认不破坏现有 TUI / channels / IDE / CLI 行为;新 daemon 能力通过 capability tag 暴露,client adapter 先 behind flag / 双栈测试,再单独 PR 切默认。 +**合入原则**:Stage 拆分必须逐步迁移。每个 PR 都要可单独合入、向后兼容、默认不破坏现有 TUI / channels / IDE / CLI 行为;新 daemon 能力通过 capability tag 暴露。remote web chat / web terminal 先做显式 POC;channel / IDE daemon 化后置;native local TUI 不进入默认切换计划。 | Stage | 状态 | 范围 | |---|:---:|---| @@ -136,7 +136,7 @@ ACP NDJSON 协议 → HTTP+SSE daemon | **Stage 1.5a must-haves** | ⏳ **P0** | chiga0 10 must-haves 剩 9 项 — Mode B 生产 blocker(~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 — `AcpChannel` / `EventBus` / `PermissionMediator` lift(~1-2 周)| -| Stage 1.5-client adapters | 🔧 **P1 behind flag** | TUI / channels / web/debug / IDE 作为 daemon HTTP/SSE clients 试点;默认切换必须等 P0/P1 | +| Stage 1.5-client/render | 🔧 **P1 / POC 并行** | remote web chat + web terminal 作为 daemon HTTP/SSE 技术 POC;抽 shared client/render core;channel / IDE 后置;native TUI 保持 direct | | **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) ✅;剩余推迟到 1.5c 后 | | Stage 1.5-remote-control | ⏳ **P2 后置** | [#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 | | Stage 2a-2d | ⏳ 待开 | 协议补齐(WebSocket / mDNS / OpenAPI / Prometheus / `/ext` + Reverse RPC)| @@ -160,12 +160,12 @@ ACP NDJSON 协议 → HTTP+SSE daemon | PR / Issue | 当前状态(2026-05-15)| Mode B roadmap 处理 | |---|---|---| -| [Issue #3803](https://github.com/QwenLM/qwen-code/issues/3803) | OPEN | daemon proposal / Stage 1.5 tracker;最新 comment 将 P0/P1/P2 重排为 Mode B must-haves + state CRUD 优先,Mode A 后置 | +| [Issue #3803](https://github.com/QwenLM/qwen-code/issues/3803) | OPEN | daemon proposal / Stage 1.5 tracker;最新 comment 将 remote web chat + web terminal POC 提前,P0/P1 仍是 production-ready 前置,channel/IDE/Mode A 后置 | | [Issue #4156](https://github.com/QwenLM/qwen-code/issues/4156) | OPEN | Mode A 设计 issue,但最新结论是 **Mode A hold,核心推进 Mode B** | | [PR#4132](https://github.com/QwenLM/qwen-code/pull/4132) | OPEN / changes requested | `/demo` debug page 可继续作为 Mode B POST+SSE client 验证面 | -| [PR#3929](https://github.com/QwenLM/qwen-code/pull/3929) | OPEN draft | remote-control foundation 后置;应等 TUI / channels / web / IDE 适配完成后改为 daemon HTTP/SSE client facade | +| [PR#3929](https://github.com/QwenLM/qwen-code/pull/3929) | OPEN draft | remote-control foundation 后置;应等 remote web chat / web terminal contract 稳定后改为 daemon HTTP/SSE client facade | | [PR#3930](https://github.com/QwenLM/qwen-code/pull/3930) | OPEN draft / changes requested | worker/WebSocket 层若保留,应成为 daemon transport facade,而不是替代 HTTP/SSE + EventBus-backed event contract | -| [PR#3931](https://github.com/QwenLM/qwen-code/pull/3931) | OPEN draft / changes requested | remote-control TUI attach 后置;TUI 自身的 Mode B client adapter 更优先 | +| [PR#3931](https://github.com/QwenLM/qwen-code/pull/3931) | OPEN draft / changes requested | remote-control TUI attach 后置;先验证 daemon + remote web chat / web terminal 的 typed event contract | ## 六、决策与文档对应