-
Notifications
You must be signed in to change notification settings - Fork 2.4k
docs(daemon): align adapter spikes with web-first roadmap #4296
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,10 +1,14 @@ | ||||||
| # Channel And Web Backend Daemon Adapter Draft | ||||||
| # Channel And Web Backend Daemon Adapter Spike | ||||||
|
|
||||||
| ## Goal | ||||||
|
|
||||||
| Let channel adapters and web chat backends consume `qwen serve` through | ||||||
| `DaemonSessionClient` while keeping existing channel ACP subprocess behavior as | ||||||
| the default. | ||||||
| Document the default-off `DaemonChannelBridge` spike for server-side channel | ||||||
| and web backends. | ||||||
|
|
||||||
| As of the 2026-05-19 architecture decision, web chat / web terminal are the | ||||||
| first daemon-native client targets. Channel adapters should continue to use the | ||||||
| existing ACP subprocess behavior by default; daemon channel integration remains | ||||||
| future / behind-flag evaluation. | ||||||
|
|
||||||
| This draft covers server-side clients only: | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Critical] The title was changed from "Draft" to "Spike" but this line still reads "This draft covers server-side clients only". Internal inconsistency within the same file.
Suggested change
— qwen-latest-series-invite-beta-v28 via Qwen Code /review |
||||||
|
|
||||||
|
|
@@ -16,13 +20,13 @@ The daemon currently rejects browser `Origin` requests by design. | |||||
|
|
||||||
| ## Proposed Entry Points | ||||||
|
|
||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] "Proposed historical channel backend experiment" — "Proposed" (forward-looking) contradicts "historical" (past). Something cannot be simultaneously proposed for the future and consigned to history. The intent appears to be describing this as a historical reference, so the word "Proposed" should be removed.
Suggested change
— DeepSeek/deepseek-v4-pro via Qwen Code /review |
||||||
| Channel backend: | ||||||
| Proposed historical channel backend experiment, not a wired command today: | ||||||
|
|
||||||
| ```bash | ||||||
| QWEN_CHANNEL_DAEMON_URL=http://127.0.0.1:4170 qwen channel start telegram | ||||||
| ``` | ||||||
|
|
||||||
| Web backend: | ||||||
| Web backend / BFF target: | ||||||
|
|
||||||
| ```bash | ||||||
| QWEN_WEB_DAEMON_URL=http://127.0.0.1:4170 qwen web-chat-backend | ||||||
|
|
@@ -46,7 +50,9 @@ default and owns daemon session state inside the backend process. | |||||
| 3. Submit inbound user text with `session.prompt()`. | ||||||
| 4. Subscribe to `session.events()` and collect assistant text chunks. | ||||||
| 5. Send final text back through the platform adapter. | ||||||
| 6. Cast permission votes through `session.respondToPermission()`. | ||||||
| 6. Cast permission votes through `session.respondToSessionPermission()` when | ||||||
| `caps.features.session_permission_vote` is advertised; use the legacy | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] "use the legacy request-id route" — the legacy method (
Suggested change
— DeepSeek/deepseek-v4-pro via Qwen Code /review |
||||||
| request-id route only for explicitly single-user or older-daemon fallback. | ||||||
| 7. Cancel active work through `session.cancel()`. | ||||||
|
|
||||||
| ## Minimal Web Backend Flow | ||||||
|
|
@@ -61,9 +67,9 @@ Browser clients must not receive daemon bearer tokens. | |||||
|
|
||||||
| ## Session Isolation Constraint | ||||||
|
|
||||||
| Current daemon Stage 1 behavior is effectively `sessionScope: single` at the | ||||||
| daemon setting level. Until per-request `sessionScope` lands, multi-user channel | ||||||
| or web deployments must choose one of these safe shapes: | ||||||
| Multi-user channel or web deployments must explicitly isolate sessions. Use | ||||||
| per-request `sessionScope: 'thread'` when supported; otherwise choose one of | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] The old text explicitly stated "Current daemon Stage 1 behavior is effectively Suggested fix: Restore the diagnostic: "As of this spike, the daemon does not support per-request — qwen-latest-series-invite-beta-v28 via Qwen Code /review |
||||||
| these safe shapes: | ||||||
|
|
||||||
| - one daemon per channel thread / web room | ||||||
| - one daemon per user workspace | ||||||
|
|
@@ -85,7 +91,7 @@ Do not silently multiplex unrelated channel threads into one daemon session. | |||||
|
|
||||||
| Unknown daemon events must be ignored or forwarded as debug metadata, not fatal. | ||||||
|
|
||||||
| The bridge is not wired into `qwen channel start` yet. Existing Telegram, | ||||||
| The bridge is not wired into `qwen channel start` by default. Existing Telegram, | ||||||
| Weixin, Dingtalk, plugin channel, and browser behavior remains unchanged. | ||||||
|
|
||||||
| ## Explicit Non-Goals | ||||||
|
|
@@ -111,10 +117,11 @@ Weixin, Dingtalk, plugin channel, and browser behavior remains unchanged. | |||||
| - Smoke-test one single-user channel backend against local `qwen serve`. | ||||||
| - Smoke-test browser -> BFF -> daemon without exposing daemon token. | ||||||
|
|
||||||
| ## Blockers Before Default Migration | ||||||
| ## Current Follow-Up Direction | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] The old "Blockers Before Default Migration" sections across all 3 files were explicit checklists of hard prerequisites (session-scoped permission route, daemon-stamped client identity, FileSystemService boundary, session lifecycle close/delete). The new "Current Follow-Up Direction" prose mentions these concepts vaguely, losing the gating semantics. A future implementer scanning the doc will not see a clear stop-sign. Suggested fix: Add a brief "Security Prerequisites" subsection within this section listing the unresolved security items (client identity, session-scoped permission, filesystem boundary). — qwen-latest-series-invite-beta-v28 via Qwen Code /review |
||||||
|
|
||||||
| - Per-request `sessionScope`. | ||||||
| - Session metadata + close/delete lifecycle. | ||||||
| - Daemon-stamped client identity. | ||||||
| - Session-scoped permission route. | ||||||
| - Read-only diagnostics for MCP, skills, providers, and environment. | ||||||
| - Prioritize web chat / web terminal daemon integration first. | ||||||
| - Keep channel adapters on the existing ACP bridge by default. | ||||||
| - Revisit daemon channel integration only after web contract, runtime | ||||||
| diagnostics, identity, permission, and session lifecycle semantics are stable. | ||||||
| - Treat this spike as a server-side bridge reference, not a default migration | ||||||
| checklist. | ||||||
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -1,15 +1,19 @@ | ||||||||
| # IDE Daemon Adapter Draft | ||||||||
| # IDE Daemon Adapter Spike | ||||||||
|
|
||||||||
| ## Goal | ||||||||
|
|
||||||||
| Let the VS Code companion extension dogfood Mode B by connecting from the | ||||||||
| extension host to `qwen serve` through `DaemonSessionClient`. | ||||||||
| Document the default-off IDE daemon adapter spike. | ||||||||
|
|
||||||||
| As of the 2026-05-19 architecture decision, the VS Code companion should keep | ||||||||
| the existing `--acp` child path as its default integration. A daemon-backed IDE | ||||||||
| adapter remains future / behind-flag evaluation after the web chat / web | ||||||||
| terminal contract and daemon control-plane parity are stable. | ||||||||
|
|
||||||||
| The webview must not call the daemon directly. The extension host owns daemon | ||||||||
| URL, token, session id, and SSE replay state, then forwards sanitized app events | ||||||||
| to the webview. | ||||||||
|
|
||||||||
| ## Proposed Entry Point | ||||||||
| ## Historical Experimental Entry Point | ||||||||
|
|
||||||||
| VS Code settings: | ||||||||
|
|
||||||||
|
|
@@ -37,7 +41,9 @@ QWEN_IDE_DAEMON_URL=http://127.0.0.1:4170 code . | |||||||
| 6. Send user prompts through `session.prompt()`. | ||||||||
| 7. Route cancel/model switch through `session.cancel()` and | ||||||||
| `session.setModel()`. | ||||||||
| 8. Route permission decisions through `session.respondToPermission()`. | ||||||||
| 8. Route permission decisions through `session.respondToSessionPermission()` | ||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] The permission-routing guidance says "when advertised; fall back to the legacy permission route" but does not name the capability key (
Suggested change
— DeepSeek/deepseek-v4-pro via Qwen Code /review |
||||||||
| when advertised; fall back to the legacy permission route only for older | ||||||||
| daemons. | ||||||||
|
|
||||||||
| ## Relationship To Existing ACP Connection | ||||||||
|
|
||||||||
|
|
@@ -55,8 +61,8 @@ If an event cannot be faithfully mapped yet, the daemon path should surface a | |||||||
| clear unsupported-state warning rather than silently pretending parity. | ||||||||
|
|
||||||||
| This PR adds `DaemonIdeConnection` as the locally verifiable extension-host | ||||||||
| adapter spike. It is not wired into the default `QwenAgentManager` path yet, so | ||||||||
| existing VS Code behavior remains ACP subprocess based. | ||||||||
| adapter spike. It is not wired into the default `QwenAgentManager` path. | ||||||||
| Existing VS Code behavior remains ACP subprocess based. | ||||||||
|
|
||||||||
| ## Event Mapping Contract | ||||||||
|
|
||||||||
|
|
@@ -112,11 +118,12 @@ the daemon. | |||||||
| - permission UI can resolve a request | ||||||||
| - SSE reconnect uses tracked `Last-Event-ID` | ||||||||
|
|
||||||||
| ## Blockers Before Default Migration | ||||||||
| ## Current Follow-Up Direction | ||||||||
|
|
||||||||
| - Typed daemon event schema. | ||||||||
| - Daemon-stamped client identity. | ||||||||
| - Session-scoped permission route. | ||||||||
| - Read-only runtime diagnostics. | ||||||||
| - FileSystemService boundary and safe file read routes. | ||||||||
| - Output sink refactor for CLI/TUI parity. | ||||||||
| - Keep the existing ACP subprocess path as the default IDE path. | ||||||||
| - Revisit daemon IDE integration later in phases: | ||||||||
| 1. web contract plus workspace/path identity checks | ||||||||
| 2. editor-context routing plus auth/status UI | ||||||||
| 3. control-plane parity | ||||||||
| - Treat this spike as future-migration reference, not an active default | ||||||||
| migration checklist. | ||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,16 +1,20 @@ | ||||||||||||||||
| # TUI Daemon Adapter Draft | ||||||||||||||||
| # TUI Daemon Adapter Spike | ||||||||||||||||
|
|
||||||||||||||||
| ## Goal | ||||||||||||||||
|
|
||||||||||||||||
| Add a flag-gated TUI transport that talks to `qwen serve` through | ||||||||||||||||
| `DaemonSessionClient` instead of creating an in-process `Config` + agent | ||||||||||||||||
| runtime. | ||||||||||||||||
| Document the default-off `DaemonTuiAdapter` spike that was added while | ||||||||||||||||
| evaluating Mode B client integration. | ||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Critical] "Mode B" is retained here but all other "Mode B" references were removed from ide.md and channel-web.md by this PR. It is now an orphaned term, undefined anywhere in the doc set. A reader encountering this file for the first time has no way to understand what "Mode B" refers to.
Suggested change
— qwen-latest-series-invite-beta-v28 via Qwen Code /review |
||||||||||||||||
|
|
||||||||||||||||
| This is a dogfood path for Mode B client migration. It must not replace the | ||||||||||||||||
| default TUI path until output sinks, typed daemon events, session-scoped | ||||||||||||||||
| permission, and lifecycle diagnostics are stable. | ||||||||||||||||
| As of the 2026-05-19 architecture decision, native local TUI is not planned to | ||||||||||||||||
| default-migrate to daemon HTTP/SSE. The normal `qwen` terminal path remains a | ||||||||||||||||
| long-term direct runtime / streamJson / Ink path because it avoids an extra | ||||||||||||||||
| localhost HTTP server hop and keeps the local UX simpler and more reliable. | ||||||||||||||||
|
|
||||||||||||||||
| ## Proposed Entry Point | ||||||||||||||||
| The useful follow-up from this spike is source-adapter / reducer / terminal | ||||||||||||||||
| render-core extraction so native TUI and web terminal can share view-model and | ||||||||||||||||
| rendering logic without forcing native TUI through daemon transport. | ||||||||||||||||
|
|
||||||||||||||||
| ## Historical Experimental Entry Point | ||||||||||||||||
|
|
||||||||||||||||
| ```bash | ||||||||||||||||
| QWEN_DAEMON_URL=http://127.0.0.1:4170 qwen --experimental-daemon-tui | ||||||||||||||||
|
|
@@ -37,9 +41,10 @@ The CLI should refuse this mode unless both are true: | |||||||||||||||
| 5. Submit user prompts through `session.prompt()`. | ||||||||||||||||
| 6. Route cancel through `session.cancel()`. | ||||||||||||||||
| 7. Route model switch through `session.setModel()`. | ||||||||||||||||
| 8. Route permission votes through `session.respondToPermission()`. | ||||||||||||||||
| 8. Route permission votes through `session.respondToSessionPermission()` when | ||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] The new permission-routing guidance says TUI should call
Suggested change
— gpt-5.5 via Qwen Code /review
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] Same capability-key gap as
Suggested change
— DeepSeek/deepseek-v4-pro via Qwen Code /review |
||||||||||||||||
| advertised; fall back to the legacy permission route only for older daemons. | ||||||||||||||||
|
|
||||||||||||||||
| ## Rendering Contract | ||||||||||||||||
| ## Rendering Contract Reference | ||||||||||||||||
|
|
||||||||||||||||
| The first implementation adds `DaemonTuiAdapter`, a locally verifiable reducer | ||||||||||||||||
| and transport spike. It maps only these daemon events: | ||||||||||||||||
|
|
@@ -54,15 +59,17 @@ and transport spike. It maps only these daemon events: | |||||||||||||||
| | `model_switched` | Update footer/model display | | ||||||||||||||||
| | `session_died` | Show disconnected state and stop streaming | | ||||||||||||||||
|
|
||||||||||||||||
| Unknown events must be ignored, not fatal. Typed event reducers will land in a | ||||||||||||||||
| later protocol PR. | ||||||||||||||||
| Unknown events must be ignored, not fatal. Typed event reducers should stay in | ||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] "Typed event reducers should stay in the daemon client/protocol layer, not in server internals" — this is a design constraint with no described enforcement mechanism. Since this doc is now framed as a Spike (historical reference), future implementers are unlikely to encounter or remember this rule. Consider either adding a note about how this constraint is enforced (lint rule, code review checklist, test), or softening the language if enforcement is aspirational. — DeepSeek/deepseek-v4-pro via Qwen Code /review |
||||||||||||||||
| the daemon client/protocol layer, not in server internals, so server transport | ||||||||||||||||
| code does not grow UI-specific state machines. | ||||||||||||||||
|
|
||||||||||||||||
| The adapter is not wired into the default Ink app yet. Existing interactive TUI, | ||||||||||||||||
| The adapter is not wired into the default Ink app. Existing interactive TUI, | ||||||||||||||||
| JSONL, stream-json, and dual-output behavior remains unchanged. | ||||||||||||||||
|
|
||||||||||||||||
| ## Explicit Non-Goals | ||||||||||||||||
|
|
||||||||||||||||
| - Do not remove the current TUI in-process runtime. | ||||||||||||||||
| - Do not make daemon transport the default native TUI path. | ||||||||||||||||
| - Do not change JSONL, stream-json, or dual-output behavior in this PR. | ||||||||||||||||
| - Do not expose file CRUD, MCP management, memory CRUD, or provider/auth | ||||||||||||||||
| mutation through TUI yet. | ||||||||||||||||
|
|
@@ -87,10 +94,11 @@ JSONL, stream-json, and dual-output behavior remains unchanged. | |||||||||||||||
| - permission request can be accepted or rejected | ||||||||||||||||
| - reconnect sends the tracked `Last-Event-ID` | ||||||||||||||||
|
|
||||||||||||||||
| ## Blockers Before Default Migration | ||||||||||||||||
| ## Current Follow-Up Direction | ||||||||||||||||
|
|
||||||||||||||||
| - Typed daemon event schema. | ||||||||||||||||
| - Session-scoped permission route. | ||||||||||||||||
| - Output sink refactor for JSONL / stream-json / dual-output parity. | ||||||||||||||||
| - Session lifecycle close/delete semantics. | ||||||||||||||||
| - Runtime diagnostics for MCP, skills, providers, and workspace env. | ||||||||||||||||
| - Keep native TUI direct by default. | ||||||||||||||||
| - Extract source adapters and a shared terminal render core that can be reused | ||||||||||||||||
| by native TUI and web terminal. | ||||||||||||||||
| - Prioritize web terminal as the daemon-native terminal surface. | ||||||||||||||||
| - Treat this spike as future-migration reference, not an active default | ||||||||||||||||
| migration checklist. | ||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Suggestion] All 3 files add "As of the 2026-05-19 architecture decision" but no ADR, design doc, or decision record exists in the repository for this date. Future readers have no way to verify what this decision entailed, who made it, or whether it has since been superseded.
Suggested fix: Add an ADR in
.qwen/design/, link to the relevant GitHub discussion, or soften the reference (e.g., "As of a May 2026 architecture direction...").— qwen-latest-series-invite-beta-v28 via Qwen Code /review