refactor(sandbox): uniformize sandbox/link/dispatch naming#3463
Merged
Conversation
Captures the full set of renames anchored on Sandbox/SandboxProvider as the canonical nouns: collapses VM/Runner synonyms, replaces vendor-flavored kinds (docker/agent-sandbox/desktop) with location/role-flavored ones (local-docker/cluster/user-desktop), restructures DispatchTarget around `runsIn`, splits dispatch errors into their own type with user_desktop_link_* codes, renames daemon routes from /_decopilot_vm/* to /_sandbox/* with one release of dual-serve, and renames the public MCP tools VM_START/VM_DELETE → SANDBOX_START/SANDBOX_DELETE. Includes a single Kysely migration that sweeps stored kind values, the vmMap→sandboxMap key rename, and stored tool-name references in agent configs; legacy tolerant readers are dropped in the same PR. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the 17-task implementation plan for the sandbox naming spec, and expands the spec's daemon-routes section to enumerate the full /_decopilot_vm/* surface (config/idle/events/read/write/edit/grep/glob/ bash/write_from_url/upload_to_url, not just dispatch/runs) so the dual-serve compat covers the whole prefix. Tasks are ordered to leave the codebase green after each task. The canonical-noun foundation (types, enum, field names) lands first; the DB migration (Task 14) goes last so it deploys alongside code that reads/writes the new shape. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…cluster/user-desktop
Renames the three SandboxProviderKind enum values throughout the codebase
to use clearer, role-descriptive names:
- "docker" → "local-docker"
- "agent-sandbox" → "cluster"
- "desktop" → "user-desktop"
Updates the env var default (STUDIO_SANDBOX_RUNNER, name unchanged), the
RUNNER_KIND constants in each provider, the resolver/lifecycle dispatch
sites, the VM_START/VM_DELETE schemas, tests, and UI references. The
sandboxPreference / DispatchTarget.sandbox string-literal unions are
intentionally left alone (renamed in a later task).
Mesh-SDK's tolerant readers (parseVmMapEntry, parseBranchMap) accept both
the canonical kinds and the legacy ones ("docker"/"agent-sandbox"/"desktop"
plus pre-removal "freestyle"/"host") and normalize them to canonical on
read, so on-disk vmMap entries written before this rename keep parsing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two describe() docstrings still referenced the legacy "docker"/ "agent-sandbox"/"desktop" kind names after the value rename in 10dd34f. Sync them to "local-docker"/"cluster"/"user-desktop" so the schema docs match the storage-types update from the same commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…w kinds T1+T2 follow-up addressing code-quality review findings: - Update tests/multi-pod/docker-compose.yml, deploy/helm/sandbox-env/README.md, packages/sandbox/README.md to use canonical kind values; the env validator now hard-rejects legacy values. - Widen input Zod schemas (decopilot/schemas.ts, vm/start.ts) to accept legacy kind values and normalize at the boundary, so Studio tabs in flight during rollout don't get 4xx errors. - Export the legacy->canonical normalizer from mesh-sdk and reuse it in vm-events-handler and vm/stop instead of inlining the cascade. - Update stale describe-string and block comment; add TODO(task-15) pointer next to the widened tolerant-reader union. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…andle Tolerant reader accepts both `vmId` (legacy) and `sandboxHandle` (canonical) on read; writers emit only the new name. The data migration in Task 14 sweeps existing rows; Task 15 removes the tolerant key after the rolling deploy window. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
readSandboxMap prefers the new `sandboxMap` key and falls back to `vmMap` for rows that the data migration (T14) hasn't rewritten yet. setSandboxMapEntry writes under the new key only and strips the legacy key from the returned metadata blob. T15 will drop the fallback after the rolling deploy window. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…r type
resolveDispatchTarget now returns { ok: true, target } | { ok: false, error }.
Success shape discriminates on `runsIn: "cluster" | "user-desktop"`; the
sandbox field uses the canonical SandboxProviderKind. Error codes renamed to
user_desktop_link_offline / user_desktop_link_capability_missing for
clarity. Callers updated to the new pattern.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The discriminated union returned by resolveDispatchTarget (T6) makes the error case impossible past the prepare boundary, so the class has zero importers. Renamed code strings live on DispatchError.kind instead. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…_DELETE Hard cutover for the public MCP tool names. The DB migration (T14) will rewrite stored references in virtualmcp.metadata; old agent configs holding "VM_START" tool-name strings get swept atomically with the deploy. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes the ambiguity between sandboxUrl (control-plane URL where the sandbox's HTTP API lives) and previewUrl (where the user's dev server serves their app). LinkEntry.tunnelUrl and Sandbox.previewUrl are unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…IDER Hard cutover. The env-var renames the "runner" noun to match the canonical "provider" terminology established elsewhere (SandboxProvider, SandboxProviderKind). Helm + deploy bump is atomic with the code rollout — no compat read of the old name. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…* (dual-serve) The cluster speaks only the new /_sandbox/* prefix. The daemon registers each route under both prefixes for one release window so daemons that haven't auto-updated keep serving while old clusters roll out. The housekeeper script tries the new idle path first and falls back to the legacy path. The next-next release will remove the legacy handlers from the daemon. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ider.ts The file implements the desktop-side provider for the user-desktop kind; the new name is self-describing within the link-daemon directory. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ents/sandbox; vm-* route files Aligns directory and file names with the canonical Sandbox vocabulary. Also renames stop.ts → delete.ts to match the SANDBOX_DELETE tool name, and updates the related web hooks/symbols (useVmStart → useSandboxStart, VmEventsContext → SandboxEventsContext, etc.) inside the renamed subtree. The vmId URL parameter in sandbox-proxy.ts is intentionally left alone to keep the change scoped — it's a routing-layer detail that needs a coordinated frontend update. The api/routes/vm-events.ts parent file is also left unrenamed (not listed in the task) and will be addressed in the docs/comments sweep. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ulary Single-transaction migration that: - Rewrites sandbox_runner_state.sandbox_provider_kind values (docker → local-docker, agent-sandbox → cluster, desktop → user-desktop, plus legacy remote-user → user-desktop). - Renames connections.metadata.vmMap → metadata.sandboxMap. - Rewrites inner kind keys and the sandboxProviderKind field inside each sandboxMap cell with the same mapping; drops legacy host/freestyle cells. - Rewrites stored tool-name strings "VM_START"/"VM_DELETE" → "SANDBOX_START"/"SANDBOX_DELETE" anywhere they appear in agent metadata. All steps idempotent. No down migration. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Migration 091 rewrote every persisted legacy value (docker/agent-sandbox/ desktop/remote-user/host/freestyle kind values; vmMap key; vmId field; VM_START/VM_DELETE tool-name strings). The tolerant readers in mesh-sdk and sandbox-map are now unreachable in steady state — drop them and the normalizer helper, narrow the kind union to the canonical 3 values, and delete the legacy-fallback tests. Input Zod schemas tighten back to canonical-only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sweeps VM → Sandbox, vmMap → sandboxMap, ensureVm → ensureSandbox, decopilot_vm → sandbox in doc comments and READMEs. Migration files, spec/plan docs, and test fixture strings are intentionally preserved as historical references. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Final stray VM→Sandbox name. The function parses a SandboxRecord; the old name was a holdover from the VmMapEntry type that T3 renamed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Final stray "runner" noun in the env validator. Aligns the private const with the rest of the canonical vocabulary. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ocab "default" → "cluster-default" (use whichever sandbox kind STUDIO_SANDBOX_PROVIDER resolves to — could be local-docker, cluster, or user-desktop). "desktop" → "user-desktop" (matches SandboxProviderKind). dispatch-run.ts no longer needs to translate at the boundary. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…sandbox/:virtualMcpId The route mount and param name both update to canonical vocab. The param's value is the virtual MCP ID — the old name `:vmId` was misleading (handler already aliased it to `virtualMcpId` internally). createVmRoutes → createSandboxRoutes. Frontend SSE URL builder updates in lockstep. Legacy unscoped /api/vm-events mount is intentionally NOT touched here — it's part of the separate deprecation-window cohort with logDeprecatedRoute middleware. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
🧪 BenchmarkShould we run the Virtual MCP strategy benchmark for this PR? React with 👍 to run the benchmark.
Benchmark will run on the next push after you react. |
Contributor
Release OptionsSuggested: Patch ( React with an emoji to override the release type:
Current version:
|
Contributor
There was a problem hiding this comment.
No issues found across 160 files
Note: This PR contains a large number of files. cubic only reviews up to 100 files per PR, so some files may not have been reviewed. cubic prioritizes the most important files to review.
On a pro plan you can use ultrareview for larger PRs.
Re-trigger cubic
…hitecture-check # Conflicts: # apps/mesh/migrations/index.ts # apps/mesh/src/web/components/sandbox/preview/preview.tsx
The "picks the most-recently-touched sandboxMap branch" test used the legacy `freestyle` provider kind, which normalizeSandboxMap now silently drops, causing the handler to fall back to a generated branch name. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ests Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
tlgimenes
added a commit
that referenced
this pull request
May 25, 2026
…3468) Releases a new studio-sandbox image that includes the dual-serve daemon routes from #3463 (/_sandbox/* + legacy /_decopilot_vm/*), and bumps the sandbox-env chart's image.tag so deployed warm-pool sandboxes pick up the new image. Without this, post-rename mesh callers hit /_sandbox/config on 0.5.4 daemons that only know the legacy prefix and get a 503 "No dev server" HTML from the fallback proxy. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is this contribution about?
Renames the sandbox subsystem around two canonical nouns (
Sandbox,SandboxProvider), eliminating the overlappingVM/Runnervocabulary. The three provider kinds becomelocal-docker/cluster/user-desktop(replacing vendor-flavoreddocker/agent-sandbox/desktop),DispatchTargetis reshaped around arunsIndiscriminant with a split error type (user_desktop_link_offline/user_desktop_link_capability_missing), the public MCP tools becomeSANDBOX_START/SANDBOX_DELETE, the env var becomesSTUDIO_SANDBOX_PROVIDER, the daemon route prefix moves from/_decopilot_vm/*to/_sandbox/*with one release of dual-serve compat, and the org-scoped URL surface moves to/api/:org/sandbox/:virtualMcpId/.... Migration091-sandbox-naming-uniformizationsweeps every stored row in one transaction (kind values,vmMap→sandboxMapkey, inner cell rewrites, andVM_START/VM_DELETEtool-name strings); legacy tolerant readers are removed in the same PR. Full spec and implementation plan committed underdocs/superpowers/{specs,plans}/.How to Test
Migration Notes
Review Checklist
Summary by cubic
Unifies sandbox naming across code, API, and UI: VM → Sandbox, runner → provider, kinds →
local-docker/cluster/user-desktop, routes moved to/_sandbox/*and/api/:org/sandbox/:virtualMcpId/:branch/*, and MCP tools renamed toSANDBOX_START/SANDBOX_DELETE. Includes migration (092) to rewrite stored data and drop legacy readers.Refactors
ensureVm→ensureSandbox.docker→local-docker,agent-sandbox→cluster,desktop→user-desktop;sandboxPreference:"default"→"cluster-default","desktop"→"user-desktop".VM_START/VM_DELETE→SANDBOX_START/SANDBOX_DELETE./_decopilot_vm/*→/_sandbox/*(daemon dual-serves for one release); org API/api/:org/vm/:vmId/...→/api/:org/sandbox/:virtualMcpId/:branch/*.vmMap→sandboxMap;VmMapEntry→SandboxRecord;vmId→sandboxHandle;sandboxUrl→sandboxApiUrl.{ ok: true, target: { runsIn: "cluster" | "user-desktop" } }or{ ok: false, error }; errors useuser_desktop_link_*codes.VM_STARTreferences.Migration
STUDIO_SANDBOX_RUNNER→STUDIO_SANDBOX_PROVIDER.092-sandbox-naming-uniformization: rewrites kind values (incl. legacyremote-user→user-desktop),vmMap→sandboxMap, inner keys/fields, and"VM_START"/"VM_DELETE"→"SANDBOX_START"/"SANDBOX_DELETE"; idempotent, no down./_sandbox/*; daemon dual-serves both prefixes for one release./api/:org/sandbox/:virtualMcpId/:branch/*URLs.Written for commit 538b4e7. Summary will update on new commits. Review in cubic