diff --git a/docs/users/qwen-serve.md b/docs/users/qwen-serve.md index 012f3e3f2fd..fb2610464b6 100644 --- a/docs/users/qwen-serve.md +++ b/docs/users/qwen-serve.md @@ -190,22 +190,21 @@ Stage 1's contract is sized for prototyping. Per [#3889 chiga0 downstream-consum **Blockers for serious downstream use:** -1. **Per-request `sessionScope` override** on `POST /session` — today the daemon-wide default is the only setting; a VSCode extension can't say "I want a private session for this window" against a daemon configured for shared sessions. -2. **`loadSession` / `unstable_resumeSession` over HTTP** — without this, no integration can survive a child crash or daemon restart, and any orchestrator coordinating the daemon can't recover state either. -3. **Persistent client identity (pair tokens + per-client revocation)** — Stage 1 uses one shared bearer; a leaked token revokes everyone, and `originatorClientId` is client-self-declared rather than daemon-stamped from authenticated identity. +1. **`loadSession` / `unstable_resumeSession` over HTTP** — without this, no integration can survive a child crash or daemon restart, and any orchestrator coordinating the daemon can't recover state either. +2. **Persistent client identity (pair tokens + per-client revocation)** — Stage 1 uses one shared bearer; a leaked token revokes everyone, and `originatorClientId` is client-self-declared rather than daemon-stamped from authenticated identity. **Reliability baseline:** -4. **Client-initiated heartbeat path** — distinguish "agent thinking" from "daemon dead" without waiting for the 15s server heartbeat. -5. **`permission_already_resolved` event** when a vote loses the first-responder race — currently UIs have to infer state from a `404`. -6. **Larger / per-session-configurable replay ring** — default 4000 covers short drops; mobile / chatty-turn workloads need 8000+ or per-session config. -7. **`slow_client_warning` event before `client_evicted`** — soft backpressure so well-behaved slow clients can self-throttle (trim render depth, drop chunks) before being terminated. +3. **Client-initiated heartbeat path** — distinguish "agent thinking" from "daemon dead" without waiting for the 15s server heartbeat. +4. **`permission_already_resolved` event** when a vote loses the first-responder race — currently UIs have to infer state from a `404`. +5. **Larger / per-session-configurable replay ring** — default 4000 covers short drops; mobile / chatty-turn workloads need 8000+ or per-session config. +6. **`slow_client_warning` event before `client_evicted`** — soft backpressure so well-behaved slow clients can self-throttle (trim render depth, drop chunks) before being terminated. **Integration ergonomics:** -8. **`POST /session/:id/_meta` for IM-style context** — per-session key-value attached to subsequent prompts (chat id, sender, thread id) replaces the per-channel improvisation. -9. **`/capabilities` actual feature negotiation** — `protocol_versions: { acp: '0.14.x', daemon_envelope: 1 }` so clients can detect drift instead of falling through to "unknown frame, ignore". -10. **First-class durability documentation** (this section) — already shipped above. +7. **`POST /session/:id/_meta` for IM-style context** — per-session key-value attached to subsequent prompts (chat id, sender, thread id) replaces the per-channel improvisation. +8. **`/capabilities` actual feature negotiation** — `protocol_versions: { acp: '0.14.x', daemon_envelope: 1 }` so clients can detect drift instead of falling through to "unknown frame, ignore". +9. **First-class durability documentation** (this section) — already shipped above. The full convergence roadmap is tracked on [#3803](https://github.com/QwenLM/qwen-code/issues/3803). diff --git a/integration-tests/cli/qwen-serve-routes.test.ts b/integration-tests/cli/qwen-serve-routes.test.ts index bef03a6e6c0..97517ac97af 100644 --- a/integration-tests/cli/qwen-serve-routes.test.ts +++ b/integration-tests/cli/qwen-serve-routes.test.ts @@ -180,14 +180,18 @@ describe('qwen serve — CORS browser-origin denial', () => { }); describe('qwen serve — capabilities envelope', () => { - it('advertises all 9 Stage 1 features', async () => { + it('advertises all 10 Stage 1 features', async () => { const caps = await client.capabilities(); expect(caps.v).toBe(1); expect(caps.mode).toBe('http-bridge'); + // Order must match `SERVE_CAPABILITY_REGISTRY` in + // `packages/cli/src/serve/capabilities.ts` and the unit-level + // `EXPECTED_STAGE1_FEATURES` in `packages/cli/src/serve/server.test.ts`. expect(caps.features).toEqual([ 'health', 'capabilities', 'session_create', + 'session_scope_override', 'session_list', 'session_prompt', 'session_cancel',