@multiplayer-app/sandbox 7.0.4 → 7.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/cli.js +45 -23
- package/dist/cli.js.map +3 -3
- package/dist/executor/qemu-executor.d.ts +2 -2
- package/dist/executor/qemu-executor.d.ts.map +1 -1
- package/dist/index.js +45 -23
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/cli.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/cli.ts", "../package.json", "../src/config.ts", "../src/images.ts", "../../builder-types/src/vm.ts", "../../builder-types/src/events.ts", "../../logger/src/logger.ts", "../../logger/src/config.ts", "../../logger/src/kafkajs-logger-creator.ts", "../../logger/src/index.ts", "../src/executor/mock-executor.ts", "../src/executor/qemu-executor.ts", "../src/executor/reattach-utils.ts", "../src/executor/env-encoding.ts", "../src/executor/firecracker-executor.ts", "../src/executor/docker-executor.ts", "../src/executor/docker-sandbox-executor.ts", "../src/executor/remote-executor.ts", "../src/executor/lambda-microvm-executor.ts", "../src/executor/fargate-executor.ts", "../src/executor/detect.ts", "../src/executor/index.ts", "../src/socket-client.ts", "../src/worker-identity.ts", "../src/services/vnc-relay.ts", "../src/services/serial-relay.ts", "../src/console-relays.ts", "../src/prepare-images.ts", "../src/health-server.ts", "../src/microvm-images.ts", "../src/microvm-guest-agents.ts"],
|
|
4
|
-
"sourcesContent": ["#!/usr/bin/env node\n/* eslint-disable no-console -- console output is the CLI's user interface */\n// Worker CLI. Published as the global `sandbox` executable and also available locally via\n// `pnpm --filter @multiplayer-app/sandbox run cli -- <args>`.\nimport 'dotenv/config'\nimport { Command } from 'commander'\nimport { version as WORKER_VERSION } from '../package.json'\nimport { loadWorkerConfigFromEnv } from './config'\nimport { createExecutor } from './executor'\nimport { probeEngines } from './executor/detect'\nimport { defaultImagesDir, hostArch, pullImages, pushImages } from './images'\nimport { connectToSandbox } from './socket-client'\nimport { attachConsoleRelays } from './console-relays'\nimport { artifactImageLocation, prepareWorkerImages } from './prepare-images'\nimport { startSandboxHealthServer } from './health-server'\nimport { createMicrovmImages, listBaseMicrovmImages } from './microvm-images'\nimport { MICROVM_BASE_IMAGE_STACKS, isMicrovmBaseImageStack } from './microvm-guest-agents'\nimport logger from '@multiplayer-app/logger'\n\n// This is a long-running daemon managing potentially many VMs \u2014 one failed operation (e.g. a\n// VM_CREATE rejected by a misconfigured/unavailable engine) must never take the whole worker\n// down and orphan every other VM it's managing. Command handlers already catch their own\n// errors (see socket-client.ts#wrap), but this is the last line of defense against anything\n// that still slips through as a bare rejection/throw.\nprocess.on('unhandledRejection', (reason) => {\n logger.error({ err: reason }, 'unhandled rejection \u2014 sandbox worker continues running')\n})\nprocess.on('uncaughtException', (error) => {\n logger.error({ err: error }, 'uncaught exception \u2014 sandbox worker continues running')\n})\n\nconst program = new Command()\n\nprogram\n .name('sandbox')\n .description('Run and manage a Multiplayer sandbox worker')\n .version(WORKER_VERSION)\n\nprogram\n .command('start')\n .description('start a worker and connect it to the sandbox control plane')\n .option('--token <token>', 'worker authentication token (env: WORKER_TOKEN)')\n .option('--worker-id <id>', 'worker pool/authentication ID (env: WORKER_ID; default: hostname)')\n .option(\n '--sandbox-url <url>',\n 'control-plane base URL (env: SANDBOX_URL; default: https://api.sandbox.filingramp.com/v0)',\n )\n .option('--max-vms <count>', 'maximum concurrent VMs (env: MAX_VMS)')\n .action(\n async (opts: { token?: string; workerId?: string; sandboxUrl?: string; maxVms?: string }) => {\n const config = loadWorkerConfigFromEnv({\n ...process.env,\n ...(opts.token ? { WORKER_TOKEN: opts.token } : {}),\n ...(opts.workerId ? { WORKER_ID: opts.workerId } : {}),\n ...(opts.sandboxUrl ? { SANDBOX_URL: opts.sandboxUrl } : {}),\n ...(opts.maxVms ? { MAX_VMS: opts.maxVms } : {}),\n })\n const socketRef: { current?: ReturnType<typeof connectToSandbox> } = {}\n const healthServer = await startSandboxHealthServer({\n host: config.healthHost,\n port: config.healthPort,\n pathPrefix: config.healthPathPrefix,\n isReady: () => socketRef.current?.connected === true,\n })\n await prepareWorkerImages(config)\n const executor = createExecutor(config)\n const socket = connectToSandbox(config, executor)\n socketRef.current = socket\n attachConsoleRelays(executor, socket)\n\n let stopping = false\n const stop = async (signal: string): Promise<void> => {\n if (stopping) return\n stopping = true\n console.log(`\\n${signal} received; shutting down sandbox worker...`)\n socket.disconnect()\n healthServer.close()\n const results = await Promise.allSettled(\n executor.list().map((vm) => executor.destroy(vm.vmId)),\n )\n const failed = results.filter((result) => result.status === 'rejected')\n if (failed.length) console.error(`Failed to destroy ${failed.length} VM(s) during shutdown`)\n process.exit(failed.length ? 1 : 0)\n }\n\n process.once('SIGINT', () => {\n void stop('SIGINT')\n })\n process.once('SIGTERM', () => {\n void stop('SIGTERM')\n })\n\n logger.info(`Starting sandbox worker ${config.workerId} \u2192 ${config.sandboxUrl}`)\n // Socket.IO's reconnect timers keep the process alive until a termination signal arrives.\n },\n )\n\nprogram\n .command('detect')\n .description('probe this host and report which micro-VM engines it can run')\n .action(() => {\n const probes = probeEngines(\n loadWorkerConfigFromEnv({ ...process.env, WORKER_ID: '-', WORKER_TOKEN: '-' }),\n )\n for (const probe of probes) {\n const status = probe.available ? 'available' : `unavailable \u2014 ${probe.reason}`\n console.log(`${probe.engine.padEnd(15)} ${status}`)\n }\n })\n\nconst images = program\n .command('images')\n .description('manage engine base images (kernel + initramfs for QEMU/Firecracker)')\n\nimages\n .command('pull')\n .description(\n 'download per-stack base images from S3 or an HTTPS mirror into the standard location',\n )\n .requiredOption(\n '--from <location>',\n 's3://bucket[/prefix] or https:// base URL (default derived from S3_BUCKET_ARTIFACTS)',\n artifactImageLocation(),\n )\n .option('--arch <arch>', 'image architecture', hostArch())\n .option('--stack <stack...>', 'stacks to pull (default: all)')\n .option('--dest <dir>', 'destination directory (default: ~/.multiplayer/vm-images/<arch>)')\n .option(\n '--endpoint <url>',\n 'custom S3 endpoint, e.g. a MinIO URL (env: S3_ARTIFACTS_ENDPOINT)',\n process.env.S3_ARTIFACTS_ENDPOINT,\n )\n .action(\n async (opts: {\n from: string\n arch: string\n stack?: string[]\n dest?: string\n endpoint?: string\n }) => {\n const dest = opts.dest ?? defaultImagesDir(opts.arch)\n const files = await pullImages(\n { location: opts.from, arch: opts.arch, stacks: opts.stack, endpoint: opts.endpoint },\n dest,\n )\n for (const file of files) console.log(`pulled ${file}`)\n console.log('\\nbase images ready \u2014 \"sandbox detect\" shows which engines they enable')\n },\n )\n\nimages\n .command('push')\n .description('upload locally built per-stack base images (scripts/setup-vm-images.sh) to S3')\n .requiredOption(\n '--to <location>',\n 's3://bucket[/prefix] (default derived from S3_BUCKET_ARTIFACTS)',\n artifactImageLocation(),\n )\n .option('--arch <arch>', 'image architecture', hostArch())\n .option('--stack <stack...>', 'stacks to push (default: all found locally)')\n .option('--src <dir>', 'source directory (default: ~/.multiplayer/vm-images/<arch>)')\n .option(\n '--endpoint <url>',\n 'custom S3 endpoint, e.g. a MinIO URL (env: S3_ARTIFACTS_ENDPOINT)',\n process.env.S3_ARTIFACTS_ENDPOINT,\n )\n .action(\n async (opts: {\n to: string\n arch: string\n stack?: string[]\n src?: string\n endpoint?: string\n }) => {\n const src = opts.src ?? defaultImagesDir(opts.arch)\n const uploaded = await pushImages(\n { location: opts.to, arch: opts.arch, stacks: opts.stack, endpoint: opts.endpoint },\n src,\n )\n for (const uri of uploaded) console.log(`pushed ${uri}`)\n },\n )\n\nimages\n .command('microvm-list-base')\n .description('list AWS-managed base OS images available in your account/region (candidates for --base-image-arn)')\n .requiredOption('--region <region>', 'AWS region', process.env.AWS_REGION)\n .action(async (opts: { region: string }) => {\n const arns = await listBaseMicrovmImages({ region: opts.region })\n console.log(`AWS-managed base images in ${opts.region}:`)\n for (const arn of arns) console.log(` ${arn}`)\n })\n\nimages\n .command('microvm-create')\n .description(\n 'build this package\\'s guest-agent base images (node/python/static) and register/update ' +\n 'them as AWS Lambda MicroVM images in your own AWS account (uses ambient AWS credentials ' +\n '\u2014 AWS_PROFILE, env vars, an assumed role, ...)',\n )\n .requiredOption('--region <region>', 'AWS region', process.env.AWS_REGION)\n .requiredOption(\n '--bucket <bucket>',\n 'S3 bucket the built code artifact is uploaded to (must already exist)',\n process.env.S3_BUCKET_ARTIFACTS,\n )\n .requiredOption(\n '--base-image-arn <arn>',\n 'AWS-managed base OS image ARN \u2014 see \"sandbox images microvm-list-base\"',\n process.env.MICROVM_BASE_IMAGE_ARN,\n )\n .requiredOption(\n '--build-role-arn <arn>',\n 'IAM role ARN the build assumes to read the artifact from --bucket (needs s3:GetObject)',\n process.env.MICROVM_BUILD_ROLE_ARN,\n )\n .option(\n '--stack <stack...>',\n `stacks to build/register (default: ${MICROVM_BASE_IMAGE_STACKS.join(' ')})`,\n )\n .option('--min-memory-mib <mib>', 'minimum guest memory, MiB', '1024')\n .option('--image-name-prefix <prefix>', 'MicroVM image name prefix, \"<prefix>-<stack>\"', 'sandbox')\n .action(\n async (opts: {\n region: string\n bucket: string\n baseImageArn: string\n buildRoleArn: string\n stack?: string[]\n minMemoryMib: string\n imageNamePrefix: string\n }) => {\n for (const stack of opts.stack ?? []) {\n if (!isMicrovmBaseImageStack(stack)) {\n throw new Error(\n `unsupported stack \"${stack}\" \u2014 must be one of: ${MICROVM_BASE_IMAGE_STACKS.join(', ')}`,\n )\n }\n }\n const { stackArns } = await createMicrovmImages({\n region: opts.region,\n bucket: opts.bucket,\n baseImageArn: opts.baseImageArn,\n buildRoleArn: opts.buildRoleArn,\n stacks: opts.stack?.filter(isMicrovmBaseImageStack),\n minMemoryMib: Number(opts.minMemoryMib),\n imageNamePrefix: opts.imageNamePrefix,\n onProgress: (message) => console.log(message),\n })\n console.log('\\nSet this in your worker environment:')\n console.log(\n `MICROVM_STACK_IMAGE_ARNS=${Object.entries(stackArns)\n .map(([stack, arn]) => `${stack}:${arn}`)\n .join(',')}`,\n )\n },\n )\n\nprogram.parseAsync().catch((error: Error) => {\n console.error(`Error: ${error.message}`)\n process.exit(1)\n})\n", "{\n \"name\": \"@multiplayer-app/sandbox\",\n \"version\": \"7.0.4\",\n \"description\": \"Sandbox worker library and CLI (Docker, QEMU, Firecracker, AWS Lambda MicroVM, Fargate)\",\n \"main\": \"dist/index.js\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"require\": \"./dist/index.js\",\n \"default\": \"./dist/index.js\"\n }\n },\n \"bin\": {\n \"sandbox\": \"dist/cli.js\"\n },\n \"files\": [\n \"dist\"\n ],\n \"publishConfig\": {\n \"access\": \"public\",\n \"registry\": \"https://registry.npmjs.org/\"\n },\n \"scripts\": {\n \"build\": \"tsc --build --force && node scripts/bundle.mjs\",\n \"dev\": \"nodemon --watch src --watch scripts/bundle.mjs --watch package.json --ext ts,mjs,json --exec \\\"pnpm run build && pnpm run worker:start\\\"\",\n \"clean\": \"rm -rf ./dist tsconfig.tsbuildinfo\",\n \"typecheck\": \"tsc --noEmit\",\n \"lint\": \"eslint src/**/*.ts --config ../../eslint.config.js\",\n \"images:build\": \"bash scripts/build-base-images.sh\",\n \"images:publish:local\": \"bash scripts/publish-base-images-local.sh\",\n \"images:upload:local\": \"SKIP_BUILD=1 bash scripts/publish-base-images-local.sh\",\n \"docker:build\": \"docker build -f Dockerfile -t multiplayer-sandbox-worker:local ../..\",\n \"start\": \"node dist/cli.js\",\n \"worker:start\": \"node dist/cli.js start\",\n \"test\": \"tsc --build --force && node --test 'dist/**/*.test.js'\",\n \"prepublishOnly\": \"pnpm run build\",\n \"postversion\": \"git commit -m \\\"sandbox v$npm_package_version\\\" -- package.json && git tag \\\"sandbox-v$npm_package_version\\\" && git push && git push --tags\"\n },\n \"dependencies\": {\n \"@aws-sdk/client-ec2\": \"^3.1087.0\",\n \"@aws-sdk/client-ecs\": \"^3.1087.0\",\n \"@aws-sdk/client-lambda-microvms\": \"^3.1079.0\",\n \"@aws-sdk/client-s3\": \"^3.1079.0\",\n \"archiver\": \"^8.0.0\",\n \"bunyan\": \"1.8.15\",\n \"commander\": \"^14.0.0\",\n \"dotenv\": \"^17.2.3\",\n \"rfb2\": \"^0.2.2\",\n \"socket.io-client\": \"4.8.3\",\n \"ws\": \"^8.18.3\"\n },\n \"devDependencies\": {\n \"@multiplayer-app/builder-types\": \"workspace:*\",\n \"@multiplayer-app/logger\": \"workspace:*\",\n \"@types/archiver\": \"^8.0.0\",\n \"@types/node\": \"^25.8.0\",\n \"@types/ws\": \"^8.18.1\",\n \"esbuild\": \"^0.25.12\",\n \"nodemon\": \"3.1.14\",\n \"typescript\": \"^6.0.3\"\n }\n}\n", "import os from 'os'\nimport path from 'path'\nimport { version as WORKER_VERSION } from '../package.json'\nimport { defaultImagesDir } from './images'\n\nexport { WORKER_VERSION }\n\nexport interface RemoteWorkerConfig {\n agentUrl: string\n authToken?: string\n}\n\nexport interface FirecrackerWorkerConfig {\n bin: string\n imagesDir: string\n kernelPath?: string\n initrdPath?: string\n vmDataPath: string\n}\n\nexport interface QemuWorkerConfig {\n bin: string\n imagesDir: string\n kernelPath?: string\n initrdPath?: string\n vmDataPath: string\n portRangeStart: number\n portRangeEnd: number\n accel: string\n cpu: string\n machine: string\n}\n\nexport interface LambdaMicrovmWorkerConfig {\n region?: string\n imageArn: string\n stackImageArns: Record<string, string>\n ingressConnectorArns?: string[]\n egressConnectorArns?: string[]\n executionRoleArn?: string\n maxIdleSeconds: number\n suspendedDurationSeconds: number\n maximumDurationInSeconds: number\n createTimeoutMs: number\n}\n\nexport interface DockerWorkerConfig {\n bin: string\n imagePrefix: string\n imageTag: string\n stackImages: Record<string, string>\n network?: string\n portRangeStart: number\n portRangeEnd: number\n guestPort: number\n}\n\nexport interface DockerSandboxWorkerConfig {\n bin: string\n imagePrefix: string\n imageTag: string\n /** Fully-qualified `sbx template load`ed ref overrides, keyed by stack. */\n stackTemplates: Record<string, string>\n /** In-sandbox start command per stack \u2014 `sbx create shell` doesn't run the image's own CMD. */\n stackAgentCommands: Record<string, string>\n workspaceRoot: string\n portRangeStart: number\n portRangeEnd: number\n guestPort: number\n minMemoryMib: number\n}\n\nexport interface FargateWorkerConfig {\n region?: string\n cluster: string\n taskDefinition?: string\n stackTaskDefinitions: Record<string, string>\n subnets: string[]\n securityGroups?: string[]\n assignPublicIp: boolean\n guestPort: number\n startTimeoutMs: number\n}\n\nexport interface WorkerConfig {\n /** Credential/pool identity. Multiple instances may intentionally share it. */\n workerId: string\n /**\n * Local file this process persists its gateway-assigned runtime routing ID to (see\n * WorkerEvent.ASSIGNED_ID) \u2014 reused on the next boot so REATTACH still finds this\n * replica's VMs after a real process restart, not just a socket reconnect. Every\n * replica needs its own path (a container's own filesystem already gives it one by\n * default; co-located processes on the same host must set distinct WORKER_ID_FILE).\n */\n workerIdFile: string\n token?: string\n sandboxUrl: string\n workerSocketPath: string\n maxVms: number\n healthHost: string\n healthPort: number\n healthPathPrefix: string\n region?: string\n remote: RemoteWorkerConfig\n firecracker: FirecrackerWorkerConfig\n qemu: QemuWorkerConfig\n docker: DockerWorkerConfig\n dockerSandbox: DockerSandboxWorkerConfig\n lambdaMicrovm: LambdaMicrovmWorkerConfig\n fargate: FargateWorkerConfig\n}\n\n/** Format: \"node:<value>,python:<value>\" \u2014 per-stack overrides (MicroVM image ARNs, Fargate task defs). */\nfunction parseStackMap(raw: string | undefined): Record<string, string> {\n const map: Record<string, string> = {}\n if (!raw) return map\n for (const pair of raw.split(',')) {\n const idx = pair.indexOf(':')\n if (idx === -1) continue\n const stack = pair.slice(0, idx).trim()\n const arn = pair.slice(idx + 1).trim()\n if (stack && arn) map[stack] = arn\n }\n return map\n}\n\nfunction parseArnList(raw: string | undefined): string[] | undefined {\n if (!raw) return undefined\n const arns = raw\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean)\n return arns.length ? arns : undefined\n}\n\nfunction resolveSandboxEndpoint(rawUrl: string): {\n sandboxUrl: string\n workerSocketPath: string\n} {\n const url = new URL(rawUrl)\n const basePath = url.pathname.replace(/\\/+$/, '')\n return {\n // Socket.IO treats a URL pathname as a namespace, so connect to the origin\n // and pass the derived HTTP transport path separately. SANDBOX_URL's pathname is the\n // sole source of truth for the socket path \u2014 it must include whatever base the control\n // plane expects (e.g. \"/v0/gapi\" or \"/internal/v0/gapi\"), and \"/workers/ws\" is appended.\n sandboxUrl: url.origin,\n workerSocketPath: `${basePath}/workers/ws`,\n }\n}\n\nexport function loadWorkerConfigFromEnv(env: NodeJS.ProcessEnv = process.env): WorkerConfig {\n const workerId = env.WORKER_ID?.trim() || os.hostname()\n const workerIdFile =\n env.WORKER_ID_FILE?.trim() ||\n path.join(os.tmpdir(), `multiplayer-sandbox-worker-${workerId}.id`)\n const token = env.WORKER_TOKEN?.trim() || undefined\n const sandboxEndpoint = resolveSandboxEndpoint(\n env.SANDBOX_URL ?? 'https://api.sandbox.filingramp.com/v0/gapi',\n )\n\n return {\n workerId,\n workerIdFile,\n token,\n sandboxUrl: sandboxEndpoint.sandboxUrl,\n workerSocketPath: sandboxEndpoint.workerSocketPath,\n maxVms: Number(env.MAX_VMS) || 10,\n healthHost: env.SANDBOX_HEALTH_HOST ?? '0.0.0.0',\n healthPort: Number(env.SANDBOX_HEALTH_PORT) || 3000,\n healthPathPrefix: (env.API_PREFIX ?? '/v0/api').replace(/\\/+$/, ''),\n region: env.WORKER_REGION,\n remote: {\n // No default: an unset AGENT_URL means the remote engine is not configured on this worker\n agentUrl: env.AGENT_URL ?? '',\n authToken: env.AGENT_TOKEN,\n },\n firecracker: {\n bin: env.FIRECRACKER_BIN ?? 'firecracker',\n // Per-stack base images (<imagesDir>/<stack>/vmlinuz + initramfs.img) from\n // `worker-cli images pull` / setup-vm-images.sh; engine detection checks\n // existence, so missing images just disable the engine.\n imagesDir: env.FIRECRACKER_IMAGES_DIR ?? env.VM_IMAGES_DIR ?? defaultImagesDir(),\n // Explicit single-image override, applied to every stack when both are set\n kernelPath: env.FIRECRACKER_KERNEL,\n initrdPath: env.FIRECRACKER_INITRD,\n vmDataPath: env.FIRECRACKER_VM_DATA ?? path.join(os.tmpdir(), 'firecracker-vms'),\n },\n lambdaMicrovm: {\n region: env.MICROVM_AWS_REGION ?? env.AWS_REGION,\n imageArn: env.MICROVM_IMAGE_ARN ?? '',\n stackImageArns: parseStackMap(env.MICROVM_STACK_IMAGE_ARNS),\n ingressConnectorArns: parseArnList(env.MICROVM_INGRESS_CONNECTORS),\n egressConnectorArns: parseArnList(env.MICROVM_EGRESS_CONNECTORS),\n executionRoleArn: env.MICROVM_EXECUTION_ROLE_ARN,\n // 0 disables auto-suspend; the sandbox drives pause/resume explicitly by default\n maxIdleSeconds: Number(env.MICROVM_MAX_IDLE_SECONDS ?? 900),\n suspendedDurationSeconds: Number(env.MICROVM_SUSPENDED_DURATION_SECONDS ?? 28_800),\n maximumDurationInSeconds: Number(env.MICROVM_MAX_DURATION_SECONDS ?? 28_800),\n // A real cold MicroVM boot can comfortably exceed the old 25s hardcoded default \u2014\n // must stay well under the api's own VM_CREATE ack timeout (see vm.service.ts).\n createTimeoutMs: Number(env.MICROVM_CREATE_TIMEOUT_MS ?? 60_000),\n },\n fargate: {\n region: env.FARGATE_AWS_REGION ?? env.AWS_REGION,\n cluster: env.FARGATE_CLUSTER ?? '',\n taskDefinition: env.FARGATE_TASK_DEFINITION,\n // Per-stack task definitions: \"node:builder-node:3,python:builder-python:1\"\n stackTaskDefinitions: parseStackMap(env.FARGATE_STACK_TASK_DEFS),\n subnets:\n env.FARGATE_SUBNETS?.split(',')\n .map((s) => s.trim())\n .filter(Boolean) ?? [],\n securityGroups: env.FARGATE_SECURITY_GROUPS?.split(',')\n .map((s) => s.trim())\n .filter(Boolean),\n // ENABLED when the worker runs outside the task VPC (proxies to the task's public IP)\n assignPublicIp: env.FARGATE_ASSIGN_PUBLIC_IP === 'true',\n guestPort: Number(env.FARGATE_GUEST_PORT) || 8080,\n startTimeoutMs: Number(env.FARGATE_START_TIMEOUT_MS) || 180_000,\n },\n docker: {\n bin: env.DOCKER_BIN ?? 'docker',\n // Local images from `scripts/setup-docker-images.sh`: <imagePrefix>-<stack>:<imageTag>\n imagePrefix: env.DOCKER_IMAGE_PREFIX ?? 'multiplayer-builder-vm',\n imageTag: env.DOCKER_IMAGE_TAG ?? 'local',\n stackImages: parseStackMap(env.DOCKER_STACK_IMAGES),\n network: env.DOCKER_NETWORK,\n portRangeStart: Number(env.DOCKER_PORT_MIN) || 9100,\n portRangeEnd: Number(env.DOCKER_PORT_MAX) || 9199,\n guestPort: Number(env.DOCKER_GUEST_PORT) || 8080,\n },\n dockerSandbox: {\n bin: env.SBX_BIN ?? 'sbx',\n // Bridged from the same local images `docker` (imagePrefix-imageTag) already uses \u2014\n // `docker save` + `sbx template load`, see docker-sandbox-executor.ts.\n imagePrefix: env.SBX_IMAGE_PREFIX ?? env.DOCKER_IMAGE_PREFIX ?? 'multiplayer-builder-vm',\n imageTag: env.SBX_IMAGE_TAG ?? env.DOCKER_IMAGE_TAG ?? 'local',\n stackTemplates: parseStackMap(env.SBX_STACK_TEMPLATES),\n // `sbx create shell` doesn't run the image's own CMD, so the engine launches\n // it explicitly \u2014 defaults match each Dockerfile's own WORKDIR /app + CMD.\n stackAgentCommands: {\n node: 'node app.js',\n python: 'python app.py',\n static: 'node app.js',\n ...parseStackMap(env.SBX_STACK_AGENT_COMMANDS),\n },\n workspaceRoot: env.SBX_WORKSPACE_DIR ?? path.join(os.tmpdir(), 'sbx-vms'),\n portRangeStart: Number(env.SBX_PORT_MIN) || 9200,\n portRangeEnd: Number(env.SBX_PORT_MAX) || 9299,\n guestPort: Number(env.SBX_GUEST_PORT) || 8080,\n // sbx rejects sandboxes below 1 GiB memory.\n minMemoryMib: Number(env.SBX_MIN_MEMORY_MIB) || 1024,\n },\n qemu: {\n bin: env.QEMU_BIN ?? 'qemu-system-aarch64',\n // Per-stack base images (<imagesDir>/<stack>/vmlinuz + initramfs.img) from\n // `worker-cli images pull` / setup-vm-images.sh; engine detection checks\n // existence, so missing images just disable the engine.\n imagesDir: env.QEMU_IMAGES_DIR ?? env.VM_IMAGES_DIR ?? defaultImagesDir(),\n // Explicit single-image override, applied to every stack when both are set\n kernelPath: env.QEMU_KERNEL,\n initrdPath: env.QEMU_INITRD,\n vmDataPath: env.QEMU_VM_DATA ?? path.join(os.tmpdir(), 'qemu-vms'),\n portRangeStart: Number(env.QEMU_PORT_MIN) || 9000,\n portRangeEnd: Number(env.QEMU_PORT_MAX) || 9999,\n // Accelerator: hvf (macOS host), kvm (Linux + /dev/kvm), tcg (software, any host \u2014 slow)\n accel: env.QEMU_ACCEL ?? (process.platform === 'darwin' ? 'hvf' : 'kvm'),\n // CPU model: host requires hvf/kvm; max is best for tcg on aarch64; qemu64 for tcg x86_64\n cpu: env.QEMU_CPU ?? 'host',\n // Machine type: virt (aarch64), q35 (x86_64)\n machine: env.QEMU_MACHINE ?? 'virt',\n },\n }\n}\n", "import fs from 'fs'\nimport os from 'os'\nimport path from 'path'\nimport { pipeline } from 'stream/promises'\nimport { Readable } from 'stream'\nimport { VM_STACKS, type VmStack } from '@multiplayer-app/builder-types'\n\n/** Files that make up one stack's base image (built by scripts/setup-vm-images.sh). */\nexport const IMAGE_FILES = ['vmlinuz', 'initramfs.img'] as const\n/** Stacks included in the published base-image catalog; `generic` remains a local fallback only. */\nexport const PUBLISHED_IMAGE_STACKS = VM_STACKS.filter((stack) => stack !== 'generic')\n\n/** Normalize Node's process.arch to the uname-style names used in image paths. */\nexport function hostArch(): string {\n switch (process.arch) {\n case 'arm64':\n return 'aarch64'\n case 'x64':\n return 'x86_64'\n default:\n return process.arch\n }\n}\n\n/** Default local image directory \u2014 the same location scripts/setup-vm-images.sh writes to. */\nexport function defaultImagesDir(arch: string = hostArch()): string {\n return path.join(os.homedir(), '.multiplayer', 'vm-images', arch)\n}\n\n/** Kernel + initrd for one stack under an images dir, or undefined if incomplete. */\nexport function resolveStackImages(\n imagesDir: string,\n stack: string,\n): { kernelPath: string; initrdPath: string } | undefined {\n const kernelPath = path.join(imagesDir, stack, 'vmlinuz')\n const initrdPath = path.join(imagesDir, stack, 'initramfs.img')\n return fs.existsSync(kernelPath) && fs.existsSync(initrdPath)\n ? { kernelPath, initrdPath }\n : undefined\n}\n\n/** Stacks that have a complete base image under an images dir. */\nexport function availableStacks(imagesDir: string): VmStack[] {\n return VM_STACKS.filter((stack) => resolveStackImages(imagesDir, stack) !== undefined)\n}\n\nexport interface ImageSourceOptions {\n /** s3://bucket[/prefix] or http(s):// base URL holding <arch>/<stack>/vmlinuz + initramfs.img */\n location: string\n arch: string\n /** Stacks to transfer (default: all known stacks). */\n stacks?: readonly string[]\n /** Custom S3 endpoint (MinIO, etc.); implies path-style addressing. */\n endpoint?: string\n}\n\nfunction parseS3Uri(uri: string): { bucket: string; prefix: string } {\n const match = /^s3:\\/\\/([^/]+)\\/?(.*)$/.exec(uri)\n if (!match) throw new Error(`invalid S3 URI \"${uri}\" \u2014 expected s3://bucket[/prefix]`)\n return { bucket: match[1], prefix: match[2].replace(/\\/+$/, '') }\n}\n\nfunction s3Key(prefix: string, arch: string, stack: string, file: string): string {\n return [prefix, arch, stack, file].filter(Boolean).join('/')\n}\n\nasync function makeS3Client(endpoint?: string) {\n const { S3Client } = await import('@aws-sdk/client-s3')\n return new S3Client({\n ...(endpoint\n ? {\n endpoint,\n forcePathStyle: true,\n // A custom endpoint means a local/self-hosted store (MinIO, etc.), not real AWS.\n // Use its own static credentials explicitly rather than the ambient default\n // provider chain \u2014 otherwise, whenever AWS_PROFILE is also set (e.g. for the\n // lambda-microvm engine's real AWS calls), the SDK unconditionally skips static env\n // credentials process-wide and sends the real AWS SSO session to this local store\n // instead, which rejects it since it only recognizes its own configured user.\n credentials: {\n accessKeyId: process.env.AWS_ACCESS_KEY_ID ?? 'minioadmin',\n secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY ?? 'minioadmin',\n },\n }\n : {}),\n ...(process.env.AWS_REGION ? {} : { region: 'us-east-1' }),\n // aws-chunked checksum streaming breaks older S3-compatible stores (MinIO)\n requestChecksumCalculation: 'WHEN_REQUIRED',\n })\n}\n\nasync function downloadFromS3(\n opts: ImageSourceOptions,\n stack: string,\n file: string,\n dest: string,\n): Promise<void> {\n const { GetObjectCommand } = await import('@aws-sdk/client-s3')\n const { bucket, prefix } = parseS3Uri(opts.location)\n const client = await makeS3Client(opts.endpoint)\n const key = s3Key(prefix, opts.arch, stack, file)\n const response = await client.send(new GetObjectCommand({ Bucket: bucket, Key: key }))\n if (!response.Body) throw new Error(`empty response for s3://${bucket}/${key}`)\n await pipeline(response.Body as Readable, fs.createWriteStream(dest))\n}\n\nasync function downloadFromHttp(\n opts: ImageSourceOptions,\n stack: string,\n file: string,\n dest: string,\n): Promise<void> {\n const url = `${opts.location.replace(/\\/+$/, '')}/${opts.arch}/${stack}/${file}`\n const response = await fetch(url)\n if (!response.ok || !response.body) {\n throw new Error(`GET ${url} failed: ${response.status} ${response.statusText}`)\n }\n await pipeline(\n Readable.fromWeb(response.body as import('stream/web').ReadableStream),\n fs.createWriteStream(dest),\n )\n}\n\n/** Download base images for the given stacks into destDir/<stack>/ (atomic per file via .partial rename). */\nexport async function pullImages(opts: ImageSourceOptions, destDir: string): Promise<string[]> {\n const isS3 = opts.location.startsWith('s3://')\n const downloaded: string[] = []\n\n for (const stack of opts.stacks ?? PUBLISHED_IMAGE_STACKS) {\n const stackDir = path.join(destDir, stack)\n fs.mkdirSync(stackDir, { recursive: true })\n for (const file of IMAGE_FILES) {\n const dest = path.join(stackDir, file)\n const partial = `${dest}.partial`\n if (isS3) await downloadFromS3(opts, stack, file, partial)\n else await downloadFromHttp(opts, stack, file, partial)\n fs.renameSync(partial, dest)\n downloaded.push(dest)\n }\n }\n return downloaded\n}\n\n/** Upload base images for the given stacks from srcDir/<stack>/ to s3://bucket[/prefix]/<arch>/<stack>/. */\nexport async function pushImages(opts: ImageSourceOptions, srcDir: string): Promise<string[]> {\n const { PutObjectCommand } = await import('@aws-sdk/client-s3')\n const { bucket, prefix } = parseS3Uri(opts.location)\n const client = await makeS3Client(opts.endpoint)\n const uploaded: string[] = []\n\n const stacks = opts.stacks ?? availableStacks(srcDir)\n if (!stacks.length) {\n throw new Error(`no stack images found under ${srcDir} \u2014 run scripts/setup-vm-images.sh first`)\n }\n\n for (const stack of stacks) {\n for (const file of IMAGE_FILES) {\n const src = path.join(srcDir, stack, file)\n if (!fs.existsSync(src)) {\n throw new Error(`${src} not found \u2014 run scripts/setup-vm-images.sh first`)\n }\n const key = s3Key(prefix, opts.arch, stack, file)\n // Buffer instead of stream: keeps Content-Length exact and avoids aws-chunked\n // encoding that older S3-compatible stores reject. Images are ~20-50 MB.\n await client.send(\n new PutObjectCommand({\n Bucket: bucket,\n Key: key,\n Body: fs.readFileSync(src),\n }),\n )\n uploaded.push(`s3://${bucket}/${key}`)\n }\n }\n return uploaded\n}\n", "import type { GatewayAccessConfig } from './access'\nimport type { VmUsage } from './vm-cost'\n\nexport const VM_STACKS = ['generic', 'node', 'python', 'static'] as const\nexport type VmStack = (typeof VM_STACKS)[number]\n\nexport const VM_ENGINES = [\n 'mock',\n 'qemu',\n 'firecracker',\n 'docker',\n 'docker-sandbox',\n 'remote',\n 'lambda-microvm',\n 'fargate',\n] as const\nexport type VmEngine = (typeof VM_ENGINES)[number]\n\n/** 'service': a persistent process the gateway proxies to. 'job': runs its entrypoint once and exits. */\nexport const VM_RUN_MODES = ['service', 'job'] as const\nexport type VmRunMode = (typeof VM_RUN_MODES)[number]\n\nexport type VmState =\n | 'creating'\n | 'running'\n | 'pausing'\n | 'paused'\n | 'resuming'\n | 'stopping'\n | 'stopped'\n | 'restoring'\n | 'destroying'\n | 'error'\n /** Job VM whose entrypoint exited with code 0. See VmRecord.result. */\n | 'completed'\n /** User-initiated teardown that keeps the record around (e.g. as deployment history) instead of deleting it. */\n | 'destroyed'\n\nexport const VM_ACTIONS = ['pause', 'resume', 'stop', 'restore'] as const\nexport type VmAction = (typeof VM_ACTIONS)[number]\n\nexport interface VmResources {\n vcpuCount: number\n memMib: number\n}\n\nexport interface VmRecord {\n vmId: string\n /** Account that created this VM \u2014 same convention as ReleaseRecord.accountId (req.accountId, never client-supplied). */\n accountId: string\n /** Builder session this VM belongs to; optional for VMs not tied to a session. */\n sessionId?: string\n workerId: string\n stack: VmStack\n /** Micro-VM engine the VM runs on. Absent on records created before engines existed. */\n engine?: VmEngine\n /** Release whose artifact the VM pulled and started at boot. */\n releaseId?: string\n /** Gateway-level access protection (Cloudflare Access-style login gate). */\n access?: GatewayAccessConfig\n resources: VmResources\n state: VmState\n /** 'service' (default) for a persistent proxied process, 'job' for a run-once script. */\n runMode: VmRunMode\n /** Custom environment variables for the guest entrypoint. */\n env?: Record<string, string>\n /** Set once a 'job' VM's entrypoint exits (state becomes 'completed' or 'error'). */\n result?: VmRunResult\n /**\n * Opaque, engine-specific data an executor needs to reattach to this VM after a worker\n * restart (e.g. a QEMU QMP socket path, a Fargate task ARN). Sandbox stores it as-is and\n * never interprets it \u2014 only the executor that created it knows the shape.\n */\n runtimeMetadata?: Record<string, unknown>\n /** Cumulative running-time/cost tracking, updated on every state transition. See vm-cost.ts. */\n usage?: VmUsage\n createdAt: string\n updatedAt: string\n}\n\nexport interface VmCreateRequest {\n /** Builder session to associate the VM with (not validated; informational for now). */\n sessionId?: string\n stack: VmStack\n /** Requested micro-VM engine. Omit to use the scheduled worker's default engine. */\n engine?: VmEngine\n /** Release to deploy into the VM: the guest pulls the artifact (presigned URL), unzips, and starts it. */\n releaseId?: string\n /** 'service' (default) keeps the entrypoint running and proxied; 'job' runs it once and exits. */\n runMode?: VmRunMode\n /** Custom environment variables for the guest entrypoint. */\n env?: Record<string, string>\n resources?: Partial<VmResources>\n}\n\nexport interface VmExecRequest {\n /** Shell command executed inside the VM workspace. */\n command: string\n /** Working directory relative to the VM workspace root. */\n cwd?: string\n /** Wall-clock limit for the command; capped by the executor. */\n timeoutMs?: number\n}\n\nexport interface VmExecResult {\n exitCode: number\n stdout: string\n stderr: string\n durationMs: number\n /** True when stdout/stderr were cut at the executor's output cap. */\n truncated: boolean\n /** True when the command was killed by the timeout. */\n timedOut: boolean\n}\n\n/** Outcome of a 'job' VM's entrypoint running to completion. */\nexport interface VmRunResult {\n exitCode: number\n stdout: string\n stderr: string\n /** True when stdout/stderr were cut at the executor's output cap. */\n truncated: boolean\n durationMs: number\n finishedAt: string\n}\n\nexport interface VmFileWrite {\n /** Path relative to the VM workspace root (no leading slash, no traversal). */\n path: string\n content: string\n /** How `content` is encoded; utf8 by default, base64 for binary files. */\n encoding?: 'utf8' | 'base64'\n}\n\nexport interface VmWriteFilesResult {\n written: Array<{ path: string; bytes: number }>\n}\n\nexport interface ProxyRequestDescriptor {\n method: string\n path: string\n headers: Record<string, string>\n body?: Buffer\n}\n\nexport interface ProxyResponseDescriptor {\n statusCode: number\n headers: Record<string, string>\n body?: Buffer\n}\n\nexport interface CommandResult {\n ok: boolean\n error?: string\n}\n\nexport interface CommandAck<T = unknown> extends CommandResult {\n result?: T\n}\n\nexport const VM_REDIS_KEY_PREFIX = 'vm:'\n\nexport interface VmRegistryEntry {\n workerId: string\n state: VmState\n access?: GatewayAccessConfig\n}\n", "import type { VmAction, VmRunResult } from './vm'\n\n// \u2500\u2500 Worker socket events (sandbox \u2194 worker) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Events exchanged on the worker socket (sandbox side listens, worker side emits \u2014 and vice versa). */\nexport const WorkerEvent = {\n // worker \u2192 sandbox\n HEARTBEAT: 'worker:heartbeat',\n\n // worker \u2192 sandbox, fire-and-forget like HEARTBEAT \u2014 sent once when a 'job' VM's\n // entrypoint exits on its own (the worker has already torn the resource down by then).\n VM_RUN_EXITED: 'vm:run-exited',\n\n // worker \u2192 sandbox after an asynchronous VM_CREATE finishes. Socket.IO acknowledgements\n // cannot be relied on across the detached Redis-adapter emitter used by the API.\n VM_CREATE_RESULT: 'vm:create-result',\n\n // worker \u2192 sandbox, fire-and-forget \u2014 sent when periodic reconciliation finds the\n // underlying resource gone without this worker ever issuing a destroy (e.g. AWS's own\n // idle-suspend/max-duration policies terminating a Lambda MicroVM). Only engines whose\n // VMs can disappear outside an explicit command from this process emit it.\n VM_EXTERNALLY_TERMINATED: 'vm:externally-terminated',\n\n // sandbox \u2192 worker, generated by the control plane and reused by this worker process\n // on Socket.IO reconnects. This keeps duplicate configured WORKER_ID values isolated.\n ASSIGNED_ID: 'worker:assigned-id',\n\n // sandbox \u2192 worker, once right after auth on every (re)connect \u2014 the VMs sandbox's\n // records say this workerId owns, so the worker can try to reattach before its first\n // heartbeat. Always sent, even with an empty array, as a handshake signal.\n REATTACH: 'worker:reattach',\n\n // sandbox \u2192 worker (VM lifecycle commands)\n VM_CREATE: 'vm:create',\n VM_PAUSE: 'vm:pause',\n VM_RESUME: 'vm:resume',\n VM_STOP: 'vm:stop',\n VM_RESTORE: 'vm:restore',\n VM_DESTROY: 'vm:destroy',\n\n // sandbox / gateway \u2192 worker (HTTP proxy)\n PROXY_HTTP: 'proxy:http',\n\n // sandbox \u2192 worker (guest workspace commands)\n VM_EXEC: 'vm:exec',\n VM_WRITE_FILES: 'vm:write-files',\n\n // worker \u2192 sandbox (VNC/terminal media relay)\n VNC_INIT: 'vnc:init',\n VNC_FRAME: 'vnc:frame',\n VNC_COPY_FRAME: 'vnc:copy-frame',\n TERMINAL_DATA: 'terminal:data',\n\n // sandbox \u2192 worker (browser input forwarded downstream)\n VNC_MOUSE: 'vnc:mouse',\n VNC_KEYBOARD: 'vnc:keyboard',\n TERMINAL_ATTACH: 'terminal:attach',\n TERMINAL_DETACH: 'terminal:detach',\n TERMINAL_INPUT: 'terminal:input',\n} as const\n\nexport type WorkerEventName = (typeof WorkerEvent)[keyof typeof WorkerEvent]\n\n/** Maps a VmAction to its worker socket event name. */\nexport const VM_ACTION_EVENTS: Record<VmAction, string> = {\n pause: WorkerEvent.VM_PAUSE,\n resume: WorkerEvent.VM_RESUME,\n stop: WorkerEvent.VM_STOP,\n restore: WorkerEvent.VM_RESTORE,\n}\n\n// \u2500\u2500 Console socket events (browser \u2194 sandbox /vm-console/ws) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Events on the browser-facing console Socket.io namespaces (/vnc and /terminal). */\nexport const ConsoleEvent = {\n // /vnc namespace: sandbox \u2192 browser\n VNC_INIT: 'init',\n VNC_FRAME: 'frame',\n VNC_COPY_FRAME: 'copy-frame',\n\n // /vnc namespace: browser \u2192 sandbox\n VNC_MOUSE: 'mouse',\n VNC_KEYBOARD: 'keyboard',\n\n // /terminal namespace: sandbox \u2194 browser\n TERMINAL_DATA: 'data',\n TERMINAL_INPUT: 'data',\n} as const\n\n// \u2500\u2500 Payload types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface VncInitPayload {\n vmId: string\n width: number\n height: number\n}\n\nexport interface VncFramePayload {\n vmId: string\n x: number\n y: number\n width: number\n height: number\n encoding: 'raw'\n data: Buffer\n}\n\nexport interface VncCopyFramePayload {\n vmId: string\n x: number\n y: number\n src: { x: number; y: number }\n width: number\n height: number\n}\n\nexport interface TerminalDataPayload {\n vmId: string\n data: Buffer\n}\n\nexport interface VncMousePayload {\n vmId: string\n x: number\n y: number\n button: number\n}\n\nexport interface VncKeyboardPayload {\n vmId: string\n keyCode: number\n isDown: boolean\n}\n\nexport interface TerminalInputPayload {\n vmId: string\n data: string\n}\n\nexport interface VmRunExitedPayload extends VmRunResult {\n vmId: string\n}\n\nexport interface VmCreateResultPayload {\n vmId: string\n ok: boolean\n metadata?: Record<string, unknown>\n error?: string\n}\n", "import bunyan, {\n type LoggerOptions,\n type LogLevelString,\n} from 'bunyan'\nimport { hostname } from 'os'\nimport {\n APP_NAME,\n LOG_LEVEL,\n} from './config'\n\nconst HOST_NAME = hostname()\n\nconst loggerOptions: LoggerOptions = {\n name: APP_NAME,\n level: LOG_LEVEL as LogLevelString,\n hostname: HOST_NAME,\n serializers: bunyan.stdSerializers,\n}\n\nexport const logger = bunyan.createLogger(loggerOptions)\n\n// const events = [\n// 'exit',\n// 'SIGINT',\n// 'SIGTERM',\n// 'uncaughtException',\n// ]\n\n// const exit = () => {\n// // logger.reopenFileStreams()\n// }\n\n// events.forEach(event => process.on(event, exit))\n", "export const NODE_ENV = process.env.NODE_ENV || 'development'\nexport const isProduction = NODE_ENV === 'production'\n// npm_package_name is only set when launched via `npm run`/`pnpm run` \u2014 production images start\n// services with a plain `node dist/index.js`, so APP_NAME must be set explicitly there.\nexport const APP_NAME =\n process.env.APP_NAME || process.env.npm_package_name?.split('/').pop() || 'unknown-app'\nexport const LOG_LEVEL = process.env.LOG_LEVEL || (isProduction ? 'info' : 'debug')\n", "import bunyan, { type LoggerOptions } from 'bunyan'\nimport { hostname } from 'os'\nimport { isProduction, APP_NAME } from './config'\n\nconst HOST_NAME = hostname()\n\nconst loggerOptions: LoggerOptions = {\n name: APP_NAME,\n level: isProduction ? 'info' : 'debug',\n hostname: HOST_NAME,\n}\n\nexport const KafkaJsLogCreator = (logLevelConverter: any) => (level: any) => {\n if (level) {\n loggerOptions.level = logLevelConverter(level)\n }\n const logger = bunyan.createLogger(loggerOptions)\n\n return ({ level, log }) => {\n const { message, ...extra } = log\n logger[logLevelConverter(level)]({\n extra,\n }, message)\n }\n}\n", "import { logger } from './logger'\n\nexport { middleware as loggerExpressMiddleware } from './middleware'\nexport { default as logError } from './log-error.decorator'\nexport { default as asyncLogError } from './log-error-async.decorator'\nexport * from './kafkajs-logger-creator'\nexport default logger\nexport * from './kafkajs-logger-creator'\n", "import { execFile } from 'child_process'\nimport fs from 'fs/promises'\nimport http from 'http'\nimport type { IncomingMessage, ServerResponse } from 'http'\nimport os from 'os'\nimport path from 'path'\nimport type { AddressInfo } from 'net'\nimport type {\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmExecRequest,\n VmExecResult,\n VmFileWrite,\n VmRunMode,\n VmRunResult,\n VmWriteFilesResult,\n} from '@multiplayer-app/builder-types'\nimport logger from '@multiplayer-app/logger'\nimport type { Executor, VmHandle, VmSpec } from './types'\n\nconst DEFAULT_EXEC_TIMEOUT_MS = 60_000\nconst MAX_EXEC_TIMEOUT_MS = 300_000\nconst MAX_OUTPUT_BYTES = 1024 * 1024\nconst MAX_FILE_BYTES = 5 * 1024 * 1024\n\nconst CONTENT_TYPES: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'text/javascript; charset=utf-8',\n '.mjs': 'text/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.png': 'image/png',\n '.txt': 'text/plain; charset=utf-8',\n '.md': 'text/plain; charset=utf-8',\n}\n\ninterface ManagedVm {\n handle: VmHandle\n server: http.Server\n port: number\n workspaceDir: string\n runMode: VmRunMode\n startedAt: number\n}\n\n/** ms until a mock 'job' VM synthesizes a completion result \u2014 short enough for tests to not stall. */\nconst MOCK_JOB_DURATION_MS = 250\n\n/** Resolve a workspace-relative path, rejecting escapes (\"../\", absolute paths). */\nfunction resolveWorkspacePath(workspaceDir: string, relativePath: string): string {\n const normalized = path.normalize(relativePath).replace(/^([/\\\\])+/, '')\n const resolved = path.resolve(workspaceDir, normalized)\n if (resolved !== workspaceDir && !resolved.startsWith(workspaceDir + path.sep)) {\n throw new Error(`Path escapes the VM workspace: ${relativePath}`)\n }\n return resolved\n}\n\n/**\n * Stand-in for a real microVM: serves the VM workspace directory over HTTP\n * (index.html fallback), playing the role of \"the app inside the VM\".\n */\nfunction startStandInServer(\n spec: VmSpec,\n workspaceDir: string,\n): Promise<{ server: http.Server; port: number }> {\n const server = http.createServer((req: IncomingMessage, res: ServerResponse) => {\n void (async () => {\n const requestPath = decodeURIComponent((req.url ?? '/').split('?')[0])\n const relative = requestPath === '/' ? 'index.html' : requestPath\n try {\n const filePath = resolveWorkspacePath(workspaceDir, relative)\n const content = await fs.readFile(filePath)\n res.writeHead(200, {\n 'content-type':\n CONTENT_TYPES[path.extname(filePath).toLowerCase()] ?? 'application/octet-stream',\n })\n res.end(content)\n } catch {\n res.writeHead(200, { 'content-type': 'text/plain' })\n res.end(\n `mock vm ${spec.vmId} (${spec.stack}) \u2014 session ${spec.sessionId} \u2014 ${req.method} ${req.url}\\n`,\n )\n }\n })()\n })\n\n return new Promise((resolve, reject) => {\n server.once('error', reject)\n server.listen(0, '127.0.0.1', () => {\n resolve({ server, port: (server.address() as AddressInfo).port })\n })\n })\n}\n\nexport class MockExecutor implements Executor {\n private readonly vms = new Map<string, ManagedVm>()\n private readonly exitHandlers = new Map<string, (result: VmRunResult) => void>()\n\n async create(spec: VmSpec): Promise<VmHandle> {\n const workspaceDir = await fs.mkdtemp(path.join(os.tmpdir(), `mock-vm-${spec.vmId}-`))\n const { server, port } = await startStandInServer(spec, workspaceDir)\n const handle: VmHandle = {\n vmId: spec.vmId,\n sessionId: spec.sessionId,\n stack: spec.stack,\n resources: spec.resources,\n running: true,\n // No real process to configure \u2014 just echoed back for introspection/tests.\n ...(spec.env ? { metadata: { env: spec.env } } : {}),\n }\n\n const runMode = spec.runMode ?? 'service'\n this.vms.set(spec.vmId, { handle, server, port, workspaceDir, runMode, startedAt: Date.now() })\n logger.info({ vmId: spec.vmId, port, workspaceDir, runMode }, 'mock vm created')\n return handle\n }\n\n /** No real process to watch \u2014 just synthesize a successful run shortly after create(). */\n onExit(vmId: string, handler: (result: VmRunResult) => void): void {\n const startedAt = this.vms.get(vmId)?.startedAt ?? Date.now()\n this.exitHandlers.set(vmId, handler)\n setTimeout(() => {\n void (async () => {\n const registered = this.exitHandlers.get(vmId)\n this.exitHandlers.delete(vmId)\n if (!registered) return\n\n const result: VmRunResult = {\n exitCode: 0,\n stdout: `mock job ${vmId} completed\\n`,\n stderr: '',\n truncated: false,\n durationMs: Date.now() - startedAt,\n finishedAt: new Date().toISOString(),\n }\n await this.destroy(vmId)\n registered(result)\n })()\n }, MOCK_JOB_DURATION_MS)\n }\n\n async pause(vmId: string): Promise<VmHandle> {\n return this.setRunning(vmId, false)\n }\n\n async resume(vmId: string): Promise<VmHandle> {\n return this.setRunning(vmId, true)\n }\n\n async stop(vmId: string): Promise<VmHandle> {\n return this.setRunning(vmId, false)\n }\n\n async restore(vmId: string): Promise<VmHandle> {\n return this.setRunning(vmId, true)\n }\n\n async destroy(vmId: string): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) return\n\n await new Promise<void>((resolve) => vm.server.close(() => resolve()))\n await fs.rm(vm.workspaceDir, { recursive: true, force: true })\n this.vms.delete(vmId)\n logger.info({ vmId }, 'mock vm destroyed')\n }\n\n get(vmId: string): VmHandle | undefined {\n return this.vms.get(vmId)?.handle\n }\n\n list(): VmHandle[] {\n return [...this.vms.values()].map((vm) => vm.handle)\n }\n\n async proxyHttp(vmId: string, request: ProxyRequestDescriptor): Promise<ProxyResponseDescriptor> {\n const vm = this.requireRunningVm(vmId)\n\n return new Promise((resolve, reject) => {\n const proxyReq = http.request(\n {\n host: '127.0.0.1',\n port: vm.port,\n method: request.method,\n path: request.path,\n headers: request.headers,\n },\n (proxyRes) => {\n const chunks: Buffer[] = []\n proxyRes.on('data', (chunk) => chunks.push(chunk))\n proxyRes.on('end', () => {\n resolve({\n statusCode: proxyRes.statusCode ?? 502,\n headers: Object.fromEntries(\n Object.entries(proxyRes.headers).map(([key, value]) => [\n key,\n Array.isArray(value) ? value.join(', ') : value ?? '',\n ]),\n ),\n body: Buffer.concat(chunks),\n })\n })\n },\n )\n\n proxyReq.on('error', reject)\n if (request.body) proxyReq.write(request.body)\n proxyReq.end()\n })\n }\n\n async writeFiles(vmId: string, files: VmFileWrite[]): Promise<VmWriteFilesResult> {\n const vm = this.requireRunningVm(vmId)\n const written: Array<{ path: string; bytes: number }> = []\n\n for (const file of files) {\n const buffer = Buffer.from(file.content, file.encoding === 'base64' ? 'base64' : 'utf8')\n if (buffer.byteLength > MAX_FILE_BYTES) {\n throw new Error(\n `File too large (${buffer.byteLength} bytes, max ${MAX_FILE_BYTES}): ${file.path}`,\n )\n }\n const filePath = resolveWorkspacePath(vm.workspaceDir, file.path)\n await fs.mkdir(path.dirname(filePath), { recursive: true })\n await fs.writeFile(filePath, buffer)\n written.push({ path: path.relative(vm.workspaceDir, filePath), bytes: buffer.byteLength })\n }\n\n logger.info({ vmId, files: written.length }, 'mock vm files written')\n return { written }\n }\n\n async exec(vmId: string, request: VmExecRequest): Promise<VmExecResult> {\n const vm = this.requireRunningVm(vmId)\n const cwd = request.cwd ? resolveWorkspacePath(vm.workspaceDir, request.cwd) : vm.workspaceDir\n const timeoutMs = Math.min(request.timeoutMs ?? DEFAULT_EXEC_TIMEOUT_MS, MAX_EXEC_TIMEOUT_MS)\n const startedAt = Date.now()\n\n return new Promise((resolve) => {\n execFile(\n '/bin/sh',\n ['-c', request.command],\n {\n cwd,\n timeout: timeoutMs,\n maxBuffer: MAX_OUTPUT_BYTES,\n env: { ...process.env, HOME: vm.workspaceDir },\n },\n (error, stdout, stderr) => {\n const failed = error as\n | (NodeJS.ErrnoException & { code?: number | string; killed?: boolean })\n | null\n const timedOut = Boolean(failed?.killed)\n const truncated = failed?.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER'\n resolve({\n exitCode: typeof failed?.code === 'number' ? failed.code : failed ? 1 : 0,\n stdout: stdout.slice(0, MAX_OUTPUT_BYTES),\n stderr: stderr.slice(0, MAX_OUTPUT_BYTES),\n durationMs: Date.now() - startedAt,\n truncated: Boolean(truncated),\n timedOut,\n })\n },\n )\n })\n }\n\n private requireRunningVm(vmId: string): ManagedVm {\n const vm = this.vms.get(vmId)\n if (!vm || !vm.handle.running) {\n throw new Error(`vm ${vmId} is not running`)\n }\n return vm\n }\n\n private setRunning(vmId: string, running: boolean): VmHandle {\n const vm = this.vms.get(vmId)\n if (!vm) throw new Error(`vm ${vmId} not found`)\n\n vm.handle = { ...vm.handle, running }\n return vm.handle\n }\n}\n", "import { spawn, type ChildProcess } from 'child_process'\nimport net from 'net'\nimport path from 'path'\nimport fs from 'fs/promises'\nimport os from 'os'\nimport logger from '@multiplayer-app/logger'\nimport type {\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmRecord,\n VmRunMode,\n VmRunResult,\n} from '@multiplayer-app/builder-types'\nimport { resolveStackImages } from '../images'\nimport type { Executor, VmHandle, VmSpec } from './types'\nimport { withTimeout } from './reattach-utils'\nimport { encodeEnvB64 } from './env-encoding'\n\nconst MAX_OUTPUT_BYTES = 1024 * 1024\n/** Printed by the guest init script (see scripts/setup-vm-images.sh) right before it powers off in job mode. */\nconst JOB_EXIT_SENTINEL = '__JOB_EXIT_CODE__:'\n\nexport interface QemuConfig {\n bin?: string\n /** Root of per-stack base images: <imagesDir>/<stack>/{vmlinuz,initramfs.img}. */\n imagesDir?: string\n /** Explicit single-image override; used for every stack when both are set. */\n kernelPath?: string\n initrdPath?: string\n vmDataPath?: string\n httpPortRangeStart?: number\n httpPortRangeEnd?: number\n vncBasePort?: number // base port for VNC displays (default 5900); display N \u2192 port vncBasePort+N\n serialBasePort?: number // base port for serial TCP (default 8000)\n accel?: string // 'hvf' (macOS), 'kvm' (Linux + /dev/kvm), 'tcg' (software, any host)\n cpu?: string // 'host' (hvf/kvm), 'max' (tcg aarch64), 'qemu64' (tcg x86_64)\n machine?: string // 'virt' (aarch64), 'q35' (x86_64)\n}\n\ninterface ManagedVm {\n handle: VmHandle\n // Absent after a reattach \u2014 the original ChildProcess object doesn't survive a worker\n // restart. Lifecycle control still works via QMP; destroy() falls back to killing `pid`.\n process?: ChildProcess\n pid?: number\n hostPort: number\n qmpSocketPath: string\n vncDisplay: number // QEMU display index (port = vncBasePort + vncDisplay)\n serialPort: number\n runMode: VmRunMode\n startedAt: number\n /** Job mode only: bounded capture of the serial console, scraped for JOB_EXIT_SENTINEL on exit. */\n serialBuffer?: { chunks: Buffer[]; bytes: number; socket: net.Socket }\n}\n\nexport class QemuExecutor implements Executor {\n private readonly vms = new Map<string, ManagedVm>()\n private readonly pendingResults = new Map<string, VmRunResult>()\n private readonly exitHandlers = new Map<string, (result: VmRunResult) => void>()\n private readonly usedHttpPorts = new Set<number>()\n private readonly usedDisplays = new Set<number>() // VNC display indices\n private readonly usedSerialPorts = new Set<number>()\n private readonly bin: string\n private readonly vmDataPath: string\n private readonly httpPortStart: number\n private readonly httpPortEnd: number\n private readonly vncBasePort: number\n private readonly serialBasePort: number\n private readonly accel: string\n private readonly cpu: string\n private readonly machine: string\n\n constructor(private readonly config: QemuConfig) {\n this.bin = config.bin ?? 'qemu-system-aarch64'\n this.vmDataPath = config.vmDataPath ?? path.join(os.tmpdir(), 'qemu-vms')\n this.httpPortStart = config.httpPortRangeStart ?? 9000\n this.httpPortEnd = config.httpPortRangeEnd ?? 9099\n this.vncBasePort = config.vncBasePort ?? 5900\n this.serialBasePort = config.serialBasePort ?? 8000\n this.accel = config.accel ?? 'hvf'\n this.cpu = config.cpu ?? 'host'\n this.machine = config.machine ?? 'virt'\n }\n\n private allocateHttpPort(): number {\n for (let p = this.httpPortStart; p <= this.httpPortEnd; p++) {\n if (!this.usedHttpPorts.has(p)) {\n this.usedHttpPorts.add(p)\n return p\n }\n }\n throw new Error('no free HTTP ports in QEMU port range')\n }\n\n private allocateVncDisplay(): number {\n for (let d = 1; d <= 99; d++) {\n if (!this.usedDisplays.has(d)) {\n this.usedDisplays.add(d)\n return d\n }\n }\n throw new Error('no free VNC displays')\n }\n\n private allocateSerialPort(): number {\n for (let p = this.serialBasePort; p <= this.serialBasePort + 99; p++) {\n if (!this.usedSerialPorts.has(p)) {\n this.usedSerialPorts.add(p)\n return p\n }\n }\n throw new Error('no free serial ports')\n }\n\n /** Explicit kernel/initrd override wins; otherwise the stack's base image, falling back to generic. */\n private resolveImages(stack: string): { kernelPath: string; initrdPath: string } {\n if (this.config.kernelPath && this.config.initrdPath) {\n return { kernelPath: this.config.kernelPath, initrdPath: this.config.initrdPath }\n }\n const resolved = this.config.imagesDir\n ? resolveStackImages(this.config.imagesDir, stack) ??\n resolveStackImages(this.config.imagesDir, 'generic')\n : undefined\n if (!resolved) {\n throw new Error(\n `no base image for stack \"${stack}\" under ${this.config.imagesDir} \u2014 run \"worker-cli images pull\"`,\n )\n }\n return resolved\n }\n\n async create(spec: VmSpec): Promise<VmHandle> {\n const { kernelPath, initrdPath } = this.resolveImages(spec.stack)\n const envB64 = encodeEnvB64(spec.env)\n const hostPort = this.allocateHttpPort()\n const vncDisplay = this.allocateVncDisplay()\n const serialPort = this.allocateSerialPort()\n const vncPort = this.vncBasePort + vncDisplay\n\n const vmDir = path.join(this.vmDataPath, spec.vmId)\n await fs.mkdir(vmDir, { recursive: true })\n const qmpSocketPath = path.join(vmDir, 'qmp.sock')\n\n const args = [\n '-machine',\n this.machine,\n '-cpu',\n this.cpu,\n '-accel',\n this.accel,\n '-smp',\n String(spec.resources.vcpuCount),\n '-m',\n String(spec.resources.memMib),\n '-kernel',\n kernelPath,\n '-initrd',\n initrdPath,\n // console=tty0 sends output to VGA framebuffer (VNC); ttyAMA0 to serial.\n // APP_URL_B64: base64-encoded presigned artifact URL \u2014 kernel cmdline params are\n // space-separated, so the raw URL (query string, &) can't be passed directly.\n '-append',\n [\n `console=tty0 console=ttyAMA0 net.ifnames=0 init=/init VM_ID=${spec.vmId} STACK=${spec.stack}`,\n spec.sessionId ? `SESSION_ID=${spec.sessionId}` : '',\n spec.appUrl ? `APP_URL_B64=${Buffer.from(spec.appUrl).toString('base64')}` : '',\n spec.runMode === 'job' ? 'RUN_MODE=job' : '',\n envB64 ? `ENV_B64=${envB64}` : '',\n ]\n .filter(Boolean)\n .join(' '),\n // Networking\n '-netdev',\n `user,id=net0,hostfwd=tcp::${hostPort}-:8080`,\n '-device',\n 'virtio-net-pci,netdev=net0',\n // Display: virtio-gpu-pci works on both aarch64 and x86_64; virtio-vga is x86-only\n '-device',\n 'virtio-gpu-pci',\n '-display',\n 'none',\n '-vnc',\n `127.0.0.1:${vncDisplay}`,\n // Serial console via TCP (xterm.js connects here)\n '-serial',\n `tcp:127.0.0.1:${serialPort},server,nowait`,\n // Control\n '-no-reboot',\n '-qmp',\n `unix:${qmpSocketPath},server,nowait`,\n ]\n\n logger.info({ vmId: spec.vmId, bin: this.bin, args }, 'spawning qemu')\n const proc = spawn(this.bin, args, { stdio: ['ignore', 'pipe', 'pipe'] })\n proc.stdout?.on('data', (d: Buffer) => logger.info({ vmId: spec.vmId }, d.toString().trimEnd()))\n proc.stderr?.on('data', (d: Buffer) =>\n logger.error({ vmId: spec.vmId }, d.toString().trimEnd()),\n )\n const runMode = spec.runMode ?? 'service'\n const startedAt = Date.now()\n proc.on('exit', (code, signal) => {\n const log = code === 0 || code === null ? logger.info.bind(logger) : logger.error.bind(logger)\n log({ vmId: spec.vmId, code, signal }, 'qemu process exited')\n const vm = this.vms.get(spec.vmId)\n if (!vm) return\n\n this.usedHttpPorts.delete(vm.hostPort)\n this.usedDisplays.delete(vm.vncDisplay)\n this.usedSerialPorts.delete(vm.serialPort)\n\n if (vm.runMode === 'job') {\n // Keep the map entry (marked not-running) until onExit() claims the result \u2014 see\n // docker-executor's deliverJobResult comment for why route() needs get() to still work.\n vm.handle = { ...vm.handle, running: false }\n this.reportJobResult(spec.vmId, vm)\n } else {\n this.vms.delete(spec.vmId)\n }\n })\n\n const metadata = { hostPort, qmpSocketPath, vncDisplay, serialPort, pid: proc.pid }\n const handle: VmHandle = {\n vmId: spec.vmId,\n sessionId: spec.sessionId,\n stack: spec.stack,\n resources: spec.resources,\n running: true,\n vncPort,\n serialPort,\n metadata,\n }\n\n const vm: ManagedVm = {\n handle,\n process: proc,\n pid: proc.pid,\n hostPort,\n qmpSocketPath,\n vncDisplay,\n serialPort,\n runMode,\n startedAt,\n }\n this.vms.set(spec.vmId, vm)\n if (runMode === 'job') vm.serialBuffer = connectSerialBuffer(serialPort)\n\n await waitForQmp(qmpSocketPath)\n logger.info({ vmId: spec.vmId, hostPort, vncPort, serialPort, runMode }, 'qemu vm ready')\n return handle\n }\n\n /** Scrapes JOB_EXIT_SENTINEL out of the buffered serial console and reports the result. */\n private reportJobResult(vmId: string, vm: ManagedVm): void {\n vm.serialBuffer?.socket.destroy()\n const output = Buffer.concat(vm.serialBuffer?.chunks ?? []).toString('utf8')\n const sentinelIndex = output.lastIndexOf(JOB_EXIT_SENTINEL)\n const exitCode =\n sentinelIndex === -1\n ? 1\n : Number.parseInt(output.slice(sentinelIndex + JOB_EXIT_SENTINEL.length), 10) || 0\n const stdout = sentinelIndex === -1 ? output : output.slice(0, sentinelIndex)\n\n const result: VmRunResult = {\n exitCode,\n stdout: stdout.slice(0, MAX_OUTPUT_BYTES),\n stderr: '',\n truncated: (vm.serialBuffer?.bytes ?? 0) > MAX_OUTPUT_BYTES,\n durationMs: Date.now() - vm.startedAt,\n finishedAt: new Date().toISOString(),\n }\n logger.info({ vmId, exitCode }, 'qemu job vm exited')\n this.deliverJobResult(vmId, result)\n }\n\n private deliverJobResult(vmId: string, result: VmRunResult): void {\n const handler = this.exitHandlers.get(vmId)\n if (handler) {\n this.exitHandlers.delete(vmId)\n this.vms.delete(vmId)\n handler(result)\n } else {\n this.pendingResults.set(vmId, result)\n }\n }\n\n onExit(vmId: string, handler: (result: VmRunResult) => void): void {\n const pending = this.pendingResults.get(vmId)\n if (pending) {\n this.pendingResults.delete(vmId)\n this.vms.delete(vmId)\n handler(pending)\n return\n }\n this.exitHandlers.set(vmId, handler)\n }\n\n async pause(vmId: string): Promise<VmHandle> {\n await this.qmp(vmId, 'stop')\n return this.setRunning(vmId, false)\n }\n\n async resume(vmId: string): Promise<VmHandle> {\n await this.qmp(vmId, 'cont')\n return this.setRunning(vmId, true)\n }\n\n async stop(vmId: string): Promise<VmHandle> {\n await this.qmp(vmId, 'stop')\n return this.setRunning(vmId, false)\n }\n\n async restore(vmId: string): Promise<VmHandle> {\n await this.qmp(vmId, 'cont')\n return this.setRunning(vmId, true)\n }\n\n async destroy(vmId: string): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) return\n\n try {\n await this.qmp(vmId, 'quit')\n } catch {\n this.killVm(vm)\n }\n\n if (vm.process) {\n const proc = vm.process\n await new Promise<void>((resolve) => {\n if (proc.exitCode !== null) return resolve()\n proc.once('exit', resolve)\n setTimeout(() => {\n this.killVm(vm)\n resolve()\n }, 3_000)\n })\n } else {\n // Reattached VM \u2014 no live ChildProcess to wait on. QMP quit was already requested\n // above; give it a moment, then fall back to killing by pid.\n await new Promise((resolve) => setTimeout(resolve, 1_000))\n this.killVm(vm)\n }\n\n this.usedHttpPorts.delete(vm.hostPort)\n this.usedDisplays.delete(vm.vncDisplay)\n this.usedSerialPorts.delete(vm.serialPort)\n this.vms.delete(vmId)\n await fs.rm(path.join(this.vmDataPath, vmId), { recursive: true, force: true })\n logger.info({ vmId }, 'qemu vm destroyed')\n }\n\n get(vmId: string): VmHandle | undefined {\n return this.vms.get(vmId)?.handle\n }\n\n list(): VmHandle[] {\n return [...this.vms.values()].map((v) => v.handle)\n }\n\n /**\n * Recover a QEMU VM after a worker restart: the process may well have survived (it's not\n * killed just because its Node parent exited), so probe its QMP socket \u2014 if it answers,\n * lifecycle control and HTTP proxying resume normally. There's no live ChildProcess to\n * reattach to, so destroy() falls back to killing the stored pid.\n */\n async reattach(record: VmRecord): Promise<VmHandle | undefined> {\n const meta = record.runtimeMetadata as\n | {\n hostPort?: number\n qmpSocketPath?: string\n vncDisplay?: number\n serialPort?: number\n pid?: number\n }\n | undefined\n if (\n !meta?.qmpSocketPath ||\n meta.hostPort === undefined ||\n meta.vncDisplay === undefined ||\n meta.serialPort === undefined\n ) {\n return undefined\n }\n\n try {\n await withTimeout(sendQmpCommand(meta.qmpSocketPath, 'query-status'), 5_000)\n } catch {\n return undefined\n }\n\n const handle: VmHandle = {\n vmId: record.vmId,\n sessionId: record.sessionId,\n stack: record.stack,\n resources: record.resources,\n running: record.state === 'running',\n vncPort: this.vncBasePort + meta.vncDisplay,\n serialPort: meta.serialPort,\n metadata: meta,\n }\n\n this.usedHttpPorts.add(meta.hostPort)\n this.usedDisplays.add(meta.vncDisplay)\n this.usedSerialPorts.add(meta.serialPort)\n this.vms.set(record.vmId, {\n handle,\n pid: meta.pid,\n hostPort: meta.hostPort,\n qmpSocketPath: meta.qmpSocketPath,\n vncDisplay: meta.vncDisplay,\n serialPort: meta.serialPort,\n runMode: record.runMode,\n startedAt: Date.parse(record.createdAt) || Date.now(),\n })\n\n // Note: a job VM that finished (or is still running) while this worker was offline has\n // no recoverable path here \u2014 the serial buffer only ever lived in the dead worker's\n // memory, and if the guest already powered off the QMP probe above would have failed and\n // returned undefined before reaching this point (reported as \"resource no longer exists\"\n // by MultiEngineExecutor.reattachAll). A still-running job just resumes being watched\n // normally below via the QMP-confirmed process.\n\n logger.info({ vmId: record.vmId }, 'qemu vm reattached')\n return handle\n }\n\n private killVm(vm: ManagedVm): void {\n if (vm.process) {\n vm.process.kill('SIGKILL')\n return\n }\n if (vm.pid) {\n try {\n process.kill(vm.pid, 'SIGKILL')\n } catch {\n /* already gone */\n }\n }\n }\n\n async proxyHttp(vmId: string, request: ProxyRequestDescriptor): Promise<ProxyResponseDescriptor> {\n const vm = this.vms.get(vmId)\n if (!vm?.handle.running) throw new Error(`vm ${vmId} is not running`)\n\n const { default: http } = await import('http')\n return new Promise((resolve, reject) => {\n const req = http.request(\n {\n host: '127.0.0.1',\n port: vm.hostPort,\n method: request.method,\n path: request.path,\n headers: request.headers,\n },\n (res) => {\n const chunks: Buffer[] = []\n res.on('data', (c: Buffer) => chunks.push(c))\n res.on('end', () =>\n resolve({\n statusCode: res.statusCode ?? 502,\n headers: Object.fromEntries(\n Object.entries(res.headers).map(([k, v]) => [\n k,\n Array.isArray(v) ? v.join(', ') : v ?? '',\n ]),\n ),\n body: Buffer.concat(chunks),\n }),\n )\n },\n )\n req.on('error', reject)\n if (request.body) req.write(request.body)\n req.end()\n })\n }\n\n private setRunning(vmId: string, running: boolean): VmHandle {\n const vm = this.vms.get(vmId)\n if (!vm) throw new Error(`vm ${vmId} not found`)\n vm.handle = { ...vm.handle, running }\n return vm.handle\n }\n\n private async qmp(vmId: string, execute: string): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) throw new Error(`vm ${vmId} not found`)\n await sendQmpCommand(vm.qmpSocketPath, execute)\n }\n}\n\n/**\n * Opens our own client connection to the serial TCP port (QEMU holds it open as a server,\n * `nowait`) purely to capture a job's output \u2014 independent of whether a browser is also\n * watching live via SerialRelay/getSerialSource.\n */\nfunction connectSerialBuffer(port: number): {\n chunks: Buffer[]\n bytes: number\n socket: net.Socket\n} {\n const buffer = {\n chunks: [] as Buffer[],\n bytes: 0,\n socket: net.connect({ host: '127.0.0.1', port }),\n }\n buffer.socket.on('data', (chunk: Buffer) => {\n if (buffer.bytes >= MAX_OUTPUT_BYTES) return\n buffer.chunks.push(chunk)\n buffer.bytes += chunk.byteLength\n })\n buffer.socket.on('error', () => {\n /* best-effort capture \u2014 a dropped connection just means a shorter log, not a failure */\n })\n return buffer\n}\n\nfunction waitForQmp(socketPath: string, timeoutMs = 30_000): Promise<void> {\n return new Promise((resolve, reject) => {\n const deadline = Date.now() + timeoutMs\n const attempt = () => {\n if (Date.now() > deadline)\n return reject(new Error(`timed out waiting for QMP socket at ${socketPath}`))\n const sock = net.createConnection(socketPath)\n sock.once('connect', () => {\n sock.destroy()\n resolve()\n })\n sock.once('error', () => setTimeout(attempt, 500))\n }\n attempt()\n })\n}\n\nasync function sendQmpCommand(socketPath: string, execute: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const sock = net.createConnection(socketPath)\n let buf = ''\n let ready = false\n const send = (obj: object) => sock.write(JSON.stringify(obj) + '\\r\\n')\n\n sock.on('data', (data: Buffer) => {\n buf += data.toString()\n let idx: number\n while ((idx = buf.indexOf('\\n')) !== -1) {\n const line = buf.slice(0, idx).trim()\n buf = buf.slice(idx + 1)\n if (!line) continue\n let msg: Record<string, unknown>\n try {\n msg = JSON.parse(line)\n } catch {\n continue\n }\n\n if (msg['QMP']) {\n send({ execute: 'qmp_capabilities' })\n } else if (!ready && 'return' in msg) {\n ready = true\n send({ execute })\n } else if (ready && 'return' in msg) {\n sock.destroy()\n resolve()\n } else if (msg['error']) {\n sock.destroy()\n reject(new Error(`QMP error for \"${execute}\": ${JSON.stringify(msg['error'])}`))\n }\n }\n })\n\n sock.on('error', (e) => {\n if (execute === 'quit') resolve()\n else reject(e)\n })\n sock.on('close', () => resolve())\n })\n}\n", "/** Bounds a reattach probe so one unresponsive socket can't hang the whole `reattachAll` batch. */\nexport function withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n return Promise.race([\n promise,\n new Promise<never>((_, reject) => setTimeout(() => reject(new Error(`timed out after ${ms}ms`)), ms)),\n ])\n}\n", "/**\n * Encodes a custom env var map into the single kernel-cmdline param QEMU/Firecracker guests\n * decode at boot (see the `ENV_B64=*` case in scripts/setup-vm-images.sh's init script).\n * The cmdline is space-delimited with no quoting, so raw `KEY=value with spaces` pairs can't\n * go directly on it (same reason APP_URL is base64-encoded as APP_URL_B64) \u2014 instead the\n * whole map is newline-joined and base64'd into one opaque param.\n */\nexport function encodeEnvB64(env: Record<string, string> | undefined): string | undefined {\n if (!env || Object.keys(env).length === 0) return undefined\n const lines = Object.entries(env)\n .map(([key, value]) => `${key}=${value}`)\n .join('\\n')\n return Buffer.from(lines).toString('base64')\n}\n", "import { spawn, type ChildProcess } from 'child_process'\nimport { exec } from 'child_process'\nimport { promisify } from 'util'\nimport http from 'http'\nimport net from 'net'\nimport path from 'path'\nimport fs from 'fs/promises'\nimport os from 'os'\nimport logger from '@multiplayer-app/logger'\nimport type {\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmRecord,\n VmRunMode,\n VmRunResult,\n} from '@multiplayer-app/builder-types'\nimport { resolveStackImages } from '../images'\nimport type { Executor, SerialSource, VmHandle, VmSpec } from './types'\nimport { withTimeout } from './reattach-utils'\nimport { encodeEnvB64 } from './env-encoding'\n\nconst execAsync = promisify(exec)\n\nconst MAX_OUTPUT_BYTES = 1024 * 1024\n/** Printed by the guest init script (see scripts/setup-vm-images.sh) right before it powers off in job mode. */\nconst JOB_EXIT_SENTINEL = '__JOB_EXIT_CODE__:'\n\nexport interface FirecrackerConfig {\n bin?: string // default: 'firecracker'\n /** Root of per-stack base images: <imagesDir>/<stack>/{vmlinuz,initramfs.img}. */\n imagesDir?: string\n /** Explicit single-image override (vmlinux/bzImage + cpio.gz); used for every stack when both are set. */\n kernelPath?: string\n initrdPath?: string\n vmDataPath?: string // default: /tmp/firecracker-vms\n}\n\ninterface ManagedVm {\n handle: VmHandle\n // Absent after a reattach \u2014 the original ChildProcess object doesn't survive a worker\n // restart. Lifecycle control and HTTP proxying still work via the API socket; the serial\n // console (piped over this process's inherited stdio) does not \u2014 see getSerialSource().\n process?: ChildProcess\n pid?: number\n apiSocketPath: string\n tapName: string\n subnet: number\n guestIp: string\n runMode: VmRunMode\n startedAt: number\n /** Job mode only: bounded capture of the guest's serial stdout, scraped for JOB_EXIT_SENTINEL on exit. */\n serialBuffer?: { chunks: Buffer[]; bytes: number }\n}\n\nexport class FirecrackerExecutor implements Executor {\n private readonly vms = new Map<string, ManagedVm>()\n private readonly usedSubnets = new Set<number>()\n private readonly pendingResults = new Map<string, VmRunResult>()\n private readonly exitHandlers = new Map<string, (result: VmRunResult) => void>()\n private tapCounter = 0\n private readonly bin: string\n private readonly vmDataPath: string\n private networkReady = false\n\n constructor(private readonly config: FirecrackerConfig) {\n this.bin = config.bin ?? 'firecracker'\n this.vmDataPath = config.vmDataPath ?? path.join(os.tmpdir(), 'firecracker-vms')\n }\n\n private allocateSubnet(): number {\n for (let s = 1; s <= 254; s++) {\n if (!this.usedSubnets.has(s)) {\n this.usedSubnets.add(s)\n return s\n }\n }\n throw new Error('no free TAP subnets (max 254 concurrent VMs)')\n }\n\n // Called once before the first VM; sets up host-level IP forwarding + masquerade.\n private async ensureNetworking(): Promise<void> {\n if (this.networkReady) return\n await execAsync('sysctl -w net.ipv4.ip_forward=1')\n const alreadySet = await execAsync(\n 'iptables -t nat -C POSTROUTING -s 172.16.0.0/12 ! -d 172.16.0.0/12 -j MASQUERADE',\n ).catch(() => null)\n if (!alreadySet) {\n await execAsync(\n 'iptables -t nat -A POSTROUTING -s 172.16.0.0/12 ! -d 172.16.0.0/12 -j MASQUERADE',\n )\n }\n this.networkReady = true\n }\n\n /** Explicit kernel/initrd override wins; otherwise the stack's base image, falling back to generic. */\n private resolveImages(stack: string): { kernelPath: string; initrdPath: string } {\n if (this.config.kernelPath && this.config.initrdPath) {\n return { kernelPath: this.config.kernelPath, initrdPath: this.config.initrdPath }\n }\n const resolved = this.config.imagesDir\n ? resolveStackImages(this.config.imagesDir, stack) ??\n resolveStackImages(this.config.imagesDir, 'generic')\n : undefined\n if (!resolved) {\n throw new Error(\n `no base image for stack \"${stack}\" under ${this.config.imagesDir} \u2014 run \"worker-cli images pull\"`,\n )\n }\n return resolved\n }\n\n async create(spec: VmSpec): Promise<VmHandle> {\n const { kernelPath, initrdPath } = this.resolveImages(spec.stack)\n await this.ensureNetworking()\n\n const subnet = this.allocateSubnet()\n const tapName = `fctap${++this.tapCounter}`\n const hostIp = `172.16.${subnet}.1`\n const guestIp = `172.16.${subnet}.2`\n\n const vmDir = path.join(this.vmDataPath, spec.vmId)\n await fs.mkdir(vmDir, { recursive: true })\n const apiSocketPath = path.join(vmDir, 'api.sock')\n await fs.rm(apiSocketPath, { force: true })\n\n // TAP device wired to this VM's Firecracker process\n await execAsync(`ip tuntap add dev ${tapName} mode tap`)\n await execAsync(`ip addr add ${hostIp}/30 dev ${tapName}`)\n await execAsync(`ip link set ${tapName} up`)\n\n const runMode = spec.runMode ?? 'service'\n const envB64 = encodeEnvB64(spec.env)\n const startedAt = Date.now()\n const serialBuffer = runMode === 'job' ? { chunks: [] as Buffer[], bytes: 0 } : undefined\n\n // stdin is piped so terminal input can be written to the guest's ttyS0 console\n const proc = spawn(this.bin, ['--api-sock', apiSocketPath], {\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n proc.stdout?.on('data', (d: Buffer) => {\n logger.debug({ vmId: spec.vmId }, d.toString().trimEnd())\n if (serialBuffer && serialBuffer.bytes < MAX_OUTPUT_BYTES) {\n serialBuffer.chunks.push(d)\n serialBuffer.bytes += d.byteLength\n }\n })\n proc.stderr?.on('data', (d: Buffer) =>\n logger.debug({ vmId: spec.vmId }, d.toString().trimEnd()),\n )\n proc.on('exit', (code, signal) => {\n logger.info({ vmId: spec.vmId, code, signal }, 'firecracker process exited')\n const vm = this.vms.get(spec.vmId)\n if (vm) {\n this.usedSubnets.delete(vm.subnet)\n if (vm.runMode === 'job') {\n // Keep the map entry (marked not-running) until onExit() claims the result \u2014 see\n // docker-executor's deliverJobResult comment for why route() needs get() to work.\n vm.handle = { ...vm.handle, running: false }\n this.reportJobResult(spec.vmId, vm)\n } else {\n this.vms.delete(spec.vmId)\n }\n }\n execAsync(`ip link del ${tapName}`).catch(() => {})\n })\n\n await waitForSocket(apiSocketPath)\n\n const macHex = (n: number) => n.toString(16).padStart(2, '0')\n await fcRequest(apiSocketPath, 'PUT', '/machine-config', {\n vcpu_count: spec.resources.vcpuCount,\n mem_size_mib: spec.resources.memMib,\n })\n await fcRequest(apiSocketPath, 'PUT', '/boot-source', {\n kernel_image_path: kernelPath,\n initrd_path: initrdPath,\n boot_args: [\n 'console=ttyS0',\n 'reboot=k',\n 'panic=1',\n 'pci=off',\n 'net.ifnames=0',\n 'init=/init',\n `VM_ID=${spec.vmId}`,\n ...(spec.sessionId ? [`SESSION_ID=${spec.sessionId}`] : []),\n `STACK=${spec.stack}`,\n // base64: kernel cmdline is space-separated, raw presigned URLs are not safe\n ...(spec.appUrl ? [`APP_URL_B64=${Buffer.from(spec.appUrl).toString('base64')}`] : []),\n `GUEST_IP=${guestIp}`,\n `HOST_IP=${hostIp}`,\n ...(runMode === 'job' ? ['RUN_MODE=job'] : []),\n ...(envB64 ? [`ENV_B64=${envB64}`] : []),\n ].join(' '),\n })\n await fcRequest(apiSocketPath, 'PUT', '/network-interfaces/eth0', {\n iface_id: 'eth0',\n // AA = locally-administered unicast; encode subnet as last two bytes\n guest_mac: `AA:FC:00:00:${macHex(subnet >> 8)}:${macHex(subnet & 0xff)}`,\n host_dev_name: tapName,\n })\n await fcRequest(apiSocketPath, 'PUT', '/actions', { action_type: 'InstanceStart' })\n\n // A job's entrypoint may finish before it ever answers HTTP \u2014 the readiness gate below\n // only applies to persistent services.\n if (runMode !== 'job') await waitForHttp(guestIp, 8080)\n\n const metadata = { apiSocketPath, tapName, subnet, guestIp, pid: proc.pid }\n const handle: VmHandle = {\n vmId: spec.vmId,\n sessionId: spec.sessionId,\n stack: spec.stack,\n resources: spec.resources,\n running: true,\n metadata,\n }\n this.vms.set(spec.vmId, {\n handle,\n process: proc,\n pid: proc.pid,\n apiSocketPath,\n tapName,\n subnet,\n guestIp,\n runMode,\n startedAt,\n serialBuffer,\n })\n logger.info({ vmId: spec.vmId, guestIp, tapName, runMode }, 'firecracker vm ready')\n return handle\n }\n\n /** Scrapes JOB_EXIT_SENTINEL out of the buffered serial stdout and reports the result. */\n private reportJobResult(vmId: string, vm: ManagedVm): void {\n const output = Buffer.concat(vm.serialBuffer?.chunks ?? []).toString('utf8')\n const sentinelIndex = output.lastIndexOf(JOB_EXIT_SENTINEL)\n const exitCode =\n sentinelIndex === -1\n ? 1\n : Number.parseInt(output.slice(sentinelIndex + JOB_EXIT_SENTINEL.length), 10) || 0\n const stdout = sentinelIndex === -1 ? output : output.slice(0, sentinelIndex)\n\n const result: VmRunResult = {\n exitCode,\n stdout: stdout.slice(0, MAX_OUTPUT_BYTES),\n stderr: '',\n truncated: (vm.serialBuffer?.bytes ?? 0) > MAX_OUTPUT_BYTES,\n durationMs: Date.now() - vm.startedAt,\n finishedAt: new Date().toISOString(),\n }\n logger.info({ vmId, exitCode }, 'firecracker job vm exited')\n this.deliverJobResult(vmId, result)\n }\n\n private deliverJobResult(vmId: string, result: VmRunResult): void {\n const handler = this.exitHandlers.get(vmId)\n if (handler) {\n this.exitHandlers.delete(vmId)\n this.vms.delete(vmId)\n handler(result)\n } else {\n this.pendingResults.set(vmId, result)\n }\n }\n\n onExit(vmId: string, handler: (result: VmRunResult) => void): void {\n const pending = this.pendingResults.get(vmId)\n if (pending) {\n this.pendingResults.delete(vmId)\n this.vms.delete(vmId)\n handler(pending)\n return\n }\n this.exitHandlers.set(vmId, handler)\n }\n\n async pause(vmId: string): Promise<VmHandle> {\n await this.patchVmState(vmId, 'Paused')\n return this.setRunning(vmId, false)\n }\n\n async resume(vmId: string): Promise<VmHandle> {\n await this.patchVmState(vmId, 'Resumed')\n return this.setRunning(vmId, true)\n }\n\n async stop(vmId: string): Promise<VmHandle> {\n await this.patchVmState(vmId, 'Paused')\n return this.setRunning(vmId, false)\n }\n\n async restore(vmId: string): Promise<VmHandle> {\n await this.patchVmState(vmId, 'Resumed')\n return this.setRunning(vmId, true)\n }\n\n async destroy(vmId: string): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) return\n\n if (vm.process) {\n const proc = vm.process\n proc.kill('SIGKILL')\n await new Promise<void>((resolve) => {\n if (proc.exitCode !== null) return resolve()\n proc.once('exit', resolve)\n setTimeout(() => {\n proc.kill('SIGKILL')\n resolve()\n }, 3_000)\n })\n } else if (vm.pid) {\n // Reattached VM \u2014 no live ChildProcess to wait on; kill by the stored pid.\n try {\n process.kill(vm.pid, 'SIGKILL')\n } catch {\n /* already gone */\n }\n }\n\n this.usedSubnets.delete(vm.subnet)\n this.vms.delete(vmId)\n await execAsync(`ip link del ${vm.tapName}`).catch(() => {})\n await fs.rm(path.join(this.vmDataPath, vmId), { recursive: true, force: true })\n logger.info({ vmId }, 'firecracker vm destroyed')\n }\n\n get(vmId: string): VmHandle | undefined {\n return this.vms.get(vmId)?.handle\n }\n\n getSerialSource(vmId: string): SerialSource | undefined {\n const vm = this.vms.get(vmId)\n // Serial is piped over the child's inherited stdio \u2014 a reattached VM has no live\n // ChildProcess to read that from, so its serial console is unavailable until it's\n // recreated. Lifecycle control and HTTP proxying are unaffected.\n if (!vm?.process) return undefined\n return { type: 'pipe', process: vm.process }\n }\n\n list(): VmHandle[] {\n return [...this.vms.values()].map((v) => v.handle)\n }\n\n /**\n * Recover a Firecracker VM after a worker restart: the process may well have survived, so\n * probe its API socket \u2014 if it answers, lifecycle control and HTTP proxying resume\n * normally. There's no live ChildProcess to reattach to, so destroy() falls back to\n * killing the stored pid, and the serial console is unavailable (see getSerialSource).\n */\n async reattach(record: VmRecord): Promise<VmHandle | undefined> {\n const meta = record.runtimeMetadata as\n | {\n apiSocketPath?: string\n tapName?: string\n subnet?: number\n guestIp?: string\n pid?: number\n }\n | undefined\n if (!meta?.apiSocketPath || !meta.tapName || meta.subnet === undefined || !meta.guestIp) {\n return undefined\n }\n\n try {\n await withTimeout(fcRequest(meta.apiSocketPath, 'GET', '/', {}), 5_000)\n } catch {\n return undefined\n }\n\n const handle: VmHandle = {\n vmId: record.vmId,\n sessionId: record.sessionId,\n stack: record.stack,\n resources: record.resources,\n running: record.state === 'running',\n metadata: meta,\n }\n\n this.usedSubnets.add(meta.subnet)\n // Keep future tap names from colliding with this reattached one.\n const tapNumber = Number(meta.tapName.replace(/^fctap/, ''))\n if (Number.isFinite(tapNumber)) this.tapCounter = Math.max(this.tapCounter, tapNumber)\n\n this.vms.set(record.vmId, {\n handle,\n pid: meta.pid,\n apiSocketPath: meta.apiSocketPath,\n tapName: meta.tapName,\n subnet: meta.subnet,\n guestIp: meta.guestIp,\n runMode: record.runMode,\n startedAt: Date.parse(record.createdAt) || Date.now(),\n })\n\n // Note: same limitation as QemuExecutor.reattach \u2014 a job VM's serial buffer only ever\n // lived in the dead worker's memory, and a still-running one has no ChildProcess here to\n // detect its eventual exit (getSerialSource already documents the equivalent gap for the\n // live console). Not solved in v1.\n\n logger.info(\n { vmId: record.vmId, guestIp: meta.guestIp, tapName: meta.tapName },\n 'firecracker vm reattached',\n )\n return handle\n }\n\n async proxyHttp(vmId: string, request: ProxyRequestDescriptor): Promise<ProxyResponseDescriptor> {\n const vm = this.vms.get(vmId)\n if (!vm?.handle.running) throw new Error(`vm ${vmId} is not running`)\n\n return new Promise((resolve, reject) => {\n const req = http.request(\n {\n host: vm.guestIp,\n port: 8080,\n method: request.method,\n path: request.path,\n headers: request.headers,\n },\n (res) => {\n const chunks: Buffer[] = []\n res.on('data', (c: Buffer) => chunks.push(c))\n res.on('end', () =>\n resolve({\n statusCode: res.statusCode ?? 502,\n headers: Object.fromEntries(\n Object.entries(res.headers).map(([k, v]) => [\n k,\n Array.isArray(v) ? v.join(', ') : v ?? '',\n ]),\n ),\n body: Buffer.concat(chunks),\n }),\n )\n },\n )\n req.on('error', reject)\n if (request.body) req.write(request.body)\n req.end()\n })\n }\n\n private async patchVmState(vmId: string, state: 'Paused' | 'Resumed'): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) throw new Error(`vm ${vmId} not found`)\n await fcRequest(vm.apiSocketPath, 'PATCH', '/vm', { state })\n }\n\n private setRunning(vmId: string, running: boolean): VmHandle {\n const vm = this.vms.get(vmId)\n if (!vm) throw new Error(`vm ${vmId} not found`)\n vm.handle = { ...vm.handle, running }\n return vm.handle\n }\n}\n\n// Send a request to the Firecracker REST API via Unix socket.\nfunction fcRequest(\n socketPath: string,\n method: string,\n urlPath: string,\n body: object,\n): Promise<object> {\n return new Promise((resolve, reject) => {\n const payload = JSON.stringify(body)\n const req = http.request(\n {\n socketPath,\n method,\n path: urlPath,\n headers: {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(payload),\n Accept: 'application/json',\n },\n },\n (res) => {\n const chunks: Buffer[] = []\n res.on('data', (c: Buffer) => chunks.push(c))\n res.on('end', () => {\n const text = Buffer.concat(chunks).toString()\n if (res.statusCode && res.statusCode >= 400) {\n reject(new Error(`Firecracker ${method} ${urlPath} \u2192 ${res.statusCode}: ${text}`))\n } else {\n try {\n resolve(JSON.parse(text))\n } catch {\n resolve({})\n }\n }\n })\n },\n )\n req.on('error', reject)\n req.write(payload)\n req.end()\n })\n}\n\nfunction waitForSocket(socketPath: string, timeoutMs = 10_000): Promise<void> {\n return new Promise((resolve, reject) => {\n const deadline = Date.now() + timeoutMs\n const attempt = () => {\n if (Date.now() > deadline)\n return reject(new Error(`timed out waiting for Firecracker socket ${socketPath}`))\n const sock = net.createConnection(socketPath)\n sock.once('connect', () => {\n sock.destroy()\n resolve()\n })\n sock.once('error', () => setTimeout(attempt, 100))\n }\n attempt()\n })\n}\n\nfunction waitForHttp(host: string, port: number, timeoutMs = 60_000): Promise<void> {\n return new Promise((resolve, reject) => {\n const deadline = Date.now() + timeoutMs\n const attempt = () => {\n if (Date.now() > deadline)\n return reject(new Error(`timed out waiting for HTTP at ${host}:${port}`))\n const req = http.get(`http://${host}:${port}/health`, (res) => {\n if (res.statusCode && res.statusCode < 500) return resolve()\n res.resume()\n setTimeout(attempt, 1_000)\n })\n req.on('error', () => setTimeout(attempt, 1_000))\n req.setTimeout(2_000, () => {\n req.destroy()\n setTimeout(attempt, 1_000)\n })\n }\n attempt()\n })\n}\n", "import { execFile, spawn } from 'child_process'\nimport { promisify } from 'util'\nimport http from 'http'\nimport logger from '@multiplayer-app/logger'\nimport type {\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmExecRequest,\n VmExecResult,\n VmFileWrite,\n VmRecord,\n VmRunMode,\n VmRunResult,\n VmWriteFilesResult,\n} from '@multiplayer-app/builder-types'\nimport type { DockerWorkerConfig } from '../config'\nimport type { Executor, VmHandle, VmSpec } from './types'\n\nconst DEFAULT_EXEC_TIMEOUT_MS = 60_000\nconst MAX_EXEC_TIMEOUT_MS = 300_000\nconst MAX_OUTPUT_BYTES = 1024 * 1024\nconst MAX_FILE_BYTES = 5 * 1024 * 1024\nconst WORKSPACE_DIR = '/workspace'\n\nconst execFileAsync = promisify(execFile)\n\ninterface ManagedVm {\n handle: VmHandle\n containerId: string\n containerName: string\n hostPort: number\n runMode: VmRunMode\n startedAt: number\n}\n\n/** Reject \"../\" and absolute paths, same rule MockExecutor applies to its own workspace. */\nfunction assertSafeWorkspacePath(relativePath: string): string {\n const normalized = relativePath.replace(/^([/\\\\])+/, '')\n if (normalized.split(/[/\\\\]/).includes('..')) {\n throw new Error(`Path escapes the VM workspace: ${relativePath}`)\n }\n return normalized\n}\n\n/**\n * Runs VMs as local Docker containers (one container per VM), via the `docker` CLI \u2014\n * same shell-out style QemuExecutor uses for qemu-system-*. No kernel/HVF/KVM needed,\n * so it's the lowest-friction local engine: just Docker Desktop/OrbStack.\n *\n * Unlike the other local engines, the container's process is directly reachable from\n * the host, so exec/writeFiles are real (`docker exec` / `docker cp`) rather than\n * MockExecutor-only stand-ins. pause/resume map to `docker pause`/`unpause` (a real\n * cgroup freeze); stop/restore map to `docker stop`/`start`, so every VmAction does\n * something meaningful \u2014 unlike QEMU (stop/restore alias pause/resume) or Fargate\n * (only stop works).\n */\nexport class DockerExecutor implements Executor {\n private readonly vms = new Map<string, ManagedVm>()\n private readonly usedPorts = new Set<number>()\n private readonly bin: string\n /** Job VMs that exited before onExit() was called to claim the result (create() \u2192 onExit() isn't atomic). */\n private readonly pendingResults = new Map<string, VmRunResult>()\n private readonly exitHandlers = new Map<string, (result: VmRunResult) => void>()\n\n constructor(private readonly config: DockerWorkerConfig) {\n this.bin = config.bin\n }\n\n private allocatePort(): number {\n for (let p = this.config.portRangeStart; p <= this.config.portRangeEnd; p++) {\n if (!this.usedPorts.has(p)) {\n this.usedPorts.add(p)\n return p\n }\n }\n throw new Error('no free ports in docker port range')\n }\n\n private async resolveImage(stack: string): Promise<string> {\n const explicit = this.config.stackImages[stack]\n if (explicit) return explicit\n\n const { imagePrefix, imageTag } = this.config\n const stackImage = `${imagePrefix}-${stack}:${imageTag}`\n if (await this.imageExists(stackImage)) return stackImage\n\n const genericImage = `${imagePrefix}-generic:${imageTag}`\n if (await this.imageExists(genericImage)) return genericImage\n\n throw new Error(\n `no local docker image for stack \"${stack}\" (${stackImage}) \u2014 run scripts/setup-docker-images.sh`,\n )\n }\n\n private async imageExists(image: string): Promise<boolean> {\n try {\n await execFileAsync(this.bin, ['image', 'inspect', image])\n return true\n } catch {\n return false\n }\n }\n\n async create(spec: VmSpec): Promise<VmHandle> {\n const image = await this.resolveImage(spec.stack)\n const hostPort = this.allocatePort()\n const containerName = `multiplayer-vm-${spec.vmId}`\n\n const args = [\n 'run',\n '-d',\n '--name',\n containerName,\n '-p',\n `127.0.0.1:${hostPort}:${this.config.guestPort}`,\n '--memory',\n `${spec.resources.memMib}m`,\n '--cpus',\n String(spec.resources.vcpuCount),\n '-e',\n `VM_ID=${spec.vmId}`,\n '-e',\n `STACK=${spec.stack}`,\n ...(spec.sessionId ? ['-e', `SESSION_ID=${spec.sessionId}`] : []),\n ...(spec.appUrl ? ['-e', `APP_URL=${spec.appUrl}`] : []),\n ...Object.entries(spec.env ?? {}).flatMap(([key, value]) => ['-e', `${key}=${value}`]),\n ...(this.config.network ? ['--network', this.config.network] : []),\n image,\n ]\n\n logger.info({ vmId: spec.vmId, bin: this.bin, args }, 'starting docker container')\n let containerId: string\n try {\n const { stdout } = await execFileAsync(this.bin, args)\n containerId = stdout.trim()\n } catch (error) {\n this.usedPorts.delete(hostPort)\n throw error\n }\n\n const handle: VmHandle = {\n vmId: spec.vmId,\n sessionId: spec.sessionId,\n stack: spec.stack,\n resources: spec.resources,\n running: true,\n metadata: { containerId, containerName, hostPort },\n }\n const runMode = spec.runMode ?? 'service'\n this.vms.set(spec.vmId, {\n handle,\n containerId,\n containerName,\n hostPort,\n runMode,\n startedAt: Date.now(),\n })\n this.watchExit(spec.vmId, containerId)\n\n // A job's entrypoint may run to completion before the agent ever comes up (e.g. it never\n // listens on a port) \u2014 waitForAgent would hang forever, so job VMs skip that readiness gate.\n if (runMode !== 'job') await this.waitForAgent(hostPort)\n logger.info({ vmId: spec.vmId, containerId, hostPort, runMode }, 'docker vm ready')\n return handle\n }\n\n /**\n * For 'service' VMs: frees the allocated port once the container exits on its own (crash,\n * OOM kill, `docker stop` from outside us) \u2014 same as before.\n * For 'job' VMs: captures the exit code + logs, tears the container down, and reports the\n * result to whoever calls onExit() (immediately if they already have, otherwise once they do).\n */\n private watchExit(vmId: string, containerId: string): void {\n execFileAsync(this.bin, ['wait', containerId])\n .catch(() => ({ stdout: '' }))\n .then(async ({ stdout }) => {\n const vm = this.vms.get(vmId)\n if (!vm || vm.containerId !== containerId) return\n\n if (vm.runMode !== 'job') {\n vm.handle = { ...vm.handle, running: false }\n return\n }\n\n const exitCode = Number.parseInt(stdout.trim(), 10) || 0\n const logs = await this.captureLogs(containerId)\n await execFileAsync(this.bin, ['rm', '-f', containerId]).catch((error: Error) =>\n logger.warn({ vmId, err: error }, 'docker rm after job exit failed'),\n )\n this.usedPorts.delete(vm.hostPort)\n // Resources are already freed above, but the map entry stays (marked not-running)\n // until onExit() claims the result \u2014 MultiEngineExecutor.route() needs get(vmId) to\n // keep finding it in the window between exit and onExit() being called (e.g. right\n // after a reattach discovers the job already finished).\n vm.handle = { ...vm.handle, running: false }\n\n const result: VmRunResult = {\n exitCode,\n ...logs,\n durationMs: Date.now() - vm.startedAt,\n finishedAt: new Date().toISOString(),\n }\n logger.info({ vmId, exitCode }, 'docker job vm exited')\n this.deliverJobResult(vmId, result)\n })\n }\n\n private deliverJobResult(vmId: string, result: VmRunResult): void {\n const handler = this.exitHandlers.get(vmId)\n if (handler) {\n this.exitHandlers.delete(vmId)\n this.vms.delete(vmId)\n handler(result)\n } else {\n this.pendingResults.set(vmId, result)\n }\n }\n\n /** `docker logs` mirrors the container's stdout/stderr onto its own, so the CLI's streams stay separate. */\n private async captureLogs(\n containerId: string,\n ): Promise<{ stdout: string; stderr: string; truncated: boolean }> {\n try {\n const { stdout, stderr } = await execFileAsync(this.bin, ['logs', containerId], {\n maxBuffer: MAX_OUTPUT_BYTES,\n })\n return {\n stdout: stdout.slice(0, MAX_OUTPUT_BYTES),\n stderr: stderr.slice(0, MAX_OUTPUT_BYTES),\n truncated: stdout.length > MAX_OUTPUT_BYTES || stderr.length > MAX_OUTPUT_BYTES,\n }\n } catch (error) {\n const failed = error as NodeJS.ErrnoException & { stdout?: string; stderr?: string }\n return {\n stdout: (failed.stdout ?? '').slice(0, MAX_OUTPUT_BYTES),\n stderr: (failed.stderr ?? '').slice(0, MAX_OUTPUT_BYTES),\n truncated: true,\n }\n }\n }\n\n onExit(vmId: string, handler: (result: VmRunResult) => void): void {\n const pending = this.pendingResults.get(vmId)\n if (pending) {\n this.pendingResults.delete(vmId)\n this.vms.delete(vmId)\n handler(pending)\n return\n }\n this.exitHandlers.set(vmId, handler)\n }\n\n async pause(vmId: string): Promise<VmHandle> {\n const vm = this.mustGet(vmId)\n await execFileAsync(this.bin, ['pause', vm.containerId])\n return this.setRunning(vmId, false)\n }\n\n async resume(vmId: string): Promise<VmHandle> {\n const vm = this.mustGet(vmId)\n await execFileAsync(this.bin, ['unpause', vm.containerId])\n return this.setRunning(vmId, true)\n }\n\n async stop(vmId: string): Promise<VmHandle> {\n const vm = this.mustGet(vmId)\n await execFileAsync(this.bin, ['stop', vm.containerId])\n return this.setRunning(vmId, false)\n }\n\n async restore(vmId: string): Promise<VmHandle> {\n const vm = this.mustGet(vmId)\n await execFileAsync(this.bin, ['start', vm.containerId])\n return this.setRunning(vmId, true)\n }\n\n async destroy(vmId: string): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) return\n\n await execFileAsync(this.bin, ['rm', '-f', vm.containerId]).catch((error: Error) =>\n logger.warn({ vmId, err: error }, 'docker rm on destroy failed'),\n )\n this.usedPorts.delete(vm.hostPort)\n this.vms.delete(vmId)\n logger.info({ vmId }, 'docker vm destroyed')\n }\n\n get(vmId: string): VmHandle | undefined {\n return this.vms.get(vmId)?.handle\n }\n\n list(): VmHandle[] {\n return [...this.vms.values()].map((v) => v.handle)\n }\n\n /**\n * Recover a container after a worker restart: it's an independent process the\n * Docker daemon owns, so just re-inspect it by ID and rebuild the local handle.\n */\n async reattach(record: VmRecord): Promise<VmHandle | undefined> {\n const meta = record.runtimeMetadata as\n | { containerId?: string; containerName?: string; hostPort?: number }\n | undefined\n if (!meta?.containerId || meta.hostPort === undefined) return undefined\n\n let running: boolean\n try {\n const { stdout } = await execFileAsync(this.bin, [\n 'inspect',\n '-f',\n '{{.State.Running}}',\n meta.containerId,\n ])\n running = stdout.trim() === 'true'\n } catch {\n return undefined\n }\n\n const handle: VmHandle = {\n vmId: record.vmId,\n sessionId: record.sessionId,\n stack: record.stack,\n resources: record.resources,\n running,\n metadata: meta,\n }\n this.usedPorts.add(meta.hostPort)\n this.vms.set(record.vmId, {\n handle,\n containerId: meta.containerId,\n containerName: meta.containerName ?? `multiplayer-vm-${record.vmId}`,\n hostPort: meta.hostPort,\n runMode: record.runMode,\n startedAt: Date.parse(record.createdAt) || Date.now(),\n })\n\n if (running) {\n this.watchExit(record.vmId, meta.containerId)\n } else if (record.runMode === 'job') {\n // The job already finished while this worker was offline (or restarting) \u2014 capture\n // whatever's left of it now instead of waiting on watchExit for a container that's\n // already dead, since `docker wait` never resolves for a container in a terminal state.\n void this.finishExitedJob(record.vmId, meta.containerId)\n }\n\n logger.info({ vmId: record.vmId, containerId: meta.containerId }, 'docker vm reattached')\n return handle\n }\n\n /** Same capture-and-report sequence as watchExit's job branch, for a container found already stopped. */\n private async finishExitedJob(vmId: string, containerId: string): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) return\n\n let exitCode = 0\n try {\n const { stdout } = await execFileAsync(this.bin, [\n 'inspect',\n '-f',\n '{{.State.ExitCode}}',\n containerId,\n ])\n exitCode = Number.parseInt(stdout.trim(), 10) || 0\n } catch {\n // container gone entirely \u2014 best effort, report a generic failure below\n }\n\n const logs = await this.captureLogs(containerId)\n await execFileAsync(this.bin, ['rm', '-f', containerId]).catch(() => {})\n this.usedPorts.delete(vm.hostPort)\n vm.handle = { ...vm.handle, running: false }\n\n const result: VmRunResult = {\n exitCode,\n ...logs,\n durationMs: Date.now() - vm.startedAt,\n finishedAt: new Date().toISOString(),\n }\n this.deliverJobResult(vmId, result)\n }\n\n async proxyHttp(vmId: string, request: ProxyRequestDescriptor): Promise<ProxyResponseDescriptor> {\n const vm = this.mustGet(vmId)\n if (!vm.handle.running) throw new Error(`vm ${vmId} is not running`)\n\n return new Promise((resolve, reject) => {\n const req = http.request(\n {\n host: '127.0.0.1',\n port: vm.hostPort,\n method: request.method,\n path: request.path,\n headers: request.headers,\n },\n (res) => {\n const chunks: Buffer[] = []\n res.on('data', (c: Buffer) => chunks.push(c))\n res.on('end', () =>\n resolve({\n statusCode: res.statusCode ?? 502,\n headers: Object.fromEntries(\n Object.entries(res.headers).map(([k, v]) => [\n k,\n Array.isArray(v) ? v.join(', ') : v ?? '',\n ]),\n ),\n body: Buffer.concat(chunks),\n }),\n )\n },\n )\n req.on('error', reject)\n if (request.body) req.write(request.body)\n req.end()\n })\n }\n\n async exec(vmId: string, request: VmExecRequest): Promise<VmExecResult> {\n const vm = this.mustGet(vmId)\n const cwd = request.cwd\n ? `${WORKSPACE_DIR}/${assertSafeWorkspacePath(request.cwd)}`\n : WORKSPACE_DIR\n const timeoutMs = Math.min(request.timeoutMs ?? DEFAULT_EXEC_TIMEOUT_MS, MAX_EXEC_TIMEOUT_MS)\n const startedAt = Date.now()\n\n return new Promise((resolve) => {\n execFile(\n this.bin,\n ['exec', '-w', cwd, vm.containerId, '/bin/sh', '-c', request.command],\n { timeout: timeoutMs, maxBuffer: MAX_OUTPUT_BYTES },\n (error, stdout, stderr) => {\n const failed = error as\n | (NodeJS.ErrnoException & { code?: number | string; killed?: boolean })\n | null\n const timedOut = Boolean(failed?.killed)\n const truncated = failed?.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER'\n resolve({\n exitCode: typeof failed?.code === 'number' ? failed.code : failed ? 1 : 0,\n stdout: stdout.slice(0, MAX_OUTPUT_BYTES),\n stderr: stderr.slice(0, MAX_OUTPUT_BYTES),\n durationMs: Date.now() - startedAt,\n truncated: Boolean(truncated),\n timedOut,\n })\n },\n )\n })\n }\n\n async writeFiles(vmId: string, files: VmFileWrite[]): Promise<VmWriteFilesResult> {\n const vm = this.mustGet(vmId)\n const written: Array<{ path: string; bytes: number }> = []\n\n for (const file of files) {\n const relativePath = assertSafeWorkspacePath(file.path)\n const buffer = Buffer.from(file.content, file.encoding === 'base64' ? 'base64' : 'utf8')\n if (buffer.byteLength > MAX_FILE_BYTES) {\n throw new Error(\n `File too large (${buffer.byteLength} bytes, max ${MAX_FILE_BYTES}): ${file.path}`,\n )\n }\n\n const dir = relativePath.includes('/')\n ? relativePath.slice(0, relativePath.lastIndexOf('/'))\n : ''\n if (dir) {\n await execFileAsync(this.bin, [\n 'exec',\n vm.containerId,\n 'mkdir',\n '-p',\n `${WORKSPACE_DIR}/${dir}`,\n ])\n }\n await this.copyIntoContainer(vm.containerId, `${WORKSPACE_DIR}/${relativePath}`, buffer)\n written.push({ path: relativePath, bytes: buffer.byteLength })\n }\n\n logger.info({ vmId, files: written.length }, 'docker vm files written')\n return { written }\n }\n\n /** `docker cp` needs a tar stream on stdin; build the smallest valid ustar archive for one file. */\n private copyIntoContainer(containerId: string, destPath: string, content: Buffer): Promise<void> {\n const entryName = destPath.replace(/^\\//, '')\n const tarStream = buildSingleFileTar(entryName, content)\n\n return new Promise((resolve, reject) => {\n const proc = spawn(this.bin, ['cp', '-', `${containerId}:/`], {\n stdio: ['pipe', 'ignore', 'pipe'],\n })\n let stderr = ''\n proc.stderr?.on('data', (d: Buffer) => {\n stderr += d.toString()\n })\n proc.on('error', reject)\n proc.on('exit', (code) =>\n code === 0 ? resolve() : reject(new Error(`docker cp exited ${code}: ${stderr}`)),\n )\n proc.stdin.end(tarStream)\n })\n }\n\n private mustGet(vmId: string): ManagedVm {\n const vm = this.vms.get(vmId)\n if (!vm) throw new Error(`vm ${vmId} not found`)\n return vm\n }\n\n private setRunning(vmId: string, running: boolean): VmHandle {\n const vm = this.mustGet(vmId)\n vm.handle = { ...vm.handle, running }\n return vm.handle\n }\n\n private async waitForAgent(port: number, timeoutMs = 30_000): Promise<void> {\n const deadline = Date.now() + timeoutMs\n for (;;) {\n const ok = await new Promise<boolean>((resolve) => {\n const req = http.get({ host: '127.0.0.1', port, path: '/', timeout: 2_000 }, (res) => {\n res.resume()\n resolve(true)\n })\n req.on('error', () => resolve(false))\n req.on('timeout', () => {\n req.destroy()\n resolve(false)\n })\n })\n if (ok) return\n if (Date.now() > deadline)\n throw new Error(`timed out waiting for docker vm agent on port ${port}`)\n await new Promise((resolve) => setTimeout(resolve, 500))\n }\n }\n}\n\n/** POSIX ustar archive containing exactly one regular file \u2014 enough for `docker cp -`. */\nfunction buildSingleFileTar(name: string, content: Buffer): Buffer {\n const header = Buffer.alloc(512)\n header.write(name, 0, 'utf8')\n header.write('0000644\\0', 100, 'utf8') // mode\n header.write('0000000\\0', 108, 'utf8') // uid\n header.write('0000000\\0', 116, 'utf8') // gid\n header.write(content.byteLength.toString(8).padStart(11, '0') + '\\0', 124, 'utf8') // size (octal)\n header.write(\n Math.floor(Date.now() / 1000)\n .toString(8)\n .padStart(11, '0') + '\\0',\n 136,\n 'utf8',\n ) // mtime\n header.write(' ', 148, 'utf8') // checksum placeholder (spaces while computing)\n header.write('0', 156, 'utf8') // typeflag: regular file\n header.write('ustar\\0', 257, 'utf8')\n header.write('00', 263, 'utf8')\n\n let checksum = 0\n for (const byte of header) checksum += byte\n header.write(checksum.toString(8).padStart(6, '0') + '\\0 ', 148, 'utf8')\n\n const paddedContentLength = Math.ceil(content.byteLength / 512) * 512\n const paddedContent = Buffer.alloc(paddedContentLength)\n content.copy(paddedContent)\n\n return Buffer.concat([header, paddedContent, Buffer.alloc(1024)]) // two 512-byte zero blocks terminate the archive\n}\n", "import { execFile, spawn } from 'child_process'\nimport { promisify } from 'util'\nimport fs from 'fs/promises'\nimport os from 'os'\nimport path from 'path'\nimport http from 'http'\nimport logger from '@multiplayer-app/logger'\nimport type {\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmExecRequest,\n VmExecResult,\n VmFileWrite,\n VmRecord,\n VmRunMode,\n VmRunResult,\n VmWriteFilesResult,\n} from '@multiplayer-app/builder-types'\nimport type { DockerSandboxWorkerConfig } from '../config'\nimport type { Executor, VmHandle, VmSpec } from './types'\n\nconst DEFAULT_EXEC_TIMEOUT_MS = 60_000\nconst MAX_EXEC_TIMEOUT_MS = 300_000\nconst MAX_OUTPUT_BYTES = 1024 * 1024\nconst MAX_FILE_BYTES = 5 * 1024 * 1024\nconst WORKSPACE_DIR = '/workspace'\nconst AGENT_DIR = '/app'\n\nconst execFileAsync = promisify(execFile)\n\ninterface ManagedVm {\n handle: VmHandle\n sandboxName: string\n vmDir: string\n hostPort: number\n agentCommand: string\n runMode: VmRunMode\n startedAt: number\n}\n\n/** Reject \"../\" and absolute paths, same rule MockExecutor/DockerExecutor apply to their workspace. */\nfunction assertSafeWorkspacePath(relativePath: string): string {\n const normalized = relativePath.replace(/^([/\\\\])+/, '')\n if (normalized.split(/[/\\\\]/).includes('..')) {\n throw new Error(`Path escapes the VM workspace: ${relativePath}`)\n }\n return normalized\n}\n\n/** sbx sandbox names: letters/digits/hyphens/periods only, starting with a letter or digit. */\nfunction sandboxNameFor(vmId: string): string {\n return `mp-${vmId.replace(/[^a-zA-Z0-9.-]/g, '-')}`\n}\n\n/**\n * Runs VMs as Docker Sandboxes (`sbx`, docker.com/products/docker-sandboxes) \u2014 Docker's own\n * microVM-per-sandbox product, originally built for safely running AI coding agents. Reuses\n * the exact same per-stack images `docker` (DockerExecutor) already builds via\n * scripts/setup-docker-images.sh, bridged into sbx's own image store with `docker save` +\n * `sbx template load`.\n *\n * Two things `sbx` does differently from plain `docker run`, driven by its \"isolated agent\n * sandbox\" design rather than \"run this image\" design:\n * - `sbx create` doesn't execute the image's own Dockerfile CMD (confirmed via `ps aux`:\n * PID 1 is a `sleep infinity` placeholder) \u2014 the guest agent is launched explicitly via\n * `sbx exec -d` right after creation.\n * - `sbx create`/`run` require a real host directory to mount as the sandbox's workspace;\n * unrelated to the image's own internal /workspace (used by the guest agent for release\n * deploys) \u2014 just a disposable per-VM directory to satisfy the CLI.\n *\n * No `docker pause`-equivalent primitive exists here, so pause/resume alias stop/restore,\n * same precedent QemuExecutor already sets for engines without a distinct freeze primitive.\n */\nexport class DockerSandboxExecutor implements Executor {\n private readonly vms = new Map<string, ManagedVm>()\n private readonly usedPorts = new Set<number>()\n private readonly loadedTemplates = new Set<string>()\n private readonly bin: string\n private readonly pendingResults = new Map<string, VmRunResult>()\n private readonly exitHandlers = new Map<string, (result: VmRunResult) => void>()\n\n constructor(private readonly config: DockerSandboxWorkerConfig) {\n this.bin = config.bin\n }\n\n private allocatePort(): number {\n for (let p = this.config.portRangeStart; p <= this.config.portRangeEnd; p++) {\n if (!this.usedPorts.has(p)) {\n this.usedPorts.add(p)\n return p\n }\n }\n throw new Error('no free ports in docker-sandbox port range')\n }\n\n private resolveAgentCommand(stack: string): string {\n return (\n this.config.stackAgentCommands[stack] ??\n this.config.stackAgentCommands.generic ??\n 'node app.js'\n )\n }\n\n /** Local `docker` image tag for a stack, same resolution order as DockerExecutor.resolveImage. */\n private localImageFor(stack: string): string {\n const { imagePrefix, imageTag } = this.config\n return `${imagePrefix}-${stack}:${imageTag}`\n }\n\n /** Bridges the local docker image into sbx's own image store once per process; returns its ref. */\n private async ensureTemplateLoaded(stack: string): Promise<string> {\n const explicit = this.config.stackTemplates[stack]\n if (explicit) return explicit\n\n const localImage = this.localImageFor(stack)\n const templateRef = `docker.io/library/${localImage}`\n if (this.loadedTemplates.has(templateRef)) return templateRef\n\n const tmpFile = path.join(os.tmpdir(), `sbx-template-${stack}-${Date.now()}.tar`)\n try {\n await execFileAsync('docker', ['save', localImage, '-o', tmpFile])\n await execFileAsync(this.bin, ['template', 'load', tmpFile])\n } catch (error) {\n throw new Error(\n `failed to bridge local image \"${localImage}\" into sbx \u2014 run scripts/setup-docker-images.sh: ${error}`,\n )\n } finally {\n await fs.rm(tmpFile, { force: true })\n }\n\n this.loadedTemplates.add(templateRef)\n return templateRef\n }\n\n async create(spec: VmSpec): Promise<VmHandle> {\n const templateRef = await this.ensureTemplateLoaded(spec.stack)\n const agentCommand = this.resolveAgentCommand(spec.stack)\n const sandboxName = sandboxNameFor(spec.vmId)\n const hostPort = this.allocatePort()\n const vmDir = path.join(this.config.workspaceRoot, spec.vmId)\n await fs.mkdir(vmDir, { recursive: true })\n const memMib = Math.max(spec.resources.memMib, this.config.minMemoryMib)\n\n const createArgs = [\n 'create',\n 'shell',\n vmDir,\n '--template',\n templateRef,\n '--name',\n sandboxName,\n '-p',\n `127.0.0.1:${hostPort}:${this.config.guestPort}`,\n '-m',\n `${memMib}m`,\n '--cpus',\n String(spec.resources.vcpuCount),\n '-e',\n `VM_ID=${spec.vmId}`,\n '-e',\n `STACK=${spec.stack}`,\n ...(spec.sessionId ? ['-e', `SESSION_ID=${spec.sessionId}`] : []),\n ...(spec.appUrl ? ['-e', `APP_URL=${spec.appUrl}`] : []),\n ...Object.entries(spec.env ?? {}).flatMap(([key, value]) => ['-e', `${key}=${value}`]),\n ]\n\n const runMode = spec.runMode ?? 'service'\n\n logger.info({ vmId: spec.vmId, bin: this.bin, args: createArgs }, 'creating docker sandbox')\n try {\n await execFileAsync(this.bin, createArgs)\n if (runMode !== 'job') this.launchAgent(sandboxName, agentCommand)\n } catch (error) {\n this.usedPorts.delete(hostPort)\n await fs.rm(vmDir, { recursive: true, force: true }).catch(() => {})\n throw error\n }\n\n const handle: VmHandle = {\n vmId: spec.vmId,\n sessionId: spec.sessionId,\n stack: spec.stack,\n resources: { ...spec.resources, memMib },\n running: true,\n metadata: { sandboxName, hostPort, vmDir, agentCommand },\n }\n this.vms.set(spec.vmId, {\n handle,\n sandboxName,\n vmDir,\n hostPort,\n agentCommand,\n runMode,\n startedAt: Date.now(),\n })\n\n if (runMode === 'job') {\n this.runJob(spec.vmId, sandboxName, agentCommand)\n } else {\n await this.waitForAgent(hostPort)\n }\n logger.info({ vmId: spec.vmId, sandboxName, hostPort, runMode }, 'docker sandbox ready')\n return handle\n }\n\n /**\n * Job mode: unlike `launchAgent` (fire-and-forget `sbx exec -d`, used for persistent\n * services), run the entrypoint in the *foreground* \u2014 the CLI call itself blocks until the\n * command exits and hands back its exit code + captured stdout/stderr directly, so there's\n * no separate wait/logs step needed the way DockerExecutor needs for a backgrounded container.\n */\n private runJob(vmId: string, sandboxName: string, agentCommand: string): void {\n const startedAt = this.vms.get(vmId)?.startedAt ?? Date.now()\n execFile(\n this.bin,\n ['exec', '-w', AGENT_DIR, sandboxName, '/bin/sh', '-c', agentCommand],\n { maxBuffer: MAX_OUTPUT_BYTES },\n (error, stdout, stderr) => {\n const failed = error as (NodeJS.ErrnoException & { code?: number | string }) | null\n const truncated = failed?.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER'\n const result: VmRunResult = {\n exitCode: typeof failed?.code === 'number' ? failed.code : failed ? 1 : 0,\n stdout: stdout.slice(0, MAX_OUTPUT_BYTES),\n stderr: stderr.slice(0, MAX_OUTPUT_BYTES),\n truncated: Boolean(truncated),\n durationMs: Date.now() - startedAt,\n finishedAt: new Date().toISOString(),\n }\n void this.finishJob(vmId, sandboxName, result)\n },\n )\n }\n\n private async finishJob(vmId: string, sandboxName: string, result: VmRunResult): Promise<void> {\n logger.info({ vmId, exitCode: result.exitCode }, 'docker sandbox job exited')\n await execFileAsync(this.bin, ['rm', '-f', sandboxName]).catch((error: Error) =>\n logger.warn({ vmId, err: error }, 'sbx rm after job exit failed'),\n )\n const vm = this.vms.get(vmId)\n if (vm) {\n await fs.rm(vm.vmDir, { recursive: true, force: true }).catch(() => {})\n this.usedPorts.delete(vm.hostPort)\n // Resources are already freed above, but the map entry stays (marked not-running)\n // until onExit() claims the result \u2014 see docker-executor's deliverJobResult for why.\n vm.handle = { ...vm.handle, running: false }\n }\n\n this.deliverJobResult(vmId, result)\n }\n\n private deliverJobResult(vmId: string, result: VmRunResult): void {\n const handler = this.exitHandlers.get(vmId)\n if (handler) {\n this.exitHandlers.delete(vmId)\n this.vms.delete(vmId)\n handler(result)\n } else {\n this.pendingResults.set(vmId, result)\n }\n }\n\n onExit(vmId: string, handler: (result: VmRunResult) => void): void {\n const pending = this.pendingResults.get(vmId)\n if (pending) {\n this.pendingResults.delete(vmId)\n this.vms.delete(vmId)\n handler(pending)\n return\n }\n this.exitHandlers.set(vmId, handler)\n }\n\n /**\n * `sbx create shell` doesn't run the image's own CMD \u2014 launch the guest agent explicitly.\n *\n * Fire-and-forget: `sbx exec -d` (detach) launches the background command correctly but its\n * own CLI process then hangs indefinitely instead of returning \u2014 confirmed live (the agent\n * was already answering on its port while the CLI call itself sat stuck for 14+ minutes,\n * needing a kill -9). `waitForAgent`'s port poll is the real readiness signal here, not this\n * process exiting, so it's spawned detached and never awaited.\n */\n private launchAgent(sandboxName: string, agentCommand: string): void {\n const proc = spawn(\n this.bin,\n ['exec', '-d', '-w', AGENT_DIR, sandboxName, '/bin/sh', '-c', agentCommand],\n {\n stdio: 'ignore',\n },\n )\n proc.on('error', (error) =>\n logger.warn({ sandboxName, err: error }, 'sbx exec -d failed to spawn'),\n )\n proc.unref()\n }\n\n async pause(vmId: string): Promise<VmHandle> {\n return this.stop(vmId)\n }\n\n async resume(vmId: string): Promise<VmHandle> {\n return this.restore(vmId)\n }\n\n async stop(vmId: string): Promise<VmHandle> {\n const vm = this.mustGet(vmId)\n await execFileAsync(this.bin, ['stop', vm.sandboxName])\n return this.setRunning(vmId, false)\n }\n\n async restore(vmId: string): Promise<VmHandle> {\n const vm = this.mustGet(vmId)\n await execFileAsync(this.bin, ['run', '--name', vm.sandboxName, '--detached'])\n const alreadyUp = await this.probeAgent(vm.hostPort)\n if (!alreadyUp) this.launchAgent(vm.sandboxName, vm.agentCommand)\n await this.waitForAgent(vm.hostPort)\n return this.setRunning(vmId, true)\n }\n\n async destroy(vmId: string): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) return\n\n await execFileAsync(this.bin, ['rm', '-f', vm.sandboxName]).catch((error: Error) =>\n logger.warn({ vmId, err: error }, 'sbx rm on destroy failed'),\n )\n await fs.rm(vm.vmDir, { recursive: true, force: true }).catch(() => {})\n this.usedPorts.delete(vm.hostPort)\n this.vms.delete(vmId)\n logger.info({ vmId }, 'docker sandbox destroyed')\n }\n\n get(vmId: string): VmHandle | undefined {\n return this.vms.get(vmId)?.handle\n }\n\n list(): VmHandle[] {\n return [...this.vms.values()].map((v) => v.handle)\n }\n\n /**\n * Recover a sandbox after a worker restart: it's owned by the independent `sandboxd`\n * daemon, so a liveness probe against its name is enough to confirm it's still there.\n */\n async reattach(record: VmRecord): Promise<VmHandle | undefined> {\n const meta = record.runtimeMetadata as\n | { sandboxName?: string; hostPort?: number; vmDir?: string; agentCommand?: string }\n | undefined\n if (!meta?.sandboxName || meta.hostPort === undefined || !meta.vmDir || !meta.agentCommand)\n return undefined\n\n let running: boolean\n try {\n await execFileAsync(this.bin, ['exec', meta.sandboxName, 'true'])\n running = true\n } catch {\n try {\n await execFileAsync(this.bin, ['ls', '--json'])\n running = false // ran but the sandbox isn't reachable \u2014 treat as stopped, not gone\n } catch {\n return undefined\n }\n }\n\n const handle: VmHandle = {\n vmId: record.vmId,\n sessionId: record.sessionId,\n stack: record.stack,\n resources: record.resources,\n running,\n metadata: meta,\n }\n this.usedPorts.add(meta.hostPort)\n this.vms.set(record.vmId, {\n handle,\n sandboxName: meta.sandboxName,\n vmDir: meta.vmDir,\n hostPort: meta.hostPort,\n agentCommand: meta.agentCommand,\n runMode: record.runMode,\n startedAt: Date.parse(record.createdAt) || Date.now(),\n })\n\n if (record.runMode === 'job') {\n // The job's entrypoint ran as this worker's own foreground child process (see runJob) \u2014\n // it died with the worker, so there's nothing left to resume watching. Report it as\n // failed rather than leaving the record stuck in 'running' forever.\n void this.finishJob(record.vmId, meta.sandboxName, {\n exitCode: -1,\n stdout: '',\n stderr: 'worker restarted while this job was still running',\n truncated: false,\n durationMs: Date.now() - (Date.parse(record.createdAt) || Date.now()),\n finishedAt: new Date().toISOString(),\n })\n }\n\n logger.info({ vmId: record.vmId, sandboxName: meta.sandboxName }, 'docker sandbox reattached')\n return handle\n }\n\n async proxyHttp(vmId: string, request: ProxyRequestDescriptor): Promise<ProxyResponseDescriptor> {\n const vm = this.mustGet(vmId)\n if (!vm.handle.running) throw new Error(`vm ${vmId} is not running`)\n\n return new Promise((resolve, reject) => {\n const req = http.request(\n {\n host: '127.0.0.1',\n port: vm.hostPort,\n method: request.method,\n path: request.path,\n headers: request.headers,\n },\n (res) => {\n const chunks: Buffer[] = []\n res.on('data', (c: Buffer) => chunks.push(c))\n res.on('end', () =>\n resolve({\n statusCode: res.statusCode ?? 502,\n headers: Object.fromEntries(\n Object.entries(res.headers).map(([k, v]) => [\n k,\n Array.isArray(v) ? v.join(', ') : v ?? '',\n ]),\n ),\n body: Buffer.concat(chunks),\n }),\n )\n },\n )\n req.on('error', reject)\n if (request.body) req.write(request.body)\n req.end()\n })\n }\n\n async exec(vmId: string, request: VmExecRequest): Promise<VmExecResult> {\n const vm = this.mustGet(vmId)\n const cwd = request.cwd\n ? `${WORKSPACE_DIR}/${assertSafeWorkspacePath(request.cwd)}`\n : WORKSPACE_DIR\n const timeoutMs = Math.min(request.timeoutMs ?? DEFAULT_EXEC_TIMEOUT_MS, MAX_EXEC_TIMEOUT_MS)\n const startedAt = Date.now()\n\n return new Promise((resolve) => {\n execFile(\n this.bin,\n ['exec', '-w', cwd, vm.sandboxName, '/bin/sh', '-c', request.command],\n { timeout: timeoutMs, maxBuffer: MAX_OUTPUT_BYTES },\n (error, stdout, stderr) => {\n const failed = error as\n | (NodeJS.ErrnoException & { code?: number | string; killed?: boolean })\n | null\n const timedOut = Boolean(failed?.killed)\n const truncated = failed?.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER'\n resolve({\n exitCode: typeof failed?.code === 'number' ? failed.code : failed ? 1 : 0,\n stdout: stdout.slice(0, MAX_OUTPUT_BYTES),\n stderr: stderr.slice(0, MAX_OUTPUT_BYTES),\n durationMs: Date.now() - startedAt,\n truncated: Boolean(truncated),\n timedOut,\n })\n },\n )\n })\n }\n\n async writeFiles(vmId: string, files: VmFileWrite[]): Promise<VmWriteFilesResult> {\n const vm = this.mustGet(vmId)\n const written: Array<{ path: string; bytes: number }> = []\n\n for (const file of files) {\n const relativePath = assertSafeWorkspacePath(file.path)\n const buffer = Buffer.from(file.content, file.encoding === 'base64' ? 'base64' : 'utf8')\n if (buffer.byteLength > MAX_FILE_BYTES) {\n throw new Error(\n `File too large (${buffer.byteLength} bytes, max ${MAX_FILE_BYTES}): ${file.path}`,\n )\n }\n\n const dir = relativePath.includes('/')\n ? relativePath.slice(0, relativePath.lastIndexOf('/'))\n : ''\n if (dir) {\n await execFileAsync(this.bin, [\n 'exec',\n vm.sandboxName,\n 'mkdir',\n '-p',\n `${WORKSPACE_DIR}/${dir}`,\n ])\n }\n\n // sbx cp takes a real host path on one side \u2014 simpler than DockerExecutor's tar-over-stdin hack.\n const tmpFile = path.join(\n os.tmpdir(),\n `sbx-write-${vmId}-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n )\n await fs.writeFile(tmpFile, buffer)\n try {\n await execFileAsync(this.bin, [\n 'cp',\n tmpFile,\n `${vm.sandboxName}:${WORKSPACE_DIR}/${relativePath}`,\n ])\n } finally {\n await fs.rm(tmpFile, { force: true })\n }\n written.push({ path: relativePath, bytes: buffer.byteLength })\n }\n\n logger.info({ vmId, files: written.length }, 'docker sandbox files written')\n return { written }\n }\n\n private mustGet(vmId: string): ManagedVm {\n const vm = this.vms.get(vmId)\n if (!vm) throw new Error(`vm ${vmId} not found`)\n return vm\n }\n\n private setRunning(vmId: string, running: boolean): VmHandle {\n const vm = this.mustGet(vmId)\n vm.handle = { ...vm.handle, running }\n return vm.handle\n }\n\n private async probeAgent(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const req = http.get({ host: '127.0.0.1', port, path: '/', timeout: 2_000 }, (res) => {\n res.resume()\n resolve(true)\n })\n req.on('error', () => resolve(false))\n req.on('timeout', () => {\n req.destroy()\n resolve(false)\n })\n })\n }\n\n private async waitForAgent(port: number, timeoutMs = 30_000): Promise<void> {\n const deadline = Date.now() + timeoutMs\n for (;;) {\n if (await this.probeAgent(port)) return\n if (Date.now() > deadline)\n throw new Error(`timed out waiting for docker sandbox agent on port ${port}`)\n await new Promise((resolve) => setTimeout(resolve, 500))\n }\n }\n}\n", "import http from 'http'\nimport https from 'https'\nimport logger from '@multiplayer-app/logger'\nimport type {\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmRecord,\n VmRunResult,\n} from '@multiplayer-app/builder-types'\nimport type { Executor, VmHandle, VmSpec } from './types'\nimport { withTimeout } from './reattach-utils'\n\nconst JOB_POLL_INTERVAL_MS = 3_000\n\nexport interface RemoteExecutorConfig {\n agentUrl: string // e.g. http://192.168.1.10:4040\n authToken?: string\n}\n\nexport class RemoteExecutor implements Executor {\n private readonly base: string\n private readonly headers: Record<string, string>\n // The remote agent is the actual source of truth, but MultiEngineExecutor.route() (used by\n // pause/resume/stop/restore/destroy/proxyHttp/exec/writeFiles) needs get() to find the\n // right executor for a vmId \u2014 cache the handle each call returns so it does.\n private readonly vms = new Map<string, VmHandle>()\n private readonly jobStartedAt = new Map<string, number>()\n\n constructor(config: RemoteExecutorConfig) {\n this.base = config.agentUrl.replace(/\\/$/, '')\n this.headers = {\n 'Content-Type': 'application/json',\n ...(config.authToken ? { Authorization: `Bearer ${config.authToken}` } : {}),\n }\n }\n\n async create(spec: VmSpec): Promise<VmHandle> {\n const handle = await this.request<VmHandle>('POST', '/vms', spec)\n this.vms.set(spec.vmId, handle)\n if (spec.runMode === 'job') this.jobStartedAt.set(spec.vmId, Date.now())\n return handle\n }\n\n /**\n * The remote agent's own wire protocol (VmHandle) has no exit-code/output field \u2014 extending\n * it is out of this repo's control, so this only detects completion (poll GET /vms/:vmId\n * until running flips false) without a real exit code or captured output. Good enough to\n * unblock the record from being stuck in 'running' forever; a real RemoteExecutor deployment\n * wanting full job support needs its agent protocol extended first.\n */\n onExit(vmId: string, handler: (result: VmRunResult) => void): void {\n const startedAt = this.jobStartedAt.get(vmId) ?? Date.now()\n const poll = async () => {\n const handle = await this.request<VmHandle>('GET', `/vms/${vmId}`).catch(() => undefined)\n if (handle) this.vms.set(vmId, handle)\n\n if (!handle || !handle.running) {\n this.jobStartedAt.delete(vmId)\n this.vms.delete(vmId)\n handler({\n exitCode: 0,\n stdout: '',\n stderr:\n 'remote engine does not report job exit codes/output \u2014 completion detected via polling only',\n truncated: false,\n durationMs: Date.now() - startedAt,\n finishedAt: new Date().toISOString(),\n })\n return\n }\n setTimeout(() => void poll(), JOB_POLL_INTERVAL_MS)\n }\n void poll()\n }\n\n async pause(vmId: string): Promise<VmHandle> {\n return this.updateCached(vmId, await this.request('POST', `/vms/${vmId}/pause`))\n }\n\n async resume(vmId: string): Promise<VmHandle> {\n return this.updateCached(vmId, await this.request('POST', `/vms/${vmId}/resume`))\n }\n\n async stop(vmId: string): Promise<VmHandle> {\n return this.updateCached(vmId, await this.request('POST', `/vms/${vmId}/stop`))\n }\n\n async restore(vmId: string): Promise<VmHandle> {\n return this.updateCached(vmId, await this.request('POST', `/vms/${vmId}/restore`))\n }\n\n async destroy(vmId: string): Promise<void> {\n await this.request('DELETE', `/vms/${vmId}`)\n this.vms.delete(vmId)\n }\n\n get(vmId: string): VmHandle | undefined {\n return this.vms.get(vmId)\n }\n\n list(): VmHandle[] {\n return [...this.vms.values()]\n }\n\n /**\n * Recover a remote-agent VM after a worker restart. The agent owns the actual VM state\n * independently of this process, so reattaching is just confirming it still knows about\n * this vmId and re-populating the local get()/list() cache above.\n */\n async reattach(record: VmRecord): Promise<VmHandle | undefined> {\n try {\n const handle = await withTimeout(this.request<VmHandle>('GET', `/vms/${record.vmId}`), 5_000)\n this.vms.set(record.vmId, handle)\n return handle\n } catch {\n return undefined\n }\n }\n\n private updateCached(vmId: string, handle: VmHandle): VmHandle {\n this.vms.set(vmId, handle)\n return handle\n }\n\n async proxyHttp(vmId: string, request: ProxyRequestDescriptor): Promise<ProxyResponseDescriptor> {\n const result = await this.request<{\n statusCode: number\n headers: Record<string, string>\n body?: string\n }>('POST', `/vms/${vmId}/proxy`, {\n method: request.method,\n path: request.path,\n headers: request.headers,\n body: request.body?.toString('base64'),\n })\n\n return {\n statusCode: result.statusCode,\n headers: result.headers,\n body: result.body ? Buffer.from(result.body, 'base64') : Buffer.alloc(0),\n }\n }\n\n private request<T = unknown>(method: string, path: string, body?: unknown): Promise<T> {\n const url = new URL(this.base + path)\n const lib = url.protocol === 'https:' ? https : http\n const payload = body !== undefined ? JSON.stringify(body) : undefined\n\n return new Promise((resolve, reject) => {\n const req = lib.request(\n {\n hostname: url.hostname,\n port: url.port || (url.protocol === 'https:' ? 443 : 80),\n path: url.pathname,\n method,\n headers: {\n ...this.headers,\n ...(payload ? { 'Content-Length': Buffer.byteLength(payload) } : {}),\n },\n },\n (res) => {\n const chunks: Buffer[] = []\n res.on('data', (c: Buffer) => chunks.push(c))\n res.on('end', () => {\n const text = Buffer.concat(chunks).toString()\n if (res.statusCode && res.statusCode >= 400) {\n reject(new Error(`vm-agent ${method} ${path} \u2192 ${res.statusCode}: ${text}`))\n return\n }\n if (res.statusCode === 204 || !text) {\n resolve(undefined as T)\n return\n }\n try {\n resolve(JSON.parse(text) as T)\n } catch {\n resolve(text as unknown as T)\n }\n })\n },\n )\n req.on('error', reject)\n if (payload) req.write(payload)\n req.end()\n })\n }\n}\n", "import https from 'https'\nimport {\n LambdaMicrovmsClient,\n RunMicrovmCommand,\n SuspendMicrovmCommand,\n ResumeMicrovmCommand,\n TerminateMicrovmCommand,\n GetMicrovmCommand,\n CreateMicrovmAuthTokenCommand,\n CreateMicrovmShellAuthTokenCommand,\n} from '@aws-sdk/client-lambda-microvms'\nimport logger from '@multiplayer-app/logger'\nimport type {\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmRecord,\n VmStack,\n} from '@multiplayer-app/builder-types'\nimport type { Executor, SerialSource, VmHandle, VmSpec } from './types'\n\nexport interface LambdaMicrovmConfig {\n region?: string\n /** Default MicroVM image ARN, used for any stack without a specific image. */\n imageArn: string\n /** Per-stack image ARN overrides, e.g. { node: 'arn:...', python: 'arn:...' }. */\n stackImageArns?: Partial<Record<VmStack, string>>\n ingressConnectorArns?: string[]\n egressConnectorArns?: string[]\n executionRoleArn?: string\n /** Suspend automatically after this many seconds without endpoint traffic (0 disables the idle policy). */\n maxIdleSeconds?: number\n /** Terminate automatically after this many seconds in the suspended state. */\n suspendedDurationSeconds?: number\n /** Hard lifetime cap for a MicroVM (running + suspended), max 28800. */\n maximumDurationInSeconds?: number\n /** How long to wait for the RUNNING state after run-microvm. */\n createTimeoutMs?: number\n}\n\ninterface ManagedMicrovm {\n handle: VmHandle\n microvmId: string\n endpoint: string\n authToken?: { headers: Record<string, string>; expiresAt: number }\n}\n\nconst AUTH_TOKEN_TTL_MINUTES = 60\nconst AUTH_TOKEN_REFRESH_MARGIN_MS = 2 * 60_000\nconst SHELL_PORT = 8022\n\nfunction managedConnectorArn(imageIdentifier: string, name: string): string {\n const [arn, partition, service, region] = imageIdentifier.split(':')\n if (arn !== 'arn' || !partition || service !== 'lambda' || !region) {\n throw new Error(`cannot derive Lambda MicroVM connector ARN from image \"${imageIdentifier}\"`)\n }\n return `arn:${partition}:lambda:${region}:aws:network-connector:aws-network-connector:${name}`\n}\n\nfunction runtimeEnv(spec: VmSpec): Record<string, string> | undefined {\n const env = {\n ...spec.env,\n // A release URL is unique and short-lived, so it belongs in per-VM run data rather than\n // the image-level environment shared by every MicroVM launched from that image.\n ...(spec.appUrl ? { APP_URL: spec.appUrl } : {}),\n }\n return Object.keys(env).length ? env : undefined\n}\n\n/**\n * Runs VMs as AWS Lambda MicroVMs (Firecracker snapshots managed by Lambda).\n * No VNC framebuffer or native serial console \u2014 HTTP(S) and an authenticated shell\n * WebSocket reach the guest through its dedicated endpoint. Suspend/resume preserve full\n * memory + disk state, so pause/resume here is a true checkpoint, unlike QEMU's.\n *\n * Intentionally has no onExit(): unlike Fargate (whose ECS task actually stops when the\n * container's process exits) or QEMU/Firecracker (a guest poweroff kills the local hypervisor\n * process we spawned), a MicroVM's AWS-managed lifecycle has no state that reflects \"the\n * guest's own entrypoint finished\" \u2014 it only transitions via explicit suspend/resume/terminate\n * calls or the idle/duration policies above. 'job' run mode isn't supported on this engine\n * until the guest image itself can signal completion back out (e.g. call TerminateMicrovm on\n * itself, or a callback through the existing HTTP proxy path) \u2014 MultiEngineExecutor.onExit()\n * already surfaces a clear \"does not support job run mode\" error for this engine as-is.\n */\nexport class LambdaMicrovmExecutor implements Executor {\n private readonly client: LambdaMicrovmsClient\n private readonly vms = new Map<string, ManagedMicrovm>()\n\n constructor(private readonly config: LambdaMicrovmConfig) {\n this.client = new LambdaMicrovmsClient(config.region ? { region: config.region } : {})\n }\n\n async create(spec: VmSpec): Promise<VmHandle> {\n const imageIdentifier = this.config.stackImageArns?.[spec.stack] ?? this.config.imageArn\n const maxIdle = this.config.maxIdleSeconds ?? 900\n const shellConnectorArn = managedConnectorArn(imageIdentifier, 'SHELL_INGRESS')\n const ingressNetworkConnectors = [\n ...new Set([...(this.config.ingressConnectorArns ?? []), shellConnectorArn]),\n ]\n\n const run = await this.client.send(\n new RunMicrovmCommand({\n imageIdentifier,\n // Required by CreateMicrovmShellAuthToken and the /shell WebSocket used by vm-console.\n ingressNetworkConnectors,\n egressNetworkConnectors: this.config.egressConnectorArns,\n executionRoleArn: this.config.executionRoleArn,\n maximumDurationInSeconds: this.config.maximumDurationInSeconds ?? 28_800,\n ...(maxIdle > 0\n ? {\n idlePolicy: {\n autoResumeEnabled: true,\n maxIdleDurationSeconds: maxIdle,\n suspendedDurationSeconds: this.config.suspendedDurationSeconds ?? 28_800,\n },\n }\n : {}),\n // The guest's /run lifecycle hook receives this payload \u2014 lets the image\n // identify which builder session/VM it serves.\n runHookPayload: JSON.stringify({\n vmId: spec.vmId,\n sessionId: spec.sessionId,\n stack: spec.stack,\n env: runtimeEnv(spec),\n }),\n // VM_CREATE may be delivered more than once by the Redis-backed control plane.\n // AWS returns the original request result instead of provisioning another MicroVM.\n clientToken: spec.vmId,\n }),\n )\n\n if (!run.microvmId || !run.endpoint) {\n throw new Error('run-microvm returned no microvmId/endpoint')\n }\n\n logger.info(\n { vmId: spec.vmId, microvmId: run.microvmId, endpoint: run.endpoint, state: run.state },\n '[LambdaMicrovm] run-microvm accepted',\n )\n\n const handle: VmHandle = {\n vmId: spec.vmId,\n sessionId: spec.sessionId,\n stack: spec.stack,\n // Resources are fixed at MicroVM image build time; echo the request back for bookkeeping.\n resources: spec.resources,\n running: true,\n metadata: { microvmId: run.microvmId, endpoint: run.endpoint },\n }\n\n const vm: ManagedMicrovm = { handle, microvmId: run.microvmId, endpoint: run.endpoint }\n this.vms.set(spec.vmId, vm)\n\n try {\n await this.waitForState(run.microvmId, 'RUNNING', this.config.createTimeoutMs ?? 25_000)\n } catch (error) {\n this.vms.delete(spec.vmId)\n await this.client\n .send(new TerminateMicrovmCommand({ microvmIdentifier: run.microvmId }))\n .catch(() => {})\n throw error\n }\n\n logger.info({ vmId: spec.vmId, microvmId: run.microvmId }, '[LambdaMicrovm] vm running')\n return handle\n }\n\n async pause(vmId: string): Promise<VmHandle> {\n const vm = this.mustGet(vmId)\n await this.client.send(new SuspendMicrovmCommand({ microvmIdentifier: vm.microvmId }))\n return this.setRunning(vmId, false)\n }\n\n async resume(vmId: string): Promise<VmHandle> {\n const vm = this.mustGet(vmId)\n await this.client.send(new ResumeMicrovmCommand({ microvmIdentifier: vm.microvmId }))\n return this.setRunning(vmId, true)\n }\n\n // Suspend preserves memory + disk, so stop/restore are the same checkpoint\n // operations as pause/resume \u2014 there is no separate \"powered off\" state.\n stop(vmId: string): Promise<VmHandle> {\n return this.pause(vmId)\n }\n\n restore(vmId: string): Promise<VmHandle> {\n return this.resume(vmId)\n }\n\n async destroy(vmId: string): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) return\n\n await this.client.send(new TerminateMicrovmCommand({ microvmIdentifier: vm.microvmId }))\n this.vms.delete(vmId)\n logger.info({ vmId, microvmId: vm.microvmId }, '[LambdaMicrovm] vm terminated')\n }\n\n get(vmId: string): VmHandle | undefined {\n return this.vms.get(vmId)?.handle\n }\n\n list(): VmHandle[] {\n return [...this.vms.values()].map((v) => v.handle)\n }\n\n getSerialSource(vmId: string): SerialSource | undefined {\n const vm = this.vms.get(vmId)\n if (!vm) return undefined\n\n return {\n type: 'websocket',\n url: `wss://${vm.endpoint}/shell`,\n protocols: async () => {\n const response = await this.client.send(\n new CreateMicrovmShellAuthTokenCommand({\n microvmIdentifier: vm.microvmId,\n expirationInMinutes: AUTH_TOKEN_TTL_MINUTES,\n }),\n )\n const token = Object.entries(response.authToken ?? {}).find(\n ([key]) => key.toLowerCase() === 'x-aws-proxy-auth',\n )?.[1]\n if (!token) throw new Error('create-microvm-shell-auth-token returned no auth token')\n\n return [\n 'lambda-microvms',\n `lambda-microvms.authentication.${token}`,\n `lambda-microvms.port.${SHELL_PORT}`,\n ]\n },\n }\n }\n\n async proxyHttp(vmId: string, request: ProxyRequestDescriptor): Promise<ProxyResponseDescriptor> {\n const vm = this.mustGet(vmId)\n const auth = await this.getAuthHeaders(vm)\n\n return new Promise((resolve, reject) => {\n const req = https.request(\n {\n host: vm.endpoint,\n method: request.method,\n path: request.path,\n headers: {\n ...request.headers,\n ...auth,\n // Lambda routes to port 8080 by default; make the guest port explicit.\n 'X-aws-proxy-port': '8080',\n host: vm.endpoint,\n },\n },\n (res) => {\n const chunks: Buffer[] = []\n res.on('data', (c: Buffer) => chunks.push(c))\n res.on('end', () =>\n resolve({\n statusCode: res.statusCode ?? 502,\n headers: Object.fromEntries(\n Object.entries(res.headers).map(([k, v]) => [\n k,\n Array.isArray(v) ? v.join(', ') : v ?? '',\n ]),\n ),\n body: Buffer.concat(chunks),\n }),\n )\n },\n )\n req.on('error', reject)\n if (request.body) req.write(request.body)\n req.end()\n })\n }\n\n /**\n * Recover a Lambda MicroVM after a worker restart. It's an independent AWS-managed\n * resource that outlives this process \u2014 just re-describe it by ID and, unless it's been\n * terminated, rebuild the local handle (the auth token refetches lazily as usual).\n */\n async reattach(record: VmRecord): Promise<VmHandle | undefined> {\n const meta = record.runtimeMetadata as { microvmId?: string; endpoint?: string } | undefined\n if (!meta?.microvmId || !meta.endpoint) return undefined\n\n const described = await this.client\n .send(new GetMicrovmCommand({ microvmIdentifier: meta.microvmId }))\n .catch(() => undefined)\n if (!described || described.state === 'TERMINATED' || described.state === 'TERMINATING') {\n return undefined\n }\n\n const handle: VmHandle = {\n vmId: record.vmId,\n sessionId: record.sessionId,\n stack: record.stack,\n resources: record.resources,\n running: described.state === 'RUNNING',\n metadata: meta,\n }\n this.vms.set(record.vmId, { handle, microvmId: meta.microvmId, endpoint: meta.endpoint })\n logger.info(\n { vmId: record.vmId, microvmId: meta.microvmId, state: described.state },\n '[LambdaMicrovm] vm reattached',\n )\n return handle\n }\n\n /**\n * AWS can suspend or terminate a MicroVM on its own (idle-suspend policy, the suspended-\n * duration cap, the hard maximumDurationInSeconds lifetime) without this process ever\n * issuing a command \u2014 nothing else here polls for that. Called periodically by the\n * worker: re-describes every tracked VM, quietly reconciles running/suspended drift, and\n * reports (then forgets) any that AWS has actually terminated so the control plane's\n * record doesn't stay stuck saying \"running\" forever.\n */\n async reconcile(): Promise<string[]> {\n const externallyTerminated: string[] = []\n\n for (const [vmId, vm] of [...this.vms.entries()]) {\n try {\n const described = await this.client.send(\n new GetMicrovmCommand({ microvmIdentifier: vm.microvmId }),\n )\n if (described.state === 'TERMINATED' || described.state === 'TERMINATING') {\n this.vms.delete(vmId)\n externallyTerminated.push(vmId)\n logger.warn(\n { vmId, microvmId: vm.microvmId, state: described.state },\n '[LambdaMicrovm] vm terminated outside our control',\n )\n } else if (typeof described.state === 'string') {\n const running = described.state === 'RUNNING'\n if (running !== vm.handle.running) vm.handle = { ...vm.handle, running }\n }\n } catch (error) {\n if (error instanceof Error && error.name === 'ResourceNotFoundException') {\n this.vms.delete(vmId)\n externallyTerminated.push(vmId)\n logger.warn(\n { vmId, microvmId: vm.microvmId },\n '[LambdaMicrovm] vm no longer exists in AWS',\n )\n } else {\n logger.error({ vmId, err: error }, '[LambdaMicrovm] reconcile check failed')\n }\n }\n }\n\n return externallyTerminated\n }\n\n private mustGet(vmId: string): ManagedMicrovm {\n const vm = this.vms.get(vmId)\n if (!vm) throw new Error(`vm ${vmId} not found`)\n return vm\n }\n\n private setRunning(vmId: string, running: boolean): VmHandle {\n const vm = this.mustGet(vmId)\n vm.handle = { ...vm.handle, running }\n return vm.handle\n }\n\n private async getAuthHeaders(vm: ManagedMicrovm): Promise<Record<string, string>> {\n if (vm.authToken && vm.authToken.expiresAt - Date.now() > AUTH_TOKEN_REFRESH_MARGIN_MS) {\n return vm.authToken.headers\n }\n\n const resp = await this.client.send(\n new CreateMicrovmAuthTokenCommand({\n microvmIdentifier: vm.microvmId,\n expirationInMinutes: AUTH_TOKEN_TTL_MINUTES,\n allowedPorts: [{ allPorts: {} }],\n }),\n )\n if (!resp.authToken) throw new Error('create-microvm-auth-token returned no token')\n\n vm.authToken = {\n headers: resp.authToken,\n expiresAt: Date.now() + AUTH_TOKEN_TTL_MINUTES * 60_000,\n }\n return vm.authToken.headers\n }\n\n private async waitForState(microvmId: string, target: string, timeoutMs: number): Promise<void> {\n const deadline = Date.now() + timeoutMs\n for (;;) {\n const resp = await this.client.send(new GetMicrovmCommand({ microvmIdentifier: microvmId }))\n if (resp.state === target) return\n if (resp.state === 'TERMINATED' || resp.state === 'TERMINATING') {\n throw new Error(`microvm ${microvmId} entered ${resp.state} while waiting for ${target}`)\n }\n if (Date.now() > deadline) {\n throw new Error(\n `timed out waiting for microvm ${microvmId} to reach ${target} (still ${resp.state})`,\n )\n }\n await new Promise((r) => setTimeout(r, 1_000))\n }\n }\n}\n", "import http from 'http'\nimport {\n ECSClient,\n RunTaskCommand,\n StopTaskCommand,\n DescribeTasksCommand,\n DescribeTaskDefinitionCommand,\n} from '@aws-sdk/client-ecs'\nimport logger from '@multiplayer-app/logger'\nimport type {\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmRecord,\n VmRunMode,\n VmRunResult,\n VmStack,\n} from '@multiplayer-app/builder-types'\nimport type { Executor, VmHandle, VmSpec } from './types'\n\nconst JOB_POLL_INTERVAL_MS = 5_000\n\nexport interface FargateConfig {\n region?: string\n /** ECS cluster name or ARN. */\n cluster: string\n /** Default task definition (family[:revision] or ARN), used for stacks without an override. */\n taskDefinition?: string\n /** Per-stack task definition overrides, e.g. { node: 'builder-node:3' }. */\n stackTaskDefinitions?: Partial<Record<VmStack, string>>\n /** VPC subnets for awsvpc networking. */\n subnets: string[]\n securityGroups?: string[]\n /**\n * ENABLED: task gets a public IP and the worker proxies to it (worker outside the VPC).\n * DISABLED (default): the worker proxies to the task's private IP (worker inside the VPC).\n */\n assignPublicIp?: boolean\n /** Guest HTTP port the app/agent listens on. */\n guestPort?: number\n /** How long to wait for the task to reach RUNNING (image pulls can be slow). */\n startTimeoutMs?: number\n}\n\ninterface ManagedTask {\n handle: VmHandle\n taskArn: string\n ip: string\n runMode: VmRunMode\n startedAt: number\n}\n\n// Valid Fargate cpu (units) \u2192 [min, max] task memory (MiB).\nconst FARGATE_MEM_RANGES: Record<number, [number, number]> = {\n 256: [512, 2048],\n 512: [1024, 4096],\n 1024: [2048, 8192],\n 2048: [4096, 16384],\n 4096: [8192, 30720],\n}\n\n/** Snap requested VM resources to a valid Fargate cpu/memory combination. */\nexport function fargateResources(\n vcpuCount: number,\n memMib: number,\n): { cpu: string; memory: string } {\n const cpu = Math.min(4096, Math.max(256, vcpuCount * 1024))\n const [min, max] = FARGATE_MEM_RANGES[cpu]\n let memory = Math.min(max, Math.max(min, memMib))\n // Above 512 MiB, Fargate only accepts 1 GiB increments\n if (memory > 512) memory = Math.ceil(memory / 1024) * 1024\n return { cpu: String(cpu), memory: String(Math.min(max, memory)) }\n}\n\n/**\n * Runs VMs as AWS Fargate tasks (one task per VM). No VNC or serial console and no\n * pause/resume \u2014 HTTP(S) into the container only, via the task's IP on the guest port.\n * Slower to start than Lambda MicroVMs (image pull + task provisioning), but supports\n * arbitrary container images via standard ECS task definitions.\n */\nexport class FargateExecutor implements Executor {\n private readonly client: ECSClient\n private readonly vms = new Map<string, ManagedTask>()\n private readonly containerNames = new Map<string, string>()\n private readonly pendingResults = new Map<string, VmRunResult>()\n private readonly exitHandlers = new Map<string, (result: VmRunResult) => void>()\n\n constructor(private readonly config: FargateConfig) {\n this.client = new ECSClient(config.region ? { region: config.region } : {})\n }\n\n /** First container of the task definition \u2014 the target for env overrides. Cached per definition. */\n private async resolveContainerName(taskDefinition: string): Promise<string> {\n const cached = this.containerNames.get(taskDefinition)\n if (cached) return cached\n\n const described = await this.client.send(new DescribeTaskDefinitionCommand({ taskDefinition }))\n const name = described.taskDefinition?.containerDefinitions?.[0]?.name\n if (!name) throw new Error(`task definition ${taskDefinition} has no containers`)\n this.containerNames.set(taskDefinition, name)\n return name\n }\n\n private async waitForRunning(taskArn: string): Promise<string> {\n const timeoutMs = this.config.startTimeoutMs ?? 180_000\n const deadline = Date.now() + timeoutMs\n\n for (;;) {\n const described = await this.client.send(\n new DescribeTasksCommand({ cluster: this.config.cluster, tasks: [taskArn] }),\n )\n const task = described.tasks?.[0]\n if (!task) throw new Error(`task ${taskArn} not found`)\n\n if (task.lastStatus === 'STOPPED') {\n throw new Error(`fargate task stopped: ${task.stoppedReason ?? 'unknown reason'}`)\n }\n if (task.lastStatus === 'RUNNING') {\n const ip = this.config.assignPublicIp\n ? await this.resolvePublicIp(task.attachments)\n : task.containers?.[0]?.networkInterfaces?.[0]?.privateIpv4Address\n if (!ip)\n throw new Error(\n `fargate task ${taskArn} is RUNNING but has no ${this.config.assignPublicIp ? 'public' : 'private'} IP`,\n )\n return ip\n }\n if (Date.now() > deadline) {\n throw new Error(\n `fargate task did not reach RUNNING within ${timeoutMs}ms (last status: ${task.lastStatus})`,\n )\n }\n await new Promise((resolve) => setTimeout(resolve, 3000))\n }\n }\n\n private async resolvePublicIp(\n attachments: { type?: string; details?: { name?: string; value?: string }[] }[] | undefined,\n ): Promise<string | undefined> {\n const eniId = attachments\n ?.find((a) => a.type === 'ElasticNetworkInterface')\n ?.details?.find((d) => d.name === 'networkInterfaceId')?.value\n if (!eniId) return undefined\n\n const { EC2Client, DescribeNetworkInterfacesCommand } = await import('@aws-sdk/client-ec2')\n const ec2 = new EC2Client(this.config.region ? { region: this.config.region } : {})\n const described = await ec2.send(\n new DescribeNetworkInterfacesCommand({ NetworkInterfaceIds: [eniId] }),\n )\n return described.NetworkInterfaces?.[0]?.Association?.PublicIp\n }\n\n async create(spec: VmSpec): Promise<VmHandle> {\n const taskDefinition =\n this.config.stackTaskDefinitions?.[spec.stack] ?? this.config.taskDefinition\n if (!taskDefinition) {\n throw new Error(`no Fargate task definition configured for stack \"${spec.stack}\"`)\n }\n\n const containerName = await this.resolveContainerName(taskDefinition)\n const { cpu, memory } = fargateResources(spec.resources.vcpuCount, spec.resources.memMib)\n\n const run = await this.client.send(\n new RunTaskCommand({\n cluster: this.config.cluster,\n taskDefinition,\n launchType: 'FARGATE',\n count: 1,\n networkConfiguration: {\n awsvpcConfiguration: {\n subnets: this.config.subnets,\n securityGroups: this.config.securityGroups,\n assignPublicIp: this.config.assignPublicIp ? 'ENABLED' : 'DISABLED',\n },\n },\n overrides: {\n cpu,\n memory,\n containerOverrides: [\n {\n name: containerName,\n environment: [\n { name: 'VM_ID', value: spec.vmId },\n ...(spec.sessionId ? [{ name: 'SESSION_ID', value: spec.sessionId }] : []),\n { name: 'STACK', value: spec.stack },\n // Release artifact: the container agent pulls, unzips, and starts it\n ...(spec.appUrl ? [{ name: 'APP_URL', value: spec.appUrl }] : []),\n ...Object.entries(spec.env ?? {}).map(([name, value]) => ({ name, value })),\n ],\n },\n ],\n },\n tags: [\n { key: 'vmId', value: spec.vmId },\n ...(spec.sessionId ? [{ key: 'sessionId', value: spec.sessionId }] : []),\n ],\n }),\n )\n\n const taskArn = run.tasks?.[0]?.taskArn\n if (!taskArn) {\n throw new Error(`RunTask failed: ${run.failures?.[0]?.reason ?? 'no task returned'}`)\n }\n logger.info({ vmId: spec.vmId, taskArn, taskDefinition, cpu, memory }, 'fargate task started')\n\n const runMode = spec.runMode ?? 'service'\n try {\n const ip = await this.waitForRunning(taskArn)\n const handle: VmHandle = {\n vmId: spec.vmId,\n sessionId: spec.sessionId,\n stack: spec.stack,\n resources: spec.resources,\n running: true,\n metadata: { taskArn, ip },\n }\n this.vms.set(spec.vmId, { handle, taskArn, ip, runMode, startedAt: Date.now() })\n if (runMode === 'job') void this.watchJob(spec.vmId, taskArn)\n logger.info({ vmId: spec.vmId, ip, runMode }, 'fargate task running')\n return handle\n } catch (error) {\n await this.client\n .send(\n new StopTaskCommand({\n cluster: this.config.cluster,\n task: taskArn,\n reason: 'startup failed',\n }),\n )\n .catch(() => {})\n throw error\n }\n }\n\n async pause(vmId: string): Promise<VmHandle> {\n throw new Error(`fargate tasks cannot be paused (vm ${vmId})`)\n }\n\n async resume(vmId: string): Promise<VmHandle> {\n throw new Error(`fargate tasks cannot be resumed (vm ${vmId})`)\n }\n\n async restore(vmId: string): Promise<VmHandle> {\n throw new Error(`fargate tasks cannot be restored (vm ${vmId})`)\n }\n\n async stop(vmId: string): Promise<VmHandle> {\n const vm = this.mustGet(vmId)\n await this.client.send(\n new StopTaskCommand({\n cluster: this.config.cluster,\n task: vm.taskArn,\n reason: 'stopped via API',\n }),\n )\n vm.handle.running = false\n return vm.handle\n }\n\n async destroy(vmId: string): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) return\n await this.client\n .send(\n new StopTaskCommand({\n cluster: this.config.cluster,\n task: vm.taskArn,\n reason: 'destroyed via API',\n }),\n )\n .catch((error: Error) => logger.warn({ vmId, err: error }, 'fargate stop on destroy failed'))\n this.vms.delete(vmId)\n }\n\n get(vmId: string): VmHandle | undefined {\n return this.vms.get(vmId)?.handle\n }\n\n list(): VmHandle[] {\n return [...this.vms.values()].map((vm) => vm.handle)\n }\n\n async proxyHttp(vmId: string, request: ProxyRequestDescriptor): Promise<ProxyResponseDescriptor> {\n const vm = this.mustGet(vmId)\n if (!vm.handle.running) throw new Error(`vm ${vmId} is not running`)\n\n return new Promise((resolve, reject) => {\n const req = http.request(\n {\n host: vm.ip,\n port: this.config.guestPort ?? 8080,\n method: request.method,\n path: request.path,\n headers: request.headers,\n },\n (res) => {\n const chunks: Buffer[] = []\n res.on('data', (c: Buffer) => chunks.push(c))\n res.on('end', () =>\n resolve({\n statusCode: res.statusCode ?? 502,\n headers: Object.fromEntries(\n Object.entries(res.headers).map(([k, v]) => [\n k,\n Array.isArray(v) ? v.join(', ') : v ?? '',\n ]),\n ),\n body: Buffer.concat(chunks),\n }),\n )\n },\n )\n req.on('error', reject)\n if (request.body) req.write(request.body)\n req.end()\n })\n }\n\n /**\n * Recover a Fargate task after a worker restart. The task is an independent AWS resource\n * that outlives this process \u2014 just re-describe it by ARN and, if it's still RUNNING,\n * rebuild the local handle.\n */\n async reattach(record: VmRecord): Promise<VmHandle | undefined> {\n const meta = record.runtimeMetadata as { taskArn?: string } | undefined\n if (!meta?.taskArn) return undefined\n\n const described = await this.client\n .send(new DescribeTasksCommand({ cluster: this.config.cluster, tasks: [meta.taskArn] }))\n .catch(() => undefined)\n const task = described?.tasks?.[0]\n if (!task || task.lastStatus !== 'RUNNING') return undefined\n\n const ip = this.config.assignPublicIp\n ? await this.resolvePublicIp(task.attachments)\n : task.containers?.[0]?.networkInterfaces?.[0]?.privateIpv4Address\n if (!ip) return undefined\n\n const handle: VmHandle = {\n vmId: record.vmId,\n sessionId: record.sessionId,\n stack: record.stack,\n resources: record.resources,\n running: true,\n metadata: { taskArn: meta.taskArn, ip },\n }\n this.vms.set(record.vmId, {\n handle,\n taskArn: meta.taskArn,\n ip,\n runMode: record.runMode,\n startedAt: Date.parse(record.createdAt) || Date.now(),\n })\n if (record.runMode === 'job') void this.watchJob(record.vmId, meta.taskArn)\n logger.info({ vmId: record.vmId, taskArn: meta.taskArn, ip }, 'fargate task reattached')\n return handle\n }\n\n /**\n * No push notification exists for \"task stopped\" without EventBridge wiring (v1 doesn't set\n * that up), so poll DescribeTasks. Exit code comes straight from the container's own\n * `exitCode` field \u2014 no CloudWatch Logs integration yet, so stdout/stderr capture isn't\n * implemented for this engine (the caller can still find full output in CloudWatch directly,\n * via the task's own log configuration).\n */\n private async watchJob(vmId: string, taskArn: string): Promise<void> {\n const startedAt = this.vms.get(vmId)?.startedAt ?? Date.now()\n for (;;) {\n await new Promise((resolve) => setTimeout(resolve, JOB_POLL_INTERVAL_MS))\n if (!this.vms.has(vmId)) return // destroyed out from under the poll\n\n const described = await this.client\n .send(new DescribeTasksCommand({ cluster: this.config.cluster, tasks: [taskArn] }))\n .catch(() => undefined)\n const task = described?.tasks?.[0]\n\n if (!task) {\n this.finishJob(vmId, {\n exitCode: -1,\n stdout: '',\n stderr: 'fargate task not found while polling for completion',\n truncated: false,\n durationMs: Date.now() - startedAt,\n finishedAt: new Date().toISOString(),\n })\n return\n }\n if (task.lastStatus === 'STOPPED') {\n const exitCode = task.containers?.[0]?.exitCode\n this.finishJob(vmId, {\n exitCode: exitCode ?? 1,\n stdout: '',\n stderr: [\n task.stoppedReason ? `stoppedReason: ${task.stoppedReason}` : undefined,\n 'output capture not implemented for the fargate engine \u2014 see CloudWatch Logs for this task',\n ]\n .filter(Boolean)\n .join('; '),\n truncated: false,\n durationMs: Date.now() - startedAt,\n finishedAt: new Date().toISOString(),\n })\n return\n }\n }\n }\n\n private finishJob(vmId: string, result: VmRunResult): void {\n logger.info({ vmId, exitCode: result.exitCode }, 'fargate job task exited')\n // Keep the map entry (marked not-running) until onExit() claims the result \u2014 see\n // docker-executor's deliverJobResult comment for why route() needs get() to still work.\n const vm = this.vms.get(vmId)\n if (vm) vm.handle = { ...vm.handle, running: false }\n\n const handler = this.exitHandlers.get(vmId)\n if (handler) {\n this.exitHandlers.delete(vmId)\n this.vms.delete(vmId)\n handler(result)\n } else {\n this.pendingResults.set(vmId, result)\n }\n }\n\n onExit(vmId: string, handler: (result: VmRunResult) => void): void {\n const pending = this.pendingResults.get(vmId)\n if (pending) {\n this.pendingResults.delete(vmId)\n this.vms.delete(vmId)\n handler(pending)\n return\n }\n this.exitHandlers.set(vmId, handler)\n }\n\n private mustGet(vmId: string): ManagedTask {\n const vm = this.vms.get(vmId)\n if (!vm) throw new Error(`vm ${vmId} not found`)\n return vm\n }\n}\n", "import fs from 'fs'\nimport { execFileSync } from 'child_process'\nimport logger from '@multiplayer-app/logger'\nimport { VM_STACKS, type VmEngine } from '@multiplayer-app/builder-types'\nimport { availableStacks } from '../images'\nimport type { WorkerConfig } from '../config'\n\n/** Auto-mode default preference when multiple engines are runnable on this host. */\nconst ENGINE_PRIORITY: VmEngine[] = [\n 'firecracker',\n 'qemu',\n 'docker-sandbox',\n 'docker',\n 'lambda-microvm',\n 'fargate',\n 'remote',\n 'mock',\n]\n\nexport interface EngineProbe {\n engine: VmEngine\n available: boolean\n /** Why the engine is unavailable (for startup logs). */\n reason?: string\n}\n\nfunction binaryOnPath(bin: string): boolean {\n if (bin.includes('/')) {\n try {\n fs.accessSync(bin, fs.constants.X_OK)\n return true\n } catch {\n return false\n }\n }\n try {\n execFileSync('which', [bin], { stdio: 'ignore' })\n return true\n } catch {\n return false\n }\n}\n\nfunction kvmUsable(): boolean {\n try {\n fs.accessSync('/dev/kvm', fs.constants.R_OK | fs.constants.W_OK)\n return true\n } catch {\n return false\n }\n}\n\n/** Explicit kernel/initrd override present, or at least one stack dir with both image files. */\nfunction hasBaseImages(cfg: {\n imagesDir: string\n kernelPath?: string\n initrdPath?: string\n}): boolean {\n if (cfg.kernelPath && cfg.initrdPath)\n return fs.existsSync(cfg.kernelPath) && fs.existsSync(cfg.initrdPath)\n return availableStacks(cfg.imagesDir).length > 0\n}\n\nfunction probeQemu(config: WorkerConfig): EngineProbe {\n const { bin, accel } = config.qemu\n if (!hasBaseImages(config.qemu)) {\n return {\n engine: 'qemu',\n available: false,\n reason: `no base images under ${config.qemu.imagesDir} \u2014 run \"worker-cli images pull\" or scripts/setup-vm-images.sh`,\n }\n }\n if (!binaryOnPath(bin)) {\n return { engine: 'qemu', available: false, reason: `${bin} not found on PATH` }\n }\n if (accel === 'hvf' && process.platform !== 'darwin') {\n return {\n engine: 'qemu',\n available: false,\n reason: 'QEMU_ACCEL=hvf requires macOS (use kvm or tcg)',\n }\n }\n if (accel === 'kvm' && !kvmUsable()) {\n return {\n engine: 'qemu',\n available: false,\n reason: 'QEMU_ACCEL=kvm but /dev/kvm is not accessible',\n }\n }\n return { engine: 'qemu', available: true }\n}\n\nfunction probeFirecracker(config: WorkerConfig): EngineProbe {\n const { bin } = config.firecracker\n if (process.platform !== 'linux') {\n return { engine: 'firecracker', available: false, reason: 'requires a Linux host' }\n }\n if (!kvmUsable()) {\n return { engine: 'firecracker', available: false, reason: '/dev/kvm is not accessible' }\n }\n if (!hasBaseImages(config.firecracker)) {\n return {\n engine: 'firecracker',\n available: false,\n reason: `no base images under ${config.firecracker.imagesDir} \u2014 run \"worker-cli images pull\" or scripts/setup-vm-images.sh`,\n }\n }\n if (!binaryOnPath(bin)) {\n return { engine: 'firecracker', available: false, reason: `${bin} not found on PATH` }\n }\n return { engine: 'firecracker', available: true }\n}\n\n/** Whether at least one <imagePrefix>-<stack>:<imageTag> image exists in the local `docker` daemon. */\nfunction hasLocalDockerImage(\n bin: string,\n imagePrefix: string,\n imageTag: string,\n stackImages: Record<string, string> = {},\n): boolean {\n return VM_STACKS.some((stack) => {\n try {\n const image = stackImages[stack] ?? `${imagePrefix}-${stack}:${imageTag}`\n execFileSync(bin, ['image', 'inspect', image], { stdio: 'ignore' })\n return true\n } catch {\n return false\n }\n })\n}\n\nfunction probeDocker(config: WorkerConfig): EngineProbe {\n const { bin, imagePrefix, imageTag, stackImages } = config.docker\n if (!binaryOnPath(bin)) {\n return { engine: 'docker', available: false, reason: `${bin} not found on PATH` }\n }\n try {\n execFileSync(bin, ['info'], { stdio: 'ignore' })\n } catch {\n return { engine: 'docker', available: false, reason: 'docker daemon not reachable' }\n }\n if (!hasLocalDockerImage(bin, imagePrefix, imageTag, stackImages)) {\n return {\n engine: 'docker',\n available: false,\n reason: 'no local docker images \u2014 run scripts/setup-docker-images.sh',\n }\n }\n return { engine: 'docker', available: true }\n}\n\n/**\n * `docker-sandbox` (Docker's own Sandboxes product, the `sbx` CLI) bridges the same local\n * `docker` images in on demand (see DockerSandboxExecutor.ensureTemplateLoaded), so it needs\n * both `sbx` itself and those local images to exist. A not-yet-initialized global network\n * policy (`sbx policy init balanced|allow-all|deny-all`, required once before any sandbox can\n * be created) isn't checked here \u2014 same as Fargate detect not validating IAM permissions\n * upfront \u2014 it'll surface as a clear error the first time `create()` is called instead.\n */\nfunction probeDockerSandbox(config: WorkerConfig): EngineProbe {\n const { bin, imagePrefix, imageTag } = config.dockerSandbox\n if (!binaryOnPath(bin)) {\n return { engine: 'docker-sandbox', available: false, reason: `${bin} not found on PATH` }\n }\n try {\n execFileSync(bin, ['ls'], { stdio: 'ignore' })\n } catch {\n return {\n engine: 'docker-sandbox',\n available: false,\n reason: 'sbx daemon not reachable \u2014 run \"sbx daemon start\" and \"sbx login\"',\n }\n }\n if (!hasLocalDockerImage(config.docker.bin, imagePrefix, imageTag)) {\n return {\n engine: 'docker-sandbox',\n available: false,\n reason: 'no local docker images \u2014 run scripts/setup-docker-images.sh',\n }\n }\n return { engine: 'docker-sandbox', available: true }\n}\n\nfunction probeRemote(config: WorkerConfig): EngineProbe {\n return config.remote.agentUrl\n ? { engine: 'remote', available: true }\n : { engine: 'remote', available: false, reason: 'AGENT_URL not set' }\n}\n\nfunction probeLambdaMicrovm(config: WorkerConfig): EngineProbe {\n const { imageArn, stackImageArns } = config.lambdaMicrovm\n return imageArn || Object.keys(stackImageArns).length\n ? { engine: 'lambda-microvm', available: true }\n : {\n engine: 'lambda-microvm',\n available: false,\n reason: 'MICROVM_IMAGE_ARN / MICROVM_STACK_IMAGE_ARNS not set',\n }\n}\n\nfunction probeFargate(config: WorkerConfig): EngineProbe {\n const { cluster, taskDefinition, stackTaskDefinitions, subnets } = config.fargate\n if (!cluster) {\n return { engine: 'fargate', available: false, reason: 'FARGATE_CLUSTER not set' }\n }\n if (!taskDefinition && !Object.keys(stackTaskDefinitions).length) {\n return {\n engine: 'fargate',\n available: false,\n reason: 'FARGATE_TASK_DEFINITION / FARGATE_STACK_TASK_DEFS not set',\n }\n }\n if (!subnets.length) {\n return { engine: 'fargate', available: false, reason: 'FARGATE_SUBNETS not set' }\n }\n return { engine: 'fargate', available: true }\n}\n\n/** Probe every engine against this host + config. Mock is always runnable. */\nexport function probeEngines(config: WorkerConfig): EngineProbe[] {\n return [\n { engine: 'mock', available: true },\n probeQemu(config),\n probeFirecracker(config),\n probeDocker(config),\n probeDockerSandbox(config),\n probeRemote(config),\n probeLambdaMicrovm(config),\n probeFargate(config),\n ]\n}\n\nexport function detectEngines(config: WorkerConfig): {\n engines: VmEngine[]\n defaultEngine: VmEngine\n} {\n const probes = probeEngines(config)\n\n for (const probe of probes) {\n if (probe.available) {\n logger.info({ engine: probe.engine }, 'micro-VM engine available')\n } else {\n logger.debug({ engine: probe.engine, reason: probe.reason }, 'micro-VM engine unavailable')\n }\n }\n\n const engines = probes.filter((p) => p.available).map((p) => p.engine)\n const defaultEngine = ENGINE_PRIORITY.find((engine) => engines.includes(engine)) ?? 'mock'\n return { engines, defaultEngine }\n}\n", "import logger from '@multiplayer-app/logger'\nimport type {\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmEngine,\n VmExecRequest,\n VmExecResult,\n VmFileWrite,\n VmRecord,\n VmRunResult,\n VmWriteFilesResult,\n} from '@multiplayer-app/builder-types'\nimport { MockExecutor } from './mock-executor'\nimport { QemuExecutor } from './qemu-executor'\nimport { FirecrackerExecutor } from './firecracker-executor'\nimport { DockerExecutor } from './docker-executor'\nimport { DockerSandboxExecutor } from './docker-sandbox-executor'\nimport { RemoteExecutor } from './remote-executor'\nimport { LambdaMicrovmExecutor } from './lambda-microvm-executor'\nimport { FargateExecutor } from './fargate-executor'\nimport { detectEngines } from './detect'\nimport type { Executor, SerialSource, VmHandle, VmSpec } from './types'\nimport type { WorkerConfig } from '../config'\n\nexport type { Executor, SerialSource, VmHandle, VmSpec } from './types'\n\n/** Internal marker: reattach ran cleanly but confirmed the resource itself is gone. */\nclass VmResourceGoneError extends Error {}\n\n/**\n * Of the VM records sandbox says this workerId owns, the ones this executor isn't already\n * tracking in memory \u2014 i.e. the ones actually worth attempting to reattach. A plain reconnect\n * (network blip, not a real process restart) never loses in-memory state, so this naturally\n * comes back empty in that case.\n */\nexport function findNotAttachedVms(\n executor: Pick<Executor, 'get'>,\n records: VmRecord[],\n): VmRecord[] {\n return records.filter((record) => !executor.get(record.vmId))\n}\n\n/** Only called for engines `detectEngines` reported runnable, so prerequisites are already verified. */\nfunction createEngineExecutor(engine: VmEngine, config: WorkerConfig): Executor {\n switch (engine) {\n case 'mock':\n return new MockExecutor()\n case 'qemu':\n return new QemuExecutor(config.qemu)\n case 'firecracker':\n return new FirecrackerExecutor(config.firecracker)\n case 'docker':\n return new DockerExecutor(config.docker)\n case 'docker-sandbox':\n return new DockerSandboxExecutor(config.dockerSandbox)\n case 'remote':\n return new RemoteExecutor(config.remote)\n case 'lambda-microvm':\n return new LambdaMicrovmExecutor(config.lambdaMicrovm)\n case 'fargate':\n return new FargateExecutor(config.fargate)\n default:\n throw new Error(`unknown engine \"${engine as string}\"`)\n }\n}\n\n/**\n * Routes VM operations to per-engine executors. `create` picks the executor from\n * `spec.engine` (falling back to the worker default); every other operation is\n * routed to whichever executor owns the vmId.\n */\nexport class MultiEngineExecutor implements Executor {\n private readonly creations = new Map<string, Promise<VmHandle>>()\n\n constructor(\n private readonly executors: Map<VmEngine, Executor>,\n readonly defaultEngine: VmEngine,\n ) {}\n\n get engines(): VmEngine[] {\n return [...this.executors.keys()]\n }\n\n async create(spec: VmSpec): Promise<VmHandle> {\n const existing = this.get(spec.vmId)\n if (existing) return existing\n\n const pending = this.creations.get(spec.vmId)\n if (pending) return pending\n\n const creation = this.createOnce(spec)\n this.creations.set(spec.vmId, creation)\n try {\n return await creation\n } finally {\n this.creations.delete(spec.vmId)\n }\n }\n\n private async createOnce(spec: VmSpec): Promise<VmHandle> {\n const engine = spec.engine ?? this.defaultEngine\n const executor = this.executors.get(engine)\n if (!executor) {\n throw new Error(\n `engine \"${engine}\" is not available on this worker (available: ${this.engines.join(', ')})`,\n )\n }\n const handle = await executor.create(spec)\n return { ...handle, engine }\n }\n\n // async here isn't a no-op: route() throws synchronously when the vmId isn't tracked in any\n // executor's in-memory map (e.g. worker restarted and hasn't reattached this VM yet). Without\n // `async`, that throw escapes as a real exception instead of a rejected promise \u2014 which,\n // called from socket-client.ts's wrap(), skips its .catch() entirely and leaves the command\n // un-acked until the caller's timeout, looking like the action \"does nothing\".\n async pause(vmId: string): Promise<VmHandle> {\n return this.route(vmId).pause(vmId)\n }\n async resume(vmId: string): Promise<VmHandle> {\n return this.route(vmId).resume(vmId)\n }\n async stop(vmId: string): Promise<VmHandle> {\n return this.route(vmId).stop(vmId)\n }\n async restore(vmId: string): Promise<VmHandle> {\n return this.route(vmId).restore(vmId)\n }\n async destroy(vmId: string): Promise<void> {\n return this.route(vmId).destroy(vmId)\n }\n\n async proxyHttp(vmId: string, request: ProxyRequestDescriptor): Promise<ProxyResponseDescriptor> {\n return this.route(vmId).proxyHttp(vmId, request)\n }\n\n get(vmId: string): VmHandle | undefined {\n for (const executor of this.executors.values()) {\n const handle = executor.get(vmId)\n if (handle) return handle\n }\n return undefined\n }\n\n list(): VmHandle[] {\n return [...this.executors.values()].flatMap((executor) => executor.list())\n }\n\n getSerialSource(vmId: string): SerialSource | undefined {\n for (const executor of this.executors.values()) {\n if (executor.get(vmId)) return executor.getSerialSource?.(vmId)\n }\n return undefined\n }\n\n async exec(vmId: string, request: VmExecRequest): Promise<VmExecResult> {\n const executor = this.route(vmId)\n if (!executor.exec) throw new Error('executor does not support guest exec')\n return executor.exec(vmId, request)\n }\n\n async writeFiles(vmId: string, files: VmFileWrite[]): Promise<VmWriteFilesResult> {\n const executor = this.route(vmId)\n if (!executor.writeFiles) throw new Error('executor does not support guest file writes')\n return executor.writeFiles(vmId, files)\n }\n\n onExit(vmId: string, handler: (result: VmRunResult) => void): void {\n const executor = this.route(vmId)\n if (!executor.onExit) throw new Error('executor does not support job run mode')\n executor.onExit(vmId, handler)\n }\n\n /** Fans out to every sub-executor that supports it (currently just lambda-microvm). */\n async reconcile(): Promise<string[]> {\n const externallyTerminated: string[] = []\n for (const executor of this.executors.values()) {\n if (!executor.reconcile) continue\n externallyTerminated.push(...(await executor.reconcile()))\n }\n return externallyTerminated\n }\n\n /**\n * Recover VMs sandbox says this workerId owns but that aren't currently tracked (a worker\n * restart, most likely). Runs in parallel \u2014 probing many VMs serially would needlessly\n * delay the first heartbeat, which reports capacity from `list()` and must reflect\n * reattached VMs to avoid sandbox overbooking this worker. Best-effort: failures are logged,\n * never thrown \u2014 a VM that can't be reattached just stays unavailable until something\n * touches it again (create/proxy/lifecycle), which already errors gracefully today.\n */\n /**\n * Returns vmIds found genuinely gone (executor.reattach resolved undefined \u2014 the\n * resource itself no longer exists, e.g. AWS already terminated it while this worker\n * was down) as distinct from any other reattach failure (engine unavailable, no reattach\n * support, a transient describe error, ...), which leave the VM merely unavailable\n * rather than confirmed gone.\n */\n async reattachAll(records: VmRecord[]): Promise<string[]> {\n const pending = findNotAttachedVms(this, records)\n if (!pending.length) return []\n\n const results = await Promise.allSettled(\n pending.map(async (record) => {\n const executor = record.engine ? this.executors.get(record.engine) : undefined\n if (!executor)\n throw new Error(`engine \"${record.engine ?? 'unknown'}\" not available on this worker`)\n if (!executor.reattach)\n throw new Error(`engine \"${record.engine}\" does not support reattach`)\n const handle = await executor.reattach(record)\n if (!handle) throw new VmResourceGoneError()\n }),\n )\n\n const externallyTerminated: string[] = []\n results.forEach((result, i) => {\n const vmId = pending[i].vmId\n if (result.status === 'fulfilled') {\n logger.info({ vmId }, 'vm reattached')\n } else if (result.reason instanceof VmResourceGoneError) {\n externallyTerminated.push(vmId)\n logger.warn({ vmId }, 'vm reattach found resource already gone')\n } else {\n logger.warn(\n { vmId, err: result.reason },\n 'vm reattach failed \u2014 staying unavailable until next touch',\n )\n }\n })\n return externallyTerminated\n }\n\n private route(vmId: string): Executor {\n for (const executor of this.executors.values()) {\n if (executor.get(vmId)) return executor\n }\n throw new Error(`vm ${vmId} not found on this worker`)\n }\n}\n\n/**\n * Probes the host (KVM, HVF, binaries, images, ARNs) and registers every runnable engine,\n * defaulting to the most capable one. Per-VM engine selection comes from the create request.\n */\nexport function createExecutor(config: WorkerConfig): MultiEngineExecutor {\n const { engines, defaultEngine } = detectEngines(config)\n\n const executors = new Map<VmEngine, Executor>()\n for (const engine of engines) {\n executors.set(engine, createEngineExecutor(engine, config))\n }\n\n logger.info({ engines, defaultEngine }, 'micro-VM engines initialized')\n return new MultiEngineExecutor(executors, defaultEngine)\n}\n", "import os from 'os'\nimport { io, type Socket } from 'socket.io-client'\nimport logger from '@multiplayer-app/logger'\nimport type {\n CommandAck,\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmExecRequest,\n VmFileWrite,\n VmCreateResultPayload,\n VmRecord,\n WorkerHeartbeat,\n} from '@multiplayer-app/builder-types'\nimport { WorkerEvent } from '@multiplayer-app/builder-types'\nimport type { WorkerConfig } from './config'\nimport { WORKER_VERSION } from './config'\nimport type { MultiEngineExecutor, VmSpec } from './executor'\nimport { loadPersistedWorkerId, savePersistedWorkerId } from './worker-identity'\n\nconst HEARTBEAT_INTERVAL_MS = 10_000\n// AWS's own idle-suspend/max-duration policies can terminate a Lambda MicroVM with no\n// command from this worker \u2014 this drives Executor.reconcile() to catch that drift. Much\n// slower than heartbeat: this is a safety net for a state a worker restart's REATTACH\n// handshake would also eventually catch, not a latency-sensitive signal.\nconst RECONCILE_INTERVAL_MS = 60_000\n// If sandbox never sends the reattach handshake (older version, edge case), start\n// heartbeating anyway rather than hanging the connection forever.\nconst REATTACH_FALLBACK_MS = 5_000\n// Retry forever \u2014 a gateway restart/deploy is a transient outage, not a reason to give up.\n// VMs keep running locally the whole time; reconnecting just resumes heartbeats/reattach.\nconst RECONNECTION_DELAY_MS = 1_000\nconst RECONNECTION_DELAY_MAX_MS = 10_000\n\nfunction primaryIp(): string | undefined {\n for (const ifaces of Object.values(os.networkInterfaces())) {\n for (const iface of ifaces ?? []) {\n if (!iface.internal && iface.family === 'IPv4') return iface.address\n }\n }\n return undefined\n}\n\nfunction buildHeartbeat(config: WorkerConfig, executor: MultiEngineExecutor): WorkerHeartbeat {\n return {\n hostname: os.hostname(),\n ip: primaryIp(),\n region: config.region,\n version: WORKER_VERSION,\n engines: executor.engines,\n defaultEngine: executor.defaultEngine,\n capacity: {\n maxVms: config.maxVms,\n usedVms: executor.list().length,\n cpuCores: os.cpus().length,\n memMib: Math.round(os.totalmem() / (1024 * 1024)),\n },\n }\n}\n\nfunction wrap<TPayload, TResult>(\n handler: (payload: TPayload) => Promise<TResult>,\n): (payload: TPayload, callback: (ack: CommandAck<TResult>) => void) => void {\n return (payload, callback) => {\n handler(payload)\n .then((result) => callback({ ok: true, result }))\n .catch((error: Error) => {\n logger.error({ err: error }, 'command failed')\n // A failed command (e.g. a VM_CREATE rejected by the underlying engine) must only\n // fail that one request \u2014 never take down the worker process. Guard the ack itself\n // too: if callback() throws (e.g. the socket ack already timed out), that throw would\n // otherwise become an unhandled rejection with no further .catch() to absorb it.\n try {\n callback({ ok: false, error: error.message })\n } catch (ackError) {\n logger.error({ err: ackError }, 'failed to send command failure ack')\n }\n })\n }\n}\n\nfunction registerCommandHandlers(socket: Socket, executor: MultiEngineExecutor): void {\n socket.on(\n WorkerEvent.VM_CREATE,\n wrap(async (spec: VmSpec) => {\n try {\n const handle = await executor.create(spec)\n if (spec.runMode === 'job') {\n executor.onExit(spec.vmId, (result) =>\n socket.emit(WorkerEvent.VM_RUN_EXITED, { vmId: spec.vmId, ...result }),\n )\n }\n const result: VmCreateResultPayload = {\n vmId: spec.vmId,\n ok: true,\n metadata: handle.metadata,\n }\n socket.emit(WorkerEvent.VM_CREATE_RESULT, result)\n return handle\n } catch (error) {\n // The engine doesn't support job mode \u2014 don't leave an orphaned resource behind.\n if (spec.runMode === 'job') await executor.destroy(spec.vmId).catch(() => {})\n const result: VmCreateResultPayload = {\n vmId: spec.vmId,\n ok: false,\n error: error instanceof Error ? error.message : String(error),\n }\n socket.emit(WorkerEvent.VM_CREATE_RESULT, result)\n throw error\n }\n }),\n )\n socket.on(\n WorkerEvent.VM_PAUSE,\n wrap(({ vmId }: { vmId: string }) => executor.pause(vmId)),\n )\n socket.on(\n WorkerEvent.VM_RESUME,\n wrap(({ vmId }: { vmId: string }) => executor.resume(vmId)),\n )\n socket.on(\n WorkerEvent.VM_STOP,\n wrap(({ vmId }: { vmId: string }) => executor.stop(vmId)),\n )\n socket.on(\n WorkerEvent.VM_RESTORE,\n wrap(({ vmId }: { vmId: string }) => executor.restore(vmId)),\n )\n socket.on(\n WorkerEvent.VM_DESTROY,\n wrap(({ vmId }: { vmId: string }) => executor.destroy(vmId)),\n )\n\n socket.on(\n WorkerEvent.PROXY_HTTP,\n wrap(\n ({\n vmId,\n ...request\n }: ProxyRequestDescriptor & { vmId: string }): Promise<ProxyResponseDescriptor> =>\n executor.proxyHttp(vmId, request),\n ),\n )\n\n socket.on(\n WorkerEvent.VM_EXEC,\n wrap(({ vmId, ...request }: VmExecRequest & { vmId: string }) => {\n if (!executor.exec) {\n return Promise.reject(new Error('executor does not support guest exec'))\n }\n return executor.exec(vmId, request)\n }),\n )\n\n socket.on(\n WorkerEvent.VM_WRITE_FILES,\n wrap(({ vmId, files }: { vmId: string; files: VmFileWrite[] }) => {\n if (!executor.writeFiles) {\n return Promise.reject(new Error('executor does not support guest file writes'))\n }\n return executor.writeFiles(vmId, files)\n }),\n )\n}\n\nexport function connectToSandbox(config: WorkerConfig, executor: MultiEngineExecutor): Socket {\n // Seed from a prior boot's assigned ID, if this process persisted one \u2014 otherwise the\n // gateway mints a fresh one below, same as a first-ever boot.\n let assignedWorkerId: string | undefined = loadPersistedWorkerId(config.workerIdFile)\n const socket = io(config.sandboxUrl, {\n path: config.workerSocketPath,\n auth: (callback) =>\n callback({\n workerId: config.workerId,\n ...(assignedWorkerId ? { assignedWorkerId } : {}),\n ...(config.token ? { token: config.token } : {}),\n }),\n transports: ['websocket'],\n reconnection: true,\n reconnectionAttempts: Infinity,\n reconnectionDelay: RECONNECTION_DELAY_MS,\n reconnectionDelayMax: RECONNECTION_DELAY_MAX_MS,\n })\n\n let heartbeatTimer: NodeJS.Timeout | undefined\n let reconcileTimer: NodeJS.Timeout | undefined\n let reattachFallbackTimer: NodeJS.Timeout | undefined\n\n socket.on(WorkerEvent.ASSIGNED_ID, ({ workerId }: { workerId: string }) => {\n assignedWorkerId = workerId\n savePersistedWorkerId(config.workerIdFile, workerId)\n logger.info({ workerId: config.workerId, assignedWorkerId }, 'worker runtime ID assigned')\n })\n\n const sendHeartbeat = () => socket.emit(WorkerEvent.HEARTBEAT, buildHeartbeat(config, executor))\n\n function startHeartbeat(): void {\n if (heartbeatTimer) return // already running for this connection\n sendHeartbeat()\n heartbeatTimer = setInterval(sendHeartbeat, HEARTBEAT_INTERVAL_MS)\n }\n\n const runReconcile = () => {\n executor\n .reconcile()\n .then((externallyTerminated) => {\n for (const vmId of externallyTerminated) {\n socket.emit(WorkerEvent.VM_EXTERNALLY_TERMINATED, { vmId })\n }\n })\n .catch((error: Error) => logger.error({ err: error }, 'vm reconcile pass failed'))\n }\n\n function startReconcile(): void {\n if (reconcileTimer) return // already running for this connection\n reconcileTimer = setInterval(runReconcile, RECONCILE_INTERVAL_MS)\n }\n\n socket.on('connect', () => {\n logger.info(\n { workerId: config.workerId, assignedWorkerId, url: config.sandboxUrl },\n 'connected to sandbox',\n )\n\n // Sandbox emits REATTACH once, right after auth, listing any VMs it thinks this worker\n // still owns. Reattach them before the first heartbeat so capacity.usedVms is accurate \u2014\n // otherwise sandbox could schedule new VMs onto capacity that's actually already in use.\n socket.off(WorkerEvent.REATTACH)\n reattachFallbackTimer = setTimeout(() => {\n logger.warn(\n { workerId: config.workerId },\n 'no reattach handshake from sandbox \u2014 starting heartbeat anyway',\n )\n startHeartbeat()\n startReconcile()\n }, REATTACH_FALLBACK_MS)\n\n socket.once(WorkerEvent.REATTACH, (records: VmRecord[]) => {\n clearTimeout(reattachFallbackTimer)\n executor\n .reattachAll(records)\n .then((externallyTerminated) => {\n for (const vmId of externallyTerminated) {\n socket.emit(WorkerEvent.VM_EXTERNALLY_TERMINATED, { vmId })\n }\n })\n .catch((error: Error) => logger.error({ err: error }, 'reattach batch failed'))\n .finally(() => {\n // A create result may have been lost while this worker was disconnected. Successful\n // reattachment is enough to finalize any control-plane record still in 'creating'.\n for (const record of records) {\n const handle = executor.get(record.vmId)\n if (record.state === 'creating' && handle) {\n const result: VmCreateResultPayload = {\n vmId: record.vmId,\n ok: true,\n metadata: handle.metadata,\n }\n socket.emit(WorkerEvent.VM_CREATE_RESULT, result)\n }\n }\n\n // Reattached job VMs may already have a result waiting (finished while this worker\n // was offline) or may still be running \u2014 either way, re-register so its eventual\n // VM_RUN_EXITED gets (re-)sent now that we're connected again.\n for (const record of records) {\n if (record.runMode !== 'job' || !executor.get(record.vmId)) continue\n try {\n executor.onExit(record.vmId, (result) =>\n socket.emit(WorkerEvent.VM_RUN_EXITED, { vmId: record.vmId, ...result }),\n )\n } catch (error) {\n logger.warn(\n { vmId: record.vmId, err: error },\n 'reattached job vm has no onExit support',\n )\n }\n }\n startHeartbeat()\n startReconcile()\n })\n })\n })\n\n socket.on('disconnect', (reason) => {\n logger.warn({ workerId: config.workerId, reason }, 'disconnected from sandbox')\n clearInterval(heartbeatTimer)\n clearInterval(reconcileTimer)\n clearTimeout(reattachFallbackTimer)\n heartbeatTimer = undefined\n reconcileTimer = undefined\n socket.off(WorkerEvent.REATTACH)\n })\n\n socket.on('connect_error', (error) => {\n logger.error(\n {\n err: error,\n sandboxUrl: config.sandboxUrl,\n },\n 'sandbox connection error',\n )\n })\n\n // Reconnection events fire on the Manager (socket.io), not the Socket itself \u2014 'connect'\n // above already fires again on every successful reconnect (restarting heartbeat/reattach),\n // this is purely for visibility into retries while the gateway is down (e.g. mid-restart).\n socket.io.on('reconnect_attempt', (attempt) => {\n logger.warn({ workerId: config.workerId, attempt }, 'reconnecting to sandbox')\n })\n socket.io.on('reconnect_error', (error) => {\n logger.warn({ workerId: config.workerId, err: error }, 'sandbox reconnect attempt failed')\n })\n socket.io.on('reconnect', (attempt) => {\n logger.info({ workerId: config.workerId, attempt }, 'reconnected to sandbox')\n })\n\n registerCommandHandlers(socket, executor)\n\n return socket\n}\n", "import fs from 'fs'\nimport path from 'path'\nimport logger from '@multiplayer-app/logger'\n\n/**\n * Reads back the gateway-assigned runtime routing ID (WorkerEvent.ASSIGNED_ID) this\n * process persisted on a previous boot, if any \u2014 lets a restarted worker present the same\n * identity it had before, so REATTACH's `findByWorkerId` still finds its VMs. Missing file,\n * unreadable, or empty all just mean \"no prior identity\" (first boot, fresh volume, etc.) \u2014\n * not an error; the worker falls back to letting the gateway mint a new one, same as today.\n */\nexport function loadPersistedWorkerId(filePath: string): string | undefined {\n try {\n const id = fs.readFileSync(filePath, 'utf8').trim()\n return id || undefined\n } catch {\n return undefined\n }\n}\n\n/** Best-effort \u2014 a failed write only costs the next restart's reattach, not this session. */\nexport function savePersistedWorkerId(filePath: string, workerId: string): void {\n try {\n fs.mkdirSync(path.dirname(filePath), { recursive: true })\n fs.writeFileSync(filePath, workerId, 'utf8')\n } catch (error) {\n logger.warn(\n { err: error, filePath },\n 'failed to persist assigned worker id \u2014 reattach after a restart may not find its VMs',\n )\n }\n}\n", "import rfb from 'rfb2'\nimport type { Socket } from 'socket.io-client'\nimport logger from '@multiplayer-app/logger'\nimport {\n WorkerEvent,\n type VncFramePayload,\n type VncCopyFramePayload,\n type VncMousePayload,\n type VncKeyboardPayload,\n} from '@multiplayer-app/builder-types'\n\nfunction bgraToRgba(src: Buffer): Buffer {\n const dst = Buffer.allocUnsafe(src.length)\n for (let i = 0; i < src.length; i += 4) {\n dst[i] = src[i + 2]\n dst[i + 1] = src[i + 1]\n dst[i + 2] = src[i]\n dst[i + 3] = 0xff\n }\n return dst\n}\n\n/** Connects to a QEMU VNC server and relays frames upstream to the sandbox socket. */\nexport class VncRelay {\n private rfbc: ReturnType<typeof rfb.createConnection> & any = null\n private interval: ReturnType<typeof setInterval> | null = null\n private mouseHandler: ((e: VncMousePayload) => void) | null = null\n private keyHandler: ((e: VncKeyboardPayload) => void) | null = null\n\n constructor(\n private readonly vmId: string,\n private readonly host: string,\n private readonly port: number,\n private readonly socket: Socket,\n ) {}\n\n start(): void {\n this.rfbc = rfb.createConnection({ host: this.host, port: this.port, password: '' })\n const rfbc = this.rfbc\n\n rfbc.on('connect', () => {\n rfbc.autoUpdate = true\n this.socket.emit(WorkerEvent.VNC_INIT, {\n vmId: this.vmId,\n width: rfbc.width,\n height: rfbc.height,\n })\n this.interval = setInterval(() => {\n rfbc.requestUpdate(false, 0, 0, rfbc.width, rfbc.height)\n }, 300)\n })\n\n rfbc.on('rect', (rect: any) => {\n switch (rect.encoding) {\n case rfb.encodings.raw: {\n const frame: VncFramePayload = {\n vmId: this.vmId,\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n encoding: 'raw',\n data: bgraToRgba(rect.data),\n }\n this.socket.emit(WorkerEvent.VNC_FRAME, frame)\n break\n }\n case rfb.encodings.copyRect: {\n const frame: VncCopyFramePayload = {\n vmId: this.vmId,\n x: rect.x,\n y: rect.y,\n src: rect.src,\n width: rect.width,\n height: rect.height,\n }\n this.socket.emit(WorkerEvent.VNC_COPY_FRAME, frame)\n break\n }\n }\n })\n\n // Guest display init/resize (e.g. QEMU placeholder 640x480 \u2192 guest fb 1280x800).\n // rfb2 updates rfbc.width/height itself; re-announce dimensions and pull a\n // full frame so browsers aren't stuck on the pre-boot placeholder.\n rfbc.on('resize', (rect: { width: number; height: number }) => {\n logger.info(\n { vmId: this.vmId, width: rect.width, height: rect.height },\n '[VNC] desktop resized',\n )\n this.socket.emit(WorkerEvent.VNC_INIT, {\n vmId: this.vmId,\n width: rect.width,\n height: rect.height,\n })\n rfbc.requestUpdate(false, 0, 0, rect.width, rect.height)\n })\n\n rfbc.on('error', (err: Error) => logger.error({ vmId: this.vmId, err }, '[VNC] RFB error'))\n\n this.mouseHandler = (e: VncMousePayload) => {\n if (e.vmId === this.vmId) rfbc.pointerEvent(e.x, e.y, e.button)\n }\n this.keyHandler = (e: VncKeyboardPayload) => {\n if (e.vmId === this.vmId) rfbc.keyEvent(e.keyCode, e.isDown)\n }\n this.socket.on(WorkerEvent.VNC_MOUSE, this.mouseHandler)\n this.socket.on(WorkerEvent.VNC_KEYBOARD, this.keyHandler)\n logger.info({ vmId: this.vmId, port: this.port }, '[VNC] relay started')\n }\n\n destroy(): void {\n if (this.interval) clearInterval(this.interval)\n if (this.mouseHandler) this.socket.off(WorkerEvent.VNC_MOUSE, this.mouseHandler)\n if (this.keyHandler) this.socket.off(WorkerEvent.VNC_KEYBOARD, this.keyHandler)\n try {\n this.rfbc?.end()\n } catch {}\n this.rfbc = null\n logger.info({ vmId: this.vmId }, '[VNC] relay destroyed')\n }\n}\n", "import net from 'net'\nimport type { ChildProcess } from 'child_process'\nimport type { Socket } from 'socket.io-client'\nimport WebSocket, { type RawData } from 'ws'\nimport logger from '@multiplayer-app/logger'\nimport { WorkerEvent, type TerminalInputPayload } from '@multiplayer-app/builder-types'\nimport type { SerialSource } from '../executor/types'\n\n/** Relays VM serial console data upstream to the sandbox socket. */\nexport class SerialRelay {\n private conn: net.Socket | null = null\n private webSocket: WebSocket | null = null\n private reconnectTimer: NodeJS.Timeout | null = null\n private connecting = false\n private browserCount = 0\n private pendingInput: string[] = []\n private destroyed = false\n private inputHandler: ((e: TerminalInputPayload) => void) | null = null\n private attachHandler: ((e: { vmId: string }) => void) | null = null\n private detachHandler: ((e: { vmId: string }) => void) | null = null\n\n constructor(\n private readonly vmId: string,\n private readonly source: SerialSource,\n private readonly socket: Socket,\n ) {}\n\n connect(): void {\n this.destroyed = false\n if (this.source.type === 'tcp') {\n this.connectTcp()\n } else if (this.source.type === 'pipe') {\n this.connectPipe()\n } else {\n // AWS shell connections are authenticated and count as MicroVM endpoint activity.\n // Keep the connection lazy so a VM with no browser attached can still auto-suspend.\n this.attachHandler = ({ vmId }) => {\n if (vmId !== this.vmId) return\n this.browserCount += 1\n if (this.browserCount === 1) void this.connectWebSocket()\n }\n this.detachHandler = ({ vmId }) => {\n if (vmId !== this.vmId) return\n this.browserCount = Math.max(0, this.browserCount - 1)\n if (this.browserCount === 0) this.disconnectWebSocket()\n }\n this.socket.on(WorkerEvent.TERMINAL_ATTACH, this.attachHandler)\n this.socket.on(WorkerEvent.TERMINAL_DETACH, this.detachHandler)\n }\n\n this.inputHandler = (e: TerminalInputPayload) => {\n if (e.vmId !== this.vmId) return\n if (this.source.type === 'tcp' && this.conn) {\n this.conn.write(e.data)\n } else if (this.source.type === 'pipe') {\n const proc = (this.source as { type: 'pipe'; process: ChildProcess }).process\n proc.stdin?.write(e.data)\n } else if (this.source.type === 'websocket') {\n if (this.webSocket?.readyState === WebSocket.OPEN) {\n this.webSocket.send(e.data)\n } else {\n // Attach can race VM creation or a worker reconnect. Treat real input as proof that\n // a browser is present, establish the shell, and replay the keystroke once it opens.\n this.browserCount = Math.max(1, this.browserCount)\n this.pendingInput.push(e.data)\n if (this.pendingInput.length > 100) this.pendingInput.shift()\n void this.connectWebSocket()\n }\n }\n }\n this.socket.on(WorkerEvent.TERMINAL_INPUT, this.inputHandler)\n }\n\n private connectTcp(): void {\n const { host, port } = this.source as { type: 'tcp'; host: string; port: number }\n const attempt = () => {\n const sock = net.createConnection(port, host)\n sock.once('connect', () => {\n this.conn = sock\n logger.info({ vmId: this.vmId, port }, '[Serial] TCP connected')\n sock.on('data', (d: Buffer) =>\n this.socket.emit(WorkerEvent.TERMINAL_DATA, { vmId: this.vmId, data: d }),\n )\n sock.on('end', () => logger.info({ vmId: this.vmId }, '[Serial] TCP ended'))\n sock.on('error', (err) => logger.error({ vmId: this.vmId, err }, '[Serial] TCP error'))\n })\n sock.once('error', () => {\n if (!this.destroyed) setTimeout(attempt, 1_000)\n })\n }\n attempt()\n }\n\n private connectPipe(): void {\n const { process: proc } = this.source as { type: 'pipe'; process: ChildProcess }\n proc.stdout?.on('data', (d: Buffer) =>\n this.socket.emit(WorkerEvent.TERMINAL_DATA, { vmId: this.vmId, data: d }),\n )\n proc.stderr?.on('data', (d: Buffer) =>\n this.socket.emit(WorkerEvent.TERMINAL_DATA, { vmId: this.vmId, data: d }),\n )\n }\n\n private async connectWebSocket(): Promise<void> {\n if (\n this.destroyed ||\n this.browserCount === 0 ||\n this.source.type !== 'websocket' ||\n this.webSocket ||\n this.connecting\n ) {\n return\n }\n\n try {\n this.connecting = true\n const protocols = await this.source.protocols()\n if (this.destroyed || this.browserCount === 0) return\n\n const webSocket = new WebSocket(this.source.url, protocols)\n this.webSocket = webSocket\n webSocket.on('open', () => {\n for (const data of this.pendingInput.splice(0)) webSocket.send(data)\n logger.info({ vmId: this.vmId }, '[Serial] Lambda shell connected')\n })\n webSocket.on('message', (data: RawData) => {\n const chunk = Array.isArray(data)\n ? Buffer.concat(data)\n : Buffer.isBuffer(data)\n ? data\n : Buffer.from(data)\n this.socket.emit(WorkerEvent.TERMINAL_DATA, { vmId: this.vmId, data: chunk })\n })\n webSocket.on('error', (error) => {\n logger.error({ vmId: this.vmId, err: error }, '[Serial] Lambda shell error')\n })\n webSocket.on('close', () => {\n if (this.webSocket === webSocket) this.webSocket = null\n logger.info({ vmId: this.vmId }, '[Serial] Lambda shell disconnected')\n this.scheduleWebSocketReconnect()\n })\n } catch (error) {\n logger.error({ vmId: this.vmId, err: error }, '[Serial] Lambda shell connect failed')\n this.scheduleWebSocketReconnect()\n } finally {\n this.connecting = false\n }\n }\n\n private scheduleWebSocketReconnect(): void {\n if (this.destroyed || this.browserCount === 0 || this.reconnectTimer) return\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null\n void this.connectWebSocket()\n }, 1_000)\n }\n\n private disconnectWebSocket(): void {\n if (this.reconnectTimer) clearTimeout(this.reconnectTimer)\n this.reconnectTimer = null\n this.pendingInput = []\n const webSocket = this.webSocket\n this.webSocket = null\n webSocket?.close()\n }\n\n destroy(): void {\n this.destroyed = true\n if (this.inputHandler) this.socket.off(WorkerEvent.TERMINAL_INPUT, this.inputHandler)\n if (this.attachHandler) this.socket.off(WorkerEvent.TERMINAL_ATTACH, this.attachHandler)\n if (this.detachHandler) this.socket.off(WorkerEvent.TERMINAL_DETACH, this.detachHandler)\n try {\n this.conn?.destroy()\n } catch {}\n this.conn = null\n this.disconnectWebSocket()\n logger.info({ vmId: this.vmId }, '[Serial] relay destroyed')\n }\n}\n", "import type { Socket } from 'socket.io-client'\nimport type { MultiEngineExecutor } from './executor'\nimport { VncRelay } from './services/vnc-relay'\nimport { SerialRelay } from './services/serial-relay'\n\n/**\n * Wires up VNC and terminal relays for any executor that exposes console endpoints (QEMU: VNC +\n * serial TCP ports; Firecracker: serial via process stdio pipe; Lambda MicroVM: authenticated\n * shell WebSocket). All media flows through the sandbox socket to browsers \u2014 the worker never\n * accepts inbound connections from the internet. Wraps create/reattach/destroy in place.\n */\nexport function attachConsoleRelays(executor: MultiEngineExecutor, sandboxSocket: Socket): void {\n const relays = new Map<string, { vnc?: VncRelay; serial?: SerialRelay }>()\n\n const attach = (handle: NonNullable<ReturnType<MultiEngineExecutor['get']>>): void => {\n if (relays.has(handle.vmId)) return\n const entry: { vnc?: VncRelay; serial?: SerialRelay } = {}\n\n if (handle.vncPort) {\n const vnc = new VncRelay(handle.vmId, '127.0.0.1', handle.vncPort, sandboxSocket)\n vnc.start()\n entry.vnc = vnc\n }\n\n const serialSource = handle.serialPort\n ? { type: 'tcp' as const, host: '127.0.0.1', port: handle.serialPort }\n : executor.getSerialSource?.(handle.vmId)\n if (serialSource) {\n const serial = new SerialRelay(handle.vmId, serialSource, sandboxSocket)\n serial.connect()\n entry.serial = serial\n }\n\n if (entry.vnc || entry.serial) relays.set(handle.vmId, entry)\n }\n\n const originalCreate = executor.create.bind(executor)\n executor.create = async (spec) => {\n const handle = await originalCreate(spec)\n attach(handle)\n return handle\n }\n\n const originalReattachAll = executor.reattachAll.bind(executor)\n executor.reattachAll = async (records) => {\n const externallyTerminated = await originalReattachAll(records)\n for (const record of records) {\n const handle = executor.get(record.vmId)\n if (handle) attach(handle)\n }\n return externallyTerminated\n }\n\n const originalDestroy = executor.destroy.bind(executor)\n executor.destroy = async (vmId) => {\n const entry = relays.get(vmId)\n entry?.vnc?.destroy()\n entry?.serial?.destroy()\n relays.delete(vmId)\n return originalDestroy(vmId)\n }\n}\n", "import { execFile } from 'child_process'\nimport { promisify } from 'util'\nimport type { WorkerConfig } from './config'\nimport { availableStacks, hostArch, PUBLISHED_IMAGE_STACKS, pullImages } from './images'\nimport { version as WORKER_VERSION } from '../package.json'\n\nconst execFileAsync = promisify(execFile)\n\nexport function artifactImageLocation(env: NodeJS.ProcessEnv = process.env): string | undefined {\n const bucket = env.S3_BUCKET_ARTIFACTS?.trim()\n if (!bucket) return undefined\n if (bucket.includes('/') || bucket.includes('://')) {\n throw new Error('S3_BUCKET_ARTIFACTS must contain only the bucket name (no scheme or path)')\n }\n const version = env.NODE_ENV === 'development' || env.BUILDER_ENV === 'local'\n ? 'local'\n : WORKER_VERSION\n return `s3://${bucket}/${version}/qemu`\n}\n\nfunction allStacksAvailable(imagesDir: string): boolean {\n const available = new Set(availableStacks(imagesDir))\n return PUBLISHED_IMAGE_STACKS.every((stack) => available.has(stack))\n}\n\nasync function dockerAvailable(bin: string): Promise<boolean> {\n try {\n await execFileAsync(bin, ['info'])\n return true\n } catch {\n return false\n }\n}\n\nasync function dockerImageExists(bin: string, image: string): Promise<boolean> {\n try {\n await execFileAsync(bin, ['image', 'inspect', image])\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Materialize remotely published images before engine detection.\n *\n * S3_BUCKET_ARTIFACTS is the artifact bucket name. The worker derives the\n * environment/version and runner prefix; pullImages appends\n * <arch>/<stack>/<file>.\n * Registry-backed Docker images are pulled whenever the configured prefix is\n * a qualified repository (contains a slash), while local development prefixes\n * continue to require locally built images.\n */\nexport async function prepareWorkerImages(\n config: WorkerConfig,\n env: NodeJS.ProcessEnv = process.env,\n): Promise<void> {\n const vmImagesUrl = artifactImageLocation(env)\n const refreshVmImages = env.VM_IMAGES_REFRESH === 'true'\n if (vmImagesUrl) {\n const destinations = new Set([config.qemu.imagesDir, config.firecracker.imagesDir])\n for (const imagesDir of destinations) {\n if (!refreshVmImages && allStacksAvailable(imagesDir)) continue\n await pullImages({\n location: vmImagesUrl,\n arch: hostArch(),\n endpoint: env.S3_ARTIFACTS_ENDPOINT,\n }, imagesDir)\n }\n }\n\n const shouldPullDocker = env.DOCKER_PULL_IMAGES === 'true'\n || (env.DOCKER_PULL_IMAGES !== 'false' && config.docker.imagePrefix.includes('/'))\n if (!shouldPullDocker || !await dockerAvailable(config.docker.bin)) return\n\n for (const stack of PUBLISHED_IMAGE_STACKS) {\n const image = config.docker.stackImages[stack]\n ?? `${config.docker.imagePrefix}-${stack}:${config.docker.imageTag}`\n if (!await dockerImageExists(config.docker.bin, image)) {\n await execFileAsync(config.docker.bin, ['pull', image])\n }\n }\n}\n", "import http, { type IncomingMessage, type Server, type ServerResponse } from 'http'\n\nexport interface SandboxHealthServerOptions {\n host: string\n port: number\n pathPrefix: string\n isReady: () => boolean\n}\n\n/** Local probe server under API_PREFIX: /healthz is liveness; /health is readiness. */\nexport async function startSandboxHealthServer(\n options: SandboxHealthServerOptions,\n): Promise<Server> {\n const server = http.createServer((req: IncomingMessage, res: ServerResponse) => {\n const pathname = new URL(req.url ?? '/', 'http://localhost').pathname\n if (pathname === `${options.pathPrefix}/healthz`) {\n res.writeHead(200, { 'content-type': 'application/json' })\n res.end(JSON.stringify({ ok: true, status: 'alive' }))\n return\n }\n if (pathname === `${options.pathPrefix}/health`) {\n const ready = options.isReady()\n res.writeHead(ready ? 200 : 503, { 'content-type': 'application/json' })\n res.end(JSON.stringify({ ok: ready, status: ready ? 'ready' : 'not-ready' }))\n return\n }\n res.writeHead(404, { 'content-type': 'application/json' })\n res.end(JSON.stringify({ ok: false, error: 'not found' }))\n })\n\n await new Promise<void>((resolve, reject) => {\n server.listen(options.port, options.host, resolve)\n server.once('error', reject)\n })\n return server\n}\n", "// Builds this package's own guest-agent base images (node/python/static) and registers/updates\n// them as AWS Lambda MicroVM images \u2014 in the caller's own AWS account, using whatever\n// credentials are ambient (AWS_PROFILE, env vars, an assumed role, ...). No repo checkout, no\n// Docker daemon, no external `zip` binary: everything is generated and zipped in-memory (see\n// microvm-guest-agents.ts), so this works the same way whether run from this monorepo's own\n// CI or from `npx @multiplayer-app/sandbox images microvm-create` in a client's own project.\n//\n// Each stack maps to one stable-named image (\"<prefix>-<stack>\", e.g. \"sandbox-node\"). The\n// first run creates it; every subsequent run updates it in place, which AWS records as a new\n// numbered version (visible as \"Active version\" in the console) rather than a new image\n// resource \u2014 so the image's ARN never changes across runs, and workers configured with it\n// always use whichever version is currently active.\nimport { ZipArchive } from 'archiver'\nimport {\n LambdaMicrovmsClient,\n CreateMicrovmImageCommand,\n UpdateMicrovmImageCommand,\n GetMicrovmImageCommand,\n GetMicrovmImageVersionCommand,\n ListManagedMicrovmImagesCommand,\n} from '@aws-sdk/client-lambda-microvms'\nimport { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'\nimport { version as SANDBOX_VERSION } from '../package.json'\nimport {\n MICROVM_BASE_IMAGE_STACKS,\n guestAgentFiles,\n isMicrovmBaseImageStack,\n type MicrovmBaseImageStack,\n} from './microvm-guest-agents'\n\nexport interface CreateMicrovmImagesOptions {\n region: string\n /** S3 bucket the built code artifact is uploaded to (must already exist). */\n bucket: string\n /** AWS-managed base OS image ARN \u2014 discover one with listBaseMicrovmImages(). */\n baseImageArn: string\n /** IAM role ARN the build assumes to read the artifact from `bucket` (needs s3:GetObject). */\n buildRoleArn: string\n /** Stacks to build/register (default: all of MICROVM_BASE_IMAGE_STACKS). */\n stacks?: MicrovmBaseImageStack[]\n /** Minimum guest memory, MiB (default: 1024). */\n minMemoryMib?: number\n /** MicroVM image name prefix, \"<prefix>-<stack>\" (default: 'sandbox'). */\n imageNamePrefix?: string\n /** Image-build poll interval, ms (default: 5000). */\n pollIntervalMs?: number\n /** Image-build poll timeout, ms (default: 600000 = 10 min). */\n pollTimeoutMs?: number\n /** Called after each step so callers (CLI, CI) can report progress. Optional. */\n onProgress?: (message: string) => void\n}\n\nexport interface CreateMicrovmImagesResult {\n /** stack -> the image ARN that's now active, ready to use as MICROVM_STACK_IMAGE_ARNS. */\n stackArns: Record<string, string>\n}\n\nconst HOOKS = {\n port: 8080,\n microvmHooks: { run: 'ENABLED', resume: 'ENABLED', suspend: 'ENABLED', terminate: 'ENABLED' },\n microvmImageHooks: { ready: 'ENABLED' },\n} as const\n\n/** Zips an in-memory file map (name -> contents) without touching disk or shelling out. */\nasync function zipFiles(files: Record<string, string>): Promise<Buffer> {\n const archive = new ZipArchive({ zlib: { level: 9 } })\n const chunks: Buffer[] = []\n const collected = new Promise<Buffer>((resolve, reject) => {\n archive.on('data', (chunk: Buffer) => chunks.push(chunk))\n archive.on('error', reject)\n archive.on('end', () => resolve(Buffer.concat(chunks)))\n })\n for (const [name, content] of Object.entries(files)) {\n archive.append(content, { name })\n }\n await archive.finalize()\n return collected\n}\n\nasync function listAllManagedImages(\n client: LambdaMicrovmsClient,\n): Promise<{ imageArn?: string }[]> {\n const images: { imageArn?: string }[] = []\n let nextToken: string | undefined\n do {\n const page = await client.send(new ListManagedMicrovmImagesCommand({ nextToken }))\n images.push(...(page.items ?? []))\n nextToken = page.nextToken\n } while (nextToken)\n return images\n}\n\n/** AWS-managed base OS images available as a `baseImageArn` candidate in this region. */\nexport async function listBaseMicrovmImages(options: { region: string }): Promise<string[]> {\n const client = new LambdaMicrovmsClient({ region: options.region })\n const images = await listAllManagedImages(client)\n return images.map((image) => image.imageArn).filter((arn): arn is string => Boolean(arn))\n}\n\nasync function imageExists(\n client: LambdaMicrovmsClient,\n imageIdentifier: string,\n): Promise<boolean> {\n try {\n await client.send(new GetMicrovmImageCommand({ imageIdentifier }))\n return true\n } catch (error) {\n if (error instanceof Error && error.name === 'ResourceNotFoundException') return false\n throw error\n }\n}\n\n/** A version's build state is tracked separately from the parent image's own state. */\nasync function waitForVersion(\n client: LambdaMicrovmsClient,\n imageIdentifier: string,\n imageVersion: string | undefined,\n pollIntervalMs: number,\n pollTimeoutMs: number,\n): Promise<void> {\n const deadline = Date.now() + pollTimeoutMs\n for (;;) {\n const version = await client.send(\n new GetMicrovmImageVersionCommand({ imageIdentifier, imageVersion }),\n )\n if (version.state === 'SUCCESSFUL') return\n if (version.state === 'FAILED') {\n throw new Error(`${imageIdentifier} version ${imageVersion} failed to build`)\n }\n if (Date.now() > deadline) {\n throw new Error(\n `timed out waiting for ${imageIdentifier} version ${imageVersion} (still ${version.state})`,\n )\n }\n await new Promise((resolve) => setTimeout(resolve, pollIntervalMs))\n }\n}\n\n/**\n * Builds and registers/updates the guest-agent base images for `options.stacks`, in the\n * caller's own AWS account. Returns the stack -> image ARN map once every image's new version\n * has finished building (polled).\n */\nexport async function createMicrovmImages(\n options: CreateMicrovmImagesOptions,\n): Promise<CreateMicrovmImagesResult> {\n const {\n region,\n bucket,\n baseImageArn,\n buildRoleArn,\n stacks = [...MICROVM_BASE_IMAGE_STACKS],\n minMemoryMib = 1024,\n imageNamePrefix = 'sandbox',\n pollIntervalMs = 5_000,\n pollTimeoutMs = 600_000,\n onProgress = () => {},\n } = options\n\n for (const stack of stacks) {\n if (!isMicrovmBaseImageStack(stack)) {\n throw new Error(\n `unsupported stack \"${stack}\" \u2014 must be one of: ${MICROVM_BASE_IMAGE_STACKS.join(', ')}`,\n )\n }\n }\n\n // GetMicrovmImage/UpdateMicrovmImage require a full ARN identifier (unlike RunMicrovmCommand,\n // which also accepts a bare name) \u2014 build it from the account ID embedded in the build role\n // ARN rather than pulling in an STS dependency just to call GetCallerIdentity.\n const accountId = buildRoleArn.split(':')[4]\n if (!accountId) throw new Error(`could not parse account ID from buildRoleArn: ${buildRoleArn}`)\n\n // The SDK's Architecture enum only defines ARM_64 today \u2014 Lambda MicroVMs is Graviton-only\n // right now (AWS's own pricing page only publishes ARM/Graviton rates too). Not configurable\n // because there's currently nothing else valid to configure it to.\n const cpuArchitecture = 'ARM_64' as const\n const s3 = new S3Client({ region })\n const lambdaMicrovms = new LambdaMicrovmsClient({ region })\n const stackArns: Record<string, string> = {}\n\n for (const stack of stacks) {\n const files = guestAgentFiles(stack)\n const zip = await zipFiles(files)\n const key = `microvm-images/${stack}/app.zip`\n onProgress(`[${stack}] uploading ${zip.byteLength}-byte artifact -> s3://${bucket}/${key}`)\n await s3.send(new PutObjectCommand({ Bucket: bucket, Key: key, Body: zip }))\n\n const imageName = `${imageNamePrefix}-${stack}`\n const imageArn = `arn:aws:lambda:${region}:${accountId}:microvm-image:${imageName}`\n const commonFields = {\n baseImageArn,\n buildRoleArn,\n codeArtifact: { uri: `s3://${bucket}/${key}` },\n cpuConfigurations: [{ architecture: cpuArchitecture }],\n resources: [{ minimumMemoryInMiB: minMemoryMib }],\n description: `sandbox v${SANDBOX_VERSION}`,\n hooks: HOOKS,\n }\n\n const exists = await imageExists(lambdaMicrovms, imageArn)\n onProgress(`[${stack}] ${exists ? 'updating' : 'creating'} MicroVM image ${imageName}...`)\n const result = exists\n ? await lambdaMicrovms.send(\n new UpdateMicrovmImageCommand({ imageIdentifier: imageArn, ...commonFields }),\n )\n : await lambdaMicrovms.send(\n new CreateMicrovmImageCommand({ name: imageName, tags: { stack }, ...commonFields }),\n )\n\n onProgress(`[${stack}] waiting for version ${result.imageVersion} to build...`)\n await waitForVersion(\n lambdaMicrovms,\n imageArn,\n result.imageVersion,\n pollIntervalMs,\n pollTimeoutMs,\n )\n const finalArn = result.imageArn ?? imageArn\n onProgress(`[${stack}] ready: ${finalArn} (version ${result.imageVersion})`)\n stackArns[stack] = finalArn\n }\n\n return { stackArns }\n}\n", "/**\n * Guest-agent source for each stack's Lambda MicroVM base image, as a set of in-memory files\n * (zipped and uploaded by microvm-images.ts \u2014 no disk/build step needed).\n *\n * Kept in sync BY HAND with scripts/base-images/{node,python,static}/build.sh, which the\n * internal build-base-images.sh pipeline still uses for QEMU/Firecracker/Docker images (those\n * need a real build host, so unifying the two isn't in scope here) \u2014 if you change one, change\n * the other. The agent itself: an HTTP server on :8080 that answers the Lambda MicroVM\n * lifecycle hooks (/aws/lambda-microvms/runtime/v1/*) and {\"status\":\"ok\"} elsewhere. The /run\n * hook payload (vmId/sessionId/stack/env from the worker executor) is kept in memory and\n * echoed back so the control plane can identify the VM.\n */\n\nexport const MICROVM_BASE_IMAGE_STACKS = ['node', 'python', 'static'] as const\nexport type MicrovmBaseImageStack = (typeof MICROVM_BASE_IMAGE_STACKS)[number]\n\nexport function isMicrovmBaseImageStack(stack: string): stack is MicrovmBaseImageStack {\n return (MICROVM_BASE_IMAGE_STACKS as readonly string[]).includes(stack)\n}\n\nconst NODE_APP = `const http = require('http')\nconst fs = require('fs')\nconst { execSync, spawn } = require('child_process')\n\nconst HOOK_PREFIX = '/aws/lambda-microvms/runtime/v1/'\nlet session = null // set by the /run hook (payload from the worker executor)\n\n// Release deployment: pull the presigned artifact, unzip, then hand :8080 over\n// to the app (it must answer the lifecycle hooks itself from that point on).\nasync function startApp(url) {\n try {\n const res = await fetch(url)\n if (!res.ok) throw new Error(\\`artifact download failed: HTTP \\${res.status}\\`)\n fs.writeFileSync('/tmp/app.zip', Buffer.from(await res.arrayBuffer()))\n execSync('unzip -o -q /tmp/app.zip -d /workspace')\n server.close(() => {\n console.log('starting release app (node app.js)')\n const child = spawn('node', ['app.js'], { cwd: '/workspace', stdio: 'inherit' })\n child.on('exit', (code) => process.exit(code ?? 1))\n })\n } catch (error) {\n console.error('release deploy failed, agent keeps serving:', error)\n }\n}\n\nconst server = http.createServer((req, res) => {\n if (req.url.startsWith(HOOK_PREFIX) && req.method === 'POST') {\n const hook = req.url.slice(HOOK_PREFIX.length)\n const chunks = []\n req.on('data', (c) => chunks.push(c))\n req.on('end', () => {\n const body = Buffer.concat(chunks).toString()\n if (hook === 'run' && body) {\n try {\n const parsed = JSON.parse(body)\n session = parsed.runHookPayload ? JSON.parse(parsed.runHookPayload) : null\n session = { ...session, microvmId: parsed.microvmId }\n for (const [key, value] of Object.entries(session?.env ?? {})) {\n if (typeof value === 'string') process.env[key] = value\n }\n } catch { /* payload is optional */ }\n }\n // Runtime env may contain a presigned release URL or other secrets; never log the body.\n console.log(\\`lifecycle hook: \\${hook}\\`)\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end('{}')\n if (hook === 'run' && process.env.APP_URL) {\n setImmediate(() => startApp(process.env.APP_URL))\n }\n })\n return\n }\n\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({ status: 'ok', path: req.url, session }))\n})\n\nserver.listen(8080, () => {\n console.log('vm agent listening on 8080')\n // Fargate/Docker: no lifecycle hook caller, so APP_URL (if set) drives startup directly.\n if (process.env.APP_URL) setImmediate(() => startApp(process.env.APP_URL))\n})\n`\n\nconst NODE_DOCKERFILE = `FROM node:24-alpine\nWORKDIR /app\nCOPY app.js .\nRUN mkdir -p /workspace\nEXPOSE 8080\nCMD [\"node\", \"app.js\"]\n`\n\nconst PYTHON_APP = `import json\nimport os\nimport threading\nimport urllib.request\nimport zipfile\nfrom http.server import BaseHTTPRequestHandler, ThreadingHTTPServer\n\nHOOK_PREFIX = \"/aws/lambda-microvms/runtime/v1/\"\nsession = None # set by the /run hook (payload from the worker executor)\n\n\ndef start_app(url):\n \"\"\"Release deployment: pull the presigned artifact, unzip, then replace this\n process with the app on :8080 (it must answer lifecycle hooks itself).\"\"\"\n try:\n urllib.request.urlretrieve(url, \"/tmp/app.zip\")\n with zipfile.ZipFile(\"/tmp/app.zip\") as zf:\n zf.extractall(\"/workspace\")\n print(\"starting release app (python app.py)\", flush=True)\n os.chdir(\"/workspace\")\n os.execvp(\"python\", [\"python\", \"app.py\"])\n except Exception as error: # noqa: BLE001 \u2014 agent keeps serving on failure\n print(f\"release deploy failed, agent keeps serving: {error}\", flush=True)\n\n\nclass Handler(BaseHTTPRequestHandler):\n def _send(self, body):\n data = body.encode()\n self.send_response(200)\n self.send_header(\"Content-Type\", \"application/json\")\n self.send_header(\"Content-Length\", str(len(data)))\n self.end_headers()\n self.wfile.write(data)\n\n def do_POST(self):\n global session\n if self.path.startswith(HOOK_PREFIX):\n hook = self.path[len(HOOK_PREFIX):]\n length = int(self.headers.get(\"Content-Length\") or 0)\n body = self.rfile.read(length).decode() if length else \"\"\n if hook == \"run\" and body:\n try:\n parsed = json.loads(body)\n payload = parsed.get(\"runHookPayload\")\n session = json.loads(payload) if payload else {}\n session[\"microvmId\"] = parsed.get(\"microvmId\")\n os.environ.update({\n key: value for key, value in session.get(\"env\", {}).items()\n if isinstance(value, str)\n })\n except (ValueError, TypeError):\n pass # payload is optional\n # Runtime env may contain a presigned release URL or other secrets.\n print(f\"lifecycle hook: {hook}\")\n self._send(\"{}\")\n if hook == \"run\" and os.environ.get(\"APP_URL\"):\n threading.Timer(0.1, start_app, args=[os.environ[\"APP_URL\"]]).start()\n return\n self._send(json.dumps({\"status\": \"ok\", \"path\": self.path, \"session\": session}))\n\n def do_GET(self):\n self._send(json.dumps({\"status\": \"ok\", \"path\": self.path, \"session\": session}))\n\n def log_message(self, fmt, *args):\n pass\n\n\nif __name__ == \"__main__\":\n print(\"vm agent listening on 8080\")\n # Fargate/Docker: no lifecycle hook caller, so APP_URL (if set) drives startup directly.\n if os.environ.get(\"APP_URL\"):\n threading.Timer(0.1, start_app, args=[os.environ[\"APP_URL\"]]).start()\n ThreadingHTTPServer((\"\", 8080), Handler).serve_forever()\n`\n\nconst PYTHON_DOCKERFILE = `FROM python:3.12-alpine\nWORKDIR /app\nCOPY app.py .\nRUN mkdir -p /workspace\nEXPOSE 8080\nCMD [\"python\", \"app.py\"]\n`\n\nconst STATIC_APP = `const http = require('http')\nconst fs = require('fs')\nconst path = require('path')\nconst { execSync } = require('child_process')\n\nconst HOOK_PREFIX = '/aws/lambda-microvms/runtime/v1/'\nconst STATIC_ROOT = '/workspace'\nlet session = null // set by the /run hook (payload from the worker executor)\nlet serving = false // true once a release has been unzipped into STATIC_ROOT\n\nconst CONTENT_TYPES = {\n '.html': 'text/html; charset=utf-8',\n '.htm': 'text/html; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.js': 'text/javascript; charset=utf-8',\n '.mjs': 'text/javascript; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.ico': 'image/x-icon',\n '.txt': 'text/plain; charset=utf-8',\n '.wasm': 'application/wasm',\n}\n\n// Release deployment: pull the presigned artifact, unzip it into STATIC_ROOT, and\n// switch the request handler into \"serve static files\" mode. No process is spawned \u2014\n// unlike the node/python base images, there is no entrypoint to run.\nasync function deployRelease(url) {\n const res = await fetch(url)\n if (!res.ok) throw new Error(\\`artifact download failed: HTTP \\${res.status}\\`)\n fs.mkdirSync(STATIC_ROOT, { recursive: true })\n fs.writeFileSync('/tmp/site.zip', Buffer.from(await res.arrayBuffer()))\n execSync(\\`unzip -o -q /tmp/site.zip -d \\${STATIC_ROOT}\\`)\n fs.rmSync('/tmp/site.zip', { force: true })\n serving = true\n console.log('serving static release from', STATIC_ROOT)\n}\n\nfunction serveStatic(req, res) {\n const urlPath = decodeURIComponent(req.url.split('?')[0])\n let filePath = path.join(STATIC_ROOT, path.normalize(urlPath).replace(/^(\\\\.\\\\.[/\\\\\\\\])+/, ''))\n if (urlPath.endsWith('/') || urlPath === '') filePath = path.join(filePath, 'index.html')\n\n fs.readFile(filePath, (err, data) => {\n if (err) {\n // SPA-style fallback: unknown paths without a file extension serve index.html\n if (!path.extname(filePath)) {\n return fs.readFile(path.join(STATIC_ROOT, 'index.html'), (err2, index) => {\n if (err2) return send404(res)\n res.writeHead(200, { 'Content-Type': CONTENT_TYPES['.html'] })\n res.end(index)\n })\n }\n return send404(res)\n }\n const ext = path.extname(filePath).toLowerCase()\n res.writeHead(200, { 'Content-Type': CONTENT_TYPES[ext] ?? 'application/octet-stream' })\n res.end(data)\n })\n}\n\nfunction send404(res) {\n res.writeHead(404, { 'Content-Type': 'text/plain' })\n res.end('not found')\n}\n\nconst server = http.createServer((req, res) => {\n if (req.url.startsWith(HOOK_PREFIX) && req.method === 'POST') {\n const hook = req.url.slice(HOOK_PREFIX.length)\n const chunks = []\n req.on('data', (c) => chunks.push(c))\n req.on('end', () => {\n const body = Buffer.concat(chunks).toString()\n if (hook === 'run' && body) {\n try {\n const parsed = JSON.parse(body)\n session = parsed.runHookPayload ? JSON.parse(parsed.runHookPayload) : null\n session = { ...session, microvmId: parsed.microvmId }\n for (const [key, value] of Object.entries(session?.env ?? {})) {\n if (typeof value === 'string') process.env[key] = value\n }\n } catch { /* payload is optional */ }\n }\n // Runtime env may contain a presigned release URL or other secrets; never log the body.\n console.log(\\`lifecycle hook: \\${hook}\\`)\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end('{}')\n if (hook === 'run' && process.env.APP_URL) {\n deployRelease(process.env.APP_URL).catch((error) => console.error('release deploy failed:', error))\n }\n })\n return\n }\n\n if (serving) return serveStatic(req, res)\n\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({ status: 'ok', path: req.url, session }))\n})\n\nserver.listen(8080, () => {\n console.log('vm agent listening on 8080')\n // Fargate/Docker: no lifecycle hook caller, so APP_URL (if set) drives startup directly.\n if (process.env.APP_URL) deployRelease(process.env.APP_URL).catch((error) => console.error('release deploy failed:', error))\n})\n`\n\nconst STATIC_DOCKERFILE = `FROM node:24-alpine\nRUN apk add --no-cache unzip\nWORKDIR /app\nCOPY app.js .\nRUN mkdir -p /workspace\nEXPOSE 8080\nCMD [\"node\", \"app.js\"]\n`\n\n/** Files to zip for `stack`'s base image, relative paths -> contents. */\nexport function guestAgentFiles(stack: MicrovmBaseImageStack): Record<string, string> {\n switch (stack) {\n case 'node':\n return { 'app.js': NODE_APP, Dockerfile: NODE_DOCKERFILE }\n case 'python':\n return { 'app.py': PYTHON_APP, Dockerfile: PYTHON_DOCKERFILE }\n case 'static':\n return { 'app.js': STATIC_APP, Dockerfile: STATIC_DOCKERFILE }\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["import_config", "import_os", "import_path", "path", "os", "fs", "S3Client", "PutObjectCommand", "os", "path", "import_os", "bunyan", "import_bunyan", "import_os", "HOST_NAME", "import_promises", "import_os", "import_path", "path", "http", "fs", "os", "import_child_process", "import_path", "import_promises", "import_os", "MAX_OUTPUT_BYTES", "path", "os", "fs", "vm", "http", "net", "import_child_process", "import_http", "import_net", "import_path", "import_promises", "import_os", "MAX_OUTPUT_BYTES", "JOB_EXIT_SENTINEL", "path", "os", "fs", "http", "net", "import_child_process", "import_util", "import_http", "DEFAULT_EXEC_TIMEOUT_MS", "MAX_EXEC_TIMEOUT_MS", "MAX_OUTPUT_BYTES", "MAX_FILE_BYTES", "http", "import_child_process", "import_util", "import_promises", "import_os", "import_path", "import_http", "DEFAULT_EXEC_TIMEOUT_MS", "MAX_EXEC_TIMEOUT_MS", "MAX_OUTPUT_BYTES", "MAX_FILE_BYTES", "WORKSPACE_DIR", "execFileAsync", "assertSafeWorkspacePath", "path", "os", "fs", "http", "import_http", "path", "https", "http", "import_https", "https", "import_http", "JOB_POLL_INTERVAL_MS", "http", "import_fs", "import_child_process", "fs", "import_os", "import_fs", "import_path", "fs", "path", "os", "result", "rfb", "import_net", "WebSocket", "net", "import_child_process", "import_util", "execFileAsync", "version", "import_http", "http", "import_client_lambda_microvms", "images", "version"]
|
|
4
|
+
"sourcesContent": ["#!/usr/bin/env node\n/* eslint-disable no-console -- console output is the CLI's user interface */\n// Worker CLI. Published as the global `sandbox` executable and also available locally via\n// `pnpm --filter @multiplayer-app/sandbox run cli -- <args>`.\nimport 'dotenv/config'\nimport { Command } from 'commander'\nimport { version as WORKER_VERSION } from '../package.json'\nimport { loadWorkerConfigFromEnv } from './config'\nimport { createExecutor } from './executor'\nimport { probeEngines } from './executor/detect'\nimport { defaultImagesDir, hostArch, pullImages, pushImages } from './images'\nimport { connectToSandbox } from './socket-client'\nimport { attachConsoleRelays } from './console-relays'\nimport { artifactImageLocation, prepareWorkerImages } from './prepare-images'\nimport { startSandboxHealthServer } from './health-server'\nimport { createMicrovmImages, listBaseMicrovmImages } from './microvm-images'\nimport { MICROVM_BASE_IMAGE_STACKS, isMicrovmBaseImageStack } from './microvm-guest-agents'\nimport logger from '@multiplayer-app/logger'\n\n// This is a long-running daemon managing potentially many VMs \u2014 one failed operation (e.g. a\n// VM_CREATE rejected by a misconfigured/unavailable engine) must never take the whole worker\n// down and orphan every other VM it's managing. Command handlers already catch their own\n// errors (see socket-client.ts#wrap), but this is the last line of defense against anything\n// that still slips through as a bare rejection/throw.\nprocess.on('unhandledRejection', (reason) => {\n logger.error({ err: reason }, 'unhandled rejection \u2014 sandbox worker continues running')\n})\nprocess.on('uncaughtException', (error) => {\n logger.error({ err: error }, 'uncaught exception \u2014 sandbox worker continues running')\n})\n\nconst program = new Command()\n\nprogram\n .name('sandbox')\n .description('Run and manage a Multiplayer sandbox worker')\n .version(WORKER_VERSION)\n\nprogram\n .command('start')\n .description('start a worker and connect it to the sandbox control plane')\n .option('--token <token>', 'worker authentication token (env: WORKER_TOKEN)')\n .option('--worker-id <id>', 'worker pool/authentication ID (env: WORKER_ID; default: hostname)')\n .option(\n '--sandbox-url <url>',\n 'control-plane base URL (env: SANDBOX_URL; default: https://api.sandbox.filingramp.com/v0)',\n )\n .option('--max-vms <count>', 'maximum concurrent VMs (env: MAX_VMS)')\n .action(\n async (opts: { token?: string; workerId?: string; sandboxUrl?: string; maxVms?: string }) => {\n const config = loadWorkerConfigFromEnv({\n ...process.env,\n ...(opts.token ? { WORKER_TOKEN: opts.token } : {}),\n ...(opts.workerId ? { WORKER_ID: opts.workerId } : {}),\n ...(opts.sandboxUrl ? { SANDBOX_URL: opts.sandboxUrl } : {}),\n ...(opts.maxVms ? { MAX_VMS: opts.maxVms } : {}),\n })\n const socketRef: { current?: ReturnType<typeof connectToSandbox> } = {}\n const healthServer = await startSandboxHealthServer({\n host: config.healthHost,\n port: config.healthPort,\n pathPrefix: config.healthPathPrefix,\n isReady: () => socketRef.current?.connected === true,\n })\n await prepareWorkerImages(config)\n const executor = createExecutor(config)\n const socket = connectToSandbox(config, executor)\n socketRef.current = socket\n attachConsoleRelays(executor, socket)\n\n let stopping = false\n const stop = async (signal: string): Promise<void> => {\n if (stopping) return\n stopping = true\n console.log(`\\n${signal} received; shutting down sandbox worker...`)\n socket.disconnect()\n healthServer.close()\n const results = await Promise.allSettled(\n executor.list().map((vm) => executor.destroy(vm.vmId)),\n )\n const failed = results.filter((result) => result.status === 'rejected')\n if (failed.length) console.error(`Failed to destroy ${failed.length} VM(s) during shutdown`)\n process.exit(failed.length ? 1 : 0)\n }\n\n process.once('SIGINT', () => {\n void stop('SIGINT')\n })\n process.once('SIGTERM', () => {\n void stop('SIGTERM')\n })\n\n logger.info(`Starting sandbox worker ${config.workerId} \u2192 ${config.sandboxUrl}`)\n // Socket.IO's reconnect timers keep the process alive until a termination signal arrives.\n },\n )\n\nprogram\n .command('detect')\n .description('probe this host and report which micro-VM engines it can run')\n .action(() => {\n const probes = probeEngines(\n loadWorkerConfigFromEnv({ ...process.env, WORKER_ID: '-', WORKER_TOKEN: '-' }),\n )\n for (const probe of probes) {\n const status = probe.available ? 'available' : `unavailable \u2014 ${probe.reason}`\n console.log(`${probe.engine.padEnd(15)} ${status}`)\n }\n })\n\nconst images = program\n .command('images')\n .description('manage engine base images (kernel + initramfs for QEMU/Firecracker)')\n\nimages\n .command('pull')\n .description(\n 'download per-stack base images from S3 or an HTTPS mirror into the standard location',\n )\n .requiredOption(\n '--from <location>',\n 's3://bucket[/prefix] or https:// base URL (default derived from S3_BUCKET_ARTIFACTS)',\n artifactImageLocation(),\n )\n .option('--arch <arch>', 'image architecture', hostArch())\n .option('--stack <stack...>', 'stacks to pull (default: all)')\n .option('--dest <dir>', 'destination directory (default: ~/.multiplayer/vm-images/<arch>)')\n .option(\n '--endpoint <url>',\n 'custom S3 endpoint, e.g. a MinIO URL (env: S3_ARTIFACTS_ENDPOINT)',\n process.env.S3_ARTIFACTS_ENDPOINT,\n )\n .action(\n async (opts: {\n from: string\n arch: string\n stack?: string[]\n dest?: string\n endpoint?: string\n }) => {\n const dest = opts.dest ?? defaultImagesDir(opts.arch)\n const files = await pullImages(\n { location: opts.from, arch: opts.arch, stacks: opts.stack, endpoint: opts.endpoint },\n dest,\n )\n for (const file of files) console.log(`pulled ${file}`)\n console.log('\\nbase images ready \u2014 \"sandbox detect\" shows which engines they enable')\n },\n )\n\nimages\n .command('push')\n .description('upload locally built per-stack base images (scripts/setup-vm-images.sh) to S3')\n .requiredOption(\n '--to <location>',\n 's3://bucket[/prefix] (default derived from S3_BUCKET_ARTIFACTS)',\n artifactImageLocation(),\n )\n .option('--arch <arch>', 'image architecture', hostArch())\n .option('--stack <stack...>', 'stacks to push (default: all found locally)')\n .option('--src <dir>', 'source directory (default: ~/.multiplayer/vm-images/<arch>)')\n .option(\n '--endpoint <url>',\n 'custom S3 endpoint, e.g. a MinIO URL (env: S3_ARTIFACTS_ENDPOINT)',\n process.env.S3_ARTIFACTS_ENDPOINT,\n )\n .action(\n async (opts: {\n to: string\n arch: string\n stack?: string[]\n src?: string\n endpoint?: string\n }) => {\n const src = opts.src ?? defaultImagesDir(opts.arch)\n const uploaded = await pushImages(\n { location: opts.to, arch: opts.arch, stacks: opts.stack, endpoint: opts.endpoint },\n src,\n )\n for (const uri of uploaded) console.log(`pushed ${uri}`)\n },\n )\n\nimages\n .command('microvm-list-base')\n .description('list AWS-managed base OS images available in your account/region (candidates for --base-image-arn)')\n .requiredOption('--region <region>', 'AWS region', process.env.AWS_REGION)\n .action(async (opts: { region: string }) => {\n const arns = await listBaseMicrovmImages({ region: opts.region })\n console.log(`AWS-managed base images in ${opts.region}:`)\n for (const arn of arns) console.log(` ${arn}`)\n })\n\nimages\n .command('microvm-create')\n .description(\n 'build this package\\'s guest-agent base images (node/python/static) and register/update ' +\n 'them as AWS Lambda MicroVM images in your own AWS account (uses ambient AWS credentials ' +\n '\u2014 AWS_PROFILE, env vars, an assumed role, ...)',\n )\n .requiredOption('--region <region>', 'AWS region', process.env.AWS_REGION)\n .requiredOption(\n '--bucket <bucket>',\n 'S3 bucket the built code artifact is uploaded to (must already exist)',\n process.env.S3_BUCKET_ARTIFACTS,\n )\n .requiredOption(\n '--base-image-arn <arn>',\n 'AWS-managed base OS image ARN \u2014 see \"sandbox images microvm-list-base\"',\n process.env.MICROVM_BASE_IMAGE_ARN,\n )\n .requiredOption(\n '--build-role-arn <arn>',\n 'IAM role ARN the build assumes to read the artifact from --bucket (needs s3:GetObject)',\n process.env.MICROVM_BUILD_ROLE_ARN,\n )\n .option(\n '--stack <stack...>',\n `stacks to build/register (default: ${MICROVM_BASE_IMAGE_STACKS.join(' ')})`,\n )\n .option('--min-memory-mib <mib>', 'minimum guest memory, MiB', '1024')\n .option('--image-name-prefix <prefix>', 'MicroVM image name prefix, \"<prefix>-<stack>\"', 'sandbox')\n .action(\n async (opts: {\n region: string\n bucket: string\n baseImageArn: string\n buildRoleArn: string\n stack?: string[]\n minMemoryMib: string\n imageNamePrefix: string\n }) => {\n for (const stack of opts.stack ?? []) {\n if (!isMicrovmBaseImageStack(stack)) {\n throw new Error(\n `unsupported stack \"${stack}\" \u2014 must be one of: ${MICROVM_BASE_IMAGE_STACKS.join(', ')}`,\n )\n }\n }\n const { stackArns } = await createMicrovmImages({\n region: opts.region,\n bucket: opts.bucket,\n baseImageArn: opts.baseImageArn,\n buildRoleArn: opts.buildRoleArn,\n stacks: opts.stack?.filter(isMicrovmBaseImageStack),\n minMemoryMib: Number(opts.minMemoryMib),\n imageNamePrefix: opts.imageNamePrefix,\n onProgress: (message) => console.log(message),\n })\n console.log('\\nSet this in your worker environment:')\n console.log(\n `MICROVM_STACK_IMAGE_ARNS=${Object.entries(stackArns)\n .map(([stack, arn]) => `${stack}:${arn}`)\n .join(',')}`,\n )\n },\n )\n\nprogram.parseAsync().catch((error: Error) => {\n console.error(`Error: ${error.message}`)\n process.exit(1)\n})\n", "{\n \"name\": \"@multiplayer-app/sandbox\",\n \"version\": \"7.0.6\",\n \"description\": \"Sandbox worker library and CLI (Docker, QEMU, Firecracker, AWS Lambda MicroVM, Fargate)\",\n \"main\": \"dist/index.js\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"require\": \"./dist/index.js\",\n \"default\": \"./dist/index.js\"\n }\n },\n \"bin\": {\n \"sandbox\": \"dist/cli.js\"\n },\n \"files\": [\n \"dist\"\n ],\n \"publishConfig\": {\n \"access\": \"public\",\n \"registry\": \"https://registry.npmjs.org/\"\n },\n \"scripts\": {\n \"build\": \"tsc --build --force && node scripts/bundle.mjs\",\n \"dev\": \"nodemon --watch src --watch scripts/bundle.mjs --watch package.json --ext ts,mjs,json --exec \\\"pnpm run build && pnpm run worker:start\\\"\",\n \"clean\": \"rm -rf ./dist tsconfig.tsbuildinfo\",\n \"typecheck\": \"tsc --noEmit\",\n \"lint\": \"eslint src/**/*.ts --config ../../eslint.config.js\",\n \"images:build\": \"bash scripts/build-base-images.sh\",\n \"images:publish:local\": \"bash scripts/publish-base-images-local.sh\",\n \"images:upload:local\": \"SKIP_BUILD=1 bash scripts/publish-base-images-local.sh\",\n \"docker:build\": \"docker build -f Dockerfile -t multiplayer-sandbox-worker:local ../..\",\n \"start\": \"node dist/cli.js\",\n \"worker:start\": \"node dist/cli.js start\",\n \"test\": \"tsc --build --force && node --test 'dist/**/*.test.js'\",\n \"prepublishOnly\": \"pnpm run build\",\n \"postversion\": \"git commit -m \\\"sandbox v$npm_package_version\\\" -- package.json && git tag \\\"sandbox-v$npm_package_version\\\" && git push && git push --tags\"\n },\n \"dependencies\": {\n \"@aws-sdk/client-ec2\": \"^3.1087.0\",\n \"@aws-sdk/client-ecs\": \"^3.1087.0\",\n \"@aws-sdk/client-lambda-microvms\": \"^3.1079.0\",\n \"@aws-sdk/client-s3\": \"^3.1079.0\",\n \"archiver\": \"^8.0.0\",\n \"bunyan\": \"1.8.15\",\n \"commander\": \"^14.0.0\",\n \"dotenv\": \"^17.2.3\",\n \"rfb2\": \"^0.2.2\",\n \"socket.io-client\": \"4.8.3\",\n \"ws\": \"^8.18.3\"\n },\n \"devDependencies\": {\n \"@multiplayer-app/builder-types\": \"workspace:*\",\n \"@multiplayer-app/logger\": \"workspace:*\",\n \"@types/archiver\": \"^8.0.0\",\n \"@types/node\": \"^25.8.0\",\n \"@types/ws\": \"^8.18.1\",\n \"esbuild\": \"^0.25.12\",\n \"nodemon\": \"3.1.14\",\n \"typescript\": \"^6.0.3\"\n }\n}\n", "import os from 'os'\nimport path from 'path'\nimport { version as WORKER_VERSION } from '../package.json'\nimport { defaultImagesDir } from './images'\n\nexport { WORKER_VERSION }\n\nexport interface RemoteWorkerConfig {\n agentUrl: string\n authToken?: string\n}\n\nexport interface FirecrackerWorkerConfig {\n bin: string\n imagesDir: string\n kernelPath?: string\n initrdPath?: string\n vmDataPath: string\n}\n\nexport interface QemuWorkerConfig {\n bin: string\n imagesDir: string\n kernelPath?: string\n initrdPath?: string\n vmDataPath: string\n portRangeStart: number\n portRangeEnd: number\n accel: string\n cpu: string\n machine: string\n}\n\nexport interface LambdaMicrovmWorkerConfig {\n region?: string\n imageArn: string\n stackImageArns: Record<string, string>\n ingressConnectorArns?: string[]\n egressConnectorArns?: string[]\n executionRoleArn?: string\n maxIdleSeconds: number\n suspendedDurationSeconds: number\n maximumDurationInSeconds: number\n createTimeoutMs: number\n}\n\nexport interface DockerWorkerConfig {\n bin: string\n imagePrefix: string\n imageTag: string\n stackImages: Record<string, string>\n network?: string\n portRangeStart: number\n portRangeEnd: number\n guestPort: number\n}\n\nexport interface DockerSandboxWorkerConfig {\n bin: string\n imagePrefix: string\n imageTag: string\n /** Fully-qualified `sbx template load`ed ref overrides, keyed by stack. */\n stackTemplates: Record<string, string>\n /** In-sandbox start command per stack \u2014 `sbx create shell` doesn't run the image's own CMD. */\n stackAgentCommands: Record<string, string>\n workspaceRoot: string\n portRangeStart: number\n portRangeEnd: number\n guestPort: number\n minMemoryMib: number\n}\n\nexport interface FargateWorkerConfig {\n region?: string\n cluster: string\n taskDefinition?: string\n stackTaskDefinitions: Record<string, string>\n subnets: string[]\n securityGroups?: string[]\n assignPublicIp: boolean\n guestPort: number\n startTimeoutMs: number\n}\n\nexport interface WorkerConfig {\n /** Credential/pool identity. Multiple instances may intentionally share it. */\n workerId: string\n /**\n * Local file this process persists its gateway-assigned runtime routing ID to (see\n * WorkerEvent.ASSIGNED_ID) \u2014 reused on the next boot so REATTACH still finds this\n * replica's VMs after a real process restart, not just a socket reconnect. Every\n * replica needs its own path (a container's own filesystem already gives it one by\n * default; co-located processes on the same host must set distinct WORKER_ID_FILE).\n */\n workerIdFile: string\n token?: string\n sandboxUrl: string\n workerSocketPath: string\n maxVms: number\n healthHost: string\n healthPort: number\n healthPathPrefix: string\n region?: string\n remote: RemoteWorkerConfig\n firecracker: FirecrackerWorkerConfig\n qemu: QemuWorkerConfig\n docker: DockerWorkerConfig\n dockerSandbox: DockerSandboxWorkerConfig\n lambdaMicrovm: LambdaMicrovmWorkerConfig\n fargate: FargateWorkerConfig\n}\n\n/** Format: \"node:<value>,python:<value>\" \u2014 per-stack overrides (MicroVM image ARNs, Fargate task defs). */\nfunction parseStackMap(raw: string | undefined): Record<string, string> {\n const map: Record<string, string> = {}\n if (!raw) return map\n for (const pair of raw.split(',')) {\n const idx = pair.indexOf(':')\n if (idx === -1) continue\n const stack = pair.slice(0, idx).trim()\n const arn = pair.slice(idx + 1).trim()\n if (stack && arn) map[stack] = arn\n }\n return map\n}\n\nfunction parseArnList(raw: string | undefined): string[] | undefined {\n if (!raw) return undefined\n const arns = raw\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean)\n return arns.length ? arns : undefined\n}\n\nfunction resolveSandboxEndpoint(rawUrl: string): {\n sandboxUrl: string\n workerSocketPath: string\n} {\n const url = new URL(rawUrl)\n const basePath = url.pathname.replace(/\\/+$/, '')\n return {\n // Socket.IO treats a URL pathname as a namespace, so connect to the origin\n // and pass the derived HTTP transport path separately. SANDBOX_URL's pathname is the\n // sole source of truth for the socket path \u2014 it must include whatever base the control\n // plane expects (e.g. \"/v0/gapi\" or \"/internal/v0/gapi\"), and \"/workers/ws\" is appended.\n sandboxUrl: url.origin,\n workerSocketPath: `${basePath}/workers/ws`,\n }\n}\n\nexport function loadWorkerConfigFromEnv(env: NodeJS.ProcessEnv = process.env): WorkerConfig {\n const workerId = env.WORKER_ID?.trim() || os.hostname()\n const workerIdFile =\n env.WORKER_ID_FILE?.trim() ||\n path.join(os.tmpdir(), `multiplayer-sandbox-worker-${workerId}.id`)\n const token = env.WORKER_TOKEN?.trim() || undefined\n const sandboxEndpoint = resolveSandboxEndpoint(\n env.SANDBOX_URL ?? 'https://api.sandbox.filingramp.com/v0/gapi',\n )\n\n return {\n workerId,\n workerIdFile,\n token,\n sandboxUrl: sandboxEndpoint.sandboxUrl,\n workerSocketPath: sandboxEndpoint.workerSocketPath,\n maxVms: Number(env.MAX_VMS) || 10,\n healthHost: env.SANDBOX_HEALTH_HOST ?? '0.0.0.0',\n healthPort: Number(env.SANDBOX_HEALTH_PORT) || 3000,\n healthPathPrefix: (env.API_PREFIX ?? '/v0/api').replace(/\\/+$/, ''),\n region: env.WORKER_REGION,\n remote: {\n // No default: an unset AGENT_URL means the remote engine is not configured on this worker\n agentUrl: env.AGENT_URL ?? '',\n authToken: env.AGENT_TOKEN,\n },\n firecracker: {\n bin: env.FIRECRACKER_BIN ?? 'firecracker',\n // Per-stack base images (<imagesDir>/<stack>/vmlinuz + initramfs.img) from\n // `worker-cli images pull` / setup-vm-images.sh; engine detection checks\n // existence, so missing images just disable the engine.\n imagesDir: env.FIRECRACKER_IMAGES_DIR ?? env.VM_IMAGES_DIR ?? defaultImagesDir(),\n // Explicit single-image override, applied to every stack when both are set\n kernelPath: env.FIRECRACKER_KERNEL,\n initrdPath: env.FIRECRACKER_INITRD,\n vmDataPath: env.FIRECRACKER_VM_DATA ?? path.join(os.tmpdir(), 'firecracker-vms'),\n },\n lambdaMicrovm: {\n region: env.MICROVM_AWS_REGION ?? env.AWS_REGION,\n imageArn: env.MICROVM_IMAGE_ARN ?? '',\n stackImageArns: parseStackMap(env.MICROVM_STACK_IMAGE_ARNS),\n ingressConnectorArns: parseArnList(env.MICROVM_INGRESS_CONNECTORS),\n egressConnectorArns: parseArnList(env.MICROVM_EGRESS_CONNECTORS),\n executionRoleArn: env.MICROVM_EXECUTION_ROLE_ARN,\n // 0 disables auto-suspend; the sandbox drives pause/resume explicitly by default\n maxIdleSeconds: Number(env.MICROVM_MAX_IDLE_SECONDS ?? 900),\n suspendedDurationSeconds: Number(env.MICROVM_SUSPENDED_DURATION_SECONDS ?? 28_800),\n maximumDurationInSeconds: Number(env.MICROVM_MAX_DURATION_SECONDS ?? 28_800),\n // A real cold MicroVM boot can comfortably exceed the old 25s hardcoded default \u2014\n // must stay well under the api's own VM_CREATE ack timeout (see vm.service.ts).\n createTimeoutMs: Number(env.MICROVM_CREATE_TIMEOUT_MS ?? 60_000),\n },\n fargate: {\n region: env.FARGATE_AWS_REGION ?? env.AWS_REGION,\n cluster: env.FARGATE_CLUSTER ?? '',\n taskDefinition: env.FARGATE_TASK_DEFINITION,\n // Per-stack task definitions: \"node:builder-node:3,python:builder-python:1\"\n stackTaskDefinitions: parseStackMap(env.FARGATE_STACK_TASK_DEFS),\n subnets:\n env.FARGATE_SUBNETS?.split(',')\n .map((s) => s.trim())\n .filter(Boolean) ?? [],\n securityGroups: env.FARGATE_SECURITY_GROUPS?.split(',')\n .map((s) => s.trim())\n .filter(Boolean),\n // ENABLED when the worker runs outside the task VPC (proxies to the task's public IP)\n assignPublicIp: env.FARGATE_ASSIGN_PUBLIC_IP === 'true',\n guestPort: Number(env.FARGATE_GUEST_PORT) || 8080,\n startTimeoutMs: Number(env.FARGATE_START_TIMEOUT_MS) || 180_000,\n },\n docker: {\n bin: env.DOCKER_BIN ?? 'docker',\n // Local images from `scripts/setup-docker-images.sh`: <imagePrefix>-<stack>:<imageTag>\n imagePrefix: env.DOCKER_IMAGE_PREFIX ?? 'multiplayer-builder-vm',\n imageTag: env.DOCKER_IMAGE_TAG ?? 'local',\n stackImages: parseStackMap(env.DOCKER_STACK_IMAGES),\n network: env.DOCKER_NETWORK,\n portRangeStart: Number(env.DOCKER_PORT_MIN) || 9100,\n portRangeEnd: Number(env.DOCKER_PORT_MAX) || 9199,\n guestPort: Number(env.DOCKER_GUEST_PORT) || 8080,\n },\n dockerSandbox: {\n bin: env.SBX_BIN ?? 'sbx',\n // Bridged from the same local images `docker` (imagePrefix-imageTag) already uses \u2014\n // `docker save` + `sbx template load`, see docker-sandbox-executor.ts.\n imagePrefix: env.SBX_IMAGE_PREFIX ?? env.DOCKER_IMAGE_PREFIX ?? 'multiplayer-builder-vm',\n imageTag: env.SBX_IMAGE_TAG ?? env.DOCKER_IMAGE_TAG ?? 'local',\n stackTemplates: parseStackMap(env.SBX_STACK_TEMPLATES),\n // `sbx create shell` doesn't run the image's own CMD, so the engine launches\n // it explicitly \u2014 defaults match each Dockerfile's own WORKDIR /app + CMD.\n stackAgentCommands: {\n node: 'node app.js',\n python: 'python app.py',\n static: 'node app.js',\n ...parseStackMap(env.SBX_STACK_AGENT_COMMANDS),\n },\n workspaceRoot: env.SBX_WORKSPACE_DIR ?? path.join(os.tmpdir(), 'sbx-vms'),\n portRangeStart: Number(env.SBX_PORT_MIN) || 9200,\n portRangeEnd: Number(env.SBX_PORT_MAX) || 9299,\n guestPort: Number(env.SBX_GUEST_PORT) || 8080,\n // sbx rejects sandboxes below 1 GiB memory.\n minMemoryMib: Number(env.SBX_MIN_MEMORY_MIB) || 1024,\n },\n qemu: {\n bin: env.QEMU_BIN ?? 'qemu-system-aarch64',\n // Per-stack base images (<imagesDir>/<stack>/vmlinuz + initramfs.img) from\n // `worker-cli images pull` / setup-vm-images.sh; engine detection checks\n // existence, so missing images just disable the engine.\n imagesDir: env.QEMU_IMAGES_DIR ?? env.VM_IMAGES_DIR ?? defaultImagesDir(),\n // Explicit single-image override, applied to every stack when both are set\n kernelPath: env.QEMU_KERNEL,\n initrdPath: env.QEMU_INITRD,\n vmDataPath: env.QEMU_VM_DATA ?? path.join(os.tmpdir(), 'qemu-vms'),\n portRangeStart: Number(env.QEMU_PORT_MIN) || 9000,\n portRangeEnd: Number(env.QEMU_PORT_MAX) || 9999,\n // Accelerator: hvf (macOS host), kvm (Linux + /dev/kvm), tcg (software, any host \u2014 slow)\n accel: env.QEMU_ACCEL ?? (process.platform === 'darwin' ? 'hvf' : 'kvm'),\n // CPU model: host requires hvf/kvm; max is best for tcg on aarch64; qemu64 for tcg x86_64\n cpu: env.QEMU_CPU ?? 'host',\n // Machine type: virt (aarch64), q35 (x86_64)\n machine: env.QEMU_MACHINE ?? 'virt',\n },\n }\n}\n", "import fs from 'fs'\nimport os from 'os'\nimport path from 'path'\nimport { pipeline } from 'stream/promises'\nimport { Readable } from 'stream'\nimport { VM_STACKS, type VmStack } from '@multiplayer-app/builder-types'\n\n/** Files that make up one stack's base image (built by scripts/setup-vm-images.sh). */\nexport const IMAGE_FILES = ['vmlinuz', 'initramfs.img'] as const\n/** Stacks included in the published base-image catalog; `generic` remains a local fallback only. */\nexport const PUBLISHED_IMAGE_STACKS = VM_STACKS.filter((stack) => stack !== 'generic')\n\n/** Normalize Node's process.arch to the uname-style names used in image paths. */\nexport function hostArch(): string {\n switch (process.arch) {\n case 'arm64':\n return 'aarch64'\n case 'x64':\n return 'x86_64'\n default:\n return process.arch\n }\n}\n\n/** Default local image directory \u2014 the same location scripts/setup-vm-images.sh writes to. */\nexport function defaultImagesDir(arch: string = hostArch()): string {\n return path.join(os.homedir(), '.multiplayer', 'vm-images', arch)\n}\n\n/** Kernel + initrd for one stack under an images dir, or undefined if incomplete. */\nexport function resolveStackImages(\n imagesDir: string,\n stack: string,\n): { kernelPath: string; initrdPath: string } | undefined {\n const kernelPath = path.join(imagesDir, stack, 'vmlinuz')\n const initrdPath = path.join(imagesDir, stack, 'initramfs.img')\n return fs.existsSync(kernelPath) && fs.existsSync(initrdPath)\n ? { kernelPath, initrdPath }\n : undefined\n}\n\n/** Stacks that have a complete base image under an images dir. */\nexport function availableStacks(imagesDir: string): VmStack[] {\n return VM_STACKS.filter((stack) => resolveStackImages(imagesDir, stack) !== undefined)\n}\n\nexport interface ImageSourceOptions {\n /** s3://bucket[/prefix] or http(s):// base URL holding <arch>/<stack>/vmlinuz + initramfs.img */\n location: string\n arch: string\n /** Stacks to transfer (default: all known stacks). */\n stacks?: readonly string[]\n /** Custom S3 endpoint (MinIO, etc.); implies path-style addressing. */\n endpoint?: string\n}\n\nfunction parseS3Uri(uri: string): { bucket: string; prefix: string } {\n const match = /^s3:\\/\\/([^/]+)\\/?(.*)$/.exec(uri)\n if (!match) throw new Error(`invalid S3 URI \"${uri}\" \u2014 expected s3://bucket[/prefix]`)\n return { bucket: match[1], prefix: match[2].replace(/\\/+$/, '') }\n}\n\nfunction s3Key(prefix: string, arch: string, stack: string, file: string): string {\n return [prefix, arch, stack, file].filter(Boolean).join('/')\n}\n\nasync function makeS3Client(endpoint?: string) {\n const { S3Client } = await import('@aws-sdk/client-s3')\n return new S3Client({\n ...(endpoint\n ? {\n endpoint,\n forcePathStyle: true,\n // A custom endpoint means a local/self-hosted store (MinIO, etc.), not real AWS.\n // Use its own static credentials explicitly rather than the ambient default\n // provider chain \u2014 otherwise, whenever AWS_PROFILE is also set (e.g. for the\n // lambda-microvm engine's real AWS calls), the SDK unconditionally skips static env\n // credentials process-wide and sends the real AWS SSO session to this local store\n // instead, which rejects it since it only recognizes its own configured user.\n credentials: {\n accessKeyId: process.env.AWS_ACCESS_KEY_ID ?? 'minioadmin',\n secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY ?? 'minioadmin',\n },\n }\n : {}),\n ...(process.env.AWS_REGION ? {} : { region: 'us-east-1' }),\n // aws-chunked checksum streaming breaks older S3-compatible stores (MinIO)\n requestChecksumCalculation: 'WHEN_REQUIRED',\n })\n}\n\nasync function downloadFromS3(\n opts: ImageSourceOptions,\n stack: string,\n file: string,\n dest: string,\n): Promise<void> {\n const { GetObjectCommand } = await import('@aws-sdk/client-s3')\n const { bucket, prefix } = parseS3Uri(opts.location)\n const client = await makeS3Client(opts.endpoint)\n const key = s3Key(prefix, opts.arch, stack, file)\n const response = await client.send(new GetObjectCommand({ Bucket: bucket, Key: key }))\n if (!response.Body) throw new Error(`empty response for s3://${bucket}/${key}`)\n await pipeline(response.Body as Readable, fs.createWriteStream(dest))\n}\n\nasync function downloadFromHttp(\n opts: ImageSourceOptions,\n stack: string,\n file: string,\n dest: string,\n): Promise<void> {\n const url = `${opts.location.replace(/\\/+$/, '')}/${opts.arch}/${stack}/${file}`\n const response = await fetch(url)\n if (!response.ok || !response.body) {\n throw new Error(`GET ${url} failed: ${response.status} ${response.statusText}`)\n }\n await pipeline(\n Readable.fromWeb(response.body as import('stream/web').ReadableStream),\n fs.createWriteStream(dest),\n )\n}\n\n/** Download base images for the given stacks into destDir/<stack>/ (atomic per file via .partial rename). */\nexport async function pullImages(opts: ImageSourceOptions, destDir: string): Promise<string[]> {\n const isS3 = opts.location.startsWith('s3://')\n const downloaded: string[] = []\n\n for (const stack of opts.stacks ?? PUBLISHED_IMAGE_STACKS) {\n const stackDir = path.join(destDir, stack)\n fs.mkdirSync(stackDir, { recursive: true })\n for (const file of IMAGE_FILES) {\n const dest = path.join(stackDir, file)\n const partial = `${dest}.partial`\n if (isS3) await downloadFromS3(opts, stack, file, partial)\n else await downloadFromHttp(opts, stack, file, partial)\n fs.renameSync(partial, dest)\n downloaded.push(dest)\n }\n }\n return downloaded\n}\n\n/** Upload base images for the given stacks from srcDir/<stack>/ to s3://bucket[/prefix]/<arch>/<stack>/. */\nexport async function pushImages(opts: ImageSourceOptions, srcDir: string): Promise<string[]> {\n const { PutObjectCommand } = await import('@aws-sdk/client-s3')\n const { bucket, prefix } = parseS3Uri(opts.location)\n const client = await makeS3Client(opts.endpoint)\n const uploaded: string[] = []\n\n const stacks = opts.stacks ?? availableStacks(srcDir)\n if (!stacks.length) {\n throw new Error(`no stack images found under ${srcDir} \u2014 run scripts/setup-vm-images.sh first`)\n }\n\n for (const stack of stacks) {\n for (const file of IMAGE_FILES) {\n const src = path.join(srcDir, stack, file)\n if (!fs.existsSync(src)) {\n throw new Error(`${src} not found \u2014 run scripts/setup-vm-images.sh first`)\n }\n const key = s3Key(prefix, opts.arch, stack, file)\n // Buffer instead of stream: keeps Content-Length exact and avoids aws-chunked\n // encoding that older S3-compatible stores reject. Images are ~20-50 MB.\n await client.send(\n new PutObjectCommand({\n Bucket: bucket,\n Key: key,\n Body: fs.readFileSync(src),\n }),\n )\n uploaded.push(`s3://${bucket}/${key}`)\n }\n }\n return uploaded\n}\n", "import type { GatewayAccessConfig } from './access'\nimport type { VmUsage } from './vm-cost'\n\nexport const VM_STACKS = ['generic', 'node', 'python', 'static'] as const\nexport type VmStack = (typeof VM_STACKS)[number]\n\nexport const VM_ENGINES = [\n 'mock',\n 'qemu',\n 'firecracker',\n 'docker',\n 'docker-sandbox',\n 'remote',\n 'lambda-microvm',\n 'fargate',\n] as const\nexport type VmEngine = (typeof VM_ENGINES)[number]\n\n/** 'service': a persistent process the gateway proxies to. 'job': runs its entrypoint once and exits. */\nexport const VM_RUN_MODES = ['service', 'job'] as const\nexport type VmRunMode = (typeof VM_RUN_MODES)[number]\n\nexport type VmState =\n | 'creating'\n | 'running'\n | 'pausing'\n | 'paused'\n | 'resuming'\n | 'stopping'\n | 'stopped'\n | 'restoring'\n | 'destroying'\n | 'error'\n /** Job VM whose entrypoint exited with code 0. See VmRecord.result. */\n | 'completed'\n /** User-initiated teardown that keeps the record around (e.g. as deployment history) instead of deleting it. */\n | 'destroyed'\n\nexport const VM_ACTIONS = ['pause', 'resume', 'stop', 'restore'] as const\nexport type VmAction = (typeof VM_ACTIONS)[number]\n\nexport interface VmResources {\n vcpuCount: number\n memMib: number\n}\n\nexport interface VmRecord {\n vmId: string\n /** Account that created this VM \u2014 same convention as ReleaseRecord.accountId (req.accountId, never client-supplied). */\n accountId: string\n /** Builder session this VM belongs to; optional for VMs not tied to a session. */\n sessionId?: string\n workerId: string\n stack: VmStack\n /** Micro-VM engine the VM runs on. Absent on records created before engines existed. */\n engine?: VmEngine\n /** Release whose artifact the VM pulled and started at boot. */\n releaseId?: string\n /** Gateway-level access protection (Cloudflare Access-style login gate). */\n access?: GatewayAccessConfig\n resources: VmResources\n state: VmState\n /** 'service' (default) for a persistent proxied process, 'job' for a run-once script. */\n runMode: VmRunMode\n /** Custom environment variables for the guest entrypoint. */\n env?: Record<string, string>\n /** Set once a 'job' VM's entrypoint exits (state becomes 'completed' or 'error'). */\n result?: VmRunResult\n /**\n * Opaque, engine-specific data an executor needs to reattach to this VM after a worker\n * restart (e.g. a QEMU QMP socket path, a Fargate task ARN). Sandbox stores it as-is and\n * never interprets it \u2014 only the executor that created it knows the shape.\n */\n runtimeMetadata?: Record<string, unknown>\n /** Cumulative running-time/cost tracking, updated on every state transition. See vm-cost.ts. */\n usage?: VmUsage\n createdAt: string\n updatedAt: string\n}\n\nexport interface VmCreateRequest {\n /** Builder session to associate the VM with (not validated; informational for now). */\n sessionId?: string\n stack: VmStack\n /** Requested micro-VM engine. Omit to use the scheduled worker's default engine. */\n engine?: VmEngine\n /** Release to deploy into the VM: the guest pulls the artifact (presigned URL), unzips, and starts it. */\n releaseId?: string\n /** 'service' (default) keeps the entrypoint running and proxied; 'job' runs it once and exits. */\n runMode?: VmRunMode\n /** Custom environment variables for the guest entrypoint. */\n env?: Record<string, string>\n resources?: Partial<VmResources>\n}\n\nexport interface VmExecRequest {\n /** Shell command executed inside the VM workspace. */\n command: string\n /** Working directory relative to the VM workspace root. */\n cwd?: string\n /** Wall-clock limit for the command; capped by the executor. */\n timeoutMs?: number\n}\n\nexport interface VmExecResult {\n exitCode: number\n stdout: string\n stderr: string\n durationMs: number\n /** True when stdout/stderr were cut at the executor's output cap. */\n truncated: boolean\n /** True when the command was killed by the timeout. */\n timedOut: boolean\n}\n\n/** Outcome of a 'job' VM's entrypoint running to completion. */\nexport interface VmRunResult {\n exitCode: number\n stdout: string\n stderr: string\n /** True when stdout/stderr were cut at the executor's output cap. */\n truncated: boolean\n durationMs: number\n finishedAt: string\n}\n\nexport interface VmFileWrite {\n /** Path relative to the VM workspace root (no leading slash, no traversal). */\n path: string\n content: string\n /** How `content` is encoded; utf8 by default, base64 for binary files. */\n encoding?: 'utf8' | 'base64'\n}\n\nexport interface VmWriteFilesResult {\n written: Array<{ path: string; bytes: number }>\n}\n\nexport interface ProxyRequestDescriptor {\n method: string\n path: string\n headers: Record<string, string>\n body?: Buffer\n}\n\nexport interface ProxyResponseDescriptor {\n statusCode: number\n headers: Record<string, string>\n body?: Buffer\n}\n\nexport interface CommandResult {\n ok: boolean\n error?: string\n}\n\nexport interface CommandAck<T = unknown> extends CommandResult {\n result?: T\n}\n\nexport const VM_REDIS_KEY_PREFIX = 'vm:'\n\nexport interface VmRegistryEntry {\n workerId: string\n state: VmState\n access?: GatewayAccessConfig\n}\n", "import type { VmAction, VmRunResult } from './vm'\n\n// \u2500\u2500 Worker socket events (sandbox \u2194 worker) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Events exchanged on the worker socket (sandbox side listens, worker side emits \u2014 and vice versa). */\nexport const WorkerEvent = {\n // worker \u2192 sandbox\n HEARTBEAT: 'worker:heartbeat',\n\n // worker \u2192 sandbox, fire-and-forget like HEARTBEAT \u2014 sent once when a 'job' VM's\n // entrypoint exits on its own (the worker has already torn the resource down by then).\n VM_RUN_EXITED: 'vm:run-exited',\n\n // worker \u2192 sandbox after an asynchronous VM_CREATE finishes. Socket.IO acknowledgements\n // cannot be relied on across the detached Redis-adapter emitter used by the API.\n VM_CREATE_RESULT: 'vm:create-result',\n\n // worker \u2192 sandbox, fire-and-forget \u2014 sent when periodic reconciliation finds the\n // underlying resource gone without this worker ever issuing a destroy (e.g. AWS's own\n // idle-suspend/max-duration policies terminating a Lambda MicroVM). Only engines whose\n // VMs can disappear outside an explicit command from this process emit it.\n VM_EXTERNALLY_TERMINATED: 'vm:externally-terminated',\n\n // sandbox \u2192 worker, generated by the control plane and reused by this worker process\n // on Socket.IO reconnects. This keeps duplicate configured WORKER_ID values isolated.\n ASSIGNED_ID: 'worker:assigned-id',\n\n // sandbox \u2192 worker, once right after auth on every (re)connect \u2014 the VMs sandbox's\n // records say this workerId owns, so the worker can try to reattach before its first\n // heartbeat. Always sent, even with an empty array, as a handshake signal.\n REATTACH: 'worker:reattach',\n\n // sandbox \u2192 worker (VM lifecycle commands)\n VM_CREATE: 'vm:create',\n VM_PAUSE: 'vm:pause',\n VM_RESUME: 'vm:resume',\n VM_STOP: 'vm:stop',\n VM_RESTORE: 'vm:restore',\n VM_DESTROY: 'vm:destroy',\n\n // sandbox / gateway \u2192 worker (HTTP proxy)\n PROXY_HTTP: 'proxy:http',\n\n // sandbox \u2192 worker (guest workspace commands)\n VM_EXEC: 'vm:exec',\n VM_WRITE_FILES: 'vm:write-files',\n\n // worker \u2192 sandbox (VNC/terminal media relay)\n VNC_INIT: 'vnc:init',\n VNC_FRAME: 'vnc:frame',\n VNC_COPY_FRAME: 'vnc:copy-frame',\n TERMINAL_DATA: 'terminal:data',\n\n // sandbox \u2192 worker (browser input forwarded downstream)\n VNC_MOUSE: 'vnc:mouse',\n VNC_KEYBOARD: 'vnc:keyboard',\n TERMINAL_ATTACH: 'terminal:attach',\n TERMINAL_DETACH: 'terminal:detach',\n TERMINAL_INPUT: 'terminal:input',\n} as const\n\nexport type WorkerEventName = (typeof WorkerEvent)[keyof typeof WorkerEvent]\n\n/** Maps a VmAction to its worker socket event name. */\nexport const VM_ACTION_EVENTS: Record<VmAction, string> = {\n pause: WorkerEvent.VM_PAUSE,\n resume: WorkerEvent.VM_RESUME,\n stop: WorkerEvent.VM_STOP,\n restore: WorkerEvent.VM_RESTORE,\n}\n\n// \u2500\u2500 Console socket events (browser \u2194 sandbox /vm-console/ws) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Events on the browser-facing console Socket.io namespaces (/vnc and /terminal). */\nexport const ConsoleEvent = {\n // /vnc namespace: sandbox \u2192 browser\n VNC_INIT: 'init',\n VNC_FRAME: 'frame',\n VNC_COPY_FRAME: 'copy-frame',\n\n // /vnc namespace: browser \u2192 sandbox\n VNC_MOUSE: 'mouse',\n VNC_KEYBOARD: 'keyboard',\n\n // /terminal namespace: sandbox \u2194 browser\n TERMINAL_DATA: 'data',\n TERMINAL_INPUT: 'data',\n} as const\n\n// \u2500\u2500 Payload types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface VncInitPayload {\n vmId: string\n width: number\n height: number\n}\n\nexport interface VncFramePayload {\n vmId: string\n x: number\n y: number\n width: number\n height: number\n encoding: 'raw'\n data: Buffer\n}\n\nexport interface VncCopyFramePayload {\n vmId: string\n x: number\n y: number\n src: { x: number; y: number }\n width: number\n height: number\n}\n\nexport interface TerminalDataPayload {\n vmId: string\n data: Buffer\n}\n\nexport interface VncMousePayload {\n vmId: string\n x: number\n y: number\n button: number\n}\n\nexport interface VncKeyboardPayload {\n vmId: string\n keyCode: number\n isDown: boolean\n}\n\nexport interface TerminalInputPayload {\n vmId: string\n data: string\n}\n\nexport interface VmRunExitedPayload extends VmRunResult {\n vmId: string\n}\n\nexport interface VmCreateResultPayload {\n vmId: string\n ok: boolean\n metadata?: Record<string, unknown>\n error?: string\n}\n", "import bunyan, {\n type LoggerOptions,\n type LogLevelString,\n} from 'bunyan'\nimport { hostname } from 'os'\nimport {\n APP_NAME,\n LOG_LEVEL,\n} from './config'\n\nconst HOST_NAME = hostname()\n\nconst loggerOptions: LoggerOptions = {\n name: APP_NAME,\n level: LOG_LEVEL as LogLevelString,\n hostname: HOST_NAME,\n serializers: bunyan.stdSerializers,\n}\n\nexport const logger = bunyan.createLogger(loggerOptions)\n\n// const events = [\n// 'exit',\n// 'SIGINT',\n// 'SIGTERM',\n// 'uncaughtException',\n// ]\n\n// const exit = () => {\n// // logger.reopenFileStreams()\n// }\n\n// events.forEach(event => process.on(event, exit))\n", "export const NODE_ENV = process.env.NODE_ENV || 'development'\nexport const isProduction = NODE_ENV === 'production'\n// npm_package_name is only set when launched via `npm run`/`pnpm run` \u2014 production images start\n// services with a plain `node dist/index.js`, so APP_NAME must be set explicitly there.\nexport const APP_NAME =\n process.env.APP_NAME || process.env.npm_package_name?.split('/').pop() || 'unknown-app'\nexport const LOG_LEVEL = process.env.LOG_LEVEL || (isProduction ? 'info' : 'debug')\n", "import bunyan, { type LoggerOptions } from 'bunyan'\nimport { hostname } from 'os'\nimport { isProduction, APP_NAME } from './config'\n\nconst HOST_NAME = hostname()\n\nconst loggerOptions: LoggerOptions = {\n name: APP_NAME,\n level: isProduction ? 'info' : 'debug',\n hostname: HOST_NAME,\n}\n\nexport const KafkaJsLogCreator = (logLevelConverter: any) => (level: any) => {\n if (level) {\n loggerOptions.level = logLevelConverter(level)\n }\n const logger = bunyan.createLogger(loggerOptions)\n\n return ({ level, log }) => {\n const { message, ...extra } = log\n logger[logLevelConverter(level)]({\n extra,\n }, message)\n }\n}\n", "import { logger } from './logger'\n\nexport { middleware as loggerExpressMiddleware } from './middleware'\nexport { default as logError } from './log-error.decorator'\nexport { default as asyncLogError } from './log-error-async.decorator'\nexport * from './kafkajs-logger-creator'\nexport default logger\nexport * from './kafkajs-logger-creator'\n", "import { execFile } from 'child_process'\nimport fs from 'fs/promises'\nimport http from 'http'\nimport type { IncomingMessage, ServerResponse } from 'http'\nimport os from 'os'\nimport path from 'path'\nimport type { AddressInfo } from 'net'\nimport type {\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmExecRequest,\n VmExecResult,\n VmFileWrite,\n VmRunMode,\n VmRunResult,\n VmWriteFilesResult,\n} from '@multiplayer-app/builder-types'\nimport logger from '@multiplayer-app/logger'\nimport type { Executor, VmHandle, VmSpec } from './types'\n\nconst DEFAULT_EXEC_TIMEOUT_MS = 60_000\nconst MAX_EXEC_TIMEOUT_MS = 300_000\nconst MAX_OUTPUT_BYTES = 1024 * 1024\nconst MAX_FILE_BYTES = 5 * 1024 * 1024\n\nconst CONTENT_TYPES: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'text/javascript; charset=utf-8',\n '.mjs': 'text/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.png': 'image/png',\n '.txt': 'text/plain; charset=utf-8',\n '.md': 'text/plain; charset=utf-8',\n}\n\ninterface ManagedVm {\n handle: VmHandle\n server: http.Server\n port: number\n workspaceDir: string\n runMode: VmRunMode\n startedAt: number\n}\n\n/** ms until a mock 'job' VM synthesizes a completion result \u2014 short enough for tests to not stall. */\nconst MOCK_JOB_DURATION_MS = 250\n\n/** Resolve a workspace-relative path, rejecting escapes (\"../\", absolute paths). */\nfunction resolveWorkspacePath(workspaceDir: string, relativePath: string): string {\n const normalized = path.normalize(relativePath).replace(/^([/\\\\])+/, '')\n const resolved = path.resolve(workspaceDir, normalized)\n if (resolved !== workspaceDir && !resolved.startsWith(workspaceDir + path.sep)) {\n throw new Error(`Path escapes the VM workspace: ${relativePath}`)\n }\n return resolved\n}\n\n/**\n * Stand-in for a real microVM: serves the VM workspace directory over HTTP\n * (index.html fallback), playing the role of \"the app inside the VM\".\n */\nfunction startStandInServer(\n spec: VmSpec,\n workspaceDir: string,\n): Promise<{ server: http.Server; port: number }> {\n const server = http.createServer((req: IncomingMessage, res: ServerResponse) => {\n void (async () => {\n const requestPath = decodeURIComponent((req.url ?? '/').split('?')[0])\n const relative = requestPath === '/' ? 'index.html' : requestPath\n try {\n const filePath = resolveWorkspacePath(workspaceDir, relative)\n const content = await fs.readFile(filePath)\n res.writeHead(200, {\n 'content-type':\n CONTENT_TYPES[path.extname(filePath).toLowerCase()] ?? 'application/octet-stream',\n })\n res.end(content)\n } catch {\n res.writeHead(200, { 'content-type': 'text/plain' })\n res.end(\n `mock vm ${spec.vmId} (${spec.stack}) \u2014 session ${spec.sessionId} \u2014 ${req.method} ${req.url}\\n`,\n )\n }\n })()\n })\n\n return new Promise((resolve, reject) => {\n server.once('error', reject)\n server.listen(0, '127.0.0.1', () => {\n resolve({ server, port: (server.address() as AddressInfo).port })\n })\n })\n}\n\nexport class MockExecutor implements Executor {\n private readonly vms = new Map<string, ManagedVm>()\n private readonly exitHandlers = new Map<string, (result: VmRunResult) => void>()\n\n async create(spec: VmSpec): Promise<VmHandle> {\n const workspaceDir = await fs.mkdtemp(path.join(os.tmpdir(), `mock-vm-${spec.vmId}-`))\n const { server, port } = await startStandInServer(spec, workspaceDir)\n const handle: VmHandle = {\n vmId: spec.vmId,\n sessionId: spec.sessionId,\n stack: spec.stack,\n resources: spec.resources,\n running: true,\n // No real process to configure \u2014 just echoed back for introspection/tests.\n ...(spec.env ? { metadata: { env: spec.env } } : {}),\n }\n\n const runMode = spec.runMode ?? 'service'\n this.vms.set(spec.vmId, { handle, server, port, workspaceDir, runMode, startedAt: Date.now() })\n logger.info({ vmId: spec.vmId, port, workspaceDir, runMode }, 'mock vm created')\n return handle\n }\n\n /** No real process to watch \u2014 just synthesize a successful run shortly after create(). */\n onExit(vmId: string, handler: (result: VmRunResult) => void): void {\n const startedAt = this.vms.get(vmId)?.startedAt ?? Date.now()\n this.exitHandlers.set(vmId, handler)\n setTimeout(() => {\n void (async () => {\n const registered = this.exitHandlers.get(vmId)\n this.exitHandlers.delete(vmId)\n if (!registered) return\n\n const result: VmRunResult = {\n exitCode: 0,\n stdout: `mock job ${vmId} completed\\n`,\n stderr: '',\n truncated: false,\n durationMs: Date.now() - startedAt,\n finishedAt: new Date().toISOString(),\n }\n await this.destroy(vmId)\n registered(result)\n })()\n }, MOCK_JOB_DURATION_MS)\n }\n\n async pause(vmId: string): Promise<VmHandle> {\n return this.setRunning(vmId, false)\n }\n\n async resume(vmId: string): Promise<VmHandle> {\n return this.setRunning(vmId, true)\n }\n\n async stop(vmId: string): Promise<VmHandle> {\n return this.setRunning(vmId, false)\n }\n\n async restore(vmId: string): Promise<VmHandle> {\n return this.setRunning(vmId, true)\n }\n\n async destroy(vmId: string): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) return\n\n await new Promise<void>((resolve) => vm.server.close(() => resolve()))\n await fs.rm(vm.workspaceDir, { recursive: true, force: true })\n this.vms.delete(vmId)\n logger.info({ vmId }, 'mock vm destroyed')\n }\n\n get(vmId: string): VmHandle | undefined {\n return this.vms.get(vmId)?.handle\n }\n\n list(): VmHandle[] {\n return [...this.vms.values()].map((vm) => vm.handle)\n }\n\n async proxyHttp(vmId: string, request: ProxyRequestDescriptor): Promise<ProxyResponseDescriptor> {\n const vm = this.requireRunningVm(vmId)\n\n return new Promise((resolve, reject) => {\n const proxyReq = http.request(\n {\n host: '127.0.0.1',\n port: vm.port,\n method: request.method,\n path: request.path,\n headers: request.headers,\n },\n (proxyRes) => {\n const chunks: Buffer[] = []\n proxyRes.on('data', (chunk) => chunks.push(chunk))\n proxyRes.on('end', () => {\n resolve({\n statusCode: proxyRes.statusCode ?? 502,\n headers: Object.fromEntries(\n Object.entries(proxyRes.headers).map(([key, value]) => [\n key,\n Array.isArray(value) ? value.join(', ') : value ?? '',\n ]),\n ),\n body: Buffer.concat(chunks),\n })\n })\n },\n )\n\n proxyReq.on('error', reject)\n if (request.body) proxyReq.write(request.body)\n proxyReq.end()\n })\n }\n\n async writeFiles(vmId: string, files: VmFileWrite[]): Promise<VmWriteFilesResult> {\n const vm = this.requireRunningVm(vmId)\n const written: Array<{ path: string; bytes: number }> = []\n\n for (const file of files) {\n const buffer = Buffer.from(file.content, file.encoding === 'base64' ? 'base64' : 'utf8')\n if (buffer.byteLength > MAX_FILE_BYTES) {\n throw new Error(\n `File too large (${buffer.byteLength} bytes, max ${MAX_FILE_BYTES}): ${file.path}`,\n )\n }\n const filePath = resolveWorkspacePath(vm.workspaceDir, file.path)\n await fs.mkdir(path.dirname(filePath), { recursive: true })\n await fs.writeFile(filePath, buffer)\n written.push({ path: path.relative(vm.workspaceDir, filePath), bytes: buffer.byteLength })\n }\n\n logger.info({ vmId, files: written.length }, 'mock vm files written')\n return { written }\n }\n\n async exec(vmId: string, request: VmExecRequest): Promise<VmExecResult> {\n const vm = this.requireRunningVm(vmId)\n const cwd = request.cwd ? resolveWorkspacePath(vm.workspaceDir, request.cwd) : vm.workspaceDir\n const timeoutMs = Math.min(request.timeoutMs ?? DEFAULT_EXEC_TIMEOUT_MS, MAX_EXEC_TIMEOUT_MS)\n const startedAt = Date.now()\n\n return new Promise((resolve) => {\n execFile(\n '/bin/sh',\n ['-c', request.command],\n {\n cwd,\n timeout: timeoutMs,\n maxBuffer: MAX_OUTPUT_BYTES,\n env: { ...process.env, HOME: vm.workspaceDir },\n },\n (error, stdout, stderr) => {\n const failed = error as\n | (NodeJS.ErrnoException & { code?: number | string; killed?: boolean })\n | null\n const timedOut = Boolean(failed?.killed)\n const truncated = failed?.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER'\n resolve({\n exitCode: typeof failed?.code === 'number' ? failed.code : failed ? 1 : 0,\n stdout: stdout.slice(0, MAX_OUTPUT_BYTES),\n stderr: stderr.slice(0, MAX_OUTPUT_BYTES),\n durationMs: Date.now() - startedAt,\n truncated: Boolean(truncated),\n timedOut,\n })\n },\n )\n })\n }\n\n private requireRunningVm(vmId: string): ManagedVm {\n const vm = this.vms.get(vmId)\n if (!vm || !vm.handle.running) {\n throw new Error(`vm ${vmId} is not running`)\n }\n return vm\n }\n\n private setRunning(vmId: string, running: boolean): VmHandle {\n const vm = this.vms.get(vmId)\n if (!vm) throw new Error(`vm ${vmId} not found`)\n\n vm.handle = { ...vm.handle, running }\n return vm.handle\n }\n}\n", "import { spawn, type ChildProcess } from 'child_process'\nimport http from 'http'\nimport net from 'net'\nimport path from 'path'\nimport fs from 'fs/promises'\nimport os from 'os'\nimport logger from '@multiplayer-app/logger'\nimport type {\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmRecord,\n VmRunMode,\n VmRunResult,\n} from '@multiplayer-app/builder-types'\nimport { resolveStackImages } from '../images'\nimport type { Executor, VmHandle, VmSpec } from './types'\nimport { withTimeout } from './reattach-utils'\nimport { encodeEnvB64 } from './env-encoding'\n\nconst MAX_OUTPUT_BYTES = 1024 * 1024\n/** Printed by the guest init script (see scripts/setup-vm-images.sh) right before it powers off in job mode. */\nconst JOB_EXIT_SENTINEL = '__JOB_EXIT_CODE__:'\n\nexport interface QemuConfig {\n bin?: string\n /** Root of per-stack base images: <imagesDir>/<stack>/{vmlinuz,initramfs.img}. */\n imagesDir?: string\n /** Explicit single-image override; used for every stack when both are set. */\n kernelPath?: string\n initrdPath?: string\n vmDataPath?: string\n portRangeStart?: number\n portRangeEnd?: number\n vncBasePort?: number // base port for VNC displays (default 5900); display N \u2192 port vncBasePort+N\n serialBasePort?: number // base port for serial TCP (default 8000)\n accel?: string // 'hvf' (macOS), 'kvm' (Linux + /dev/kvm), 'tcg' (software, any host)\n cpu?: string // 'host' (hvf/kvm), 'max' (tcg aarch64), 'qemu64' (tcg x86_64)\n machine?: string // 'virt' (aarch64), 'q35' (x86_64)\n}\n\ninterface ManagedVm {\n handle: VmHandle\n // Absent after a reattach \u2014 the original ChildProcess object doesn't survive a worker\n // restart. Lifecycle control still works via QMP; destroy() falls back to killing `pid`.\n process?: ChildProcess\n pid?: number\n hostPort: number\n qmpSocketPath: string\n vncDisplay: number // QEMU display index (port = vncBasePort + vncDisplay)\n serialPort: number\n runMode: VmRunMode\n startedAt: number\n /** Job mode only: bounded capture of the serial console, scraped for JOB_EXIT_SENTINEL on exit. */\n serialBuffer?: { chunks: Buffer[]; bytes: number; socket: net.Socket }\n}\n\nexport class QemuExecutor implements Executor {\n private readonly vms = new Map<string, ManagedVm>()\n private readonly pendingResults = new Map<string, VmRunResult>()\n private readonly exitHandlers = new Map<string, (result: VmRunResult) => void>()\n private readonly usedHttpPorts = new Set<number>()\n private readonly usedDisplays = new Set<number>() // VNC display indices\n private readonly usedSerialPorts = new Set<number>()\n private readonly bin: string\n private readonly vmDataPath: string\n private readonly httpPortStart: number\n private readonly httpPortEnd: number\n private readonly vncBasePort: number\n private readonly serialBasePort: number\n private readonly accel: string\n private readonly cpu: string\n private readonly machine: string\n\n constructor(private readonly config: QemuConfig) {\n this.bin = config.bin ?? 'qemu-system-aarch64'\n this.vmDataPath = config.vmDataPath ?? path.join(os.tmpdir(), 'qemu-vms')\n this.httpPortStart = config.portRangeStart ?? 9000\n this.httpPortEnd = config.portRangeEnd ?? 9099\n this.vncBasePort = config.vncBasePort ?? 5900\n this.serialBasePort = config.serialBasePort ?? 8000\n this.accel = config.accel ?? 'hvf'\n this.cpu = config.cpu ?? 'host'\n this.machine = config.machine ?? 'virt'\n }\n\n private allocateHttpPort(): number {\n for (let p = this.httpPortStart; p <= this.httpPortEnd; p++) {\n if (!this.usedHttpPorts.has(p)) {\n this.usedHttpPorts.add(p)\n return p\n }\n }\n throw new Error('no free HTTP ports in QEMU port range')\n }\n\n private allocateVncDisplay(): number {\n for (let d = 1; d <= 99; d++) {\n if (!this.usedDisplays.has(d)) {\n this.usedDisplays.add(d)\n return d\n }\n }\n throw new Error('no free VNC displays')\n }\n\n private allocateSerialPort(): number {\n for (let p = this.serialBasePort; p <= this.serialBasePort + 99; p++) {\n if (!this.usedSerialPorts.has(p)) {\n this.usedSerialPorts.add(p)\n return p\n }\n }\n throw new Error('no free serial ports')\n }\n\n /** Explicit kernel/initrd override wins; otherwise the stack's base image, falling back to generic. */\n private resolveImages(stack: string): { kernelPath: string; initrdPath: string } {\n if (this.config.kernelPath && this.config.initrdPath) {\n return { kernelPath: this.config.kernelPath, initrdPath: this.config.initrdPath }\n }\n const resolved = this.config.imagesDir\n ? resolveStackImages(this.config.imagesDir, stack) ??\n resolveStackImages(this.config.imagesDir, 'generic')\n : undefined\n if (!resolved) {\n throw new Error(\n `no base image for stack \"${stack}\" under ${this.config.imagesDir} \u2014 run \"worker-cli images pull\"`,\n )\n }\n return resolved\n }\n\n async create(spec: VmSpec): Promise<VmHandle> {\n const { kernelPath, initrdPath } = this.resolveImages(spec.stack)\n const envB64 = encodeEnvB64(spec.env)\n const hostPort = this.allocateHttpPort()\n const vncDisplay = this.allocateVncDisplay()\n const serialPort = this.allocateSerialPort()\n const vncPort = this.vncBasePort + vncDisplay\n\n const vmDir = path.join(this.vmDataPath, spec.vmId)\n await fs.mkdir(vmDir, { recursive: true })\n const qmpSocketPath = path.join(vmDir, 'qmp.sock')\n\n const args = [\n '-machine',\n this.machine,\n '-cpu',\n this.cpu,\n '-accel',\n this.accel,\n '-smp',\n String(spec.resources.vcpuCount),\n '-m',\n String(spec.resources.memMib),\n '-kernel',\n kernelPath,\n '-initrd',\n initrdPath,\n // console=tty0 sends output to VGA framebuffer (VNC); ttyAMA0 to serial.\n // APP_URL_B64: base64-encoded presigned artifact URL \u2014 kernel cmdline params are\n // space-separated, so the raw URL (query string, &) can't be passed directly.\n '-append',\n [\n `console=tty0 console=ttyAMA0 net.ifnames=0 init=/init VM_ID=${spec.vmId} STACK=${spec.stack}`,\n spec.sessionId ? `SESSION_ID=${spec.sessionId}` : '',\n spec.appUrl ? `APP_URL_B64=${Buffer.from(spec.appUrl).toString('base64')}` : '',\n spec.runMode === 'job' ? 'RUN_MODE=job' : '',\n envB64 ? `ENV_B64=${envB64}` : '',\n ]\n .filter(Boolean)\n .join(' '),\n // Networking\n '-netdev',\n `user,id=net0,hostfwd=tcp::${hostPort}-:8080`,\n '-device',\n 'virtio-net-pci,netdev=net0',\n // Display: virtio-gpu-pci works on both aarch64 and x86_64; virtio-vga is x86-only\n '-device',\n 'virtio-gpu-pci',\n '-display',\n 'none',\n '-vnc',\n `127.0.0.1:${vncDisplay}`,\n // Serial console via TCP (xterm.js connects here)\n '-serial',\n `tcp:127.0.0.1:${serialPort},server,nowait`,\n // Control\n '-no-reboot',\n '-qmp',\n `unix:${qmpSocketPath},server,nowait`,\n ]\n\n logger.info({ vmId: spec.vmId, bin: this.bin, args }, 'spawning qemu')\n const proc = spawn(this.bin, args, { stdio: ['ignore', 'pipe', 'pipe'] })\n proc.stdout?.on('data', (d: Buffer) => logger.info({ vmId: spec.vmId }, d.toString().trimEnd()))\n proc.stderr?.on('data', (d: Buffer) =>\n logger.error({ vmId: spec.vmId }, d.toString().trimEnd()),\n )\n const runMode = spec.runMode ?? 'service'\n const startedAt = Date.now()\n proc.on('exit', (code, signal) => {\n const log = code === 0 || code === null ? logger.info.bind(logger) : logger.error.bind(logger)\n log({ vmId: spec.vmId, code, signal }, 'qemu process exited')\n const vm = this.vms.get(spec.vmId)\n if (!vm) return\n\n this.usedHttpPorts.delete(vm.hostPort)\n this.usedDisplays.delete(vm.vncDisplay)\n this.usedSerialPorts.delete(vm.serialPort)\n\n if (vm.runMode === 'job') {\n // Keep the map entry (marked not-running) until onExit() claims the result \u2014 see\n // docker-executor's deliverJobResult comment for why route() needs get() to still work.\n vm.handle = { ...vm.handle, running: false }\n this.reportJobResult(spec.vmId, vm)\n } else {\n this.vms.delete(spec.vmId)\n }\n })\n\n const metadata = { hostPort, qmpSocketPath, vncDisplay, serialPort, pid: proc.pid }\n const handle: VmHandle = {\n vmId: spec.vmId,\n sessionId: spec.sessionId,\n stack: spec.stack,\n resources: spec.resources,\n running: true,\n vncPort,\n serialPort,\n metadata,\n }\n\n const vm: ManagedVm = {\n handle,\n process: proc,\n pid: proc.pid,\n hostPort,\n qmpSocketPath,\n vncDisplay,\n serialPort,\n runMode,\n startedAt,\n }\n this.vms.set(spec.vmId, vm)\n if (runMode === 'job') vm.serialBuffer = connectSerialBuffer(serialPort)\n\n await waitForQmp(qmpSocketPath)\n // QMP only proves the QEMU process itself booted \u2014 the guest still has to boot its\n // kernel, bring up networking, pull+unpack the release artifact, and start the\n // entrypoint before anything answers on the forwarded port. A job's entrypoint may\n // finish before it ever answers HTTP, so the readiness gate only applies to services\n // (mirrors FirecrackerExecutor's own waitForHttp call).\n if (runMode !== 'job') await waitForHttp('127.0.0.1', hostPort)\n logger.info({ vmId: spec.vmId, hostPort, vncPort, serialPort, runMode }, 'qemu vm ready')\n return handle\n }\n\n /** Scrapes JOB_EXIT_SENTINEL out of the buffered serial console and reports the result. */\n private reportJobResult(vmId: string, vm: ManagedVm): void {\n vm.serialBuffer?.socket.destroy()\n const output = Buffer.concat(vm.serialBuffer?.chunks ?? []).toString('utf8')\n const sentinelIndex = output.lastIndexOf(JOB_EXIT_SENTINEL)\n const exitCode =\n sentinelIndex === -1\n ? 1\n : Number.parseInt(output.slice(sentinelIndex + JOB_EXIT_SENTINEL.length), 10) || 0\n const stdout = sentinelIndex === -1 ? output : output.slice(0, sentinelIndex)\n\n const result: VmRunResult = {\n exitCode,\n stdout: stdout.slice(0, MAX_OUTPUT_BYTES),\n stderr: '',\n truncated: (vm.serialBuffer?.bytes ?? 0) > MAX_OUTPUT_BYTES,\n durationMs: Date.now() - vm.startedAt,\n finishedAt: new Date().toISOString(),\n }\n logger.info({ vmId, exitCode }, 'qemu job vm exited')\n this.deliverJobResult(vmId, result)\n }\n\n private deliverJobResult(vmId: string, result: VmRunResult): void {\n const handler = this.exitHandlers.get(vmId)\n if (handler) {\n this.exitHandlers.delete(vmId)\n this.vms.delete(vmId)\n handler(result)\n } else {\n this.pendingResults.set(vmId, result)\n }\n }\n\n onExit(vmId: string, handler: (result: VmRunResult) => void): void {\n const pending = this.pendingResults.get(vmId)\n if (pending) {\n this.pendingResults.delete(vmId)\n this.vms.delete(vmId)\n handler(pending)\n return\n }\n this.exitHandlers.set(vmId, handler)\n }\n\n async pause(vmId: string): Promise<VmHandle> {\n await this.qmp(vmId, 'stop')\n return this.setRunning(vmId, false)\n }\n\n async resume(vmId: string): Promise<VmHandle> {\n await this.qmp(vmId, 'cont')\n return this.setRunning(vmId, true)\n }\n\n async stop(vmId: string): Promise<VmHandle> {\n await this.qmp(vmId, 'stop')\n return this.setRunning(vmId, false)\n }\n\n async restore(vmId: string): Promise<VmHandle> {\n await this.qmp(vmId, 'cont')\n return this.setRunning(vmId, true)\n }\n\n async destroy(vmId: string): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) return\n\n try {\n await this.qmp(vmId, 'quit')\n } catch {\n this.killVm(vm)\n }\n\n if (vm.process) {\n const proc = vm.process\n await new Promise<void>((resolve) => {\n if (proc.exitCode !== null) return resolve()\n proc.once('exit', resolve)\n setTimeout(() => {\n this.killVm(vm)\n resolve()\n }, 3_000)\n })\n } else {\n // Reattached VM \u2014 no live ChildProcess to wait on. QMP quit was already requested\n // above; give it a moment, then fall back to killing by pid.\n await new Promise((resolve) => setTimeout(resolve, 1_000))\n this.killVm(vm)\n }\n\n this.usedHttpPorts.delete(vm.hostPort)\n this.usedDisplays.delete(vm.vncDisplay)\n this.usedSerialPorts.delete(vm.serialPort)\n this.vms.delete(vmId)\n await fs.rm(path.join(this.vmDataPath, vmId), { recursive: true, force: true })\n logger.info({ vmId }, 'qemu vm destroyed')\n }\n\n get(vmId: string): VmHandle | undefined {\n return this.vms.get(vmId)?.handle\n }\n\n list(): VmHandle[] {\n return [...this.vms.values()].map((v) => v.handle)\n }\n\n /**\n * Recover a QEMU VM after a worker restart: the process may well have survived (it's not\n * killed just because its Node parent exited), so probe its QMP socket \u2014 if it answers,\n * lifecycle control and HTTP proxying resume normally. There's no live ChildProcess to\n * reattach to, so destroy() falls back to killing the stored pid.\n */\n async reattach(record: VmRecord): Promise<VmHandle | undefined> {\n const meta = record.runtimeMetadata as\n | {\n hostPort?: number\n qmpSocketPath?: string\n vncDisplay?: number\n serialPort?: number\n pid?: number\n }\n | undefined\n if (\n !meta?.qmpSocketPath ||\n meta.hostPort === undefined ||\n meta.vncDisplay === undefined ||\n meta.serialPort === undefined\n ) {\n return undefined\n }\n\n try {\n await withTimeout(sendQmpCommand(meta.qmpSocketPath, 'query-status'), 5_000)\n } catch {\n return undefined\n }\n\n const handle: VmHandle = {\n vmId: record.vmId,\n sessionId: record.sessionId,\n stack: record.stack,\n resources: record.resources,\n running: record.state === 'running',\n vncPort: this.vncBasePort + meta.vncDisplay,\n serialPort: meta.serialPort,\n metadata: meta,\n }\n\n this.usedHttpPorts.add(meta.hostPort)\n this.usedDisplays.add(meta.vncDisplay)\n this.usedSerialPorts.add(meta.serialPort)\n this.vms.set(record.vmId, {\n handle,\n pid: meta.pid,\n hostPort: meta.hostPort,\n qmpSocketPath: meta.qmpSocketPath,\n vncDisplay: meta.vncDisplay,\n serialPort: meta.serialPort,\n runMode: record.runMode,\n startedAt: Date.parse(record.createdAt) || Date.now(),\n })\n\n // Note: a job VM that finished (or is still running) while this worker was offline has\n // no recoverable path here \u2014 the serial buffer only ever lived in the dead worker's\n // memory, and if the guest already powered off the QMP probe above would have failed and\n // returned undefined before reaching this point (reported as \"resource no longer exists\"\n // by MultiEngineExecutor.reattachAll). A still-running job just resumes being watched\n // normally below via the QMP-confirmed process.\n\n logger.info({ vmId: record.vmId }, 'qemu vm reattached')\n return handle\n }\n\n private killVm(vm: ManagedVm): void {\n if (vm.process) {\n vm.process.kill('SIGKILL')\n return\n }\n if (vm.pid) {\n try {\n process.kill(vm.pid, 'SIGKILL')\n } catch {\n /* already gone */\n }\n }\n }\n\n async proxyHttp(vmId: string, request: ProxyRequestDescriptor): Promise<ProxyResponseDescriptor> {\n const vm = this.vms.get(vmId)\n if (!vm?.handle.running) throw new Error(`vm ${vmId} is not running`)\n\n const { default: http } = await import('http')\n return new Promise((resolve, reject) => {\n const req = http.request(\n {\n host: '127.0.0.1',\n port: vm.hostPort,\n method: request.method,\n path: request.path,\n headers: request.headers,\n },\n (res) => {\n const chunks: Buffer[] = []\n res.on('data', (c: Buffer) => chunks.push(c))\n res.on('end', () =>\n resolve({\n statusCode: res.statusCode ?? 502,\n headers: Object.fromEntries(\n Object.entries(res.headers).map(([k, v]) => [\n k,\n Array.isArray(v) ? v.join(', ') : v ?? '',\n ]),\n ),\n body: Buffer.concat(chunks),\n }),\n )\n },\n )\n req.on('error', reject)\n if (request.body) req.write(request.body)\n req.end()\n })\n }\n\n private setRunning(vmId: string, running: boolean): VmHandle {\n const vm = this.vms.get(vmId)\n if (!vm) throw new Error(`vm ${vmId} not found`)\n vm.handle = { ...vm.handle, running }\n return vm.handle\n }\n\n private async qmp(vmId: string, execute: string): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) throw new Error(`vm ${vmId} not found`)\n await sendQmpCommand(vm.qmpSocketPath, execute)\n }\n}\n\n/**\n * Opens our own client connection to the serial TCP port (QEMU holds it open as a server,\n * `nowait`) purely to capture a job's output \u2014 independent of whether a browser is also\n * watching live via SerialRelay/getSerialSource.\n */\nfunction connectSerialBuffer(port: number): {\n chunks: Buffer[]\n bytes: number\n socket: net.Socket\n} {\n const buffer = {\n chunks: [] as Buffer[],\n bytes: 0,\n socket: net.connect({ host: '127.0.0.1', port }),\n }\n buffer.socket.on('data', (chunk: Buffer) => {\n if (buffer.bytes >= MAX_OUTPUT_BYTES) return\n buffer.chunks.push(chunk)\n buffer.bytes += chunk.byteLength\n })\n buffer.socket.on('error', () => {\n /* best-effort capture \u2014 a dropped connection just means a shorter log, not a failure */\n })\n return buffer\n}\n\nfunction waitForQmp(socketPath: string, timeoutMs = 30_000): Promise<void> {\n return new Promise((resolve, reject) => {\n const deadline = Date.now() + timeoutMs\n const attempt = () => {\n if (Date.now() > deadline)\n return reject(new Error(`timed out waiting for QMP socket at ${socketPath}`))\n const sock = net.createConnection(socketPath)\n sock.once('connect', () => {\n sock.destroy()\n resolve()\n })\n sock.once('error', () => setTimeout(attempt, 500))\n }\n attempt()\n })\n}\n\n/** Mirrors FirecrackerExecutor's own waitForHttp \u2014 any non-5xx response proves something is listening. */\nfunction waitForHttp(host: string, port: number, timeoutMs = 60_000): Promise<void> {\n return new Promise((resolve, reject) => {\n const deadline = Date.now() + timeoutMs\n const attempt = () => {\n if (Date.now() > deadline)\n return reject(new Error(`timed out waiting for HTTP at ${host}:${port}`))\n const req = http.get(`http://${host}:${port}/health`, (res) => {\n if (res.statusCode && res.statusCode < 500) return resolve()\n res.resume()\n setTimeout(attempt, 1_000)\n })\n req.on('error', () => setTimeout(attempt, 1_000))\n req.setTimeout(2_000, () => {\n req.destroy()\n setTimeout(attempt, 1_000)\n })\n }\n attempt()\n })\n}\n\nasync function sendQmpCommand(socketPath: string, execute: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const sock = net.createConnection(socketPath)\n let buf = ''\n let ready = false\n const send = (obj: object) => sock.write(JSON.stringify(obj) + '\\r\\n')\n\n sock.on('data', (data: Buffer) => {\n buf += data.toString()\n let idx: number\n while ((idx = buf.indexOf('\\n')) !== -1) {\n const line = buf.slice(0, idx).trim()\n buf = buf.slice(idx + 1)\n if (!line) continue\n let msg: Record<string, unknown>\n try {\n msg = JSON.parse(line)\n } catch {\n continue\n }\n\n if (msg['QMP']) {\n send({ execute: 'qmp_capabilities' })\n } else if (!ready && 'return' in msg) {\n ready = true\n send({ execute })\n } else if (ready && 'return' in msg) {\n sock.destroy()\n resolve()\n } else if (msg['error']) {\n sock.destroy()\n reject(new Error(`QMP error for \"${execute}\": ${JSON.stringify(msg['error'])}`))\n }\n }\n })\n\n sock.on('error', (e) => {\n if (execute === 'quit') resolve()\n else reject(e)\n })\n sock.on('close', () => resolve())\n })\n}\n", "/** Bounds a reattach probe so one unresponsive socket can't hang the whole `reattachAll` batch. */\nexport function withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n return Promise.race([\n promise,\n new Promise<never>((_, reject) => setTimeout(() => reject(new Error(`timed out after ${ms}ms`)), ms)),\n ])\n}\n", "/**\n * Encodes a custom env var map into the single kernel-cmdline param QEMU/Firecracker guests\n * decode at boot (see the `ENV_B64=*` case in scripts/setup-vm-images.sh's init script).\n * The cmdline is space-delimited with no quoting, so raw `KEY=value with spaces` pairs can't\n * go directly on it (same reason APP_URL is base64-encoded as APP_URL_B64) \u2014 instead the\n * whole map is newline-joined and base64'd into one opaque param.\n */\nexport function encodeEnvB64(env: Record<string, string> | undefined): string | undefined {\n if (!env || Object.keys(env).length === 0) return undefined\n const lines = Object.entries(env)\n .map(([key, value]) => `${key}=${value}`)\n .join('\\n')\n return Buffer.from(lines).toString('base64')\n}\n", "import { spawn, type ChildProcess } from 'child_process'\nimport { exec } from 'child_process'\nimport { promisify } from 'util'\nimport http from 'http'\nimport net from 'net'\nimport path from 'path'\nimport fs from 'fs/promises'\nimport os from 'os'\nimport logger from '@multiplayer-app/logger'\nimport type {\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmRecord,\n VmRunMode,\n VmRunResult,\n} from '@multiplayer-app/builder-types'\nimport { resolveStackImages } from '../images'\nimport type { Executor, SerialSource, VmHandle, VmSpec } from './types'\nimport { withTimeout } from './reattach-utils'\nimport { encodeEnvB64 } from './env-encoding'\n\nconst execAsync = promisify(exec)\n\nconst MAX_OUTPUT_BYTES = 1024 * 1024\n/** Printed by the guest init script (see scripts/setup-vm-images.sh) right before it powers off in job mode. */\nconst JOB_EXIT_SENTINEL = '__JOB_EXIT_CODE__:'\n\nexport interface FirecrackerConfig {\n bin?: string // default: 'firecracker'\n /** Root of per-stack base images: <imagesDir>/<stack>/{vmlinuz,initramfs.img}. */\n imagesDir?: string\n /** Explicit single-image override (vmlinux/bzImage + cpio.gz); used for every stack when both are set. */\n kernelPath?: string\n initrdPath?: string\n vmDataPath?: string // default: /tmp/firecracker-vms\n}\n\ninterface ManagedVm {\n handle: VmHandle\n // Absent after a reattach \u2014 the original ChildProcess object doesn't survive a worker\n // restart. Lifecycle control and HTTP proxying still work via the API socket; the serial\n // console (piped over this process's inherited stdio) does not \u2014 see getSerialSource().\n process?: ChildProcess\n pid?: number\n apiSocketPath: string\n tapName: string\n subnet: number\n guestIp: string\n runMode: VmRunMode\n startedAt: number\n /** Job mode only: bounded capture of the guest's serial stdout, scraped for JOB_EXIT_SENTINEL on exit. */\n serialBuffer?: { chunks: Buffer[]; bytes: number }\n}\n\nexport class FirecrackerExecutor implements Executor {\n private readonly vms = new Map<string, ManagedVm>()\n private readonly usedSubnets = new Set<number>()\n private readonly pendingResults = new Map<string, VmRunResult>()\n private readonly exitHandlers = new Map<string, (result: VmRunResult) => void>()\n private tapCounter = 0\n private readonly bin: string\n private readonly vmDataPath: string\n private networkReady = false\n\n constructor(private readonly config: FirecrackerConfig) {\n this.bin = config.bin ?? 'firecracker'\n this.vmDataPath = config.vmDataPath ?? path.join(os.tmpdir(), 'firecracker-vms')\n }\n\n private allocateSubnet(): number {\n for (let s = 1; s <= 254; s++) {\n if (!this.usedSubnets.has(s)) {\n this.usedSubnets.add(s)\n return s\n }\n }\n throw new Error('no free TAP subnets (max 254 concurrent VMs)')\n }\n\n // Called once before the first VM; sets up host-level IP forwarding + masquerade.\n private async ensureNetworking(): Promise<void> {\n if (this.networkReady) return\n await execAsync('sysctl -w net.ipv4.ip_forward=1')\n const alreadySet = await execAsync(\n 'iptables -t nat -C POSTROUTING -s 172.16.0.0/12 ! -d 172.16.0.0/12 -j MASQUERADE',\n ).catch(() => null)\n if (!alreadySet) {\n await execAsync(\n 'iptables -t nat -A POSTROUTING -s 172.16.0.0/12 ! -d 172.16.0.0/12 -j MASQUERADE',\n )\n }\n this.networkReady = true\n }\n\n /** Explicit kernel/initrd override wins; otherwise the stack's base image, falling back to generic. */\n private resolveImages(stack: string): { kernelPath: string; initrdPath: string } {\n if (this.config.kernelPath && this.config.initrdPath) {\n return { kernelPath: this.config.kernelPath, initrdPath: this.config.initrdPath }\n }\n const resolved = this.config.imagesDir\n ? resolveStackImages(this.config.imagesDir, stack) ??\n resolveStackImages(this.config.imagesDir, 'generic')\n : undefined\n if (!resolved) {\n throw new Error(\n `no base image for stack \"${stack}\" under ${this.config.imagesDir} \u2014 run \"worker-cli images pull\"`,\n )\n }\n return resolved\n }\n\n async create(spec: VmSpec): Promise<VmHandle> {\n const { kernelPath, initrdPath } = this.resolveImages(spec.stack)\n await this.ensureNetworking()\n\n const subnet = this.allocateSubnet()\n const tapName = `fctap${++this.tapCounter}`\n const hostIp = `172.16.${subnet}.1`\n const guestIp = `172.16.${subnet}.2`\n\n const vmDir = path.join(this.vmDataPath, spec.vmId)\n await fs.mkdir(vmDir, { recursive: true })\n const apiSocketPath = path.join(vmDir, 'api.sock')\n await fs.rm(apiSocketPath, { force: true })\n\n // TAP device wired to this VM's Firecracker process\n await execAsync(`ip tuntap add dev ${tapName} mode tap`)\n await execAsync(`ip addr add ${hostIp}/30 dev ${tapName}`)\n await execAsync(`ip link set ${tapName} up`)\n\n const runMode = spec.runMode ?? 'service'\n const envB64 = encodeEnvB64(spec.env)\n const startedAt = Date.now()\n const serialBuffer = runMode === 'job' ? { chunks: [] as Buffer[], bytes: 0 } : undefined\n\n // stdin is piped so terminal input can be written to the guest's ttyS0 console\n const proc = spawn(this.bin, ['--api-sock', apiSocketPath], {\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n proc.stdout?.on('data', (d: Buffer) => {\n logger.debug({ vmId: spec.vmId }, d.toString().trimEnd())\n if (serialBuffer && serialBuffer.bytes < MAX_OUTPUT_BYTES) {\n serialBuffer.chunks.push(d)\n serialBuffer.bytes += d.byteLength\n }\n })\n proc.stderr?.on('data', (d: Buffer) =>\n logger.debug({ vmId: spec.vmId }, d.toString().trimEnd()),\n )\n proc.on('exit', (code, signal) => {\n logger.info({ vmId: spec.vmId, code, signal }, 'firecracker process exited')\n const vm = this.vms.get(spec.vmId)\n if (vm) {\n this.usedSubnets.delete(vm.subnet)\n if (vm.runMode === 'job') {\n // Keep the map entry (marked not-running) until onExit() claims the result \u2014 see\n // docker-executor's deliverJobResult comment for why route() needs get() to work.\n vm.handle = { ...vm.handle, running: false }\n this.reportJobResult(spec.vmId, vm)\n } else {\n this.vms.delete(spec.vmId)\n }\n }\n execAsync(`ip link del ${tapName}`).catch(() => {})\n })\n\n await waitForSocket(apiSocketPath)\n\n const macHex = (n: number) => n.toString(16).padStart(2, '0')\n await fcRequest(apiSocketPath, 'PUT', '/machine-config', {\n vcpu_count: spec.resources.vcpuCount,\n mem_size_mib: spec.resources.memMib,\n })\n await fcRequest(apiSocketPath, 'PUT', '/boot-source', {\n kernel_image_path: kernelPath,\n initrd_path: initrdPath,\n boot_args: [\n 'console=ttyS0',\n 'reboot=k',\n 'panic=1',\n 'pci=off',\n 'net.ifnames=0',\n 'init=/init',\n `VM_ID=${spec.vmId}`,\n ...(spec.sessionId ? [`SESSION_ID=${spec.sessionId}`] : []),\n `STACK=${spec.stack}`,\n // base64: kernel cmdline is space-separated, raw presigned URLs are not safe\n ...(spec.appUrl ? [`APP_URL_B64=${Buffer.from(spec.appUrl).toString('base64')}`] : []),\n `GUEST_IP=${guestIp}`,\n `HOST_IP=${hostIp}`,\n ...(runMode === 'job' ? ['RUN_MODE=job'] : []),\n ...(envB64 ? [`ENV_B64=${envB64}`] : []),\n ].join(' '),\n })\n await fcRequest(apiSocketPath, 'PUT', '/network-interfaces/eth0', {\n iface_id: 'eth0',\n // AA = locally-administered unicast; encode subnet as last two bytes\n guest_mac: `AA:FC:00:00:${macHex(subnet >> 8)}:${macHex(subnet & 0xff)}`,\n host_dev_name: tapName,\n })\n await fcRequest(apiSocketPath, 'PUT', '/actions', { action_type: 'InstanceStart' })\n\n // A job's entrypoint may finish before it ever answers HTTP \u2014 the readiness gate below\n // only applies to persistent services.\n if (runMode !== 'job') await waitForHttp(guestIp, 8080)\n\n const metadata = { apiSocketPath, tapName, subnet, guestIp, pid: proc.pid }\n const handle: VmHandle = {\n vmId: spec.vmId,\n sessionId: spec.sessionId,\n stack: spec.stack,\n resources: spec.resources,\n running: true,\n metadata,\n }\n this.vms.set(spec.vmId, {\n handle,\n process: proc,\n pid: proc.pid,\n apiSocketPath,\n tapName,\n subnet,\n guestIp,\n runMode,\n startedAt,\n serialBuffer,\n })\n logger.info({ vmId: spec.vmId, guestIp, tapName, runMode }, 'firecracker vm ready')\n return handle\n }\n\n /** Scrapes JOB_EXIT_SENTINEL out of the buffered serial stdout and reports the result. */\n private reportJobResult(vmId: string, vm: ManagedVm): void {\n const output = Buffer.concat(vm.serialBuffer?.chunks ?? []).toString('utf8')\n const sentinelIndex = output.lastIndexOf(JOB_EXIT_SENTINEL)\n const exitCode =\n sentinelIndex === -1\n ? 1\n : Number.parseInt(output.slice(sentinelIndex + JOB_EXIT_SENTINEL.length), 10) || 0\n const stdout = sentinelIndex === -1 ? output : output.slice(0, sentinelIndex)\n\n const result: VmRunResult = {\n exitCode,\n stdout: stdout.slice(0, MAX_OUTPUT_BYTES),\n stderr: '',\n truncated: (vm.serialBuffer?.bytes ?? 0) > MAX_OUTPUT_BYTES,\n durationMs: Date.now() - vm.startedAt,\n finishedAt: new Date().toISOString(),\n }\n logger.info({ vmId, exitCode }, 'firecracker job vm exited')\n this.deliverJobResult(vmId, result)\n }\n\n private deliverJobResult(vmId: string, result: VmRunResult): void {\n const handler = this.exitHandlers.get(vmId)\n if (handler) {\n this.exitHandlers.delete(vmId)\n this.vms.delete(vmId)\n handler(result)\n } else {\n this.pendingResults.set(vmId, result)\n }\n }\n\n onExit(vmId: string, handler: (result: VmRunResult) => void): void {\n const pending = this.pendingResults.get(vmId)\n if (pending) {\n this.pendingResults.delete(vmId)\n this.vms.delete(vmId)\n handler(pending)\n return\n }\n this.exitHandlers.set(vmId, handler)\n }\n\n async pause(vmId: string): Promise<VmHandle> {\n await this.patchVmState(vmId, 'Paused')\n return this.setRunning(vmId, false)\n }\n\n async resume(vmId: string): Promise<VmHandle> {\n await this.patchVmState(vmId, 'Resumed')\n return this.setRunning(vmId, true)\n }\n\n async stop(vmId: string): Promise<VmHandle> {\n await this.patchVmState(vmId, 'Paused')\n return this.setRunning(vmId, false)\n }\n\n async restore(vmId: string): Promise<VmHandle> {\n await this.patchVmState(vmId, 'Resumed')\n return this.setRunning(vmId, true)\n }\n\n async destroy(vmId: string): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) return\n\n if (vm.process) {\n const proc = vm.process\n proc.kill('SIGKILL')\n await new Promise<void>((resolve) => {\n if (proc.exitCode !== null) return resolve()\n proc.once('exit', resolve)\n setTimeout(() => {\n proc.kill('SIGKILL')\n resolve()\n }, 3_000)\n })\n } else if (vm.pid) {\n // Reattached VM \u2014 no live ChildProcess to wait on; kill by the stored pid.\n try {\n process.kill(vm.pid, 'SIGKILL')\n } catch {\n /* already gone */\n }\n }\n\n this.usedSubnets.delete(vm.subnet)\n this.vms.delete(vmId)\n await execAsync(`ip link del ${vm.tapName}`).catch(() => {})\n await fs.rm(path.join(this.vmDataPath, vmId), { recursive: true, force: true })\n logger.info({ vmId }, 'firecracker vm destroyed')\n }\n\n get(vmId: string): VmHandle | undefined {\n return this.vms.get(vmId)?.handle\n }\n\n getSerialSource(vmId: string): SerialSource | undefined {\n const vm = this.vms.get(vmId)\n // Serial is piped over the child's inherited stdio \u2014 a reattached VM has no live\n // ChildProcess to read that from, so its serial console is unavailable until it's\n // recreated. Lifecycle control and HTTP proxying are unaffected.\n if (!vm?.process) return undefined\n return { type: 'pipe', process: vm.process }\n }\n\n list(): VmHandle[] {\n return [...this.vms.values()].map((v) => v.handle)\n }\n\n /**\n * Recover a Firecracker VM after a worker restart: the process may well have survived, so\n * probe its API socket \u2014 if it answers, lifecycle control and HTTP proxying resume\n * normally. There's no live ChildProcess to reattach to, so destroy() falls back to\n * killing the stored pid, and the serial console is unavailable (see getSerialSource).\n */\n async reattach(record: VmRecord): Promise<VmHandle | undefined> {\n const meta = record.runtimeMetadata as\n | {\n apiSocketPath?: string\n tapName?: string\n subnet?: number\n guestIp?: string\n pid?: number\n }\n | undefined\n if (!meta?.apiSocketPath || !meta.tapName || meta.subnet === undefined || !meta.guestIp) {\n return undefined\n }\n\n try {\n await withTimeout(fcRequest(meta.apiSocketPath, 'GET', '/', {}), 5_000)\n } catch {\n return undefined\n }\n\n const handle: VmHandle = {\n vmId: record.vmId,\n sessionId: record.sessionId,\n stack: record.stack,\n resources: record.resources,\n running: record.state === 'running',\n metadata: meta,\n }\n\n this.usedSubnets.add(meta.subnet)\n // Keep future tap names from colliding with this reattached one.\n const tapNumber = Number(meta.tapName.replace(/^fctap/, ''))\n if (Number.isFinite(tapNumber)) this.tapCounter = Math.max(this.tapCounter, tapNumber)\n\n this.vms.set(record.vmId, {\n handle,\n pid: meta.pid,\n apiSocketPath: meta.apiSocketPath,\n tapName: meta.tapName,\n subnet: meta.subnet,\n guestIp: meta.guestIp,\n runMode: record.runMode,\n startedAt: Date.parse(record.createdAt) || Date.now(),\n })\n\n // Note: same limitation as QemuExecutor.reattach \u2014 a job VM's serial buffer only ever\n // lived in the dead worker's memory, and a still-running one has no ChildProcess here to\n // detect its eventual exit (getSerialSource already documents the equivalent gap for the\n // live console). Not solved in v1.\n\n logger.info(\n { vmId: record.vmId, guestIp: meta.guestIp, tapName: meta.tapName },\n 'firecracker vm reattached',\n )\n return handle\n }\n\n async proxyHttp(vmId: string, request: ProxyRequestDescriptor): Promise<ProxyResponseDescriptor> {\n const vm = this.vms.get(vmId)\n if (!vm?.handle.running) throw new Error(`vm ${vmId} is not running`)\n\n return new Promise((resolve, reject) => {\n const req = http.request(\n {\n host: vm.guestIp,\n port: 8080,\n method: request.method,\n path: request.path,\n headers: request.headers,\n },\n (res) => {\n const chunks: Buffer[] = []\n res.on('data', (c: Buffer) => chunks.push(c))\n res.on('end', () =>\n resolve({\n statusCode: res.statusCode ?? 502,\n headers: Object.fromEntries(\n Object.entries(res.headers).map(([k, v]) => [\n k,\n Array.isArray(v) ? v.join(', ') : v ?? '',\n ]),\n ),\n body: Buffer.concat(chunks),\n }),\n )\n },\n )\n req.on('error', reject)\n if (request.body) req.write(request.body)\n req.end()\n })\n }\n\n private async patchVmState(vmId: string, state: 'Paused' | 'Resumed'): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) throw new Error(`vm ${vmId} not found`)\n await fcRequest(vm.apiSocketPath, 'PATCH', '/vm', { state })\n }\n\n private setRunning(vmId: string, running: boolean): VmHandle {\n const vm = this.vms.get(vmId)\n if (!vm) throw new Error(`vm ${vmId} not found`)\n vm.handle = { ...vm.handle, running }\n return vm.handle\n }\n}\n\n// Send a request to the Firecracker REST API via Unix socket.\nfunction fcRequest(\n socketPath: string,\n method: string,\n urlPath: string,\n body: object,\n): Promise<object> {\n return new Promise((resolve, reject) => {\n const payload = JSON.stringify(body)\n const req = http.request(\n {\n socketPath,\n method,\n path: urlPath,\n headers: {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(payload),\n Accept: 'application/json',\n },\n },\n (res) => {\n const chunks: Buffer[] = []\n res.on('data', (c: Buffer) => chunks.push(c))\n res.on('end', () => {\n const text = Buffer.concat(chunks).toString()\n if (res.statusCode && res.statusCode >= 400) {\n reject(new Error(`Firecracker ${method} ${urlPath} \u2192 ${res.statusCode}: ${text}`))\n } else {\n try {\n resolve(JSON.parse(text))\n } catch {\n resolve({})\n }\n }\n })\n },\n )\n req.on('error', reject)\n req.write(payload)\n req.end()\n })\n}\n\nfunction waitForSocket(socketPath: string, timeoutMs = 10_000): Promise<void> {\n return new Promise((resolve, reject) => {\n const deadline = Date.now() + timeoutMs\n const attempt = () => {\n if (Date.now() > deadline)\n return reject(new Error(`timed out waiting for Firecracker socket ${socketPath}`))\n const sock = net.createConnection(socketPath)\n sock.once('connect', () => {\n sock.destroy()\n resolve()\n })\n sock.once('error', () => setTimeout(attempt, 100))\n }\n attempt()\n })\n}\n\nfunction waitForHttp(host: string, port: number, timeoutMs = 60_000): Promise<void> {\n return new Promise((resolve, reject) => {\n const deadline = Date.now() + timeoutMs\n const attempt = () => {\n if (Date.now() > deadline)\n return reject(new Error(`timed out waiting for HTTP at ${host}:${port}`))\n const req = http.get(`http://${host}:${port}/health`, (res) => {\n if (res.statusCode && res.statusCode < 500) return resolve()\n res.resume()\n setTimeout(attempt, 1_000)\n })\n req.on('error', () => setTimeout(attempt, 1_000))\n req.setTimeout(2_000, () => {\n req.destroy()\n setTimeout(attempt, 1_000)\n })\n }\n attempt()\n })\n}\n", "import { execFile, spawn } from 'child_process'\nimport { promisify } from 'util'\nimport http from 'http'\nimport logger from '@multiplayer-app/logger'\nimport type {\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmExecRequest,\n VmExecResult,\n VmFileWrite,\n VmRecord,\n VmRunMode,\n VmRunResult,\n VmWriteFilesResult,\n} from '@multiplayer-app/builder-types'\nimport type { DockerWorkerConfig } from '../config'\nimport type { Executor, VmHandle, VmSpec } from './types'\n\nconst DEFAULT_EXEC_TIMEOUT_MS = 60_000\nconst MAX_EXEC_TIMEOUT_MS = 300_000\nconst MAX_OUTPUT_BYTES = 1024 * 1024\nconst MAX_FILE_BYTES = 5 * 1024 * 1024\nconst WORKSPACE_DIR = '/workspace'\n\nconst execFileAsync = promisify(execFile)\n\ninterface ManagedVm {\n handle: VmHandle\n containerId: string\n containerName: string\n hostPort: number\n runMode: VmRunMode\n startedAt: number\n}\n\n/** Reject \"../\" and absolute paths, same rule MockExecutor applies to its own workspace. */\nfunction assertSafeWorkspacePath(relativePath: string): string {\n const normalized = relativePath.replace(/^([/\\\\])+/, '')\n if (normalized.split(/[/\\\\]/).includes('..')) {\n throw new Error(`Path escapes the VM workspace: ${relativePath}`)\n }\n return normalized\n}\n\n/**\n * Runs VMs as local Docker containers (one container per VM), via the `docker` CLI \u2014\n * same shell-out style QemuExecutor uses for qemu-system-*. No kernel/HVF/KVM needed,\n * so it's the lowest-friction local engine: just Docker Desktop/OrbStack.\n *\n * Unlike the other local engines, the container's process is directly reachable from\n * the host, so exec/writeFiles are real (`docker exec` / `docker cp`) rather than\n * MockExecutor-only stand-ins. pause/resume map to `docker pause`/`unpause` (a real\n * cgroup freeze); stop/restore map to `docker stop`/`start`, so every VmAction does\n * something meaningful \u2014 unlike QEMU (stop/restore alias pause/resume) or Fargate\n * (only stop works).\n */\nexport class DockerExecutor implements Executor {\n private readonly vms = new Map<string, ManagedVm>()\n private readonly usedPorts = new Set<number>()\n private readonly bin: string\n /** Job VMs that exited before onExit() was called to claim the result (create() \u2192 onExit() isn't atomic). */\n private readonly pendingResults = new Map<string, VmRunResult>()\n private readonly exitHandlers = new Map<string, (result: VmRunResult) => void>()\n\n constructor(private readonly config: DockerWorkerConfig) {\n this.bin = config.bin\n }\n\n private allocatePort(): number {\n for (let p = this.config.portRangeStart; p <= this.config.portRangeEnd; p++) {\n if (!this.usedPorts.has(p)) {\n this.usedPorts.add(p)\n return p\n }\n }\n throw new Error('no free ports in docker port range')\n }\n\n private async resolveImage(stack: string): Promise<string> {\n const explicit = this.config.stackImages[stack]\n if (explicit) return explicit\n\n const { imagePrefix, imageTag } = this.config\n const stackImage = `${imagePrefix}-${stack}:${imageTag}`\n if (await this.imageExists(stackImage)) return stackImage\n\n const genericImage = `${imagePrefix}-generic:${imageTag}`\n if (await this.imageExists(genericImage)) return genericImage\n\n throw new Error(\n `no local docker image for stack \"${stack}\" (${stackImage}) \u2014 run scripts/setup-docker-images.sh`,\n )\n }\n\n private async imageExists(image: string): Promise<boolean> {\n try {\n await execFileAsync(this.bin, ['image', 'inspect', image])\n return true\n } catch {\n return false\n }\n }\n\n async create(spec: VmSpec): Promise<VmHandle> {\n const image = await this.resolveImage(spec.stack)\n const hostPort = this.allocatePort()\n const containerName = `multiplayer-vm-${spec.vmId}`\n\n const args = [\n 'run',\n '-d',\n '--name',\n containerName,\n '-p',\n `127.0.0.1:${hostPort}:${this.config.guestPort}`,\n '--memory',\n `${spec.resources.memMib}m`,\n '--cpus',\n String(spec.resources.vcpuCount),\n '-e',\n `VM_ID=${spec.vmId}`,\n '-e',\n `STACK=${spec.stack}`,\n ...(spec.sessionId ? ['-e', `SESSION_ID=${spec.sessionId}`] : []),\n ...(spec.appUrl ? ['-e', `APP_URL=${spec.appUrl}`] : []),\n ...Object.entries(spec.env ?? {}).flatMap(([key, value]) => ['-e', `${key}=${value}`]),\n ...(this.config.network ? ['--network', this.config.network] : []),\n image,\n ]\n\n logger.info({ vmId: spec.vmId, bin: this.bin, args }, 'starting docker container')\n let containerId: string\n try {\n const { stdout } = await execFileAsync(this.bin, args)\n containerId = stdout.trim()\n } catch (error) {\n this.usedPorts.delete(hostPort)\n throw error\n }\n\n const handle: VmHandle = {\n vmId: spec.vmId,\n sessionId: spec.sessionId,\n stack: spec.stack,\n resources: spec.resources,\n running: true,\n metadata: { containerId, containerName, hostPort },\n }\n const runMode = spec.runMode ?? 'service'\n this.vms.set(spec.vmId, {\n handle,\n containerId,\n containerName,\n hostPort,\n runMode,\n startedAt: Date.now(),\n })\n this.watchExit(spec.vmId, containerId)\n\n // A job's entrypoint may run to completion before the agent ever comes up (e.g. it never\n // listens on a port) \u2014 waitForAgent would hang forever, so job VMs skip that readiness gate.\n if (runMode !== 'job') await this.waitForAgent(hostPort)\n logger.info({ vmId: spec.vmId, containerId, hostPort, runMode }, 'docker vm ready')\n return handle\n }\n\n /**\n * For 'service' VMs: frees the allocated port once the container exits on its own (crash,\n * OOM kill, `docker stop` from outside us) \u2014 same as before.\n * For 'job' VMs: captures the exit code + logs, tears the container down, and reports the\n * result to whoever calls onExit() (immediately if they already have, otherwise once they do).\n */\n private watchExit(vmId: string, containerId: string): void {\n execFileAsync(this.bin, ['wait', containerId])\n .catch(() => ({ stdout: '' }))\n .then(async ({ stdout }) => {\n const vm = this.vms.get(vmId)\n if (!vm || vm.containerId !== containerId) return\n\n if (vm.runMode !== 'job') {\n vm.handle = { ...vm.handle, running: false }\n return\n }\n\n const exitCode = Number.parseInt(stdout.trim(), 10) || 0\n const logs = await this.captureLogs(containerId)\n await execFileAsync(this.bin, ['rm', '-f', containerId]).catch((error: Error) =>\n logger.warn({ vmId, err: error }, 'docker rm after job exit failed'),\n )\n this.usedPorts.delete(vm.hostPort)\n // Resources are already freed above, but the map entry stays (marked not-running)\n // until onExit() claims the result \u2014 MultiEngineExecutor.route() needs get(vmId) to\n // keep finding it in the window between exit and onExit() being called (e.g. right\n // after a reattach discovers the job already finished).\n vm.handle = { ...vm.handle, running: false }\n\n const result: VmRunResult = {\n exitCode,\n ...logs,\n durationMs: Date.now() - vm.startedAt,\n finishedAt: new Date().toISOString(),\n }\n logger.info({ vmId, exitCode }, 'docker job vm exited')\n this.deliverJobResult(vmId, result)\n })\n }\n\n private deliverJobResult(vmId: string, result: VmRunResult): void {\n const handler = this.exitHandlers.get(vmId)\n if (handler) {\n this.exitHandlers.delete(vmId)\n this.vms.delete(vmId)\n handler(result)\n } else {\n this.pendingResults.set(vmId, result)\n }\n }\n\n /** `docker logs` mirrors the container's stdout/stderr onto its own, so the CLI's streams stay separate. */\n private async captureLogs(\n containerId: string,\n ): Promise<{ stdout: string; stderr: string; truncated: boolean }> {\n try {\n const { stdout, stderr } = await execFileAsync(this.bin, ['logs', containerId], {\n maxBuffer: MAX_OUTPUT_BYTES,\n })\n return {\n stdout: stdout.slice(0, MAX_OUTPUT_BYTES),\n stderr: stderr.slice(0, MAX_OUTPUT_BYTES),\n truncated: stdout.length > MAX_OUTPUT_BYTES || stderr.length > MAX_OUTPUT_BYTES,\n }\n } catch (error) {\n const failed = error as NodeJS.ErrnoException & { stdout?: string; stderr?: string }\n return {\n stdout: (failed.stdout ?? '').slice(0, MAX_OUTPUT_BYTES),\n stderr: (failed.stderr ?? '').slice(0, MAX_OUTPUT_BYTES),\n truncated: true,\n }\n }\n }\n\n onExit(vmId: string, handler: (result: VmRunResult) => void): void {\n const pending = this.pendingResults.get(vmId)\n if (pending) {\n this.pendingResults.delete(vmId)\n this.vms.delete(vmId)\n handler(pending)\n return\n }\n this.exitHandlers.set(vmId, handler)\n }\n\n async pause(vmId: string): Promise<VmHandle> {\n const vm = this.mustGet(vmId)\n await execFileAsync(this.bin, ['pause', vm.containerId])\n return this.setRunning(vmId, false)\n }\n\n async resume(vmId: string): Promise<VmHandle> {\n const vm = this.mustGet(vmId)\n await execFileAsync(this.bin, ['unpause', vm.containerId])\n return this.setRunning(vmId, true)\n }\n\n async stop(vmId: string): Promise<VmHandle> {\n const vm = this.mustGet(vmId)\n await execFileAsync(this.bin, ['stop', vm.containerId])\n return this.setRunning(vmId, false)\n }\n\n async restore(vmId: string): Promise<VmHandle> {\n const vm = this.mustGet(vmId)\n await execFileAsync(this.bin, ['start', vm.containerId])\n return this.setRunning(vmId, true)\n }\n\n async destroy(vmId: string): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) return\n\n await execFileAsync(this.bin, ['rm', '-f', vm.containerId]).catch((error: Error) =>\n logger.warn({ vmId, err: error }, 'docker rm on destroy failed'),\n )\n this.usedPorts.delete(vm.hostPort)\n this.vms.delete(vmId)\n logger.info({ vmId }, 'docker vm destroyed')\n }\n\n get(vmId: string): VmHandle | undefined {\n return this.vms.get(vmId)?.handle\n }\n\n list(): VmHandle[] {\n return [...this.vms.values()].map((v) => v.handle)\n }\n\n /**\n * Recover a container after a worker restart: it's an independent process the\n * Docker daemon owns, so just re-inspect it by ID and rebuild the local handle.\n */\n async reattach(record: VmRecord): Promise<VmHandle | undefined> {\n const meta = record.runtimeMetadata as\n | { containerId?: string; containerName?: string; hostPort?: number }\n | undefined\n if (!meta?.containerId || meta.hostPort === undefined) return undefined\n\n let running: boolean\n try {\n const { stdout } = await execFileAsync(this.bin, [\n 'inspect',\n '-f',\n '{{.State.Running}}',\n meta.containerId,\n ])\n running = stdout.trim() === 'true'\n } catch {\n return undefined\n }\n\n const handle: VmHandle = {\n vmId: record.vmId,\n sessionId: record.sessionId,\n stack: record.stack,\n resources: record.resources,\n running,\n metadata: meta,\n }\n this.usedPorts.add(meta.hostPort)\n this.vms.set(record.vmId, {\n handle,\n containerId: meta.containerId,\n containerName: meta.containerName ?? `multiplayer-vm-${record.vmId}`,\n hostPort: meta.hostPort,\n runMode: record.runMode,\n startedAt: Date.parse(record.createdAt) || Date.now(),\n })\n\n if (running) {\n this.watchExit(record.vmId, meta.containerId)\n } else if (record.runMode === 'job') {\n // The job already finished while this worker was offline (or restarting) \u2014 capture\n // whatever's left of it now instead of waiting on watchExit for a container that's\n // already dead, since `docker wait` never resolves for a container in a terminal state.\n void this.finishExitedJob(record.vmId, meta.containerId)\n }\n\n logger.info({ vmId: record.vmId, containerId: meta.containerId }, 'docker vm reattached')\n return handle\n }\n\n /** Same capture-and-report sequence as watchExit's job branch, for a container found already stopped. */\n private async finishExitedJob(vmId: string, containerId: string): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) return\n\n let exitCode = 0\n try {\n const { stdout } = await execFileAsync(this.bin, [\n 'inspect',\n '-f',\n '{{.State.ExitCode}}',\n containerId,\n ])\n exitCode = Number.parseInt(stdout.trim(), 10) || 0\n } catch {\n // container gone entirely \u2014 best effort, report a generic failure below\n }\n\n const logs = await this.captureLogs(containerId)\n await execFileAsync(this.bin, ['rm', '-f', containerId]).catch(() => {})\n this.usedPorts.delete(vm.hostPort)\n vm.handle = { ...vm.handle, running: false }\n\n const result: VmRunResult = {\n exitCode,\n ...logs,\n durationMs: Date.now() - vm.startedAt,\n finishedAt: new Date().toISOString(),\n }\n this.deliverJobResult(vmId, result)\n }\n\n async proxyHttp(vmId: string, request: ProxyRequestDescriptor): Promise<ProxyResponseDescriptor> {\n const vm = this.mustGet(vmId)\n if (!vm.handle.running) throw new Error(`vm ${vmId} is not running`)\n\n return new Promise((resolve, reject) => {\n const req = http.request(\n {\n host: '127.0.0.1',\n port: vm.hostPort,\n method: request.method,\n path: request.path,\n headers: request.headers,\n },\n (res) => {\n const chunks: Buffer[] = []\n res.on('data', (c: Buffer) => chunks.push(c))\n res.on('end', () =>\n resolve({\n statusCode: res.statusCode ?? 502,\n headers: Object.fromEntries(\n Object.entries(res.headers).map(([k, v]) => [\n k,\n Array.isArray(v) ? v.join(', ') : v ?? '',\n ]),\n ),\n body: Buffer.concat(chunks),\n }),\n )\n },\n )\n req.on('error', reject)\n if (request.body) req.write(request.body)\n req.end()\n })\n }\n\n async exec(vmId: string, request: VmExecRequest): Promise<VmExecResult> {\n const vm = this.mustGet(vmId)\n const cwd = request.cwd\n ? `${WORKSPACE_DIR}/${assertSafeWorkspacePath(request.cwd)}`\n : WORKSPACE_DIR\n const timeoutMs = Math.min(request.timeoutMs ?? DEFAULT_EXEC_TIMEOUT_MS, MAX_EXEC_TIMEOUT_MS)\n const startedAt = Date.now()\n\n return new Promise((resolve) => {\n execFile(\n this.bin,\n ['exec', '-w', cwd, vm.containerId, '/bin/sh', '-c', request.command],\n { timeout: timeoutMs, maxBuffer: MAX_OUTPUT_BYTES },\n (error, stdout, stderr) => {\n const failed = error as\n | (NodeJS.ErrnoException & { code?: number | string; killed?: boolean })\n | null\n const timedOut = Boolean(failed?.killed)\n const truncated = failed?.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER'\n resolve({\n exitCode: typeof failed?.code === 'number' ? failed.code : failed ? 1 : 0,\n stdout: stdout.slice(0, MAX_OUTPUT_BYTES),\n stderr: stderr.slice(0, MAX_OUTPUT_BYTES),\n durationMs: Date.now() - startedAt,\n truncated: Boolean(truncated),\n timedOut,\n })\n },\n )\n })\n }\n\n async writeFiles(vmId: string, files: VmFileWrite[]): Promise<VmWriteFilesResult> {\n const vm = this.mustGet(vmId)\n const written: Array<{ path: string; bytes: number }> = []\n\n for (const file of files) {\n const relativePath = assertSafeWorkspacePath(file.path)\n const buffer = Buffer.from(file.content, file.encoding === 'base64' ? 'base64' : 'utf8')\n if (buffer.byteLength > MAX_FILE_BYTES) {\n throw new Error(\n `File too large (${buffer.byteLength} bytes, max ${MAX_FILE_BYTES}): ${file.path}`,\n )\n }\n\n const dir = relativePath.includes('/')\n ? relativePath.slice(0, relativePath.lastIndexOf('/'))\n : ''\n if (dir) {\n await execFileAsync(this.bin, [\n 'exec',\n vm.containerId,\n 'mkdir',\n '-p',\n `${WORKSPACE_DIR}/${dir}`,\n ])\n }\n await this.copyIntoContainer(vm.containerId, `${WORKSPACE_DIR}/${relativePath}`, buffer)\n written.push({ path: relativePath, bytes: buffer.byteLength })\n }\n\n logger.info({ vmId, files: written.length }, 'docker vm files written')\n return { written }\n }\n\n /** `docker cp` needs a tar stream on stdin; build the smallest valid ustar archive for one file. */\n private copyIntoContainer(containerId: string, destPath: string, content: Buffer): Promise<void> {\n const entryName = destPath.replace(/^\\//, '')\n const tarStream = buildSingleFileTar(entryName, content)\n\n return new Promise((resolve, reject) => {\n const proc = spawn(this.bin, ['cp', '-', `${containerId}:/`], {\n stdio: ['pipe', 'ignore', 'pipe'],\n })\n let stderr = ''\n proc.stderr?.on('data', (d: Buffer) => {\n stderr += d.toString()\n })\n proc.on('error', reject)\n proc.on('exit', (code) =>\n code === 0 ? resolve() : reject(new Error(`docker cp exited ${code}: ${stderr}`)),\n )\n proc.stdin.end(tarStream)\n })\n }\n\n private mustGet(vmId: string): ManagedVm {\n const vm = this.vms.get(vmId)\n if (!vm) throw new Error(`vm ${vmId} not found`)\n return vm\n }\n\n private setRunning(vmId: string, running: boolean): VmHandle {\n const vm = this.mustGet(vmId)\n vm.handle = { ...vm.handle, running }\n return vm.handle\n }\n\n private async waitForAgent(port: number, timeoutMs = 30_000): Promise<void> {\n const deadline = Date.now() + timeoutMs\n for (;;) {\n const ok = await new Promise<boolean>((resolve) => {\n const req = http.get({ host: '127.0.0.1', port, path: '/', timeout: 2_000 }, (res) => {\n res.resume()\n resolve(true)\n })\n req.on('error', () => resolve(false))\n req.on('timeout', () => {\n req.destroy()\n resolve(false)\n })\n })\n if (ok) return\n if (Date.now() > deadline)\n throw new Error(`timed out waiting for docker vm agent on port ${port}`)\n await new Promise((resolve) => setTimeout(resolve, 500))\n }\n }\n}\n\n/** POSIX ustar archive containing exactly one regular file \u2014 enough for `docker cp -`. */\nfunction buildSingleFileTar(name: string, content: Buffer): Buffer {\n const header = Buffer.alloc(512)\n header.write(name, 0, 'utf8')\n header.write('0000644\\0', 100, 'utf8') // mode\n header.write('0000000\\0', 108, 'utf8') // uid\n header.write('0000000\\0', 116, 'utf8') // gid\n header.write(content.byteLength.toString(8).padStart(11, '0') + '\\0', 124, 'utf8') // size (octal)\n header.write(\n Math.floor(Date.now() / 1000)\n .toString(8)\n .padStart(11, '0') + '\\0',\n 136,\n 'utf8',\n ) // mtime\n header.write(' ', 148, 'utf8') // checksum placeholder (spaces while computing)\n header.write('0', 156, 'utf8') // typeflag: regular file\n header.write('ustar\\0', 257, 'utf8')\n header.write('00', 263, 'utf8')\n\n let checksum = 0\n for (const byte of header) checksum += byte\n header.write(checksum.toString(8).padStart(6, '0') + '\\0 ', 148, 'utf8')\n\n const paddedContentLength = Math.ceil(content.byteLength / 512) * 512\n const paddedContent = Buffer.alloc(paddedContentLength)\n content.copy(paddedContent)\n\n return Buffer.concat([header, paddedContent, Buffer.alloc(1024)]) // two 512-byte zero blocks terminate the archive\n}\n", "import { execFile, spawn } from 'child_process'\nimport { promisify } from 'util'\nimport fs from 'fs/promises'\nimport os from 'os'\nimport path from 'path'\nimport http from 'http'\nimport logger from '@multiplayer-app/logger'\nimport type {\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmExecRequest,\n VmExecResult,\n VmFileWrite,\n VmRecord,\n VmRunMode,\n VmRunResult,\n VmWriteFilesResult,\n} from '@multiplayer-app/builder-types'\nimport type { DockerSandboxWorkerConfig } from '../config'\nimport type { Executor, VmHandle, VmSpec } from './types'\n\nconst DEFAULT_EXEC_TIMEOUT_MS = 60_000\nconst MAX_EXEC_TIMEOUT_MS = 300_000\nconst MAX_OUTPUT_BYTES = 1024 * 1024\nconst MAX_FILE_BYTES = 5 * 1024 * 1024\nconst WORKSPACE_DIR = '/workspace'\nconst AGENT_DIR = '/app'\n\nconst execFileAsync = promisify(execFile)\n\ninterface ManagedVm {\n handle: VmHandle\n sandboxName: string\n vmDir: string\n hostPort: number\n agentCommand: string\n runMode: VmRunMode\n startedAt: number\n}\n\n/** Reject \"../\" and absolute paths, same rule MockExecutor/DockerExecutor apply to their workspace. */\nfunction assertSafeWorkspacePath(relativePath: string): string {\n const normalized = relativePath.replace(/^([/\\\\])+/, '')\n if (normalized.split(/[/\\\\]/).includes('..')) {\n throw new Error(`Path escapes the VM workspace: ${relativePath}`)\n }\n return normalized\n}\n\n/** sbx sandbox names: letters/digits/hyphens/periods only, starting with a letter or digit. */\nfunction sandboxNameFor(vmId: string): string {\n return `mp-${vmId.replace(/[^a-zA-Z0-9.-]/g, '-')}`\n}\n\n/**\n * Runs VMs as Docker Sandboxes (`sbx`, docker.com/products/docker-sandboxes) \u2014 Docker's own\n * microVM-per-sandbox product, originally built for safely running AI coding agents. Reuses\n * the exact same per-stack images `docker` (DockerExecutor) already builds via\n * scripts/setup-docker-images.sh, bridged into sbx's own image store with `docker save` +\n * `sbx template load`.\n *\n * Two things `sbx` does differently from plain `docker run`, driven by its \"isolated agent\n * sandbox\" design rather than \"run this image\" design:\n * - `sbx create` doesn't execute the image's own Dockerfile CMD (confirmed via `ps aux`:\n * PID 1 is a `sleep infinity` placeholder) \u2014 the guest agent is launched explicitly via\n * `sbx exec -d` right after creation.\n * - `sbx create`/`run` require a real host directory to mount as the sandbox's workspace;\n * unrelated to the image's own internal /workspace (used by the guest agent for release\n * deploys) \u2014 just a disposable per-VM directory to satisfy the CLI.\n *\n * No `docker pause`-equivalent primitive exists here, so pause/resume alias stop/restore,\n * same precedent QemuExecutor already sets for engines without a distinct freeze primitive.\n */\nexport class DockerSandboxExecutor implements Executor {\n private readonly vms = new Map<string, ManagedVm>()\n private readonly usedPorts = new Set<number>()\n private readonly loadedTemplates = new Set<string>()\n private readonly bin: string\n private readonly pendingResults = new Map<string, VmRunResult>()\n private readonly exitHandlers = new Map<string, (result: VmRunResult) => void>()\n\n constructor(private readonly config: DockerSandboxWorkerConfig) {\n this.bin = config.bin\n }\n\n private allocatePort(): number {\n for (let p = this.config.portRangeStart; p <= this.config.portRangeEnd; p++) {\n if (!this.usedPorts.has(p)) {\n this.usedPorts.add(p)\n return p\n }\n }\n throw new Error('no free ports in docker-sandbox port range')\n }\n\n private resolveAgentCommand(stack: string): string {\n return (\n this.config.stackAgentCommands[stack] ??\n this.config.stackAgentCommands.generic ??\n 'node app.js'\n )\n }\n\n /** Local `docker` image tag for a stack, same resolution order as DockerExecutor.resolveImage. */\n private localImageFor(stack: string): string {\n const { imagePrefix, imageTag } = this.config\n return `${imagePrefix}-${stack}:${imageTag}`\n }\n\n /** Bridges the local docker image into sbx's own image store once per process; returns its ref. */\n private async ensureTemplateLoaded(stack: string): Promise<string> {\n const explicit = this.config.stackTemplates[stack]\n if (explicit) return explicit\n\n const localImage = this.localImageFor(stack)\n const templateRef = `docker.io/library/${localImage}`\n if (this.loadedTemplates.has(templateRef)) return templateRef\n\n const tmpFile = path.join(os.tmpdir(), `sbx-template-${stack}-${Date.now()}.tar`)\n try {\n await execFileAsync('docker', ['save', localImage, '-o', tmpFile])\n await execFileAsync(this.bin, ['template', 'load', tmpFile])\n } catch (error) {\n throw new Error(\n `failed to bridge local image \"${localImage}\" into sbx \u2014 run scripts/setup-docker-images.sh: ${error}`,\n )\n } finally {\n await fs.rm(tmpFile, { force: true })\n }\n\n this.loadedTemplates.add(templateRef)\n return templateRef\n }\n\n async create(spec: VmSpec): Promise<VmHandle> {\n const templateRef = await this.ensureTemplateLoaded(spec.stack)\n const agentCommand = this.resolveAgentCommand(spec.stack)\n const sandboxName = sandboxNameFor(spec.vmId)\n const hostPort = this.allocatePort()\n const vmDir = path.join(this.config.workspaceRoot, spec.vmId)\n await fs.mkdir(vmDir, { recursive: true })\n const memMib = Math.max(spec.resources.memMib, this.config.minMemoryMib)\n\n const createArgs = [\n 'create',\n 'shell',\n vmDir,\n '--template',\n templateRef,\n '--name',\n sandboxName,\n '-p',\n `127.0.0.1:${hostPort}:${this.config.guestPort}`,\n '-m',\n `${memMib}m`,\n '--cpus',\n String(spec.resources.vcpuCount),\n '-e',\n `VM_ID=${spec.vmId}`,\n '-e',\n `STACK=${spec.stack}`,\n ...(spec.sessionId ? ['-e', `SESSION_ID=${spec.sessionId}`] : []),\n ...(spec.appUrl ? ['-e', `APP_URL=${spec.appUrl}`] : []),\n ...Object.entries(spec.env ?? {}).flatMap(([key, value]) => ['-e', `${key}=${value}`]),\n ]\n\n const runMode = spec.runMode ?? 'service'\n\n logger.info({ vmId: spec.vmId, bin: this.bin, args: createArgs }, 'creating docker sandbox')\n try {\n await execFileAsync(this.bin, createArgs)\n if (runMode !== 'job') this.launchAgent(sandboxName, agentCommand)\n } catch (error) {\n this.usedPorts.delete(hostPort)\n await fs.rm(vmDir, { recursive: true, force: true }).catch(() => {})\n throw error\n }\n\n const handle: VmHandle = {\n vmId: spec.vmId,\n sessionId: spec.sessionId,\n stack: spec.stack,\n resources: { ...spec.resources, memMib },\n running: true,\n metadata: { sandboxName, hostPort, vmDir, agentCommand },\n }\n this.vms.set(spec.vmId, {\n handle,\n sandboxName,\n vmDir,\n hostPort,\n agentCommand,\n runMode,\n startedAt: Date.now(),\n })\n\n if (runMode === 'job') {\n this.runJob(spec.vmId, sandboxName, agentCommand)\n } else {\n await this.waitForAgent(hostPort)\n }\n logger.info({ vmId: spec.vmId, sandboxName, hostPort, runMode }, 'docker sandbox ready')\n return handle\n }\n\n /**\n * Job mode: unlike `launchAgent` (fire-and-forget `sbx exec -d`, used for persistent\n * services), run the entrypoint in the *foreground* \u2014 the CLI call itself blocks until the\n * command exits and hands back its exit code + captured stdout/stderr directly, so there's\n * no separate wait/logs step needed the way DockerExecutor needs for a backgrounded container.\n */\n private runJob(vmId: string, sandboxName: string, agentCommand: string): void {\n const startedAt = this.vms.get(vmId)?.startedAt ?? Date.now()\n execFile(\n this.bin,\n ['exec', '-w', AGENT_DIR, sandboxName, '/bin/sh', '-c', agentCommand],\n { maxBuffer: MAX_OUTPUT_BYTES },\n (error, stdout, stderr) => {\n const failed = error as (NodeJS.ErrnoException & { code?: number | string }) | null\n const truncated = failed?.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER'\n const result: VmRunResult = {\n exitCode: typeof failed?.code === 'number' ? failed.code : failed ? 1 : 0,\n stdout: stdout.slice(0, MAX_OUTPUT_BYTES),\n stderr: stderr.slice(0, MAX_OUTPUT_BYTES),\n truncated: Boolean(truncated),\n durationMs: Date.now() - startedAt,\n finishedAt: new Date().toISOString(),\n }\n void this.finishJob(vmId, sandboxName, result)\n },\n )\n }\n\n private async finishJob(vmId: string, sandboxName: string, result: VmRunResult): Promise<void> {\n logger.info({ vmId, exitCode: result.exitCode }, 'docker sandbox job exited')\n await execFileAsync(this.bin, ['rm', '-f', sandboxName]).catch((error: Error) =>\n logger.warn({ vmId, err: error }, 'sbx rm after job exit failed'),\n )\n const vm = this.vms.get(vmId)\n if (vm) {\n await fs.rm(vm.vmDir, { recursive: true, force: true }).catch(() => {})\n this.usedPorts.delete(vm.hostPort)\n // Resources are already freed above, but the map entry stays (marked not-running)\n // until onExit() claims the result \u2014 see docker-executor's deliverJobResult for why.\n vm.handle = { ...vm.handle, running: false }\n }\n\n this.deliverJobResult(vmId, result)\n }\n\n private deliverJobResult(vmId: string, result: VmRunResult): void {\n const handler = this.exitHandlers.get(vmId)\n if (handler) {\n this.exitHandlers.delete(vmId)\n this.vms.delete(vmId)\n handler(result)\n } else {\n this.pendingResults.set(vmId, result)\n }\n }\n\n onExit(vmId: string, handler: (result: VmRunResult) => void): void {\n const pending = this.pendingResults.get(vmId)\n if (pending) {\n this.pendingResults.delete(vmId)\n this.vms.delete(vmId)\n handler(pending)\n return\n }\n this.exitHandlers.set(vmId, handler)\n }\n\n /**\n * `sbx create shell` doesn't run the image's own CMD \u2014 launch the guest agent explicitly.\n *\n * Fire-and-forget: `sbx exec -d` (detach) launches the background command correctly but its\n * own CLI process then hangs indefinitely instead of returning \u2014 confirmed live (the agent\n * was already answering on its port while the CLI call itself sat stuck for 14+ minutes,\n * needing a kill -9). `waitForAgent`'s port poll is the real readiness signal here, not this\n * process exiting, so it's spawned detached and never awaited.\n */\n private launchAgent(sandboxName: string, agentCommand: string): void {\n const proc = spawn(\n this.bin,\n ['exec', '-d', '-w', AGENT_DIR, sandboxName, '/bin/sh', '-c', agentCommand],\n {\n stdio: 'ignore',\n },\n )\n proc.on('error', (error) =>\n logger.warn({ sandboxName, err: error }, 'sbx exec -d failed to spawn'),\n )\n proc.unref()\n }\n\n async pause(vmId: string): Promise<VmHandle> {\n return this.stop(vmId)\n }\n\n async resume(vmId: string): Promise<VmHandle> {\n return this.restore(vmId)\n }\n\n async stop(vmId: string): Promise<VmHandle> {\n const vm = this.mustGet(vmId)\n await execFileAsync(this.bin, ['stop', vm.sandboxName])\n return this.setRunning(vmId, false)\n }\n\n async restore(vmId: string): Promise<VmHandle> {\n const vm = this.mustGet(vmId)\n await execFileAsync(this.bin, ['run', '--name', vm.sandboxName, '--detached'])\n const alreadyUp = await this.probeAgent(vm.hostPort)\n if (!alreadyUp) this.launchAgent(vm.sandboxName, vm.agentCommand)\n await this.waitForAgent(vm.hostPort)\n return this.setRunning(vmId, true)\n }\n\n async destroy(vmId: string): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) return\n\n await execFileAsync(this.bin, ['rm', '-f', vm.sandboxName]).catch((error: Error) =>\n logger.warn({ vmId, err: error }, 'sbx rm on destroy failed'),\n )\n await fs.rm(vm.vmDir, { recursive: true, force: true }).catch(() => {})\n this.usedPorts.delete(vm.hostPort)\n this.vms.delete(vmId)\n logger.info({ vmId }, 'docker sandbox destroyed')\n }\n\n get(vmId: string): VmHandle | undefined {\n return this.vms.get(vmId)?.handle\n }\n\n list(): VmHandle[] {\n return [...this.vms.values()].map((v) => v.handle)\n }\n\n /**\n * Recover a sandbox after a worker restart: it's owned by the independent `sandboxd`\n * daemon, so a liveness probe against its name is enough to confirm it's still there.\n */\n async reattach(record: VmRecord): Promise<VmHandle | undefined> {\n const meta = record.runtimeMetadata as\n | { sandboxName?: string; hostPort?: number; vmDir?: string; agentCommand?: string }\n | undefined\n if (!meta?.sandboxName || meta.hostPort === undefined || !meta.vmDir || !meta.agentCommand)\n return undefined\n\n let running: boolean\n try {\n await execFileAsync(this.bin, ['exec', meta.sandboxName, 'true'])\n running = true\n } catch {\n try {\n await execFileAsync(this.bin, ['ls', '--json'])\n running = false // ran but the sandbox isn't reachable \u2014 treat as stopped, not gone\n } catch {\n return undefined\n }\n }\n\n const handle: VmHandle = {\n vmId: record.vmId,\n sessionId: record.sessionId,\n stack: record.stack,\n resources: record.resources,\n running,\n metadata: meta,\n }\n this.usedPorts.add(meta.hostPort)\n this.vms.set(record.vmId, {\n handle,\n sandboxName: meta.sandboxName,\n vmDir: meta.vmDir,\n hostPort: meta.hostPort,\n agentCommand: meta.agentCommand,\n runMode: record.runMode,\n startedAt: Date.parse(record.createdAt) || Date.now(),\n })\n\n if (record.runMode === 'job') {\n // The job's entrypoint ran as this worker's own foreground child process (see runJob) \u2014\n // it died with the worker, so there's nothing left to resume watching. Report it as\n // failed rather than leaving the record stuck in 'running' forever.\n void this.finishJob(record.vmId, meta.sandboxName, {\n exitCode: -1,\n stdout: '',\n stderr: 'worker restarted while this job was still running',\n truncated: false,\n durationMs: Date.now() - (Date.parse(record.createdAt) || Date.now()),\n finishedAt: new Date().toISOString(),\n })\n }\n\n logger.info({ vmId: record.vmId, sandboxName: meta.sandboxName }, 'docker sandbox reattached')\n return handle\n }\n\n async proxyHttp(vmId: string, request: ProxyRequestDescriptor): Promise<ProxyResponseDescriptor> {\n const vm = this.mustGet(vmId)\n if (!vm.handle.running) throw new Error(`vm ${vmId} is not running`)\n\n return new Promise((resolve, reject) => {\n const req = http.request(\n {\n host: '127.0.0.1',\n port: vm.hostPort,\n method: request.method,\n path: request.path,\n headers: request.headers,\n },\n (res) => {\n const chunks: Buffer[] = []\n res.on('data', (c: Buffer) => chunks.push(c))\n res.on('end', () =>\n resolve({\n statusCode: res.statusCode ?? 502,\n headers: Object.fromEntries(\n Object.entries(res.headers).map(([k, v]) => [\n k,\n Array.isArray(v) ? v.join(', ') : v ?? '',\n ]),\n ),\n body: Buffer.concat(chunks),\n }),\n )\n },\n )\n req.on('error', reject)\n if (request.body) req.write(request.body)\n req.end()\n })\n }\n\n async exec(vmId: string, request: VmExecRequest): Promise<VmExecResult> {\n const vm = this.mustGet(vmId)\n const cwd = request.cwd\n ? `${WORKSPACE_DIR}/${assertSafeWorkspacePath(request.cwd)}`\n : WORKSPACE_DIR\n const timeoutMs = Math.min(request.timeoutMs ?? DEFAULT_EXEC_TIMEOUT_MS, MAX_EXEC_TIMEOUT_MS)\n const startedAt = Date.now()\n\n return new Promise((resolve) => {\n execFile(\n this.bin,\n ['exec', '-w', cwd, vm.sandboxName, '/bin/sh', '-c', request.command],\n { timeout: timeoutMs, maxBuffer: MAX_OUTPUT_BYTES },\n (error, stdout, stderr) => {\n const failed = error as\n | (NodeJS.ErrnoException & { code?: number | string; killed?: boolean })\n | null\n const timedOut = Boolean(failed?.killed)\n const truncated = failed?.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER'\n resolve({\n exitCode: typeof failed?.code === 'number' ? failed.code : failed ? 1 : 0,\n stdout: stdout.slice(0, MAX_OUTPUT_BYTES),\n stderr: stderr.slice(0, MAX_OUTPUT_BYTES),\n durationMs: Date.now() - startedAt,\n truncated: Boolean(truncated),\n timedOut,\n })\n },\n )\n })\n }\n\n async writeFiles(vmId: string, files: VmFileWrite[]): Promise<VmWriteFilesResult> {\n const vm = this.mustGet(vmId)\n const written: Array<{ path: string; bytes: number }> = []\n\n for (const file of files) {\n const relativePath = assertSafeWorkspacePath(file.path)\n const buffer = Buffer.from(file.content, file.encoding === 'base64' ? 'base64' : 'utf8')\n if (buffer.byteLength > MAX_FILE_BYTES) {\n throw new Error(\n `File too large (${buffer.byteLength} bytes, max ${MAX_FILE_BYTES}): ${file.path}`,\n )\n }\n\n const dir = relativePath.includes('/')\n ? relativePath.slice(0, relativePath.lastIndexOf('/'))\n : ''\n if (dir) {\n await execFileAsync(this.bin, [\n 'exec',\n vm.sandboxName,\n 'mkdir',\n '-p',\n `${WORKSPACE_DIR}/${dir}`,\n ])\n }\n\n // sbx cp takes a real host path on one side \u2014 simpler than DockerExecutor's tar-over-stdin hack.\n const tmpFile = path.join(\n os.tmpdir(),\n `sbx-write-${vmId}-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n )\n await fs.writeFile(tmpFile, buffer)\n try {\n await execFileAsync(this.bin, [\n 'cp',\n tmpFile,\n `${vm.sandboxName}:${WORKSPACE_DIR}/${relativePath}`,\n ])\n } finally {\n await fs.rm(tmpFile, { force: true })\n }\n written.push({ path: relativePath, bytes: buffer.byteLength })\n }\n\n logger.info({ vmId, files: written.length }, 'docker sandbox files written')\n return { written }\n }\n\n private mustGet(vmId: string): ManagedVm {\n const vm = this.vms.get(vmId)\n if (!vm) throw new Error(`vm ${vmId} not found`)\n return vm\n }\n\n private setRunning(vmId: string, running: boolean): VmHandle {\n const vm = this.mustGet(vmId)\n vm.handle = { ...vm.handle, running }\n return vm.handle\n }\n\n private async probeAgent(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const req = http.get({ host: '127.0.0.1', port, path: '/', timeout: 2_000 }, (res) => {\n res.resume()\n resolve(true)\n })\n req.on('error', () => resolve(false))\n req.on('timeout', () => {\n req.destroy()\n resolve(false)\n })\n })\n }\n\n private async waitForAgent(port: number, timeoutMs = 30_000): Promise<void> {\n const deadline = Date.now() + timeoutMs\n for (;;) {\n if (await this.probeAgent(port)) return\n if (Date.now() > deadline)\n throw new Error(`timed out waiting for docker sandbox agent on port ${port}`)\n await new Promise((resolve) => setTimeout(resolve, 500))\n }\n }\n}\n", "import http from 'http'\nimport https from 'https'\nimport logger from '@multiplayer-app/logger'\nimport type {\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmRecord,\n VmRunResult,\n} from '@multiplayer-app/builder-types'\nimport type { Executor, VmHandle, VmSpec } from './types'\nimport { withTimeout } from './reattach-utils'\n\nconst JOB_POLL_INTERVAL_MS = 3_000\n\nexport interface RemoteExecutorConfig {\n agentUrl: string // e.g. http://192.168.1.10:4040\n authToken?: string\n}\n\nexport class RemoteExecutor implements Executor {\n private readonly base: string\n private readonly headers: Record<string, string>\n // The remote agent is the actual source of truth, but MultiEngineExecutor.route() (used by\n // pause/resume/stop/restore/destroy/proxyHttp/exec/writeFiles) needs get() to find the\n // right executor for a vmId \u2014 cache the handle each call returns so it does.\n private readonly vms = new Map<string, VmHandle>()\n private readonly jobStartedAt = new Map<string, number>()\n\n constructor(config: RemoteExecutorConfig) {\n this.base = config.agentUrl.replace(/\\/$/, '')\n this.headers = {\n 'Content-Type': 'application/json',\n ...(config.authToken ? { Authorization: `Bearer ${config.authToken}` } : {}),\n }\n }\n\n async create(spec: VmSpec): Promise<VmHandle> {\n const handle = await this.request<VmHandle>('POST', '/vms', spec)\n this.vms.set(spec.vmId, handle)\n if (spec.runMode === 'job') this.jobStartedAt.set(spec.vmId, Date.now())\n return handle\n }\n\n /**\n * The remote agent's own wire protocol (VmHandle) has no exit-code/output field \u2014 extending\n * it is out of this repo's control, so this only detects completion (poll GET /vms/:vmId\n * until running flips false) without a real exit code or captured output. Good enough to\n * unblock the record from being stuck in 'running' forever; a real RemoteExecutor deployment\n * wanting full job support needs its agent protocol extended first.\n */\n onExit(vmId: string, handler: (result: VmRunResult) => void): void {\n const startedAt = this.jobStartedAt.get(vmId) ?? Date.now()\n const poll = async () => {\n const handle = await this.request<VmHandle>('GET', `/vms/${vmId}`).catch(() => undefined)\n if (handle) this.vms.set(vmId, handle)\n\n if (!handle || !handle.running) {\n this.jobStartedAt.delete(vmId)\n this.vms.delete(vmId)\n handler({\n exitCode: 0,\n stdout: '',\n stderr:\n 'remote engine does not report job exit codes/output \u2014 completion detected via polling only',\n truncated: false,\n durationMs: Date.now() - startedAt,\n finishedAt: new Date().toISOString(),\n })\n return\n }\n setTimeout(() => void poll(), JOB_POLL_INTERVAL_MS)\n }\n void poll()\n }\n\n async pause(vmId: string): Promise<VmHandle> {\n return this.updateCached(vmId, await this.request('POST', `/vms/${vmId}/pause`))\n }\n\n async resume(vmId: string): Promise<VmHandle> {\n return this.updateCached(vmId, await this.request('POST', `/vms/${vmId}/resume`))\n }\n\n async stop(vmId: string): Promise<VmHandle> {\n return this.updateCached(vmId, await this.request('POST', `/vms/${vmId}/stop`))\n }\n\n async restore(vmId: string): Promise<VmHandle> {\n return this.updateCached(vmId, await this.request('POST', `/vms/${vmId}/restore`))\n }\n\n async destroy(vmId: string): Promise<void> {\n await this.request('DELETE', `/vms/${vmId}`)\n this.vms.delete(vmId)\n }\n\n get(vmId: string): VmHandle | undefined {\n return this.vms.get(vmId)\n }\n\n list(): VmHandle[] {\n return [...this.vms.values()]\n }\n\n /**\n * Recover a remote-agent VM after a worker restart. The agent owns the actual VM state\n * independently of this process, so reattaching is just confirming it still knows about\n * this vmId and re-populating the local get()/list() cache above.\n */\n async reattach(record: VmRecord): Promise<VmHandle | undefined> {\n try {\n const handle = await withTimeout(this.request<VmHandle>('GET', `/vms/${record.vmId}`), 5_000)\n this.vms.set(record.vmId, handle)\n return handle\n } catch {\n return undefined\n }\n }\n\n private updateCached(vmId: string, handle: VmHandle): VmHandle {\n this.vms.set(vmId, handle)\n return handle\n }\n\n async proxyHttp(vmId: string, request: ProxyRequestDescriptor): Promise<ProxyResponseDescriptor> {\n const result = await this.request<{\n statusCode: number\n headers: Record<string, string>\n body?: string\n }>('POST', `/vms/${vmId}/proxy`, {\n method: request.method,\n path: request.path,\n headers: request.headers,\n body: request.body?.toString('base64'),\n })\n\n return {\n statusCode: result.statusCode,\n headers: result.headers,\n body: result.body ? Buffer.from(result.body, 'base64') : Buffer.alloc(0),\n }\n }\n\n private request<T = unknown>(method: string, path: string, body?: unknown): Promise<T> {\n const url = new URL(this.base + path)\n const lib = url.protocol === 'https:' ? https : http\n const payload = body !== undefined ? JSON.stringify(body) : undefined\n\n return new Promise((resolve, reject) => {\n const req = lib.request(\n {\n hostname: url.hostname,\n port: url.port || (url.protocol === 'https:' ? 443 : 80),\n path: url.pathname,\n method,\n headers: {\n ...this.headers,\n ...(payload ? { 'Content-Length': Buffer.byteLength(payload) } : {}),\n },\n },\n (res) => {\n const chunks: Buffer[] = []\n res.on('data', (c: Buffer) => chunks.push(c))\n res.on('end', () => {\n const text = Buffer.concat(chunks).toString()\n if (res.statusCode && res.statusCode >= 400) {\n reject(new Error(`vm-agent ${method} ${path} \u2192 ${res.statusCode}: ${text}`))\n return\n }\n if (res.statusCode === 204 || !text) {\n resolve(undefined as T)\n return\n }\n try {\n resolve(JSON.parse(text) as T)\n } catch {\n resolve(text as unknown as T)\n }\n })\n },\n )\n req.on('error', reject)\n if (payload) req.write(payload)\n req.end()\n })\n }\n}\n", "import https from 'https'\nimport {\n LambdaMicrovmsClient,\n RunMicrovmCommand,\n SuspendMicrovmCommand,\n ResumeMicrovmCommand,\n TerminateMicrovmCommand,\n GetMicrovmCommand,\n CreateMicrovmAuthTokenCommand,\n CreateMicrovmShellAuthTokenCommand,\n} from '@aws-sdk/client-lambda-microvms'\nimport logger from '@multiplayer-app/logger'\nimport type {\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmRecord,\n VmStack,\n} from '@multiplayer-app/builder-types'\nimport type { Executor, SerialSource, VmHandle, VmSpec } from './types'\n\nexport interface LambdaMicrovmConfig {\n region?: string\n /** Default MicroVM image ARN, used for any stack without a specific image. */\n imageArn: string\n /** Per-stack image ARN overrides, e.g. { node: 'arn:...', python: 'arn:...' }. */\n stackImageArns?: Partial<Record<VmStack, string>>\n ingressConnectorArns?: string[]\n egressConnectorArns?: string[]\n executionRoleArn?: string\n /** Suspend automatically after this many seconds without endpoint traffic (0 disables the idle policy). */\n maxIdleSeconds?: number\n /** Terminate automatically after this many seconds in the suspended state. */\n suspendedDurationSeconds?: number\n /** Hard lifetime cap for a MicroVM (running + suspended), max 28800. */\n maximumDurationInSeconds?: number\n /** How long to wait for the RUNNING state after run-microvm. */\n createTimeoutMs?: number\n}\n\ninterface ManagedMicrovm {\n handle: VmHandle\n microvmId: string\n endpoint: string\n authToken?: { headers: Record<string, string>; expiresAt: number }\n}\n\nconst AUTH_TOKEN_TTL_MINUTES = 60\nconst AUTH_TOKEN_REFRESH_MARGIN_MS = 2 * 60_000\nconst SHELL_PORT = 8022\n\nfunction managedConnectorArn(imageIdentifier: string, name: string): string {\n const [arn, partition, service, region] = imageIdentifier.split(':')\n if (arn !== 'arn' || !partition || service !== 'lambda' || !region) {\n throw new Error(`cannot derive Lambda MicroVM connector ARN from image \"${imageIdentifier}\"`)\n }\n return `arn:${partition}:lambda:${region}:aws:network-connector:aws-network-connector:${name}`\n}\n\nfunction runtimeEnv(spec: VmSpec): Record<string, string> | undefined {\n const env = {\n ...spec.env,\n // A release URL is unique and short-lived, so it belongs in per-VM run data rather than\n // the image-level environment shared by every MicroVM launched from that image.\n ...(spec.appUrl ? { APP_URL: spec.appUrl } : {}),\n }\n return Object.keys(env).length ? env : undefined\n}\n\n/**\n * Runs VMs as AWS Lambda MicroVMs (Firecracker snapshots managed by Lambda).\n * No VNC framebuffer or native serial console \u2014 HTTP(S) and an authenticated shell\n * WebSocket reach the guest through its dedicated endpoint. Suspend/resume preserve full\n * memory + disk state, so pause/resume here is a true checkpoint, unlike QEMU's.\n *\n * Intentionally has no onExit(): unlike Fargate (whose ECS task actually stops when the\n * container's process exits) or QEMU/Firecracker (a guest poweroff kills the local hypervisor\n * process we spawned), a MicroVM's AWS-managed lifecycle has no state that reflects \"the\n * guest's own entrypoint finished\" \u2014 it only transitions via explicit suspend/resume/terminate\n * calls or the idle/duration policies above. 'job' run mode isn't supported on this engine\n * until the guest image itself can signal completion back out (e.g. call TerminateMicrovm on\n * itself, or a callback through the existing HTTP proxy path) \u2014 MultiEngineExecutor.onExit()\n * already surfaces a clear \"does not support job run mode\" error for this engine as-is.\n */\nexport class LambdaMicrovmExecutor implements Executor {\n private readonly client: LambdaMicrovmsClient\n private readonly vms = new Map<string, ManagedMicrovm>()\n\n constructor(private readonly config: LambdaMicrovmConfig) {\n this.client = new LambdaMicrovmsClient(config.region ? { region: config.region } : {})\n }\n\n async create(spec: VmSpec): Promise<VmHandle> {\n const imageIdentifier = this.config.stackImageArns?.[spec.stack] ?? this.config.imageArn\n const maxIdle = this.config.maxIdleSeconds ?? 900\n const shellConnectorArn = managedConnectorArn(imageIdentifier, 'SHELL_INGRESS')\n const ingressNetworkConnectors = [\n ...new Set([...(this.config.ingressConnectorArns ?? []), shellConnectorArn]),\n ]\n\n const run = await this.client.send(\n new RunMicrovmCommand({\n imageIdentifier,\n // Required by CreateMicrovmShellAuthToken and the /shell WebSocket used by vm-console.\n ingressNetworkConnectors,\n egressNetworkConnectors: this.config.egressConnectorArns,\n executionRoleArn: this.config.executionRoleArn,\n maximumDurationInSeconds: this.config.maximumDurationInSeconds ?? 28_800,\n ...(maxIdle > 0\n ? {\n idlePolicy: {\n autoResumeEnabled: true,\n maxIdleDurationSeconds: maxIdle,\n suspendedDurationSeconds: this.config.suspendedDurationSeconds ?? 28_800,\n },\n }\n : {}),\n // The guest's /run lifecycle hook receives this payload \u2014 lets the image\n // identify which builder session/VM it serves.\n runHookPayload: JSON.stringify({\n vmId: spec.vmId,\n sessionId: spec.sessionId,\n stack: spec.stack,\n env: runtimeEnv(spec),\n }),\n // VM_CREATE may be delivered more than once by the Redis-backed control plane.\n // AWS returns the original request result instead of provisioning another MicroVM.\n clientToken: spec.vmId,\n }),\n )\n\n if (!run.microvmId || !run.endpoint) {\n throw new Error('run-microvm returned no microvmId/endpoint')\n }\n\n logger.info(\n { vmId: spec.vmId, microvmId: run.microvmId, endpoint: run.endpoint, state: run.state },\n '[LambdaMicrovm] run-microvm accepted',\n )\n\n const handle: VmHandle = {\n vmId: spec.vmId,\n sessionId: spec.sessionId,\n stack: spec.stack,\n // Resources are fixed at MicroVM image build time; echo the request back for bookkeeping.\n resources: spec.resources,\n running: true,\n metadata: { microvmId: run.microvmId, endpoint: run.endpoint },\n }\n\n const vm: ManagedMicrovm = { handle, microvmId: run.microvmId, endpoint: run.endpoint }\n this.vms.set(spec.vmId, vm)\n\n try {\n await this.waitForState(run.microvmId, 'RUNNING', this.config.createTimeoutMs ?? 25_000)\n } catch (error) {\n this.vms.delete(spec.vmId)\n await this.client\n .send(new TerminateMicrovmCommand({ microvmIdentifier: run.microvmId }))\n .catch(() => {})\n throw error\n }\n\n logger.info({ vmId: spec.vmId, microvmId: run.microvmId }, '[LambdaMicrovm] vm running')\n return handle\n }\n\n async pause(vmId: string): Promise<VmHandle> {\n const vm = this.mustGet(vmId)\n await this.client.send(new SuspendMicrovmCommand({ microvmIdentifier: vm.microvmId }))\n return this.setRunning(vmId, false)\n }\n\n async resume(vmId: string): Promise<VmHandle> {\n const vm = this.mustGet(vmId)\n await this.client.send(new ResumeMicrovmCommand({ microvmIdentifier: vm.microvmId }))\n return this.setRunning(vmId, true)\n }\n\n // Suspend preserves memory + disk, so stop/restore are the same checkpoint\n // operations as pause/resume \u2014 there is no separate \"powered off\" state.\n stop(vmId: string): Promise<VmHandle> {\n return this.pause(vmId)\n }\n\n restore(vmId: string): Promise<VmHandle> {\n return this.resume(vmId)\n }\n\n async destroy(vmId: string): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) return\n\n await this.client.send(new TerminateMicrovmCommand({ microvmIdentifier: vm.microvmId }))\n this.vms.delete(vmId)\n logger.info({ vmId, microvmId: vm.microvmId }, '[LambdaMicrovm] vm terminated')\n }\n\n get(vmId: string): VmHandle | undefined {\n return this.vms.get(vmId)?.handle\n }\n\n list(): VmHandle[] {\n return [...this.vms.values()].map((v) => v.handle)\n }\n\n getSerialSource(vmId: string): SerialSource | undefined {\n const vm = this.vms.get(vmId)\n if (!vm) return undefined\n\n return {\n type: 'websocket',\n url: `wss://${vm.endpoint}/shell`,\n protocols: async () => {\n const response = await this.client.send(\n new CreateMicrovmShellAuthTokenCommand({\n microvmIdentifier: vm.microvmId,\n expirationInMinutes: AUTH_TOKEN_TTL_MINUTES,\n }),\n )\n const token = Object.entries(response.authToken ?? {}).find(\n ([key]) => key.toLowerCase() === 'x-aws-proxy-auth',\n )?.[1]\n if (!token) throw new Error('create-microvm-shell-auth-token returned no auth token')\n\n return [\n 'lambda-microvms',\n `lambda-microvms.authentication.${token}`,\n `lambda-microvms.port.${SHELL_PORT}`,\n ]\n },\n }\n }\n\n async proxyHttp(vmId: string, request: ProxyRequestDescriptor): Promise<ProxyResponseDescriptor> {\n const vm = this.mustGet(vmId)\n const auth = await this.getAuthHeaders(vm)\n\n return new Promise((resolve, reject) => {\n const req = https.request(\n {\n host: vm.endpoint,\n method: request.method,\n path: request.path,\n headers: {\n ...request.headers,\n ...auth,\n // Lambda routes to port 8080 by default; make the guest port explicit.\n 'X-aws-proxy-port': '8080',\n host: vm.endpoint,\n },\n },\n (res) => {\n const chunks: Buffer[] = []\n res.on('data', (c: Buffer) => chunks.push(c))\n res.on('end', () =>\n resolve({\n statusCode: res.statusCode ?? 502,\n headers: Object.fromEntries(\n Object.entries(res.headers).map(([k, v]) => [\n k,\n Array.isArray(v) ? v.join(', ') : v ?? '',\n ]),\n ),\n body: Buffer.concat(chunks),\n }),\n )\n },\n )\n req.on('error', reject)\n if (request.body) req.write(request.body)\n req.end()\n })\n }\n\n /**\n * Recover a Lambda MicroVM after a worker restart. It's an independent AWS-managed\n * resource that outlives this process \u2014 just re-describe it by ID and, unless it's been\n * terminated, rebuild the local handle (the auth token refetches lazily as usual).\n */\n async reattach(record: VmRecord): Promise<VmHandle | undefined> {\n const meta = record.runtimeMetadata as { microvmId?: string; endpoint?: string } | undefined\n if (!meta?.microvmId || !meta.endpoint) return undefined\n\n const described = await this.client\n .send(new GetMicrovmCommand({ microvmIdentifier: meta.microvmId }))\n .catch(() => undefined)\n if (!described || described.state === 'TERMINATED' || described.state === 'TERMINATING') {\n return undefined\n }\n\n const handle: VmHandle = {\n vmId: record.vmId,\n sessionId: record.sessionId,\n stack: record.stack,\n resources: record.resources,\n running: described.state === 'RUNNING',\n metadata: meta,\n }\n this.vms.set(record.vmId, { handle, microvmId: meta.microvmId, endpoint: meta.endpoint })\n logger.info(\n { vmId: record.vmId, microvmId: meta.microvmId, state: described.state },\n '[LambdaMicrovm] vm reattached',\n )\n return handle\n }\n\n /**\n * AWS can suspend or terminate a MicroVM on its own (idle-suspend policy, the suspended-\n * duration cap, the hard maximumDurationInSeconds lifetime) without this process ever\n * issuing a command \u2014 nothing else here polls for that. Called periodically by the\n * worker: re-describes every tracked VM, quietly reconciles running/suspended drift, and\n * reports (then forgets) any that AWS has actually terminated so the control plane's\n * record doesn't stay stuck saying \"running\" forever.\n */\n async reconcile(): Promise<string[]> {\n const externallyTerminated: string[] = []\n\n for (const [vmId, vm] of [...this.vms.entries()]) {\n try {\n const described = await this.client.send(\n new GetMicrovmCommand({ microvmIdentifier: vm.microvmId }),\n )\n if (described.state === 'TERMINATED' || described.state === 'TERMINATING') {\n this.vms.delete(vmId)\n externallyTerminated.push(vmId)\n logger.warn(\n { vmId, microvmId: vm.microvmId, state: described.state },\n '[LambdaMicrovm] vm terminated outside our control',\n )\n } else if (typeof described.state === 'string') {\n const running = described.state === 'RUNNING'\n if (running !== vm.handle.running) vm.handle = { ...vm.handle, running }\n }\n } catch (error) {\n if (error instanceof Error && error.name === 'ResourceNotFoundException') {\n this.vms.delete(vmId)\n externallyTerminated.push(vmId)\n logger.warn(\n { vmId, microvmId: vm.microvmId },\n '[LambdaMicrovm] vm no longer exists in AWS',\n )\n } else {\n logger.error({ vmId, err: error }, '[LambdaMicrovm] reconcile check failed')\n }\n }\n }\n\n return externallyTerminated\n }\n\n private mustGet(vmId: string): ManagedMicrovm {\n const vm = this.vms.get(vmId)\n if (!vm) throw new Error(`vm ${vmId} not found`)\n return vm\n }\n\n private setRunning(vmId: string, running: boolean): VmHandle {\n const vm = this.mustGet(vmId)\n vm.handle = { ...vm.handle, running }\n return vm.handle\n }\n\n private async getAuthHeaders(vm: ManagedMicrovm): Promise<Record<string, string>> {\n if (vm.authToken && vm.authToken.expiresAt - Date.now() > AUTH_TOKEN_REFRESH_MARGIN_MS) {\n return vm.authToken.headers\n }\n\n const resp = await this.client.send(\n new CreateMicrovmAuthTokenCommand({\n microvmIdentifier: vm.microvmId,\n expirationInMinutes: AUTH_TOKEN_TTL_MINUTES,\n allowedPorts: [{ allPorts: {} }],\n }),\n )\n if (!resp.authToken) throw new Error('create-microvm-auth-token returned no token')\n\n vm.authToken = {\n headers: resp.authToken,\n expiresAt: Date.now() + AUTH_TOKEN_TTL_MINUTES * 60_000,\n }\n return vm.authToken.headers\n }\n\n private async waitForState(microvmId: string, target: string, timeoutMs: number): Promise<void> {\n const deadline = Date.now() + timeoutMs\n for (;;) {\n const resp = await this.client.send(new GetMicrovmCommand({ microvmIdentifier: microvmId }))\n if (resp.state === target) return\n if (resp.state === 'TERMINATED' || resp.state === 'TERMINATING') {\n throw new Error(`microvm ${microvmId} entered ${resp.state} while waiting for ${target}`)\n }\n if (Date.now() > deadline) {\n throw new Error(\n `timed out waiting for microvm ${microvmId} to reach ${target} (still ${resp.state})`,\n )\n }\n await new Promise((r) => setTimeout(r, 1_000))\n }\n }\n}\n", "import http from 'http'\nimport {\n ECSClient,\n RunTaskCommand,\n StopTaskCommand,\n DescribeTasksCommand,\n DescribeTaskDefinitionCommand,\n} from '@aws-sdk/client-ecs'\nimport logger from '@multiplayer-app/logger'\nimport type {\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmRecord,\n VmRunMode,\n VmRunResult,\n VmStack,\n} from '@multiplayer-app/builder-types'\nimport type { Executor, VmHandle, VmSpec } from './types'\n\nconst JOB_POLL_INTERVAL_MS = 5_000\n\nexport interface FargateConfig {\n region?: string\n /** ECS cluster name or ARN. */\n cluster: string\n /** Default task definition (family[:revision] or ARN), used for stacks without an override. */\n taskDefinition?: string\n /** Per-stack task definition overrides, e.g. { node: 'builder-node:3' }. */\n stackTaskDefinitions?: Partial<Record<VmStack, string>>\n /** VPC subnets for awsvpc networking. */\n subnets: string[]\n securityGroups?: string[]\n /**\n * ENABLED: task gets a public IP and the worker proxies to it (worker outside the VPC).\n * DISABLED (default): the worker proxies to the task's private IP (worker inside the VPC).\n */\n assignPublicIp?: boolean\n /** Guest HTTP port the app/agent listens on. */\n guestPort?: number\n /** How long to wait for the task to reach RUNNING (image pulls can be slow). */\n startTimeoutMs?: number\n}\n\ninterface ManagedTask {\n handle: VmHandle\n taskArn: string\n ip: string\n runMode: VmRunMode\n startedAt: number\n}\n\n// Valid Fargate cpu (units) \u2192 [min, max] task memory (MiB).\nconst FARGATE_MEM_RANGES: Record<number, [number, number]> = {\n 256: [512, 2048],\n 512: [1024, 4096],\n 1024: [2048, 8192],\n 2048: [4096, 16384],\n 4096: [8192, 30720],\n}\n\n/** Snap requested VM resources to a valid Fargate cpu/memory combination. */\nexport function fargateResources(\n vcpuCount: number,\n memMib: number,\n): { cpu: string; memory: string } {\n const cpu = Math.min(4096, Math.max(256, vcpuCount * 1024))\n const [min, max] = FARGATE_MEM_RANGES[cpu]\n let memory = Math.min(max, Math.max(min, memMib))\n // Above 512 MiB, Fargate only accepts 1 GiB increments\n if (memory > 512) memory = Math.ceil(memory / 1024) * 1024\n return { cpu: String(cpu), memory: String(Math.min(max, memory)) }\n}\n\n/**\n * Runs VMs as AWS Fargate tasks (one task per VM). No VNC or serial console and no\n * pause/resume \u2014 HTTP(S) into the container only, via the task's IP on the guest port.\n * Slower to start than Lambda MicroVMs (image pull + task provisioning), but supports\n * arbitrary container images via standard ECS task definitions.\n */\nexport class FargateExecutor implements Executor {\n private readonly client: ECSClient\n private readonly vms = new Map<string, ManagedTask>()\n private readonly containerNames = new Map<string, string>()\n private readonly pendingResults = new Map<string, VmRunResult>()\n private readonly exitHandlers = new Map<string, (result: VmRunResult) => void>()\n\n constructor(private readonly config: FargateConfig) {\n this.client = new ECSClient(config.region ? { region: config.region } : {})\n }\n\n /** First container of the task definition \u2014 the target for env overrides. Cached per definition. */\n private async resolveContainerName(taskDefinition: string): Promise<string> {\n const cached = this.containerNames.get(taskDefinition)\n if (cached) return cached\n\n const described = await this.client.send(new DescribeTaskDefinitionCommand({ taskDefinition }))\n const name = described.taskDefinition?.containerDefinitions?.[0]?.name\n if (!name) throw new Error(`task definition ${taskDefinition} has no containers`)\n this.containerNames.set(taskDefinition, name)\n return name\n }\n\n private async waitForRunning(taskArn: string): Promise<string> {\n const timeoutMs = this.config.startTimeoutMs ?? 180_000\n const deadline = Date.now() + timeoutMs\n\n for (;;) {\n const described = await this.client.send(\n new DescribeTasksCommand({ cluster: this.config.cluster, tasks: [taskArn] }),\n )\n const task = described.tasks?.[0]\n if (!task) throw new Error(`task ${taskArn} not found`)\n\n if (task.lastStatus === 'STOPPED') {\n throw new Error(`fargate task stopped: ${task.stoppedReason ?? 'unknown reason'}`)\n }\n if (task.lastStatus === 'RUNNING') {\n const ip = this.config.assignPublicIp\n ? await this.resolvePublicIp(task.attachments)\n : task.containers?.[0]?.networkInterfaces?.[0]?.privateIpv4Address\n if (!ip)\n throw new Error(\n `fargate task ${taskArn} is RUNNING but has no ${this.config.assignPublicIp ? 'public' : 'private'} IP`,\n )\n return ip\n }\n if (Date.now() > deadline) {\n throw new Error(\n `fargate task did not reach RUNNING within ${timeoutMs}ms (last status: ${task.lastStatus})`,\n )\n }\n await new Promise((resolve) => setTimeout(resolve, 3000))\n }\n }\n\n private async resolvePublicIp(\n attachments: { type?: string; details?: { name?: string; value?: string }[] }[] | undefined,\n ): Promise<string | undefined> {\n const eniId = attachments\n ?.find((a) => a.type === 'ElasticNetworkInterface')\n ?.details?.find((d) => d.name === 'networkInterfaceId')?.value\n if (!eniId) return undefined\n\n const { EC2Client, DescribeNetworkInterfacesCommand } = await import('@aws-sdk/client-ec2')\n const ec2 = new EC2Client(this.config.region ? { region: this.config.region } : {})\n const described = await ec2.send(\n new DescribeNetworkInterfacesCommand({ NetworkInterfaceIds: [eniId] }),\n )\n return described.NetworkInterfaces?.[0]?.Association?.PublicIp\n }\n\n async create(spec: VmSpec): Promise<VmHandle> {\n const taskDefinition =\n this.config.stackTaskDefinitions?.[spec.stack] ?? this.config.taskDefinition\n if (!taskDefinition) {\n throw new Error(`no Fargate task definition configured for stack \"${spec.stack}\"`)\n }\n\n const containerName = await this.resolveContainerName(taskDefinition)\n const { cpu, memory } = fargateResources(spec.resources.vcpuCount, spec.resources.memMib)\n\n const run = await this.client.send(\n new RunTaskCommand({\n cluster: this.config.cluster,\n taskDefinition,\n launchType: 'FARGATE',\n count: 1,\n networkConfiguration: {\n awsvpcConfiguration: {\n subnets: this.config.subnets,\n securityGroups: this.config.securityGroups,\n assignPublicIp: this.config.assignPublicIp ? 'ENABLED' : 'DISABLED',\n },\n },\n overrides: {\n cpu,\n memory,\n containerOverrides: [\n {\n name: containerName,\n environment: [\n { name: 'VM_ID', value: spec.vmId },\n ...(spec.sessionId ? [{ name: 'SESSION_ID', value: spec.sessionId }] : []),\n { name: 'STACK', value: spec.stack },\n // Release artifact: the container agent pulls, unzips, and starts it\n ...(spec.appUrl ? [{ name: 'APP_URL', value: spec.appUrl }] : []),\n ...Object.entries(spec.env ?? {}).map(([name, value]) => ({ name, value })),\n ],\n },\n ],\n },\n tags: [\n { key: 'vmId', value: spec.vmId },\n ...(spec.sessionId ? [{ key: 'sessionId', value: spec.sessionId }] : []),\n ],\n }),\n )\n\n const taskArn = run.tasks?.[0]?.taskArn\n if (!taskArn) {\n throw new Error(`RunTask failed: ${run.failures?.[0]?.reason ?? 'no task returned'}`)\n }\n logger.info({ vmId: spec.vmId, taskArn, taskDefinition, cpu, memory }, 'fargate task started')\n\n const runMode = spec.runMode ?? 'service'\n try {\n const ip = await this.waitForRunning(taskArn)\n const handle: VmHandle = {\n vmId: spec.vmId,\n sessionId: spec.sessionId,\n stack: spec.stack,\n resources: spec.resources,\n running: true,\n metadata: { taskArn, ip },\n }\n this.vms.set(spec.vmId, { handle, taskArn, ip, runMode, startedAt: Date.now() })\n if (runMode === 'job') void this.watchJob(spec.vmId, taskArn)\n logger.info({ vmId: spec.vmId, ip, runMode }, 'fargate task running')\n return handle\n } catch (error) {\n await this.client\n .send(\n new StopTaskCommand({\n cluster: this.config.cluster,\n task: taskArn,\n reason: 'startup failed',\n }),\n )\n .catch(() => {})\n throw error\n }\n }\n\n async pause(vmId: string): Promise<VmHandle> {\n throw new Error(`fargate tasks cannot be paused (vm ${vmId})`)\n }\n\n async resume(vmId: string): Promise<VmHandle> {\n throw new Error(`fargate tasks cannot be resumed (vm ${vmId})`)\n }\n\n async restore(vmId: string): Promise<VmHandle> {\n throw new Error(`fargate tasks cannot be restored (vm ${vmId})`)\n }\n\n async stop(vmId: string): Promise<VmHandle> {\n const vm = this.mustGet(vmId)\n await this.client.send(\n new StopTaskCommand({\n cluster: this.config.cluster,\n task: vm.taskArn,\n reason: 'stopped via API',\n }),\n )\n vm.handle.running = false\n return vm.handle\n }\n\n async destroy(vmId: string): Promise<void> {\n const vm = this.vms.get(vmId)\n if (!vm) return\n await this.client\n .send(\n new StopTaskCommand({\n cluster: this.config.cluster,\n task: vm.taskArn,\n reason: 'destroyed via API',\n }),\n )\n .catch((error: Error) => logger.warn({ vmId, err: error }, 'fargate stop on destroy failed'))\n this.vms.delete(vmId)\n }\n\n get(vmId: string): VmHandle | undefined {\n return this.vms.get(vmId)?.handle\n }\n\n list(): VmHandle[] {\n return [...this.vms.values()].map((vm) => vm.handle)\n }\n\n async proxyHttp(vmId: string, request: ProxyRequestDescriptor): Promise<ProxyResponseDescriptor> {\n const vm = this.mustGet(vmId)\n if (!vm.handle.running) throw new Error(`vm ${vmId} is not running`)\n\n return new Promise((resolve, reject) => {\n const req = http.request(\n {\n host: vm.ip,\n port: this.config.guestPort ?? 8080,\n method: request.method,\n path: request.path,\n headers: request.headers,\n },\n (res) => {\n const chunks: Buffer[] = []\n res.on('data', (c: Buffer) => chunks.push(c))\n res.on('end', () =>\n resolve({\n statusCode: res.statusCode ?? 502,\n headers: Object.fromEntries(\n Object.entries(res.headers).map(([k, v]) => [\n k,\n Array.isArray(v) ? v.join(', ') : v ?? '',\n ]),\n ),\n body: Buffer.concat(chunks),\n }),\n )\n },\n )\n req.on('error', reject)\n if (request.body) req.write(request.body)\n req.end()\n })\n }\n\n /**\n * Recover a Fargate task after a worker restart. The task is an independent AWS resource\n * that outlives this process \u2014 just re-describe it by ARN and, if it's still RUNNING,\n * rebuild the local handle.\n */\n async reattach(record: VmRecord): Promise<VmHandle | undefined> {\n const meta = record.runtimeMetadata as { taskArn?: string } | undefined\n if (!meta?.taskArn) return undefined\n\n const described = await this.client\n .send(new DescribeTasksCommand({ cluster: this.config.cluster, tasks: [meta.taskArn] }))\n .catch(() => undefined)\n const task = described?.tasks?.[0]\n if (!task || task.lastStatus !== 'RUNNING') return undefined\n\n const ip = this.config.assignPublicIp\n ? await this.resolvePublicIp(task.attachments)\n : task.containers?.[0]?.networkInterfaces?.[0]?.privateIpv4Address\n if (!ip) return undefined\n\n const handle: VmHandle = {\n vmId: record.vmId,\n sessionId: record.sessionId,\n stack: record.stack,\n resources: record.resources,\n running: true,\n metadata: { taskArn: meta.taskArn, ip },\n }\n this.vms.set(record.vmId, {\n handle,\n taskArn: meta.taskArn,\n ip,\n runMode: record.runMode,\n startedAt: Date.parse(record.createdAt) || Date.now(),\n })\n if (record.runMode === 'job') void this.watchJob(record.vmId, meta.taskArn)\n logger.info({ vmId: record.vmId, taskArn: meta.taskArn, ip }, 'fargate task reattached')\n return handle\n }\n\n /**\n * No push notification exists for \"task stopped\" without EventBridge wiring (v1 doesn't set\n * that up), so poll DescribeTasks. Exit code comes straight from the container's own\n * `exitCode` field \u2014 no CloudWatch Logs integration yet, so stdout/stderr capture isn't\n * implemented for this engine (the caller can still find full output in CloudWatch directly,\n * via the task's own log configuration).\n */\n private async watchJob(vmId: string, taskArn: string): Promise<void> {\n const startedAt = this.vms.get(vmId)?.startedAt ?? Date.now()\n for (;;) {\n await new Promise((resolve) => setTimeout(resolve, JOB_POLL_INTERVAL_MS))\n if (!this.vms.has(vmId)) return // destroyed out from under the poll\n\n const described = await this.client\n .send(new DescribeTasksCommand({ cluster: this.config.cluster, tasks: [taskArn] }))\n .catch(() => undefined)\n const task = described?.tasks?.[0]\n\n if (!task) {\n this.finishJob(vmId, {\n exitCode: -1,\n stdout: '',\n stderr: 'fargate task not found while polling for completion',\n truncated: false,\n durationMs: Date.now() - startedAt,\n finishedAt: new Date().toISOString(),\n })\n return\n }\n if (task.lastStatus === 'STOPPED') {\n const exitCode = task.containers?.[0]?.exitCode\n this.finishJob(vmId, {\n exitCode: exitCode ?? 1,\n stdout: '',\n stderr: [\n task.stoppedReason ? `stoppedReason: ${task.stoppedReason}` : undefined,\n 'output capture not implemented for the fargate engine \u2014 see CloudWatch Logs for this task',\n ]\n .filter(Boolean)\n .join('; '),\n truncated: false,\n durationMs: Date.now() - startedAt,\n finishedAt: new Date().toISOString(),\n })\n return\n }\n }\n }\n\n private finishJob(vmId: string, result: VmRunResult): void {\n logger.info({ vmId, exitCode: result.exitCode }, 'fargate job task exited')\n // Keep the map entry (marked not-running) until onExit() claims the result \u2014 see\n // docker-executor's deliverJobResult comment for why route() needs get() to still work.\n const vm = this.vms.get(vmId)\n if (vm) vm.handle = { ...vm.handle, running: false }\n\n const handler = this.exitHandlers.get(vmId)\n if (handler) {\n this.exitHandlers.delete(vmId)\n this.vms.delete(vmId)\n handler(result)\n } else {\n this.pendingResults.set(vmId, result)\n }\n }\n\n onExit(vmId: string, handler: (result: VmRunResult) => void): void {\n const pending = this.pendingResults.get(vmId)\n if (pending) {\n this.pendingResults.delete(vmId)\n this.vms.delete(vmId)\n handler(pending)\n return\n }\n this.exitHandlers.set(vmId, handler)\n }\n\n private mustGet(vmId: string): ManagedTask {\n const vm = this.vms.get(vmId)\n if (!vm) throw new Error(`vm ${vmId} not found`)\n return vm\n }\n}\n", "import fs from 'fs'\nimport { execFileSync } from 'child_process'\nimport logger from '@multiplayer-app/logger'\nimport { VM_STACKS, type VmEngine } from '@multiplayer-app/builder-types'\nimport { availableStacks } from '../images'\nimport type { WorkerConfig } from '../config'\n\n/** Auto-mode default preference when multiple engines are runnable on this host. */\nconst ENGINE_PRIORITY: VmEngine[] = [\n 'firecracker',\n 'qemu',\n 'docker-sandbox',\n 'docker',\n 'lambda-microvm',\n 'fargate',\n 'remote',\n 'mock',\n]\n\nexport interface EngineProbe {\n engine: VmEngine\n available: boolean\n /** Why the engine is unavailable (for startup logs). */\n reason?: string\n}\n\nfunction binaryOnPath(bin: string): boolean {\n if (bin.includes('/')) {\n try {\n fs.accessSync(bin, fs.constants.X_OK)\n return true\n } catch {\n return false\n }\n }\n try {\n execFileSync('which', [bin], { stdio: 'ignore' })\n return true\n } catch {\n return false\n }\n}\n\nfunction kvmUsable(): boolean {\n try {\n fs.accessSync('/dev/kvm', fs.constants.R_OK | fs.constants.W_OK)\n return true\n } catch {\n return false\n }\n}\n\n/** Explicit kernel/initrd override present, or at least one stack dir with both image files. */\nfunction hasBaseImages(cfg: {\n imagesDir: string\n kernelPath?: string\n initrdPath?: string\n}): boolean {\n if (cfg.kernelPath && cfg.initrdPath)\n return fs.existsSync(cfg.kernelPath) && fs.existsSync(cfg.initrdPath)\n return availableStacks(cfg.imagesDir).length > 0\n}\n\nfunction probeQemu(config: WorkerConfig): EngineProbe {\n const { bin, accel } = config.qemu\n if (!hasBaseImages(config.qemu)) {\n return {\n engine: 'qemu',\n available: false,\n reason: `no base images under ${config.qemu.imagesDir} \u2014 run \"worker-cli images pull\" or scripts/setup-vm-images.sh`,\n }\n }\n if (!binaryOnPath(bin)) {\n return { engine: 'qemu', available: false, reason: `${bin} not found on PATH` }\n }\n if (accel === 'hvf' && process.platform !== 'darwin') {\n return {\n engine: 'qemu',\n available: false,\n reason: 'QEMU_ACCEL=hvf requires macOS (use kvm or tcg)',\n }\n }\n if (accel === 'kvm' && !kvmUsable()) {\n return {\n engine: 'qemu',\n available: false,\n reason: 'QEMU_ACCEL=kvm but /dev/kvm is not accessible',\n }\n }\n return { engine: 'qemu', available: true }\n}\n\nfunction probeFirecracker(config: WorkerConfig): EngineProbe {\n const { bin } = config.firecracker\n if (process.platform !== 'linux') {\n return { engine: 'firecracker', available: false, reason: 'requires a Linux host' }\n }\n if (!kvmUsable()) {\n return { engine: 'firecracker', available: false, reason: '/dev/kvm is not accessible' }\n }\n if (!hasBaseImages(config.firecracker)) {\n return {\n engine: 'firecracker',\n available: false,\n reason: `no base images under ${config.firecracker.imagesDir} \u2014 run \"worker-cli images pull\" or scripts/setup-vm-images.sh`,\n }\n }\n if (!binaryOnPath(bin)) {\n return { engine: 'firecracker', available: false, reason: `${bin} not found on PATH` }\n }\n return { engine: 'firecracker', available: true }\n}\n\n/** Whether at least one <imagePrefix>-<stack>:<imageTag> image exists in the local `docker` daemon. */\nfunction hasLocalDockerImage(\n bin: string,\n imagePrefix: string,\n imageTag: string,\n stackImages: Record<string, string> = {},\n): boolean {\n return VM_STACKS.some((stack) => {\n try {\n const image = stackImages[stack] ?? `${imagePrefix}-${stack}:${imageTag}`\n execFileSync(bin, ['image', 'inspect', image], { stdio: 'ignore' })\n return true\n } catch {\n return false\n }\n })\n}\n\nfunction probeDocker(config: WorkerConfig): EngineProbe {\n const { bin, imagePrefix, imageTag, stackImages } = config.docker\n if (!binaryOnPath(bin)) {\n return { engine: 'docker', available: false, reason: `${bin} not found on PATH` }\n }\n try {\n execFileSync(bin, ['info'], { stdio: 'ignore' })\n } catch {\n return { engine: 'docker', available: false, reason: 'docker daemon not reachable' }\n }\n if (!hasLocalDockerImage(bin, imagePrefix, imageTag, stackImages)) {\n return {\n engine: 'docker',\n available: false,\n reason: 'no local docker images \u2014 run scripts/setup-docker-images.sh',\n }\n }\n return { engine: 'docker', available: true }\n}\n\n/**\n * `docker-sandbox` (Docker's own Sandboxes product, the `sbx` CLI) bridges the same local\n * `docker` images in on demand (see DockerSandboxExecutor.ensureTemplateLoaded), so it needs\n * both `sbx` itself and those local images to exist. A not-yet-initialized global network\n * policy (`sbx policy init balanced|allow-all|deny-all`, required once before any sandbox can\n * be created) isn't checked here \u2014 same as Fargate detect not validating IAM permissions\n * upfront \u2014 it'll surface as a clear error the first time `create()` is called instead.\n */\nfunction probeDockerSandbox(config: WorkerConfig): EngineProbe {\n const { bin, imagePrefix, imageTag } = config.dockerSandbox\n if (!binaryOnPath(bin)) {\n return { engine: 'docker-sandbox', available: false, reason: `${bin} not found on PATH` }\n }\n try {\n execFileSync(bin, ['ls'], { stdio: 'ignore' })\n } catch {\n return {\n engine: 'docker-sandbox',\n available: false,\n reason: 'sbx daemon not reachable \u2014 run \"sbx daemon start\" and \"sbx login\"',\n }\n }\n if (!hasLocalDockerImage(config.docker.bin, imagePrefix, imageTag)) {\n return {\n engine: 'docker-sandbox',\n available: false,\n reason: 'no local docker images \u2014 run scripts/setup-docker-images.sh',\n }\n }\n return { engine: 'docker-sandbox', available: true }\n}\n\nfunction probeRemote(config: WorkerConfig): EngineProbe {\n return config.remote.agentUrl\n ? { engine: 'remote', available: true }\n : { engine: 'remote', available: false, reason: 'AGENT_URL not set' }\n}\n\nfunction probeLambdaMicrovm(config: WorkerConfig): EngineProbe {\n const { imageArn, stackImageArns } = config.lambdaMicrovm\n return imageArn || Object.keys(stackImageArns).length\n ? { engine: 'lambda-microvm', available: true }\n : {\n engine: 'lambda-microvm',\n available: false,\n reason: 'MICROVM_IMAGE_ARN / MICROVM_STACK_IMAGE_ARNS not set',\n }\n}\n\nfunction probeFargate(config: WorkerConfig): EngineProbe {\n const { cluster, taskDefinition, stackTaskDefinitions, subnets } = config.fargate\n if (!cluster) {\n return { engine: 'fargate', available: false, reason: 'FARGATE_CLUSTER not set' }\n }\n if (!taskDefinition && !Object.keys(stackTaskDefinitions).length) {\n return {\n engine: 'fargate',\n available: false,\n reason: 'FARGATE_TASK_DEFINITION / FARGATE_STACK_TASK_DEFS not set',\n }\n }\n if (!subnets.length) {\n return { engine: 'fargate', available: false, reason: 'FARGATE_SUBNETS not set' }\n }\n return { engine: 'fargate', available: true }\n}\n\n/** Probe every engine against this host + config. Mock is always runnable. */\nexport function probeEngines(config: WorkerConfig): EngineProbe[] {\n return [\n { engine: 'mock', available: true },\n probeQemu(config),\n probeFirecracker(config),\n probeDocker(config),\n probeDockerSandbox(config),\n probeRemote(config),\n probeLambdaMicrovm(config),\n probeFargate(config),\n ]\n}\n\nexport function detectEngines(config: WorkerConfig): {\n engines: VmEngine[]\n defaultEngine: VmEngine\n} {\n const probes = probeEngines(config)\n\n for (const probe of probes) {\n if (probe.available) {\n logger.info({ engine: probe.engine }, 'micro-VM engine available')\n } else {\n logger.debug({ engine: probe.engine, reason: probe.reason }, 'micro-VM engine unavailable')\n }\n }\n\n const engines = probes.filter((p) => p.available).map((p) => p.engine)\n const defaultEngine = ENGINE_PRIORITY.find((engine) => engines.includes(engine)) ?? 'mock'\n return { engines, defaultEngine }\n}\n", "import logger from '@multiplayer-app/logger'\nimport type {\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmEngine,\n VmExecRequest,\n VmExecResult,\n VmFileWrite,\n VmRecord,\n VmRunResult,\n VmWriteFilesResult,\n} from '@multiplayer-app/builder-types'\nimport { MockExecutor } from './mock-executor'\nimport { QemuExecutor } from './qemu-executor'\nimport { FirecrackerExecutor } from './firecracker-executor'\nimport { DockerExecutor } from './docker-executor'\nimport { DockerSandboxExecutor } from './docker-sandbox-executor'\nimport { RemoteExecutor } from './remote-executor'\nimport { LambdaMicrovmExecutor } from './lambda-microvm-executor'\nimport { FargateExecutor } from './fargate-executor'\nimport { detectEngines } from './detect'\nimport type { Executor, SerialSource, VmHandle, VmSpec } from './types'\nimport type { WorkerConfig } from '../config'\n\nexport type { Executor, SerialSource, VmHandle, VmSpec } from './types'\n\n/** Internal marker: reattach ran cleanly but confirmed the resource itself is gone. */\nclass VmResourceGoneError extends Error {}\n\n/**\n * Of the VM records sandbox says this workerId owns, the ones this executor isn't already\n * tracking in memory \u2014 i.e. the ones actually worth attempting to reattach. A plain reconnect\n * (network blip, not a real process restart) never loses in-memory state, so this naturally\n * comes back empty in that case.\n */\nexport function findNotAttachedVms(\n executor: Pick<Executor, 'get'>,\n records: VmRecord[],\n): VmRecord[] {\n return records.filter((record) => !executor.get(record.vmId))\n}\n\n/** Only called for engines `detectEngines` reported runnable, so prerequisites are already verified. */\nfunction createEngineExecutor(engine: VmEngine, config: WorkerConfig): Executor {\n switch (engine) {\n case 'mock':\n return new MockExecutor()\n case 'qemu':\n return new QemuExecutor(config.qemu)\n case 'firecracker':\n return new FirecrackerExecutor(config.firecracker)\n case 'docker':\n return new DockerExecutor(config.docker)\n case 'docker-sandbox':\n return new DockerSandboxExecutor(config.dockerSandbox)\n case 'remote':\n return new RemoteExecutor(config.remote)\n case 'lambda-microvm':\n return new LambdaMicrovmExecutor(config.lambdaMicrovm)\n case 'fargate':\n return new FargateExecutor(config.fargate)\n default:\n throw new Error(`unknown engine \"${engine as string}\"`)\n }\n}\n\n/**\n * Routes VM operations to per-engine executors. `create` picks the executor from\n * `spec.engine` (falling back to the worker default); every other operation is\n * routed to whichever executor owns the vmId.\n */\nexport class MultiEngineExecutor implements Executor {\n private readonly creations = new Map<string, Promise<VmHandle>>()\n\n constructor(\n private readonly executors: Map<VmEngine, Executor>,\n readonly defaultEngine: VmEngine,\n ) {}\n\n get engines(): VmEngine[] {\n return [...this.executors.keys()]\n }\n\n async create(spec: VmSpec): Promise<VmHandle> {\n const existing = this.get(spec.vmId)\n if (existing) return existing\n\n const pending = this.creations.get(spec.vmId)\n if (pending) return pending\n\n const creation = this.createOnce(spec)\n this.creations.set(spec.vmId, creation)\n try {\n return await creation\n } finally {\n this.creations.delete(spec.vmId)\n }\n }\n\n private async createOnce(spec: VmSpec): Promise<VmHandle> {\n const engine = spec.engine ?? this.defaultEngine\n const executor = this.executors.get(engine)\n if (!executor) {\n throw new Error(\n `engine \"${engine}\" is not available on this worker (available: ${this.engines.join(', ')})`,\n )\n }\n const handle = await executor.create(spec)\n return { ...handle, engine }\n }\n\n // async here isn't a no-op: route() throws synchronously when the vmId isn't tracked in any\n // executor's in-memory map (e.g. worker restarted and hasn't reattached this VM yet). Without\n // `async`, that throw escapes as a real exception instead of a rejected promise \u2014 which,\n // called from socket-client.ts's wrap(), skips its .catch() entirely and leaves the command\n // un-acked until the caller's timeout, looking like the action \"does nothing\".\n async pause(vmId: string): Promise<VmHandle> {\n return this.route(vmId).pause(vmId)\n }\n async resume(vmId: string): Promise<VmHandle> {\n return this.route(vmId).resume(vmId)\n }\n async stop(vmId: string): Promise<VmHandle> {\n return this.route(vmId).stop(vmId)\n }\n async restore(vmId: string): Promise<VmHandle> {\n return this.route(vmId).restore(vmId)\n }\n async destroy(vmId: string): Promise<void> {\n return this.route(vmId).destroy(vmId)\n }\n\n async proxyHttp(vmId: string, request: ProxyRequestDescriptor): Promise<ProxyResponseDescriptor> {\n return this.route(vmId).proxyHttp(vmId, request)\n }\n\n get(vmId: string): VmHandle | undefined {\n for (const executor of this.executors.values()) {\n const handle = executor.get(vmId)\n if (handle) return handle\n }\n return undefined\n }\n\n list(): VmHandle[] {\n return [...this.executors.values()].flatMap((executor) => executor.list())\n }\n\n getSerialSource(vmId: string): SerialSource | undefined {\n for (const executor of this.executors.values()) {\n if (executor.get(vmId)) return executor.getSerialSource?.(vmId)\n }\n return undefined\n }\n\n async exec(vmId: string, request: VmExecRequest): Promise<VmExecResult> {\n const executor = this.route(vmId)\n if (!executor.exec) throw new Error('executor does not support guest exec')\n return executor.exec(vmId, request)\n }\n\n async writeFiles(vmId: string, files: VmFileWrite[]): Promise<VmWriteFilesResult> {\n const executor = this.route(vmId)\n if (!executor.writeFiles) throw new Error('executor does not support guest file writes')\n return executor.writeFiles(vmId, files)\n }\n\n onExit(vmId: string, handler: (result: VmRunResult) => void): void {\n const executor = this.route(vmId)\n if (!executor.onExit) throw new Error('executor does not support job run mode')\n executor.onExit(vmId, handler)\n }\n\n /** Fans out to every sub-executor that supports it (currently just lambda-microvm). */\n async reconcile(): Promise<string[]> {\n const externallyTerminated: string[] = []\n for (const executor of this.executors.values()) {\n if (!executor.reconcile) continue\n externallyTerminated.push(...(await executor.reconcile()))\n }\n return externallyTerminated\n }\n\n /**\n * Recover VMs sandbox says this workerId owns but that aren't currently tracked (a worker\n * restart, most likely). Runs in parallel \u2014 probing many VMs serially would needlessly\n * delay the first heartbeat, which reports capacity from `list()` and must reflect\n * reattached VMs to avoid sandbox overbooking this worker. Best-effort: failures are logged,\n * never thrown \u2014 a VM that can't be reattached just stays unavailable until something\n * touches it again (create/proxy/lifecycle), which already errors gracefully today.\n */\n /**\n * Returns vmIds found genuinely gone (executor.reattach resolved undefined \u2014 the\n * resource itself no longer exists, e.g. AWS already terminated it while this worker\n * was down) as distinct from any other reattach failure (engine unavailable, no reattach\n * support, a transient describe error, ...), which leave the VM merely unavailable\n * rather than confirmed gone.\n */\n async reattachAll(records: VmRecord[]): Promise<string[]> {\n const pending = findNotAttachedVms(this, records)\n if (!pending.length) return []\n\n const results = await Promise.allSettled(\n pending.map(async (record) => {\n const executor = record.engine ? this.executors.get(record.engine) : undefined\n if (!executor)\n throw new Error(`engine \"${record.engine ?? 'unknown'}\" not available on this worker`)\n if (!executor.reattach)\n throw new Error(`engine \"${record.engine}\" does not support reattach`)\n const handle = await executor.reattach(record)\n if (!handle) throw new VmResourceGoneError()\n }),\n )\n\n const externallyTerminated: string[] = []\n results.forEach((result, i) => {\n const vmId = pending[i].vmId\n if (result.status === 'fulfilled') {\n logger.info({ vmId }, 'vm reattached')\n } else if (result.reason instanceof VmResourceGoneError) {\n externallyTerminated.push(vmId)\n logger.warn({ vmId }, 'vm reattach found resource already gone')\n } else {\n logger.warn(\n { vmId, err: result.reason },\n 'vm reattach failed \u2014 staying unavailable until next touch',\n )\n }\n })\n return externallyTerminated\n }\n\n private route(vmId: string): Executor {\n for (const executor of this.executors.values()) {\n if (executor.get(vmId)) return executor\n }\n throw new Error(`vm ${vmId} not found on this worker`)\n }\n}\n\n/**\n * Probes the host (KVM, HVF, binaries, images, ARNs) and registers every runnable engine,\n * defaulting to the most capable one. Per-VM engine selection comes from the create request.\n */\nexport function createExecutor(config: WorkerConfig): MultiEngineExecutor {\n const { engines, defaultEngine } = detectEngines(config)\n\n const executors = new Map<VmEngine, Executor>()\n for (const engine of engines) {\n executors.set(engine, createEngineExecutor(engine, config))\n }\n\n logger.info({ engines, defaultEngine }, 'micro-VM engines initialized')\n return new MultiEngineExecutor(executors, defaultEngine)\n}\n", "import os from 'os'\nimport { io, type Socket } from 'socket.io-client'\nimport logger from '@multiplayer-app/logger'\nimport type {\n CommandAck,\n ProxyRequestDescriptor,\n ProxyResponseDescriptor,\n VmExecRequest,\n VmFileWrite,\n VmCreateResultPayload,\n VmRecord,\n WorkerHeartbeat,\n} from '@multiplayer-app/builder-types'\nimport { WorkerEvent } from '@multiplayer-app/builder-types'\nimport type { WorkerConfig } from './config'\nimport { WORKER_VERSION } from './config'\nimport type { MultiEngineExecutor, VmSpec } from './executor'\nimport { loadPersistedWorkerId, savePersistedWorkerId } from './worker-identity'\n\nconst HEARTBEAT_INTERVAL_MS = 10_000\n// AWS's own idle-suspend/max-duration policies can terminate a Lambda MicroVM with no\n// command from this worker \u2014 this drives Executor.reconcile() to catch that drift. Much\n// slower than heartbeat: this is a safety net for a state a worker restart's REATTACH\n// handshake would also eventually catch, not a latency-sensitive signal.\nconst RECONCILE_INTERVAL_MS = 60_000\n// If sandbox never sends the reattach handshake (older version, edge case), start\n// heartbeating anyway rather than hanging the connection forever.\nconst REATTACH_FALLBACK_MS = 5_000\n// Retry forever \u2014 a gateway restart/deploy is a transient outage, not a reason to give up.\n// VMs keep running locally the whole time; reconnecting just resumes heartbeats/reattach.\nconst RECONNECTION_DELAY_MS = 1_000\nconst RECONNECTION_DELAY_MAX_MS = 10_000\n\nfunction primaryIp(): string | undefined {\n for (const ifaces of Object.values(os.networkInterfaces())) {\n for (const iface of ifaces ?? []) {\n if (!iface.internal && iface.family === 'IPv4') return iface.address\n }\n }\n return undefined\n}\n\nfunction buildHeartbeat(config: WorkerConfig, executor: MultiEngineExecutor): WorkerHeartbeat {\n return {\n hostname: os.hostname(),\n ip: primaryIp(),\n region: config.region,\n version: WORKER_VERSION,\n engines: executor.engines,\n defaultEngine: executor.defaultEngine,\n capacity: {\n maxVms: config.maxVms,\n usedVms: executor.list().length,\n cpuCores: os.cpus().length,\n memMib: Math.round(os.totalmem() / (1024 * 1024)),\n },\n }\n}\n\nfunction wrap<TPayload, TResult>(\n handler: (payload: TPayload) => Promise<TResult>,\n): (payload: TPayload, callback: (ack: CommandAck<TResult>) => void) => void {\n return (payload, callback) => {\n handler(payload)\n .then((result) => callback({ ok: true, result }))\n .catch((error: Error) => {\n logger.error({ err: error }, 'command failed')\n // A failed command (e.g. a VM_CREATE rejected by the underlying engine) must only\n // fail that one request \u2014 never take down the worker process. Guard the ack itself\n // too: if callback() throws (e.g. the socket ack already timed out), that throw would\n // otherwise become an unhandled rejection with no further .catch() to absorb it.\n try {\n callback({ ok: false, error: error.message })\n } catch (ackError) {\n logger.error({ err: ackError }, 'failed to send command failure ack')\n }\n })\n }\n}\n\nfunction registerCommandHandlers(socket: Socket, executor: MultiEngineExecutor): void {\n socket.on(\n WorkerEvent.VM_CREATE,\n wrap(async (spec: VmSpec) => {\n try {\n const handle = await executor.create(spec)\n if (spec.runMode === 'job') {\n executor.onExit(spec.vmId, (result) =>\n socket.emit(WorkerEvent.VM_RUN_EXITED, { vmId: spec.vmId, ...result }),\n )\n }\n const result: VmCreateResultPayload = {\n vmId: spec.vmId,\n ok: true,\n metadata: handle.metadata,\n }\n socket.emit(WorkerEvent.VM_CREATE_RESULT, result)\n return handle\n } catch (error) {\n // The engine doesn't support job mode \u2014 don't leave an orphaned resource behind.\n if (spec.runMode === 'job') await executor.destroy(spec.vmId).catch(() => {})\n const result: VmCreateResultPayload = {\n vmId: spec.vmId,\n ok: false,\n error: error instanceof Error ? error.message : String(error),\n }\n socket.emit(WorkerEvent.VM_CREATE_RESULT, result)\n throw error\n }\n }),\n )\n socket.on(\n WorkerEvent.VM_PAUSE,\n wrap(({ vmId }: { vmId: string }) => executor.pause(vmId)),\n )\n socket.on(\n WorkerEvent.VM_RESUME,\n wrap(({ vmId }: { vmId: string }) => executor.resume(vmId)),\n )\n socket.on(\n WorkerEvent.VM_STOP,\n wrap(({ vmId }: { vmId: string }) => executor.stop(vmId)),\n )\n socket.on(\n WorkerEvent.VM_RESTORE,\n wrap(({ vmId }: { vmId: string }) => executor.restore(vmId)),\n )\n socket.on(\n WorkerEvent.VM_DESTROY,\n wrap(({ vmId }: { vmId: string }) => executor.destroy(vmId)),\n )\n\n socket.on(\n WorkerEvent.PROXY_HTTP,\n wrap(\n ({\n vmId,\n ...request\n }: ProxyRequestDescriptor & { vmId: string }): Promise<ProxyResponseDescriptor> =>\n executor.proxyHttp(vmId, request),\n ),\n )\n\n socket.on(\n WorkerEvent.VM_EXEC,\n wrap(({ vmId, ...request }: VmExecRequest & { vmId: string }) => {\n if (!executor.exec) {\n return Promise.reject(new Error('executor does not support guest exec'))\n }\n return executor.exec(vmId, request)\n }),\n )\n\n socket.on(\n WorkerEvent.VM_WRITE_FILES,\n wrap(({ vmId, files }: { vmId: string; files: VmFileWrite[] }) => {\n if (!executor.writeFiles) {\n return Promise.reject(new Error('executor does not support guest file writes'))\n }\n return executor.writeFiles(vmId, files)\n }),\n )\n}\n\nexport function connectToSandbox(config: WorkerConfig, executor: MultiEngineExecutor): Socket {\n // Seed from a prior boot's assigned ID, if this process persisted one \u2014 otherwise the\n // gateway mints a fresh one below, same as a first-ever boot.\n let assignedWorkerId: string | undefined = loadPersistedWorkerId(config.workerIdFile)\n const socket = io(config.sandboxUrl, {\n path: config.workerSocketPath,\n auth: (callback) =>\n callback({\n workerId: config.workerId,\n ...(assignedWorkerId ? { assignedWorkerId } : {}),\n ...(config.token ? { token: config.token } : {}),\n }),\n transports: ['websocket'],\n reconnection: true,\n reconnectionAttempts: Infinity,\n reconnectionDelay: RECONNECTION_DELAY_MS,\n reconnectionDelayMax: RECONNECTION_DELAY_MAX_MS,\n })\n\n let heartbeatTimer: NodeJS.Timeout | undefined\n let reconcileTimer: NodeJS.Timeout | undefined\n let reattachFallbackTimer: NodeJS.Timeout | undefined\n\n socket.on(WorkerEvent.ASSIGNED_ID, ({ workerId }: { workerId: string }) => {\n assignedWorkerId = workerId\n savePersistedWorkerId(config.workerIdFile, workerId)\n logger.info({ workerId: config.workerId, assignedWorkerId }, 'worker runtime ID assigned')\n })\n\n const sendHeartbeat = () => socket.emit(WorkerEvent.HEARTBEAT, buildHeartbeat(config, executor))\n\n function startHeartbeat(): void {\n if (heartbeatTimer) return // already running for this connection\n sendHeartbeat()\n heartbeatTimer = setInterval(sendHeartbeat, HEARTBEAT_INTERVAL_MS)\n }\n\n const runReconcile = () => {\n executor\n .reconcile()\n .then((externallyTerminated) => {\n for (const vmId of externallyTerminated) {\n socket.emit(WorkerEvent.VM_EXTERNALLY_TERMINATED, { vmId })\n }\n })\n .catch((error: Error) => logger.error({ err: error }, 'vm reconcile pass failed'))\n }\n\n function startReconcile(): void {\n if (reconcileTimer) return // already running for this connection\n reconcileTimer = setInterval(runReconcile, RECONCILE_INTERVAL_MS)\n }\n\n socket.on('connect', () => {\n logger.info(\n { workerId: config.workerId, assignedWorkerId, url: config.sandboxUrl },\n 'connected to sandbox',\n )\n\n // Sandbox emits REATTACH once, right after auth, listing any VMs it thinks this worker\n // still owns. Reattach them before the first heartbeat so capacity.usedVms is accurate \u2014\n // otherwise sandbox could schedule new VMs onto capacity that's actually already in use.\n socket.off(WorkerEvent.REATTACH)\n reattachFallbackTimer = setTimeout(() => {\n logger.warn(\n { workerId: config.workerId },\n 'no reattach handshake from sandbox \u2014 starting heartbeat anyway',\n )\n startHeartbeat()\n startReconcile()\n }, REATTACH_FALLBACK_MS)\n\n socket.once(WorkerEvent.REATTACH, (records: VmRecord[]) => {\n clearTimeout(reattachFallbackTimer)\n executor\n .reattachAll(records)\n .then((externallyTerminated) => {\n for (const vmId of externallyTerminated) {\n socket.emit(WorkerEvent.VM_EXTERNALLY_TERMINATED, { vmId })\n }\n })\n .catch((error: Error) => logger.error({ err: error }, 'reattach batch failed'))\n .finally(() => {\n // A create result may have been lost while this worker was disconnected. Successful\n // reattachment is enough to finalize any control-plane record still in 'creating'.\n for (const record of records) {\n const handle = executor.get(record.vmId)\n if (record.state === 'creating' && handle) {\n const result: VmCreateResultPayload = {\n vmId: record.vmId,\n ok: true,\n metadata: handle.metadata,\n }\n socket.emit(WorkerEvent.VM_CREATE_RESULT, result)\n }\n }\n\n // Reattached job VMs may already have a result waiting (finished while this worker\n // was offline) or may still be running \u2014 either way, re-register so its eventual\n // VM_RUN_EXITED gets (re-)sent now that we're connected again.\n for (const record of records) {\n if (record.runMode !== 'job' || !executor.get(record.vmId)) continue\n try {\n executor.onExit(record.vmId, (result) =>\n socket.emit(WorkerEvent.VM_RUN_EXITED, { vmId: record.vmId, ...result }),\n )\n } catch (error) {\n logger.warn(\n { vmId: record.vmId, err: error },\n 'reattached job vm has no onExit support',\n )\n }\n }\n startHeartbeat()\n startReconcile()\n })\n })\n })\n\n socket.on('disconnect', (reason) => {\n logger.warn({ workerId: config.workerId, reason }, 'disconnected from sandbox')\n clearInterval(heartbeatTimer)\n clearInterval(reconcileTimer)\n clearTimeout(reattachFallbackTimer)\n heartbeatTimer = undefined\n reconcileTimer = undefined\n socket.off(WorkerEvent.REATTACH)\n })\n\n socket.on('connect_error', (error) => {\n logger.error(\n {\n err: error,\n sandboxUrl: config.sandboxUrl,\n },\n 'sandbox connection error',\n )\n })\n\n // Reconnection events fire on the Manager (socket.io), not the Socket itself \u2014 'connect'\n // above already fires again on every successful reconnect (restarting heartbeat/reattach),\n // this is purely for visibility into retries while the gateway is down (e.g. mid-restart).\n socket.io.on('reconnect_attempt', (attempt) => {\n logger.warn({ workerId: config.workerId, attempt }, 'reconnecting to sandbox')\n })\n socket.io.on('reconnect_error', (error) => {\n logger.warn({ workerId: config.workerId, err: error }, 'sandbox reconnect attempt failed')\n })\n socket.io.on('reconnect', (attempt) => {\n logger.info({ workerId: config.workerId, attempt }, 'reconnected to sandbox')\n })\n\n registerCommandHandlers(socket, executor)\n\n return socket\n}\n", "import fs from 'fs'\nimport path from 'path'\nimport logger from '@multiplayer-app/logger'\n\n/**\n * Reads back the gateway-assigned runtime routing ID (WorkerEvent.ASSIGNED_ID) this\n * process persisted on a previous boot, if any \u2014 lets a restarted worker present the same\n * identity it had before, so REATTACH's `findByWorkerId` still finds its VMs. Missing file,\n * unreadable, or empty all just mean \"no prior identity\" (first boot, fresh volume, etc.) \u2014\n * not an error; the worker falls back to letting the gateway mint a new one, same as today.\n */\nexport function loadPersistedWorkerId(filePath: string): string | undefined {\n try {\n const id = fs.readFileSync(filePath, 'utf8').trim()\n return id || undefined\n } catch {\n return undefined\n }\n}\n\n/** Best-effort \u2014 a failed write only costs the next restart's reattach, not this session. */\nexport function savePersistedWorkerId(filePath: string, workerId: string): void {\n try {\n fs.mkdirSync(path.dirname(filePath), { recursive: true })\n fs.writeFileSync(filePath, workerId, 'utf8')\n } catch (error) {\n logger.warn(\n { err: error, filePath },\n 'failed to persist assigned worker id \u2014 reattach after a restart may not find its VMs',\n )\n }\n}\n", "import rfb from 'rfb2'\nimport type { Socket } from 'socket.io-client'\nimport logger from '@multiplayer-app/logger'\nimport {\n WorkerEvent,\n type VncFramePayload,\n type VncCopyFramePayload,\n type VncMousePayload,\n type VncKeyboardPayload,\n} from '@multiplayer-app/builder-types'\n\nfunction bgraToRgba(src: Buffer): Buffer {\n const dst = Buffer.allocUnsafe(src.length)\n for (let i = 0; i < src.length; i += 4) {\n dst[i] = src[i + 2]\n dst[i + 1] = src[i + 1]\n dst[i + 2] = src[i]\n dst[i + 3] = 0xff\n }\n return dst\n}\n\n/** Connects to a QEMU VNC server and relays frames upstream to the sandbox socket. */\nexport class VncRelay {\n private rfbc: ReturnType<typeof rfb.createConnection> & any = null\n private interval: ReturnType<typeof setInterval> | null = null\n private mouseHandler: ((e: VncMousePayload) => void) | null = null\n private keyHandler: ((e: VncKeyboardPayload) => void) | null = null\n\n constructor(\n private readonly vmId: string,\n private readonly host: string,\n private readonly port: number,\n private readonly socket: Socket,\n ) {}\n\n start(): void {\n this.rfbc = rfb.createConnection({ host: this.host, port: this.port, password: '' })\n const rfbc = this.rfbc\n\n rfbc.on('connect', () => {\n rfbc.autoUpdate = true\n this.socket.emit(WorkerEvent.VNC_INIT, {\n vmId: this.vmId,\n width: rfbc.width,\n height: rfbc.height,\n })\n this.interval = setInterval(() => {\n rfbc.requestUpdate(false, 0, 0, rfbc.width, rfbc.height)\n }, 300)\n })\n\n rfbc.on('rect', (rect: any) => {\n switch (rect.encoding) {\n case rfb.encodings.raw: {\n const frame: VncFramePayload = {\n vmId: this.vmId,\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n encoding: 'raw',\n data: bgraToRgba(rect.data),\n }\n this.socket.emit(WorkerEvent.VNC_FRAME, frame)\n break\n }\n case rfb.encodings.copyRect: {\n const frame: VncCopyFramePayload = {\n vmId: this.vmId,\n x: rect.x,\n y: rect.y,\n src: rect.src,\n width: rect.width,\n height: rect.height,\n }\n this.socket.emit(WorkerEvent.VNC_COPY_FRAME, frame)\n break\n }\n }\n })\n\n // Guest display init/resize (e.g. QEMU placeholder 640x480 \u2192 guest fb 1280x800).\n // rfb2 updates rfbc.width/height itself; re-announce dimensions and pull a\n // full frame so browsers aren't stuck on the pre-boot placeholder.\n rfbc.on('resize', (rect: { width: number; height: number }) => {\n logger.info(\n { vmId: this.vmId, width: rect.width, height: rect.height },\n '[VNC] desktop resized',\n )\n this.socket.emit(WorkerEvent.VNC_INIT, {\n vmId: this.vmId,\n width: rect.width,\n height: rect.height,\n })\n rfbc.requestUpdate(false, 0, 0, rect.width, rect.height)\n })\n\n rfbc.on('error', (err: Error) => logger.error({ vmId: this.vmId, err }, '[VNC] RFB error'))\n\n this.mouseHandler = (e: VncMousePayload) => {\n if (e.vmId === this.vmId) rfbc.pointerEvent(e.x, e.y, e.button)\n }\n this.keyHandler = (e: VncKeyboardPayload) => {\n if (e.vmId === this.vmId) rfbc.keyEvent(e.keyCode, e.isDown)\n }\n this.socket.on(WorkerEvent.VNC_MOUSE, this.mouseHandler)\n this.socket.on(WorkerEvent.VNC_KEYBOARD, this.keyHandler)\n logger.info({ vmId: this.vmId, port: this.port }, '[VNC] relay started')\n }\n\n destroy(): void {\n if (this.interval) clearInterval(this.interval)\n if (this.mouseHandler) this.socket.off(WorkerEvent.VNC_MOUSE, this.mouseHandler)\n if (this.keyHandler) this.socket.off(WorkerEvent.VNC_KEYBOARD, this.keyHandler)\n try {\n this.rfbc?.end()\n } catch {}\n this.rfbc = null\n logger.info({ vmId: this.vmId }, '[VNC] relay destroyed')\n }\n}\n", "import net from 'net'\nimport type { ChildProcess } from 'child_process'\nimport type { Socket } from 'socket.io-client'\nimport WebSocket, { type RawData } from 'ws'\nimport logger from '@multiplayer-app/logger'\nimport { WorkerEvent, type TerminalInputPayload } from '@multiplayer-app/builder-types'\nimport type { SerialSource } from '../executor/types'\n\n/** Relays VM serial console data upstream to the sandbox socket. */\nexport class SerialRelay {\n private conn: net.Socket | null = null\n private webSocket: WebSocket | null = null\n private reconnectTimer: NodeJS.Timeout | null = null\n private connecting = false\n private browserCount = 0\n private pendingInput: string[] = []\n private destroyed = false\n private inputHandler: ((e: TerminalInputPayload) => void) | null = null\n private attachHandler: ((e: { vmId: string }) => void) | null = null\n private detachHandler: ((e: { vmId: string }) => void) | null = null\n\n constructor(\n private readonly vmId: string,\n private readonly source: SerialSource,\n private readonly socket: Socket,\n ) {}\n\n connect(): void {\n this.destroyed = false\n if (this.source.type === 'tcp') {\n this.connectTcp()\n } else if (this.source.type === 'pipe') {\n this.connectPipe()\n } else {\n // AWS shell connections are authenticated and count as MicroVM endpoint activity.\n // Keep the connection lazy so a VM with no browser attached can still auto-suspend.\n this.attachHandler = ({ vmId }) => {\n if (vmId !== this.vmId) return\n this.browserCount += 1\n if (this.browserCount === 1) void this.connectWebSocket()\n }\n this.detachHandler = ({ vmId }) => {\n if (vmId !== this.vmId) return\n this.browserCount = Math.max(0, this.browserCount - 1)\n if (this.browserCount === 0) this.disconnectWebSocket()\n }\n this.socket.on(WorkerEvent.TERMINAL_ATTACH, this.attachHandler)\n this.socket.on(WorkerEvent.TERMINAL_DETACH, this.detachHandler)\n }\n\n this.inputHandler = (e: TerminalInputPayload) => {\n if (e.vmId !== this.vmId) return\n if (this.source.type === 'tcp' && this.conn) {\n this.conn.write(e.data)\n } else if (this.source.type === 'pipe') {\n const proc = (this.source as { type: 'pipe'; process: ChildProcess }).process\n proc.stdin?.write(e.data)\n } else if (this.source.type === 'websocket') {\n if (this.webSocket?.readyState === WebSocket.OPEN) {\n this.webSocket.send(e.data)\n } else {\n // Attach can race VM creation or a worker reconnect. Treat real input as proof that\n // a browser is present, establish the shell, and replay the keystroke once it opens.\n this.browserCount = Math.max(1, this.browserCount)\n this.pendingInput.push(e.data)\n if (this.pendingInput.length > 100) this.pendingInput.shift()\n void this.connectWebSocket()\n }\n }\n }\n this.socket.on(WorkerEvent.TERMINAL_INPUT, this.inputHandler)\n }\n\n private connectTcp(): void {\n const { host, port } = this.source as { type: 'tcp'; host: string; port: number }\n const attempt = () => {\n const sock = net.createConnection(port, host)\n sock.once('connect', () => {\n this.conn = sock\n logger.info({ vmId: this.vmId, port }, '[Serial] TCP connected')\n sock.on('data', (d: Buffer) =>\n this.socket.emit(WorkerEvent.TERMINAL_DATA, { vmId: this.vmId, data: d }),\n )\n sock.on('end', () => logger.info({ vmId: this.vmId }, '[Serial] TCP ended'))\n sock.on('error', (err) => logger.error({ vmId: this.vmId, err }, '[Serial] TCP error'))\n })\n sock.once('error', () => {\n if (!this.destroyed) setTimeout(attempt, 1_000)\n })\n }\n attempt()\n }\n\n private connectPipe(): void {\n const { process: proc } = this.source as { type: 'pipe'; process: ChildProcess }\n proc.stdout?.on('data', (d: Buffer) =>\n this.socket.emit(WorkerEvent.TERMINAL_DATA, { vmId: this.vmId, data: d }),\n )\n proc.stderr?.on('data', (d: Buffer) =>\n this.socket.emit(WorkerEvent.TERMINAL_DATA, { vmId: this.vmId, data: d }),\n )\n }\n\n private async connectWebSocket(): Promise<void> {\n if (\n this.destroyed ||\n this.browserCount === 0 ||\n this.source.type !== 'websocket' ||\n this.webSocket ||\n this.connecting\n ) {\n return\n }\n\n try {\n this.connecting = true\n const protocols = await this.source.protocols()\n if (this.destroyed || this.browserCount === 0) return\n\n const webSocket = new WebSocket(this.source.url, protocols)\n this.webSocket = webSocket\n webSocket.on('open', () => {\n for (const data of this.pendingInput.splice(0)) webSocket.send(data)\n logger.info({ vmId: this.vmId }, '[Serial] Lambda shell connected')\n })\n webSocket.on('message', (data: RawData) => {\n const chunk = Array.isArray(data)\n ? Buffer.concat(data)\n : Buffer.isBuffer(data)\n ? data\n : Buffer.from(data)\n this.socket.emit(WorkerEvent.TERMINAL_DATA, { vmId: this.vmId, data: chunk })\n })\n webSocket.on('error', (error) => {\n logger.error({ vmId: this.vmId, err: error }, '[Serial] Lambda shell error')\n })\n webSocket.on('close', () => {\n if (this.webSocket === webSocket) this.webSocket = null\n logger.info({ vmId: this.vmId }, '[Serial] Lambda shell disconnected')\n this.scheduleWebSocketReconnect()\n })\n } catch (error) {\n logger.error({ vmId: this.vmId, err: error }, '[Serial] Lambda shell connect failed')\n this.scheduleWebSocketReconnect()\n } finally {\n this.connecting = false\n }\n }\n\n private scheduleWebSocketReconnect(): void {\n if (this.destroyed || this.browserCount === 0 || this.reconnectTimer) return\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null\n void this.connectWebSocket()\n }, 1_000)\n }\n\n private disconnectWebSocket(): void {\n if (this.reconnectTimer) clearTimeout(this.reconnectTimer)\n this.reconnectTimer = null\n this.pendingInput = []\n const webSocket = this.webSocket\n this.webSocket = null\n webSocket?.close()\n }\n\n destroy(): void {\n this.destroyed = true\n if (this.inputHandler) this.socket.off(WorkerEvent.TERMINAL_INPUT, this.inputHandler)\n if (this.attachHandler) this.socket.off(WorkerEvent.TERMINAL_ATTACH, this.attachHandler)\n if (this.detachHandler) this.socket.off(WorkerEvent.TERMINAL_DETACH, this.detachHandler)\n try {\n this.conn?.destroy()\n } catch {}\n this.conn = null\n this.disconnectWebSocket()\n logger.info({ vmId: this.vmId }, '[Serial] relay destroyed')\n }\n}\n", "import type { Socket } from 'socket.io-client'\nimport type { MultiEngineExecutor } from './executor'\nimport { VncRelay } from './services/vnc-relay'\nimport { SerialRelay } from './services/serial-relay'\n\n/**\n * Wires up VNC and terminal relays for any executor that exposes console endpoints (QEMU: VNC +\n * serial TCP ports; Firecracker: serial via process stdio pipe; Lambda MicroVM: authenticated\n * shell WebSocket). All media flows through the sandbox socket to browsers \u2014 the worker never\n * accepts inbound connections from the internet. Wraps create/reattach/destroy in place.\n */\nexport function attachConsoleRelays(executor: MultiEngineExecutor, sandboxSocket: Socket): void {\n const relays = new Map<string, { vnc?: VncRelay; serial?: SerialRelay }>()\n\n const attach = (handle: NonNullable<ReturnType<MultiEngineExecutor['get']>>): void => {\n if (relays.has(handle.vmId)) return\n const entry: { vnc?: VncRelay; serial?: SerialRelay } = {}\n\n if (handle.vncPort) {\n const vnc = new VncRelay(handle.vmId, '127.0.0.1', handle.vncPort, sandboxSocket)\n vnc.start()\n entry.vnc = vnc\n }\n\n const serialSource = handle.serialPort\n ? { type: 'tcp' as const, host: '127.0.0.1', port: handle.serialPort }\n : executor.getSerialSource?.(handle.vmId)\n if (serialSource) {\n const serial = new SerialRelay(handle.vmId, serialSource, sandboxSocket)\n serial.connect()\n entry.serial = serial\n }\n\n if (entry.vnc || entry.serial) relays.set(handle.vmId, entry)\n }\n\n const originalCreate = executor.create.bind(executor)\n executor.create = async (spec) => {\n const handle = await originalCreate(spec)\n attach(handle)\n return handle\n }\n\n const originalReattachAll = executor.reattachAll.bind(executor)\n executor.reattachAll = async (records) => {\n const externallyTerminated = await originalReattachAll(records)\n for (const record of records) {\n const handle = executor.get(record.vmId)\n if (handle) attach(handle)\n }\n return externallyTerminated\n }\n\n const originalDestroy = executor.destroy.bind(executor)\n executor.destroy = async (vmId) => {\n const entry = relays.get(vmId)\n entry?.vnc?.destroy()\n entry?.serial?.destroy()\n relays.delete(vmId)\n return originalDestroy(vmId)\n }\n}\n", "import { execFile } from 'child_process'\nimport { promisify } from 'util'\nimport type { WorkerConfig } from './config'\nimport { availableStacks, hostArch, PUBLISHED_IMAGE_STACKS, pullImages } from './images'\nimport { version as WORKER_VERSION } from '../package.json'\n\nconst execFileAsync = promisify(execFile)\n\nexport function artifactImageLocation(env: NodeJS.ProcessEnv = process.env): string | undefined {\n const bucket = env.S3_BUCKET_ARTIFACTS?.trim()\n if (!bucket) return undefined\n if (bucket.includes('/') || bucket.includes('://')) {\n throw new Error('S3_BUCKET_ARTIFACTS must contain only the bucket name (no scheme or path)')\n }\n const version = env.NODE_ENV === 'development' || env.BUILDER_ENV === 'local'\n ? 'local'\n : WORKER_VERSION\n return `s3://${bucket}/${version}/qemu`\n}\n\nfunction allStacksAvailable(imagesDir: string): boolean {\n const available = new Set(availableStacks(imagesDir))\n return PUBLISHED_IMAGE_STACKS.every((stack) => available.has(stack))\n}\n\nasync function dockerAvailable(bin: string): Promise<boolean> {\n try {\n await execFileAsync(bin, ['info'])\n return true\n } catch {\n return false\n }\n}\n\nasync function dockerImageExists(bin: string, image: string): Promise<boolean> {\n try {\n await execFileAsync(bin, ['image', 'inspect', image])\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Materialize remotely published images before engine detection.\n *\n * S3_BUCKET_ARTIFACTS is the artifact bucket name. The worker derives the\n * environment/version and runner prefix; pullImages appends\n * <arch>/<stack>/<file>.\n * Registry-backed Docker images are pulled whenever the configured prefix is\n * a qualified repository (contains a slash), while local development prefixes\n * continue to require locally built images.\n */\nexport async function prepareWorkerImages(\n config: WorkerConfig,\n env: NodeJS.ProcessEnv = process.env,\n): Promise<void> {\n const vmImagesUrl = artifactImageLocation(env)\n const refreshVmImages = env.VM_IMAGES_REFRESH === 'true'\n if (vmImagesUrl) {\n const destinations = new Set([config.qemu.imagesDir, config.firecracker.imagesDir])\n for (const imagesDir of destinations) {\n if (!refreshVmImages && allStacksAvailable(imagesDir)) continue\n await pullImages({\n location: vmImagesUrl,\n arch: hostArch(),\n endpoint: env.S3_ARTIFACTS_ENDPOINT,\n }, imagesDir)\n }\n }\n\n const shouldPullDocker = env.DOCKER_PULL_IMAGES === 'true'\n || (env.DOCKER_PULL_IMAGES !== 'false' && config.docker.imagePrefix.includes('/'))\n if (!shouldPullDocker || !await dockerAvailable(config.docker.bin)) return\n\n for (const stack of PUBLISHED_IMAGE_STACKS) {\n const image = config.docker.stackImages[stack]\n ?? `${config.docker.imagePrefix}-${stack}:${config.docker.imageTag}`\n if (!await dockerImageExists(config.docker.bin, image)) {\n await execFileAsync(config.docker.bin, ['pull', image])\n }\n }\n}\n", "import http, { type IncomingMessage, type Server, type ServerResponse } from 'http'\n\nexport interface SandboxHealthServerOptions {\n host: string\n port: number\n pathPrefix: string\n isReady: () => boolean\n}\n\n/** Local probe server under API_PREFIX: /healthz is liveness; /health is readiness. */\nexport async function startSandboxHealthServer(\n options: SandboxHealthServerOptions,\n): Promise<Server> {\n const server = http.createServer((req: IncomingMessage, res: ServerResponse) => {\n const pathname = new URL(req.url ?? '/', 'http://localhost').pathname\n if (pathname === `${options.pathPrefix}/healthz`) {\n res.writeHead(200, { 'content-type': 'application/json' })\n res.end(JSON.stringify({ ok: true, status: 'alive' }))\n return\n }\n if (pathname === `${options.pathPrefix}/health`) {\n const ready = options.isReady()\n res.writeHead(ready ? 200 : 503, { 'content-type': 'application/json' })\n res.end(JSON.stringify({ ok: ready, status: ready ? 'ready' : 'not-ready' }))\n return\n }\n res.writeHead(404, { 'content-type': 'application/json' })\n res.end(JSON.stringify({ ok: false, error: 'not found' }))\n })\n\n await new Promise<void>((resolve, reject) => {\n server.listen(options.port, options.host, resolve)\n server.once('error', reject)\n })\n return server\n}\n", "// Builds this package's own guest-agent base images (node/python/static) and registers/updates\n// them as AWS Lambda MicroVM images \u2014 in the caller's own AWS account, using whatever\n// credentials are ambient (AWS_PROFILE, env vars, an assumed role, ...). No repo checkout, no\n// Docker daemon, no external `zip` binary: everything is generated and zipped in-memory (see\n// microvm-guest-agents.ts), so this works the same way whether run from this monorepo's own\n// CI or from `npx @multiplayer-app/sandbox images microvm-create` in a client's own project.\n//\n// Each stack maps to one stable-named image (\"<prefix>-<stack>\", e.g. \"sandbox-node\"). The\n// first run creates it; every subsequent run updates it in place, which AWS records as a new\n// numbered version (visible as \"Active version\" in the console) rather than a new image\n// resource \u2014 so the image's ARN never changes across runs, and workers configured with it\n// always use whichever version is currently active.\nimport { ZipArchive } from 'archiver'\nimport {\n LambdaMicrovmsClient,\n CreateMicrovmImageCommand,\n UpdateMicrovmImageCommand,\n GetMicrovmImageCommand,\n GetMicrovmImageVersionCommand,\n ListManagedMicrovmImagesCommand,\n} from '@aws-sdk/client-lambda-microvms'\nimport { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'\nimport { version as SANDBOX_VERSION } from '../package.json'\nimport {\n MICROVM_BASE_IMAGE_STACKS,\n guestAgentFiles,\n isMicrovmBaseImageStack,\n type MicrovmBaseImageStack,\n} from './microvm-guest-agents'\n\nexport interface CreateMicrovmImagesOptions {\n region: string\n /** S3 bucket the built code artifact is uploaded to (must already exist). */\n bucket: string\n /** AWS-managed base OS image ARN \u2014 discover one with listBaseMicrovmImages(). */\n baseImageArn: string\n /** IAM role ARN the build assumes to read the artifact from `bucket` (needs s3:GetObject). */\n buildRoleArn: string\n /** Stacks to build/register (default: all of MICROVM_BASE_IMAGE_STACKS). */\n stacks?: MicrovmBaseImageStack[]\n /** Minimum guest memory, MiB (default: 1024). */\n minMemoryMib?: number\n /** MicroVM image name prefix, \"<prefix>-<stack>\" (default: 'sandbox'). */\n imageNamePrefix?: string\n /** Image-build poll interval, ms (default: 5000). */\n pollIntervalMs?: number\n /** Image-build poll timeout, ms (default: 600000 = 10 min). */\n pollTimeoutMs?: number\n /** Called after each step so callers (CLI, CI) can report progress. Optional. */\n onProgress?: (message: string) => void\n}\n\nexport interface CreateMicrovmImagesResult {\n /** stack -> the image ARN that's now active, ready to use as MICROVM_STACK_IMAGE_ARNS. */\n stackArns: Record<string, string>\n}\n\nconst HOOKS = {\n port: 8080,\n microvmHooks: { run: 'ENABLED', resume: 'ENABLED', suspend: 'ENABLED', terminate: 'ENABLED' },\n microvmImageHooks: { ready: 'ENABLED' },\n} as const\n\n/** Zips an in-memory file map (name -> contents) without touching disk or shelling out. */\nasync function zipFiles(files: Record<string, string>): Promise<Buffer> {\n const archive = new ZipArchive({ zlib: { level: 9 } })\n const chunks: Buffer[] = []\n const collected = new Promise<Buffer>((resolve, reject) => {\n archive.on('data', (chunk: Buffer) => chunks.push(chunk))\n archive.on('error', reject)\n archive.on('end', () => resolve(Buffer.concat(chunks)))\n })\n for (const [name, content] of Object.entries(files)) {\n archive.append(content, { name })\n }\n await archive.finalize()\n return collected\n}\n\nasync function listAllManagedImages(\n client: LambdaMicrovmsClient,\n): Promise<{ imageArn?: string }[]> {\n const images: { imageArn?: string }[] = []\n let nextToken: string | undefined\n do {\n const page = await client.send(new ListManagedMicrovmImagesCommand({ nextToken }))\n images.push(...(page.items ?? []))\n nextToken = page.nextToken\n } while (nextToken)\n return images\n}\n\n/** AWS-managed base OS images available as a `baseImageArn` candidate in this region. */\nexport async function listBaseMicrovmImages(options: { region: string }): Promise<string[]> {\n const client = new LambdaMicrovmsClient({ region: options.region })\n const images = await listAllManagedImages(client)\n return images.map((image) => image.imageArn).filter((arn): arn is string => Boolean(arn))\n}\n\nasync function imageExists(\n client: LambdaMicrovmsClient,\n imageIdentifier: string,\n): Promise<boolean> {\n try {\n await client.send(new GetMicrovmImageCommand({ imageIdentifier }))\n return true\n } catch (error) {\n if (error instanceof Error && error.name === 'ResourceNotFoundException') return false\n throw error\n }\n}\n\n/** A version's build state is tracked separately from the parent image's own state. */\nasync function waitForVersion(\n client: LambdaMicrovmsClient,\n imageIdentifier: string,\n imageVersion: string | undefined,\n pollIntervalMs: number,\n pollTimeoutMs: number,\n): Promise<void> {\n const deadline = Date.now() + pollTimeoutMs\n for (;;) {\n const version = await client.send(\n new GetMicrovmImageVersionCommand({ imageIdentifier, imageVersion }),\n )\n if (version.state === 'SUCCESSFUL') return\n if (version.state === 'FAILED') {\n throw new Error(`${imageIdentifier} version ${imageVersion} failed to build`)\n }\n if (Date.now() > deadline) {\n throw new Error(\n `timed out waiting for ${imageIdentifier} version ${imageVersion} (still ${version.state})`,\n )\n }\n await new Promise((resolve) => setTimeout(resolve, pollIntervalMs))\n }\n}\n\n/**\n * Builds and registers/updates the guest-agent base images for `options.stacks`, in the\n * caller's own AWS account. Returns the stack -> image ARN map once every image's new version\n * has finished building (polled).\n */\nexport async function createMicrovmImages(\n options: CreateMicrovmImagesOptions,\n): Promise<CreateMicrovmImagesResult> {\n const {\n region,\n bucket,\n baseImageArn,\n buildRoleArn,\n stacks = [...MICROVM_BASE_IMAGE_STACKS],\n minMemoryMib = 1024,\n imageNamePrefix = 'sandbox',\n pollIntervalMs = 5_000,\n pollTimeoutMs = 600_000,\n onProgress = () => {},\n } = options\n\n for (const stack of stacks) {\n if (!isMicrovmBaseImageStack(stack)) {\n throw new Error(\n `unsupported stack \"${stack}\" \u2014 must be one of: ${MICROVM_BASE_IMAGE_STACKS.join(', ')}`,\n )\n }\n }\n\n // GetMicrovmImage/UpdateMicrovmImage require a full ARN identifier (unlike RunMicrovmCommand,\n // which also accepts a bare name) \u2014 build it from the account ID embedded in the build role\n // ARN rather than pulling in an STS dependency just to call GetCallerIdentity.\n const accountId = buildRoleArn.split(':')[4]\n if (!accountId) throw new Error(`could not parse account ID from buildRoleArn: ${buildRoleArn}`)\n\n // The SDK's Architecture enum only defines ARM_64 today \u2014 Lambda MicroVMs is Graviton-only\n // right now (AWS's own pricing page only publishes ARM/Graviton rates too). Not configurable\n // because there's currently nothing else valid to configure it to.\n const cpuArchitecture = 'ARM_64' as const\n const s3 = new S3Client({ region })\n const lambdaMicrovms = new LambdaMicrovmsClient({ region })\n const stackArns: Record<string, string> = {}\n\n for (const stack of stacks) {\n const files = guestAgentFiles(stack)\n const zip = await zipFiles(files)\n const key = `microvm-images/${stack}/app.zip`\n onProgress(`[${stack}] uploading ${zip.byteLength}-byte artifact -> s3://${bucket}/${key}`)\n await s3.send(new PutObjectCommand({ Bucket: bucket, Key: key, Body: zip }))\n\n const imageName = `${imageNamePrefix}-${stack}`\n const imageArn = `arn:aws:lambda:${region}:${accountId}:microvm-image:${imageName}`\n const commonFields = {\n baseImageArn,\n buildRoleArn,\n codeArtifact: { uri: `s3://${bucket}/${key}` },\n cpuConfigurations: [{ architecture: cpuArchitecture }],\n resources: [{ minimumMemoryInMiB: minMemoryMib }],\n description: `sandbox v${SANDBOX_VERSION}`,\n hooks: HOOKS,\n }\n\n const exists = await imageExists(lambdaMicrovms, imageArn)\n onProgress(`[${stack}] ${exists ? 'updating' : 'creating'} MicroVM image ${imageName}...`)\n const result = exists\n ? await lambdaMicrovms.send(\n new UpdateMicrovmImageCommand({ imageIdentifier: imageArn, ...commonFields }),\n )\n : await lambdaMicrovms.send(\n new CreateMicrovmImageCommand({ name: imageName, tags: { stack }, ...commonFields }),\n )\n\n onProgress(`[${stack}] waiting for version ${result.imageVersion} to build...`)\n await waitForVersion(\n lambdaMicrovms,\n imageArn,\n result.imageVersion,\n pollIntervalMs,\n pollTimeoutMs,\n )\n const finalArn = result.imageArn ?? imageArn\n onProgress(`[${stack}] ready: ${finalArn} (version ${result.imageVersion})`)\n stackArns[stack] = finalArn\n }\n\n return { stackArns }\n}\n", "/**\n * Guest-agent source for each stack's Lambda MicroVM base image, as a set of in-memory files\n * (zipped and uploaded by microvm-images.ts \u2014 no disk/build step needed).\n *\n * Kept in sync BY HAND with scripts/base-images/{node,python,static}/build.sh, which the\n * internal build-base-images.sh pipeline still uses for QEMU/Firecracker/Docker images (those\n * need a real build host, so unifying the two isn't in scope here) \u2014 if you change one, change\n * the other. The agent itself: an HTTP server on :8080 that answers the Lambda MicroVM\n * lifecycle hooks (/aws/lambda-microvms/runtime/v1/*) and {\"status\":\"ok\"} elsewhere. The /run\n * hook payload (vmId/sessionId/stack/env from the worker executor) is kept in memory and\n * echoed back so the control plane can identify the VM.\n */\n\nexport const MICROVM_BASE_IMAGE_STACKS = ['node', 'python', 'static'] as const\nexport type MicrovmBaseImageStack = (typeof MICROVM_BASE_IMAGE_STACKS)[number]\n\nexport function isMicrovmBaseImageStack(stack: string): stack is MicrovmBaseImageStack {\n return (MICROVM_BASE_IMAGE_STACKS as readonly string[]).includes(stack)\n}\n\nconst NODE_APP = `const http = require('http')\nconst fs = require('fs')\nconst { execSync, spawn } = require('child_process')\n\nconst HOOK_PREFIX = '/aws/lambda-microvms/runtime/v1/'\nlet session = null // set by the /run hook (payload from the worker executor)\n\n// Release deployment: pull the presigned artifact, unzip, then hand :8080 over\n// to the app (it must answer the lifecycle hooks itself from that point on).\nasync function startApp(url) {\n try {\n const res = await fetch(url)\n if (!res.ok) throw new Error(\\`artifact download failed: HTTP \\${res.status}\\`)\n fs.writeFileSync('/tmp/app.zip', Buffer.from(await res.arrayBuffer()))\n execSync('unzip -o -q /tmp/app.zip -d /workspace')\n server.close(() => {\n console.log('starting release app (node app.js)')\n const child = spawn('node', ['app.js'], { cwd: '/workspace', stdio: 'inherit' })\n child.on('exit', (code) => process.exit(code ?? 1))\n })\n } catch (error) {\n console.error('release deploy failed, agent keeps serving:', error)\n }\n}\n\nconst server = http.createServer((req, res) => {\n if (req.url.startsWith(HOOK_PREFIX) && req.method === 'POST') {\n const hook = req.url.slice(HOOK_PREFIX.length)\n const chunks = []\n req.on('data', (c) => chunks.push(c))\n req.on('end', () => {\n const body = Buffer.concat(chunks).toString()\n if (hook === 'run' && body) {\n try {\n const parsed = JSON.parse(body)\n session = parsed.runHookPayload ? JSON.parse(parsed.runHookPayload) : null\n session = { ...session, microvmId: parsed.microvmId }\n for (const [key, value] of Object.entries(session?.env ?? {})) {\n if (typeof value === 'string') process.env[key] = value\n }\n } catch { /* payload is optional */ }\n }\n // Runtime env may contain a presigned release URL or other secrets; never log the body.\n console.log(\\`lifecycle hook: \\${hook}\\`)\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end('{}')\n if (hook === 'run' && process.env.APP_URL) {\n setImmediate(() => startApp(process.env.APP_URL))\n }\n })\n return\n }\n\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({ status: 'ok', path: req.url, session }))\n})\n\nserver.listen(8080, () => {\n console.log('vm agent listening on 8080')\n // Fargate/Docker: no lifecycle hook caller, so APP_URL (if set) drives startup directly.\n if (process.env.APP_URL) setImmediate(() => startApp(process.env.APP_URL))\n})\n`\n\nconst NODE_DOCKERFILE = `FROM node:24-alpine\nWORKDIR /app\nCOPY app.js .\nRUN mkdir -p /workspace\nEXPOSE 8080\nCMD [\"node\", \"app.js\"]\n`\n\nconst PYTHON_APP = `import json\nimport os\nimport threading\nimport urllib.request\nimport zipfile\nfrom http.server import BaseHTTPRequestHandler, ThreadingHTTPServer\n\nHOOK_PREFIX = \"/aws/lambda-microvms/runtime/v1/\"\nsession = None # set by the /run hook (payload from the worker executor)\n\n\ndef start_app(url):\n \"\"\"Release deployment: pull the presigned artifact, unzip, then replace this\n process with the app on :8080 (it must answer lifecycle hooks itself).\"\"\"\n try:\n urllib.request.urlretrieve(url, \"/tmp/app.zip\")\n with zipfile.ZipFile(\"/tmp/app.zip\") as zf:\n zf.extractall(\"/workspace\")\n print(\"starting release app (python app.py)\", flush=True)\n os.chdir(\"/workspace\")\n os.execvp(\"python\", [\"python\", \"app.py\"])\n except Exception as error: # noqa: BLE001 \u2014 agent keeps serving on failure\n print(f\"release deploy failed, agent keeps serving: {error}\", flush=True)\n\n\nclass Handler(BaseHTTPRequestHandler):\n def _send(self, body):\n data = body.encode()\n self.send_response(200)\n self.send_header(\"Content-Type\", \"application/json\")\n self.send_header(\"Content-Length\", str(len(data)))\n self.end_headers()\n self.wfile.write(data)\n\n def do_POST(self):\n global session\n if self.path.startswith(HOOK_PREFIX):\n hook = self.path[len(HOOK_PREFIX):]\n length = int(self.headers.get(\"Content-Length\") or 0)\n body = self.rfile.read(length).decode() if length else \"\"\n if hook == \"run\" and body:\n try:\n parsed = json.loads(body)\n payload = parsed.get(\"runHookPayload\")\n session = json.loads(payload) if payload else {}\n session[\"microvmId\"] = parsed.get(\"microvmId\")\n os.environ.update({\n key: value for key, value in session.get(\"env\", {}).items()\n if isinstance(value, str)\n })\n except (ValueError, TypeError):\n pass # payload is optional\n # Runtime env may contain a presigned release URL or other secrets.\n print(f\"lifecycle hook: {hook}\")\n self._send(\"{}\")\n if hook == \"run\" and os.environ.get(\"APP_URL\"):\n threading.Timer(0.1, start_app, args=[os.environ[\"APP_URL\"]]).start()\n return\n self._send(json.dumps({\"status\": \"ok\", \"path\": self.path, \"session\": session}))\n\n def do_GET(self):\n self._send(json.dumps({\"status\": \"ok\", \"path\": self.path, \"session\": session}))\n\n def log_message(self, fmt, *args):\n pass\n\n\nif __name__ == \"__main__\":\n print(\"vm agent listening on 8080\")\n # Fargate/Docker: no lifecycle hook caller, so APP_URL (if set) drives startup directly.\n if os.environ.get(\"APP_URL\"):\n threading.Timer(0.1, start_app, args=[os.environ[\"APP_URL\"]]).start()\n ThreadingHTTPServer((\"\", 8080), Handler).serve_forever()\n`\n\nconst PYTHON_DOCKERFILE = `FROM python:3.12-alpine\nWORKDIR /app\nCOPY app.py .\nRUN mkdir -p /workspace\nEXPOSE 8080\nCMD [\"python\", \"app.py\"]\n`\n\nconst STATIC_APP = `const http = require('http')\nconst fs = require('fs')\nconst path = require('path')\nconst { execSync } = require('child_process')\n\nconst HOOK_PREFIX = '/aws/lambda-microvms/runtime/v1/'\nconst STATIC_ROOT = '/workspace'\nlet session = null // set by the /run hook (payload from the worker executor)\nlet serving = false // true once a release has been unzipped into STATIC_ROOT\n\nconst CONTENT_TYPES = {\n '.html': 'text/html; charset=utf-8',\n '.htm': 'text/html; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.js': 'text/javascript; charset=utf-8',\n '.mjs': 'text/javascript; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.ico': 'image/x-icon',\n '.txt': 'text/plain; charset=utf-8',\n '.wasm': 'application/wasm',\n}\n\n// Release deployment: pull the presigned artifact, unzip it into STATIC_ROOT, and\n// switch the request handler into \"serve static files\" mode. No process is spawned \u2014\n// unlike the node/python base images, there is no entrypoint to run.\nasync function deployRelease(url) {\n const res = await fetch(url)\n if (!res.ok) throw new Error(\\`artifact download failed: HTTP \\${res.status}\\`)\n fs.mkdirSync(STATIC_ROOT, { recursive: true })\n fs.writeFileSync('/tmp/site.zip', Buffer.from(await res.arrayBuffer()))\n execSync(\\`unzip -o -q /tmp/site.zip -d \\${STATIC_ROOT}\\`)\n fs.rmSync('/tmp/site.zip', { force: true })\n serving = true\n console.log('serving static release from', STATIC_ROOT)\n}\n\nfunction serveStatic(req, res) {\n const urlPath = decodeURIComponent(req.url.split('?')[0])\n let filePath = path.join(STATIC_ROOT, path.normalize(urlPath).replace(/^(\\\\.\\\\.[/\\\\\\\\])+/, ''))\n if (urlPath.endsWith('/') || urlPath === '') filePath = path.join(filePath, 'index.html')\n\n fs.readFile(filePath, (err, data) => {\n if (err) {\n // SPA-style fallback: unknown paths without a file extension serve index.html\n if (!path.extname(filePath)) {\n return fs.readFile(path.join(STATIC_ROOT, 'index.html'), (err2, index) => {\n if (err2) return send404(res)\n res.writeHead(200, { 'Content-Type': CONTENT_TYPES['.html'] })\n res.end(index)\n })\n }\n return send404(res)\n }\n const ext = path.extname(filePath).toLowerCase()\n res.writeHead(200, { 'Content-Type': CONTENT_TYPES[ext] ?? 'application/octet-stream' })\n res.end(data)\n })\n}\n\nfunction send404(res) {\n res.writeHead(404, { 'Content-Type': 'text/plain' })\n res.end('not found')\n}\n\nconst server = http.createServer((req, res) => {\n if (req.url.startsWith(HOOK_PREFIX) && req.method === 'POST') {\n const hook = req.url.slice(HOOK_PREFIX.length)\n const chunks = []\n req.on('data', (c) => chunks.push(c))\n req.on('end', () => {\n const body = Buffer.concat(chunks).toString()\n if (hook === 'run' && body) {\n try {\n const parsed = JSON.parse(body)\n session = parsed.runHookPayload ? JSON.parse(parsed.runHookPayload) : null\n session = { ...session, microvmId: parsed.microvmId }\n for (const [key, value] of Object.entries(session?.env ?? {})) {\n if (typeof value === 'string') process.env[key] = value\n }\n } catch { /* payload is optional */ }\n }\n // Runtime env may contain a presigned release URL or other secrets; never log the body.\n console.log(\\`lifecycle hook: \\${hook}\\`)\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end('{}')\n if (hook === 'run' && process.env.APP_URL) {\n deployRelease(process.env.APP_URL).catch((error) => console.error('release deploy failed:', error))\n }\n })\n return\n }\n\n if (serving) return serveStatic(req, res)\n\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({ status: 'ok', path: req.url, session }))\n})\n\nserver.listen(8080, () => {\n console.log('vm agent listening on 8080')\n // Fargate/Docker: no lifecycle hook caller, so APP_URL (if set) drives startup directly.\n if (process.env.APP_URL) deployRelease(process.env.APP_URL).catch((error) => console.error('release deploy failed:', error))\n})\n`\n\nconst STATIC_DOCKERFILE = `FROM node:24-alpine\nRUN apk add --no-cache unzip\nWORKDIR /app\nCOPY app.js .\nRUN mkdir -p /workspace\nEXPOSE 8080\nCMD [\"node\", \"app.js\"]\n`\n\n/** Files to zip for `stack`'s base image, relative paths -> contents. */\nexport function guestAgentFiles(stack: MicrovmBaseImageStack): Record<string, string> {\n switch (stack) {\n case 'node':\n return { 'app.js': NODE_APP, Dockerfile: NODE_DOCKERFILE }\n case 'python':\n return { 'app.py': PYTHON_APP, Dockerfile: PYTHON_DOCKERFILE }\n case 'static':\n return { 'app.js': STATIC_APP, Dockerfile: STATIC_DOCKERFILE }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_config", "import_os", "import_path", "path", "os", "fs", "S3Client", "PutObjectCommand", "os", "path", "import_os", "bunyan", "import_bunyan", "import_os", "HOST_NAME", "import_promises", "import_os", "import_path", "path", "http", "fs", "os", "import_child_process", "import_http", "import_path", "import_promises", "import_os", "MAX_OUTPUT_BYTES", "path", "os", "fs", "vm", "http", "net", "import_child_process", "import_http", "import_net", "import_path", "import_promises", "import_os", "MAX_OUTPUT_BYTES", "JOB_EXIT_SENTINEL", "path", "os", "fs", "waitForHttp", "http", "net", "import_child_process", "import_util", "import_http", "DEFAULT_EXEC_TIMEOUT_MS", "MAX_EXEC_TIMEOUT_MS", "MAX_OUTPUT_BYTES", "MAX_FILE_BYTES", "http", "import_child_process", "import_util", "import_promises", "import_os", "import_path", "import_http", "DEFAULT_EXEC_TIMEOUT_MS", "MAX_EXEC_TIMEOUT_MS", "MAX_OUTPUT_BYTES", "MAX_FILE_BYTES", "WORKSPACE_DIR", "execFileAsync", "assertSafeWorkspacePath", "path", "os", "fs", "http", "import_http", "path", "https", "http", "import_https", "https", "import_http", "JOB_POLL_INTERVAL_MS", "http", "import_fs", "import_child_process", "fs", "import_os", "import_fs", "import_path", "fs", "path", "os", "result", "rfb", "import_net", "WebSocket", "net", "import_child_process", "import_util", "execFileAsync", "version", "import_http", "http", "import_client_lambda_microvms", "images", "version"]
|
|
7
7
|
}
|