Skip to content

Commit 95eeb4c

Browse files
doudouOUCqwencoder
andcommitted
docs: Smooth daemon developer docs language
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
1 parent b055197 commit 95eeb4c

23 files changed

Lines changed: 192 additions & 185 deletions

docs/developers/_meta.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export default {
1010
title: 'Agent SDK',
1111
type: 'separator',
1212
},
13-
'sdk-typescript': 'Typescript SDK',
13+
'sdk-typescript': 'TypeScript SDK',
1414
'sdk-python': 'Python SDK (alpha)',
1515
'sdk-java': 'Java SDK (alpha)',
1616
'Dive Into Qwen Code': {

docs/developers/daemon-client-adapters/tui.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Add a flag-gated TUI transport that talks to `qwen serve` through
1010
`DaemonSessionClient` instead of creating an in-process `Config` + agent
1111
runtime.
1212

13-
This is a dogfood path for Mode B client migration. It must not replace the
13+
This is an internal validation path for Mode B client migration. It must not replace the
1414
default TUI path until output sinks, typed daemon events, session-scoped
1515
permission, and lifecycle diagnostics are stable.
1616

docs/developers/daemon/00-index.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Daemon Developer Documentation
22

3-
This is the developer-facing technical documentation set for **qwen-code daemon mode**: the `qwen serve` HTTP daemon, the `@qwen-code/acp-bridge` package, the workspace-scoped MCP transport pool, multi-client permission mediation, typed daemon event schema v1, the TypeScript SDK daemon client, and the adapters that talk to the daemon.
3+
This is the developer-facing technical documentation for **qwen-code daemon mode**: the `qwen serve` HTTP daemon, the `@qwen-code/acp-bridge` package, the workspace-scoped MCP transport pool, multi-client permission mediation, typed daemon event schema v1, the TypeScript SDK daemon client, and the adapters that connect to the daemon.
44

55
It complements, rather than replaces, these existing docs:
66

@@ -17,7 +17,7 @@ If you want to **start a daemon and use it**, read `qwen-serve.md` first. If you
1717

1818
Pick the path that matches your goal:
1919

20-
- **I want to start it first**: `20 -> 17 -> 19`.
20+
- **Start and verify a daemon first**: `20 -> 17 -> 19`.
2121
- **New contributor**: `01 -> 02 -> 03 -> 08 -> 09 -> 10 -> 11 -> 12`.
2222
- **Adding a new client adapter**: `01 -> 09 -> 10 -> 13 -> (14 / 15 / 16)`.
2323
- **Working on the MCP pool or budget**: `01 -> 03 -> 05 -> 06`.
@@ -68,7 +68,7 @@ Pick the path that matches your goal:
6868
- **DaemonClient** - `packages/sdk-typescript/src/daemon/DaemonClient.ts`. The TypeScript SDK HTTP-level facade over the daemon.
6969
- **DaemonSessionClient** - `packages/sdk-typescript/src/daemon/DaemonSessionClient.ts`. Session-scoped wrapper that tracks `lastSeenEventId` for SSE replay.
7070
- **EventBus** - `packages/acp-bridge/src/eventBus.ts`. Per-session in-memory pub/sub with monotonic IDs, a bounded ring, and per-subscriber backpressure.
71-
- **F1 / F2 / F3 / F4** - internal milestones inside [#4175](https://github.com/QwenLM/qwen-code/issues/4175). F1: bridge lift and `BridgeFileSystem`. F2: workspace-scoped MCP transport pool. F3: multi-client permission mediation. F4: protocol completion and daemon client surfaces.
71+
- **F1 / F2 / F3 / F4** - internal milestones tracked in [#4175](https://github.com/QwenLM/qwen-code/issues/4175). F1: bridge extraction and `BridgeFileSystem`. F2: workspace-scoped MCP transport pool. F3: multi-client permission mediation. F4: protocol completion and daemon client surfaces.
7272
- **MCP** - Model Context Protocol. Servers expose tools, resources, and prompts; the daemon ACP child connects to them.
7373
- **McpTransportPool** - `packages/core/src/tools/mcp-transport-pool.ts`. F2 workspace-scoped pool sharing one MCP transport per server name and config fingerprint.
7474
- **Mediator policy** - one of `first-responder`, `designated`, `consensus`, or `local-only`. Decides how multi-client permission votes resolve.
@@ -135,7 +135,7 @@ Use these anchors when moving from the docs into the latest `main` code:
135135
| TypeScript SDK daemon client | `DaemonClient`, `DaemonSessionClient`, `DaemonAuthFlow`, SSE parser, event reducers, feature preflight, and UI transcript exports are documented. | [`13`](./13-sdk-daemon-client.md) |
136136
| Shared UI transcript layer | SDK `daemon/ui/*` normalizes daemon events into 36 UI semantic event types, reduces them into transcript blocks, and provides renderers/conformance helpers. | [`14`](./14-cli-tui-adapter.md), [`../daemon-ui/README.md`](../daemon-ui/README.md), [`../daemon-ui/MIGRATION.md`](../daemon-ui/MIGRATION.md) |
137137
| Web UI daemon consumer | `packages/webui/src/daemon/` consumes the SDK transcript store through React providers and adapters. | [`14`](./14-cli-tui-adapter.md), [`../daemon-client-adapters/web-ui.md`](../daemon-client-adapters/web-ui.md) |
138-
| CLI TUI / channels / VSCode | Legacy paths still exist; migration to shared transcript primitives is documented as follow-up work, not completed behavior. | [`14`](./14-cli-tui-adapter.md), [`15`](./15-channel-adapters.md), [`16`](./16-vscode-ide-adapter.md) |
138+
| CLI TUI / channels / VS Code | Legacy paths still exist; migration to shared transcript primitives is documented as follow-up work, not completed behavior. | [`14`](./14-cli-tui-adapter.md), [`15`](./15-channel-adapters.md), [`16`](./16-vscode-ide-adapter.md) |
139139

140140
### Reference and operations
141141

docs/developers/daemon/01-architecture.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ A `qwen serve` process is **one daemon = one workspace**. It hosts a single Expr
66

77
Inside the ACP child, MCP servers are shared workspace-wide through `McpTransportPool` (F2): a single (server-name + config-fingerprint) tuple maps to one MCP transport, regardless of how many sessions discover it. The bridge's `MultiClientPermissionMediator` (F3) coordinates permission votes across all connected clients under one of four policies.
88

9-
This doc gives the **system-level picture** that every other doc in this set hangs off. Each load-bearing flow is shown as a Mermaid sequence diagram; per-component implementation details live in the other 18 docs.
9+
This doc gives the **system-level picture** that the rest of this documentation set builds on. Each critical flow is shown as a Mermaid sequence diagram; per-component implementation details live in the other 18 docs.
1010

1111
## Process topology
1212

1313
```mermaid
1414
flowchart LR
1515
subgraph clients["Clients"]
1616
TUI["CLI TUI<br/>(packages/cli/src/ui/daemon)"]
17-
IDE["VSCode IDE<br/>(packages/vscode-ide-companion)"]
17+
IDE["VS Code IDE<br/>(packages/vscode-ide-companion)"]
1818
CH["Channel bots<br/>(DingTalk / WeChat / Telegram)"]
1919
SDK["Any SDK consumer<br/>(packages/sdk-typescript/src/daemon)"]
2020
end
@@ -55,7 +55,7 @@ flowchart LR
5555
POOL -- "shared transport" --> MCP2
5656
```
5757

58-
The daemon process and the ACP child are connected by an `AcpChannel` (default: a real subprocess pair-of-pipes; `inMemoryChannel` for tests). Everything the daemon does is shaped by this split: HTTP and SSE traffic terminate in the daemon; agent decisions and tool invocations happen in the child; the bridge is the seam.
58+
The daemon process and the ACP child are connected by an `AcpChannel` (default: a real subprocess stdio pipe pair; `inMemoryChannel` for tests). Everything the daemon does is shaped by this split: HTTP and SSE traffic terminate in the daemon, agent decisions and tool invocations happen in the child, and the bridge connects the two.
5959

6060
## Package map
6161

@@ -132,7 +132,7 @@ flowchart TB
132132
DC --> AUTHF
133133
```
134134

135-
Three trust boundaries to keep in mind: the HTTP edge (`serve/auth.ts` middleware chain), the bridgeACP-child seam (NDJSON over stdio, no auththe child trusts the bridge implicitly), and the agentMCP server seam (the agent may invoke tools that touch the host).
135+
Three trust boundaries matter: the HTTP edge (`serve/auth.ts` middleware chain), the bridge-to-ACP-child boundary (NDJSON over stdio, no auth; the child trusts the bridge implicitly), and the agent-to-MCP-server boundary (the agent may invoke tools that touch the host).
136136

137137
## Workflow 1: HTTP request lifecycle
138138

@@ -272,7 +272,7 @@ sequenceDiagram
272272
S->>P: release(id, sessionId)
273273
P->>E: detach session
274274
E->>E: arm drain timer (default 30s)
275-
Note over E: refs==0 → drain timer fires → close transport<br/>(MAX_IDLE_MS 5min hard cap survives flap)
275+
Note over E: refs==0 → drain timer fires → close transport<br/>(MAX_IDLE_MS 5min hard cap survives attach/detach churn)
276276
277277
Note over S,P: Operator restart flow…
278278
S->>P: restartByName(name, opts?)
@@ -314,7 +314,7 @@ sequenceDiagram
314314
Note over Op,RQS: Second SIGTERM during shutdown →<br/>bridge.killAllSync() + process.exit(1) (orphan prevention)
315315
```
316316

317-
The two-phase shutdown matters because in-flight HTTP requests, in-flight SSE subscribers, and the ACP child's in-flight tool calls all need bounded teardown windows. If anything blocks past those deadlines, the force-close path takes over so a stuck child can't keep the daemon process alive.
317+
The two-phase shutdown matters because in-flight HTTP requests, in-flight SSE subscribers, and the ACP child's in-flight tool calls all need bounded teardown windows. If anything blocks past those deadlines, the force-close path takes over so a stuck child cannot keep the daemon process alive.
318318

319319
## Critical files
320320

docs/developers/daemon/02-serve-runtime.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
## Overview
44

5-
`packages/cli/src/serve/` is the boot layer for `qwen serve`. It translates CLI flags into `ServeOptions`, validates boot posture, builds the Express app, wires middleware, registers routes, exposes daemon-host preflight/status providers, maintains the permission audit ring, and owns the two-phase graceful shutdown sequence. HTTP-shaped work lives in this layer; ACP-shaped work lives one layer below in `@qwen-code/acp-bridge` (see [`03-acp-bridge.md`](./03-acp-bridge.md)).
5+
`packages/cli/src/serve/` is the boot layer for `qwen serve`. It translates CLI flags into `ServeOptions`, validates startup configuration, builds the Express app, wires middleware, registers routes, exposes daemon-host preflight/status providers, maintains the permission audit ring, and owns the two-phase graceful shutdown sequence. HTTP-facing work lives in this layer; ACP-facing work lives one layer below in `@qwen-code/acp-bridge` (see [`03-acp-bridge.md`](./03-acp-bridge.md)).
66

77
## Responsibilities
88

99
- Parse and validate `ServeOptions`: listen address, auth, workspace, session / connection caps, MCP budget / pool, CORS, prompt / SSE / session idle timeouts, rate limit, and related toggles.
1010
- **Canonicalize** the bound workspace exactly once. The same canonical form is shared by `/capabilities`, the `POST /session` fallback, and the bridge.
11-
- Refuse unsafe or impossible boot postures: non-loopback bind without token, `--require-auth` without token, `--allow-origin '*'` without token, `mcpBudgetMode='enforce'` without a positive `mcpClientBudget`, nonexistent / non-directory `--workspace`, and invalid timeout or rate-limit values.
11+
- Reject unsafe or invalid startup configurations: non-loopback bind without token, `--require-auth` without token, `--allow-origin '*'` without token, `mcpBudgetMode='enforce'` without a positive `mcpClientBudget`, a nonexistent or non-directory `--workspace`, and invalid timeout or rate-limit values.
1212
- Construct the `WorkspaceFileSystem` factory, permission audit publisher, `DaemonStatusProvider`, and `acp-bridge`.
1313
- Build the Express app, wire middleware (`denyBrowserOriginCors` / `allowOriginCors` -> `hostAllowlist` -> access log -> `bearerAuth` -> rate limit -> JSON parser -> telemetry -> per-route `mutationGate`), and mount session, workspace CRUD, file, device-flow auth, permission vote, and ACP HTTP routes.
1414
- Bind the listening port and register signal handlers.
@@ -30,7 +30,7 @@
3030
| `hostAllowlist(bind, getPort)` | On loopback, validate `Host` belongs to `localhost`, `127.0.0.1`, `[::1]`, or `host.docker.internal` plus the actual port. | Defense against DNS rebinding. Comparison is case-insensitive and cached per port. |
3131
| Access-log middleware | Records method, path, status, durationMs, sessionId, and clientId to `DaemonLogger` when a request finishes. | Registered **before** `bearerAuth`, so 401 denials are logged too. Skips `/health` and heartbeat. |
3232
| `bearerAuth(token)` | SHA-256 plus `timingSafeEqual` constant-time bearer comparison. | Open passthrough when no token is configured (loopback dev default). `Bearer` scheme is case-insensitive. |
33-
| Rate-limit middleware | Optional per-tier token bucket for prompt, mutation, and read routes. | Registered after `bearerAuth` and before JSON parsing; returns 429 early on hit. |
33+
| Rate-limit middleware | Optional per-tier token bucket for prompt, mutation, and read routes. | Registered after `bearerAuth` and before JSON parsing; returns 429 before parsing when a bucket is exhausted. |
3434
| `express.json({ limit: '10mb' })` | JSON body parsing. | Parse errors return 400. |
3535
| `daemonTelemetryMiddleware` | Wraps each HTTP request in an OpenTelemetry span through `withDaemonRequestSpan`. | Attributes include route, sessionId, clientId, and status code. |
3636
| `createMutationGate` (per-route) | Route-level opt-in gate for mutation routes that require token even on loopback. | Returns `401 { code: 'token_required' }`. Not global `app.use`; routes call `mutate({ strict: true })` as needed. |
@@ -139,7 +139,7 @@ See [`17-configuration.md`](./17-configuration.md) for the merged reference.
139139

140140
- Direct `createServeApp` without `deps.fsFactory` or `deps.bridge` defaults to `trusted: false`; agent-side ACP `writeTextFile` rejects as `untrusted_workspace`. The warning is printed once.
141141
- `denyBrowserOriginCors` rejects **all** requests carrying `Origin`; the demo page works because another middleware strips matching same-origin values first.
142-
- Body-parser ordering: route calls such as `mutate({ strict: true })` / `mutateGate({strict: true})` return 401 only after `express.json()`. Worst case is `--max-connections × express.json({limit: '10mb'})`, about 2.5 GB transient on a saturated loopback listener, intentionally accepted.
142+
- Body-parser ordering: routes using `mutate({ strict: true })` return 401 only after `express.json()`. The worst case is `--max-connections × express.json({limit: '10mb'})`, up to about 2.5 GB of transient memory on a saturated loopback listener; this tradeoff is intentional.
143143
- Multiple daemons in one process must use per-handle `childEnvOverrides`; mutating `process.env` races because `defaultSpawnChannelFactory` snapshots env at spawn time.
144144

145145
## References

0 commit comments

Comments
 (0)