Summary
When hosting a webview-heavy extension as a remote extension (ExtensionHostKind.Remote + getRemoteAgentServiceOverride({ scanRemoteExtensions: true }) + a real VS Code server), the extension's webview SPA loads fully but stalls mid-bootstrap: the first webview↔extension round-trip succeeds, then no further messages flow, so the SPA never reaches its "ready" state. The same .vsix works perfectly in stock VS Code, so the extension itself is fine.
Concrete case: OpenAI's openai.chatgpt (Codex) extension.
Environment
@codingame/monaco-vscode-api 33.0.9
- VS Code server pinned to commit
987c9597516278c9fcf10d963a0592ce1384ab93
- Remote extension host (REH server) on
localhost:<port>, remoteAuthority set
- Electron 41, macOS (arm64), React 19 renderer
- Service overrides: configuration, extensions, files, model, theme, view-common, views, storage, secret-storage, authentication, notifications, dialogs, chat, extension-gallery, remote-agent
Repro
- Install
openai.chatgpt (platform darwin-arm64) into the REH server's extensions dir; enable its proposed APIs (chatSessionsProvider, languageModelProxy) via product.json.
- Boot monaco-vscode-api as a remote client to the server; open Codex's custom editor (
chatgpt.conversationEditor, scheme openai-codex:) or its webview view.
Expected
SPA boots and renders the chat UI (it does in stock VS Code — verified: renders "Ask Codex to do anything… Powered by your ChatGPT account" in a fresh profile with shared ~/.codex auth).
Actual
- SPA bundle loads fully (all ~250 assets HTTP 200), renders its startup loader.
- Over the webview port I observe the capnp bootstrap:
webview → ["push",["pipeline",0,["services"]]]
webview → ["pull",1]
ext → ["resolve",1,{customAvatars:{…}, fileAttachments:{…}}]
- After that resolve: silence. No further webview↔ext messages (no app-server progress, no shared-object subscribe, no app-level
ready). The SPA's ready is gated behind a React <Suspense> that never releases, so the extension's onDidReceiveMessage('ready') init (font/prompts/route) never fires → permanent loader.
Hypothesis
Webview↔extension message delivery for remote extensions appears to stall after the initial exchange — the first capnp round-trip is delivered, but subsequent webview.postMessage / onDidReceiveMessage traffic doesn't flow (possibly ordering/buffering/volume in the remote webview channel, given ~250 concurrent resource loads + capnp). The same SPA over a local ext host (stock VS Code / Cursor) works.
Questions
- Is bidirectional webview↔ext messaging fully supported for remote extensions in monaco-vscode-api, or is there a known limitation/gap?
- Could the concurrent resource-loading + message volume cause drops on the remote webview channel?
- Any guidance to make a webview-SPA extension complete its bootstrap when hosted remotely?
I can provide the full captured message trace and more details. Thanks!
Summary
When hosting a webview-heavy extension as a remote extension (
ExtensionHostKind.Remote+getRemoteAgentServiceOverride({ scanRemoteExtensions: true })+ a real VS Code server), the extension's webview SPA loads fully but stalls mid-bootstrap: the first webview↔extension round-trip succeeds, then no further messages flow, so the SPA never reaches its "ready" state. The same.vsixworks perfectly in stock VS Code, so the extension itself is fine.Concrete case: OpenAI's
openai.chatgpt(Codex) extension.Environment
@codingame/monaco-vscode-api33.0.9987c9597516278c9fcf10d963a0592ce1384ab93localhost:<port>,remoteAuthoritysetRepro
openai.chatgpt(platformdarwin-arm64) into the REH server's extensions dir; enable its proposed APIs (chatSessionsProvider,languageModelProxy) viaproduct.json.chatgpt.conversationEditor, schemeopenai-codex:) or its webview view.Expected
SPA boots and renders the chat UI (it does in stock VS Code — verified: renders "Ask Codex to do anything… Powered by your ChatGPT account" in a fresh profile with shared
~/.codexauth).Actual
ready). The SPA'sreadyis gated behind a React<Suspense>that never releases, so the extension'sonDidReceiveMessage('ready')init (font/prompts/route) never fires → permanent loader.Hypothesis
Webview↔extension message delivery for remote extensions appears to stall after the initial exchange — the first capnp round-trip is delivered, but subsequent
webview.postMessage/onDidReceiveMessagetraffic doesn't flow (possibly ordering/buffering/volume in the remote webview channel, given ~250 concurrent resource loads + capnp). The same SPA over a local ext host (stock VS Code / Cursor) works.Questions
I can provide the full captured message trace and more details. Thanks!