docs/design/2026-08-23-vscode-web-shell-cutover.md
Status: Draft
Depends on #9719.
Make the VS Code companion use Web Shell for the complete chat experience, not only the transcript. Web Shell owns the visible chat UI and its interaction state, and the extension host keeps the VS Code integrations: process lifecycle, authentication, workspace trust, diff editors, and the contributed commands.
This is the first of two follow-up changes. The second change removes the
remaining repository consumers and deletes packages/webui.
PR #9719 replaces the legacy VS Code message timeline with
WebShellTranscript, but the companion remains a hybrid UI:
@qwen-code/webui.packages/webui.@qwen-code/webui/daemon-react-sdk.@qwen-code/web-shell declares @qwen-code/webui as both a peer dependency
and a development dependency.WebShellWithProviders expects the daemon HTTP/SSE runtime, while the
extension owned an ACP connection and exchanged messages with the webview
through postMessage.
This work first built a controlled host entry point driven by the ACP bridge
over postMessage. That entry point reimplemented, against a second protocol,
state Web Shell already derives from the daemon — transcript, streaming,
permissions, questions, session history — and the reimplementation is what kept
regressing. The chat now runs on WebShellWithProviders instead.
The extension spawns qwen serve on a loopback port bound to the workspace,
with --require-auth and a per-process token passed through the environment,
and hands the webview its base URL. The webview talks to that daemon directly;
Web Shell's own session, transcript, and permission machinery is the single
implementation.
The ACP connection remains, but its role narrows to authentication state and
the /auth flow. It no longer carries prompts.
Consequences worth stating plainly:
vscode source type
and its history is scoped to that source. Without it the panel would list
conversations the user started in a terminal./insight progress no longer reaches the host. Web Shell renders its own
insight cards. Restoring the tab dot and notifications needs the webview to
report turn and permission transitions to the host; that is not in this
change.The companion mounts WebShellWithProviders and customizes it through props
rather than through a bespoke embedded component: composer toolbar actions,
host-only slash entries, active-editor context injection, review-diff and
insight-report open handlers, and the session source type. The VS Code chrome
the daemon cannot supply — the view header, session history dropdown,
onboarding, and account dialog — stays in the extension and is themed from VS
Code tokens and localized from the same language signal Web Shell uses.
The host contract covers these existing capabilities:
| State supplied by the host | Actions sent to the host |
|---|---|
| Active session and session summaries | Submit and cancel a prompt |
| Transcript blocks and streaming state | Create or switch session |
| Pending permission and question requests | Respond to permission or question |
| Models, approval mode, commands, and skills | Change model or approval mode |
| Context usage, authentication, and account state | Request completion and authentication |
| Workspace files and pasted images | Open a file, diff, report, or external link |
The contract is owned by @qwen-code/web-shell; it is not a new workspace
package and it does not introduce another shared Message[] model. Transcript
data continues to use the canonical SDK DaemonTranscriptBlock[] contract.
The daemon React providers and hooks currently stored under
packages/webui/src/daemon belong to the Web Shell runtime integration. They
move under packages/web-shell and Web Shell stops importing or declaring
@qwen-code/webui.
If the low-level provider API must remain available to external Web Shell
embedders, it will be exported from a Web Shell subpath. It will not be moved
to a new package. The batteries-included WebShellWithProviders entry remains
the preferred daemon integration.
The cutover is not complete while two implementations remain. When the controlled Web Shell surface owns a capability, the corresponding companion component, hook, state branch, compatibility re-export, style import, and test is removed in the same PR.
The extension may keep code only when it is a real VS Code host capability, such as opening files, showing native diffs, reading the active editor, workspace file search, clipboard integration, or extension lifecycle.
The PR completes and verifies these user flows:
The latest user message remains editable. The host maps the selected transcript turn to a daemon rewind snapshot and rewinds the session before resubmitting.
/insight progress on daemon turn events.@qwen-code/chat-panel, another UI package, or a parallel message
model.packages/webui; that is the dependent cleanup PR.packages/desktop/apps/webui, which is a separately named desktop
application and is not the legacy shared package targeted here.WebShellWithProviders against that daemon and add the props the
companion needs, including its session source type.packages/web-shell nor
packages/vscode-ide-companion depends on @qwen-code/webui.These are implementation steps within one review unit, not separate PRs.
Run the built extension in one real VS Code Extension Development Host using a stable test profile. Launch that host once and reuse it for the full matrix instead of restarting VS Code per case. The dedicated profile avoids modifying the user's normal editor process, must dismiss onboarding without requiring GitHub or Copilot sign-in, and must preserve its extension state between cases.
Capture screenshots for:
The PR test report must distinguish WebView-only assertions from actions whose VS Code host or daemon side effect was observed end to end.
vscode source and the
panel's history lists only them.@qwen-code/webui.@qwen-code/webui.packages/webui are enumerated in the
dependent deletion PR.