@mastra/deployer-sandbox 0.1.2 → 0.1.3

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/alias.ts","../src/engine.ts","../src/manifest.ts","../src/deployer.ts"],"names":["join","readFile"],"mappings":"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","file":"index.js","sourcesContent":["import type { SandboxAliasOptions } from './types';\n\n/**\n * Upsert a Vercel Edge Config item so a stable key always points at the\n * current sandbox URL. Used for Tier 3 routing: apps read the key from Edge\n * Config (e.g. in middleware) instead of hardcoding the rotating sandbox URL.\n */\nexport async function updateEdgeConfigAlias(options: SandboxAliasOptions & { url: string }): Promise<void> {\n const { token, teamId } = options;\n if (!token) {\n throw new Error('Updating the Edge Config alias requires a Vercel API token. Pass `alias.token`.');\n }\n\n const endpoint = new URL(`https://api.vercel.com/v1/edge-config/${options.edgeConfigId}/items`);\n if (teamId) {\n endpoint.searchParams.set('teamId', teamId);\n }\n\n const res = await fetch(endpoint, {\n method: 'PATCH',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n items: [{ operation: 'upsert', key: options.key, value: options.url }],\n }),\n // Bounded so a hung Vercel API request can't keep `mastra build` open\n // after the sandbox itself is already deployed.\n signal: AbortSignal.timeout(30_000),\n });\n\n if (!res.ok) {\n const body = await res.text().catch(() => '');\n throw new Error(`Failed to update Edge Config alias \"${options.key}\" (${res.status}): ${body}`);\n }\n}\n","import { execFile } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport { existsSync } from 'node:fs';\nimport { mkdtemp, readFile, rm } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { promisify } from 'node:util';\nimport { supportsNetworking } from '@mastra/core/workspace';\nimport type { WorkspaceSandbox } from '@mastra/core/workspace';\nimport {\n DEFAULT_PORT,\n INSTALL_MARKER,\n SERVER_LOGFILE,\n SERVER_PIDFILE,\n SERVER_SCRIPT,\n getInfoSafe,\n killPreviousServer,\n launchServer,\n resolveRemoteDir,\n runInSandbox,\n shellQuote,\n tailServerLog,\n waitForHealthy,\n} from './shared';\nimport type { DeployToSandboxOptions, SandboxDeployLogger, SandboxDeployment } from './types';\n\nconst execFileAsync = promisify(execFile);\n\nconst noopLogger: SandboxDeployLogger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\n/** Max shell-command payload per chunk for the base64 upload fallback. */\nconst UPLOAD_CHUNK_SIZE = 96_000;\n\n/**\n * Deploy a prebuilt Mastra server directory into any workspace sandbox that\n * supports networking. Provider-agnostic: only uses the core WorkspaceSandbox\n * contract (`executeCommand` + `networking`, with `writeFiles` / `processes`\n * as fast paths).\n */\nexport async function deployToSandbox(options: DeployToSandboxOptions): Promise<SandboxDeployment> {\n const {\n sandbox,\n dir,\n port = DEFAULT_PORT,\n env = {},\n studio = false,\n healthCheckPath = '/api',\n healthCheckTimeoutMs = 60_000,\n healthCheckIntervalMs = 1_000,\n installCommand = 'npm install --omit=dev',\n logger = noopLogger,\n } = options;\n\n if (!existsSync(join(dir, 'index.mjs'))) {\n throw new Error(`No index.mjs found in \"${dir}\" — did the build succeed?`);\n }\n\n // 1. Start (providers handle create-or-resume by identity, e.g. sandbox name).\n logger.info(`Starting ${sandbox.provider} sandbox...`);\n await sandbox.start?.();\n\n if (!supportsNetworking(sandbox)) {\n throw new Error(\n `Sandbox provider \"${sandbox.provider}\" does not support networking (public port URLs), ` +\n `which is required for sandbox deploys.`,\n );\n }\n if (!sandbox.executeCommand) {\n throw new Error(\n `Sandbox provider \"${sandbox.provider}\" does not support executeCommand, which is required for sandbox deploys.`,\n );\n }\n\n const url = await sandbox.networking.getPortUrl(port);\n if (!url) {\n throw new Error(\n `Sandbox provider \"${sandbox.provider}\" did not expose a public URL for port ${port}. ` +\n `Make sure the port is declared when constructing the sandbox (e.g. \\`ports: [${port}]\\`).`,\n );\n }\n\n // Default the remote dir to $HOME/mastra-app — home directories persist\n // across snapshot stop/resume (unlike /tmp), so wakes find the app intact.\n const remoteDir = await resolveRemoteDir(sandbox, options.remoteDir);\n\n const mergedEnv = { ...env };\n if (studio && mergedEnv.MASTRA_STUDIO_PATH === undefined) {\n mergedEnv.MASTRA_STUDIO_PATH = `${remoteDir}/studio`;\n }\n\n // 2. Upload the build output as a tarball and extract it in the sandbox.\n logger.info(`Uploading build output from ${dir}...`);\n const tarball = await createTarball(dir);\n logger.debug(`Tarball size: ${(tarball.length / 1024 / 1024).toFixed(2)} MB`);\n\n const remoteTarball = `${remoteDir}/.deploy.tgz`;\n await runInSandbox(sandbox, `mkdir -p ${shellQuote(remoteDir)}`);\n await uploadFile(sandbox, remoteTarball, tarball);\n\n // Stop the previous server BEFORE extracting over the live directory so it\n // can never serve a mix of old and new files while the release lands.\n await killPreviousServer(sandbox, remoteDir);\n\n await runInSandbox(sandbox, `cd ${shellQuote(remoteDir)} && tar -xzf .deploy.tgz && rm -f .deploy.tgz`, {\n timeout: 120_000,\n });\n\n // 3. Install dependencies, skipped when the install inputs (package.json,\n // bundled lockfiles, and the install command itself) are unchanged since\n // the last completed install.\n const installHash = await hashInstallInputs(dir, installCommand);\n const marker = `${remoteDir}/${INSTALL_MARKER}`;\n const markerCheck = await runInSandbox(sandbox, `cat ${shellQuote(marker)} 2>/dev/null || true`, {\n allowFailure: true,\n });\n\n if (installHash && markerCheck.stdout.trim() === installHash) {\n logger.info('Dependencies unchanged — skipping install.');\n } else {\n logger.info(`Installing dependencies (${installCommand})...`);\n await runInSandbox(sandbox, `cd ${shellQuote(remoteDir)} && ${installCommand}`, {\n timeout: 600_000,\n label: `install dependencies (${installCommand})`,\n });\n if (installHash) {\n await runInSandbox(sandbox, `printf '%s' ${shellQuote(installHash)} > ${shellQuote(marker)}`);\n }\n }\n\n // 4. Write the launch script and start the new server (the previous one was\n // stopped before extraction).\n const launchScript = buildLaunchScript({ remoteDir, port, env: mergedEnv });\n await uploadFile(sandbox, `${remoteDir}/${SERVER_SCRIPT}`, Buffer.from(launchScript));\n await runInSandbox(sandbox, `chmod 700 ${shellQuote(`${remoteDir}/${SERVER_SCRIPT}`)}`);\n\n logger.info('Starting Mastra server...');\n await launchServer(sandbox, remoteDir);\n\n // 5. Wait for the server to answer on its public URL.\n const healthy = await waitForHealthy(url, {\n path: healthCheckPath,\n timeoutMs: healthCheckTimeoutMs,\n intervalMs: healthCheckIntervalMs,\n });\n if (!healthy) {\n const log = await tailServerLog(sandbox, remoteDir).catch(() => '');\n throw new Error(\n `Mastra server did not become healthy at ${url}${healthCheckPath} within ${healthCheckTimeoutMs}ms.` +\n (log ? `\\n\\nServer log:\\n${log}` : '\\n\\n(no server log output captured)'),\n );\n }\n\n const info = await getInfoSafe(sandbox);\n\n return {\n url,\n sandboxId: info?.id ?? sandbox.id,\n expiresAt: info?.timeoutAt,\n stop: async () => {\n await sandbox.stop?.();\n },\n destroy: async () => {\n await sandbox.destroy?.();\n },\n logs: (lines?: number) => tailServerLog(sandbox, remoteDir, lines),\n };\n}\n\n/**\n * Build the POSIX launch script. Re-running the script restarts the server —\n * the wake path uses this after a snapshot resume (which restores the\n * filesystem but not processes).\n */\nexport function buildLaunchScript(opts: { remoteDir: string; port: number; env: Record<string, string> }): string {\n const lines = ['#!/bin/sh', `cd ${shellQuote(opts.remoteDir)}`];\n\n // MASTRA_AUTO_DETECT_URL so Studio connects to the sandbox's public URL\n // (same origin) instead of localhost:4111 — overridable. PORT and\n // MASTRA_HOST are applied AFTER custom env: networking (`getPortUrl`) and\n // health checks target the configured port, and the server must bind\n // 0.0.0.0 to be reachable through the public port proxy. Change the port\n // via the deploy `port` option, not env.\n const env: Record<string, string> = {\n MASTRA_AUTO_DETECT_URL: 'true',\n ...opts.env,\n PORT: String(opts.port),\n MASTRA_HOST: '0.0.0.0',\n };\n for (const [key, value] of Object.entries(env)) {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {\n throw new Error(`Invalid environment variable name: \"${key}\"`);\n }\n lines.push(`export ${key}=${shellQuote(value)}`);\n }\n\n lines.push(`echo $$ > ${shellQuote(SERVER_PIDFILE)}`);\n lines.push(`exec node index.mjs >> ${shellQuote(SERVER_LOGFILE)} 2>&1`);\n return lines.join('\\n') + '\\n';\n}\n\n/** Create a gzipped tarball of the directory contents (excluding node_modules). */\nasync function createTarball(dir: string): Promise<Buffer> {\n const tmp = await mkdtemp(join(tmpdir(), 'mastra-sandbox-'));\n const tarPath = join(tmp, 'deploy.tgz');\n try {\n await execFileAsync('tar', ['-czf', tarPath, '--exclude=node_modules', '-C', dir, '.']);\n return await readFile(tarPath);\n } finally {\n await rm(tmp, { recursive: true, force: true });\n }\n}\n\n/**\n * Upload a file into the sandbox. Uses the provider's native `writeFiles` fast\n * path when available, otherwise falls back to base64 chunks over\n * `executeCommand` — so `executeCommand` + `networking` is the minimum contract.\n */\nasync function uploadFile(sandbox: WorkspaceSandbox, remotePath: string, content: Buffer): Promise<void> {\n if (sandbox.writeFiles) {\n await sandbox.writeFiles([{ path: remotePath, content }]);\n return;\n }\n\n const b64 = content.toString('base64');\n const tmpPath = `${remotePath}.b64`;\n await runInSandbox(sandbox, `rm -f ${shellQuote(tmpPath)}`);\n for (let i = 0; i < b64.length; i += UPLOAD_CHUNK_SIZE) {\n const chunk = b64.slice(i, i + UPLOAD_CHUNK_SIZE);\n await runInSandbox(sandbox, `printf '%s' ${shellQuote(chunk)} >> ${shellQuote(tmpPath)}`, {\n label: `upload chunk to ${remotePath}`,\n });\n }\n await runInSandbox(\n sandbox,\n `base64 -d ${shellQuote(tmpPath)} > ${shellQuote(remotePath)} && rm -f ${shellQuote(tmpPath)}`,\n { label: `decode upload at ${remotePath}` },\n );\n}\n\n/** Lockfiles that, when present in the build output, participate in the install-skip hash. */\nconst LOCKFILES = ['package-lock.json', 'npm-shrinkwrap.json', 'pnpm-lock.yaml', 'yarn.lock', 'bun.lock'];\n\n/**\n * Hash everything that determines the outcome of a dependency install:\n * package.json, any bundled lockfile, and the install command itself. A\n * matching hash means the previous `node_modules` can be reused.\n */\nasync function hashInstallInputs(dir: string, installCommand: string): Promise<string | null> {\n const hash = createHash('sha256');\n try {\n hash.update(await readFile(join(dir, 'package.json')));\n } catch {\n return null;\n }\n for (const lockfile of LOCKFILES) {\n let content: Buffer;\n try {\n content = await readFile(join(dir, lockfile));\n } catch {\n // Lockfile not part of the build output.\n continue;\n }\n hash.update(lockfile).update(content);\n }\n hash.update(installCommand);\n return hash.digest('hex');\n}\n","import { readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { SandboxDeploymentManifest } from './types';\n\nexport const MANIFEST_FILENAME = 'sandbox-deployment.json';\n\n/** Write `sandbox-deployment.json` into the build output directory. */\nexport async function writeDeploymentManifest(outputDir: string, manifest: SandboxDeploymentManifest): Promise<void> {\n await writeFile(join(outputDir, MANIFEST_FILENAME), JSON.stringify(manifest, null, 2));\n}\n\n/** Read `sandbox-deployment.json` from the build output directory, or null when absent. */\nexport async function readDeploymentManifest(outputDir: string): Promise<SandboxDeploymentManifest | null> {\n let raw: string;\n try {\n raw = await readFile(join(outputDir, MANIFEST_FILENAME), 'utf-8');\n } catch (error) {\n // Only \"no manifest\" maps to null — anything else (permissions, a\n // corrupted file, malformed JSON below) should surface, not be hidden.\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return null;\n }\n throw error;\n }\n return JSON.parse(raw) as SandboxDeploymentManifest;\n}\n","import { access } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Config } from '@mastra/core/mastra';\nimport type { WorkspaceSandbox } from '@mastra/core/workspace';\nimport { Deployer } from '@mastra/deployer';\nimport { copy } from 'fs-extra/esm';\nimport { updateEdgeConfigAlias } from './alias';\nimport { deployToSandbox } from './engine';\nimport { writeDeploymentManifest } from './manifest';\nimport { DEFAULT_PORT } from './shared';\nimport type { SandboxDeployerOptions } from './types';\n\n/**\n * Deploy a full Mastra server into any workspace sandbox that supports\n * networking (Vercel Sandbox, E2B, ...) and get a live public URL.\n *\n * Positioning: ephemeral environments — instant previews, PR/CI smoke deploys,\n * agent-built-app verification. Not production hosting.\n *\n * @example\n * ```typescript\n * import { SandboxDeployer } from '@mastra/deployer-sandbox';\n * import { VercelSandbox } from '@mastra/vercel';\n *\n * export const mastra = new Mastra({\n * deployer: new SandboxDeployer({\n * sandbox: new VercelSandbox({ sandboxName: 'my-preview', timeout: 3_600_000, ports: [4111] }),\n * }),\n * });\n * ```\n */\nexport class SandboxDeployer extends Deployer {\n /** Sandbox deploys are push-style: `mastra build` runs `deploy()` after bundling. */\n readonly deployOnBuild = true;\n readonly sandbox: WorkspaceSandbox;\n readonly port: number;\n readonly studio: boolean;\n /** Explicit remote dir, when configured. The engine defaults to `$HOME/mastra-app` inside the sandbox. */\n readonly remoteDir?: string;\n private readonly env: Record<string, string>;\n private readonly alias?: SandboxDeployerOptions['alias'];\n private readonly healthCheckTimeoutMs?: number;\n\n constructor(options: SandboxDeployerOptions) {\n super({ name: 'SANDBOX' });\n\n this.sandbox = options.sandbox;\n this.port = options.port ?? DEFAULT_PORT;\n this.studio = options.studio ?? true;\n this.remoteDir = options.remoteDir;\n this.env = options.env ?? {};\n this.alias = options.alias;\n this.healthCheckTimeoutMs = options.healthCheckTimeoutMs;\n }\n\n /**\n * Merge all existing env files instead of only the first one (base behavior).\n * Later files win in `loadEnvVars()`, so order least → most specific: a\n * `.env.local` written by `vercel env pull` shouldn't shadow the `.env` that\n * holds the app's own keys.\n */\n override async getEnvFiles(): Promise<string[]> {\n const candidates = ['.env', '.env.production', '.env.local'];\n const existing: string[] = [];\n for (const file of candidates) {\n try {\n await access(file);\n existing.push(file);\n } catch {\n // skip missing files\n }\n }\n return existing;\n }\n\n protected async getUserBundlerOptions(\n mastraEntryFile: string,\n outputDirectory: string,\n ): Promise<NonNullable<Config['bundler']>> {\n const bundlerOptions = await super.getUserBundlerOptions(mastraEntryFile, outputDirectory);\n\n // Dependencies are installed inside the sandbox, so keep them external.\n return {\n ...bundlerOptions,\n externals: true,\n };\n }\n\n protected getEntry(): string {\n return `\n // @ts-expect-error\n import { scoreTracesWorkflow } from '@mastra/core/evals/scoreTraces';\n import { mastra } from '#mastra';\n import { createNodeServer, getToolExports } from '#server';\n import { tools } from '#tools';\n\n // @ts-expect-error\n await createNodeServer(mastra, { tools: getToolExports(tools), studio: ${this.studio} });\n\n const storage = mastra.getStorage();\n if (storage) {\n if (!storage.disableInit) {\n storage.init();\n }\n mastra.__registerInternalWorkflow(scoreTracesWorkflow);\n }\n `;\n }\n\n async prepare(outputDirectory: string): Promise<void> {\n await super.prepare(outputDirectory);\n\n if (this.studio) {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = dirname(__filename);\n\n const studioSource = join(dirname(__dirname), 'dist', 'studio');\n const studioServePath = join(outputDirectory, this.outputDir, 'studio');\n\n try {\n await copy(studioSource, studioServePath, { overwrite: true });\n } catch (err) {\n throw new Error(\n `Failed to copy studio assets from \"${studioSource}\" to \"${studioServePath}\": ${err instanceof Error ? err.message : err}`,\n );\n }\n }\n }\n\n async bundle(\n entryFile: string,\n outputDirectory: string,\n { toolsPaths, projectRoot }: { toolsPaths: (string | string[])[]; projectRoot: string },\n ): Promise<void> {\n return this._bundle(this.getEntry(), entryFile, { outputDirectory, projectRoot }, toolsPaths);\n }\n\n /**\n * Deploy the built output into the sandbox and wait for the server to come\n * up on its public URL. Writes `sandbox-deployment.json` into the output\n * directory and updates the Edge Config alias when configured.\n */\n async deploy(outputDirectory: string): Promise<void> {\n const dir = join(outputDirectory, this.outputDir);\n\n // Merge .env file vars under explicitly configured env.\n const envVars = await this.loadEnvVars();\n const env: Record<string, string> = { ...Object.fromEntries(envVars), ...this.env };\n if (envVars.size > 0) {\n this.logger.warn(\n 'Environment variables from your .env file are injected into the remote sandbox. ' +\n 'Anyone with access to the sandbox can read them.',\n );\n }\n\n const deployment = await deployToSandbox({\n sandbox: this.sandbox,\n dir,\n port: this.port,\n env,\n studio: this.studio,\n remoteDir: this.remoteDir,\n healthCheckTimeoutMs: this.healthCheckTimeoutMs,\n logger: this.logger,\n });\n\n await writeDeploymentManifest(dir, {\n provider: this.sandbox.provider,\n sandboxId: deployment.sandboxId,\n url: deployment.url,\n port: this.port,\n deployedAt: new Date().toISOString(),\n expiresAt: deployment.expiresAt?.toISOString(),\n });\n\n if (this.alias) {\n await updateEdgeConfigAlias({ ...this.alias, url: deployment.url });\n this.logger.info(`Edge Config alias \"${this.alias.key}\" now points at ${deployment.url}`);\n }\n\n this.logger.info(`Mastra server deployed: ${deployment.url}/api`);\n if (this.studio) {\n this.logger.info(`Studio: ${deployment.url}`);\n }\n if (deployment.expiresAt) {\n this.logger.warn(`Sandbox expires at ${deployment.expiresAt.toISOString()} (provider runtime cap).`);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/alias.ts","../src/engine.ts","../src/manifest.ts","../src/deployer.ts"],"sourcesContent":["import type { SandboxAliasOptions } from './types';\n\n/**\n * Upsert a Vercel Edge Config item so a stable key always points at the\n * current sandbox URL. Used for Tier 3 routing: apps read the key from Edge\n * Config (e.g. in middleware) instead of hardcoding the rotating sandbox URL.\n */\nexport async function updateEdgeConfigAlias(options: SandboxAliasOptions & { url: string }): Promise<void> {\n const { token, teamId } = options;\n if (!token) {\n throw new Error('Updating the Edge Config alias requires a Vercel API token. Pass `alias.token`.');\n }\n\n const endpoint = new URL(`https://api.vercel.com/v1/edge-config/${options.edgeConfigId}/items`);\n if (teamId) {\n endpoint.searchParams.set('teamId', teamId);\n }\n\n const res = await fetch(endpoint, {\n method: 'PATCH',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n items: [{ operation: 'upsert', key: options.key, value: options.url }],\n }),\n // Bounded so a hung Vercel API request can't keep `mastra build` open\n // after the sandbox itself is already deployed.\n signal: AbortSignal.timeout(30_000),\n });\n\n if (!res.ok) {\n const body = await res.text().catch(() => '');\n throw new Error(`Failed to update Edge Config alias \"${options.key}\" (${res.status}): ${body}`);\n }\n}\n","import { execFile } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport { existsSync } from 'node:fs';\nimport { mkdtemp, readFile, rm } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { promisify } from 'node:util';\nimport { supportsNetworking } from '@mastra/core/workspace';\nimport type { WorkspaceSandbox } from '@mastra/core/workspace';\nimport {\n DEFAULT_PORT,\n INSTALL_MARKER,\n SERVER_LOGFILE,\n SERVER_PIDFILE,\n SERVER_SCRIPT,\n getInfoSafe,\n killPreviousServer,\n launchServer,\n resolveRemoteDir,\n runInSandbox,\n shellQuote,\n tailServerLog,\n waitForHealthy,\n} from './shared';\nimport type { DeployToSandboxOptions, SandboxDeployLogger, SandboxDeployment } from './types';\n\nconst execFileAsync = promisify(execFile);\n\nconst noopLogger: SandboxDeployLogger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\n/** Max shell-command payload per chunk for the base64 upload fallback. */\nconst UPLOAD_CHUNK_SIZE = 96_000;\n\n/**\n * Deploy a prebuilt Mastra server directory into any workspace sandbox that\n * supports networking. Provider-agnostic: only uses the core WorkspaceSandbox\n * contract (`executeCommand` + `networking`, with `writeFiles` / `processes`\n * as fast paths).\n */\nexport async function deployToSandbox(options: DeployToSandboxOptions): Promise<SandboxDeployment> {\n const {\n sandbox,\n dir,\n port = DEFAULT_PORT,\n env = {},\n studio = false,\n healthCheckPath = '/api',\n healthCheckTimeoutMs = 60_000,\n healthCheckIntervalMs = 1_000,\n installCommand = 'npm install --omit=dev',\n logger = noopLogger,\n } = options;\n\n if (!existsSync(join(dir, 'index.mjs'))) {\n throw new Error(`No index.mjs found in \"${dir}\" — did the build succeed?`);\n }\n\n // 1. Start (providers handle create-or-resume by identity, e.g. sandbox name).\n logger.info(`Starting ${sandbox.provider} sandbox...`);\n await sandbox.start?.();\n\n if (!supportsNetworking(sandbox)) {\n throw new Error(\n `Sandbox provider \"${sandbox.provider}\" does not support networking (public port URLs), ` +\n `which is required for sandbox deploys.`,\n );\n }\n if (!sandbox.executeCommand) {\n throw new Error(\n `Sandbox provider \"${sandbox.provider}\" does not support executeCommand, which is required for sandbox deploys.`,\n );\n }\n\n const url = await sandbox.networking.getPortUrl(port);\n if (!url) {\n throw new Error(\n `Sandbox provider \"${sandbox.provider}\" did not expose a public URL for port ${port}. ` +\n `Make sure the port is declared when constructing the sandbox (e.g. \\`ports: [${port}]\\`).`,\n );\n }\n\n // Default the remote dir to $HOME/mastra-app — home directories persist\n // across snapshot stop/resume (unlike /tmp), so wakes find the app intact.\n const remoteDir = await resolveRemoteDir(sandbox, options.remoteDir);\n\n const mergedEnv = { ...env };\n if (studio && mergedEnv.MASTRA_STUDIO_PATH === undefined) {\n mergedEnv.MASTRA_STUDIO_PATH = `${remoteDir}/studio`;\n }\n\n // 2. Upload the build output as a tarball and extract it in the sandbox.\n logger.info(`Uploading build output from ${dir}...`);\n const tarball = await createTarball(dir);\n logger.debug(`Tarball size: ${(tarball.length / 1024 / 1024).toFixed(2)} MB`);\n\n const remoteTarball = `${remoteDir}/.deploy.tgz`;\n await runInSandbox(sandbox, `mkdir -p ${shellQuote(remoteDir)}`);\n await uploadFile(sandbox, remoteTarball, tarball);\n\n // Stop the previous server BEFORE extracting over the live directory so it\n // can never serve a mix of old and new files while the release lands.\n await killPreviousServer(sandbox, remoteDir);\n\n await runInSandbox(sandbox, `cd ${shellQuote(remoteDir)} && tar -xzf .deploy.tgz && rm -f .deploy.tgz`, {\n timeout: 120_000,\n });\n\n // 3. Install dependencies, skipped when the install inputs (package.json,\n // bundled lockfiles, and the install command itself) are unchanged since\n // the last completed install.\n const installHash = await hashInstallInputs(dir, installCommand);\n const marker = `${remoteDir}/${INSTALL_MARKER}`;\n const markerCheck = await runInSandbox(sandbox, `cat ${shellQuote(marker)} 2>/dev/null || true`, {\n allowFailure: true,\n });\n\n if (installHash && markerCheck.stdout.trim() === installHash) {\n logger.info('Dependencies unchanged — skipping install.');\n } else {\n logger.info(`Installing dependencies (${installCommand})...`);\n await runInSandbox(sandbox, `cd ${shellQuote(remoteDir)} && ${installCommand}`, {\n timeout: 600_000,\n label: `install dependencies (${installCommand})`,\n });\n if (installHash) {\n await runInSandbox(sandbox, `printf '%s' ${shellQuote(installHash)} > ${shellQuote(marker)}`);\n }\n }\n\n // 4. Write the launch script and start the new server (the previous one was\n // stopped before extraction).\n const launchScript = buildLaunchScript({ remoteDir, port, env: mergedEnv });\n await uploadFile(sandbox, `${remoteDir}/${SERVER_SCRIPT}`, Buffer.from(launchScript));\n await runInSandbox(sandbox, `chmod 700 ${shellQuote(`${remoteDir}/${SERVER_SCRIPT}`)}`);\n\n logger.info('Starting Mastra server...');\n await launchServer(sandbox, remoteDir);\n\n // 5. Wait for the server to answer on its public URL.\n const healthy = await waitForHealthy(url, {\n path: healthCheckPath,\n timeoutMs: healthCheckTimeoutMs,\n intervalMs: healthCheckIntervalMs,\n });\n if (!healthy) {\n const log = await tailServerLog(sandbox, remoteDir).catch(() => '');\n throw new Error(\n `Mastra server did not become healthy at ${url}${healthCheckPath} within ${healthCheckTimeoutMs}ms.` +\n (log ? `\\n\\nServer log:\\n${log}` : '\\n\\n(no server log output captured)'),\n );\n }\n\n const info = await getInfoSafe(sandbox);\n\n return {\n url,\n sandboxId: info?.id ?? sandbox.id,\n expiresAt: info?.timeoutAt,\n stop: async () => {\n await sandbox.stop?.();\n },\n destroy: async () => {\n await sandbox.destroy?.();\n },\n logs: (lines?: number) => tailServerLog(sandbox, remoteDir, lines),\n };\n}\n\n/**\n * Build the POSIX launch script. Re-running the script restarts the server —\n * the wake path uses this after a snapshot resume (which restores the\n * filesystem but not processes).\n */\nexport function buildLaunchScript(opts: { remoteDir: string; port: number; env: Record<string, string> }): string {\n const lines = ['#!/bin/sh', `cd ${shellQuote(opts.remoteDir)}`];\n\n // MASTRA_AUTO_DETECT_URL so Studio connects to the sandbox's public URL\n // (same origin) instead of localhost:4111 — overridable. PORT and\n // MASTRA_HOST are applied AFTER custom env: networking (`getPortUrl`) and\n // health checks target the configured port, and the server must bind\n // 0.0.0.0 to be reachable through the public port proxy. Change the port\n // via the deploy `port` option, not env.\n const env: Record<string, string> = {\n MASTRA_AUTO_DETECT_URL: 'true',\n ...opts.env,\n PORT: String(opts.port),\n MASTRA_HOST: '0.0.0.0',\n };\n for (const [key, value] of Object.entries(env)) {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {\n throw new Error(`Invalid environment variable name: \"${key}\"`);\n }\n lines.push(`export ${key}=${shellQuote(value)}`);\n }\n\n lines.push(`echo $$ > ${shellQuote(SERVER_PIDFILE)}`);\n lines.push(`exec node index.mjs >> ${shellQuote(SERVER_LOGFILE)} 2>&1`);\n return lines.join('\\n') + '\\n';\n}\n\n/** Create a gzipped tarball of the directory contents (excluding node_modules). */\nasync function createTarball(dir: string): Promise<Buffer> {\n const tmp = await mkdtemp(join(tmpdir(), 'mastra-sandbox-'));\n const tarPath = join(tmp, 'deploy.tgz');\n try {\n await execFileAsync('tar', ['-czf', tarPath, '--exclude=node_modules', '-C', dir, '.']);\n return await readFile(tarPath);\n } finally {\n await rm(tmp, { recursive: true, force: true });\n }\n}\n\n/**\n * Upload a file into the sandbox. Uses the provider's native `writeFiles` fast\n * path when available, otherwise falls back to base64 chunks over\n * `executeCommand` — so `executeCommand` + `networking` is the minimum contract.\n */\nasync function uploadFile(sandbox: WorkspaceSandbox, remotePath: string, content: Buffer): Promise<void> {\n if (sandbox.writeFiles) {\n await sandbox.writeFiles([{ path: remotePath, content }]);\n return;\n }\n\n const b64 = content.toString('base64');\n const tmpPath = `${remotePath}.b64`;\n await runInSandbox(sandbox, `rm -f ${shellQuote(tmpPath)}`);\n for (let i = 0; i < b64.length; i += UPLOAD_CHUNK_SIZE) {\n const chunk = b64.slice(i, i + UPLOAD_CHUNK_SIZE);\n await runInSandbox(sandbox, `printf '%s' ${shellQuote(chunk)} >> ${shellQuote(tmpPath)}`, {\n label: `upload chunk to ${remotePath}`,\n });\n }\n await runInSandbox(\n sandbox,\n `base64 -d ${shellQuote(tmpPath)} > ${shellQuote(remotePath)} && rm -f ${shellQuote(tmpPath)}`,\n { label: `decode upload at ${remotePath}` },\n );\n}\n\n/** Lockfiles that, when present in the build output, participate in the install-skip hash. */\nconst LOCKFILES = ['package-lock.json', 'npm-shrinkwrap.json', 'pnpm-lock.yaml', 'yarn.lock', 'bun.lock'];\n\n/**\n * Hash everything that determines the outcome of a dependency install:\n * package.json, any bundled lockfile, and the install command itself. A\n * matching hash means the previous `node_modules` can be reused.\n */\nasync function hashInstallInputs(dir: string, installCommand: string): Promise<string | null> {\n const hash = createHash('sha256');\n try {\n hash.update(await readFile(join(dir, 'package.json')));\n } catch {\n return null;\n }\n for (const lockfile of LOCKFILES) {\n let content: Buffer;\n try {\n content = await readFile(join(dir, lockfile));\n } catch {\n // Lockfile not part of the build output.\n continue;\n }\n hash.update(lockfile).update(content);\n }\n hash.update(installCommand);\n return hash.digest('hex');\n}\n","import { readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { SandboxDeploymentManifest } from './types';\n\nexport const MANIFEST_FILENAME = 'sandbox-deployment.json';\n\n/** Write `sandbox-deployment.json` into the build output directory. */\nexport async function writeDeploymentManifest(outputDir: string, manifest: SandboxDeploymentManifest): Promise<void> {\n await writeFile(join(outputDir, MANIFEST_FILENAME), JSON.stringify(manifest, null, 2));\n}\n\n/** Read `sandbox-deployment.json` from the build output directory, or null when absent. */\nexport async function readDeploymentManifest(outputDir: string): Promise<SandboxDeploymentManifest | null> {\n let raw: string;\n try {\n raw = await readFile(join(outputDir, MANIFEST_FILENAME), 'utf-8');\n } catch (error) {\n // Only \"no manifest\" maps to null — anything else (permissions, a\n // corrupted file, malformed JSON below) should surface, not be hidden.\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return null;\n }\n throw error;\n }\n return JSON.parse(raw) as SandboxDeploymentManifest;\n}\n","import { access } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Config } from '@mastra/core/mastra';\nimport type { WorkspaceSandbox } from '@mastra/core/workspace';\nimport { Deployer } from '@mastra/deployer';\nimport { copy } from 'fs-extra/esm';\nimport { updateEdgeConfigAlias } from './alias';\nimport { deployToSandbox } from './engine';\nimport { writeDeploymentManifest } from './manifest';\nimport { DEFAULT_PORT } from './shared';\nimport type { SandboxDeployerOptions } from './types';\n\n/**\n * Deploy a full Mastra server into any workspace sandbox that supports\n * networking (Vercel Sandbox, E2B, ...) and get a live public URL.\n *\n * Positioning: ephemeral environments — instant previews, PR/CI smoke deploys,\n * agent-built-app verification. Not production hosting.\n *\n * @example\n * ```typescript\n * import { SandboxDeployer } from '@mastra/deployer-sandbox';\n * import { VercelSandbox } from '@mastra/vercel';\n *\n * export const mastra = new Mastra({\n * deployer: new SandboxDeployer({\n * sandbox: new VercelSandbox({ sandboxName: 'my-preview', timeout: 3_600_000, ports: [4111] }),\n * }),\n * });\n * ```\n */\nexport class SandboxDeployer extends Deployer {\n /** Sandbox deploys are push-style: `mastra build` runs `deploy()` after bundling. */\n readonly deployOnBuild = true;\n readonly sandbox: WorkspaceSandbox;\n readonly port: number;\n readonly studio: boolean;\n /** Explicit remote dir, when configured. The engine defaults to `$HOME/mastra-app` inside the sandbox. */\n readonly remoteDir?: string;\n private readonly env: Record<string, string>;\n private readonly alias?: SandboxDeployerOptions['alias'];\n private readonly healthCheckTimeoutMs?: number;\n\n constructor(options: SandboxDeployerOptions) {\n super({ name: 'SANDBOX' });\n\n this.sandbox = options.sandbox;\n this.port = options.port ?? DEFAULT_PORT;\n this.studio = options.studio ?? true;\n this.remoteDir = options.remoteDir;\n this.env = options.env ?? {};\n this.alias = options.alias;\n this.healthCheckTimeoutMs = options.healthCheckTimeoutMs;\n }\n\n /**\n * Merge all existing env files instead of only the first one (base behavior).\n * Later files win in `loadEnvVars()`, so order least → most specific: a\n * `.env.local` written by `vercel env pull` shouldn't shadow the `.env` that\n * holds the app's own keys.\n */\n override async getEnvFiles(): Promise<string[]> {\n const candidates = ['.env', '.env.production', '.env.local'];\n const existing: string[] = [];\n for (const file of candidates) {\n try {\n await access(file);\n existing.push(file);\n } catch {\n // skip missing files\n }\n }\n return existing;\n }\n\n protected async getUserBundlerOptions(\n mastraEntryFile: string,\n outputDirectory: string,\n ): Promise<NonNullable<Config['bundler']>> {\n const bundlerOptions = await super.getUserBundlerOptions(mastraEntryFile, outputDirectory);\n\n // Dependencies are installed inside the sandbox, so keep them external.\n return {\n ...bundlerOptions,\n externals: true,\n };\n }\n\n protected getEntry(): string {\n return `\n // @ts-expect-error\n import { scoreTracesWorkflow } from '@mastra/core/evals/scoreTraces';\n import { mastra } from '#mastra';\n import { createNodeServer, getToolExports } from '#server';\n import { tools } from '#tools';\n\n // @ts-expect-error\n await createNodeServer(mastra, { tools: getToolExports(tools), studio: ${this.studio} });\n\n const storage = mastra.getStorage();\n if (storage) {\n if (!storage.disableInit) {\n storage.init();\n }\n mastra.__registerInternalWorkflow(scoreTracesWorkflow);\n }\n `;\n }\n\n async prepare(outputDirectory: string): Promise<void> {\n await super.prepare(outputDirectory);\n\n if (this.studio) {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = dirname(__filename);\n\n const studioSource = join(dirname(__dirname), 'dist', 'studio');\n const studioServePath = join(outputDirectory, this.outputDir, 'studio');\n\n try {\n await copy(studioSource, studioServePath, { overwrite: true });\n } catch (err) {\n throw new Error(\n `Failed to copy studio assets from \"${studioSource}\" to \"${studioServePath}\": ${err instanceof Error ? err.message : err}`,\n );\n }\n }\n }\n\n async bundle(\n entryFile: string,\n outputDirectory: string,\n { toolsPaths, projectRoot }: { toolsPaths: (string | string[])[]; projectRoot: string },\n ): Promise<void> {\n return this._bundle(this.getEntry(), entryFile, { outputDirectory, projectRoot }, toolsPaths);\n }\n\n /**\n * Deploy the built output into the sandbox and wait for the server to come\n * up on its public URL. Writes `sandbox-deployment.json` into the output\n * directory and updates the Edge Config alias when configured.\n */\n async deploy(outputDirectory: string): Promise<void> {\n const dir = join(outputDirectory, this.outputDir);\n\n // Merge .env file vars under explicitly configured env.\n const envVars = await this.loadEnvVars();\n const env: Record<string, string> = { ...Object.fromEntries(envVars), ...this.env };\n if (envVars.size > 0) {\n this.logger.warn(\n 'Environment variables from your .env file are injected into the remote sandbox. ' +\n 'Anyone with access to the sandbox can read them.',\n );\n }\n\n const deployment = await deployToSandbox({\n sandbox: this.sandbox,\n dir,\n port: this.port,\n env,\n studio: this.studio,\n remoteDir: this.remoteDir,\n healthCheckTimeoutMs: this.healthCheckTimeoutMs,\n logger: this.logger,\n });\n\n await writeDeploymentManifest(dir, {\n provider: this.sandbox.provider,\n sandboxId: deployment.sandboxId,\n url: deployment.url,\n port: this.port,\n deployedAt: new Date().toISOString(),\n expiresAt: deployment.expiresAt?.toISOString(),\n });\n\n if (this.alias) {\n await updateEdgeConfigAlias({ ...this.alias, url: deployment.url });\n this.logger.info(`Edge Config alias \"${this.alias.key}\" now points at ${deployment.url}`);\n }\n\n this.logger.info(`Mastra server deployed: ${deployment.url}/api`);\n if (this.studio) {\n this.logger.info(`Studio: ${deployment.url}`);\n }\n if (deployment.expiresAt) {\n this.logger.warn(`Sandbox expires at ${deployment.expiresAt.toISOString()} (provider runtime cap).`);\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ //#region src/shared.ts
2
+ /** Directory name (under the sandbox user's home) that the app is deployed into by default. */
3
+ const REMOTE_DIR_NAME = "mastra-app";
4
+ /** Default port the Mastra server listens on. */
5
+ const DEFAULT_PORT = 4111;
6
+ /** Launch script written into the remote dir. Re-running it restarts the server (e.g. after a wake). */
7
+ const SERVER_SCRIPT = ".mastra-server.sh";
8
+ /** Pidfile written by the launch script. */
9
+ const SERVER_PIDFILE = ".mastra-server.pid";
10
+ /** Server log file inside the remote dir. */
11
+ const SERVER_LOGFILE = ".mastra-server.log";
12
+ /** Marker recording the package.json hash of the last completed dependency install. */
13
+ const INSTALL_MARKER = ".mastra-install-hash";
14
+ /** getInfo may be sync or async, and may throw — normalize to `undefined` on failure. */
15
+ async function getInfoSafe(sandbox) {
16
+ try {
17
+ return await sandbox.getInfo?.();
18
+ } catch {
19
+ return;
20
+ }
21
+ }
22
+ /**
23
+ * Resolve the directory the app is (or will be) deployed into. Defaults to
24
+ * `$HOME/mastra-app` resolved inside the sandbox — home directories persist
25
+ * across snapshot stop/resume on providers that support it, unlike `/tmp`.
26
+ * The sandbox must be running.
27
+ */
28
+ async function resolveRemoteDir(sandbox, remoteDir) {
29
+ if (remoteDir) return remoteDir;
30
+ const base = (await runInSandbox(sandbox, `printf %s "\${HOME:-$(pwd)}"`, { allowFailure: true })).stdout.trim();
31
+ if (!base) throw new Error("Could not resolve the sandbox home directory. Pass `remoteDir` explicitly.");
32
+ return `${base}/${REMOTE_DIR_NAME}`;
33
+ }
34
+ /** Single-quote a value for POSIX shells. */
35
+ function shellQuote(value) {
36
+ return `'${value.replace(/'/g, `'\\''`)}'`;
37
+ }
38
+ /** Run a shell script string inside the sandbox and throw on failure. */
39
+ async function runInSandbox(sandbox, script, opts) {
40
+ if (!sandbox.executeCommand) throw new Error(`Sandbox provider "${sandbox.provider}" does not support executeCommand, which is required for sandbox deploys.`);
41
+ const result = await sandbox.executeCommand("sh", ["-c", script], opts?.timeout ? { timeout: opts.timeout } : void 0);
42
+ if (!result.success && !opts?.allowFailure) {
43
+ const what = opts?.label ?? truncate(script, 120);
44
+ throw new Error(`Command failed inside sandbox (exit ${result.exitCode}): ${what}\n${truncate(result.stderr || result.stdout, 4e3)}`);
45
+ }
46
+ return {
47
+ stdout: result.stdout,
48
+ stderr: result.stderr,
49
+ exitCode: result.exitCode
50
+ };
51
+ }
52
+ function truncate(value, max) {
53
+ return value.length > max ? `${value.slice(0, max)}… (truncated)` : value;
54
+ }
55
+ /**
56
+ * Kill the previously launched server (if any) using its pidfile, waiting for
57
+ * the process to exit (bounded, then SIGKILL) so the replacement never races
58
+ * the old server for the port. Safe when nothing is running.
59
+ */
60
+ async function killPreviousServer(sandbox, remoteDir) {
61
+ const pidfile = shellQuote(`${remoteDir}/${SERVER_PIDFILE}`);
62
+ await runInSandbox(sandbox, [
63
+ `if [ -f ${pidfile} ]; then`,
64
+ ` pid="$(cat ${pidfile})"`,
65
+ ` kill "$pid" 2>/dev/null || true`,
66
+ ` i=0`,
67
+ ` while kill -0 "$pid" 2>/dev/null && [ "$i" -lt 50 ]; do sleep 0.1; i=$((i + 1)); done`,
68
+ ` kill -9 "$pid" 2>/dev/null || true`,
69
+ ` rm -f ${pidfile}`,
70
+ `fi`
71
+ ].join("\n"), {
72
+ allowFailure: true,
73
+ timeout: 15e3
74
+ });
75
+ }
76
+ /**
77
+ * Launch (or relaunch) the server by running the recorded launch script,
78
+ * detached via nohup. Deliberately NOT `processes.spawn()`: provider process
79
+ * handles follow the command's log stream, which would keep the calling
80
+ * process's event loop alive for as long as the server runs. The server's
81
+ * lifecycle is managed through its pidfile instead.
82
+ */
83
+ async function launchServer(sandbox, remoteDir) {
84
+ await runInSandbox(sandbox, `nohup sh ${shellQuote(`${remoteDir}/${SERVER_SCRIPT}`)} >/dev/null 2>&1 & echo launched`);
85
+ }
86
+ /** Tail the server log from inside the sandbox. */
87
+ async function tailServerLog(sandbox, remoteDir, lines = 50) {
88
+ const logfile = `${remoteDir}/${SERVER_LOGFILE}`;
89
+ return (await runInSandbox(sandbox, `tail -n ${Math.floor(lines)} ${shellQuote(logfile)} 2>/dev/null || true`, { allowFailure: true })).stdout;
90
+ }
91
+ /**
92
+ * Poll `${url}${path}` until the server responds. Any HTTP status below 500
93
+ * counts as "the server is up" — gateway errors (502/503) mean nothing is
94
+ * listening on the port, and 410 is what some providers (e.g. Vercel) return
95
+ * from their edge when the sandbox itself is stopped.
96
+ */
97
+ async function waitForHealthy(url, opts = {}) {
98
+ const path = opts.path ?? "/api";
99
+ const timeoutMs = opts.timeoutMs ?? 6e4;
100
+ const intervalMs = opts.intervalMs ?? 1e3;
101
+ const deadline = Date.now() + timeoutMs;
102
+ while (Date.now() < deadline) {
103
+ try {
104
+ const res = await fetch(new URL(path, url), { signal: AbortSignal.timeout(intervalMs * 5) });
105
+ const providerError = res.status === 410 || res.headers.has("x-vercel-error");
106
+ if (res.status < 500 && !providerError) return true;
107
+ } catch {}
108
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
109
+ }
110
+ return false;
111
+ }
112
+ //#endregion
113
+ export { SERVER_SCRIPT as a, launchServer as c, shellQuote as d, tailServerLog as f, SERVER_PIDFILE as i, resolveRemoteDir as l, INSTALL_MARKER as n, getInfoSafe as o, waitForHealthy as p, SERVER_LOGFILE as r, killPreviousServer as s, DEFAULT_PORT as t, runInSandbox as u };
114
+
115
+ //# sourceMappingURL=shared-C-piQAcU.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shared.ts"],"names":[],"mappings":"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","file":"chunk-CSXC6CZL.cjs","sourcesContent":["import type { SandboxInfo, WorkspaceSandbox } from '@mastra/core/workspace';\n\n/** Directory name (under the sandbox user's home) that the app is deployed into by default. */\nexport const REMOTE_DIR_NAME = 'mastra-app';\n/** Default port the Mastra server listens on. */\nexport const DEFAULT_PORT = 4111;\n/** Launch script written into the remote dir. Re-running it restarts the server (e.g. after a wake). */\nexport const SERVER_SCRIPT = '.mastra-server.sh';\n/** Pidfile written by the launch script. */\nexport const SERVER_PIDFILE = '.mastra-server.pid';\n/** Server log file inside the remote dir. */\nexport const SERVER_LOGFILE = '.mastra-server.log';\n/** Marker recording the package.json hash of the last completed dependency install. */\nexport const INSTALL_MARKER = '.mastra-install-hash';\n\n/** getInfo may be sync or async, and may throw — normalize to `undefined` on failure. */\nexport async function getInfoSafe(sandbox: WorkspaceSandbox): Promise<SandboxInfo | undefined> {\n try {\n return await sandbox.getInfo?.();\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolve the directory the app is (or will be) deployed into. Defaults to\n * `$HOME/mastra-app` resolved inside the sandbox — home directories persist\n * across snapshot stop/resume on providers that support it, unlike `/tmp`.\n * The sandbox must be running.\n */\nexport async function resolveRemoteDir(sandbox: WorkspaceSandbox, remoteDir?: string): Promise<string> {\n if (remoteDir) return remoteDir;\n const result = await runInSandbox(sandbox, `printf %s \"\\${HOME:-$(pwd)}\"`, { allowFailure: true });\n const base = result.stdout.trim();\n if (!base) {\n throw new Error('Could not resolve the sandbox home directory. Pass `remoteDir` explicitly.');\n }\n return `${base}/${REMOTE_DIR_NAME}`;\n}\n\n/** Single-quote a value for POSIX shells. */\nexport function shellQuote(value: string): string {\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n\n/** Run a shell script string inside the sandbox and throw on failure. */\nexport async function runInSandbox(\n sandbox: WorkspaceSandbox,\n script: string,\n opts?: {\n allowFailure?: boolean;\n timeout?: number;\n /** Safe description used in error messages instead of the script itself. */\n label?: string;\n },\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n if (!sandbox.executeCommand) {\n throw new Error(\n `Sandbox provider \"${sandbox.provider}\" does not support executeCommand, which is required for sandbox deploys.`,\n );\n }\n // Run via `sh -c` (argv style): providers pass `command` straight to their\n // exec API as an executable, so a raw script string with spaces would fail.\n const result = await sandbox.executeCommand(\n 'sh',\n ['-c', script],\n opts?.timeout ? { timeout: opts.timeout } : undefined,\n );\n if (!result.success && !opts?.allowFailure) {\n // Never echo the full script back: it can contain secrets (env values)\n // or entire base64 upload chunks. Use the label or a bounded excerpt.\n const what = opts?.label ?? truncate(script, 120);\n throw new Error(\n `Command failed inside sandbox (exit ${result.exitCode}): ${what}\\n${truncate(result.stderr || result.stdout, 4_000)}`,\n );\n }\n return { stdout: result.stdout, stderr: result.stderr, exitCode: result.exitCode };\n}\n\nfunction truncate(value: string, max: number): string {\n return value.length > max ? `${value.slice(0, max)}… (truncated)` : value;\n}\n\n/**\n * Kill the previously launched server (if any) using its pidfile, waiting for\n * the process to exit (bounded, then SIGKILL) so the replacement never races\n * the old server for the port. Safe when nothing is running.\n */\nexport async function killPreviousServer(sandbox: WorkspaceSandbox, remoteDir: string): Promise<void> {\n const pidfile = shellQuote(`${remoteDir}/${SERVER_PIDFILE}`);\n const script = [\n `if [ -f ${pidfile} ]; then`,\n ` pid=\"$(cat ${pidfile})\"`,\n ` kill \"$pid\" 2>/dev/null || true`,\n // Wait up to ~5s for the old server to release the port, then force-kill.\n ` i=0`,\n ` while kill -0 \"$pid\" 2>/dev/null && [ \"$i\" -lt 50 ]; do sleep 0.1; i=$((i + 1)); done`,\n ` kill -9 \"$pid\" 2>/dev/null || true`,\n ` rm -f ${pidfile}`,\n `fi`,\n ].join('\\n');\n await runInSandbox(sandbox, script, { allowFailure: true, timeout: 15_000 });\n}\n\n/**\n * Launch (or relaunch) the server by running the recorded launch script,\n * detached via nohup. Deliberately NOT `processes.spawn()`: provider process\n * handles follow the command's log stream, which would keep the calling\n * process's event loop alive for as long as the server runs. The server's\n * lifecycle is managed through its pidfile instead.\n */\nexport async function launchServer(sandbox: WorkspaceSandbox, remoteDir: string): Promise<void> {\n const script = `${remoteDir}/${SERVER_SCRIPT}`;\n await runInSandbox(sandbox, `nohup sh ${shellQuote(script)} >/dev/null 2>&1 & echo launched`);\n}\n\n/** Tail the server log from inside the sandbox. */\nexport async function tailServerLog(sandbox: WorkspaceSandbox, remoteDir: string, lines = 50): Promise<string> {\n const logfile = `${remoteDir}/${SERVER_LOGFILE}`;\n const result = await runInSandbox(\n sandbox,\n `tail -n ${Math.floor(lines)} ${shellQuote(logfile)} 2>/dev/null || true`,\n {\n allowFailure: true,\n },\n );\n return result.stdout;\n}\n\n/**\n * Poll `${url}${path}` until the server responds. Any HTTP status below 500\n * counts as \"the server is up\" — gateway errors (502/503) mean nothing is\n * listening on the port, and 410 is what some providers (e.g. Vercel) return\n * from their edge when the sandbox itself is stopped.\n */\nexport async function waitForHealthy(\n url: string,\n opts: { path?: string; timeoutMs?: number; intervalMs?: number } = {},\n): Promise<boolean> {\n const path = opts.path ?? '/api';\n const timeoutMs = opts.timeoutMs ?? 60_000;\n const intervalMs = opts.intervalMs ?? 1_000;\n const deadline = Date.now() + timeoutMs;\n\n while (Date.now() < deadline) {\n try {\n const res = await fetch(new URL(path, url), { signal: AbortSignal.timeout(intervalMs * 5) });\n // A provider-edge error header means the response came from the sandbox\n // infrastructure (stopped/unreachable VM), not from the Mastra server.\n const providerError = res.status === 410 || res.headers.has('x-vercel-error');\n if (res.status < 500 && !providerError) {\n return true;\n }\n } catch {\n // Not reachable yet.\n }\n await new Promise(resolve => setTimeout(resolve, intervalMs));\n }\n return false;\n}\n"]}
1
+ {"version":3,"file":"shared-C-piQAcU.js","names":[],"sources":["../src/shared.ts"],"sourcesContent":["import type { SandboxInfo, WorkspaceSandbox } from '@mastra/core/workspace';\n\n/** Directory name (under the sandbox user's home) that the app is deployed into by default. */\nexport const REMOTE_DIR_NAME = 'mastra-app';\n/** Default port the Mastra server listens on. */\nexport const DEFAULT_PORT = 4111;\n/** Launch script written into the remote dir. Re-running it restarts the server (e.g. after a wake). */\nexport const SERVER_SCRIPT = '.mastra-server.sh';\n/** Pidfile written by the launch script. */\nexport const SERVER_PIDFILE = '.mastra-server.pid';\n/** Server log file inside the remote dir. */\nexport const SERVER_LOGFILE = '.mastra-server.log';\n/** Marker recording the package.json hash of the last completed dependency install. */\nexport const INSTALL_MARKER = '.mastra-install-hash';\n\n/** getInfo may be sync or async, and may throw — normalize to `undefined` on failure. */\nexport async function getInfoSafe(sandbox: WorkspaceSandbox): Promise<SandboxInfo | undefined> {\n try {\n return await sandbox.getInfo?.();\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolve the directory the app is (or will be) deployed into. Defaults to\n * `$HOME/mastra-app` resolved inside the sandbox — home directories persist\n * across snapshot stop/resume on providers that support it, unlike `/tmp`.\n * The sandbox must be running.\n */\nexport async function resolveRemoteDir(sandbox: WorkspaceSandbox, remoteDir?: string): Promise<string> {\n if (remoteDir) return remoteDir;\n const result = await runInSandbox(sandbox, `printf %s \"\\${HOME:-$(pwd)}\"`, { allowFailure: true });\n const base = result.stdout.trim();\n if (!base) {\n throw new Error('Could not resolve the sandbox home directory. Pass `remoteDir` explicitly.');\n }\n return `${base}/${REMOTE_DIR_NAME}`;\n}\n\n/** Single-quote a value for POSIX shells. */\nexport function shellQuote(value: string): string {\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n\n/** Run a shell script string inside the sandbox and throw on failure. */\nexport async function runInSandbox(\n sandbox: WorkspaceSandbox,\n script: string,\n opts?: {\n allowFailure?: boolean;\n timeout?: number;\n /** Safe description used in error messages instead of the script itself. */\n label?: string;\n },\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n if (!sandbox.executeCommand) {\n throw new Error(\n `Sandbox provider \"${sandbox.provider}\" does not support executeCommand, which is required for sandbox deploys.`,\n );\n }\n // Run via `sh -c` (argv style): providers pass `command` straight to their\n // exec API as an executable, so a raw script string with spaces would fail.\n const result = await sandbox.executeCommand(\n 'sh',\n ['-c', script],\n opts?.timeout ? { timeout: opts.timeout } : undefined,\n );\n if (!result.success && !opts?.allowFailure) {\n // Never echo the full script back: it can contain secrets (env values)\n // or entire base64 upload chunks. Use the label or a bounded excerpt.\n const what = opts?.label ?? truncate(script, 120);\n throw new Error(\n `Command failed inside sandbox (exit ${result.exitCode}): ${what}\\n${truncate(result.stderr || result.stdout, 4_000)}`,\n );\n }\n return { stdout: result.stdout, stderr: result.stderr, exitCode: result.exitCode };\n}\n\nfunction truncate(value: string, max: number): string {\n return value.length > max ? `${value.slice(0, max)}… (truncated)` : value;\n}\n\n/**\n * Kill the previously launched server (if any) using its pidfile, waiting for\n * the process to exit (bounded, then SIGKILL) so the replacement never races\n * the old server for the port. Safe when nothing is running.\n */\nexport async function killPreviousServer(sandbox: WorkspaceSandbox, remoteDir: string): Promise<void> {\n const pidfile = shellQuote(`${remoteDir}/${SERVER_PIDFILE}`);\n const script = [\n `if [ -f ${pidfile} ]; then`,\n ` pid=\"$(cat ${pidfile})\"`,\n ` kill \"$pid\" 2>/dev/null || true`,\n // Wait up to ~5s for the old server to release the port, then force-kill.\n ` i=0`,\n ` while kill -0 \"$pid\" 2>/dev/null && [ \"$i\" -lt 50 ]; do sleep 0.1; i=$((i + 1)); done`,\n ` kill -9 \"$pid\" 2>/dev/null || true`,\n ` rm -f ${pidfile}`,\n `fi`,\n ].join('\\n');\n await runInSandbox(sandbox, script, { allowFailure: true, timeout: 15_000 });\n}\n\n/**\n * Launch (or relaunch) the server by running the recorded launch script,\n * detached via nohup. Deliberately NOT `processes.spawn()`: provider process\n * handles follow the command's log stream, which would keep the calling\n * process's event loop alive for as long as the server runs. The server's\n * lifecycle is managed through its pidfile instead.\n */\nexport async function launchServer(sandbox: WorkspaceSandbox, remoteDir: string): Promise<void> {\n const script = `${remoteDir}/${SERVER_SCRIPT}`;\n await runInSandbox(sandbox, `nohup sh ${shellQuote(script)} >/dev/null 2>&1 & echo launched`);\n}\n\n/** Tail the server log from inside the sandbox. */\nexport async function tailServerLog(sandbox: WorkspaceSandbox, remoteDir: string, lines = 50): Promise<string> {\n const logfile = `${remoteDir}/${SERVER_LOGFILE}`;\n const result = await runInSandbox(\n sandbox,\n `tail -n ${Math.floor(lines)} ${shellQuote(logfile)} 2>/dev/null || true`,\n {\n allowFailure: true,\n },\n );\n return result.stdout;\n}\n\n/**\n * Poll `${url}${path}` until the server responds. Any HTTP status below 500\n * counts as \"the server is up\" — gateway errors (502/503) mean nothing is\n * listening on the port, and 410 is what some providers (e.g. Vercel) return\n * from their edge when the sandbox itself is stopped.\n */\nexport async function waitForHealthy(\n url: string,\n opts: { path?: string; timeoutMs?: number; intervalMs?: number } = {},\n): Promise<boolean> {\n const path = opts.path ?? '/api';\n const timeoutMs = opts.timeoutMs ?? 60_000;\n const intervalMs = opts.intervalMs ?? 1_000;\n const deadline = Date.now() + timeoutMs;\n\n while (Date.now() < deadline) {\n try {\n const res = await fetch(new URL(path, url), { signal: AbortSignal.timeout(intervalMs * 5) });\n // A provider-edge error header means the response came from the sandbox\n // infrastructure (stopped/unreachable VM), not from the Mastra server.\n const providerError = res.status === 410 || res.headers.has('x-vercel-error');\n if (res.status < 500 && !providerError) {\n return true;\n }\n } catch {\n // Not reachable yet.\n }\n await new Promise(resolve => setTimeout(resolve, intervalMs));\n }\n return false;\n}\n"],"mappings":"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"}
@@ -0,0 +1,192 @@
1
+ //#region src/shared.ts
2
+ /** Directory name (under the sandbox user's home) that the app is deployed into by default. */
3
+ const REMOTE_DIR_NAME = "mastra-app";
4
+ /** Default port the Mastra server listens on. */
5
+ const DEFAULT_PORT = 4111;
6
+ /** Launch script written into the remote dir. Re-running it restarts the server (e.g. after a wake). */
7
+ const SERVER_SCRIPT = ".mastra-server.sh";
8
+ /** Pidfile written by the launch script. */
9
+ const SERVER_PIDFILE = ".mastra-server.pid";
10
+ /** Server log file inside the remote dir. */
11
+ const SERVER_LOGFILE = ".mastra-server.log";
12
+ /** Marker recording the package.json hash of the last completed dependency install. */
13
+ const INSTALL_MARKER = ".mastra-install-hash";
14
+ /** getInfo may be sync or async, and may throw — normalize to `undefined` on failure. */
15
+ async function getInfoSafe(sandbox) {
16
+ try {
17
+ return await sandbox.getInfo?.();
18
+ } catch {
19
+ return;
20
+ }
21
+ }
22
+ /**
23
+ * Resolve the directory the app is (or will be) deployed into. Defaults to
24
+ * `$HOME/mastra-app` resolved inside the sandbox — home directories persist
25
+ * across snapshot stop/resume on providers that support it, unlike `/tmp`.
26
+ * The sandbox must be running.
27
+ */
28
+ async function resolveRemoteDir(sandbox, remoteDir) {
29
+ if (remoteDir) return remoteDir;
30
+ const base = (await runInSandbox(sandbox, `printf %s "\${HOME:-$(pwd)}"`, { allowFailure: true })).stdout.trim();
31
+ if (!base) throw new Error("Could not resolve the sandbox home directory. Pass `remoteDir` explicitly.");
32
+ return `${base}/${REMOTE_DIR_NAME}`;
33
+ }
34
+ /** Single-quote a value for POSIX shells. */
35
+ function shellQuote(value) {
36
+ return `'${value.replace(/'/g, `'\\''`)}'`;
37
+ }
38
+ /** Run a shell script string inside the sandbox and throw on failure. */
39
+ async function runInSandbox(sandbox, script, opts) {
40
+ if (!sandbox.executeCommand) throw new Error(`Sandbox provider "${sandbox.provider}" does not support executeCommand, which is required for sandbox deploys.`);
41
+ const result = await sandbox.executeCommand("sh", ["-c", script], opts?.timeout ? { timeout: opts.timeout } : void 0);
42
+ if (!result.success && !opts?.allowFailure) {
43
+ const what = opts?.label ?? truncate(script, 120);
44
+ throw new Error(`Command failed inside sandbox (exit ${result.exitCode}): ${what}\n${truncate(result.stderr || result.stdout, 4e3)}`);
45
+ }
46
+ return {
47
+ stdout: result.stdout,
48
+ stderr: result.stderr,
49
+ exitCode: result.exitCode
50
+ };
51
+ }
52
+ function truncate(value, max) {
53
+ return value.length > max ? `${value.slice(0, max)}… (truncated)` : value;
54
+ }
55
+ /**
56
+ * Kill the previously launched server (if any) using its pidfile, waiting for
57
+ * the process to exit (bounded, then SIGKILL) so the replacement never races
58
+ * the old server for the port. Safe when nothing is running.
59
+ */
60
+ async function killPreviousServer(sandbox, remoteDir) {
61
+ const pidfile = shellQuote(`${remoteDir}/${SERVER_PIDFILE}`);
62
+ await runInSandbox(sandbox, [
63
+ `if [ -f ${pidfile} ]; then`,
64
+ ` pid="$(cat ${pidfile})"`,
65
+ ` kill "$pid" 2>/dev/null || true`,
66
+ ` i=0`,
67
+ ` while kill -0 "$pid" 2>/dev/null && [ "$i" -lt 50 ]; do sleep 0.1; i=$((i + 1)); done`,
68
+ ` kill -9 "$pid" 2>/dev/null || true`,
69
+ ` rm -f ${pidfile}`,
70
+ `fi`
71
+ ].join("\n"), {
72
+ allowFailure: true,
73
+ timeout: 15e3
74
+ });
75
+ }
76
+ /**
77
+ * Launch (or relaunch) the server by running the recorded launch script,
78
+ * detached via nohup. Deliberately NOT `processes.spawn()`: provider process
79
+ * handles follow the command's log stream, which would keep the calling
80
+ * process's event loop alive for as long as the server runs. The server's
81
+ * lifecycle is managed through its pidfile instead.
82
+ */
83
+ async function launchServer(sandbox, remoteDir) {
84
+ await runInSandbox(sandbox, `nohup sh ${shellQuote(`${remoteDir}/${SERVER_SCRIPT}`)} >/dev/null 2>&1 & echo launched`);
85
+ }
86
+ /** Tail the server log from inside the sandbox. */
87
+ async function tailServerLog(sandbox, remoteDir, lines = 50) {
88
+ const logfile = `${remoteDir}/${SERVER_LOGFILE}`;
89
+ return (await runInSandbox(sandbox, `tail -n ${Math.floor(lines)} ${shellQuote(logfile)} 2>/dev/null || true`, { allowFailure: true })).stdout;
90
+ }
91
+ /**
92
+ * Poll `${url}${path}` until the server responds. Any HTTP status below 500
93
+ * counts as "the server is up" — gateway errors (502/503) mean nothing is
94
+ * listening on the port, and 410 is what some providers (e.g. Vercel) return
95
+ * from their edge when the sandbox itself is stopped.
96
+ */
97
+ async function waitForHealthy(url, opts = {}) {
98
+ const path = opts.path ?? "/api";
99
+ const timeoutMs = opts.timeoutMs ?? 6e4;
100
+ const intervalMs = opts.intervalMs ?? 1e3;
101
+ const deadline = Date.now() + timeoutMs;
102
+ while (Date.now() < deadline) {
103
+ try {
104
+ const res = await fetch(new URL(path, url), { signal: AbortSignal.timeout(intervalMs * 5) });
105
+ const providerError = res.status === 410 || res.headers.has("x-vercel-error");
106
+ if (res.status < 500 && !providerError) return true;
107
+ } catch {}
108
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
109
+ }
110
+ return false;
111
+ }
112
+ //#endregion
113
+ Object.defineProperty(exports, "DEFAULT_PORT", {
114
+ enumerable: true,
115
+ get: function() {
116
+ return DEFAULT_PORT;
117
+ }
118
+ });
119
+ Object.defineProperty(exports, "INSTALL_MARKER", {
120
+ enumerable: true,
121
+ get: function() {
122
+ return INSTALL_MARKER;
123
+ }
124
+ });
125
+ Object.defineProperty(exports, "SERVER_LOGFILE", {
126
+ enumerable: true,
127
+ get: function() {
128
+ return SERVER_LOGFILE;
129
+ }
130
+ });
131
+ Object.defineProperty(exports, "SERVER_PIDFILE", {
132
+ enumerable: true,
133
+ get: function() {
134
+ return SERVER_PIDFILE;
135
+ }
136
+ });
137
+ Object.defineProperty(exports, "SERVER_SCRIPT", {
138
+ enumerable: true,
139
+ get: function() {
140
+ return SERVER_SCRIPT;
141
+ }
142
+ });
143
+ Object.defineProperty(exports, "getInfoSafe", {
144
+ enumerable: true,
145
+ get: function() {
146
+ return getInfoSafe;
147
+ }
148
+ });
149
+ Object.defineProperty(exports, "killPreviousServer", {
150
+ enumerable: true,
151
+ get: function() {
152
+ return killPreviousServer;
153
+ }
154
+ });
155
+ Object.defineProperty(exports, "launchServer", {
156
+ enumerable: true,
157
+ get: function() {
158
+ return launchServer;
159
+ }
160
+ });
161
+ Object.defineProperty(exports, "resolveRemoteDir", {
162
+ enumerable: true,
163
+ get: function() {
164
+ return resolveRemoteDir;
165
+ }
166
+ });
167
+ Object.defineProperty(exports, "runInSandbox", {
168
+ enumerable: true,
169
+ get: function() {
170
+ return runInSandbox;
171
+ }
172
+ });
173
+ Object.defineProperty(exports, "shellQuote", {
174
+ enumerable: true,
175
+ get: function() {
176
+ return shellQuote;
177
+ }
178
+ });
179
+ Object.defineProperty(exports, "tailServerLog", {
180
+ enumerable: true,
181
+ get: function() {
182
+ return tailServerLog;
183
+ }
184
+ });
185
+ Object.defineProperty(exports, "waitForHealthy", {
186
+ enumerable: true,
187
+ get: function() {
188
+ return waitForHealthy;
189
+ }
190
+ });
191
+
192
+ //# sourceMappingURL=shared-H9GioaPM.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-H9GioaPM.cjs","names":[],"sources":["../src/shared.ts"],"sourcesContent":["import type { SandboxInfo, WorkspaceSandbox } from '@mastra/core/workspace';\n\n/** Directory name (under the sandbox user's home) that the app is deployed into by default. */\nexport const REMOTE_DIR_NAME = 'mastra-app';\n/** Default port the Mastra server listens on. */\nexport const DEFAULT_PORT = 4111;\n/** Launch script written into the remote dir. Re-running it restarts the server (e.g. after a wake). */\nexport const SERVER_SCRIPT = '.mastra-server.sh';\n/** Pidfile written by the launch script. */\nexport const SERVER_PIDFILE = '.mastra-server.pid';\n/** Server log file inside the remote dir. */\nexport const SERVER_LOGFILE = '.mastra-server.log';\n/** Marker recording the package.json hash of the last completed dependency install. */\nexport const INSTALL_MARKER = '.mastra-install-hash';\n\n/** getInfo may be sync or async, and may throw — normalize to `undefined` on failure. */\nexport async function getInfoSafe(sandbox: WorkspaceSandbox): Promise<SandboxInfo | undefined> {\n try {\n return await sandbox.getInfo?.();\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolve the directory the app is (or will be) deployed into. Defaults to\n * `$HOME/mastra-app` resolved inside the sandbox — home directories persist\n * across snapshot stop/resume on providers that support it, unlike `/tmp`.\n * The sandbox must be running.\n */\nexport async function resolveRemoteDir(sandbox: WorkspaceSandbox, remoteDir?: string): Promise<string> {\n if (remoteDir) return remoteDir;\n const result = await runInSandbox(sandbox, `printf %s \"\\${HOME:-$(pwd)}\"`, { allowFailure: true });\n const base = result.stdout.trim();\n if (!base) {\n throw new Error('Could not resolve the sandbox home directory. Pass `remoteDir` explicitly.');\n }\n return `${base}/${REMOTE_DIR_NAME}`;\n}\n\n/** Single-quote a value for POSIX shells. */\nexport function shellQuote(value: string): string {\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n\n/** Run a shell script string inside the sandbox and throw on failure. */\nexport async function runInSandbox(\n sandbox: WorkspaceSandbox,\n script: string,\n opts?: {\n allowFailure?: boolean;\n timeout?: number;\n /** Safe description used in error messages instead of the script itself. */\n label?: string;\n },\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n if (!sandbox.executeCommand) {\n throw new Error(\n `Sandbox provider \"${sandbox.provider}\" does not support executeCommand, which is required for sandbox deploys.`,\n );\n }\n // Run via `sh -c` (argv style): providers pass `command` straight to their\n // exec API as an executable, so a raw script string with spaces would fail.\n const result = await sandbox.executeCommand(\n 'sh',\n ['-c', script],\n opts?.timeout ? { timeout: opts.timeout } : undefined,\n );\n if (!result.success && !opts?.allowFailure) {\n // Never echo the full script back: it can contain secrets (env values)\n // or entire base64 upload chunks. Use the label or a bounded excerpt.\n const what = opts?.label ?? truncate(script, 120);\n throw new Error(\n `Command failed inside sandbox (exit ${result.exitCode}): ${what}\\n${truncate(result.stderr || result.stdout, 4_000)}`,\n );\n }\n return { stdout: result.stdout, stderr: result.stderr, exitCode: result.exitCode };\n}\n\nfunction truncate(value: string, max: number): string {\n return value.length > max ? `${value.slice(0, max)}… (truncated)` : value;\n}\n\n/**\n * Kill the previously launched server (if any) using its pidfile, waiting for\n * the process to exit (bounded, then SIGKILL) so the replacement never races\n * the old server for the port. Safe when nothing is running.\n */\nexport async function killPreviousServer(sandbox: WorkspaceSandbox, remoteDir: string): Promise<void> {\n const pidfile = shellQuote(`${remoteDir}/${SERVER_PIDFILE}`);\n const script = [\n `if [ -f ${pidfile} ]; then`,\n ` pid=\"$(cat ${pidfile})\"`,\n ` kill \"$pid\" 2>/dev/null || true`,\n // Wait up to ~5s for the old server to release the port, then force-kill.\n ` i=0`,\n ` while kill -0 \"$pid\" 2>/dev/null && [ \"$i\" -lt 50 ]; do sleep 0.1; i=$((i + 1)); done`,\n ` kill -9 \"$pid\" 2>/dev/null || true`,\n ` rm -f ${pidfile}`,\n `fi`,\n ].join('\\n');\n await runInSandbox(sandbox, script, { allowFailure: true, timeout: 15_000 });\n}\n\n/**\n * Launch (or relaunch) the server by running the recorded launch script,\n * detached via nohup. Deliberately NOT `processes.spawn()`: provider process\n * handles follow the command's log stream, which would keep the calling\n * process's event loop alive for as long as the server runs. The server's\n * lifecycle is managed through its pidfile instead.\n */\nexport async function launchServer(sandbox: WorkspaceSandbox, remoteDir: string): Promise<void> {\n const script = `${remoteDir}/${SERVER_SCRIPT}`;\n await runInSandbox(sandbox, `nohup sh ${shellQuote(script)} >/dev/null 2>&1 & echo launched`);\n}\n\n/** Tail the server log from inside the sandbox. */\nexport async function tailServerLog(sandbox: WorkspaceSandbox, remoteDir: string, lines = 50): Promise<string> {\n const logfile = `${remoteDir}/${SERVER_LOGFILE}`;\n const result = await runInSandbox(\n sandbox,\n `tail -n ${Math.floor(lines)} ${shellQuote(logfile)} 2>/dev/null || true`,\n {\n allowFailure: true,\n },\n );\n return result.stdout;\n}\n\n/**\n * Poll `${url}${path}` until the server responds. Any HTTP status below 500\n * counts as \"the server is up\" — gateway errors (502/503) mean nothing is\n * listening on the port, and 410 is what some providers (e.g. Vercel) return\n * from their edge when the sandbox itself is stopped.\n */\nexport async function waitForHealthy(\n url: string,\n opts: { path?: string; timeoutMs?: number; intervalMs?: number } = {},\n): Promise<boolean> {\n const path = opts.path ?? '/api';\n const timeoutMs = opts.timeoutMs ?? 60_000;\n const intervalMs = opts.intervalMs ?? 1_000;\n const deadline = Date.now() + timeoutMs;\n\n while (Date.now() < deadline) {\n try {\n const res = await fetch(new URL(path, url), { signal: AbortSignal.timeout(intervalMs * 5) });\n // A provider-edge error header means the response came from the sandbox\n // infrastructure (stopped/unreachable VM), not from the Mastra server.\n const providerError = res.status === 410 || res.headers.has('x-vercel-error');\n if (res.status < 500 && !providerError) {\n return true;\n }\n } catch {\n // Not reachable yet.\n }\n await new Promise(resolve => setTimeout(resolve, intervalMs));\n }\n return false;\n}\n"],"mappings":"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"}