-
Notifications
You must be signed in to change notification settings - Fork 3k
feat(ide): add daemon connection spike #4199
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
1b28c01
1832fad
7935db3
7664d37
9564083
f3d44b7
fe40ad8
1d9360f
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 |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| # IDE Daemon Adapter Draft | ||
|
|
||
| ## Goal | ||
|
|
||
| Let the VS Code companion extension dogfood Mode B by connecting from the | ||
| extension host to `qwen serve` through `DaemonSessionClient`. | ||
|
|
||
| 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 | ||
|
|
||
| VS Code settings: | ||
|
|
||
| ```json | ||
| { | ||
| "qwen-code.experimentalDaemon.enabled": true, | ||
| "qwen-code.experimentalDaemon.url": "http://127.0.0.1:4170", | ||
| "qwen-code.experimentalDaemon.token": "" | ||
| } | ||
| ``` | ||
|
|
||
| Environment fallback for local dogfood: | ||
|
|
||
| ```bash | ||
| QWEN_IDE_DAEMON_URL=http://127.0.0.1:4170 code . | ||
| ``` | ||
|
|
||
| ## Minimal Flow | ||
|
|
||
| 1. Extension host creates `DaemonClient`. | ||
| 2. Fetch `/capabilities` and verify workspace compatibility. | ||
| 3. Create or attach with `DaemonSessionClient.createOrAttach()`. | ||
| 4. Subscribe to `session.events()` in the extension host. | ||
| 5. Translate daemon events into existing webview messages. | ||
| 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()`. | ||
|
|
||
| ## Relationship To Existing ACP Connection | ||
|
|
||
| The first implementation introduces a sibling connection path, not replace | ||
| `AcpConnection`: | ||
|
|
||
| ```text | ||
| QwenAgentManager | ||
| current default -> AcpConnection -> qwen --acp child | ||
| experimental -> DaemonIdeConnection -> qwen serve HTTP/SSE | ||
| ``` | ||
|
|
||
| Both paths should feed the same higher-level webview callbacks where practical. | ||
| 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. | ||
|
|
||
| ## Event Mapping Contract | ||
|
|
||
| | Daemon event | IDE handling | | ||
| | ---------------------------------------- | -------------------------------------------- | | ||
| | `session_update` / `agent_message_chunk` | Existing assistant stream callback | | ||
| | `session_update` / `agent_thought_chunk` | Existing thinking stream callback | | ||
| | `session_update` / `tool_call` | Existing tool-call update callback | | ||
| | `permission_request` | Existing approval UI callback | | ||
| | `permission_resolved` | Close/update approval UI | | ||
| | `model_switched` | Existing model-state callback where possible | | ||
| | `session_died` | Disconnect UI + reconnect affordance | | ||
|
|
||
| Unknown events must be ignored or logged as debug metadata. | ||
|
|
||
| ## Runtime Locality UX | ||
|
|
||
| The extension must make daemon locality visible: | ||
|
|
||
| - workspace/files are daemon-host paths | ||
| - MCP servers run on the daemon host | ||
| - skills load from the daemon filesystem | ||
| - provider credentials are resolved in the daemon process environment | ||
|
|
||
| Do not imply that local VS Code extensions, local browser profile, local | ||
| localhost services, or local SSH/kube credentials are automatically available to | ||
| the daemon. | ||
|
|
||
| ## Explicit Non-Goals | ||
|
|
||
| - No default migration away from `AcpConnection`. | ||
| - No webview direct-to-daemon transport. | ||
| - No daemon-side file CRUD through the IDE until file service boundaries land. | ||
| - No reverse RPC for editor/browser/clipboard yet. | ||
| - No full remote-control integration. | ||
|
|
||
| ## Merge Safety | ||
|
|
||
| - Default off behind setting/env. | ||
| - Additive sibling connection path. | ||
| - Existing VS Code ACP subprocess path unchanged. | ||
| - Daemon token never crosses into webview JavaScript. | ||
|
|
||
| ## Validation Plan | ||
|
|
||
| - Unit-test daemon session factory connection and SSE event consumption. | ||
| - Unit-test daemon event to existing extension-host callback mapping. | ||
| - Unit-test prompt, cancel, model switch, and permission response forwarding. | ||
| - Unit-test settings/env resolution when the feature flag is wired. | ||
| - Smoke-test local extension host against `qwen serve`: | ||
| - prompt streams into chat | ||
| - cancel works | ||
| - permission UI can resolve a request | ||
| - SSE reconnect uses tracked `Last-Event-ID` | ||
|
|
||
| ## Blockers Before Default Migration | ||
|
|
||
| - 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. |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -310,6 +310,7 @@ | |
| }, | ||
| "dependencies": { | ||
| "@agentclientprotocol/sdk": "^0.14.1", | ||
| "@qwen-code/sdk": "*", | ||
|
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] Consider pinning to a minimum major version or using a caret range ( |
||
| "@qwen-code/webui": "*", | ||
| "@modelcontextprotocol/sdk": "^1.25.1", | ||
| "cors": "^2.8.5", | ||
|
|
||
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.
[Critical] Declaring
@qwen-code/sdkhere does not make the hidden dynamic import available in the packaged VSIX. The extension script still usesvsce package --no-dependencies,.vscodeignoreonly includesdist/plus a few assets, anddaemonIdeConnection.tsintentionally hidesimport('@qwen-code/sdk')from esbuild. That means local builds/tests can pass, but an installed extension will not containnode_modules/@qwen-code/sdk, so enabling the daemon adapter fails at runtime before it can connect. Please either bundle the SDK with a normal import/esbuild path or explicitly include the runtime dependency in the VSIX packaging.— gpt-5.5 via Qwen Code /review