@mastra/deployer-sandbox 0.3.26-alpha.0 → 0.3.26

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.
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_shared = require("../shared-DZSzffib.cjs");
2
+ const require_shared = require("../shared-CA7a9oiC.cjs");
3
3
  let _mastra_core_workspace = require("@mastra/core/workspace");
4
4
  // src/client/index.ts
5
5
  /**
@@ -1,4 +1,4 @@
1
- import { c as launchServer, f as tailServerLog, l as resolveRemoteDir, o as getInfoSafe, p as waitForHealthy, s as killPreviousServer, t as DEFAULT_PORT } from "../shared-CmXDAiwu.js";
1
+ import { c as launchServer, f as tailServerLog, l as resolveRemoteDir, o as getInfoSafe, p as waitForHealthy, s as killPreviousServer, t as DEFAULT_PORT } from "../shared-eTQj_qC7.js";
2
2
  import { supportsNetworking } from "@mastra/core/workspace";
3
3
  // src/client/index.ts
4
4
  /**
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_shared = require("./shared-DZSzffib.cjs");
2
+ const require_shared = require("./shared-CA7a9oiC.cjs");
3
3
  let fs_promises = require("fs/promises");
4
4
  let path = require("path");
5
5
  let url = require("url");
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as SERVER_SCRIPT, c as launchServer, d as shellQuote, f as tailServerLog, i as SERVER_PIDFILE, l as resolveRemoteDir, n as INSTALL_MARKER$1, o as getInfoSafe, p as waitForHealthy, r as SERVER_LOGFILE, s as killPreviousServer, t as DEFAULT_PORT, u as runInSandbox } from "./shared-CmXDAiwu.js";
1
+ import { a as SERVER_SCRIPT, c as launchServer, d as shellQuote, f as tailServerLog, i as SERVER_PIDFILE, l as resolveRemoteDir, n as INSTALL_MARKER$1, o as getInfoSafe, p as waitForHealthy, r as SERVER_LOGFILE, s as killPreviousServer, t as DEFAULT_PORT, u as runInSandbox } from "./shared-eTQj_qC7.js";
2
2
  import { access, mkdtemp, readFile, rm, writeFile } from "fs/promises";
3
3
  import { dirname, join, posix } from "path";
4
4
  import { fileURLToPath } from "url";
@@ -95,7 +95,9 @@ async function tailServerLog(sandbox, remoteDir, lines = 50) {
95
95
  * Poll `${url}${path}` until the server responds. Any HTTP status below 500
96
96
  * counts as "the server is up" — gateway errors (502/503) mean nothing is
97
97
  * listening on the port, and 410 is what some providers (e.g. Vercel) return
98
- * from their edge when the sandbox itself is stopped.
98
+ * from their edge when the sandbox itself is stopped. Responses a provider's
99
+ * edge marks as its own (`x-vercel-error`, `x-mastra-preview-error`) don't
100
+ * count either.
99
101
  */
