refactor(vm/daemon): port to Bun.serve + web-standard Request/Response#3175
Open
refactor(vm/daemon): port to Bun.serve + web-standard Request/Response#3175
Conversation
Ports the in-VM daemon from Node's http.createServer to Bun.serve with web-standard Request/Response handlers, fetch()-based reverse proxy and liveness probe, ReadableStream SSE, and AbortSignal.timeout for client timeouts. Top-level imports are ESM; only OS-level concerns (fs, path, child_process, crypto.timingSafeEqual) still come from node: modules. Runner-side: VmBun is now attached to every VmSpec unconditionally (not only when runtime === "bun"), /opt/run-daemon.sh invokes bun directly (with nvm sourced first so child processes inherit corepack/node on PATH), and install-bun.service joins the daemon service's requires/after list. Resolves the VM start hang caused by the old Node launcher dropping PATH for the daemon's child processes. Setup hardening baked in along the way: re-entry guard + resume-on- restart in runSetup, SSE replay ordered before live-broadcast registration, spawnSync-based gitSync helper that surfaces stderr on failure, git safe.directory /app prepended so git 2.35+ can't trip on dubious-ownership, rg output limiting with SIGTERM escalation so large result sets can't wedge the pipe, SIGKILL escalation for stuck processes, and X-Accel-Buffering: no on the SSE stream so edge proxies flush chunks immediately. New daemon-script.e2e.test.ts boots the generated script under Bun on a random port and exercises auth, SSE replay + live broadcast, exec/setup 409 re-entry, bash timeout, reverse-proxy HTML bootstrap injection, chunked POST forwarding, and CORS headers on every response branch. 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:
|
…encies Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two exec/setup tests raced against the daemon's auto-boot runSetup() — the clone to invalid.example.com keeps setupRunning=true for tens of milliseconds, long enough that on CI both the "returns 200" and "returns [200, 409]" tests saw 409 on every call. Strip the boot runSetup() out of the generated script in the test fixture so tests drive setup explicitly and the Bun.serve handler ordering makes the concurrent race deterministic. The grep/glob test spawns rg, which isn't on bare Ubuntu runners — install ripgrep in the test workflow and guard the test with it.skipIf(!hasRipgrep) so dev machines without it don't fail. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
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?
Ports the in-VM daemon from Node's
http.createServertoBun.servewith web-standardRequest/Responsehandlers,fetch()-based reverse proxy and liveness probe,ReadableStreamSSE, andAbortSignal.timeoutfor client timeouts (ESM imports throughout; only OS-level concerns still come fromnode:modules).VmBunis now attached to every VmSpec unconditionally and/opt/run-daemon.shinvokes bun directly withinstall-bun.servicein the daemon's requires — resolving the VM start hang caused by the old Node launcher dropping PATH for the daemon's child processes. Along the way: setup re-entry guard + resume-on-restart,spawnSync-based git helper that surfaces stderr on failure,git safe.directory /appprepended, ordered SSE replay before live broadcasts, rg output limiting with SIGTERM escalation, SIGKILL escalation for stuck processes, andX-Accel-Buffering: noon the SSE stream. A newdaemon-script.e2e.test.tsboots the generated script under Bun on a random port and covers auth, SSE replay + live, exec/setup 409, bash timeout, HTML bootstrap injection, chunked POST forwarding, and CORS on every branch.How to Test
bun test packages/mesh-plugin-user-sandbox/server/runner/freestyle/— 31 pass./app/.gitexists, skip the clone, and continue from install — no hang, no duplicate setup.Migration Notes
None. Behavior is end-to-end compatible: same
/_decopilot_vm/*routes, same bearer-token auth, same base64 body wire format.Review Checklist
🤖 Generated with Claude Code
Summary by cubic
Ports the in-VM daemon to
Bun.servewith web-standard Request/Response and afetch()-based reverse proxy; the daemon now runs under Bun in all VMs. Fixes the VM start hang by always installingVmBunand invoking the daemon via Bun, with no route or wire-format changes.Refactors
Bun.serve;fetch()reverse proxy + HEAD probe; SSE viaReadableStreamwith keep-alives andX-Accel-Buffering: no.rgoutput with SIGTERM, SIGKILL escalation for stuck kills, spawn error handling; re-entry guard + resume-on-restart;gitSyncviaspawnSync;git safe.directory /app.VmBunto everyVmSpec, sourcenvmin the launcher, run/opt/bun/bin/bun; addinstall-bun.service.bun.lock(apps/mesh 2.274.0) and add optional deps@freestyle-sh/with-bun,@freestyle-sh/with-deno,@freestyle-sh/with-nodejs,freestyle-sandboxes.Bug Fixes
VmBunto everyVmSpec(includesinstall-bun.service).Written for commit 6d0c649. Summary will update on new commits.