fix(decopilot): defer ensureVm() so POST /messages doesn't require a sandbox#3434
Merged
Conversation
…sandbox The eager `ensureVm()` added to `POST /api/:org/decopilot/threads/:id/messages` in #3417 made the route fail when no sandbox provider could be provisioned — e.g. CI environments that don't run a link daemon and don't set STUDIO_SANDBOX_RUNNER (default `"remote-user"` ⇒ `provisionSandbox` throws "No link daemon registered for user ..."). The cross-pod attach scenario in `tests/multi-pod/scenarios/attach-cross-pod.test.ts` only drives the mock AI provider and never needs a real VM, yet POST `/messages` was 500-ing before it ever enqueued the run. `resolveDispatchTarget` only consumed `vm.sandboxProviderKind` from the returned entry, so refactor it to take the kind directly and drop the `ensureVm` call from the POST handler. The built-in tools layer already provisions the sandbox lazily on the first VM-tool invocation via `ensureHandle` in `apps/mesh/src/harnesses/decopilot/built-in-tools/index.ts`, so runs that never touch a VM-backed tool no longer pay the provisioning cost (or its hard prerequisites). 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:
|
tlgimenes
added a commit
that referenced
this pull request
May 22, 2026
…nk-gated (#3436) Without an explicit runner the env defaults to "remote-user", and resolveDispatchTarget then 409s with link_offline because CI doesn't run a link daemon. PR #3434 removed the eager ensureVm() but left the dispatch check in place, so attach-cross-pod still failed at POST /messages. Pinning to "docker" makes resolveDispatchTarget short-circuit to the local cluster default; no sandbox is actually provisioned because ensureVm is lazy and the mock-ai scenario never emits tool calls. 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?
Fixes the multi-pod CI failure (
tests/multi-pod/scenarios/attach-cross-pod.test.ts→ 500"No link daemon registered for user ..."on POST/api/:org/decopilot/threads/:id/messages). PR #3417 added an eagerensureVm()to that handler, which provisions a sandbox viaresolveDefaultSandboxProviderKind→ defaults to"remote-user"when no link is registered ANDSTUDIO_SANDBOX_RUNNERis unset (the multi-pod compose), then throws insideprovisionSandboxbecause there is no link daemon. SinceresolveDispatchTargetonly ever readvm.sandboxProviderKindoff the returned entry, this refactors it to take the kind directly and drops the eagerensureVmcall from the POST handler — the built-in tools layer already provisions the sandbox lazily on the first VM-tool invocation (ensureHandleinapps/mesh/src/harnesses/decopilot/built-in-tools/index.ts), so runs that never touch a VM-backed tool no longer pay the provisioning cost (or its hard prerequisites).How to Test
Multi-Pod Testsworkflow on this branch —attach-cross-pod.test.tsshould pass.cd apps/mesh && bun test src/links/resolve-dispatch-target.test.ts src/api/routes/decopilot/routes.test.ts— all 18 tests pass.bun run dev, send a message that triggersbash/read/write— the VM is provisioned on first tool call (unchanged behavior).Migration Notes
None —
resolveDispatchTargetis internal to mesh and has one production caller.Review Checklist
Summary by cubic
Defers VM provisioning for Decopilot so
POST /api/:org/decopilot/threads/:id/messagesno longer requires a sandbox, fixing 500s in multi-pod CI without a link daemon. Dispatch target is now resolved from the sandbox provider kind, and the VM is created lazily on first tool use.Bug Fixes
ensureVm()inPOST /messages.Refactors
resolveDispatchTargetnow takessandboxProviderKindinstead of a VM entry and avoids provisioning.ensureVm.Written for commit 8fa7d10. Summary will update on new commits. Review in cubic