100
102
  async function waitForHealthy(url, opts = {}) {
101
103
  const path = opts.path ?? "/api";
@@ -105,7 +107,7 @@ async function waitForHealthy(url, opts = {}) {
105
107
  while (Date.now() < deadline) {
106
108
  try {
107
109
  const res = await fetch(new URL(path, url), { signal: AbortSignal.timeout(intervalMs * 5) });
108
- const providerError = res.status === 410 || res.headers.has("x-vercel-error");
110
+ const providerError = res.status === 410 || res.headers.has("x-vercel-error") || res.headers.has("x-mastra-preview-error");
109
111
  if (res.status < 500 && !providerError) return true;
110
112
  } catch {}
111
113
  await new Promise((resolve) => setTimeout(resolve, intervalMs));
@@ -191,4 +193,4 @@ Object.defineProperty(exports, "waitForHealthy", {
191
193
  }
192
194
  });
193
195
 
194
- //# sourceMappingURL=shared-DZSzffib.cjs.map
196
+ //# sourceMappingURL=shared-CA7a9oiC.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"shared-DZSzffib.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 // Scripts here bound their own output (e.g. `head -c` before base64), and\n // dropping the oldest bytes would corrupt the leading size line and base64.\n const result = await sandbox.executeCommand('sh', ['-c', script], {\n ...(opts?.timeout ? { timeout: opts.timeout } : {}),\n maxRetainedBytes: Infinity,\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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"}
1
+ {"version":3,"file":"shared-CA7a9oiC.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 // Scripts here bound their own output (e.g. `head -c` before base64), and\n // dropping the oldest bytes would corrupt the leading size line and base64.\n const result = await sandbox.executeCommand('sh', ['-c', script], {\n ...(opts?.timeout ? { timeout: opts.timeout } : {}),\n maxRetainedBytes: Infinity,\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. Responses a provider's\n * edge marks as its own (`x-vercel-error`, `x-mastra-preview-error`) don't\n * count either.\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, or a private port turning the\n // caller away), not from the Mastra server.\n const providerError =\n res.status === 410 || res.headers.has('x-vercel-error') || res.headers.has('x-mastra-preview-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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"}
@@ -95,7 +95,9 @@ async function tailServerLog(sandbox, remoteDir, lines = 50) {
95
95
  * Poll `${url}${path}` until the server responds. Any HTTP status below 500
96
96
  * counts as "the server is up" — gateway errors (502/503) mean nothing is
97
97
  * listening on the port, and 410 is what some providers (e.g. Vercel) return
98
- * from their edge when the sandbox itself is stopped.
98
+ * from their edge when the sandbox itself is stopped. Responses a provider's
99
+ * edge marks as its own (`x-vercel-error`, `x-mastra-preview-error`) don't
100
+ * count either.
99
101
  */
100
102
  async function waitForHealthy(url, opts = {}) {
101
103
  const path = opts.path ?? "/api";
@@ -105,7 +107,7 @@ async function waitForHealthy(url, opts = {}) {
105
107
  while (Date.now() < deadline) {
106
108
  try {
107
109
  const res = await fetch(new URL(path, url), { signal: AbortSignal.timeout(intervalMs * 5) });
108
- const providerError = res.status === 410 || res.headers.has("x-vercel-error");
110
+ const providerError = res.status === 410 || res.headers.has("x-vercel-error") || res.headers.has("x-mastra-preview-error");
109
111
  if (res.status < 500 && !providerError) return true;
110
112
  } catch {}
111
113
  await new Promise((resolve) => setTimeout(resolve, intervalMs));
@@ -114,4 +116,4 @@ async function waitForHealthy(url, opts = {}) {
114
116
  }
115
117
  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 };
116
118
 
117
- //# sourceMappingURL=shared-CmXDAiwu.js.map
119
+ //# sourceMappingURL=shared-eTQj_qC7.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shared-CmXDAiwu.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 // Scripts here bound their own output (e.g. `head -c` before base64), and\n // dropping the oldest bytes would corrupt the leading size line and base64.\n const result = await sandbox.executeCommand('sh', ['-c', script], {\n ...(opts?.timeout ? { timeout: opts.timeout } : {}),\n maxRetainedBytes: Infinity,\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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"}
1
+ {"version":3,"file":"shared-eTQj_qC7.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 // Scripts here bound their own output (e.g. `head -c` before base64), and\n // dropping the oldest bytes would corrupt the leading size line and base64.\n const result = await sandbox.executeCommand('sh', ['-c', script], {\n ...(opts?.timeout ? { timeout: opts.timeout } : {}),\n maxRetainedBytes: Infinity,\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. Responses a provider's\n * edge marks as its own (`x-vercel-error`, `x-mastra-preview-error`) don't\n * count either.\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, or a private port turning the\n // caller away), not from the Mastra server.\n const providerError =\n res.status === 410 || res.headers.has('x-vercel-error') || res.headers.has('x-mastra-preview-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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"}
package/dist/shared.d.ts CHANGED
@@ -53,7 +53,9 @@ export declare function tailServerLog(sandbox: WorkspaceSandbox, remoteDir: stri
53
53
  * Poll `${url}${path}` until the server responds. Any HTTP status below 500
54
54
  * counts as "the server is up" — gateway errors (502/503) mean nothing is
55
55
  * listening on the port, and 410 is what some providers (e.g. Vercel) return
56
- * from their edge when the sandbox itself is stopped.
56
+ * from their edge when the sandbox itself is stopped. Responses a provider's
57
+ * edge marks as its own (`x-vercel-error`, `x-mastra-preview-error`) don't
58
+ * count either.
57
59
  */
58
60
  export declare function waitForHealthy(url: string, opts?: {
59
61
  path?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE5E,+FAA+F;AAC/F,eAAO,MAAM,eAAe,eAAe,CAAC;AAC5C,iDAAiD;AACjD,eAAO,MAAM,YAAY,OAAO,CAAC;AACjC,wGAAwG;AACxG,eAAO,MAAM,aAAa,sBAAsB,CAAC;AACjD,4CAA4C;AAC5C,eAAO,MAAM,cAAc,uBAAuB,CAAC;AACnD,6CAA6C;AAC7C,eAAO,MAAM,cAAc,uBAAuB,CAAC;AACnD,uFAAuF;AACvF,eAAO,MAAM,cAAc,yBAAyB,CAAC;AAErD,yFAAyF;AACzF,wBAAsB,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAM7F;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQrG;AAED,6CAA6C;AAC7C,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,yEAAyE;AACzE,wBAAsB,YAAY,CAChC,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE;IACL,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GACA,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAuB/D;AAMD;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAcpG;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9F;AAED,mDAAmD;AACnD,wBAAsB,aAAa,CAAC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAU7G;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GACpE,OAAO,CAAC,OAAO,CAAC,CAqBlB"}
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE5E,+FAA+F;AAC/F,eAAO,MAAM,eAAe,eAAe,CAAC;AAC5C,iDAAiD;AACjD,eAAO,MAAM,YAAY,OAAO,CAAC;AACjC,wGAAwG;AACxG,eAAO,MAAM,aAAa,sBAAsB,CAAC;AACjD,4CAA4C;AAC5C,eAAO,MAAM,cAAc,uBAAuB,CAAC;AACnD,6CAA6C;AAC7C,eAAO,MAAM,cAAc,uBAAuB,CAAC;AACnD,uFAAuF;AACvF,eAAO,MAAM,cAAc,yBAAyB,CAAC;AAErD,yFAAyF;AACzF,wBAAsB,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAM7F;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQrG;AAED,6CAA6C;AAC7C,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,yEAAyE;AACzE,wBAAsB,YAAY,CAChC,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE;IACL,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GACA,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAuB/D;AAMD;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAcpG;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9F;AAED,mDAAmD;AACnD,wBAAsB,aAAa,CAAC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAU7G;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GACpE,OAAO,CAAC,OAAO,CAAC,CAuBlB"}
@@ -1,2 +1,2 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./main-B7L0jx6R.js","./rolldown-runtime-BWaJ3C7D.js","./preload-helper-CRzLMJPS.js","./dist-CgB3_3n_.js","./dist-CZ3nRtXK.js","./dist-kzlMryCP.js","./dist-Dea0Dfa0.js","./dist-Bg8xUYnp.js","./lib-DRuii7jc.js"])))=>i.map(i=>d[i]);
2
- import{t as e}from"./preload-helper-CRzLMJPS.js";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var t=!1;function n(e){return e instanceof Error?e.stack||e.message:String(e)}function r(e,{showDetails:r=t}={}){let i=document.getElementById(`root`);if(!i||i.childElementCount>0)return;let a=document.createElement(`main`);a.setAttribute(`role`,`alert`),a.style.cssText=`min-height:100vh;background:#0b0d10;color:#f4f4f5;font-family:"Mona Sans",ui-sans-serif,system-ui,sans-serif;font-feature-settings:"ss06" on;padding:32px;box-sizing:border-box;`;let o=document.createElement(`h1`);o.textContent=`Mastra Studio failed to start`,o.style.cssText=`font-size:20px;line-height:1.4;margin:0 0 8px;`;let s=document.createElement(`p`);if(s.textContent=r?`The startup module failed before React could render. Check the Vite terminal and browser console for the original request details.`:`The startup module failed before React could render. Run Studio in development mode to view detailed diagnostics.`,s.style.cssText=`color:#a1a1aa;max-width:760px;margin:0 0 20px;line-height:1.6;`,a.append(o,s),r){let t=document.createElement(`pre`);t.textContent=n(e),t.style.cssText=`white-space:pre-wrap;overflow:auto;background:#18181b;border:1px solid #3f3f46;border-radius:8px;padding:16px;max-width:100%;line-height:1.5;`,a.append(t)}i.replaceChildren(a)}try{let{startStudio:t}=await e(async()=>{let{startStudio:e}=await import(`./main-B7L0jx6R.js`);return{startStudio:e}},__vite__mapDeps([0,1,2,3,4,5,6,7,8]),import.meta.url);t()}catch(e){console.error(`Mastra Studio failed to start`,e),r(e)}
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./main-C4wZvSZw.js","./rolldown-runtime-BWaJ3C7D.js","./preload-helper-CRzLMJPS.js","./dist-CgB3_3n_.js","./dist-CZ3nRtXK.js","./dist-kzlMryCP.js","./dist-Dea0Dfa0.js","./dist-Bg8xUYnp.js","./lib-DRuii7jc.js"])))=>i.map(i=>d[i]);
2
+ import{t as e}from"./preload-helper-CRzLMJPS.js";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var t=!1;function n(e){return e instanceof Error?e.stack||e.message:String(e)}function r(e,{showDetails:r=t}={}){let i=document.getElementById(`root`);if(!i||i.childElementCount>0)return;let a=document.createElement(`main`);a.setAttribute(`role`,`alert`),a.style.cssText=`min-height:100vh;background:#0b0d10;color:#f4f4f5;font-family:"Mona Sans",ui-sans-serif,system-ui,sans-serif;font-feature-settings:"ss06" on;padding:32px;box-sizing:border-box;`;let o=document.createElement(`h1`);o.textContent=`Mastra Studio failed to start`,o.style.cssText=`font-size:20px;line-height:1.4;margin:0 0 8px;`;let s=document.createElement(`p`);if(s.textContent=r?`The startup module failed before React could render. Check the Vite terminal and browser console for the original request details.`:`The startup module failed before React could render. Run Studio in development mode to view detailed diagnostics.`,s.style.cssText=`color:#a1a1aa;max-width:760px;margin:0 0 20px;line-height:1.6;`,a.append(o,s),r){let t=document.createElement(`pre`);t.textContent=n(e),t.style.cssText=`white-space:pre-wrap;overflow:auto;background:#18181b;border:1px solid #3f3f46;border-radius:8px;padding:16px;max-width:100%;line-height:1.5;`,a.append(t)}i.replaceChildren(a)}try{let{startStudio:t}=await e(async()=>{let{startStudio:e}=await import(`./main-C4wZvSZw.js`);return{startStudio:e}},__vite__mapDeps([0,1,2,3,4,5,6,7,8]),import.meta.url);t()}catch(e){console.error(`Mastra Studio failed to start`,e),r(e)}