qwen-code/docs/developers
wenshao 215e0dbf53 refactor(serve): 1 daemon = 1 workspace (#3803 §02)
Stage 1 shipped with M-workspaces-per-daemon routing (`byWorkspaceChannel`
Map keyed by request `cwd`). The §02 architectural revision in
`docs/comparison/qwen-code-daemon-design/02-architectural-decisions.md`
narrows the bridge to 1 daemon = 1 workspace × N sessions: each daemon
binds to one canonical workspace path at boot; `POST /session` with a
mismatched `cwd` returns 400 `workspace_mismatch`. Multi-workspace
deployments run multiple daemon processes (one per workspace, supervised
externally — systemd / docker-compose / k8s / `qwen-coordinator`).

Bridge state collapses from maps to single optional slots:

- `byWorkspaceChannel: Map<string, ChannelInfo>` → `channelInfo?: ChannelInfo`
- `inFlightChannelSpawns: Map<string, Promise>` → `inFlightChannelSpawn?: Promise`
- `byWorkspace: Map<string, SessionEntry>` → `defaultEntry?: SessionEntry`
- `liveChannels: Set<ChannelInfo>` → not needed; `channelInfo` is the live
  reference, cleared only by `channel.exited` (preserves the tanzhenxin
  BkUyD invariant that `killAllSync` finds a target mid-SIGTERM-grace)

`BridgeOptions.boundWorkspace` becomes required. `WorkspaceMismatchError`
is thrown from `spawnOrAttach` when the request's canonical cwd doesn't
match the bound path, translated to 400 `workspace_mismatch` (with both
paths in the body) by the route layer. `CapabilitiesEnvelope.workspaceCwd`
surfaces the bound path so clients pre-flight check + omit `cwd` from
`POST /session` (it falls back to the bound workspace).

A new `--workspace <path>` CLI flag lets operators override
`process.cwd()` at boot. The previous `--http-bridge` / `--multi-workspace`
opt-in was never shipped; nothing changes for default users running
`qwen serve` in their project directory.

Removed code path: ~150 LOC of multi-workspace map machinery in
`httpAcpBridge.ts` plus the test cases that exercised it.

Test surgery:

- New `makeBridge()` helper in `httpAcpBridge.test.ts` injects
  `boundWorkspace: WS_A` by default; tests that need a different bind
  (the mismatch test) pass it explicitly.
- `does NOT reuse across workspaces` → `rejects cross-workspace requests
  with WorkspaceMismatchError` (the new semantics under §02).
- `shutdown kills every live channel` retargeted to single-channel
  multi-session shutdown.
- `killAllSync force-kills channels even after shutdown cleared
  byWorkspaceChannel (BkUyD)` retargeted to single-channel: the
  invariant is the same (channel reference must outlive eager shutdown
  clearing), the surface is just smaller.
- `listWorkspaceSessions` cross-workspace assertion now expects empty
  for the un-bound path.
- `--max-sessions` cap test uses two thread-scope sessions on `WS_A`
  instead of WS_A + WS_B.

Closes #3803 §02.
2026-05-13 17:36:58 +08:00
..
development docs(telemetry): align config and docs semantics for target, outfile, and CLI flags (#4066) 2026-05-13 08:27:41 +08:00
examples feat(cli,sdk): qwen serve daemon (Stage 1) (#3889) 2026-05-13 14:47:47 +08:00
tools feat(web-search): remove built-in web_search tool, replace with MCP-based approach (#3502) 2026-04-24 11:29:02 +08:00
_meta.ts feat(cli,sdk): qwen serve daemon (Stage 1) (#3889) 2026-05-13 14:47:47 +08:00
architecture.md docs: enhance architecture documentation and add contribution guidelines 2025-12-11 18:31:24 +08:00
channel-plugins.md feat(channels): add dispatch modes and prompt lifecycle hooks 2026-03-28 06:19:02 +00:00
contributing.md chore(deps): upgrade ink 6.2.3 → 7.0.2 + bump Node engine to 22 (#3860) 2026-05-11 17:29:50 +08:00
qwen-serve-protocol.md refactor(serve): 1 daemon = 1 workspace (#3803 §02) 2026-05-13 17:36:58 +08:00
roadmap.md feat(cli): improve auth dialog UX with clearer three-option layout 2026-03-01 15:22:35 +08:00
sdk-java.md Fix typo in class name (#2189) 2026-04-18 11:59:36 +08:00
sdk-python.md doc[sdk-python] Expand Python SDK usage documentation (#3995) 2026-05-12 15:27:00 +08:00
sdk-typescript.md chore(deps): upgrade ink 6.2.3 → 7.0.2 + bump Node engine to 22 (#3860) 2026-05-11 17:29:50 +08:00