Skip to content

Studio Web: run the agent in a hosted SecEx sandbox (opt-in runtime)#3890

Draft
lezama wants to merge 21 commits into
trunkfrom
add-studio-web-secex-runtime
Draft

Studio Web: run the agent in a hosted SecEx sandbox (opt-in runtime)#3890
lezama wants to merge 21 commits into
trunkfrom
add-studio-web-secex-runtime

Conversation

@lezama

@lezama lezama commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Related issues

Continues the Studio Web effort that landed the web-server + web connector (#3816) and the AgentRuntime seam.

How AI was used in this PR

The runtime, the SSE reader, the pause/answer/resume handling, and this description were drafted with Claude Code, then reviewed; the change typechecks and builds locally.

Proposed Changes

Studio Web can now run the agent in a hosted SecEx sandbox instead of a local child process, so the browser build of Studio works without anything running on the user's machine. Each user gets one sandbox — the cloud analog of "your laptop", with the same ~/Studio/ sites and ~/.claude sessions inside it, like the desktop app.

It plugs into the existing AgentRuntime seam: a new runtime drives the wpcom studio-code endpoint (POST /wpcom/v2/studio-code/run), which runs studio code --json in the sandbox and streams its events back over SSE. The web-server relays those through the same callbacks the local runtime already uses, so the run-manager and the browser UI are untouched.

Interactive questions and multi-turn work like the desktop. There's no live process in the sandbox to answer over IPC, so the runtime mirrors the proven headless pattern: when a turn pauses on a question the agent process stays "connected" instead of exiting, and answering re-drives the endpoint with the user's choice as the next message on the same sandbox session (resolved from turn.completed.sessionId). To the web-server and the UI it looks like an ordinary live run that asks and gets answered.

It's opt-in and zero-risk by default: the local child-process backend stays the default, and the SecEx runtime is only installed when STUDIO_WEB_BACKEND=secex is set.

Testing Instructions

npm run cli:build
STUDIO_WEB_BACKEND=secex node apps/cli/dist/cli/main.mjs web-server
# (sign in first with `auth login`; open the printed URL and send a prompt;
#  when the agent asks a question, answer it in the UI and the turn resumes)

Without the env var, web-server behaves exactly as before (local agent).

Note: full end-to-end depends on the wpcom studio-code /run route being deployed; the runtime is written to that endpoint's contract.

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors? (npm run typecheck and npm run cli:build pass.)

…time

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
lezama and others added 7 commits June 18, 2026 17:55
…runtime

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…debug logging

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…x session

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…enders

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… the getSession race

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… in Node)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread apps/cli/web-server/site-server.ts Fixed
Comment thread apps/cli/web-server/site-server.ts Fixed
lezama and others added 3 commits June 19, 2026 10:47
…preview widget

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… error frame

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nges show

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

const raw = Buffer.from( base64, 'base64' );
const buffer = isDb ? repointDbBuffer( raw, brokerUrl ) : raw;
await fs.mkdir( path.dirname( dest ), { recursive: true } );
const raw = Buffer.from( base64, 'base64' );
const buffer = isDb ? repointDbBuffer( raw, brokerUrl ) : raw;
await fs.mkdir( path.dirname( dest ), { recursive: true } );
await fs.writeFile( dest, buffer );
lezama and others added 10 commits June 19, 2026 11:50
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…paused

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… snapshot lag

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…es mid-session

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t lost to the run lock

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ssion (UI jump-back)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…not any path in the transcript

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The URL newChat-param trigger didn't fire the provider effect from outside the
ChatsProvider; create the session via the connector and navigate to it instead.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants