* docs(ide): draft daemon adapter plan * feat(ide): add daemon connection spike * fix(ide): harden daemon connection lifecycle * fix(ide): harden daemon permission replay * fix(ide): harden daemon connection lifecycle * fix(ide): harden daemon connection adapter * fix(ide): harden daemon permission routing * fix(ide): tighten daemon adapter review gaps --------- Co-authored-by: 秦奇 <gary.gq@alibaba-inc.com>
4.4 KiB
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:
{
"qwen-code.experimentalDaemon.enabled": true,
"qwen-code.experimentalDaemon.url": "http://127.0.0.1:4170",
"qwen-code.experimentalDaemon.token": ""
}
Environment fallback for local dogfood:
QWEN_IDE_DAEMON_URL=http://127.0.0.1:4170 code .
Minimal Flow
- Extension host creates
DaemonClient. - Fetch
/capabilitiesand verify workspace compatibility. - Create or attach with
DaemonSessionClient.createOrAttach(). - Subscribe to
session.events()in the extension host. - Translate daemon events into existing webview messages.
- Send user prompts through
session.prompt(). - Route cancel/model switch through
session.cancel()andsession.setModel(). - Route permission decisions through
session.respondToPermission().
Relationship To Existing ACP Connection
The first implementation introduces a sibling connection path, not replace
AcpConnection:
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.