@mastra/e2b 0.12.1-alpha.2 → 0.12.2-alpha.0

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,"file":"index.js","names":["shellQuote","shellQuote","shellQuote","shellQuote","normalizeSetupCommands","gitAuthFlag"],"sources":["../src/utils/template.ts","../src/sandbox/mounts/types.ts","../src/utils/shell-quote.ts","../src/sandbox/mounts/s3.ts","../src/sandbox/mounts/gcs.ts","../src/sandbox/mounts/azure.ts","../src/sandbox/process-manager.ts","../src/sandbox/index.ts","../../../packages/_internals/workspace/dist/index.js","../src/utils/repo-template.ts","../src/provider.ts","../src/code-mode/transport.ts"],"sourcesContent":["/**\n * E2B Template Utilities\n *\n * Helper functions for creating and managing E2B sandbox templates.\n */\nimport { createHash } from 'node:crypto';\nimport { Template } from 'e2b';\nimport type { TemplateBuilder } from 'e2b';\n\n// =============================================================================\n// Template Types\n// =============================================================================\n\n/**\n * Template specification for E2B sandbox.\n *\n * Can be:\n * - `string` - Existing template ID (e.g., 'base', 'my-custom-template')\n * - `TemplateBuilder` - A built template object from Template()\n * - `(base: TemplateBuilder) => TemplateBuilder` - Callback to customize the base template\n *\n * @example Using template ID\n * ```typescript\n * new E2BSandbox({ template: 'my-custom-template' })\n * ```\n *\n * @example Using Template builder\n * ```typescript\n * import { Template } from 'e2b';\n *\n * new E2BSandbox({\n * template: Template()\n * .fromUbuntuImage('22.04')\n * .aptInstall(['s3fs', 'curl'])\n * .setEnvs({ NODE_ENV: 'production' })\n * })\n * ```\n *\n * @example Customizing default mountable template\n * ```typescript\n * new E2BSandbox({\n * template: base => base\n * .aptInstall(['nodejs', 'npm'])\n * .runCmd('npm install -g typescript')\n * })\n * ```\n */\nexport type TemplateSpec =\n | string\n | TemplateBuilder\n | ((base: TemplateBuilder) => TemplateBuilder)\n | NamedTemplateSpec\n | DeferredNamedTemplateSpec;\n\n/**\n * A template builder paired with a deterministic name (the word E2B's own\n * `Template.build(template, name)` uses: the name IS the identity, and may\n * carry a `:tag` qualifier).\n *\n * Resolution is lazy build-if-missing: the sandbox checks\n * `Template.exists(name)` and reuses the existing build when present, so\n * every sandbox constructed with the same name shares one template. When\n * the name is missing the build runs once; if the build fails the sandbox\n * falls back to `fallbackTemplate` (or the default mountable template) so a\n * broken build degrades to a cold start instead of a wedged session.\n */\nexport interface NamedTemplateSpec {\n /** Deterministic template ref (`name:tag`, e.g. content-hashed name). */\n ref: string;\n /** Builder used when no template exists under the name yet. */\n template: TemplateBuilder;\n /**\n * Template used when the named build fails. May itself be a named spec,\n * resolved exists-then-build under its own name — one rung only: a named\n * fallback's own `fallbackTemplate` is ignored, and anything failing past\n * it lands on the default mountable template. Defaults to the default\n * mountable template.\n */\n fallbackTemplate?: string | TemplateBuilder | NamedTemplateSpec;\n /**\n * Ref (`name:tag`) of a previous successful build of this template. When\n * `name` does not exist yet but this ref does, the sandbox is created\n * from the stale build immediately and the `name` build is kicked off in\n * the background (non-blocking rebuild-in-place) — only the very first\n * build of a template ever blocks a sandbox start.\n */\n staleRef?: string;\n /**\n * Extra tags assigned alongside the name's tag on every successful build\n * (e.g. a stable `current` pointer that {@link staleRef} targets).\n */\n buildTags?: string[];\n /**\n * Machine resources for builds of this template — sandboxes created from\n * it get exactly these. Applied to the named build and its background\n * rebuilds. For content-hashed specs the same values must participate in\n * the name, or a resize would silently reuse a template built at the\n * old size.\n */\n buildResources?: TemplateResources;\n}\n\n/** Machine resources for a template build. */\nexport interface TemplateResources {\n cpuCount?: number;\n memoryMB?: number;\n}\n\n/** Options for the default mountable template. */\nexport interface MountableTemplateOptions extends TemplateResources {\n /**\n * Exact Node.js version installed over the base image's stale runtime\n * (`MAJOR.MINOR.PATCH`). Part of the template identity, so changing it\n * builds a new template. Defaults to {@link DEFAULT_NODE_VERSION}.\n */\n nodeVersion?: string;\n}\n\n/**\n * Resource defaults matching the e2b SDK's own build defaults. Hashed and\n * passed to every build explicitly, so a template's identity and its built\n * artifact can never disagree about machine size — even if the SDK\n * defaults drift.\n */\nexport const DEFAULT_CPU_COUNT = 2;\nexport const DEFAULT_MEMORY_MB = 1024;\n\n/**\n * Node.js version installed into the default template — the current LTS at\n * pin time. An exact version rather than an `lts` alias so the template's\n * contents can never drift under a stable identity hash; bump deliberately\n * (each bump builds new templates).\n */\nexport const DEFAULT_NODE_VERSION = '24.20.0';\n\nconst NODE_VERSION_PATTERN = /^\\d+\\.\\d+\\.\\d+$/;\n\nexport function isNamedTemplateSpec(spec: TemplateSpec): spec is NamedTemplateSpec {\n return typeof spec === 'object' && spec !== null && 'ref' in spec && 'template' in spec;\n}\n\n/**\n * A named spec whose name and build steps are computed at resolution time\n * rather than construction time — e.g. a repo template that pins itself to\n * the repository's current default-branch head, fetched right before the\n * exists-then-build check. `resolveSpec()` runs once per `start()` template\n * resolution; failures inside it must be handled by the implementation\n * (return a degraded spec) — a rejection falls through to the sandbox's\n * default-template fallback.\n */\nexport interface DeferredNamedTemplateSpec {\n resolveSpec(): Promise<NamedTemplateSpec>;\n}\n\nexport function isDeferredNamedTemplateSpec(spec: TemplateSpec): spec is DeferredNamedTemplateSpec {\n return (\n typeof spec === 'object' &&\n spec !== null &&\n 'resolveSpec' in spec &&\n typeof (spec as DeferredNamedTemplateSpec).resolveSpec === 'function'\n );\n}\n\n/**\n * Result from createMountableTemplate containing both the template and its ID.\n */\nexport interface MountableTemplateResult {\n /** The template builder with mount dependencies */\n template: TemplateBuilder;\n /** Deterministic template ID for caching */\n id: string;\n /** List of apt packages installed in the template */\n aptPackages: string[];\n /**\n * Machine resources baked into the identity, normalized to the defaults.\n * Pass these to the build so the artifact matches the hash.\n */\n resources: Required<TemplateResources>;\n}\n\n/**\n * Version of the default mountable template.\n * Increment this when changing the default template dependencies.\n * v2 added machine resources to the identity hash.\n * v3 installed a pinned current Node LTS over the base image's stale\n * runtime and enabled corepack.\n */\nexport const MOUNTABLE_TEMPLATE_VERSION = 'v3';\n\n/**\n * Create a base template with FUSE mounting dependencies pre-installed.\n *\n * This template includes s3fs and fuse packages required for mounting\n * cloud filesystems (S3, GCS, R2) into the sandbox.\n *\n * The returned `id` is deterministic, allowing E2BSandbox to check if\n * the template already exists before building it.\n *\n * @example Basic usage\n * ```typescript\n * const { template, id } = createMountableTemplate();\n * // First time: builds and caches the template\n * // Subsequent times: reuses existing template\n * const sandbox = new E2BSandbox({ template });\n * ```\n *\n * @example With customization\n * ```typescript\n * const { template } = createMountableTemplate();\n * const customTemplate = template\n * .aptInstall(['nodejs', 'npm'])\n * .runCmd('npm install -g typescript');\n *\n * // Note: customized templates get a unique ID, not the cached one\n * const sandbox = new E2BSandbox({ template: customTemplate });\n * ```\n *\n * @returns Object with template builder and deterministic ID\n */\nexport function createDefaultMountableTemplate(options?: MountableTemplateOptions): MountableTemplateResult {\n const aptPackages = ['s3fs', 'fuse'];\n // Resources are part of the template's identity: each machine size is its\n // own template, so a resize can never silently reuse a build at the old\n // size. Absent and explicitly-default are the same template.\n const cpuCount = options?.cpuCount ?? DEFAULT_CPU_COUNT;\n const memoryMB = options?.memoryMB ?? DEFAULT_MEMORY_MB;\n const nodeVersion = options?.nodeVersion ?? DEFAULT_NODE_VERSION;\n // The version is interpolated into a build shell command below, so it is\n // validated before it can be interpolated into one.\n if (!NODE_VERSION_PATTERN.test(nodeVersion)) {\n throw new Error(`Invalid nodeVersion \"${nodeVersion}\": expected an exact version like \"24.20.0\"`);\n }\n const config = { version: MOUNTABLE_TEMPLATE_VERSION, aptPackages, cpuCount, memoryMB, nodeVersion };\n\n const hash = createHash('sha256')\n .update(JSON.stringify(config, Object.keys(config).sort()))\n .digest('hex')\n .slice(0, 16);\n\n // Build steps and runtime commands both run as the non-root `user` in its\n // home directory — repo checkouts live there (`$HOME/<repo>`), so no\n // extra writable root needs prepping.\n const template = Template()\n .fromTemplate('base')\n .aptInstall(aptPackages)\n // The base image ships a stale Node under /usr/local (v20.9.0 at last\n // check), old enough that corepack-fetched pnpm/yarn crash on it\n // (ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING). Overwrite it in place with\n // a pinned current release so the fresh binaries win the PATH.\n .runCmd(\n `curl -fsSL https://nodejs.org/dist/v${nodeVersion}/node-v${nodeVersion}-linux-x64.tar.gz | sudo tar -xz -C /usr/local --strip-components=1`,\n )\n // Corepack shims make `pnpm`/`yarn` resolve to whatever the repo's\n // `packageManager` field pins. It refuses to download a package manager\n // non-interactively unless the prompt is disabled, so persist that for\n // every session, not just the build shell.\n .runCmd('sudo corepack enable')\n .runCmd(`echo 'COREPACK_ENABLE_DOWNLOAD_PROMPT=0' | sudo tee -a /etc/environment`)\n .setEnvs({ COREPACK_ENABLE_DOWNLOAD_PROMPT: '0' });\n\n // Note: gcsfuse requires adding Google's apt repo which can be flaky\n // For now, we'll install it at mount time if needed\n\n return {\n template,\n id: `mastra-${hash}`,\n aptPackages,\n resources: { cpuCount, memoryMB },\n };\n}\n","/**\n * Shared types for E2B mount operations.\n */\n\nimport type { Sandbox } from 'e2b';\n\nimport type { E2BAzureBlobMountConfig } from './azure';\nimport type { E2BGCSMountConfig } from './gcs';\nimport type { E2BS3MountConfig } from './s3';\n\nexport const LOG_PREFIX = '[@mastra/e2b]';\n\n/**\n * Union of mount configs supported by E2B sandbox.\n */\nexport type E2BMountConfig = E2BS3MountConfig | E2BGCSMountConfig | E2BAzureBlobMountConfig;\n\n/**\n * Context for mount operations.\n */\nexport interface MountContext {\n sandbox: Sandbox;\n logger: {\n debug: (message: string, ...args: unknown[]) => void;\n info: (message: string, ...args: unknown[]) => void;\n warn: (message: string, ...args: unknown[]) => void;\n error: (message: string, ...args: unknown[]) => void;\n };\n}\n\n/**\n * Result of a mount operation.\n */\nexport interface MountOperationResult {\n success: boolean;\n error?: string;\n}\n\nconst SAFE_S3_BUCKET_NAME = /^[a-z0-9][a-z0-9.\\-]{1,61}[a-z0-9]$/;\nconst SAFE_GCS_BUCKET_NAME = /^[a-z0-9][a-z0-9._-]{1,61}[a-z0-9]$/;\n\nexport function validateS3BucketName(bucket: string): void {\n if (!SAFE_S3_BUCKET_NAME.test(bucket)) {\n throw new Error(\n `Invalid S3 bucket name: \"${bucket}\". Bucket names must be 3-63 characters, lowercase alphanumeric, hyphens, or dots.`,\n );\n }\n}\n\nexport function validateGCSBucketName(bucket: string): void {\n if (!SAFE_GCS_BUCKET_NAME.test(bucket)) {\n throw new Error(\n `Invalid GCS bucket name: \"${bucket}\". Bucket names must be 3-63 characters, lowercase alphanumeric, hyphens, underscores, or dots.`,\n );\n }\n}\n\n/**\n * Validate an endpoint URL before interpolating into shell commands.\n */\nexport function validateEndpoint(endpoint: string): void {\n try {\n new URL(endpoint);\n } catch {\n throw new Error(`Invalid endpoint URL: \"${endpoint}\"`);\n }\n}\n\n/**\n * Validate an AWS region (or R2's \"auto\") before interpolating into shell commands.\n * Accepts standard AWS region codes like \"us-east-1\", \"ap-northeast-1\", and \"auto\".\n */\nconst SAFE_REGION = /^[a-z0-9-]{2,32}$/;\n\nexport function validateRegion(region: unknown): asserts region is string {\n if (typeof region !== 'string' || !SAFE_REGION.test(region)) {\n throw new Error(\n `Invalid region: ${JSON.stringify(region)}. Region must be a string of lowercase alphanumeric or hyphens (e.g., \"us-east-1\", \"ap-northeast-1\", \"auto\").`,\n );\n }\n}\n\n/**\n * Validate and normalize a mount prefix before interpolating into shell commands.\n * Returns the normalized prefix (no leading/trailing slashes).\n *\n * Shell safety is handled by shellQuote() at the call site, so this function\n * only enforces path-level rules (no traversal, no empty result, no control chars).\n */\nexport function validatePrefix(prefix: string): string {\n // Trim leading/trailing slashes\n let normalized = prefix;\n while (normalized.startsWith('/')) normalized = normalized.slice(1);\n while (normalized.endsWith('/')) normalized = normalized.slice(0, -1);\n\n if (!normalized) {\n throw new Error('Mount prefix cannot be empty after normalization.');\n }\n if (normalized.includes('//') || normalized.split('/').some(s => s === '.' || s === '..')) {\n throw new Error(`Invalid mount prefix: \"${prefix}\". Path traversal is not allowed.`);\n }\n // Block control characters (U+0000–U+001F, U+007F) which are invalid in filesystem paths\n if (/[\\x00-\\x1f\\x7f]/.test(normalized)) {\n throw new Error(`Invalid mount prefix: \"${prefix}\". Control characters are not allowed.`);\n }\n return normalized;\n}\n","/**\n * Shell-quote a single argument for safe use in a command string.\n *\n * Arguments containing only safe characters are returned as-is.\n * All others are wrapped in single quotes with embedded single quotes escaped.\n */\nexport function shellQuote(arg: string): string {\n // Safe characters that don't need quoting\n if (/^[a-zA-Z0-9._\\-/@:=]+$/.test(arg)) return arg;\n // Wrap in single quotes, escaping any embedded single quotes\n return \"'\" + arg.replace(/'/g, \"'\\\\''\") + \"'\";\n}\n","import { createHash } from 'node:crypto';\n\nimport type { FilesystemMountConfig } from '@mastra/core/workspace';\n\nimport { shellQuote } from '../../utils/shell-quote';\nimport { LOG_PREFIX, validateEndpoint, validatePrefix, validateRegion, validateS3BucketName } from './types';\nimport type { MountContext } from './types';\n\n/**\n * S3 mount config for E2B (mounted via s3fs-fuse).\n *\n * If credentials are not provided, the bucket will be mounted as read-only\n * using the `public_bucket=1` option (for public AWS S3 buckets only).\n *\n * Note: S3-compatible services (R2, MinIO, etc.) always require credentials.\n */\nexport interface E2BS3MountConfig extends FilesystemMountConfig {\n type: 's3';\n /** S3 bucket name */\n bucket: string;\n /** AWS region */\n region: string;\n /** S3 endpoint for S3-compatible storage (MinIO, etc.) */\n endpoint?: string;\n /** AWS access key ID (optional - omit for public buckets) */\n accessKeyId?: string;\n /** AWS secret access key (optional - omit for public buckets) */\n secretAccessKey?: string;\n /**\n * Optional prefix (subdirectory) to mount instead of the entire bucket.\n * Uses s3fs `bucket:/prefix` syntax. Leading/trailing slashes are normalized.\n */\n prefix?: string;\n /** Mount as read-only (even if credentials have write access) */\n readOnly?: boolean;\n}\n\n/**\n * Mount an S3 bucket using s3fs-fuse.\n */\nexport async function mountS3(mountPath: string, config: E2BS3MountConfig, ctx: MountContext): Promise<void> {\n const { sandbox, logger } = ctx;\n\n // Validate inputs before interpolating into shell commands\n validateS3BucketName(config.bucket);\n validateRegion(config.region);\n if (config.endpoint) {\n validateEndpoint(config.endpoint);\n }\n\n // Check if s3fs is installed\n const checkResult = await sandbox.commands.run('which s3fs || echo \"not found\"');\n if (checkResult.stdout.includes('not found')) {\n logger.warn(`${LOG_PREFIX} s3fs not found, attempting runtime installation...`);\n logger.info(\n `${LOG_PREFIX} Tip: For faster startup, use createMountableTemplate() to pre-install s3fs in your sandbox template`,\n );\n\n await sandbox.commands.run('sudo apt-get update 2>&1', { timeoutMs: 60000 });\n\n const installResult = await sandbox.commands.run(\n 'sudo apt-get install -y s3fs fuse 2>&1 || sudo apt-get install -y s3fs-fuse fuse 2>&1',\n { timeoutMs: 120000 },\n );\n\n if (installResult.exitCode !== 0) {\n throw new Error(\n `Failed to install s3fs. ` +\n `For S3 mounting, your template needs s3fs and fuse packages.\\n\\n` +\n `Option 1: Use createMountableTemplate() helper:\\n` +\n ` import { E2BSandbox, createMountableTemplate } from '@mastra/e2b';\\n` +\n ` const sandbox = new E2BSandbox({ template: createMountableTemplate() });\\n\\n` +\n `Option 2: Customize the base template:\\n` +\n ` new E2BSandbox({ template: base => base.aptInstall(['your-packages']) })\\n\\n` +\n `Error details: ${installResult.stderr || installResult.stdout}`,\n );\n }\n }\n\n // Get user's uid/gid for proper file ownership\n const idResult = await sandbox.commands.run('id -u && id -g');\n const [uid, gid] = idResult.stdout.trim().split('\\n');\n\n // Validate credentials before any network calls — this gives the user a clear,\n // immediate error instead of a confusing connectivity failure.\n const hasAccessKey = !!config.accessKeyId;\n const hasSecretKey = !!config.secretAccessKey;\n if (hasAccessKey !== hasSecretKey) {\n throw new Error('Both accessKeyId and secretAccessKey must be provided together.');\n }\n const hasCredentials = hasAccessKey && hasSecretKey;\n\n // Use a per-mount credentials file. s3fs reads `passwd_file` at mount time, so a\n // single shared path (rewritten rm -> write -> chmod on every mount) lets\n // concurrent mounts race: one mount's write/chmod interleaves with another's rm,\n // causing EACCES or a mount reading another mount's credentials. Hashing the\n // mountPath gives each mount a unique, stable file (same approach as azure.ts).\n const mountHash = createHash('md5').update(mountPath).digest('hex').slice(0, 8);\n const credentialsPath = `/tmp/.passwd-s3fs-${mountHash}`;\n\n // S3-compatible services (R2, MinIO, etc.) require credentials\n // public_bucket=1 only works for truly public AWS S3 buckets\n if (!hasCredentials && config.endpoint) {\n throw new Error(\n `S3-compatible storage requires credentials. ` +\n `Detected endpoint: ${config.endpoint}. ` +\n `The public_bucket option only works for AWS S3 public buckets, not R2, MinIO, etc.`,\n );\n }\n\n if (hasCredentials) {\n // Write credentials file (remove old one first to avoid permission issues)\n const credentialsContent = `${config.accessKeyId}:${config.secretAccessKey}`;\n await sandbox.commands.run(`sudo rm -f ${credentialsPath}`);\n await sandbox.files.write(credentialsPath, credentialsContent);\n await sandbox.commands.run(`chmod 600 ${credentialsPath}`);\n }\n\n // Build mount options\n const mountOptions: string[] = [];\n\n if (hasCredentials) {\n mountOptions.push(`passwd_file=${credentialsPath}`);\n } else {\n // Public bucket mode - read-only access without credentials\n mountOptions.push('public_bucket=1');\n logger.debug(`${LOG_PREFIX} No credentials provided, mounting as public bucket (read-only)`);\n }\n\n mountOptions.push('allow_other'); // Allow non-root users to access the mount\n\n // Set uid/gid so mounted files are owned by user, not root\n if (uid && gid) {\n mountOptions.push(`uid=${uid}`, `gid=${gid}`);\n }\n\n if (config.endpoint) {\n // For S3-compatible storage (MinIO, R2, etc.)\n const endpoint = config.endpoint.replace(/\\/$/, '');\n mountOptions.push(`url=${endpoint}`, 'use_path_request_style', 'sigv4', 'nomultipart');\n }\n\n // s3fs's `endpoint` option sets the AWS region used for sigv4 signing\n // (confusingly named — distinct from the URL `endpoint` flag above).\n // Default is us-east-1, which produces SignatureDoesNotMatch errors against\n // buckets in other regions or S3-compatible services that validate the region.\n mountOptions.push(`endpoint=${config.region}`);\n\n if (config.readOnly) {\n mountOptions.push('ro');\n logger.debug(`${LOG_PREFIX} Mounting as read-only`);\n }\n\n // Build the s3fs bucket argument — supports optional prefix via `bucket:/path` syntax\n let bucketArg = config.bucket;\n if (config.prefix) {\n const normalizedPrefix = validatePrefix(config.prefix);\n bucketArg = `${config.bucket}:/${normalizedPrefix}`;\n }\n\n // Mount with sudo (required for /dev/fuse access)\n const mountCmd = `sudo s3fs ${shellQuote(bucketArg)} ${shellQuote(mountPath)} -o ${mountOptions.join(' -o ')}`;\n logger.debug(`${LOG_PREFIX} Mounting S3:`, hasCredentials ? mountCmd.replace(credentialsPath, '***') : mountCmd);\n\n try {\n const result = await sandbox.commands.run(mountCmd, { timeoutMs: 60_000 });\n logger.debug(`${LOG_PREFIX} s3fs result:`, {\n exitCode: result.exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n });\n if (result.exitCode !== 0) {\n throw new Error(`Failed to mount S3 bucket: ${result.stderr || result.stdout}`);\n }\n } catch (error: unknown) {\n const errorObj = error as { result?: { exitCode: number; stdout: string; stderr: string } };\n const stderr = errorObj.result?.stderr || '';\n const stdout = errorObj.result?.stdout || '';\n logger.error(`${LOG_PREFIX} s3fs error:`, { stderr, stdout, error: String(error) });\n throw new Error(`Failed to mount S3 bucket: ${stderr || stdout || error}`);\n }\n\n // s3fs daemonizes before running its FUSE init, where the bucket check happens.\n // If that check fails (wrong region, bad credentials, unsupported endpoint),\n // the daemon exits but the parent has already returned exit code 0.\n // Verify the mount actually attached.\n const verify = await sandbox.commands.run(`mountpoint -q ${shellQuote(mountPath)}`);\n if (verify.exitCode !== 0) {\n throw new Error(\n `s3fs returned exit 0 but ${mountPath} is not a mountpoint. ` +\n `The s3fs daemon likely failed during FUSE init (common causes: region mismatch, ` +\n `invalid credentials, or an S3-compatible endpoint that rejects the signature). ` +\n `Re-run inside the sandbox with '-f -o dbglevel=info' to see the underlying error.`,\n );\n }\n}\n","import { createHash } from 'node:crypto';\n\nimport type { FilesystemMountConfig } from '@mastra/core/workspace';\n\nimport { shellQuote } from '../../utils/shell-quote';\nimport { LOG_PREFIX, validateGCSBucketName, validatePrefix } from './types';\nimport type { MountContext } from './types';\n\n/**\n * GCS mount config for E2B (mounted via gcsfuse).\n *\n * If credentials are not provided, the bucket will be mounted as read-only\n * using anonymous access (for public buckets only).\n */\nexport interface E2BGCSMountConfig extends FilesystemMountConfig {\n type: 'gcs';\n /** GCS bucket name */\n bucket: string;\n /** Service account key JSON (optional - omit for public buckets) */\n serviceAccountKey?: string;\n /**\n * GCS key prefix to scope the mount (without trailing slash).\n * When set, gcsfuse uses --only-dir to mount only this subdirectory, so\n * sandbox paths map directly to prefixed GCS keys.\n */\n prefix?: string;\n}\n\n/**\n * Mount a GCS bucket using gcsfuse.\n *\n * When `config.prefix` is set, gcsfuse uses `--only-dir` to mount only that\n * subdirectory, aligning sandbox paths with the prefixed GCS keys (mirrors the\n * S3 `bucket:/prefix` and Azure `--subdirectory` mounts).\n */\nexport async function mountGCS(mountPath: string, config: E2BGCSMountConfig, ctx: MountContext): Promise<void> {\n const { sandbox, logger } = ctx;\n\n // Validate inputs before interpolating into shell commands\n validateGCSBucketName(config.bucket);\n\n // Install gcsfuse if not present\n const checkResult = await sandbox.commands.run('which gcsfuse || echo \"not found\"');\n if (checkResult.stdout.includes('not found')) {\n // Detect Ubuntu codename for the gcsfuse repo (default to jammy if unknown)\n const codenameResult = await sandbox.commands.run('lsb_release -cs 2>/dev/null || echo jammy');\n const codename = codenameResult.stdout.trim() || 'jammy';\n\n // Use signed-by keyring instead of deprecated apt-key\n await sandbox.commands.run(\n 'curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/gcsfuse.gpg && ' +\n `echo \"deb [signed-by=/etc/apt/keyrings/gcsfuse.gpg] https://packages.cloud.google.com/apt gcsfuse-${codename} main\" | sudo tee /etc/apt/sources.list.d/gcsfuse.list && ` +\n 'sudo apt-get update && sudo apt-get install -y gcsfuse',\n { timeoutMs: 120_000 },\n );\n }\n\n // Get user's uid/gid for proper file ownership\n const idResult = await sandbox.commands.run('id -u && id -g');\n const [uid, gid] = idResult.stdout.trim().split('\\n');\n\n // Build gcsfuse flags\n // Note: gcsfuse uses --uid/--gid flags, not -o uid=X style\n const uidGidFlags = uid && gid ? `--uid=${uid} --gid=${gid}` : '';\n\n // Scope the mount to a subdirectory when a prefix is set (mirrors S3/Azure mounts).\n // validatePrefix normalizes and guards against path traversal; shellQuote guards the shell.\n const onlyDirFlag = config.prefix ? ` --only-dir=${shellQuote(validatePrefix(config.prefix))}` : '';\n\n const hasCredentials = !!config.serviceAccountKey;\n let mountCmd: string;\n\n if (hasCredentials) {\n // Write service account key with root ownership so sudo gcsfuse can read it.\n // Per-mount path (hashed mountPath) so concurrent mounts don't race on a single\n // shared rm -> write -> chmod sequence (same approach as azure.ts).\n const mountHash = createHash('md5').update(mountPath).digest('hex').slice(0, 8);\n const keyPath = `/tmp/gcs-key-${mountHash}.json`;\n await sandbox.commands.run(`sudo rm -f ${keyPath}`);\n await sandbox.files.write(keyPath, config.serviceAccountKey!);\n // Make readable by root (sudo gcsfuse runs as root)\n await sandbox.commands.run(`sudo chown root:root ${keyPath} && sudo chmod 600 ${keyPath}`);\n\n // Mount with credentials using --key-file flag\n // Use sudo for /dev/fuse access (same as s3fs)\n // -o allow_other lets non-root users access the FUSE mount\n mountCmd = `sudo gcsfuse --key-file=${keyPath} -o allow_other ${uidGidFlags}${onlyDirFlag} ${config.bucket} ${mountPath}`;\n } else {\n // Public bucket mode - read-only access without credentials\n // Use --anonymous-access flag (not -o option)\n // Use sudo for /dev/fuse access (same as s3fs)\n logger.debug(`${LOG_PREFIX} No credentials provided, mounting GCS as public bucket (read-only)`);\n\n mountCmd = `sudo gcsfuse --anonymous-access -o allow_other ${uidGidFlags}${onlyDirFlag} ${config.bucket} ${mountPath}`;\n }\n\n logger.debug(`${LOG_PREFIX} Mounting GCS:`, mountCmd);\n\n try {\n const result = await sandbox.commands.run(mountCmd, { timeoutMs: 60_000 });\n logger.debug(`${LOG_PREFIX} gcsfuse result:`, {\n exitCode: result.exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n });\n if (result.exitCode !== 0) {\n throw new Error(`Failed to mount GCS bucket: ${result.stderr || result.stdout}`);\n }\n } catch (error: unknown) {\n const errorObj = error as { result?: { exitCode: number; stdout: string; stderr: string } };\n const stderr = errorObj.result?.stderr || '';\n const stdout = errorObj.result?.stdout || '';\n logger.error(`${LOG_PREFIX} gcsfuse error:`, { stderr, stdout, error: String(error) });\n throw new Error(`Failed to mount GCS bucket: ${stderr || stdout || error}`);\n }\n}\n","import { createHash } from 'node:crypto';\n\nimport type { FilesystemMountConfig } from '@mastra/core/workspace';\n\nimport { shellQuote } from '../../utils/shell-quote';\nimport { LOG_PREFIX, validateEndpoint, validatePrefix } from './types';\nimport type { MountContext } from './types';\n\n/**\n * Azure Blob mount config for E2B (mounted via blobfuse2).\n *\n * Authentication is selected from the first applicable option:\n * 1. `useDefaultCredential` (managed identity, requires running in Azure)\n * 2. `sasToken`\n * 3. `accountKey`\n * 4. `connectionString` (parsed for AccountName/AccountKey/SharedAccessSignature/BlobEndpoint)\n */\nexport interface E2BAzureBlobMountConfig extends FilesystemMountConfig {\n type: 'azure-blob';\n /** Azure Blob container name */\n container: string;\n /** Storage account name (required unless supplied via connectionString) */\n accountName?: string;\n /** Storage account access key */\n accountKey?: string;\n /** Shared Access Signature token (without leading '?') */\n sasToken?: string;\n /** Azure Storage connection string */\n connectionString?: string;\n /** Use DefaultAzureCredential / managed identity (mode: msi) */\n useDefaultCredential?: boolean;\n /** Custom blob endpoint (e.g. for sovereign clouds or Azurite) */\n endpoint?: string;\n /**\n * Optional prefix (subdirectory) to mount instead of the entire container.\n * Uses blobfuse2 --subdirectory. Leading/trailing slashes are normalized.\n */\n prefix?: string;\n /** Mount as read-only */\n readOnly?: boolean;\n}\n\n// Azure container names: 3-63 lowercase alphanumeric chars or hyphens, no leading/\n// trailing hyphen, no consecutive hyphens. Stricter than the generic bucket regex.\nconst SAFE_CONTAINER_NAME = /^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/;\nconst BLOBFUSE2_GITHUB_DEB =\n 'https://github.com/Azure/azure-storage-fuse/releases/download/blobfuse2-2.5.1/blobfuse2-2.5.1-Ubuntu-22.04.x86_64.deb';\n\nfunction validateContainerName(name: string): void {\n if (!SAFE_CONTAINER_NAME.test(name) || name.includes('--')) {\n throw new Error(\n `Invalid Azure container name: \"${name}\". Container names must be 3-63 lowercase alphanumeric characters or hyphens, with no consecutive hyphens.`,\n );\n }\n}\n\ninterface ParsedConnectionString {\n accountName?: string;\n accountKey?: string;\n sasToken?: string;\n endpoint?: string;\n endpointSuffix?: string;\n protocol?: string;\n}\n\nfunction parseConnectionString(cs: string): ParsedConnectionString {\n const out: ParsedConnectionString = {};\n for (const part of cs.split(';')) {\n const eq = part.indexOf('=');\n if (eq === -1) continue;\n const key = part.slice(0, eq).trim();\n const value = part.slice(eq + 1).trim();\n if (!value) continue;\n if (key === 'AccountName') out.accountName = value;\n else if (key === 'AccountKey') out.accountKey = value;\n else if (key === 'SharedAccessSignature') out.sasToken = value;\n else if (key === 'BlobEndpoint') out.endpoint = value;\n else if (key === 'EndpointSuffix') out.endpointSuffix = value;\n else if (key === 'DefaultEndpointsProtocol') out.protocol = value;\n }\n if (!out.endpoint && out.accountName) {\n out.endpoint = `${out.protocol || 'https'}://${out.accountName}.blob.${out.endpointSuffix || 'core.windows.net'}`;\n }\n return out;\n}\n\nfunction yamlString(value: string): string {\n return `\"${value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`;\n}\n\nfunction parseOsRelease(output: string): Record<string, string> {\n const values: Record<string, string> = {};\n for (const line of output.split('\\n')) {\n const eq = line.indexOf('=');\n if (eq === -1) continue;\n const key = line.slice(0, eq);\n const value = line\n .slice(eq + 1)\n .trim()\n .replace(/^\"|\"$/g, '');\n values[key] = value;\n }\n return values;\n}\n\ninterface MicrosoftAptRepo {\n repoUrl: string;\n suite: string;\n}\n\nfunction resolveMicrosoftAptRepos(osReleaseOutput: string): MicrosoftAptRepo[] {\n const osRelease = parseOsRelease(osReleaseOutput);\n const distroId = osRelease.ID || 'ubuntu';\n const codename = osRelease.VERSION_CODENAME || (distroId === 'debian' ? 'bookworm' : 'jammy');\n const versionId = osRelease.VERSION_ID || (distroId === 'debian' ? '12' : '22.04');\n\n if (!/^[a-z0-9][a-z0-9-]*$/.test(codename)) {\n throw new Error(`Invalid distro codename for blobfuse2 repo: \"${codename}\"`);\n }\n if (!/^\\d+(?:\\.\\d+)?$/.test(versionId)) {\n throw new Error(`Invalid distro version for blobfuse2 repo: \"${versionId}\"`);\n }\n\n if (distroId === 'debian') {\n const repos = [\n { repoUrl: `https://packages.microsoft.com/debian/${versionId.split('.')[0]}/prod`, suite: codename },\n ];\n if (versionId.split('.')[0] !== '12' || codename !== 'bookworm') {\n repos.push({ repoUrl: 'https://packages.microsoft.com/debian/12/prod', suite: 'bookworm' });\n }\n return repos;\n }\n if (distroId === 'ubuntu') {\n const repos = [{ repoUrl: `https://packages.microsoft.com/ubuntu/${versionId}/prod`, suite: codename }];\n if (versionId !== '24.04' || codename !== 'noble') {\n repos.push({ repoUrl: 'https://packages.microsoft.com/ubuntu/24.04/prod', suite: 'noble' });\n }\n if (versionId !== '22.04' || codename !== 'jammy') {\n repos.push({ repoUrl: 'https://packages.microsoft.com/ubuntu/22.04/prod', suite: 'jammy' });\n }\n return repos;\n }\n\n throw new Error(`Unsupported distro for blobfuse2 runtime installation: \"${distroId}\"`);\n}\n\ninterface ResolvedAuth {\n mode: 'key' | 'sas' | 'msi';\n accountName: string;\n accountKey?: string;\n sasToken?: string;\n endpoint?: string;\n}\n\nfunction resolveAuth(config: E2BAzureBlobMountConfig): ResolvedAuth {\n let accountName = config.accountName;\n let accountKey = config.accountKey;\n let sasToken = config.sasToken;\n let endpoint = config.endpoint;\n\n if (config.connectionString) {\n const parsed = parseConnectionString(config.connectionString);\n accountName = accountName ?? parsed.accountName;\n accountKey = accountKey ?? parsed.accountKey;\n sasToken = sasToken ?? parsed.sasToken;\n endpoint = endpoint ?? parsed.endpoint;\n }\n\n let mode: 'key' | 'sas' | 'msi';\n if (config.useDefaultCredential) {\n mode = 'msi';\n } else if (sasToken) {\n mode = 'sas';\n } else if (accountKey) {\n mode = 'key';\n } else {\n throw new Error(\n 'Azure Blob mount requires credentials: provide connectionString, accountKey + accountName, sasToken + accountName, or useDefaultCredential.',\n );\n }\n\n if (!accountName) {\n throw new Error('Azure Blob mount requires an accountName (either explicitly or via connectionString).');\n }\n\n if (endpoint) {\n validateEndpoint(endpoint);\n }\n\n return { mode, accountName, accountKey, sasToken, endpoint };\n}\n\nfunction buildBlobfuseConfig(container: string, auth: ResolvedAuth, cachePath: string, readOnly: boolean): string {\n const lines: string[] = [\n 'allow-other: true',\n 'foreground: false',\n `read-only: ${readOnly ? 'true' : 'false'}`,\n 'logging:',\n ' type: silent',\n 'components:',\n ' - libfuse',\n ' - file_cache',\n ' - attr_cache',\n ' - azstorage',\n 'libfuse:',\n ' attribute-expiration-sec: 240',\n ' entry-expiration-sec: 240',\n ' negative-entry-expiration-sec: 120',\n 'file_cache:',\n ` path: ${yamlString(cachePath)}`,\n ' timeout-sec: 120',\n 'attr_cache:',\n ' timeout-sec: 7200',\n 'azstorage:',\n ` mode: ${auth.mode}`,\n ` account-name: ${yamlString(auth.accountName)}`,\n ` container: ${yamlString(container)}`,\n ];\n if (auth.mode === 'key' && auth.accountKey) {\n lines.push(` account-key: ${yamlString(auth.accountKey)}`);\n } else if (auth.mode === 'sas' && auth.sasToken) {\n lines.push(` sas: ${yamlString(auth.sasToken)}`);\n }\n if (auth.endpoint) {\n lines.push(` endpoint: ${yamlString(auth.endpoint.replace(/\\/$/, ''))}`);\n }\n return lines.join('\\n') + '\\n';\n}\n\n/**\n * Mount an Azure Blob container using blobfuse2.\n */\nexport async function mountAzure(mountPath: string, config: E2BAzureBlobMountConfig, ctx: MountContext): Promise<void> {\n const { sandbox, logger } = ctx;\n\n validateContainerName(config.container);\n const auth = resolveAuth(config);\n const prefix = config.prefix ? validatePrefix(config.prefix) : undefined;\n\n // Install blobfuse2 if not present. Prefer Microsoft apt packages and fall\n // back to the official Azure GitHub release when the repo is unavailable.\n const checkResult = await sandbox.commands.run('which blobfuse2 || echo \"not found\"');\n if (checkResult.stdout.includes('not found')) {\n logger.warn(`${LOG_PREFIX} blobfuse2 not found, attempting runtime installation...`);\n logger.info(\n `${LOG_PREFIX} Tip: For faster startup, pre-install blobfuse2 in your sandbox template via createMountableTemplate()`,\n );\n\n const osReleaseResult = await sandbox.commands.run('cat /etc/os-release 2>/dev/null || true');\n const repos = resolveMicrosoftAptRepos(osReleaseResult.stdout);\n\n const repoSetupResult = await sandbox.commands.run(\n 'sudo mkdir -p /etc/apt/keyrings && ' +\n 'curl --retry 3 --retry-all-errors --retry-delay 2 -fsSL https://packages.microsoft.com/keys/microsoft.asc -o /tmp/ms-key.asc && ' +\n 'sudo gpg --batch --yes --dearmor -o /etc/apt/keyrings/microsoft.gpg /tmp/ms-key.asc',\n { timeoutMs: 60_000 },\n );\n\n let installResult: { exitCode: number; stdout: string; stderr: string } | undefined;\n if (repoSetupResult.exitCode === 0) {\n for (const { repoUrl, suite } of repos) {\n installResult = await sandbox.commands.run(\n `echo \"deb [signed-by=/etc/apt/keyrings/microsoft.gpg] ${repoUrl} ${suite} main\" | sudo tee /etc/apt/sources.list.d/microsoft-prod.list && ` +\n 'sudo apt-get update 2>&1 && sudo apt-get install -y blobfuse2 fuse3 2>&1',\n { timeoutMs: 180_000 },\n );\n if (installResult.exitCode === 0) break;\n logger.warn(`${LOG_PREFIX} blobfuse2 install failed for ${repoUrl} ${suite}, trying fallback if available`);\n }\n } else {\n logger.warn(`${LOG_PREFIX} Failed to set up Microsoft apt repository, trying GitHub release fallback`);\n }\n\n let verifyResult = await sandbox.commands.run('which blobfuse2 && blobfuse2 --version', { timeoutMs: 30_000 });\n if (verifyResult.exitCode !== 0) {\n installResult = await sandbox.commands.run(\n 'sudo apt-get update -qq 2>&1 || true && ' +\n 'sudo apt-get install -y fuse3 ca-certificates curl 2>&1 && ' +\n `curl -L --retry 3 --retry-all-errors --retry-delay 2 -fSLo /tmp/blobfuse2.deb ${BLOBFUSE2_GITHUB_DEB} && ` +\n 'sudo dpkg -i /tmp/blobfuse2.deb 2>&1 && ' +\n 'sudo bash -c \\'lib=$(find /usr/lib -name \"libfuse3.so.3.*\" | head -1); [ -z \"$lib\" ] || ln -sf \"$lib\" /usr/lib/x86_64-linux-gnu/libfuse3.so.3\\'',\n { timeoutMs: 180_000 },\n );\n verifyResult = await sandbox.commands.run('which blobfuse2 && blobfuse2 --version', { timeoutMs: 30_000 });\n }\n\n if (!installResult || verifyResult.exitCode !== 0) {\n throw new Error(\n `Failed to install blobfuse2. ` +\n `For Azure Blob mounting, your template needs blobfuse2 and fuse3.\\n\\n` +\n `Option 1: Use createMountableTemplate() helper:\\n` +\n ` import { E2BSandbox, createMountableTemplate } from '@mastra/e2b';\\n` +\n ` const sandbox = new E2BSandbox({ template: createMountableTemplate() });\\n\\n` +\n `Option 2: Customize the base template:\\n` +\n ` new E2BSandbox({ template: base => base.aptInstall(['your-packages']) })\\n\\n` +\n `Error details: ${\n verifyResult.stderr ||\n verifyResult.stdout ||\n installResult?.stderr ||\n installResult?.stdout ||\n 'unknown error'\n }`,\n );\n }\n }\n\n const mountHash = createHash('md5').update(mountPath).digest('hex').slice(0, 8);\n const configPath = `/tmp/.blobfuse2-config-${mountHash}.yaml`;\n const cachePath = `/tmp/blobfuse2-cache-${mountHash}`;\n const yaml = buildBlobfuseConfig(config.container, auth, cachePath, !!config.readOnly);\n\n // Write config (root-owned, 0600) since blobfuse2 runs as root via sudo for /dev/fuse access.\n await sandbox.commands.run(`sudo rm -f ${configPath}`);\n await sandbox.files.write(configPath, yaml);\n await sandbox.commands.run(`sudo chown root:root ${configPath} && sudo chmod 600 ${configPath}`);\n\n // blobfuse2 requires an empty cache directory when mounting.\n await sandbox.commands.run(`sudo rm -rf ${shellQuote(cachePath)} && sudo mkdir -p ${shellQuote(cachePath)}`);\n\n const prefixFlags = prefix ? ` --virtual-directory=true --subdirectory=${shellQuote(prefix)}` : '';\n const mountCmd = `sudo blobfuse2 mount ${shellQuote(mountPath)} --config-file=${shellQuote(configPath)}${prefixFlags}`;\n logger.debug(`${LOG_PREFIX} Mounting Azure Blob:`, mountCmd);\n\n try {\n const result = await sandbox.commands.run(mountCmd, { timeoutMs: 60_000 });\n logger.debug(`${LOG_PREFIX} blobfuse2 result:`, {\n exitCode: result.exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n });\n if (result.exitCode !== 0) {\n throw new Error(`Failed to mount Azure Blob container: ${result.stderr || result.stdout}`);\n }\n } catch (error: unknown) {\n const errorObj = error as { result?: { exitCode: number; stdout: string; stderr: string } };\n const stderr = errorObj.result?.stderr || '';\n const stdout = errorObj.result?.stdout || '';\n logger.error(`${LOG_PREFIX} blobfuse2 error:`, { stderr, stdout, error: String(error) });\n throw new Error(`Failed to mount Azure Blob container: ${stderr || stdout || error}`);\n }\n}\n","/**\n * E2B Process Manager\n *\n * Implements SandboxProcessManager for E2B cloud sandboxes.\n * Wraps the E2B SDK's commands API (background mode, sendStdin, kill, list).\n */\n\nimport { ProcessHandle, UnsupportedStdinCloseError, SandboxProcessManager } from '@mastra/core/workspace';\nimport type { CommandResult, ProcessInfo, SpawnProcessOptions } from '@mastra/core/workspace';\nimport type { CommandHandle as E2BCommandHandle, Sandbox } from 'e2b';\nimport type { E2BSandbox } from './index';\n\n// =============================================================================\n// E2B Process Handle\n// =============================================================================\n\n/**\n * Wraps an E2B CommandHandle to conform to Mastra's ProcessHandle.\n * Not exported — internal to this module.\n *\n * Listener dispatch is handled by the base class. The manager's spawn()/get()\n * methods wire E2B's constructor-time callbacks to handle.emitStdout/emitStderr.\n */\nclass E2BProcessHandle extends ProcessHandle {\n readonly pid: string;\n\n private readonly _e2bHandle: E2BCommandHandle;\n private readonly _sandbox: Sandbox;\n private readonly _startTime: number;\n private readonly _stdinMode: SpawnProcessOptions['stdinMode'];\n\n constructor(e2bHandle: E2BCommandHandle, sandbox: Sandbox, startTime: number, options?: SpawnProcessOptions) {\n super(options);\n this.pid = String(e2bHandle.pid);\n this._e2bHandle = e2bHandle;\n this._sandbox = sandbox;\n this._startTime = startTime;\n this._stdinMode = options?.stdinMode;\n }\n\n /** Delegates to E2B's handle so exitCode reflects server-side state without needing wait(). */\n get exitCode(): number | undefined {\n return this._e2bHandle.exitCode;\n }\n\n async wait(): Promise<CommandResult> {\n try {\n const result = await this._e2bHandle.wait();\n return {\n success: result.exitCode === 0,\n exitCode: result.exitCode,\n stdout: this.stdout,\n stderr: this.stderr,\n executionTimeMs: Date.now() - this._startTime,\n };\n } catch (error) {\n // E2B throws CommandExitError for non-zero exit codes (has .exitCode directly)\n // Some E2B errors also carry stdout/stderr in error.result\n const errorObj = error as {\n exitCode?: number;\n error?: string;\n stdout?: string;\n stderr?: string;\n result?: { exitCode: number; error?: string; stdout: string; stderr: string };\n };\n const exitCode = errorObj.result?.exitCode ?? errorObj.exitCode ?? this.exitCode ?? 1;\n\n // If E2B skipped the stream callbacks, retain and dispatch its attached\n // output through the normal path so maxRetainedBytes still applies.\n const attachedStdout = errorObj.result?.stdout || errorObj.stdout;\n const attachedStderr = errorObj.result?.stderr || errorObj.stderr;\n if (!this.stdout && !this.stdoutTruncated && attachedStdout) this.emitStdout(attachedStdout);\n if (!this.stderr && !this.stderrTruncated && attachedStderr) this.emitStderr(attachedStderr);\n\n const stdout = this.stdout;\n const stderr = this.stderr;\n const terminalError =\n errorObj.result?.error || errorObj.error || (error instanceof Error ? error.message : String(error));\n const errorDetail = terminalError && !stderr.includes(terminalError) ? `Error: ${terminalError}` : '';\n\n return {\n success: false,\n exitCode,\n stdout,\n stderr: [stderr, errorDetail].filter(Boolean).join('\\n'),\n executionTimeMs: Date.now() - this._startTime,\n };\n }\n }\n\n async kill(): Promise<boolean> {\n if (this.exitCode !== undefined) return false;\n return this._e2bHandle.kill();\n }\n\n async sendStdin(data: string): Promise<void> {\n if (this.exitCode !== undefined) {\n throw new Error(`Process ${this.pid} has already exited with code ${this.exitCode}`);\n }\n // Spawned with `stdinMode: 'ignore'`, so the command was started with\n // stdin detached and there is nothing to write to. Match the local and\n // Docker handles, which reject rather than posting an input RPC to a\n // process that has no stdin channel.\n if (this._stdinMode === 'ignore') {\n throw new Error(`Process ${this.pid} was not started with stdin support`);\n }\n await this._sandbox.commands.sendStdin(this._e2bHandle.pid, data);\n }\n\n async closeStdin(): Promise<void> {\n throw new UnsupportedStdinCloseError('E2B SDK does not expose a way to close stdin for a running command');\n }\n}\n\n// =============================================================================\n// E2B Process Manager\n// =============================================================================\n\n/**\n * E2B implementation of SandboxProcessManager.\n * Uses the E2B SDK's commands.run() with background: true.\n */\nexport interface E2BProcessManagerOptions {\n /** Default timeout in milliseconds for commands that don't specify one. */\n defaultTimeout?: number;\n}\n\nexport class E2BProcessManager extends SandboxProcessManager<E2BSandbox> {\n private readonly _defaultTimeout?: number;\n\n constructor(opts: E2BProcessManagerOptions = {}) {\n super();\n this._defaultTimeout = opts.defaultTimeout;\n }\n\n async spawn(command: string, options: SpawnProcessOptions = {}): Promise<ProcessHandle> {\n return this.sandbox.retryOnDead(async () => {\n const e2b = this.sandbox.e2b;\n\n // The base spawn wrapper already merged the sandbox env into options.env\n const mergedEnv = { ...options.env };\n const envs = Object.fromEntries(\n Object.entries(mergedEnv).filter((entry): entry is [string, string] => entry[1] !== undefined),\n );\n\n // Deferred reference — E2B requires callbacks at run() time, but data\n // arrives asynchronously after the promise resolves, so handle is always\n // assigned by the time the first callback fires.\n let handle: E2BProcessHandle;\n\n const e2bHandle = await e2b.commands.run(command, {\n background: true,\n // `stdinMode: 'ignore'` closes stdin at spawn so a command that reads it\n // (a bare `rg`/`grep`/`cat` with no path argument) sees EOF and exits\n // instead of blocking forever. Callers that drive stdin (`spawn` for an\n // LSP server) keep the default attached stdin.\n stdin: options.stdinMode !== 'ignore',\n cwd: options.cwd ?? this.sandbox.workingDirectory,\n envs,\n // Without this the E2B SDK falls back to its own 60s connection\n // deadline, which bounds the whole streaming command lifetime and kills\n // any command that runs longer than a minute.\n timeoutMs: options.timeout ?? this._defaultTimeout,\n onStdout: (data: string) => handle.emitStdout(data),\n onStderr: (data: string) => handle.emitStderr(data),\n });\n\n handle = new E2BProcessHandle(e2bHandle, e2b, Date.now(), options);\n this._tracked.set(handle.pid, handle);\n return handle;\n });\n }\n\n /**\n * List processes by querying E2B's commands API.\n * E2B manages all state server-side — no local tracking needed.\n */\n async list(): Promise<ProcessInfo[]> {\n const e2b = this.sandbox.e2b;\n const procs = await e2b.commands.list();\n return procs.map(proc => ({\n pid: String(proc.pid),\n command: [proc.cmd, ...proc.args].join(' '),\n running: true, // E2B only lists running processes\n }));\n }\n\n /**\n * Get a handle to a process by PID.\n * Checks base class tracking first, then falls back to commands.connect()\n * for processes spawned externally or before reconnection.\n */\n async get(pid: string): Promise<ProcessHandle | undefined> {\n const tracked = this._tracked.get(pid);\n if (tracked) return tracked;\n\n // Fall back to connect() for unknown PIDs (e.g., pre-existing processes).\n // E2B uses numeric PIDs; parse numeric strings for the SDK call.\n const numericPid = /^\\d+$/.test(pid) ? Number(pid) : undefined;\n if (numericPid === undefined) return undefined;\n\n const e2b = this.sandbox.e2b;\n let handle: E2BProcessHandle;\n try {\n const e2bHandle = await e2b.commands.connect(numericPid, {\n onStdout: (data: string) => handle.emitStdout(data),\n onStderr: (data: string) => handle.emitStderr(data),\n });\n handle = new E2BProcessHandle(e2bHandle, e2b, Date.now());\n this._tracked.set(handle.pid, handle);\n return handle;\n } catch {\n return undefined;\n }\n }\n}\n","/**\n * E2B Sandbox Provider\n *\n * A simplified E2B sandbox implementation that supports mounting\n * cloud filesystems (S3, GCS, R2) via FUSE.\n *\n * @see https://e2b.dev/docs\n */\n\nimport type { RequestContext } from '@mastra/core/di';\nimport type {\n SandboxInfo,\n WorkspaceFilesystem,\n MountResult,\n FilesystemMountConfig,\n ProviderStatus,\n MountManager,\n MastraSandboxOptions,\n SandboxFileInput,\n SandboxNetworking,\n SandboxCloneOptions,\n SandboxStartResult,\n} from '@mastra/core/workspace';\n\n/**\n * Inlined from `@mastra/core/workspace` to avoid requiring a newer core peer dep.\n */\ntype InstructionsOption = string | ((opts: { defaultInstructions: string; requestContext?: RequestContext }) => string);\nimport { MastraSandbox, SandboxNotReadyError, assertModesUnsupported } from '@mastra/core/workspace';\nimport { Sandbox, Template } from 'e2b';\nimport type {\n BuildOptions,\n SandboxConnectOpts,\n SandboxInfo as E2BSandboxListInfo,\n SandboxLifecycle,\n SandboxNetworkOpts,\n SandboxOpts,\n TemplateBuilder,\n TemplateClass,\n} from 'e2b';\nimport { createDefaultMountableTemplate, isDeferredNamedTemplateSpec, isNamedTemplateSpec } from '../utils/template';\nimport type { DeferredNamedTemplateSpec, NamedTemplateSpec, TemplateResources, TemplateSpec } from '../utils/template';\nimport { mountS3, mountGCS, mountAzure, LOG_PREFIX } from './mounts';\nimport type {\n E2BMountConfig,\n E2BS3MountConfig,\n E2BGCSMountConfig,\n E2BAzureBlobMountConfig,\n MountContext,\n} from './mounts';\nimport { E2BProcessManager } from './process-manager';\n\n/** Allowlist pattern for mount paths — absolute path with safe characters only. */\nconst SAFE_MOUNT_PATH = /^\\/[a-zA-Z0-9_.\\-/]+$/;\n\nfunction validateMountPath(mountPath: string): void {\n if (!SAFE_MOUNT_PATH.test(mountPath)) {\n throw new Error(\n `Invalid mount path: ${mountPath}. Must be an absolute path with alphanumeric, dash, dot, underscore, or slash characters only.`,\n );\n }\n}\n\n/** Allowlist for marker filenames from ls output — e.g. \"mount-abc123\" */\nconst SAFE_MARKER_NAME = /^mount-[a-z0-9]+$/;\n\n/**\n * Per-process dedupe of background template rebuild triggers, keyed by\n * template ref. Retained on successful trigger (the ref only ever needs one\n * build; once it exists the exists-check short-circuits before this path),\n * cleared on trigger failure so a later start can retry.\n */\nconst inFlightBackgroundBuilds = new Set<string>();\n\n// =============================================================================\n// E2B Sandbox Options\n// =============================================================================\n\n/**\n * E2B sandbox provider configuration.\n */\nexport interface E2BSandboxOptions extends Omit<MastraSandboxOptions, 'processes'> {\n /** Unique identifier for this sandbox instance */\n id?: string;\n /**\n * Persisted E2B provider sandbox ID to reattach to deterministically.\n *\n * When set, `start()` first queries this exact sandbox and connects to it\n * (resuming it if paused) instead of discovering by logical `id` metadata.\n * Only a typed \"sandbox gone\" error (not found / killed / not running)\n * falls through to the usual logical-id lookup and create ladder;\n * auth, quota, rate-limit, timeout, and network errors propagate without\n * creating a new sandbox.\n */\n sandboxId?: string;\n /**\n * Sandbox template specification.\n *\n * - `string` - Use an existing template by ID\n * - `TemplateBuilder` - Use a custom template (e.g., from `createMountableTemplate()`)\n * - `(base) => base.aptInstall([...])` - Customize the default mountable template\n *\n * If not provided and mounting is used, a default template with s3fs will be built.\n * For best performance, pre-build your template and use the template ID.\n *\n * @see createDefaultMountableTemplate\n */\n template?: TemplateSpec;\n /** Execution timeout in milliseconds\n *\n * @default 300_000 // 5 minutes\n */\n timeout?: number;\n /** Environment variables to set in the sandbox */\n env?: Record<string, string>;\n /** Custom metadata */\n metadata?: Record<string, unknown>;\n /** Network configuration to use when creating the E2B sandbox */\n network?: SandboxNetworkOpts;\n /**\n * Sandbox lifecycle behavior when the `timeout` is reached.\n *\n * Defaults to `{ onTimeout: 'pause' }`, which snapshots the sandbox so the\n * next `start()` reconnects and resumes it. Pass `{ onTimeout: 'kill' }` for\n * stateless workspaces whose data lives outside the sandbox (e.g. mounted\n * from S3) — idle sandboxes are then destroyed and recreated on next use\n * instead of retained as paused snapshots.\n *\n * Note: an explicit `stop()` always pauses, regardless of this setting.\n */\n lifecycle?: SandboxLifecycle;\n\n /** Domain for self-hosted E2B. Falls back to E2B_DOMAIN env var. */\n domain?: string;\n /** API URL for self-hosted E2B. Falls back to E2B_API_URL env var. */\n apiUrl?: string;\n /** API key for authentication. Falls back to E2B_API_KEY env var. */\n apiKey?: string;\n /** Access token for authentication. Falls back to E2B_ACCESS_TOKEN env var. */\n accessToken?: string;\n /**\n * Custom instructions that override the default instructions\n * returned by `getInstructions()`.\n *\n * - `string` — Fully replaces the default instructions.\n * Pass an empty string to suppress instructions entirely.\n * - `(opts) => string` — Receives the default instructions and\n * optional request context so you can extend or customise per-request.\n */\n instructions?: InstructionsOption;\n}\n\n// =============================================================================\n// E2B Sandbox Implementation\n// =============================================================================\n\n/**\n * Simplified E2B sandbox implementation.\n *\n * Features:\n * - Single sandbox instance lifecycle\n * - Supports mounting cloud filesystems (S3, GCS, R2) via FUSE\n * - Automatic sandbox timeout handling with retry\n *\n * @example Basic usage\n * ```typescript\n * import { Workspace } from '@mastra/core/workspace';\n * import { E2BSandbox } from '@mastra/e2b';\n *\n * const sandbox = new E2BSandbox({\n * timeout: 60000,\n * });\n *\n * const workspace = new Workspace({ sandbox });\n * const result = await workspace.executeCode('console.log(\"Hello!\")');\n * ```\n *\n * @example With S3 filesystem mounting\n * ```typescript\n * import { Workspace } from '@mastra/core/workspace';\n * import { E2BSandbox } from '@mastra/e2b';\n * import { S3Filesystem } from '@mastra/s3';\n *\n * const workspace = new Workspace({\n * mounts: {\n * '/bucket': new S3Filesystem({\n * bucket: 'my-bucket',\n * region: 'us-east-1',\n * }),\n * },\n * sandbox: new E2BSandbox({ timeout: 60000 }),\n * });\n *\n * ```\n */\nexport class E2BSandbox extends MastraSandbox<Sandbox> {\n readonly id: string;\n readonly name: string = 'E2BSandbox';\n readonly provider: string = 'e2b';\n status: ProviderStatus = 'pending';\n\n declare readonly mounts: MountManager; // Non-optional (initialized by BaseSandbox)\n declare readonly processes: E2BProcessManager;\n\n /**\n * Networking capability: public HTTPS URLs for sandbox ports.\n * E2B exposes every port via `getHost(port)` — no upfront declaration needed.\n *\n * When not attached in this process, the URL is resolved by looking up the\n * existing sandbox by identity (without resuming it) and deriving the host\n * (`{port}-{sandboxId}.{domain}`), so other processes can resolve\n * deployments without waking a paused sandbox.\n */\n readonly networking: SandboxNetworking = {\n getPortUrl: async (port: number): Promise<string | null> => {\n try {\n if (this._sandbox) {\n return `https://${this._sandbox.getHost(port)}`;\n }\n const info = await this.lookupExistingSandboxInfo();\n if (!info) return null;\n return `https://${port}-${info.sandboxId}.${this.sandboxDomain}`;\n } catch {\n return null;\n }\n },\n };\n\n protected _sandbox: Sandbox | null = null;\n private _createdAt: Date | null = null;\n private _isRetrying = false;\n private readonly timeout: number;\n protected readonly templateSpec?: TemplateSpec;\n private readonly metadata: Record<string, unknown>;\n private readonly network?: SandboxNetworkOpts;\n private readonly lifecycle: SandboxLifecycle;\n protected readonly connectionOpts: Record<string, string>;\n private readonly _preferredSandboxId?: string;\n private readonly _instructionsOverride?: InstructionsOption;\n private readonly _constructorOptions: E2BSandboxOptions;\n\n /**\n * Resolved template ID after building (if needed). The single cache for\n * template resolution: `resolveTemplate()` returns it when set, and the\n * create-time fallback ladder rewrites it to whichever template actually\n * produced a sandbox.\n *\n * `protected` so a subclass with its own default template (e.g. desktop\n * sandboxes) shares the same cache when it overrides `resolveTemplate()`.\n */\n protected _resolvedTemplateId?: string;\n /**\n * The named spec a deferred template spec resolved to — kept so the\n * 404-on-create fallback ladder can walk the same name/fallback rungs it\n * would for a plain named spec.\n */\n private _resolvedNamedSpec?: NamedTemplateSpec;\n\n constructor(options: E2BSandboxOptions = {}) {\n super({\n ...options,\n name: 'E2BSandbox',\n processes: new E2BProcessManager({\n defaultTimeout: options.timeout ?? 300_000,\n }),\n });\n\n this.id = options.id ?? this.generateId();\n this.timeout = options.timeout ?? 300_000; // 5 minutes;\n this.templateSpec = options.template;\n this.metadata = options.metadata ?? {};\n this.network = options.network;\n // Always sent explicitly: the E2B API defaults to 'kill' when lifecycle is omitted.\n this.lifecycle = options.lifecycle ?? { onTimeout: 'pause' };\n this.connectionOpts = {\n ...(options.domain && { domain: options.domain }),\n ...(options.apiUrl && { apiUrl: options.apiUrl }),\n ...(options.apiKey && { apiKey: options.apiKey }),\n ...(options.accessToken && { accessToken: options.accessToken }),\n };\n\n this._preferredSandboxId = options.sandboxId;\n this._instructionsOverride = options.instructions;\n this._constructorOptions = { ...options };\n }\n\n /**\n * Construct a sibling `E2BSandbox` that inherits this sandbox's\n * configuration (credentials, template, network, metadata, instructions)\n * with per-instance overrides.\n *\n * Performs no I/O — the sandbox clone provisions (or reconnects to an\n * existing E2B sandbox with the same logical `id`) on its own `start()`.\n * Use it when one configured sandbox acts as the template for a fleet of\n * independent sandboxes (e.g. one per project).\n *\n * `options.idleTimeoutMinutes` maps to the E2B sandbox `timeout` (ms);\n * `options.sandboxId` reattaches the clone to that exact E2B sandbox on\n * `start()`. The parent's own preferred provider sandbox ID is never\n * inherited — physical identity is per-instance.\n */\n clone(options: SandboxCloneOptions = {}): E2BSandbox {\n const { id: _id, sandboxId: _sandboxId, ...base } = this._constructorOptions;\n return new E2BSandbox({\n ...base,\n ...(options.id !== undefined && { id: options.id }),\n ...(options.sandboxId !== undefined && { sandboxId: options.sandboxId }),\n ...(options.env !== undefined && { env: options.env }),\n ...(options.idleTimeoutMinutes !== undefined && { timeout: options.idleTimeoutMinutes * 60_000 }),\n });\n }\n\n /**\n * Get the underlying E2B Sandbox instance for direct access to E2B APIs.\n *\n * Use this when you need to access E2B features not exposed through the\n * WorkspaceSandbox interface (e.g., files API, ports, etc.).\n *\n * @throws {SandboxNotReadyError} If the sandbox has not been started\n *\n * @example Direct file operations\n * ```typescript\n * const e2b = sandbox.e2b;\n * await e2b.files.write('/tmp/test.txt', 'Hello');\n * const content = await e2b.files.read('/tmp/test.txt');\n * const files = await e2b.files.list('/tmp');\n * ```\n *\n * @example Access ports\n * ```typescript\n * const e2b = sandbox.e2b;\n * const url = e2b.getHost(3000);\n * ```\n */\n get e2b(): Sandbox {\n if (!this._sandbox) {\n throw new SandboxNotReadyError(this.id);\n }\n return this._sandbox;\n }\n\n /**\n * The E2B provider sandbox ID resolved after connect or create.\n *\n * Persist this to reattach deterministically later via the `sandboxId`\n * option (or `clone({ sandboxId })`). Undefined until the sandbox has been\n * started (attached) in this process.\n */\n get sandboxId(): string | undefined {\n return this._sandbox?.sandboxId;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n /**\n * Acquisition primitives (base-orchestrated start): the base derives\n * `outcome: 'created'` only when a brand-new sandbox VM was created;\n * reconnecting (including resuming a paused sandbox) is `outcome: 'connected'`.\n *\n * `find` returns an already-connected E2B handle: `Sandbox.connect`\n * resumes paused sandboxes, and its failures are deliberately swallowed\n * (unusable handle → create fresh) — that forgiveness is this provider's\n * policy, so it lives here rather than in `connect`. The exception is the\n * `sandboxId` reattach inside {@link acquireExistingSandbox}, which is\n * fail-closed: only a \"sandbox gone\" error falls through to discovery.\n */\n protected override async find(): Promise<Sandbox | undefined> {\n // Already have a sandbox instance\n if (this._sandbox) {\n return this._sandbox;\n }\n return (await this.acquireExistingSandbox()) ?? undefined;\n }\n\n protected override async connect(existingSandbox: Sandbox): Promise<void> {\n if (existingSandbox === this._sandbox) {\n return;\n }\n this._sandbox = existingSandbox;\n this._createdAt = new Date();\n this.logger.debug(`${LOG_PREFIX} Reconnected to existing sandbox for: ${this.id}`);\n\n // Clean up stale mounts from previous config\n // (processPending is called by base class after start completes)\n const expectedPaths = Array.from(this.mounts.entries.keys());\n this.logger.debug(`${LOG_PREFIX} Running mount reconciliation...`);\n await this.reconcileMounts(expectedPaths);\n this.logger.debug(`${LOG_PREFIX} Mount reconciliation complete`);\n }\n\n protected override async create(): Promise<void> {\n // Template resolution happens here — never at construction or during a\n // reconnect — so a sandbox that only ever resumes never triggers a\n // template build. `resolveTemplate()` caches via `_resolvedTemplateId`.\n const resolvedTemplateId = await this.resolveTemplate();\n\n // Create a new sandbox with our logical ID in metadata.\n // lifecycle defaults to onTimeout: 'pause', which pauses the sandbox on timeout instead of\n // destroying it so the next start() can resume it. Callers can override it (e.g. 'kill').\n this.logger.debug(`${LOG_PREFIX} Creating new sandbox for: ${this.id} with template: ${resolvedTemplateId}`);\n\n const createOpts: SandboxOpts = {\n ...this.connectionOpts,\n lifecycle: this.lifecycle,\n metadata: {\n ...this.metadata,\n 'mastra-sandbox-id': this.id,\n },\n ...(this.network && { network: this.network }),\n timeoutMs: this.timeout,\n };\n // Every rung of the fallback ladder goes through `createSdkSandbox` so a\n // provider layered on the E2B SDK (e.g. `@e2b/desktop`) keeps its override\n // on the retries, not just on the first attempt.\n const createFromTemplate = (templateId: string) => this.createSdkSandbox(templateId, createOpts);\n // A 404 from create means the template id cannot produce a sandbox:\n // deleted between resolve and create, or the name was registered by a\n // FAILED build — E2B keeps a failed build's name visible to\n // `Template.exists`, so a broken name would otherwise be reused forever.\n // Only 404s trigger a fallback retry; auth, quota, and network errors\n // propagate (an ambiguous timeout must not create a duplicate VM).\n const isTemplateUnusable = (error: unknown) => String(error).includes('404');\n\n let sdkSandbox: Sandbox;\n try {\n sdkSandbox = await createFromTemplate(resolvedTemplateId);\n } catch (createError) {\n if (!isTemplateUnusable(createError)) throw createError;\n\n const namedSpec =\n this.templateSpec && isNamedTemplateSpec(this.templateSpec) ? this.templateSpec : this._resolvedNamedSpec;\n if (namedSpec) {\n // Bounded ladder: broken name → named fallback → default mountable\n // template. Every rung only advances on a template-unusable error, so\n // a broken build never wedges the session on a dead name.\n this.logger.warn(\n `${LOG_PREFIX} Creating from '${resolvedTemplateId}' failed, retrying on fallback: ${createError}`,\n );\n this._resolvedTemplateId = undefined;\n const spec = namedSpec;\n const fallbackId =\n resolvedTemplateId === spec.ref\n ? await this.resolveFallbackTemplate(spec.fallbackTemplate)\n : await this.buildOrReuseDefaultTemplate();\n try {\n sdkSandbox = await createFromTemplate(fallbackId);\n // Cache coherence: later creates on this instance (e.g. after the\n // VM died) must reuse the template that actually worked, not\n // re-walk the ladder from the broken name.\n this._resolvedTemplateId = fallbackId;\n } catch (fallbackError) {\n if (!isTemplateUnusable(fallbackError)) throw fallbackError;\n // Terminal recovery: the default name itself may be registered by\n // a FAILED build. Force-rebuild it once (mirrors the no-spec\n // path's 404 recovery) — past this, the error propagates.\n const rebuildDefaultAndCreate = async (): Promise<Sandbox> => {\n this.logger.warn(`${LOG_PREFIX} Default template broken too, rebuilding: ${fallbackError}`);\n const rebuiltId = await this.buildDefaultTemplate();\n const rebuilt = await createFromTemplate(rebuiltId);\n this._resolvedTemplateId = rebuiltId;\n return rebuilt;\n };\n const defaultId = await this.buildOrReuseDefaultTemplate();\n if (defaultId === fallbackId) {\n // The failed fallback WAS the default (specs without a named\n // fallback land on it directly) — skip straight to the rebuild.\n sdkSandbox = await rebuildDefaultAndCreate();\n } else {\n this.logger.warn(`${LOG_PREFIX} Fallback '${fallbackId}' failed too, using default: ${fallbackError}`);\n try {\n sdkSandbox = await createFromTemplate(defaultId);\n this._resolvedTemplateId = defaultId;\n } catch (defaultError) {\n if (!isTemplateUnusable(defaultError)) throw defaultError;\n sdkSandbox = await rebuildDefaultAndCreate();\n }\n }\n }\n this.logger.debug(`${LOG_PREFIX} Created sandbox ${sdkSandbox.sandboxId} from fallback for: ${this.id}`);\n } else if (!this.templateSpec) {\n this.logger.debug(`${LOG_PREFIX} Template not found, rebuilding: ${resolvedTemplateId}`);\n this._resolvedTemplateId = undefined; // Clear cached ID to force rebuild\n const rebuiltTemplateId = await this.buildDefaultTemplate();\n\n this.logger.debug(`${LOG_PREFIX} Retrying sandbox creation with rebuilt template: ${rebuiltTemplateId}`);\n sdkSandbox = await createFromTemplate(rebuiltTemplateId);\n } else {\n throw createError;\n }\n }\n this._sandbox = sdkSandbox;\n\n this.logger.debug(`${LOG_PREFIX} Created sandbox ${sdkSandbox.sandboxId} for logical ID: ${this.id}`);\n this._createdAt = new Date();\n // Note: processPending is called by base class after start completes\n }\n\n /**\n * Stop the E2B sandbox by pausing it (snapshot-stop).\n *\n * Pausing freezes the whole VM — filesystem, memory, and running processes —\n * and stops billing immediately. The next `start()` reconnects and resumes it,\n * with background processes still running. Filesystem mounts are unmounted\n * first (FUSE mounts don't survive pause) and reconciled again on start.\n *\n * Status management is handled by the base class.\n */\n async stop(): Promise<void> {\n // Unmount all filesystems before pausing\n // Collect keys first since unmount() mutates the map\n for (const mountPath of [...this.mounts.entries.keys()]) {\n try {\n await this.unmount(mountPath);\n } catch {\n // Best-effort unmount; sandbox may already be dead\n }\n }\n\n // Pause failures propagate — a sandbox that failed to pause is still\n // running (and billing), so callers must not assume it stopped.\n if (this._sandbox) {\n await this._sandbox.pause();\n this.logger.debug(`${LOG_PREFIX} Paused sandbox ${this._sandbox.sandboxId} for: ${this.id}`);\n } else {\n // Not attached in this process — pause by identity without resuming.\n const info = await this.lookupExistingSandboxInfo();\n if (info?.state === 'running') {\n await Sandbox.pause(info.sandboxId, this.connectionOpts);\n this.logger.debug(`${LOG_PREFIX} Paused detached sandbox ${info.sandboxId} for: ${this.id}`);\n }\n }\n\n this._sandbox = null;\n }\n\n /**\n * Destroy the E2B sandbox and clean up all resources.\n * Unmounts filesystems, kills the sandbox, and clears mount state.\n * Status management is handled by the base class.\n */\n async destroy(): Promise<void> {\n if (this._sandbox) {\n // Kill all background processes\n try {\n const procs = await this.processes.list();\n await Promise.all(procs.map(p => this.processes.kill(p.pid)));\n } catch {\n // Best-effort: sandbox may already be dead\n }\n\n // Unmount all filesystems\n // Collect keys first since unmount() mutates the map\n for (const mountPath of [...this.mounts.entries.keys()]) {\n try {\n await this.unmount(mountPath);\n } catch {\n // Ignore errors during cleanup\n }\n }\n\n // Kill failures propagate — a sandbox that failed to delete is still\n // alive, so callers must not assume cleanup completed.\n await this._sandbox.kill();\n\n this._sandbox = null;\n } else {\n // Not attached in this process — kill by identity without resuming.\n const info = await this.lookupExistingSandboxInfo();\n if (info) {\n await Sandbox.kill(info.sandboxId, this.connectionOpts);\n this.logger.debug(`${LOG_PREFIX} Killed detached sandbox ${info.sandboxId} for: ${this.id}`);\n }\n }\n\n this.mounts.clear();\n }\n\n async getInfo(): Promise<SandboxInfo> {\n return {\n id: this.id,\n name: this.name,\n provider: this.provider,\n status: this.status,\n createdAt: this._createdAt ?? new Date(),\n mounts: Array.from(this.mounts.entries).map(([path, entry]) => ({\n path,\n filesystem: entry.filesystem?.provider ?? entry.config?.type ?? 'unknown',\n })),\n metadata: {\n ...this.metadata,\n ...(this._sandbox && { sandboxId: this._sandbox.sandboxId }),\n },\n };\n }\n\n // ---------------------------------------------------------------------------\n // File Upload\n // ---------------------------------------------------------------------------\n\n /**\n * Bulk-write files into the sandbox filesystem via the SDK's native upload.\n *\n * Per-file permission modes are not supported; an explicit `mode` is\n * rejected rather than silently discarded.\n */\n async writeFiles(files: SandboxFileInput[]): Promise<void> {\n assertModesUnsupported(files, 'E2B');\n await this.ensureRunning();\n await this.e2b.files.write(\n files.map(f => ({\n path: f.path,\n data: typeof f.content === 'string' ? f.content : new Blob([new Uint8Array(f.content)]),\n })),\n );\n }\n\n /**\n * Get instructions describing this E2B sandbox.\n * Used by agents to understand the execution environment.\n */\n getInstructions(opts?: { requestContext?: RequestContext }): string {\n if (this._instructionsOverride === undefined) return this._getDefaultInstructions();\n if (typeof this._instructionsOverride === 'string') return this._instructionsOverride;\n const defaultInstructions = this._getDefaultInstructions();\n return this._instructionsOverride({ defaultInstructions, requestContext: opts?.requestContext });\n }\n\n private _getDefaultInstructions(): string {\n const mountCount = this.mounts.entries.size;\n const mountInfo = mountCount > 0 ? ` ${mountCount} filesystem(s) mounted via FUSE.` : '';\n return `Cloud sandbox.${mountInfo}`;\n }\n\n // ---------------------------------------------------------------------------\n // Mounting\n // ---------------------------------------------------------------------------\n\n /**\n * Mount a filesystem at a path in the sandbox.\n * Uses FUSE tools (s3fs, gcsfuse) to mount cloud storage.\n */\n async mount(filesystem: WorkspaceFilesystem, mountPath: string): Promise<MountResult> {\n validateMountPath(mountPath);\n\n if (!this._sandbox) {\n throw new SandboxNotReadyError(this.id);\n }\n\n this.logger.debug(`${LOG_PREFIX} Mounting \"${mountPath}\"...`);\n\n // Get mount config - MountManager validates this exists before calling mount()\n const config = filesystem.getMountConfig?.() as E2BMountConfig | undefined;\n if (!config) {\n const error = `Filesystem \"${filesystem.id}\" does not provide a mount config`;\n this.logger.error(`${LOG_PREFIX} ${error}`);\n this.mounts.set(mountPath, { filesystem, state: 'error', error });\n return { success: false, mountPath, error };\n }\n\n // Check if already mounted with matching config (e.g., when reconnecting to existing sandbox)\n const existingMount = await this.checkExistingMount(mountPath, config);\n if (existingMount === 'matching') {\n this.logger.debug(\n `${LOG_PREFIX} Detected existing mount for ${filesystem.provider} (\"${filesystem.id}\") at \"${mountPath}\" with correct config, skipping`,\n );\n this.mounts.set(mountPath, { state: 'mounted', config });\n return { success: true, mountPath };\n } else if (existingMount === 'mismatched') {\n // Different config - unmount and re-mount\n this.logger.debug(`${LOG_PREFIX} Config mismatch, unmounting to re-mount with new config...`);\n await this.unmount(mountPath);\n }\n this.logger.debug(`${LOG_PREFIX} Config type: ${config.type}`);\n\n // Mark as mounting (handles direct mount() calls; MountManager also sets this for processPending)\n this.mounts.set(mountPath, { filesystem, state: 'mounting', config });\n\n // Check if directory exists and is non-empty (would shadow existing files)\n try {\n const checkResult = await this._sandbox.commands.run(\n `[ -d \"${mountPath}\" ] && [ \"$(ls -A \"${mountPath}\" 2>/dev/null)\" ] && echo \"non-empty\" || echo \"ok\"`,\n );\n if (checkResult.stdout.trim() === 'non-empty') {\n const error = `Cannot mount at ${mountPath}: directory exists and is not empty. Mounting would hide existing files. Use a different path or empty the directory first.`;\n this.logger.error(`${LOG_PREFIX} ${error}`);\n this.mounts.set(mountPath, { filesystem, state: 'error', config, error });\n return { success: false, mountPath, error };\n }\n } catch {\n // Check failed, proceed anyway\n }\n\n // Create mount directory with sudo (for paths outside home dir like /data)\n // Then chown to current user so mount works without issues\n try {\n this.logger.debug(`${LOG_PREFIX} Creating mount directory for ${mountPath}...`);\n const mkdirCommand = `sudo mkdir -p \"${mountPath}\" && sudo chown $(id -u):$(id -g) \"${mountPath}\"`;\n\n this.logger.debug(`${LOG_PREFIX} Running command: ${mkdirCommand}`);\n const mkdirResult = await this._sandbox.commands.run(mkdirCommand);\n\n this.logger.debug(`${LOG_PREFIX} Created mount directory for mount path \"${mountPath}\":`, mkdirResult);\n } catch (mkdirError) {\n this.logger.debug(`${LOG_PREFIX} mkdir error for \"${mountPath}\":`, mkdirError);\n this.mounts.set(mountPath, { filesystem, state: 'error', config, error: String(mkdirError) });\n return { success: false, mountPath, error: String(mkdirError) };\n }\n\n // Create mount context for mount operations\n const mountCtx: MountContext = {\n sandbox: this._sandbox,\n logger: this.logger,\n };\n\n try {\n switch (config.type) {\n case 's3':\n this.logger.debug(`${LOG_PREFIX} Mounting S3 bucket at ${mountPath}...`);\n await mountS3(mountPath, config as E2BS3MountConfig, mountCtx);\n this.logger.debug(`${LOG_PREFIX} Mounted S3 bucket at ${mountPath}`);\n break;\n case 'gcs':\n this.logger.debug(`${LOG_PREFIX} Mounting GCS bucket at ${mountPath}...`);\n await mountGCS(mountPath, config as E2BGCSMountConfig, mountCtx);\n this.logger.debug(`${LOG_PREFIX} Mounted GCS bucket at ${mountPath}`);\n break;\n case 'azure-blob':\n this.logger.debug(`${LOG_PREFIX} Mounting Azure Blob container at ${mountPath}...`);\n await mountAzure(mountPath, config as E2BAzureBlobMountConfig, mountCtx);\n this.logger.debug(`${LOG_PREFIX} Mounted Azure Blob container at ${mountPath}`);\n break;\n default:\n this.mounts.set(mountPath, {\n filesystem,\n state: 'unsupported',\n config,\n error: `Unsupported mount type: ${(config as FilesystemMountConfig).type}`,\n });\n return {\n success: false,\n mountPath,\n error: `Unsupported mount type: ${(config as FilesystemMountConfig).type}`,\n };\n }\n } catch (error) {\n this.logger.error(\n `${LOG_PREFIX} Error mounting \"${filesystem.provider}\" (${filesystem.id}) at \"${mountPath}\":`,\n error,\n );\n this.mounts.set(mountPath, { filesystem, state: 'error', config, error: String(error) });\n\n // Clean up the directory we created since mount failed\n try {\n await this._sandbox!.commands.run(`sudo rmdir \"${mountPath}\" 2>/dev/null || true`);\n this.logger.debug(`${LOG_PREFIX} Cleaned up directory after failed mount: ${mountPath}`);\n } catch {\n // Ignore cleanup errors\n }\n\n return { success: false, mountPath, error: String(error) };\n }\n\n // Mark as mounted\n this.mounts.set(mountPath, { state: 'mounted', config });\n\n // Write marker file so we can detect config changes on reconnect\n await this.writeMarkerFile(mountPath);\n\n this.logger.debug(`${LOG_PREFIX} Mounted ${mountPath}`);\n return { success: true, mountPath };\n }\n\n /**\n * Unmount a filesystem from a path in the sandbox.\n */\n async unmount(mountPath: string): Promise<void> {\n validateMountPath(mountPath);\n\n if (!this._sandbox) {\n throw new SandboxNotReadyError(this.id);\n }\n\n this.logger.debug(`${LOG_PREFIX} Unmounting ${mountPath}...`);\n\n try {\n // Use fusermount for FUSE mounts, fall back to umount\n const result = await this._sandbox.commands.run(\n `sudo fusermount -u \"${mountPath}\" 2>/dev/null || sudo umount \"${mountPath}\"`,\n );\n if (result.exitCode !== 0) {\n this.logger.debug(`${LOG_PREFIX} Unmount warning: ${result.stderr || result.stdout}`);\n }\n } catch (error) {\n this.logger.debug(`${LOG_PREFIX} Unmount error:`, error);\n // Try lazy unmount as last resort\n await this._sandbox.commands.run(`sudo umount -l \"${mountPath}\" 2>/dev/null || true`);\n }\n\n this.mounts.delete(mountPath);\n\n // Clean up marker file\n const filename = this.mounts.markerFilename(mountPath);\n const markerPath = `/tmp/.mastra-mounts/${filename}`;\n await this._sandbox.commands.run(`rm -f \"${markerPath}\" 2>/dev/null || true`);\n\n // Remove empty mount directory (only if empty, rmdir fails on non-empty)\n // Use sudo since mount directories outside home (like /data) were created with sudo\n const rmdirResult = await this._sandbox.commands.run(`sudo rmdir \"${mountPath}\" 2>&1`);\n if (rmdirResult.exitCode === 0) {\n this.logger.debug(`${LOG_PREFIX} Unmounted and removed ${mountPath}`);\n } else {\n this.logger.debug(\n `${LOG_PREFIX} Unmounted ${mountPath} (directory not removed: ${rmdirResult.stderr?.trim() || 'not empty'})`,\n );\n }\n }\n\n /**\n * Unmount all stale mounts that are not in the expected mounts list.\n * Also cleans up orphaned directories and marker files from failed mount attempts.\n * Call this after reconnecting to an existing sandbox to clean up old mounts.\n */\n async reconcileMounts(expectedMountPaths: string[]): Promise<void> {\n if (!this._sandbox) {\n throw new SandboxNotReadyError(this.id);\n }\n\n this.logger.debug(`${LOG_PREFIX} Reconciling mounts. Expected paths:`, expectedMountPaths);\n\n // Get current FUSE mounts in the sandbox\n const mountsResult = await this._sandbox.commands.run(\n `grep -E 'fuse\\\\.(s3fs|gcsfuse|blobfuse2)' /proc/mounts | awk '{print $2}'`,\n );\n const currentMounts = mountsResult.stdout\n .trim()\n .split('\\n')\n .filter(p => p.length > 0);\n\n this.logger.debug(`${LOG_PREFIX} Current FUSE mounts in sandbox:`, currentMounts);\n\n // Read our marker files to know which mounts WE created\n const markersResult = await this._sandbox.commands.run(`ls /tmp/.mastra-mounts/ 2>/dev/null || echo \"\"`);\n const markerFiles = markersResult.stdout\n .trim()\n .split('\\n')\n .filter(f => f.length > 0 && SAFE_MARKER_NAME.test(f));\n\n // Build a map of mount paths → marker filenames for mounts WE created\n const managedMountPaths = new Map<string, string>();\n for (const markerFile of markerFiles) {\n const markerResult = await this._sandbox.commands.run(\n `cat \"/tmp/.mastra-mounts/${markerFile}\" 2>/dev/null || echo \"\"`,\n );\n const parsed = this.mounts.parseMarkerContent(markerResult.stdout.trim());\n if (parsed && SAFE_MOUNT_PATH.test(parsed.path)) {\n managedMountPaths.set(parsed.path, markerFile);\n }\n }\n\n // Find mounts that exist but shouldn't — only unmount if WE created them (have a marker)\n const staleMounts = currentMounts.filter(path => !expectedMountPaths.includes(path));\n\n for (const stalePath of staleMounts) {\n if (managedMountPaths.has(stalePath)) {\n this.logger.debug(`${LOG_PREFIX} Found stale managed FUSE mount at ${stalePath}, unmounting...`);\n await this.unmount(stalePath);\n } else {\n this.logger.debug(`${LOG_PREFIX} Found external FUSE mount at ${stalePath}, leaving untouched`);\n }\n }\n\n // Clean up orphaned marker files and empty directories from failed mounts\n try {\n const expectedMarkerFiles = new Set(expectedMountPaths.map(p => this.mounts.markerFilename(p)));\n\n // Build a reverse map: markerFile → mountPath\n const markerToPath = new Map<string, string>();\n for (const [path, file] of managedMountPaths) {\n markerToPath.set(file, path);\n }\n\n for (const markerFile of markerFiles) {\n // If this marker file doesn't correspond to an expected mount path, clean it up\n if (!expectedMarkerFiles.has(markerFile)) {\n const mountPath = markerToPath.get(markerFile);\n\n if (mountPath) {\n // Only clean up directory if not currently FUSE mounted\n if (!currentMounts.includes(mountPath)) {\n this.logger.debug(`${LOG_PREFIX} Cleaning up orphaned marker and directory for ${mountPath}`);\n\n // Remove marker file\n await this._sandbox.commands.run(`rm -f \"/tmp/.mastra-mounts/${markerFile}\" 2>/dev/null || true`);\n\n // Try to remove the directory (will fail if not empty or doesn't exist, which is fine)\n await this._sandbox.commands.run(`sudo rmdir \"${mountPath}\" 2>/dev/null || true`);\n }\n } else {\n // Malformed marker file - just delete it\n this.logger.debug(`${LOG_PREFIX} Removing malformed marker file: ${markerFile}`);\n await this._sandbox.commands.run(`rm -f \"/tmp/.mastra-mounts/${markerFile}\" 2>/dev/null || true`);\n }\n }\n }\n } catch {\n // Ignore errors during orphan cleanup\n this.logger.debug(`${LOG_PREFIX} Error during orphan cleanup (non-fatal)`);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Deprecated\n // ---------------------------------------------------------------------------\n\n /** @deprecated Use `e2b` instead. */\n get instance(): Sandbox {\n return this.e2b;\n }\n\n /** @deprecated Use `status === 'running'` instead. */\n async isReady(): Promise<boolean> {\n return this.status === 'running' && this._sandbox !== null;\n }\n\n // ---------------------------------------------------------------------------\n // Internal Helpers\n // ---------------------------------------------------------------------------\n\n private generateId(): string {\n return `e2b-sandbox-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n }\n\n /** Domain used to derive public sandbox hosts (self-hosted E2B or e2b.app). */\n private get sandboxDomain(): string {\n return this.connectionOpts.domain ?? process.env.E2B_DOMAIN ?? 'e2b.app';\n }\n\n /**\n * Look up an existing sandbox with matching mastra-sandbox-id metadata\n * WITHOUT connecting or resuming it. Returns its list info or null.\n */\n private async lookupExistingSandboxInfo(): Promise<E2BSandboxListInfo | null> {\n try {\n // Query E2B for existing sandbox with our logical ID in metadata\n const paginator = Sandbox.list({\n ...this.connectionOpts,\n query: {\n metadata: { 'mastra-sandbox-id': this.id },\n state: ['running', 'paused'],\n },\n });\n\n const sandboxes = await paginator.nextItems();\n\n this.logger.debug(`${LOG_PREFIX} sandboxes:`, sandboxes);\n\n // Sandbox.list only returns running/paused sandboxes, so no need to filter\n if (sandboxes.length > 0) {\n const existingSandbox = sandboxes[0]!;\n this.logger.debug(\n `${LOG_PREFIX} Found existing sandbox for ${this.id}: ${existingSandbox.sandboxId} (state: ${existingSandbox.state})`,\n );\n return existingSandbox;\n }\n } catch (e) {\n this.logger.debug(`${LOG_PREFIX} Error querying for existing sandbox:`, e);\n // Continue to create new sandbox\n }\n\n return null;\n }\n\n /**\n * Acquire an existing sandbox: try the preferred provider sandbox ID first\n * (deterministic reattach), then fall back to logical-id metadata discovery.\n */\n private async acquireExistingSandbox(): Promise<Sandbox | null> {\n if (this._preferredSandboxId) {\n const preferred = await this.connectToPreferredSandbox(this._preferredSandboxId);\n if (preferred) return preferred;\n }\n return this.findExistingSandbox();\n }\n\n /**\n * Deterministically reattach to a sandbox by its E2B provider ID.\n *\n * Fail-closed: only a typed \"sandbox gone\" error (not found / killed /\n * not running) returns null so the caller can fall through to logical-id\n * discovery or creation. Any other error (auth, quota, rate limit,\n * timeout, network) propagates so a duplicate sandbox is never created.\n *\n * Ownership is validated before connecting: a sandbox tagged with a\n * different `mastra-sandbox-id` is refused (without resuming it).\n * Sandboxes without the tag (created outside Mastra) are attachable.\n */\n private async connectToPreferredSandbox(preferredSandboxId: string): Promise<Sandbox | null> {\n let info: E2BSandboxListInfo;\n try {\n info = await Sandbox.getInfo(preferredSandboxId, this.connectionOpts);\n } catch (e) {\n if (this.isSandboxDeadError(e)) {\n this.logger.debug(\n `${LOG_PREFIX} Preferred sandbox ${preferredSandboxId} is gone, falling back to logical-id discovery:`,\n e,\n );\n return null;\n }\n throw e;\n }\n\n const owner = info.metadata?.['mastra-sandbox-id'];\n if (owner !== undefined && owner !== this.id) {\n throw new Error(\n `${LOG_PREFIX} Provider sandbox ${preferredSandboxId} belongs to logical sandbox id \"${owner}\", refusing to attach it to \"${this.id}\"`,\n );\n }\n\n try {\n return await Sandbox.connect(preferredSandboxId, { ...this.connectionOpts, timeoutMs: this.timeout });\n } catch (e) {\n // The sandbox can terminate between getInfo and connect.\n if (this.isSandboxDeadError(e)) {\n this.logger.debug(\n `${LOG_PREFIX} Preferred sandbox ${preferredSandboxId} vanished before connect, falling back:`,\n e,\n );\n return null;\n }\n throw e;\n }\n }\n\n /**\n * Find an existing sandbox with matching mastra-sandbox-id metadata.\n * Returns the connected sandbox if found, null otherwise.\n * Connecting to a paused sandbox resumes it.\n */\n private async findExistingSandbox(): Promise<Sandbox | null> {\n const info = await this.lookupExistingSandboxInfo();\n if (!info) return null;\n try {\n return await this.connectSdkSandbox(info.sandboxId, { ...this.connectionOpts, timeoutMs: this.timeout });\n } catch (e) {\n this.logger.debug(`${LOG_PREFIX} Error connecting to existing sandbox:`, e);\n return null;\n }\n }\n\n // ---------------------------------------------------------------------------\n // SDK Factory Hooks (subclass override points)\n // ---------------------------------------------------------------------------\n\n /**\n * Create a new SDK sandbox from a resolved template ID.\n *\n * Override point for providers layered on the E2B SDK whose `Sandbox`\n * class extends `e2b`'s (e.g. `@e2b/desktop`): override to call their\n * `Sandbox.create`. Connection options are already spread into `opts`.\n */\n protected async createSdkSandbox(templateId: string, opts: SandboxOpts): Promise<Sandbox> {\n return Sandbox.create(templateId, opts);\n }\n\n /**\n * Connect to (and resume) an existing SDK sandbox by its E2B sandbox ID.\n * Override point — see {@link createSdkSandbox}.\n */\n protected async connectSdkSandbox(sandboxId: string, opts: SandboxConnectOpts): Promise<Sandbox> {\n return Sandbox.connect(sandboxId, opts);\n }\n\n /**\n * Resolve the template specification to a template ID.\n *\n * - String: Use as-is (template ID)\n * - TemplateBuilder: Build and return the template ID\n * - Function: Apply to base mountable template, then build\n * - undefined: Use default mountable template (cached)\n *\n * Override point: subclasses with a different default template (e.g.\n * desktop sandboxes) override this and {@link buildDefaultTemplate}.\n */\n protected async resolveTemplate(): Promise<string> {\n // If already resolved, return cached ID\n if (this._resolvedTemplateId) {\n return this._resolvedTemplateId;\n }\n\n // No template specified - use default mountable template with caching\n if (!this.templateSpec) {\n return await this.buildOrReuseDefaultTemplate();\n }\n\n // String template ID - use directly\n if (typeof this.templateSpec === 'string') {\n this._resolvedTemplateId = this.templateSpec;\n return this.templateSpec;\n }\n\n // Named spec (e.g. createRepoTemplate) - lazy build-if-missing under a\n // deterministic name, with a fallback so a failed build degrades to a\n // cold start instead of a wedged session. A deferred spec (sha-less\n // createRepoTemplate) computes its name right before the exists check —\n // pinning to the repo's current default-branch head; a rejection there\n // degrades to the default mountable template like any other resolution\n // failure.\n let spec: Exclude<TemplateSpec, DeferredNamedTemplateSpec>;\n if (isDeferredNamedTemplateSpec(this.templateSpec)) {\n try {\n spec = await this.templateSpec.resolveSpec();\n this._resolvedNamedSpec = spec;\n } catch (error) {\n this.logger.warn(`${LOG_PREFIX} Deferred template spec resolution failed, falling back: ${error}`);\n return await this.resolveFallbackTemplate(undefined);\n }\n } else {\n spec = this.templateSpec;\n }\n if (isNamedTemplateSpec(spec)) {\n const { ref, template: namedTemplate, fallbackTemplate, staleRef, buildTags, buildResources } = spec;\n const buildOpts = {\n ...this.connectionOpts,\n ...(buildTags?.length ? { tags: buildTags } : {}),\n ...buildResources,\n };\n try {\n if (await Template.exists(ref, this.connectionOpts)) {\n this.logger.debug(`${LOG_PREFIX} Using cached template: ${ref}`);\n this._resolvedTemplateId = ref;\n return ref;\n }\n // Stale-build-first: when the exact ref is missing but a previous\n // build exists, boot from it immediately and rebuild the fresh ref\n // in the background — only a template's very first build ever\n // blocks a sandbox start. Runtime setup fast-forwards the slightly\n // stale checkout, so freshness never depends on the template.\n if (staleRef && staleRef !== ref && (await Template.exists(staleRef, this.connectionOpts))) {\n this.logger.debug(`${LOG_PREFIX} Using stale build ${staleRef}; rebuilding ${ref} in background`);\n this.triggerBackgroundBuild(namedTemplate as TemplateClass, ref, buildOpts);\n this._resolvedTemplateId = staleRef;\n return staleRef;\n }\n this.logger.debug(`${LOG_PREFIX} Building template: ${ref}...`);\n const buildResult = await Template.build(namedTemplate as TemplateClass, ref, buildOpts);\n this.logger.debug(`${LOG_PREFIX} Template built: ${buildResult.templateId}`);\n // Resolve to the ref, NOT the raw build id: creating a sandbox from\n // a bare template id looks up its `default` tag, which a\n // tag-qualified build (e.g. `name:sha-<sha>`) never assigns — the\n // create would 404 and needlessly ride the fallback ladder.\n this._resolvedTemplateId = ref;\n return ref;\n } catch (error) {\n this.logger.warn(`${LOG_PREFIX} Template '${ref}' resolution failed, falling back: ${error}`);\n return await this.resolveFallbackTemplate(fallbackTemplate);\n }\n }\n // TemplateBuilder or function - need to build\n let template: TemplateBuilder;\n let templateName: string;\n\n if (typeof spec === 'function') {\n // Apply customization function to base mountable template\n const { template: baseTemplate } = createDefaultMountableTemplate();\n template = spec(baseTemplate);\n // Custom templates get unique names since they're modified\n templateName = `mastra-custom-${this.id.replace(/[^a-zA-Z0-9-]/g, '-')}`;\n } else {\n // Use provided TemplateBuilder directly\n template = spec;\n templateName = `mastra-${this.id.replace(/[^a-zA-Z0-9-]/g, '-')}`;\n }\n\n // Build the template\n this.logger.debug(`${LOG_PREFIX} Building custom template: ${templateName}...`);\n const buildResult = await Template.build(template as TemplateClass, templateName, this.connectionOpts);\n this._resolvedTemplateId = buildResult.templateId;\n this.logger.debug(`${LOG_PREFIX} Template built: ${buildResult.templateId}`);\n\n return buildResult.templateId;\n }\n\n /**\n * Resolve the default mountable template: reuse when it exists, build once\n * when it does not.\n */\n /**\n * Resolve a named spec's fallback template. A named fallback gets its own\n * exists-then-build resolution; anything failing past that (including\n * specs without a fallback, e.g. repo templates) lands on the default\n * mountable template so a broken build never wedges a session.\n */\n /**\n * Trigger a non-blocking template rebuild via `Template.buildInBackground`\n * (the build runs on E2B's side, so it outlives this process). Deduped\n * per-process by ref so concurrent session starts on the same moved head\n * don't stack duplicate builds; a failed TRIGGER clears the guard so a\n * later start retries. A build that fails server-side simply never\n * registers the ref — the next start falls back to the stale build again\n * and re-triggers.\n */\n private triggerBackgroundBuild(template: TemplateClass, ref: string, buildOpts: Omit<BuildOptions, 'alias'>): void {\n if (inFlightBackgroundBuilds.has(ref)) return;\n inFlightBackgroundBuilds.add(ref);\n void Template.buildInBackground(template, ref, buildOpts)\n .then(result => {\n this.logger.debug(`${LOG_PREFIX} Background template build triggered: ${ref} (${result.buildId})`);\n })\n .catch(error => {\n inFlightBackgroundBuilds.delete(ref);\n this.logger.warn(`${LOG_PREFIX} Background template build trigger failed for '${ref}': ${error}`);\n });\n }\n\n private async resolveFallbackTemplate(fallbackTemplate: NamedTemplateSpec['fallbackTemplate']): Promise<string> {\n if (typeof fallbackTemplate === 'string') {\n this._resolvedTemplateId = fallbackTemplate;\n return fallbackTemplate;\n }\n if (fallbackTemplate && isNamedTemplateSpec(fallbackTemplate)) {\n try {\n if (await Template.exists(fallbackTemplate.ref, this.connectionOpts)) {\n this._resolvedTemplateId = fallbackTemplate.ref;\n return fallbackTemplate.ref;\n }\n const buildResult = await Template.build(fallbackTemplate.template as TemplateClass, fallbackTemplate.ref, {\n ...this.connectionOpts,\n ...fallbackTemplate.buildResources,\n });\n this._resolvedTemplateId = buildResult.templateId;\n return buildResult.templateId;\n } catch (error) {\n this.logger.warn(`${LOG_PREFIX} Fallback template '${fallbackTemplate.ref}' failed too: ${error}`);\n return await this.buildOrReuseDefaultTemplate();\n }\n }\n if (fallbackTemplate) {\n try {\n const buildResult = await Template.build(\n fallbackTemplate as unknown as TemplateClass,\n `mastra-fallback-${this.id.replace(/[^a-zA-Z0-9-]/g, '-')}`,\n this.connectionOpts,\n );\n this._resolvedTemplateId = buildResult.templateId;\n return buildResult.templateId;\n } catch (error) {\n this.logger.warn(`${LOG_PREFIX} Fallback template build failed, using default: ${error}`);\n return await this.buildOrReuseDefaultTemplate();\n }\n }\n return await this.buildOrReuseDefaultTemplate();\n }\n\n /**\n * Resources the configured template asked for. The default mountable\n * template honors them too, so a repo template that falls back never\n * silently downgrades the machine — a 2 GB session's setup would OOM in\n * the 1 GB default. Per-size default templates cost one extra build each.\n */\n private requestedBuildResources(): TemplateResources | undefined {\n const spec =\n this.templateSpec && isNamedTemplateSpec(this.templateSpec) ? this.templateSpec : this._resolvedNamedSpec;\n return spec?.buildResources;\n }\n\n private async buildOrReuseDefaultTemplate(): Promise<string> {\n const { template, id, resources } = createDefaultMountableTemplate(this.requestedBuildResources());\n\n const exists = await Template.exists(id, this.connectionOpts);\n if (exists) {\n this.logger.debug(`${LOG_PREFIX} Using cached mountable template: ${id}`);\n this._resolvedTemplateId = id;\n return id;\n }\n\n this.logger.debug(`${LOG_PREFIX} Building default mountable template: ${id}...`);\n const buildResult = await Template.build(template as TemplateClass, id, { ...this.connectionOpts, ...resources });\n this._resolvedTemplateId = buildResult.templateId;\n this.logger.debug(`${LOG_PREFIX} Template built and cached: ${buildResult.templateId}`);\n return buildResult.templateId;\n }\n\n /**\n * Build the default mountable template (bypasses exists check).\n *\n * Override point: called from the template-not-found retry path in\n * `start()` when no explicit template was configured.\n */\n protected async buildDefaultTemplate(): Promise<string> {\n const { template, id, resources } = createDefaultMountableTemplate(this.requestedBuildResources());\n this.logger.debug(`${LOG_PREFIX} Building default mountable template: ${id}...`);\n const buildResult = await Template.build(template as TemplateClass, id, { ...this.connectionOpts, ...resources });\n this._resolvedTemplateId = buildResult.templateId;\n this.logger.debug(`${LOG_PREFIX} Template built: ${buildResult.templateId}`);\n return buildResult.templateId;\n }\n\n /**\n * Write marker file for detecting config changes on reconnect.\n * Stores both the mount path and config hash in the file.\n */\n private async writeMarkerFile(mountPath: string): Promise<void> {\n if (!this._sandbox) return;\n\n const markerContent = this.mounts.getMarkerContent(mountPath);\n if (!markerContent) return;\n\n const filename = this.mounts.markerFilename(mountPath);\n const markerPath = `/tmp/.mastra-mounts/${filename}`;\n try {\n await this._sandbox.commands.run('mkdir -p /tmp/.mastra-mounts');\n await this._sandbox.files.write(markerPath, markerContent);\n } catch {\n // Non-fatal - marker is just for optimization\n this.logger.debug(`${LOG_PREFIX} Warning: Could not write marker file at ${markerPath}`);\n }\n }\n\n /**\n * Check if a path is already mounted and if the config matches.\n */\n private async checkExistingMount(\n mountPath: string,\n newConfig: E2BMountConfig,\n ): Promise<'not_mounted' | 'matching' | 'mismatched'> {\n if (!this._sandbox) throw new SandboxNotReadyError(this.id);\n\n // Check if path is a mount point\n const mountCheck = await this._sandbox.commands.run(\n `mountpoint -q \"${mountPath}\" && echo \"mounted\" || echo \"not mounted\"`,\n );\n\n if (mountCheck.stdout.trim() !== 'mounted') {\n return 'not_mounted';\n }\n\n // Path is mounted - check if config matches via marker file\n const filename = this.mounts.markerFilename(mountPath);\n const markerPath = `/tmp/.mastra-mounts/${filename}`;\n\n try {\n const markerResult = await this._sandbox.commands.run(`cat \"${markerPath}\" 2>/dev/null || echo \"\"`);\n const parsed = this.mounts.parseMarkerContent(markerResult.stdout.trim());\n\n if (!parsed) {\n return 'mismatched';\n }\n\n // Compute hash of the NEW config and compare with stored hash\n const newConfigHash = this.mounts.computeConfigHash(newConfig);\n this.logger.debug(\n `${LOG_PREFIX} Marker check - stored hash: \"${parsed.configHash}\", new config hash: \"${newConfigHash}\"`,\n );\n\n if (parsed.path === mountPath && parsed.configHash === newConfigHash) {\n return 'matching';\n }\n } catch {\n // Marker doesn't exist or can't be read - treat as mismatched\n }\n\n return 'mismatched';\n }\n\n /**\n * Check if an error indicates the sandbox itself is dead/gone.\n * Does NOT include code execution timeouts (those are the user's code taking too long).\n * Does NOT include \"port is not open\" - that needs sandbox kill, not reconnect.\n */\n private isSandboxDeadError(error: unknown): boolean {\n if (!error) return false;\n const errorStr = String(error);\n return (\n /\\b(?:paused\\s+)?sandbox(?:\\s+\\S+)?\\s+(?:was\\s+)?not found\\b/i.test(errorStr) ||\n errorStr.includes('Sandbox is probably not running') ||\n errorStr.includes('sandbox has been killed')\n );\n }\n\n /**\n * Handle sandbox timeout by clearing the instance and resetting state.\n *\n * Bypasses the normal stop() lifecycle because the sandbox is already dead —\n * we can't unmount filesystems or run cleanup commands. Instead we reset\n * mount states to 'pending' so they get re-mounted when start() runs again.\n */\n private handleSandboxTimeout(): void {\n this._sandbox = null;\n\n // Reset retryable entries to pending so they get re-mounted on restart.\n // A mount error belongs to the dead physical sandbox and must not prevent\n // the configured filesystem from being attempted in its replacement.\n for (const [path, entry] of this.mounts.entries) {\n if (entry.state === 'mounted' || entry.state === 'mounting' || entry.state === 'error') {\n this.mounts.set(path, { state: 'pending', error: undefined });\n }\n }\n\n this.status = 'stopped';\n }\n\n /**\n * Execute an operation with automatic retry if the sandbox is found to be dead.\n *\n * When the E2B sandbox times out or crashes mid-operation, this method\n * resets sandbox state, restarts it, and retries the operation once.\n *\n * @internal Used by E2BProcessManager to handle dead sandboxes during spawn.\n */\n async retryOnDead<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n if (this.isSandboxDeadError(error) && !this._isRetrying) {\n this.handleSandboxTimeout();\n this._isRetrying = true;\n try {\n await this.ensureRunning();\n return await fn();\n } finally {\n this._isRetrying = false;\n }\n }\n throw error;\n }\n }\n}\n","import { createHash } from \"crypto\";\n//#region src/setup-marker.ts\n/**\n* Setup completion marker shared by repo templates and their consumers.\n*\n* A repo template writes this file beside the checkout as its last build\n* step, so it exists only in images where every setup command succeeded. Its\n* content is a digest of the setup commands the image ran, letting a sandbox\n* booted from the image tell whether the setup it is about to run already\n* happened. Relative to the template's build cwd, which is also the runtime\n* working directory the repo was cloned into.\n*/\nconst SETUP_MARKER_PATH = \".mastra-sandbox/setup\";\n/** Blank entries never become build steps, so they never count toward the digest either. */\nfunction normalizeSetupCommands(setupCommand) {\n\treturn (setupCommand === void 0 ? [] : Array.isArray(setupCommand) ? setupCommand : [setupCommand]).filter((command) => command.trim() !== \"\");\n}\n/** The marker content for a setup command list: `sha256:<hex>` over the commands joined by newlines. */\nfunction setupMarkerContent(setupCommand) {\n\treturn `sha256:${createHash(\"sha256\").update(normalizeSetupCommands(setupCommand).join(\"\\n\")).digest(\"hex\")}`;\n}\n/** Shell step that writes the marker relative to the cwd. `content` is a digest, so it is shell-safe. */\nfunction setupMarkerCommand(content) {\n\treturn `mkdir -p \"$(dirname \"${SETUP_MARKER_PATH}\")\" && printf '%s' '${content}' > \"${SETUP_MARKER_PATH}\"`;\n}\n//#endregion\n//#region src/repo-clone.ts\nfunction repoCloneCommand({ cloneUrl, destination, branch, tokenEnv }) {\n\treturn `git ${tokenEnv ? `${gitAuthFlag(tokenEnv)} ` : \"\"}clone --depth=1 --single-branch ${branch ? `--branch ${shellQuote(branch)} ` : \"\"}${shellQuote(cloneUrl)} ${shellQuote(destination)}`;\n}\n/** Per-invocation auth header; `-c` config never reaches `.git/config`. */\nfunction gitAuthFlag(tokenEnv) {\n\treturn `-c http.extraheader=\"AUTHORIZATION: basic $(printf 'x-access-token:%s' \"$${tokenEnv}\" | base64 -w0)\"`;\n}\nfunction shellQuote(value) {\n\treturn `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n//#endregion\nexport { SETUP_MARKER_PATH, normalizeSetupCommands, repoCloneCommand, setupMarkerCommand, setupMarkerContent };\n\n//# sourceMappingURL=index.js.map","/**\n * Sha-tagged repo templates.\n *\n * A repo template is an E2B template with the repository already cloned and\n * its dependencies installed at a known commit. Sessions started from it only\n * need `git fetch` + checkout of their actual ref plus setup drift, instead\n * of a cold clone + full install.\n *\n * There is exactly ONE template per (repo, setup command, repoDir): the\n * template name is a deterministic `mastra-repo-<hash>` over those inputs,\n * and the commit sha rides as a docker-style TAG on that name\n * (`mastra-repo-<hash>:sha-<sha>`). A moved default branch produces a new\n * tag via a rebuild-in-place of the same template — old sha tags remain as\n * prunable build history instead of accumulating stale template names.\n * Builds are lazy: the first `E2BSandbox.start()` that resolves a missing\n * tag triggers the build; nothing pre-builds templates for idle repos.\n *\n * Credential invariant: a build credential may enter the template\n * DEFINITION (via `setEnvs`, visible to build steps but not persisted into\n * runtime sandbox environments) and the build process — never the image\n * filesystem. Clones authenticate through an in-shell computed\n * `http.extraheader`, so no tokened remote URL or credential file can land\n * in a captured layer. Callers must supply a short-lived credential (a\n * GitHub App installation token, which self-expires); never a long-lived\n * PAT. Without a credential the clone is plain tokenless HTTPS — public\n * repos build fine; a private repo's build fails and the sandbox falls back\n * to the fallback template, with the session's runtime setup performing the\n * full clone using its runtime-injected credential instead.\n */\nimport { execFile } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport { promisify } from 'node:util';\nimport { repoCloneCommand, setupMarkerCommand, setupMarkerContent } from '@internal/workspace';\n\nimport { Template } from 'e2b';\nimport type { ConnectionOpts, TemplateClass } from 'e2b';\n\nimport { createDefaultMountableTemplate, DEFAULT_CPU_COUNT, DEFAULT_MEMORY_MB } from './template';\nimport type { DeferredNamedTemplateSpec, NamedTemplateSpec } from './template';\n\nconst execFileAsync = promisify(execFile);\n\n// Monotonic; never reuse a retired value. v4 added the machine resources\n// (cpuCount, memoryMB) to the identity hash — resources are baked into the\n// built template, so a resize must produce a new template rather than\n// silently reusing one built at the old size. v5 picked up the v3 default\n// mountable base (pinned current Node LTS + corepack) — base contents are\n// not part of this hash, so the bump is what forces existing repo\n// templates to rebuild on the new base.\nconst ALIAS_VERSION = 'v5';\n\n/**\n * Stable tag assigned to every successful repo-template build. Points at the\n * latest build regardless of sha, so a moved head can boot from the previous\n * build (`name:current`) while the fresh sha builds in the background.\n */\nconst CURRENT_TAG = 'current';\n\n/**\n * Env var carrying the repository credential during the build. The same\n * name a session installs before running setup, so a setup command sees the\n * same environment in both places. Set via `setEnvs`; the git auth header is\n * computed from it too.\n */\nconst BUILD_TOKEN_ENV = 'GH_TOKEN';\n\n/**\n * Clone URLs interpolate into build shell commands, so constrain them to\n * https plus plain host/path characters. This rejects shell metacharacters\n * outright rather than escaping them. Every regex here is a single anchored\n * character class, so matching stays linear on adversarial input; the\n * structural checks (scheme, host, path segments) go through WHATWG URL\n * parsing instead of one big backtracking pattern.\n */\nconst CLONE_URL_ALLOWED_CHARS = /^[a-z0-9:/._-]+$/i;\nconst CLONE_URL_HOST_PATTERN = /^[a-z0-9.-]+$/i;\nconst CLONE_URL_SEGMENT_PATTERN = /^[\\w.-]+$/;\nconst SHA_PATTERN = /^[0-9a-f]{7,40}$/i;\n\nfunction isValidCloneUrl(cloneUrl: string): boolean {\n // The RAW string is what reaches shell commands, so allowlist it directly:\n // URL normalization (backslash folding, percent-decoding) must not be able\n // to launder characters the raw string carries.\n if (cloneUrl.length > 2048 || !CLONE_URL_ALLOWED_CHARS.test(cloneUrl)) return false;\n let url: URL;\n try {\n url = new URL(cloneUrl);\n } catch {\n return false;\n }\n if (url.protocol !== 'https:' || url.username || url.password || url.search || url.hash) return false;\n if (!CLONE_URL_HOST_PATTERN.test(url.hostname)) return false;\n // At least one path segment, none empty — rejects bare hosts and\n // trailing slashes, exactly as the previous single-pattern check did.\n const segments = url.pathname.split('/').slice(1);\n return segments.length > 0 && segments.every(segment => CLONE_URL_SEGMENT_PATTERN.test(segment));\n}\n\n/**\n * Repository clone target plus an optional credential for it.\n *\n * Structurally identical to the factory capability of the same name, and\n * declared here so this package carries no factory dependency: a host can\n * pass its context accessor straight through.\n */\nexport interface RepositoryAccess {\n /** https clone URL, e.g. `https://github.com/acme/widgets.git`. */\n cloneUrl: string;\n /**\n * Credential for private repositories. `scheme` describes the credential\n * itself; git over https accepts only basic auth, so a bearer token is\n * presented as `x-access-token:<token>` (see {@link gitAuthFlag}).\n */\n authorization?: { scheme: 'bearer'; token: string };\n}\n\nexport interface RepoTemplateOptions {\n /**\n * Resolves the clone URL and, for private repositories, a SHORT-LIVED\n * credential (e.g. a GitHub App installation token). Called once per\n * template resolution: the credential authenticates the head lookup and,\n * when a build is needed, the build's clone (via `setEnvs` plus an\n * in-shell `http.extraheader` — it never touches the image filesystem,\n * and probing confirms `setEnvs` values do not persist into runtime\n * sandbox environments). Never supply a long-lived PAT: the value enters\n * the template definition, where only its expiry bounds the exposure. A\n * rejection degrades to tokenless behavior.\n *\n * Sole source of the clone URL, so what gets cloned and what the template\n * is identified by can never disagree. A public repository needs no\n * credential: `async () => ({ cloneUrl })`.\n *\n * The key is required so that passing a host context whose field was\n * renamed fails to compile instead of silently producing no template.\n * `undefined` means the session has no repository, and\n * {@link createRepoTemplate} then returns undefined.\n */\n getRepositoryAccess: (() => Promise<RepositoryAccess | undefined>) | undefined;\n /**\n * Setup command(s) run inside the checkout and hashed into the template name.\n * Array entries run as separate cached build steps.\n */\n setupCommand?: string | string[];\n /**\n * Extra environment for the build, available to every build step\n * including {@link RepoTemplateOptions.setupCommand}. Use it for the\n * credentials a setup command needs (registry tokens, private index\n * URLs) so the build reaches the same state a runtime setup would.\n *\n * Hashed into the template name (keys and values), because env that\n * changes what setup installs changes the image just as the setup command\n * does. Rotating a value therefore forces a rebuild — put credentials\n * that rotate often in {@link RepoTemplateOptions.getRepositoryAccess}\n * instead, which is excluded from identity.\n *\n * Values reach the template definition, so they must be short-lived or\n * non-secret.\n */\n buildEnv?: Record<string, string> | (() => Promise<Record<string, string>>);\n /**\n * vCPUs allocated to sandboxes created from this template. Resources are\n * a property of the built template, not of an individual sandbox, so this\n * is hashed into the template name — a resize builds a new template\n * instead of silently reusing one built at the old size. Defaults to the\n * SDK default (2). Account tier caps the maximum.\n */\n cpuCount?: number;\n /**\n * Memory in MB allocated to sandboxes created from this template. Hashed\n * into the template name for the same reason as {@link cpuCount}.\n * Defaults to the SDK default (1024).\n */\n memoryMB?: number;\n /**\n * Absolute parent for the checkout. Created by the build user, so its parent\n * must already be writable by that user. Becomes the build cwd, the runtime\n * cwd, and part of template identity; the repo lands at `<workingDirectory>/<repo>`.\n * Omit to use the base image's working directory for all of the above.\n */\n workingDirectory?: string;\n}\n\n/**\n * Identity inputs for a repo template, already resolved. Separate from\n * {@link RepoTemplateOptions} because identity must be computable without\n * awaiting anything, while the clone URL and credential arrive from an\n * async accessor.\n */\nexport interface RepoTemplateIdentity {\n /** https clone URL. Host is part of the identity. */\n cloneUrl: string;\n /** Resolved head sha. Becomes the template's tag. */\n sha?: string;\n setupCommand?: string | string[];\n buildEnv?: Record<string, string>;\n cpuCount?: number;\n memoryMB?: number;\n workingDirectory?: string;\n}\n\n/**\n * Compute the deterministic template ref for a set of repo template inputs\n * without constructing the builder: `mastra-repo-<hash>` named over\n * (clone URL, setup command, build env), tag-qualified with `:sha-<sha>`\n * when the sha is known. Exposed so callers (and proofs) can predict which\n * ref a sandbox will resolve.\n */\nexport function repoTemplateRef(identity: RepoTemplateIdentity): string {\n const name = repoTemplateName(identity);\n // The sha-less degrade also pins a tag (`current`) rather than the bare\n // name: `Template.exists(name)` is true whenever ANY tagged build exists,\n // but creating from a bare name resolves its `default` tag — which\n // sha-tagged builds never assign — so an untagged ref could pass the\n // exists check and still 404 on create.\n return identity.sha ? `${name}:${shaTag(identity.sha)}` : `${name}:${CURRENT_TAG}`;\n}\n\n// `sha` is excluded at the type level: the name is sha-independent by\n// design (the sha rides the tag), and the signature is what enforces it —\n// making the name sha-dependent would collapse every commit into its own\n// template and kill warm reuse.\nfunction repoTemplateName(identity: Omit<RepoTemplateIdentity, 'sha'>): string {\n const cloneUrl = normalizeCloneUrl(identity.cloneUrl);\n // Fixed key order, so a plain stringify is already canonical. Not a\n // replacer array: that filters keys at every level, which would drop the\n // build env's own keys from the hash.\n const config = [\n ALIAS_VERSION,\n cloneUrl,\n identity.setupCommand ?? null,\n // Sorted, since key order isn't identity. Values participate: env that\n // changes what setup installs changes the image.\n identity.buildEnv ? Object.entries(identity.buildEnv).sort(([a], [b]) => a.localeCompare(b)) : null,\n // Normalized to the defaults, so \"absent\" and \"explicitly default\" are\n // the same template.\n identity.cpuCount ?? DEFAULT_CPU_COUNT,\n identity.memoryMB ?? DEFAULT_MEMORY_MB,\n // Appended only when set, so templates predating the option keep their\n // existing names (and warm builds) instead of all rebuilding.\n ...(identity.workingDirectory !== undefined ? [identity.workingDirectory] : []),\n ];\n const hash = createHash('sha256').update(JSON.stringify(config)).digest('hex').slice(0, 8);\n // Readable name: the repo slug is right in the template name; the short\n // hash suffix keeps host/setup-command variants and sanitization\n // collisions distinct.\n const { owner, repo } = parseCloneUrl(cloneUrl);\n const slug = [owner, repo]\n .map(part =>\n (part ?? '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n // The previous replace collapsed runs, so at most one leading and\n // one trailing dash exist — no `+` needed, which keeps the pattern\n // linear on dash-heavy input.\n .replace(/^-/, '')\n .replace(/-$/, '')\n .slice(0, 24),\n )\n .filter(Boolean)\n .join('-');\n return `mastra-repo-${slug}-${hash}`;\n}\n\nfunction shaTag(sha: string): string {\n return `sha-${sha.slice(0, 12).toLowerCase()}`;\n}\n\n/**\n * Create a sha-tagged repo template spec for `E2BSandbox`.\n *\n * Returns undefined when {@link RepoTemplateOptions.getRepositoryAccess} is\n * absent, which is how a session with no repository asks for no template —\n * so a host can write `template: createRepoTemplate(ctx)` without a\n * conditional.\n *\n * Resolution is deferred: right before the exists-then-build check it\n * resolves the clone URL and credential, resolves the repository's current\n * default-branch head (`git ls-remote`, ~100ms, no clone), and keys the\n * template ref as `mastra-repo-<hash>:sha-<head>` — so a moved default\n * branch produces a fresh tagged build of the SAME template on the next new\n * session (rebuild-in-place), and an unmoved head reuses the existing\n * tagged build. When the head cannot be resolved the ref degrades to the\n * untagged name and the build clones whatever the default branch is at\n * build time.\n *\n * When the build itself fails — inaccessible repo, registry flake — the\n * sandbox falls back to its fallback template and the session's runtime\n * setup performs the full clone, so a broken build never wedges a session.\n */\nexport function createRepoTemplate(options: RepoTemplateOptions): DeferredNamedTemplateSpec | undefined {\n if (!options.getRepositoryAccess) return undefined;\n return {\n resolveSpec: async () => (await resolveSpecAtHead(options)).spec,\n };\n}\n\n/**\n * Resolve the clone URL and credential, resolve the current default-branch\n * head, and produce the concrete sha-tagged spec. Shared by the deferred\n * spec form and {@link refreshRepoTemplate}.\n *\n * A failed access call leaves no clone URL and throws, which the sandbox\n * turns into its default-template fallback rather than a failed start.\n */\nasync function resolveSpecAtHead(options: RepoTemplateOptions): Promise<{ spec: NamedTemplateSpec; sha?: string }> {\n const access = options.getRepositoryAccess ? await options.getRepositoryAccess().catch(() => undefined) : undefined;\n const cloneUrl = access?.cloneUrl;\n if (!cloneUrl) {\n throw new Error('Repo template has no clone URL: repository access returned none.');\n }\n assertCloneUrl(cloneUrl);\n const token = access?.authorization?.token;\n const buildEnv = typeof options.buildEnv === 'function' ? await options.buildEnv() : options.buildEnv;\n\n const resolved = await resolveDefaultBranchHead(cloneUrl, token).catch(() => undefined);\n const sha = resolved && SHA_PATTERN.test(resolved) ? resolved : undefined;\n\n const identity: RepoTemplateIdentity = {\n cloneUrl,\n ...(sha ? { sha } : {}),\n // Kept in its original shape (string vs array) so existing string-form\n // templates keep their hashes; omitted entirely when nothing would run.\n ...(normalizeSetupCommands(options.setupCommand).length > 0 ? { setupCommand: options.setupCommand } : {}),\n ...(buildEnv ? { buildEnv } : {}),\n ...(options.cpuCount !== undefined ? { cpuCount: options.cpuCount } : {}),\n ...(options.memoryMB !== undefined ? { memoryMB: options.memoryMB } : {}),\n ...(options.workingDirectory !== undefined\n ? { workingDirectory: trimTrailingSlashes(assertWorkingDirectory(options.workingDirectory)) }\n : {}),\n };\n return { spec: buildRepoTemplateSpec(identity, token), ...(sha ? { sha } : {}) };\n}\n\n/** Result of a {@link refreshRepoTemplate} call. */\nexport interface RefreshRepoTemplateResult {\n /** Template ref (`name:tag`) that is now current. */\n ref: string;\n /** Whether an up-to-date build already existed or a fresh build ran. */\n action: 'reused' | 'built';\n /** Resolved head sha, when it could be determined. */\n sha?: string;\n}\n\n/**\n * Ensure the repo template is built at the repository's current\n * default-branch head, building it (and moving the `current` tag) when it\n * is not. This is the same resolution the lazy sandbox-start path performs\n * — exposed standalone so template warming can be driven externally: call\n * it from a scheduled workflow (cron) or a merge-to-main event handler and\n * the next session boots warm instead of paying the build.\n *\n * The build is awaited; a build failure rejects so callers can observe it.\n * An unresolvable head degrades to the sha-less `name:current` form, same\n * as the lazy path.\n */\nexport async function refreshRepoTemplate(\n options: RepoTemplateOptions,\n connection?: ConnectionOpts,\n): Promise<RefreshRepoTemplateResult> {\n const { spec, sha } = await resolveSpecAtHead(options);\n const shaField = sha ? { sha } : {};\n if (await Template.exists(spec.ref, connection)) {\n return { ref: spec.ref, action: 'reused', ...shaField };\n }\n await Template.build(spec.template as TemplateClass, spec.ref, {\n ...connection,\n ...(spec.buildTags?.length ? { tags: spec.buildTags } : {}),\n ...spec.buildResources,\n });\n return { ref: spec.ref, action: 'built', ...shaField };\n}\n\n/**\n * The clone URL is the only untrusted input that reaches a build command,\n * so it is checked before it can be interpolated into one. The repoDir is\n * derived from it rather than supplied, so it needs no separate guard.\n */\n\nfunction assertCloneUrl(cloneUrl: string): void {\n if (!isValidCloneUrl(cloneUrl)) {\n throw new Error(`Invalid cloneUrl '${cloneUrl}': expected an https URL with a plain host and path`);\n }\n if (parseCloneUrl(cloneUrl).repo === '') {\n throw new Error(`Invalid cloneUrl '${cloneUrl}': expected a repository path such as https://host/owner/repo.git`);\n }\n}\n\n/**\n * In-shell git auth flag: computes a basic-auth header from the build env\n * var at execution time. The stored command contains only the env-var\n * REFERENCE — the token value never appears in the command string, and no\n * credential is written to the build filesystem.\n */\nfunction gitAuthFlag(): string {\n return `-c http.extraheader=\"AUTHORIZATION: basic $(printf 'x-access-token:%s' \"$${BUILD_TOKEN_ENV}\" | base64 -w0)\"`;\n}\n\nfunction buildRepoTemplateSpec(identity: RepoTemplateIdentity, token?: string): NamedTemplateSpec {\n const { sha, setupCommand, buildEnv, workingDirectory } = identity;\n const cloneUrl = normalizeCloneUrl(identity.cloneUrl);\n // Relative to the build cwd, which `setWorkdir` (or the base image) also\n // makes the runtime cwd, so the checkout sits at `<cwd>/<repo>` either way.\n const repoDir = repoDirName(cloneUrl);\n\n const auth = token ? `${gitAuthFlag()} ` : '';\n\n let template = createDefaultMountableTemplate().template;\n const env: Record<string, string> = { ...buildEnv };\n if (token) env[BUILD_TOKEN_ENV] = token;\n if (Object.keys(env).length > 0) {\n // Visible to build steps; probed to NOT persist into runtime sandbox\n // environments. Values must be short-lived — they stay in the template\n // definition until the next rebuild.\n template = template.setEnvs(env);\n }\n if (workingDirectory) {\n // Created by the build user so it is writable; `setWorkdir` then makes\n // it the cwd for the steps below and the runtime default, without\n // shell expansion.\n const dir = trimTrailingSlashes(workingDirectory);\n template = template.runCmd(`mkdir -p \"${dir}\"`).setWorkdir(dir);\n }\n // Each command gets its own cached build layer. Same shallow clone Factory\n // makes at session start when no image provided one, so both paths yield\n // the same checkout.\n template = template.runCmd(\n repoCloneCommand({ cloneUrl, destination: repoDir, ...(token ? { tokenEnv: BUILD_TOKEN_ENV } : {}) }),\n );\n if (sha) {\n // GitHub serves fetches of reachable shas, so pinning after a default\n // clone is reliable without full-history flags.\n template = template\n .runCmd(`git -C \"${repoDir}\" ${auth}fetch origin ${sha}`)\n .runCmd(`git -C \"${repoDir}\" checkout ${sha}`);\n }\n // Build steps use fresh shells, so each setup command needs its own `cd`.\n const setupCommands = normalizeSetupCommands(setupCommand);\n for (const command of setupCommands) {\n template = template.runCmd(`cd \"${repoDir}\" && ${command}`);\n }\n // Last, so it only exists in images where every step above succeeded.\n template = template.runCmd(setupMarkerCommand(setupMarkerContent(setupCommands)));\n\n return {\n ref: repoTemplateRef(identity),\n template,\n // A failed repo build degrades to the default mountable template; the\n // session's runtime cold clone into `$HOME` keeps working.\n //\n // Every successful build also moves the stable `current` tag; when a\n // moved head means the exact sha tag doesn't exist yet, the sandbox\n // boots from `name:current` immediately (runtime setup fast-forwards\n // the checkout) while the fresh sha builds in the background.\n staleRef: `${repoTemplateName(identity)}:${CURRENT_TAG}`,\n buildTags: [CURRENT_TAG],\n // Always explicit, so what gets built matches what got hashed.\n buildResources: {\n cpuCount: identity.cpuCount ?? DEFAULT_CPU_COUNT,\n memoryMB: identity.memoryMB ?? DEFAULT_MEMORY_MB,\n },\n };\n}\n\n/**\n * `owner/repo` for a github.com clone URL, else undefined. Only the public\n * host is API-resolvable: GitHub Enterprise and other forges keep the git\n * path.\n */\nfunction parseGithubRepo(cloneUrl: string): { owner: string; repo: string } | undefined {\n let url: URL;\n try {\n url = new URL(cloneUrl);\n } catch {\n return undefined;\n }\n if (url.hostname.toLowerCase() !== 'github.com') return undefined;\n const [owner, repo, ...rest] = url.pathname.split('/').filter(Boolean);\n if (!owner || !repo || rest.length > 0) return undefined;\n return { owner, repo: repo.replace(/\\.git$/i, '') };\n}\n\n/**\n * Resolve the repository's current default-branch head without cloning.\n * github.com repositories go through the REST API so resolution works\n * wherever the host runs, including images without a git binary; other\n * hosts use `git ls-remote <url> HEAD`, authenticated via an in-process\n * `http.extraheader` when a token is provided. Returns undefined when the\n * head cannot be resolved (inaccessible repo, offline, no git binary);\n * callers degrade to the untagged template ref.\n */\nasync function resolveDefaultBranchHead(cloneUrl: string, token?: string): Promise<string | undefined> {\n const github = parseGithubRepo(cloneUrl);\n if (github) {\n try {\n const response = await fetch(`https://api.github.com/repos/${github.owner}/${github.repo}/commits/HEAD`, {\n headers: {\n Accept: 'application/vnd.github.sha',\n 'X-GitHub-Api-Version': '2022-11-28',\n 'User-Agent': 'mastra-e2b',\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n },\n signal: AbortSignal.timeout(10_000),\n });\n if (!response.ok) return undefined;\n const sha = (await response.text()).trim();\n return SHA_PATTERN.test(sha) ? sha : undefined;\n } catch {\n return undefined;\n }\n }\n try {\n const authArgs = token\n ? ['-c', `http.extraheader=AUTHORIZATION: basic ${Buffer.from(`x-access-token:${token}`).toString('base64')}`]\n : [];\n // `--` makes the URL position unambiguous to git: even a hostile value\n // can never be read as an option such as `--upload-pack`.\n const { stdout } = await execFileAsync('git', [...authArgs, 'ls-remote', '--', cloneUrl, 'HEAD'], {\n timeout: 10_000,\n env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },\n });\n const sha = stdout.split(/\\s/, 1)[0];\n return sha && SHA_PATTERN.test(sha) ? sha : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Canonical form used for identity and for the build's clone: lowercase\n * host, no trailing `.git` or slash. Two spellings of one repository must\n * not produce two templates.\n */\nfunction normalizeCloneUrl(cloneUrl: string): string {\n // Avoid regex backtracking on long trailing-slash runs.\n let end = cloneUrl.length;\n while (end > 0 && cloneUrl[end - 1] === '/') end--;\n const withoutSuffix = cloneUrl.slice(0, end).replace(/\\.git$/i, '');\n return withoutSuffix.replace(/^(https:\\/\\/)([^/]+)/i, (_match, scheme: string, host: string) => {\n return `${scheme.toLowerCase()}${host.toLowerCase()}`;\n });\n}\n\n/**\n * Split a normalized clone URL into its host and trailing owner/repo pair.\n * Hosts that nest groups (GitLab subgroups) keep only the last two path\n * segments as owner/repo; the full URL still drives identity.\n */\nfunction parseCloneUrl(cloneUrl: string): { host: string; owner: string; repo: string } {\n const withoutScheme = normalizeCloneUrl(cloneUrl).replace(/^https:\\/\\//i, '');\n const [host = '', ...segments] = withoutScheme.split('/');\n const repo = segments.at(-1) ?? '';\n const owner = segments.length > 1 ? (segments.at(-2) ?? '') : '';\n return { host, owner, repo };\n}\n\n/** Normalize setup commands and drop blank entries that would produce invalid shell steps. */\nfunction normalizeSetupCommands(setupCommand: string | string[] | undefined): string[] {\n const list = setupCommand === undefined ? [] : Array.isArray(setupCommand) ? setupCommand : [setupCommand];\n return list.filter(command => command.trim() !== '');\n}\n\nfunction repoDirName(cloneUrl: string): string {\n const { repo } = parseCloneUrl(cloneUrl);\n return repo.replace(/[^\\w.-]/g, '-').replace(/^\\.+/, '') || 'repo';\n}\n\n// Avoid regex backtracking on long trailing-slash runs.\nfunction trimTrailingSlashes(path: string): string {\n let end = path.length;\n while (end > 1 && path[end - 1] === '/') end--;\n return path.slice(0, end);\n}\n\n/** Validate a literal absolute path before embedding it in shell build steps. */\nfunction assertWorkingDirectory(dir: string): string {\n const valid = /^\\/[A-Za-z0-9._/-]*$/.test(dir) && !dir.split('/').includes('..');\n if (!valid) {\n throw new Error(\n `Repo template workingDirectory must be an absolute path of plain path characters (got ${JSON.stringify(dir)}); ~ and $HOME are not expanded.`,\n );\n }\n return dir;\n}\n","/**\n * E2B sandbox provider descriptor for MastraEditor.\n *\n * @example\n * ```typescript\n * import { e2bSandboxProvider } from '@mastra/e2b';\n *\n * const editor = new MastraEditor({\n * sandboxes: [e2bSandboxProvider],\n * });\n * ```\n */\nimport type { SandboxProvider } from '@mastra/core/editor';\nimport { E2BSandbox } from './sandbox';\n\n/**\n * Serializable subset of E2BSandboxOptions for editor storage.\n * Non-serializable options (TemplateBuilder callbacks, runtime objects) are excluded.\n */\ninterface E2BProviderConfig {\n template?: string;\n timeout?: number;\n env?: Record<string, string>;\n metadata?: Record<string, unknown>;\n domain?: string;\n apiUrl?: string;\n apiKey?: string;\n accessToken?: string;\n}\n\nexport const e2bSandboxProvider: SandboxProvider<E2BProviderConfig> = {\n id: 'e2b',\n name: 'E2B Sandbox',\n description: 'Cloud sandbox powered by E2B',\n configSchema: {\n type: 'object',\n properties: {\n template: { type: 'string', description: 'Sandbox template ID' },\n timeout: { type: 'number', description: 'Execution timeout in milliseconds', default: 300000 },\n env: {\n type: 'object',\n description: 'Environment variables',\n additionalProperties: { type: 'string' },\n },\n metadata: {\n type: 'object',\n description: 'Custom metadata',\n additionalProperties: true,\n },\n domain: { type: 'string', description: 'Domain for self-hosted E2B' },\n apiUrl: { type: 'string', description: 'API URL for self-hosted E2B' },\n apiKey: { type: 'string', description: 'E2B API key' },\n accessToken: { type: 'string', description: 'E2B access token' },\n },\n },\n createSandbox: config => new E2BSandbox(config),\n};\n","/**\n * Code Mode — E2B transport\n *\n * The default {@link StdioCodeModeTransport} in `@mastra/core` writes the\n * runner/program files to the *host* tmpdir and spawns `node <hostPath>`. That\n * only works when the sandbox shares the host filesystem (e.g. `LocalSandbox`).\n * E2B runs the program in a remote micro-VM with its own filesystem, so the\n * host paths don't exist there and `node` exits immediately.\n *\n * `E2BCodeModeTransport` writes the runner/program *into* the sandbox via the\n * E2B files API and runs plain `node <runnerPath>` inside the VM. TypeScript is\n * stripped on the host with esbuild before upload, so it doesn't depend on the\n * sandbox's Node version (the core transport relies on\n * `node --experimental-strip-types`, which needs Node >= 22.6).\n *\n * The RPC frame protocol (host <-> runner) is unchanged: it reuses\n * `buildProgramModule`, `buildRunner`, and `FRAME_PREFIX` from\n * `@mastra/core/tools`.\n */\n\nimport { randomBytes } from 'node:crypto';\nimport { buildProgramModule, buildRunner, FRAME_PREFIX, sanitizeToolId } from '@mastra/core/tools';\nimport type { CodeModeRunnerFrame, CodeModeToolResult, CodeModeTransport } from '@mastra/core/tools';\nimport type { ProcessHandle } from '@mastra/core/workspace';\nimport { transformSync } from 'esbuild';\nimport { E2BSandbox } from '../sandbox';\n\n/** Base directory inside the E2B sandbox where Code Mode programs are written. */\nconst SANDBOX_TMP = '/home/user/mastra-code-mode';\n\n/**\n * Code Mode transport for {@link E2BSandbox}.\n *\n * Writes the generated program and runner into the sandbox filesystem, runs\n * `node` there, and bridges `external_*` RPC calls back to the host over the\n * process's stdout/stdin — the same frame protocol as the core stdio transport.\n *\n * @example\n * ```typescript\n * import { createCodeMode } from '@mastra/core/tools';\n * import { E2BSandbox, E2BCodeModeTransport } from '@mastra/e2b';\n *\n * const { tool, instructions } = createCodeMode(\n * { tools: { getWeather, getForecast }, sandbox: new E2BSandbox() },\n * new E2BCodeModeTransport(),\n * );\n * ```\n */\nexport class E2BCodeModeTransport implements CodeModeTransport {\n async run(opts: Parameters<CodeModeTransport['run']>[0]): Promise<CodeModeToolResult> {\n const { sandbox, program, toolIds, dispatch, timeout, abortSignal, onExternalCall, onExternalResult } = opts;\n\n if (!(sandbox instanceof E2BSandbox)) {\n throw new Error('E2BCodeModeTransport requires an E2BSandbox');\n }\n if (!sandbox.processes) {\n throw new Error('Sandbox has no process manager');\n }\n\n // Auto-start the sandbox so callers don't have to pre-start it. `start()`\n // is a no-op when already running.\n if (sandbox.status !== 'running') {\n await sandbox.start();\n }\n\n const e2b = sandbox.e2b;\n const externals = toolIds.map(toolId => ({ toolId, externalName: sanitizeToolId(toolId) }));\n const allowList = new Set(toolIds);\n\n const suffix = randomBytes(4).toString('hex');\n const dir = `${SANDBOX_TMP}/${suffix}`;\n const programPath = `${dir}/program-${suffix}.mjs`;\n const runnerPath = `${dir}/runner-${suffix}.mjs`;\n\n // Strip TypeScript on the host so the sandbox runs plain JS with no\n // experimental flag and no Node-version dependency.\n const programSource = transformSync(buildProgramModule(program), { loader: 'ts', target: 'es2022' }).code;\n const runnerSource = buildRunner({ programModule: `file://${programPath}`, externals });\n\n const logs: string[] = [];\n let stderr = '';\n let done: CodeModeToolResult | undefined;\n let stdoutBuffer = '';\n\n let resolveDone!: () => void;\n const donePromise = new Promise<void>(resolve => {\n resolveDone = resolve;\n });\n\n // Observer hooks are caller-supplied and best-effort: a throwing hook must\n // never prevent `respond()` from running, or the matching in-sandbox promise\n // would hang until the timeout.\n const notifyCall = (tool: string, args: unknown): void => {\n try {\n onExternalCall?.(tool, args);\n } catch {\n /* observer errors are non-fatal */\n }\n };\n const notifyResult = (tool: string, durationMs: number, error?: Error): void => {\n try {\n onExternalResult?.(tool, durationMs, error);\n } catch {\n /* observer errors are non-fatal */\n }\n };\n\n try {\n await e2b.files.makeDir(dir);\n await e2b.files.write(programPath, programSource);\n await e2b.files.write(runnerPath, runnerSource);\n\n let handle: ProcessHandle;\n\n const respond = async (\n id: number,\n ok: boolean,\n result?: unknown,\n error?: { message: string; name?: string },\n ): Promise<void> => {\n await handle.sendStdin(JSON.stringify({ type: 'rpc-result', id, ok, result, error }) + '\\n');\n };\n\n const serveRpc = async (id: number, tool: string, args: unknown): Promise<void> => {\n const started = Date.now();\n notifyCall(tool, args);\n // Allow-list enforcement: never invoke a tool that wasn't exposed.\n if (!allowList.has(tool)) {\n notifyResult(tool, Date.now() - started, new Error('not allowed'));\n await respond(id, false, undefined, {\n message: `Tool \"${tool}\" is not available in Code Mode`,\n name: 'NotAllowedError',\n });\n return;\n }\n try {\n const result = await dispatch(tool, args);\n notifyResult(tool, Date.now() - started);\n await respond(id, true, result);\n } catch (error) {\n const err = error as { message?: string; name?: string };\n notifyResult(tool, Date.now() - started, error instanceof Error ? error : new Error(String(error)));\n await respond(id, false, undefined, {\n message: err?.message ?? String(error),\n name: err?.name,\n });\n }\n };\n\n const handleFrame = (frame: CodeModeRunnerFrame): void => {\n switch (frame.type) {\n case 'log':\n logs.push(frame.message);\n return;\n case 'done':\n done = frame.ok\n ? { success: true, result: frame.result, logs }\n : { success: false, error: frame.error, logs };\n resolveDone();\n return;\n case 'rpc':\n // `serveRpc` awaits `respond`, which writes to the child's stdin and\n // can reject if the process already exited/was killed. Swallow that\n // so it never surfaces as an unhandled rejection.\n void serveRpc(frame.id, frame.tool, frame.args).catch(() => {});\n return;\n }\n };\n\n handle = await sandbox.processes.spawn(`node ${runnerPath}`, {\n cwd: dir,\n abortSignal,\n // E2B failures are otherwise silent, which makes them painful to debug.\n // Capture stderr and surface it in Timeout/NoResult errors below.\n onStderr: (chunk: string) => {\n stderr += chunk;\n },\n onStdout: (chunk: string) => {\n stdoutBuffer += chunk;\n let idx: number;\n while ((idx = stdoutBuffer.indexOf('\\n')) >= 0) {\n const line = stdoutBuffer.slice(0, idx);\n stdoutBuffer = stdoutBuffer.slice(idx + 1);\n if (!line.startsWith(FRAME_PREFIX)) continue;\n let frame: CodeModeRunnerFrame;\n try {\n frame = JSON.parse(line.slice(FRAME_PREFIX.length));\n } catch {\n continue;\n }\n handleFrame(frame);\n }\n },\n });\n\n // Race completion against process exit and the timeout. Including process\n // exit means a runner that dies without emitting `done` resolves\n // immediately instead of waiting out the full timeout.\n let timer: NodeJS.Timeout | undefined;\n const timeoutPromise = new Promise<'timeout'>(resolve => {\n timer = setTimeout(() => resolve('timeout'), timeout);\n });\n const exitPromise = handle.wait().then(() => 'exited' as const);\n\n const outcome = await Promise.race([\n donePromise.then(() => 'done' as const),\n exitPromise.catch(() => 'exited' as const),\n timeoutPromise,\n ]);\n if (timer) clearTimeout(timer);\n\n if (outcome === 'timeout') {\n await handle.kill().catch(() => {});\n return {\n success: false,\n logs,\n error: {\n message: `Code Mode execution timed out after ${timeout}ms${stderr ? `\\nstderr: ${stderr}` : ''}`,\n name: 'TimeoutError',\n },\n };\n }\n\n // Either `done` arrived or the process exited. If we raced ahead of a\n // `done` frame still in flight, give it a brief beat to land.\n if (!done) {\n await exitPromise.catch(() => {});\n }\n\n return (\n done ?? {\n success: false,\n logs,\n error: {\n message: `Program exited without returning a result${stderr ? `\\nstderr: ${stderr}` : ''}`,\n name: 'NoResultError',\n },\n }\n );\n } finally {\n await e2b.files.remove(dir).catch(() => {});\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["shellQuote","shellQuote","shellQuote","shellQuote","normalizeSetupCommands","gitAuthFlag"],"sources":["../src/utils/template.ts","../src/sandbox/mounts/types.ts","../src/utils/shell-quote.ts","../src/sandbox/mounts/s3.ts","../src/sandbox/mounts/gcs.ts","../src/sandbox/mounts/azure.ts","../src/sandbox/process-manager.ts","../src/sandbox/index.ts","../../../packages/_internals/workspace/dist/index.js","../src/utils/repo-template.ts","../src/provider.ts","../src/code-mode/transport.ts"],"sourcesContent":["/**\n * E2B Template Utilities\n *\n * Helper functions for creating and managing E2B sandbox templates.\n */\nimport { createHash } from 'node:crypto';\nimport { Template } from 'e2b';\nimport type { TemplateBuilder } from 'e2b';\n\n// =============================================================================\n// Template Types\n// =============================================================================\n\n/**\n * Template specification for E2B sandbox.\n *\n * Can be:\n * - `string` - Existing template ID (e.g., 'base', 'my-custom-template')\n * - `TemplateBuilder` - A built template object from Template()\n * - `(base: TemplateBuilder) => TemplateBuilder` - Callback to customize the base template\n *\n * @example Using template ID\n * ```typescript\n * new E2BSandbox({ template: 'my-custom-template' })\n * ```\n *\n * @example Using Template builder\n * ```typescript\n * import { Template } from 'e2b';\n *\n * new E2BSandbox({\n * template: Template()\n * .fromUbuntuImage('22.04')\n * .aptInstall(['s3fs', 'curl'])\n * .setEnvs({ NODE_ENV: 'production' })\n * })\n * ```\n *\n * @example Customizing default mountable template\n * ```typescript\n * new E2BSandbox({\n * template: base => base\n * .aptInstall(['nodejs', 'npm'])\n * .runCmd('npm install -g typescript')\n * })\n * ```\n */\nexport type TemplateSpec =\n | string\n | TemplateBuilder\n | ((base: TemplateBuilder) => TemplateBuilder)\n | NamedTemplateSpec\n | DeferredNamedTemplateSpec;\n\n/**\n * A template builder paired with a deterministic name (the word E2B's own\n * `Template.build(template, name)` uses: the name IS the identity, and may\n * carry a `:tag` qualifier).\n *\n * Resolution is lazy build-if-missing: the sandbox checks\n * `Template.exists(name)` and reuses the existing build when present, so\n * every sandbox constructed with the same name shares one template. When\n * the name is missing the build runs once; if the build fails the sandbox\n * falls back to `fallbackTemplate` (or the default mountable template) so a\n * broken build degrades to a cold start instead of a wedged session.\n */\nexport interface NamedTemplateSpec {\n /** Deterministic template ref (`name:tag`, e.g. content-hashed name). */\n ref: string;\n /** Builder used when no template exists under the name yet. */\n template: TemplateBuilder;\n /**\n * Template used when the named build fails. May itself be a named spec,\n * resolved exists-then-build under its own name — one rung only: a named\n * fallback's own `fallbackTemplate` is ignored, and anything failing past\n * it lands on the default mountable template. Defaults to the default\n * mountable template.\n */\n fallbackTemplate?: string | TemplateBuilder | NamedTemplateSpec;\n /**\n * Ref (`name:tag`) of a previous successful build of this template. When\n * `name` does not exist yet but this ref does, the sandbox is created\n * from the stale build immediately and the `name` build is kicked off in\n * the background (non-blocking rebuild-in-place) — only the very first\n * build of a template ever blocks a sandbox start.\n */\n staleRef?: string;\n /**\n * Extra tags assigned alongside the name's tag on every successful build\n * (e.g. a stable `current` pointer that {@link staleRef} targets).\n */\n buildTags?: string[];\n /**\n * Machine resources for builds of this template — sandboxes created from\n * it get exactly these. Applied to the named build and its background\n * rebuilds. For content-hashed specs the same values must participate in\n * the name, or a resize would silently reuse a template built at the\n * old size.\n */\n buildResources?: TemplateResources;\n}\n\n/** Machine resources for a template build. */\nexport interface TemplateResources {\n cpuCount?: number;\n memoryMB?: number;\n}\n\n/** Options for the default mountable template. */\nexport interface MountableTemplateOptions extends TemplateResources {\n /**\n * Exact Node.js version installed over the base image's stale runtime\n * (`MAJOR.MINOR.PATCH`). Part of the template identity, so changing it\n * builds a new template. Defaults to {@link DEFAULT_NODE_VERSION}.\n */\n nodeVersion?: string;\n}\n\n/**\n * Resource defaults matching the e2b SDK's own build defaults. Hashed and\n * passed to every build explicitly, so a template's identity and its built\n * artifact can never disagree about machine size — even if the SDK\n * defaults drift.\n */\nexport const DEFAULT_CPU_COUNT = 2;\nexport const DEFAULT_MEMORY_MB = 1024;\n\n/**\n * Node.js version installed into the default template — the current LTS at\n * pin time. An exact version rather than an `lts` alias so the template's\n * contents can never drift under a stable identity hash; bump deliberately\n * (each bump builds new templates).\n */\nexport const DEFAULT_NODE_VERSION = '24.20.0';\n\nconst NODE_VERSION_PATTERN = /^\\d+\\.\\d+\\.\\d+$/;\n\nexport function isNamedTemplateSpec(spec: TemplateSpec): spec is NamedTemplateSpec {\n return typeof spec === 'object' && spec !== null && 'ref' in spec && 'template' in spec;\n}\n\n/**\n * A named spec whose name and build steps are computed at resolution time\n * rather than construction time — e.g. a repo template that pins itself to\n * the repository's current default-branch head, fetched right before the\n * exists-then-build check. `resolveSpec()` runs once per `start()` template\n * resolution; failures inside it must be handled by the implementation\n * (return a degraded spec) — a rejection falls through to the sandbox's\n * default-template fallback.\n */\nexport interface DeferredNamedTemplateSpec {\n resolveSpec(): Promise<NamedTemplateSpec>;\n}\n\nexport function isDeferredNamedTemplateSpec(spec: TemplateSpec): spec is DeferredNamedTemplateSpec {\n return (\n typeof spec === 'object' &&\n spec !== null &&\n 'resolveSpec' in spec &&\n typeof (spec as DeferredNamedTemplateSpec).resolveSpec === 'function'\n );\n}\n\n/**\n * Result from createMountableTemplate containing both the template and its ID.\n */\nexport interface MountableTemplateResult {\n /** The template builder with mount dependencies */\n template: TemplateBuilder;\n /** Deterministic template ID for caching */\n id: string;\n /** List of apt packages installed in the template */\n aptPackages: string[];\n /**\n * Machine resources baked into the identity, normalized to the defaults.\n * Pass these to the build so the artifact matches the hash.\n */\n resources: Required<TemplateResources>;\n}\n\n/**\n * Version of the default mountable template.\n * Increment this when changing the default template dependencies.\n * v2 added machine resources to the identity hash.\n * v3 installed a pinned current Node LTS over the base image's stale\n * runtime and enabled corepack.\n */\nexport const MOUNTABLE_TEMPLATE_VERSION = 'v3';\n\n/**\n * Create a base template with FUSE mounting dependencies pre-installed.\n *\n * This template includes s3fs and fuse packages required for mounting\n * cloud filesystems (S3, GCS, R2) into the sandbox.\n *\n * The returned `id` is deterministic, allowing E2BSandbox to check if\n * the template already exists before building it.\n *\n * @example Basic usage\n * ```typescript\n * const { template, id } = createMountableTemplate();\n * // First time: builds and caches the template\n * // Subsequent times: reuses existing template\n * const sandbox = new E2BSandbox({ template });\n * ```\n *\n * @example With customization\n * ```typescript\n * const { template } = createMountableTemplate();\n * const customTemplate = template\n * .aptInstall(['nodejs', 'npm'])\n * .runCmd('npm install -g typescript');\n *\n * // Note: customized templates get a unique ID, not the cached one\n * const sandbox = new E2BSandbox({ template: customTemplate });\n * ```\n *\n * @returns Object with template builder and deterministic ID\n */\nexport function createDefaultMountableTemplate(options?: MountableTemplateOptions): MountableTemplateResult {\n const aptPackages = ['s3fs', 'fuse'];\n // Resources are part of the template's identity: each machine size is its\n // own template, so a resize can never silently reuse a build at the old\n // size. Absent and explicitly-default are the same template.\n const cpuCount = options?.cpuCount ?? DEFAULT_CPU_COUNT;\n const memoryMB = options?.memoryMB ?? DEFAULT_MEMORY_MB;\n const nodeVersion = options?.nodeVersion ?? DEFAULT_NODE_VERSION;\n // The version is interpolated into a build shell command below, so it is\n // validated before it can be interpolated into one.\n if (!NODE_VERSION_PATTERN.test(nodeVersion)) {\n throw new Error(`Invalid nodeVersion \"${nodeVersion}\": expected an exact version like \"24.20.0\"`);\n }\n const config = { version: MOUNTABLE_TEMPLATE_VERSION, aptPackages, cpuCount, memoryMB, nodeVersion };\n\n const hash = createHash('sha256')\n .update(JSON.stringify(config, Object.keys(config).sort()))\n .digest('hex')\n .slice(0, 16);\n\n // Build steps and runtime commands both run as the non-root `user` in its\n // home directory — repo checkouts live there (`$HOME/<repo>`), so no\n // extra writable root needs prepping.\n const template = Template()\n .fromTemplate('base')\n .aptInstall(aptPackages)\n // The base image ships a stale Node under /usr/local (v20.9.0 at last\n // check), old enough that corepack-fetched pnpm/yarn crash on it\n // (ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING). Overwrite it in place with\n // a pinned current release so the fresh binaries win the PATH.\n .runCmd(\n `curl -fsSL https://nodejs.org/dist/v${nodeVersion}/node-v${nodeVersion}-linux-x64.tar.gz | sudo tar -xz -C /usr/local --strip-components=1`,\n )\n // Corepack shims make `pnpm`/`yarn` resolve to whatever the repo's\n // `packageManager` field pins. It refuses to download a package manager\n // non-interactively unless the prompt is disabled, so persist that for\n // every session, not just the build shell.\n .runCmd('sudo corepack enable')\n .runCmd(`echo 'COREPACK_ENABLE_DOWNLOAD_PROMPT=0' | sudo tee -a /etc/environment`)\n .setEnvs({ COREPACK_ENABLE_DOWNLOAD_PROMPT: '0' });\n\n // Note: gcsfuse requires adding Google's apt repo which can be flaky\n // For now, we'll install it at mount time if needed\n\n return {\n template,\n id: `mastra-${hash}`,\n aptPackages,\n resources: { cpuCount, memoryMB },\n };\n}\n","/**\n * Shared types for E2B mount operations.\n */\n\nimport type { Sandbox } from 'e2b';\n\nimport type { E2BAzureBlobMountConfig } from './azure';\nimport type { E2BGCSMountConfig } from './gcs';\nimport type { E2BS3MountConfig } from './s3';\n\nexport const LOG_PREFIX = '[@mastra/e2b]';\n\n/**\n * Union of mount configs supported by E2B sandbox.\n */\nexport type E2BMountConfig = E2BS3MountConfig | E2BGCSMountConfig | E2BAzureBlobMountConfig;\n\n/**\n * Context for mount operations.\n */\nexport interface MountContext {\n sandbox: Sandbox;\n logger: {\n debug: (message: string, ...args: unknown[]) => void;\n info: (message: string, ...args: unknown[]) => void;\n warn: (message: string, ...args: unknown[]) => void;\n error: (message: string, ...args: unknown[]) => void;\n };\n}\n\n/**\n * Result of a mount operation.\n */\nexport interface MountOperationResult {\n success: boolean;\n error?: string;\n}\n\nconst SAFE_S3_BUCKET_NAME = /^[a-z0-9][a-z0-9.\\-]{1,61}[a-z0-9]$/;\nconst SAFE_GCS_BUCKET_NAME = /^[a-z0-9][a-z0-9._-]{1,61}[a-z0-9]$/;\n\nexport function validateS3BucketName(bucket: string): void {\n if (!SAFE_S3_BUCKET_NAME.test(bucket)) {\n throw new Error(\n `Invalid S3 bucket name: \"${bucket}\". Bucket names must be 3-63 characters, lowercase alphanumeric, hyphens, or dots.`,\n );\n }\n}\n\nexport function validateGCSBucketName(bucket: string): void {\n if (!SAFE_GCS_BUCKET_NAME.test(bucket)) {\n throw new Error(\n `Invalid GCS bucket name: \"${bucket}\". Bucket names must be 3-63 characters, lowercase alphanumeric, hyphens, underscores, or dots.`,\n );\n }\n}\n\n/**\n * Validate an endpoint URL before interpolating into shell commands.\n */\nexport function validateEndpoint(endpoint: string): void {\n try {\n new URL(endpoint);\n } catch {\n throw new Error(`Invalid endpoint URL: \"${endpoint}\"`);\n }\n}\n\n/**\n * Validate an AWS region (or R2's \"auto\") before interpolating into shell commands.\n * Accepts standard AWS region codes like \"us-east-1\", \"ap-northeast-1\", and \"auto\".\n */\nconst SAFE_REGION = /^[a-z0-9-]{2,32}$/;\n\nexport function validateRegion(region: unknown): asserts region is string {\n if (typeof region !== 'string' || !SAFE_REGION.test(region)) {\n throw new Error(\n `Invalid region: ${JSON.stringify(region)}. Region must be a string of lowercase alphanumeric or hyphens (e.g., \"us-east-1\", \"ap-northeast-1\", \"auto\").`,\n );\n }\n}\n\n/**\n * Validate and normalize a mount prefix before interpolating into shell commands.\n * Returns the normalized prefix (no leading/trailing slashes).\n *\n * Shell safety is handled by shellQuote() at the call site, so this function\n * only enforces path-level rules (no traversal, no empty result, no control chars).\n */\nexport function validatePrefix(prefix: string): string {\n // Trim leading/trailing slashes\n let normalized = prefix;\n while (normalized.startsWith('/')) normalized = normalized.slice(1);\n while (normalized.endsWith('/')) normalized = normalized.slice(0, -1);\n\n if (!normalized) {\n throw new Error('Mount prefix cannot be empty after normalization.');\n }\n if (normalized.includes('//') || normalized.split('/').some(s => s === '.' || s === '..')) {\n throw new Error(`Invalid mount prefix: \"${prefix}\". Path traversal is not allowed.`);\n }\n // Block control characters (U+0000–U+001F, U+007F) which are invalid in filesystem paths\n if (/[\\x00-\\x1f\\x7f]/.test(normalized)) {\n throw new Error(`Invalid mount prefix: \"${prefix}\". Control characters are not allowed.`);\n }\n return normalized;\n}\n","/**\n * Shell-quote a single argument for safe use in a command string.\n *\n * Arguments containing only safe characters are returned as-is.\n * All others are wrapped in single quotes with embedded single quotes escaped.\n */\nexport function shellQuote(arg: string): string {\n // Safe characters that don't need quoting\n if (/^[a-zA-Z0-9._\\-/@:=]+$/.test(arg)) return arg;\n // Wrap in single quotes, escaping any embedded single quotes\n return \"'\" + arg.replace(/'/g, \"'\\\\''\") + \"'\";\n}\n","import { createHash } from 'node:crypto';\n\nimport type { FilesystemMountConfig } from '@mastra/core/workspace';\n\nimport { shellQuote } from '../../utils/shell-quote';\nimport { LOG_PREFIX, validateEndpoint, validatePrefix, validateRegion, validateS3BucketName } from './types';\nimport type { MountContext } from './types';\n\n/**\n * S3 mount config for E2B (mounted via s3fs-fuse).\n *\n * If credentials are not provided, the bucket will be mounted as read-only\n * using the `public_bucket=1` option (for public AWS S3 buckets only).\n *\n * Note: S3-compatible services (R2, MinIO, etc.) always require credentials.\n */\nexport interface E2BS3MountConfig extends FilesystemMountConfig {\n type: 's3';\n /** S3 bucket name */\n bucket: string;\n /** AWS region */\n region: string;\n /** S3 endpoint for S3-compatible storage (MinIO, etc.) */\n endpoint?: string;\n /** AWS access key ID (optional - omit for public buckets) */\n accessKeyId?: string;\n /** AWS secret access key (optional - omit for public buckets) */\n secretAccessKey?: string;\n /**\n * Optional prefix (subdirectory) to mount instead of the entire bucket.\n * Uses s3fs `bucket:/prefix` syntax. Leading/trailing slashes are normalized.\n */\n prefix?: string;\n /** Mount as read-only (even if credentials have write access) */\n readOnly?: boolean;\n}\n\n/**\n * Mount an S3 bucket using s3fs-fuse.\n */\nexport async function mountS3(mountPath: string, config: E2BS3MountConfig, ctx: MountContext): Promise<void> {\n const { sandbox, logger } = ctx;\n\n // Validate inputs before interpolating into shell commands\n validateS3BucketName(config.bucket);\n validateRegion(config.region);\n if (config.endpoint) {\n validateEndpoint(config.endpoint);\n }\n\n // Check if s3fs is installed\n const checkResult = await sandbox.commands.run('which s3fs || echo \"not found\"');\n if (checkResult.stdout.includes('not found')) {\n logger.warn(`${LOG_PREFIX} s3fs not found, attempting runtime installation...`);\n logger.info(\n `${LOG_PREFIX} Tip: For faster startup, use createMountableTemplate() to pre-install s3fs in your sandbox template`,\n );\n\n await sandbox.commands.run('sudo apt-get update 2>&1', { timeoutMs: 60000 });\n\n const installResult = await sandbox.commands.run(\n 'sudo apt-get install -y s3fs fuse 2>&1 || sudo apt-get install -y s3fs-fuse fuse 2>&1',\n { timeoutMs: 120000 },\n );\n\n if (installResult.exitCode !== 0) {\n throw new Error(\n `Failed to install s3fs. ` +\n `For S3 mounting, your template needs s3fs and fuse packages.\\n\\n` +\n `Option 1: Use createMountableTemplate() helper:\\n` +\n ` import { E2BSandbox, createMountableTemplate } from '@mastra/e2b';\\n` +\n ` const sandbox = new E2BSandbox({ template: createMountableTemplate() });\\n\\n` +\n `Option 2: Customize the base template:\\n` +\n ` new E2BSandbox({ template: base => base.aptInstall(['your-packages']) })\\n\\n` +\n `Error details: ${installResult.stderr || installResult.stdout}`,\n );\n }\n }\n\n // Get user's uid/gid for proper file ownership\n const idResult = await sandbox.commands.run('id -u && id -g');\n const [uid, gid] = idResult.stdout.trim().split('\\n');\n\n // Validate credentials before any network calls — this gives the user a clear,\n // immediate error instead of a confusing connectivity failure.\n const hasAccessKey = !!config.accessKeyId;\n const hasSecretKey = !!config.secretAccessKey;\n if (hasAccessKey !== hasSecretKey) {\n throw new Error('Both accessKeyId and secretAccessKey must be provided together.');\n }\n const hasCredentials = hasAccessKey && hasSecretKey;\n\n // Use a per-mount credentials file. s3fs reads `passwd_file` at mount time, so a\n // single shared path (rewritten rm -> write -> chmod on every mount) lets\n // concurrent mounts race: one mount's write/chmod interleaves with another's rm,\n // causing EACCES or a mount reading another mount's credentials. Hashing the\n // mountPath gives each mount a unique, stable file (same approach as azure.ts).\n const mountHash = createHash('md5').update(mountPath).digest('hex').slice(0, 8);\n const credentialsPath = `/tmp/.passwd-s3fs-${mountHash}`;\n\n // S3-compatible services (R2, MinIO, etc.) require credentials\n // public_bucket=1 only works for truly public AWS S3 buckets\n if (!hasCredentials && config.endpoint) {\n throw new Error(\n `S3-compatible storage requires credentials. ` +\n `Detected endpoint: ${config.endpoint}. ` +\n `The public_bucket option only works for AWS S3 public buckets, not R2, MinIO, etc.`,\n );\n }\n\n if (hasCredentials) {\n // Write credentials file (remove old one first to avoid permission issues)\n const credentialsContent = `${config.accessKeyId}:${config.secretAccessKey}`;\n await sandbox.commands.run(`sudo rm -f ${credentialsPath}`);\n await sandbox.files.write(credentialsPath, credentialsContent);\n await sandbox.commands.run(`chmod 600 ${credentialsPath}`);\n }\n\n // Build mount options\n const mountOptions: string[] = [];\n\n if (hasCredentials) {\n mountOptions.push(`passwd_file=${credentialsPath}`);\n } else {\n // Public bucket mode - read-only access without credentials\n mountOptions.push('public_bucket=1');\n logger.debug(`${LOG_PREFIX} No credentials provided, mounting as public bucket (read-only)`);\n }\n\n mountOptions.push('allow_other'); // Allow non-root users to access the mount\n\n // Set uid/gid so mounted files are owned by user, not root\n if (uid && gid) {\n mountOptions.push(`uid=${uid}`, `gid=${gid}`);\n }\n\n if (config.endpoint) {\n // For S3-compatible storage (MinIO, R2, etc.)\n const endpoint = config.endpoint.replace(/\\/$/, '');\n mountOptions.push(`url=${endpoint}`, 'use_path_request_style', 'sigv4', 'nomultipart');\n }\n\n // s3fs's `endpoint` option sets the AWS region used for sigv4 signing\n // (confusingly named — distinct from the URL `endpoint` flag above).\n // Default is us-east-1, which produces SignatureDoesNotMatch errors against\n // buckets in other regions or S3-compatible services that validate the region.\n mountOptions.push(`endpoint=${config.region}`);\n\n if (config.readOnly) {\n mountOptions.push('ro');\n logger.debug(`${LOG_PREFIX} Mounting as read-only`);\n }\n\n // Build the s3fs bucket argument — supports optional prefix via `bucket:/path` syntax\n let bucketArg = config.bucket;\n if (config.prefix) {\n const normalizedPrefix = validatePrefix(config.prefix);\n bucketArg = `${config.bucket}:/${normalizedPrefix}`;\n }\n\n // Mount with sudo (required for /dev/fuse access)\n const mountCmd = `sudo s3fs ${shellQuote(bucketArg)} ${shellQuote(mountPath)} -o ${mountOptions.join(' -o ')}`;\n logger.debug(`${LOG_PREFIX} Mounting S3:`, hasCredentials ? mountCmd.replace(credentialsPath, '***') : mountCmd);\n\n try {\n const result = await sandbox.commands.run(mountCmd, { timeoutMs: 60_000 });\n logger.debug(`${LOG_PREFIX} s3fs result:`, {\n exitCode: result.exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n });\n if (result.exitCode !== 0) {\n throw new Error(`Failed to mount S3 bucket: ${result.stderr || result.stdout}`);\n }\n } catch (error: unknown) {\n const errorObj = error as { result?: { exitCode: number; stdout: string; stderr: string } };\n const stderr = errorObj.result?.stderr || '';\n const stdout = errorObj.result?.stdout || '';\n logger.error(`${LOG_PREFIX} s3fs error:`, { stderr, stdout, error: String(error) });\n throw new Error(`Failed to mount S3 bucket: ${stderr || stdout || error}`);\n }\n\n // s3fs daemonizes before running its FUSE init, where the bucket check happens.\n // If that check fails (wrong region, bad credentials, unsupported endpoint),\n // the daemon exits but the parent has already returned exit code 0.\n // Verify the mount actually attached.\n const verify = await sandbox.commands.run(`mountpoint -q ${shellQuote(mountPath)}`);\n if (verify.exitCode !== 0) {\n throw new Error(\n `s3fs returned exit 0 but ${mountPath} is not a mountpoint. ` +\n `The s3fs daemon likely failed during FUSE init (common causes: region mismatch, ` +\n `invalid credentials, or an S3-compatible endpoint that rejects the signature). ` +\n `Re-run inside the sandbox with '-f -o dbglevel=info' to see the underlying error.`,\n );\n }\n}\n","import { createHash } from 'node:crypto';\n\nimport type { FilesystemMountConfig } from '@mastra/core/workspace';\n\nimport { shellQuote } from '../../utils/shell-quote';\nimport { LOG_PREFIX, validateGCSBucketName, validatePrefix } from './types';\nimport type { MountContext } from './types';\n\n/**\n * GCS mount config for E2B (mounted via gcsfuse).\n *\n * If credentials are not provided, the bucket will be mounted as read-only\n * using anonymous access (for public buckets only).\n */\nexport interface E2BGCSMountConfig extends FilesystemMountConfig {\n type: 'gcs';\n /** GCS bucket name */\n bucket: string;\n /** Service account key JSON (optional - omit for public buckets) */\n serviceAccountKey?: string;\n /**\n * GCS key prefix to scope the mount (without trailing slash).\n * When set, gcsfuse uses --only-dir to mount only this subdirectory, so\n * sandbox paths map directly to prefixed GCS keys.\n */\n prefix?: string;\n}\n\n/**\n * Mount a GCS bucket using gcsfuse.\n *\n * When `config.prefix` is set, gcsfuse uses `--only-dir` to mount only that\n * subdirectory, aligning sandbox paths with the prefixed GCS keys (mirrors the\n * S3 `bucket:/prefix` and Azure `--subdirectory` mounts).\n */\nexport async function mountGCS(mountPath: string, config: E2BGCSMountConfig, ctx: MountContext): Promise<void> {\n const { sandbox, logger } = ctx;\n\n // Validate inputs before interpolating into shell commands\n validateGCSBucketName(config.bucket);\n\n // Install gcsfuse if not present\n const checkResult = await sandbox.commands.run('which gcsfuse || echo \"not found\"');\n if (checkResult.stdout.includes('not found')) {\n // Detect Ubuntu codename for the gcsfuse repo (default to jammy if unknown)\n const codenameResult = await sandbox.commands.run('lsb_release -cs 2>/dev/null || echo jammy');\n const codename = codenameResult.stdout.trim() || 'jammy';\n\n // Use signed-by keyring instead of deprecated apt-key\n await sandbox.commands.run(\n 'curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/gcsfuse.gpg && ' +\n `echo \"deb [signed-by=/etc/apt/keyrings/gcsfuse.gpg] https://packages.cloud.google.com/apt gcsfuse-${codename} main\" | sudo tee /etc/apt/sources.list.d/gcsfuse.list && ` +\n 'sudo apt-get update && sudo apt-get install -y gcsfuse',\n { timeoutMs: 120_000 },\n );\n }\n\n // Get user's uid/gid for proper file ownership\n const idResult = await sandbox.commands.run('id -u && id -g');\n const [uid, gid] = idResult.stdout.trim().split('\\n');\n\n // Build gcsfuse flags\n // Note: gcsfuse uses --uid/--gid flags, not -o uid=X style\n const uidGidFlags = uid && gid ? `--uid=${uid} --gid=${gid}` : '';\n\n // Scope the mount to a subdirectory when a prefix is set (mirrors S3/Azure mounts).\n // validatePrefix normalizes and guards against path traversal; shellQuote guards the shell.\n const onlyDirFlag = config.prefix ? ` --only-dir=${shellQuote(validatePrefix(config.prefix))}` : '';\n\n const hasCredentials = !!config.serviceAccountKey;\n let mountCmd: string;\n\n if (hasCredentials) {\n // Write service account key with root ownership so sudo gcsfuse can read it.\n // Per-mount path (hashed mountPath) so concurrent mounts don't race on a single\n // shared rm -> write -> chmod sequence (same approach as azure.ts).\n const mountHash = createHash('md5').update(mountPath).digest('hex').slice(0, 8);\n const keyPath = `/tmp/gcs-key-${mountHash}.json`;\n await sandbox.commands.run(`sudo rm -f ${keyPath}`);\n await sandbox.files.write(keyPath, config.serviceAccountKey!);\n // Make readable by root (sudo gcsfuse runs as root)\n await sandbox.commands.run(`sudo chown root:root ${keyPath} && sudo chmod 600 ${keyPath}`);\n\n // Mount with credentials using --key-file flag\n // Use sudo for /dev/fuse access (same as s3fs)\n // -o allow_other lets non-root users access the FUSE mount\n mountCmd = `sudo gcsfuse --key-file=${keyPath} -o allow_other ${uidGidFlags}${onlyDirFlag} ${config.bucket} ${mountPath}`;\n } else {\n // Public bucket mode - read-only access without credentials\n // Use --anonymous-access flag (not -o option)\n // Use sudo for /dev/fuse access (same as s3fs)\n logger.debug(`${LOG_PREFIX} No credentials provided, mounting GCS as public bucket (read-only)`);\n\n mountCmd = `sudo gcsfuse --anonymous-access -o allow_other ${uidGidFlags}${onlyDirFlag} ${config.bucket} ${mountPath}`;\n }\n\n logger.debug(`${LOG_PREFIX} Mounting GCS:`, mountCmd);\n\n try {\n const result = await sandbox.commands.run(mountCmd, { timeoutMs: 60_000 });\n logger.debug(`${LOG_PREFIX} gcsfuse result:`, {\n exitCode: result.exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n });\n if (result.exitCode !== 0) {\n throw new Error(`Failed to mount GCS bucket: ${result.stderr || result.stdout}`);\n }\n } catch (error: unknown) {\n const errorObj = error as { result?: { exitCode: number; stdout: string; stderr: string } };\n const stderr = errorObj.result?.stderr || '';\n const stdout = errorObj.result?.stdout || '';\n logger.error(`${LOG_PREFIX} gcsfuse error:`, { stderr, stdout, error: String(error) });\n throw new Error(`Failed to mount GCS bucket: ${stderr || stdout || error}`);\n }\n}\n","import { createHash } from 'node:crypto';\n\nimport type { FilesystemMountConfig } from '@mastra/core/workspace';\n\nimport { shellQuote } from '../../utils/shell-quote';\nimport { LOG_PREFIX, validateEndpoint, validatePrefix } from './types';\nimport type { MountContext } from './types';\n\n/**\n * Azure Blob mount config for E2B (mounted via blobfuse2).\n *\n * Authentication is selected from the first applicable option:\n * 1. `useDefaultCredential` (managed identity, requires running in Azure)\n * 2. `sasToken`\n * 3. `accountKey`\n * 4. `connectionString` (parsed for AccountName/AccountKey/SharedAccessSignature/BlobEndpoint)\n */\nexport interface E2BAzureBlobMountConfig extends FilesystemMountConfig {\n type: 'azure-blob';\n /** Azure Blob container name */\n container: string;\n /** Storage account name (required unless supplied via connectionString) */\n accountName?: string;\n /** Storage account access key */\n accountKey?: string;\n /** Shared Access Signature token (without leading '?') */\n sasToken?: string;\n /** Azure Storage connection string */\n connectionString?: string;\n /** Use DefaultAzureCredential / managed identity (mode: msi) */\n useDefaultCredential?: boolean;\n /** Custom blob endpoint (e.g. for sovereign clouds or Azurite) */\n endpoint?: string;\n /**\n * Optional prefix (subdirectory) to mount instead of the entire container.\n * Uses blobfuse2 --subdirectory. Leading/trailing slashes are normalized.\n */\n prefix?: string;\n /** Mount as read-only */\n readOnly?: boolean;\n}\n\n// Azure container names: 3-63 lowercase alphanumeric chars or hyphens, no leading/\n// trailing hyphen, no consecutive hyphens. Stricter than the generic bucket regex.\nconst SAFE_CONTAINER_NAME = /^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/;\nconst BLOBFUSE2_GITHUB_DEB =\n 'https://github.com/Azure/azure-storage-fuse/releases/download/blobfuse2-2.5.1/blobfuse2-2.5.1-Ubuntu-22.04.x86_64.deb';\n\nfunction validateContainerName(name: string): void {\n if (!SAFE_CONTAINER_NAME.test(name) || name.includes('--')) {\n throw new Error(\n `Invalid Azure container name: \"${name}\". Container names must be 3-63 lowercase alphanumeric characters or hyphens, with no consecutive hyphens.`,\n );\n }\n}\n\ninterface ParsedConnectionString {\n accountName?: string;\n accountKey?: string;\n sasToken?: string;\n endpoint?: string;\n endpointSuffix?: string;\n protocol?: string;\n}\n\nfunction parseConnectionString(cs: string): ParsedConnectionString {\n const out: ParsedConnectionString = {};\n for (const part of cs.split(';')) {\n const eq = part.indexOf('=');\n if (eq === -1) continue;\n const key = part.slice(0, eq).trim();\n const value = part.slice(eq + 1).trim();\n if (!value) continue;\n if (key === 'AccountName') out.accountName = value;\n else if (key === 'AccountKey') out.accountKey = value;\n else if (key === 'SharedAccessSignature') out.sasToken = value;\n else if (key === 'BlobEndpoint') out.endpoint = value;\n else if (key === 'EndpointSuffix') out.endpointSuffix = value;\n else if (key === 'DefaultEndpointsProtocol') out.protocol = value;\n }\n if (!out.endpoint && out.accountName) {\n out.endpoint = `${out.protocol || 'https'}://${out.accountName}.blob.${out.endpointSuffix || 'core.windows.net'}`;\n }\n return out;\n}\n\nfunction yamlString(value: string): string {\n return `\"${value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`;\n}\n\nfunction parseOsRelease(output: string): Record<string, string> {\n const values: Record<string, string> = {};\n for (const line of output.split('\\n')) {\n const eq = line.indexOf('=');\n if (eq === -1) continue;\n const key = line.slice(0, eq);\n const value = line\n .slice(eq + 1)\n .trim()\n .replace(/^\"|\"$/g, '');\n values[key] = value;\n }\n return values;\n}\n\ninterface MicrosoftAptRepo {\n repoUrl: string;\n suite: string;\n}\n\nfunction resolveMicrosoftAptRepos(osReleaseOutput: string): MicrosoftAptRepo[] {\n const osRelease = parseOsRelease(osReleaseOutput);\n const distroId = osRelease.ID || 'ubuntu';\n const codename = osRelease.VERSION_CODENAME || (distroId === 'debian' ? 'bookworm' : 'jammy');\n const versionId = osRelease.VERSION_ID || (distroId === 'debian' ? '12' : '22.04');\n\n if (!/^[a-z0-9][a-z0-9-]*$/.test(codename)) {\n throw new Error(`Invalid distro codename for blobfuse2 repo: \"${codename}\"`);\n }\n if (!/^\\d+(?:\\.\\d+)?$/.test(versionId)) {\n throw new Error(`Invalid distro version for blobfuse2 repo: \"${versionId}\"`);\n }\n\n if (distroId === 'debian') {\n const repos = [\n { repoUrl: `https://packages.microsoft.com/debian/${versionId.split('.')[0]}/prod`, suite: codename },\n ];\n if (versionId.split('.')[0] !== '12' || codename !== 'bookworm') {\n repos.push({ repoUrl: 'https://packages.microsoft.com/debian/12/prod', suite: 'bookworm' });\n }\n return repos;\n }\n if (distroId === 'ubuntu') {\n const repos = [{ repoUrl: `https://packages.microsoft.com/ubuntu/${versionId}/prod`, suite: codename }];\n if (versionId !== '24.04' || codename !== 'noble') {\n repos.push({ repoUrl: 'https://packages.microsoft.com/ubuntu/24.04/prod', suite: 'noble' });\n }\n if (versionId !== '22.04' || codename !== 'jammy') {\n repos.push({ repoUrl: 'https://packages.microsoft.com/ubuntu/22.04/prod', suite: 'jammy' });\n }\n return repos;\n }\n\n throw new Error(`Unsupported distro for blobfuse2 runtime installation: \"${distroId}\"`);\n}\n\ninterface ResolvedAuth {\n mode: 'key' | 'sas' | 'msi';\n accountName: string;\n accountKey?: string;\n sasToken?: string;\n endpoint?: string;\n}\n\nfunction resolveAuth(config: E2BAzureBlobMountConfig): ResolvedAuth {\n let accountName = config.accountName;\n let accountKey = config.accountKey;\n let sasToken = config.sasToken;\n let endpoint = config.endpoint;\n\n if (config.connectionString) {\n const parsed = parseConnectionString(config.connectionString);\n accountName = accountName ?? parsed.accountName;\n accountKey = accountKey ?? parsed.accountKey;\n sasToken = sasToken ?? parsed.sasToken;\n endpoint = endpoint ?? parsed.endpoint;\n }\n\n let mode: 'key' | 'sas' | 'msi';\n if (config.useDefaultCredential) {\n mode = 'msi';\n } else if (sasToken) {\n mode = 'sas';\n } else if (accountKey) {\n mode = 'key';\n } else {\n throw new Error(\n 'Azure Blob mount requires credentials: provide connectionString, accountKey + accountName, sasToken + accountName, or useDefaultCredential.',\n );\n }\n\n if (!accountName) {\n throw new Error('Azure Blob mount requires an accountName (either explicitly or via connectionString).');\n }\n\n if (endpoint) {\n validateEndpoint(endpoint);\n }\n\n return { mode, accountName, accountKey, sasToken, endpoint };\n}\n\nfunction buildBlobfuseConfig(container: string, auth: ResolvedAuth, cachePath: string, readOnly: boolean): string {\n const lines: string[] = [\n 'allow-other: true',\n 'foreground: false',\n `read-only: ${readOnly ? 'true' : 'false'}`,\n 'logging:',\n ' type: silent',\n 'components:',\n ' - libfuse',\n ' - file_cache',\n ' - attr_cache',\n ' - azstorage',\n 'libfuse:',\n ' attribute-expiration-sec: 240',\n ' entry-expiration-sec: 240',\n ' negative-entry-expiration-sec: 120',\n 'file_cache:',\n ` path: ${yamlString(cachePath)}`,\n ' timeout-sec: 120',\n 'attr_cache:',\n ' timeout-sec: 7200',\n 'azstorage:',\n ` mode: ${auth.mode}`,\n ` account-name: ${yamlString(auth.accountName)}`,\n ` container: ${yamlString(container)}`,\n ];\n if (auth.mode === 'key' && auth.accountKey) {\n lines.push(` account-key: ${yamlString(auth.accountKey)}`);\n } else if (auth.mode === 'sas' && auth.sasToken) {\n lines.push(` sas: ${yamlString(auth.sasToken)}`);\n }\n if (auth.endpoint) {\n lines.push(` endpoint: ${yamlString(auth.endpoint.replace(/\\/$/, ''))}`);\n }\n return lines.join('\\n') + '\\n';\n}\n\n/**\n * Mount an Azure Blob container using blobfuse2.\n */\nexport async function mountAzure(mountPath: string, config: E2BAzureBlobMountConfig, ctx: MountContext): Promise<void> {\n const { sandbox, logger } = ctx;\n\n validateContainerName(config.container);\n const auth = resolveAuth(config);\n const prefix = config.prefix ? validatePrefix(config.prefix) : undefined;\n\n // Install blobfuse2 if not present. Prefer Microsoft apt packages and fall\n // back to the official Azure GitHub release when the repo is unavailable.\n const checkResult = await sandbox.commands.run('which blobfuse2 || echo \"not found\"');\n if (checkResult.stdout.includes('not found')) {\n logger.warn(`${LOG_PREFIX} blobfuse2 not found, attempting runtime installation...`);\n logger.info(\n `${LOG_PREFIX} Tip: For faster startup, pre-install blobfuse2 in your sandbox template via createMountableTemplate()`,\n );\n\n const osReleaseResult = await sandbox.commands.run('cat /etc/os-release 2>/dev/null || true');\n const repos = resolveMicrosoftAptRepos(osReleaseResult.stdout);\n\n const repoSetupResult = await sandbox.commands.run(\n 'sudo mkdir -p /etc/apt/keyrings && ' +\n 'curl --retry 3 --retry-all-errors --retry-delay 2 -fsSL https://packages.microsoft.com/keys/microsoft.asc -o /tmp/ms-key.asc && ' +\n 'sudo gpg --batch --yes --dearmor -o /etc/apt/keyrings/microsoft.gpg /tmp/ms-key.asc',\n { timeoutMs: 60_000 },\n );\n\n let installResult: { exitCode: number; stdout: string; stderr: string } | undefined;\n if (repoSetupResult.exitCode === 0) {\n for (const { repoUrl, suite } of repos) {\n installResult = await sandbox.commands.run(\n `echo \"deb [signed-by=/etc/apt/keyrings/microsoft.gpg] ${repoUrl} ${suite} main\" | sudo tee /etc/apt/sources.list.d/microsoft-prod.list && ` +\n 'sudo apt-get update 2>&1 && sudo apt-get install -y blobfuse2 fuse3 2>&1',\n { timeoutMs: 180_000 },\n );\n if (installResult.exitCode === 0) break;\n logger.warn(`${LOG_PREFIX} blobfuse2 install failed for ${repoUrl} ${suite}, trying fallback if available`);\n }\n } else {\n logger.warn(`${LOG_PREFIX} Failed to set up Microsoft apt repository, trying GitHub release fallback`);\n }\n\n let verifyResult = await sandbox.commands.run('which blobfuse2 && blobfuse2 --version', { timeoutMs: 30_000 });\n if (verifyResult.exitCode !== 0) {\n installResult = await sandbox.commands.run(\n 'sudo apt-get update -qq 2>&1 || true && ' +\n 'sudo apt-get install -y fuse3 ca-certificates curl 2>&1 && ' +\n `curl -L --retry 3 --retry-all-errors --retry-delay 2 -fSLo /tmp/blobfuse2.deb ${BLOBFUSE2_GITHUB_DEB} && ` +\n 'sudo dpkg -i /tmp/blobfuse2.deb 2>&1 && ' +\n 'sudo bash -c \\'lib=$(find /usr/lib -name \"libfuse3.so.3.*\" | head -1); [ -z \"$lib\" ] || ln -sf \"$lib\" /usr/lib/x86_64-linux-gnu/libfuse3.so.3\\'',\n { timeoutMs: 180_000 },\n );\n verifyResult = await sandbox.commands.run('which blobfuse2 && blobfuse2 --version', { timeoutMs: 30_000 });\n }\n\n if (!installResult || verifyResult.exitCode !== 0) {\n throw new Error(\n `Failed to install blobfuse2. ` +\n `For Azure Blob mounting, your template needs blobfuse2 and fuse3.\\n\\n` +\n `Option 1: Use createMountableTemplate() helper:\\n` +\n ` import { E2BSandbox, createMountableTemplate } from '@mastra/e2b';\\n` +\n ` const sandbox = new E2BSandbox({ template: createMountableTemplate() });\\n\\n` +\n `Option 2: Customize the base template:\\n` +\n ` new E2BSandbox({ template: base => base.aptInstall(['your-packages']) })\\n\\n` +\n `Error details: ${\n verifyResult.stderr ||\n verifyResult.stdout ||\n installResult?.stderr ||\n installResult?.stdout ||\n 'unknown error'\n }`,\n );\n }\n }\n\n const mountHash = createHash('md5').update(mountPath).digest('hex').slice(0, 8);\n const configPath = `/tmp/.blobfuse2-config-${mountHash}.yaml`;\n const cachePath = `/tmp/blobfuse2-cache-${mountHash}`;\n const yaml = buildBlobfuseConfig(config.container, auth, cachePath, !!config.readOnly);\n\n // Write config (root-owned, 0600) since blobfuse2 runs as root via sudo for /dev/fuse access.\n await sandbox.commands.run(`sudo rm -f ${configPath}`);\n await sandbox.files.write(configPath, yaml);\n await sandbox.commands.run(`sudo chown root:root ${configPath} && sudo chmod 600 ${configPath}`);\n\n // blobfuse2 requires an empty cache directory when mounting.\n await sandbox.commands.run(`sudo rm -rf ${shellQuote(cachePath)} && sudo mkdir -p ${shellQuote(cachePath)}`);\n\n const prefixFlags = prefix ? ` --virtual-directory=true --subdirectory=${shellQuote(prefix)}` : '';\n const mountCmd = `sudo blobfuse2 mount ${shellQuote(mountPath)} --config-file=${shellQuote(configPath)}${prefixFlags}`;\n logger.debug(`${LOG_PREFIX} Mounting Azure Blob:`, mountCmd);\n\n try {\n const result = await sandbox.commands.run(mountCmd, { timeoutMs: 60_000 });\n logger.debug(`${LOG_PREFIX} blobfuse2 result:`, {\n exitCode: result.exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n });\n if (result.exitCode !== 0) {\n throw new Error(`Failed to mount Azure Blob container: ${result.stderr || result.stdout}`);\n }\n } catch (error: unknown) {\n const errorObj = error as { result?: { exitCode: number; stdout: string; stderr: string } };\n const stderr = errorObj.result?.stderr || '';\n const stdout = errorObj.result?.stdout || '';\n logger.error(`${LOG_PREFIX} blobfuse2 error:`, { stderr, stdout, error: String(error) });\n throw new Error(`Failed to mount Azure Blob container: ${stderr || stdout || error}`);\n }\n}\n","/**\n * E2B Process Manager\n *\n * Implements SandboxProcessManager for E2B cloud sandboxes.\n * Wraps the E2B SDK's commands API (background mode, sendStdin, kill, list).\n */\n\nimport { ProcessHandle, UnsupportedStdinCloseError, SandboxProcessManager } from '@mastra/core/workspace';\nimport type { CommandResult, ProcessInfo, SpawnProcessOptions } from '@mastra/core/workspace';\nimport type { CommandHandle as E2BCommandHandle, Sandbox } from 'e2b';\nimport type { E2BSandbox } from './index';\n\n// =============================================================================\n// E2B Process Handle\n// =============================================================================\n\n/**\n * Wraps an E2B CommandHandle to conform to Mastra's ProcessHandle.\n * Not exported — internal to this module.\n *\n * Listener dispatch is handled by the base class. The manager's spawn()/get()\n * methods wire E2B's constructor-time callbacks to handle.emitStdout/emitStderr.\n */\nclass E2BProcessHandle extends ProcessHandle {\n readonly pid: string;\n\n private readonly _e2bHandle: E2BCommandHandle;\n private readonly _sandbox: Sandbox;\n private readonly _startTime: number;\n private readonly _stdinMode: SpawnProcessOptions['stdinMode'];\n\n constructor(e2bHandle: E2BCommandHandle, sandbox: Sandbox, startTime: number, options?: SpawnProcessOptions) {\n super(options);\n this.pid = String(e2bHandle.pid);\n this._e2bHandle = e2bHandle;\n this._sandbox = sandbox;\n this._startTime = startTime;\n this._stdinMode = options?.stdinMode;\n }\n\n /** Delegates to E2B's handle so exitCode reflects server-side state without needing wait(). */\n get exitCode(): number | undefined {\n return this._e2bHandle.exitCode;\n }\n\n async wait(): Promise<CommandResult> {\n try {\n const result = await this._e2bHandle.wait();\n return {\n success: result.exitCode === 0,\n exitCode: result.exitCode,\n stdout: this.stdout,\n stderr: this.stderr,\n executionTimeMs: Date.now() - this._startTime,\n };\n } catch (error) {\n // E2B throws CommandExitError for non-zero exit codes (has .exitCode directly)\n // Some E2B errors also carry stdout/stderr in error.result\n const errorObj = error as {\n exitCode?: number;\n error?: string;\n stdout?: string;\n stderr?: string;\n result?: { exitCode: number; error?: string; stdout: string; stderr: string };\n };\n const exitCode = errorObj.result?.exitCode ?? errorObj.exitCode ?? this.exitCode ?? 1;\n\n // If E2B skipped the stream callbacks, retain and dispatch its attached\n // output through the normal path so maxRetainedBytes still applies.\n const attachedStdout = errorObj.result?.stdout || errorObj.stdout;\n const attachedStderr = errorObj.result?.stderr || errorObj.stderr;\n if (!this.stdout && !this.stdoutTruncated && attachedStdout) this.emitStdout(attachedStdout);\n if (!this.stderr && !this.stderrTruncated && attachedStderr) this.emitStderr(attachedStderr);\n\n const stdout = this.stdout;\n const stderr = this.stderr;\n const terminalError =\n errorObj.result?.error || errorObj.error || (error instanceof Error ? error.message : String(error));\n const errorDetail = terminalError && !stderr.includes(terminalError) ? `Error: ${terminalError}` : '';\n\n return {\n success: false,\n exitCode,\n stdout,\n stderr: [stderr, errorDetail].filter(Boolean).join('\\n'),\n executionTimeMs: Date.now() - this._startTime,\n };\n }\n }\n\n async kill(): Promise<boolean> {\n if (this.exitCode !== undefined) return false;\n return this._e2bHandle.kill();\n }\n\n async sendStdin(data: string): Promise<void> {\n if (this.exitCode !== undefined) {\n throw new Error(`Process ${this.pid} has already exited with code ${this.exitCode}`);\n }\n // Spawned with `stdinMode: 'ignore'`, so the command was started with\n // stdin detached and there is nothing to write to. Match the local and\n // Docker handles, which reject rather than posting an input RPC to a\n // process that has no stdin channel.\n if (this._stdinMode === 'ignore') {\n throw new Error(`Process ${this.pid} was not started with stdin support`);\n }\n await this._sandbox.commands.sendStdin(this._e2bHandle.pid, data);\n }\n\n async closeStdin(): Promise<void> {\n throw new UnsupportedStdinCloseError('E2B SDK does not expose a way to close stdin for a running command');\n }\n}\n\n// =============================================================================\n// E2B Process Manager\n// =============================================================================\n\n/**\n * E2B implementation of SandboxProcessManager.\n * Uses the E2B SDK's commands.run() with background: true.\n */\nexport interface E2BProcessManagerOptions {\n /** Default timeout in milliseconds for commands that don't specify one. */\n defaultTimeout?: number;\n}\n\nexport class E2BProcessManager extends SandboxProcessManager<E2BSandbox> {\n private readonly _defaultTimeout?: number;\n\n constructor(opts: E2BProcessManagerOptions = {}) {\n super();\n this._defaultTimeout = opts.defaultTimeout;\n }\n\n async spawn(command: string, options: SpawnProcessOptions = {}): Promise<ProcessHandle> {\n return this.sandbox.retryOnDead(async () => {\n const e2b = this.sandbox.e2b;\n\n // The base spawn wrapper already merged the sandbox env into options.env\n const mergedEnv = { ...options.env };\n const envs = Object.fromEntries(\n Object.entries(mergedEnv).filter((entry): entry is [string, string] => entry[1] !== undefined),\n );\n\n // Deferred reference — E2B requires callbacks at run() time, but data\n // arrives asynchronously after the promise resolves, so handle is always\n // assigned by the time the first callback fires.\n let handle: E2BProcessHandle;\n\n const e2bHandle = await e2b.commands.run(command, {\n background: true,\n // `stdinMode: 'ignore'` closes stdin at spawn so a command that reads it\n // (a bare `rg`/`grep`/`cat` with no path argument) sees EOF and exits\n // instead of blocking forever. Callers that drive stdin (`spawn` for an\n // LSP server) keep the default attached stdin.\n stdin: options.stdinMode !== 'ignore',\n cwd: options.cwd ?? this.sandbox.workingDirectory,\n envs,\n // Without this the E2B SDK falls back to its own 60s connection\n // deadline, which bounds the whole streaming command lifetime and kills\n // any command that runs longer than a minute.\n timeoutMs: options.timeout ?? this._defaultTimeout,\n onStdout: (data: string) => handle.emitStdout(data),\n onStderr: (data: string) => handle.emitStderr(data),\n });\n\n handle = new E2BProcessHandle(e2bHandle, e2b, Date.now(), options);\n this._tracked.set(handle.pid, handle);\n return handle;\n });\n }\n\n /**\n * List processes by querying E2B's commands API.\n * E2B manages all state server-side — no local tracking needed.\n */\n async list(): Promise<ProcessInfo[]> {\n const e2b = this.sandbox.e2b;\n const procs = await e2b.commands.list();\n return procs.map(proc => ({\n pid: String(proc.pid),\n command: [proc.cmd, ...proc.args].join(' '),\n running: true, // E2B only lists running processes\n }));\n }\n\n /**\n * Get a handle to a process by PID.\n * Checks base class tracking first, then falls back to commands.connect()\n * for processes spawned externally or before reconnection.\n */\n async get(pid: string): Promise<ProcessHandle | undefined> {\n const tracked = this._tracked.get(pid);\n if (tracked) return tracked;\n\n // Fall back to connect() for unknown PIDs (e.g., pre-existing processes).\n // E2B uses numeric PIDs; parse numeric strings for the SDK call.\n const numericPid = /^\\d+$/.test(pid) ? Number(pid) : undefined;\n if (numericPid === undefined) return undefined;\n\n const e2b = this.sandbox.e2b;\n let handle: E2BProcessHandle;\n try {\n const e2bHandle = await e2b.commands.connect(numericPid, {\n onStdout: (data: string) => handle.emitStdout(data),\n onStderr: (data: string) => handle.emitStderr(data),\n });\n handle = new E2BProcessHandle(e2bHandle, e2b, Date.now());\n this._tracked.set(handle.pid, handle);\n return handle;\n } catch {\n return undefined;\n }\n }\n}\n","/**\n * E2B Sandbox Provider\n *\n * A simplified E2B sandbox implementation that supports mounting\n * cloud filesystems (S3, GCS, R2) via FUSE.\n *\n * @see https://e2b.dev/docs\n */\n\nimport type { RequestContext } from '@mastra/core/di';\nimport type {\n SandboxInfo,\n WorkspaceFilesystem,\n MountResult,\n FilesystemMountConfig,\n ProviderStatus,\n MountManager,\n MastraSandboxOptions,\n SandboxFileInput,\n SandboxNetworking,\n SandboxCloneOptions,\n SandboxStartResult,\n} from '@mastra/core/workspace';\n\n/**\n * Inlined from `@mastra/core/workspace` to avoid requiring a newer core peer dep.\n */\ntype InstructionsOption = string | ((opts: { defaultInstructions: string; requestContext?: RequestContext }) => string);\nimport { MastraSandbox, SandboxNotReadyError, assertModesUnsupported } from '@mastra/core/workspace';\nimport { Sandbox, Template } from 'e2b';\nimport type {\n BuildOptions,\n SandboxConnectOpts,\n SandboxInfo as E2BSandboxListInfo,\n SandboxLifecycle,\n SandboxNetworkOpts,\n SandboxOpts,\n TemplateBuilder,\n TemplateClass,\n} from 'e2b';\nimport { createDefaultMountableTemplate, isDeferredNamedTemplateSpec, isNamedTemplateSpec } from '../utils/template';\nimport type { DeferredNamedTemplateSpec, NamedTemplateSpec, TemplateResources, TemplateSpec } from '../utils/template';\nimport { mountS3, mountGCS, mountAzure, LOG_PREFIX } from './mounts';\nimport type {\n E2BMountConfig,\n E2BS3MountConfig,\n E2BGCSMountConfig,\n E2BAzureBlobMountConfig,\n MountContext,\n} from './mounts';\nimport { E2BProcessManager } from './process-manager';\n\n/** Allowlist pattern for mount paths — absolute path with safe characters only. */\nconst SAFE_MOUNT_PATH = /^\\/[a-zA-Z0-9_.\\-/]+$/;\n\nfunction validateMountPath(mountPath: string): void {\n if (!SAFE_MOUNT_PATH.test(mountPath)) {\n throw new Error(\n `Invalid mount path: ${mountPath}. Must be an absolute path with alphanumeric, dash, dot, underscore, or slash characters only.`,\n );\n }\n}\n\n/** Allowlist for marker filenames from ls output — e.g. \"mount-abc123\" */\nconst SAFE_MARKER_NAME = /^mount-[a-z0-9]+$/;\n\n/**\n * Per-process dedupe of background template rebuild triggers, keyed by\n * template ref. Retained on successful trigger (the ref only ever needs one\n * build; once it exists the exists-check short-circuits before this path),\n * cleared on trigger failure so a later start can retry.\n */\nconst inFlightBackgroundBuilds = new Set<string>();\n\n// =============================================================================\n// E2B Sandbox Options\n// =============================================================================\n\n/**\n * E2B sandbox provider configuration.\n */\nexport interface E2BSandboxOptions extends Omit<MastraSandboxOptions, 'processes'> {\n /** Unique identifier for this sandbox instance */\n id?: string;\n /**\n * Persisted E2B provider sandbox ID to reattach to deterministically.\n *\n * When set, `start()` first queries this exact sandbox and connects to it\n * (resuming it if paused) instead of discovering by logical `id` metadata.\n * Only a typed \"sandbox gone\" error (not found / killed / not running)\n * falls through to the usual logical-id lookup and create ladder;\n * auth, quota, rate-limit, timeout, and network errors propagate without\n * creating a new sandbox.\n */\n sandboxId?: string;\n /**\n * Sandbox template specification.\n *\n * - `string` - Use an existing template by ID\n * - `TemplateBuilder` - Use a custom template (e.g., from `createMountableTemplate()`)\n * - `(base) => base.aptInstall([...])` - Customize the default mountable template\n *\n * If not provided and mounting is used, a default template with s3fs will be built.\n * For best performance, pre-build your template and use the template ID.\n *\n * @see createDefaultMountableTemplate\n */\n template?: TemplateSpec;\n /** Execution timeout in milliseconds\n *\n * @default 300_000 // 5 minutes\n */\n timeout?: number;\n /** Environment variables to set in the sandbox */\n env?: Record<string, string>;\n /** Custom metadata */\n metadata?: Record<string, unknown>;\n /** Network configuration to use when creating the E2B sandbox */\n network?: SandboxNetworkOpts;\n /**\n * Sandbox lifecycle behavior when the `timeout` is reached.\n *\n * Defaults to `{ onTimeout: 'pause' }`, which snapshots the sandbox so the\n * next `start()` reconnects and resumes it. Pass `{ onTimeout: 'kill' }` for\n * stateless workspaces whose data lives outside the sandbox (e.g. mounted\n * from S3) — idle sandboxes are then destroyed and recreated on next use\n * instead of retained as paused snapshots.\n *\n * Note: an explicit `stop()` always pauses, regardless of this setting.\n */\n lifecycle?: SandboxLifecycle;\n\n /** Domain for self-hosted E2B. Falls back to E2B_DOMAIN env var. */\n domain?: string;\n /** API URL for self-hosted E2B. Falls back to E2B_API_URL env var. */\n apiUrl?: string;\n /** API key for authentication. Falls back to E2B_API_KEY env var. */\n apiKey?: string;\n /** Access token for authentication. Falls back to E2B_ACCESS_TOKEN env var. */\n accessToken?: string;\n /**\n * Custom instructions that override the default instructions\n * returned by `getInstructions()`.\n *\n * - `string` — Fully replaces the default instructions.\n * Pass an empty string to suppress instructions entirely.\n * - `(opts) => string` — Receives the default instructions and\n * optional request context so you can extend or customise per-request.\n */\n instructions?: InstructionsOption;\n}\n\n// =============================================================================\n// E2B Sandbox Implementation\n// =============================================================================\n\n/**\n * Simplified E2B sandbox implementation.\n *\n * Features:\n * - Single sandbox instance lifecycle\n * - Supports mounting cloud filesystems (S3, GCS, R2) via FUSE\n * - Automatic sandbox timeout handling with retry\n *\n * @example Basic usage\n * ```typescript\n * import { Workspace } from '@mastra/core/workspace';\n * import { E2BSandbox } from '@mastra/e2b';\n *\n * const sandbox = new E2BSandbox({\n * timeout: 60000,\n * });\n *\n * const workspace = new Workspace({ sandbox });\n * const result = await workspace.executeCode('console.log(\"Hello!\")');\n * ```\n *\n * @example With S3 filesystem mounting\n * ```typescript\n * import { Workspace } from '@mastra/core/workspace';\n * import { E2BSandbox } from '@mastra/e2b';\n * import { S3Filesystem } from '@mastra/s3';\n *\n * const workspace = new Workspace({\n * mounts: {\n * '/bucket': new S3Filesystem({\n * bucket: 'my-bucket',\n * region: 'us-east-1',\n * }),\n * },\n * sandbox: new E2BSandbox({ timeout: 60000 }),\n * });\n *\n * ```\n */\nexport class E2BSandbox extends MastraSandbox<Sandbox> {\n readonly id: string;\n readonly name: string = 'E2BSandbox';\n readonly provider: string = 'e2b';\n status: ProviderStatus = 'pending';\n\n declare readonly mounts: MountManager; // Non-optional (initialized by BaseSandbox)\n declare readonly processes: E2BProcessManager;\n\n /**\n * Networking capability: public HTTPS URLs for sandbox ports.\n * E2B exposes every port via `getHost(port)` — no upfront declaration needed.\n *\n * When not attached in this process, the URL is resolved by looking up the\n * existing sandbox by identity (without resuming it) and deriving the host\n * (`{port}-{sandboxId}.{domain}`), so other processes can resolve\n * deployments without waking a paused sandbox.\n */\n readonly networking: SandboxNetworking = {\n getPortUrl: async (port: number): Promise<string | null> => {\n try {\n if (this._sandbox) {\n return `https://${this._sandbox.getHost(port)}`;\n }\n const info = await this.lookupExistingSandboxInfo();\n if (!info) return null;\n return `https://${port}-${info.sandboxId}.${this.sandboxDomain}`;\n } catch {\n return null;\n }\n },\n };\n\n protected _sandbox: Sandbox | null = null;\n private _createdAt: Date | null = null;\n private _isRetrying = false;\n private readonly timeout: number;\n protected readonly templateSpec?: TemplateSpec;\n private readonly metadata: Record<string, unknown>;\n private readonly network?: SandboxNetworkOpts;\n private readonly lifecycle: SandboxLifecycle;\n protected readonly connectionOpts: Record<string, string>;\n private readonly _preferredSandboxId?: string;\n private readonly _instructionsOverride?: InstructionsOption;\n private readonly _constructorOptions: E2BSandboxOptions;\n\n /**\n * Resolved template ID after building (if needed). The single cache for\n * template resolution: `resolveTemplate()` returns it when set, and the\n * create-time fallback ladder rewrites it to whichever template actually\n * produced a sandbox.\n *\n * `protected` so a subclass with its own default template (e.g. desktop\n * sandboxes) shares the same cache when it overrides `resolveTemplate()`.\n */\n protected _resolvedTemplateId?: string;\n /**\n * The named spec a deferred template spec resolved to — kept so the\n * 404-on-create fallback ladder can walk the same name/fallback rungs it\n * would for a plain named spec.\n */\n private _resolvedNamedSpec?: NamedTemplateSpec;\n\n constructor(options: E2BSandboxOptions = {}) {\n super({\n ...options,\n name: 'E2BSandbox',\n processes: new E2BProcessManager({\n defaultTimeout: options.timeout ?? 300_000,\n }),\n });\n\n this.id = options.id ?? this.generateId();\n this.timeout = options.timeout ?? 300_000; // 5 minutes;\n this.templateSpec = options.template;\n this.metadata = options.metadata ?? {};\n this.network = options.network;\n // Always sent explicitly: the E2B API defaults to 'kill' when lifecycle is omitted.\n this.lifecycle = options.lifecycle ?? { onTimeout: 'pause' };\n this.connectionOpts = {\n ...(options.domain && { domain: options.domain }),\n ...(options.apiUrl && { apiUrl: options.apiUrl }),\n ...(options.apiKey && { apiKey: options.apiKey }),\n ...(options.accessToken && { accessToken: options.accessToken }),\n };\n\n this._preferredSandboxId = options.sandboxId;\n this._instructionsOverride = options.instructions;\n this._constructorOptions = { ...options };\n }\n\n /**\n * Construct a sibling `E2BSandbox` that inherits this sandbox's\n * configuration (credentials, template, network, metadata, instructions)\n * with per-instance overrides.\n *\n * Performs no I/O — the sandbox clone provisions (or reconnects to an\n * existing E2B sandbox with the same logical `id`) on its own `start()`.\n * Use it when one configured sandbox acts as the template for a fleet of\n * independent sandboxes (e.g. one per project).\n *\n * `options.idleTimeoutMinutes` maps to the E2B sandbox `timeout` (ms);\n * `options.sandboxId` reattaches the clone to that exact E2B sandbox on\n * `start()`. The parent's own preferred provider sandbox ID is never\n * inherited — physical identity is per-instance.\n */\n clone(options: SandboxCloneOptions = {}): E2BSandbox {\n const { id: _id, sandboxId: _sandboxId, ...base } = this._constructorOptions;\n return new E2BSandbox({\n ...base,\n ...(options.id !== undefined && { id: options.id }),\n ...(options.sandboxId !== undefined && { sandboxId: options.sandboxId }),\n ...(options.env !== undefined && { env: options.env }),\n ...(options.idleTimeoutMinutes !== undefined && { timeout: options.idleTimeoutMinutes * 60_000 }),\n });\n }\n\n /**\n * Get the underlying E2B Sandbox instance for direct access to E2B APIs.\n *\n * Use this when you need to access E2B features not exposed through the\n * WorkspaceSandbox interface (e.g., files API, ports, etc.).\n *\n * @throws {SandboxNotReadyError} If the sandbox has not been started\n *\n * @example Direct file operations\n * ```typescript\n * const e2b = sandbox.e2b;\n * await e2b.files.write('/tmp/test.txt', 'Hello');\n * const content = await e2b.files.read('/tmp/test.txt');\n * const files = await e2b.files.list('/tmp');\n * ```\n *\n * @example Access ports\n * ```typescript\n * const e2b = sandbox.e2b;\n * const url = e2b.getHost(3000);\n * ```\n */\n get e2b(): Sandbox {\n if (!this._sandbox) {\n throw new SandboxNotReadyError(this.id);\n }\n return this._sandbox;\n }\n\n /**\n * The E2B provider sandbox ID resolved after connect or create.\n *\n * Persist this to reattach deterministically later via the `sandboxId`\n * option (or `clone({ sandboxId })`). Undefined until the sandbox has been\n * started (attached) in this process.\n */\n get sandboxId(): string | undefined {\n return this._sandbox?.sandboxId;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n /**\n * Acquisition primitives (base-orchestrated start): the base derives\n * `outcome: 'created'` only when a brand-new sandbox VM was created;\n * reconnecting (including resuming a paused sandbox) is `outcome: 'connected'`.\n *\n * `find` returns an already-connected E2B handle: `Sandbox.connect`\n * resumes paused sandboxes, and its failures are deliberately swallowed\n * (unusable handle → create fresh) — that forgiveness is this provider's\n * policy, so it lives here rather than in `connect`. The exception is the\n * `sandboxId` reattach inside {@link acquireExistingSandbox}, which is\n * fail-closed: only a \"sandbox gone\" error falls through to discovery.\n */\n protected override async find(): Promise<Sandbox | undefined> {\n // Already have a sandbox instance\n if (this._sandbox) {\n return this._sandbox;\n }\n return (await this.acquireExistingSandbox()) ?? undefined;\n }\n\n protected override async connect(existingSandbox: Sandbox): Promise<void> {\n if (existingSandbox === this._sandbox) {\n return;\n }\n this._sandbox = existingSandbox;\n this._createdAt = new Date();\n this.logger.debug(`${LOG_PREFIX} Reconnected to existing sandbox for: ${this.id}`);\n\n // Clean up stale mounts from previous config\n // (processPending is called by base class after start completes)\n const expectedPaths = Array.from(this.mounts.entries.keys());\n this.logger.debug(`${LOG_PREFIX} Running mount reconciliation...`);\n await this.reconcileMounts(expectedPaths);\n this.logger.debug(`${LOG_PREFIX} Mount reconciliation complete`);\n }\n\n protected override async create(): Promise<void> {\n // Template resolution happens here — never at construction or during a\n // reconnect — so a sandbox that only ever resumes never triggers a\n // template build. `resolveTemplate()` caches via `_resolvedTemplateId`.\n const resolvedTemplateId = await this.resolveTemplate();\n\n // Create a new sandbox with our logical ID in metadata.\n // lifecycle defaults to onTimeout: 'pause', which pauses the sandbox on timeout instead of\n // destroying it so the next start() can resume it. Callers can override it (e.g. 'kill').\n this.logger.debug(`${LOG_PREFIX} Creating new sandbox for: ${this.id} with template: ${resolvedTemplateId}`);\n\n const createOpts: SandboxOpts = {\n ...this.connectionOpts,\n lifecycle: this.lifecycle,\n metadata: {\n ...this.metadata,\n 'mastra-sandbox-id': this.id,\n },\n ...(this.network && { network: this.network }),\n timeoutMs: this.timeout,\n };\n // Every rung of the fallback ladder goes through `createSdkSandbox` so a\n // provider layered on the E2B SDK (e.g. `@e2b/desktop`) keeps its override\n // on the retries, not just on the first attempt.\n const createFromTemplate = (templateId: string) => this.createSdkSandbox(templateId, createOpts);\n // A 404 from create means the template id cannot produce a sandbox:\n // deleted between resolve and create, or the name was registered by a\n // FAILED build — E2B keeps a failed build's name visible to\n // `Template.exists`, so a broken name would otherwise be reused forever.\n // Only 404s trigger a fallback retry; auth, quota, and network errors\n // propagate (an ambiguous timeout must not create a duplicate VM).\n const isTemplateUnusable = (error: unknown) => String(error).includes('404');\n\n let sdkSandbox: Sandbox;\n try {\n sdkSandbox = await createFromTemplate(resolvedTemplateId);\n } catch (createError) {\n if (!isTemplateUnusable(createError)) throw createError;\n\n const namedSpec =\n this.templateSpec && isNamedTemplateSpec(this.templateSpec) ? this.templateSpec : this._resolvedNamedSpec;\n if (namedSpec) {\n // Bounded ladder: broken name → named fallback → default mountable\n // template. Every rung only advances on a template-unusable error, so\n // a broken build never wedges the session on a dead name.\n this.logger.warn(\n `${LOG_PREFIX} Creating from '${resolvedTemplateId}' failed, retrying on fallback: ${createError}`,\n );\n this._resolvedTemplateId = undefined;\n const spec = namedSpec;\n const fallbackId =\n resolvedTemplateId === spec.ref\n ? await this.resolveFallbackTemplate(spec.fallbackTemplate)\n : await this.buildOrReuseDefaultTemplate();\n try {\n sdkSandbox = await createFromTemplate(fallbackId);\n // Cache coherence: later creates on this instance (e.g. after the\n // VM died) must reuse the template that actually worked, not\n // re-walk the ladder from the broken name.\n this._resolvedTemplateId = fallbackId;\n } catch (fallbackError) {\n if (!isTemplateUnusable(fallbackError)) throw fallbackError;\n // Terminal recovery: the default name itself may be registered by\n // a FAILED build. Force-rebuild it once (mirrors the no-spec\n // path's 404 recovery) — past this, the error propagates.\n const rebuildDefaultAndCreate = async (): Promise<Sandbox> => {\n this.logger.warn(`${LOG_PREFIX} Default template broken too, rebuilding: ${fallbackError}`);\n const rebuiltId = await this.buildDefaultTemplate();\n const rebuilt = await createFromTemplate(rebuiltId);\n this._resolvedTemplateId = rebuiltId;\n return rebuilt;\n };\n const defaultId = await this.buildOrReuseDefaultTemplate();\n if (defaultId === fallbackId) {\n // The failed fallback WAS the default (specs without a named\n // fallback land on it directly) — skip straight to the rebuild.\n sdkSandbox = await rebuildDefaultAndCreate();\n } else {\n this.logger.warn(`${LOG_PREFIX} Fallback '${fallbackId}' failed too, using default: ${fallbackError}`);\n try {\n sdkSandbox = await createFromTemplate(defaultId);\n this._resolvedTemplateId = defaultId;\n } catch (defaultError) {\n if (!isTemplateUnusable(defaultError)) throw defaultError;\n sdkSandbox = await rebuildDefaultAndCreate();\n }\n }\n }\n this.logger.debug(`${LOG_PREFIX} Created sandbox ${sdkSandbox.sandboxId} from fallback for: ${this.id}`);\n } else if (!this.templateSpec) {\n this.logger.debug(`${LOG_PREFIX} Template not found, rebuilding: ${resolvedTemplateId}`);\n this._resolvedTemplateId = undefined; // Clear cached ID to force rebuild\n const rebuiltTemplateId = await this.buildDefaultTemplate();\n\n this.logger.debug(`${LOG_PREFIX} Retrying sandbox creation with rebuilt template: ${rebuiltTemplateId}`);\n sdkSandbox = await createFromTemplate(rebuiltTemplateId);\n } else {\n throw createError;\n }\n }\n this._sandbox = sdkSandbox;\n\n this.logger.debug(`${LOG_PREFIX} Created sandbox ${sdkSandbox.sandboxId} for logical ID: ${this.id}`);\n this._createdAt = new Date();\n // Note: processPending is called by base class after start completes\n }\n\n /**\n * Stop the E2B sandbox by pausing it (snapshot-stop).\n *\n * Pausing freezes the whole VM — filesystem, memory, and running processes —\n * and stops billing immediately. The next `start()` reconnects and resumes it,\n * with background processes still running. Filesystem mounts are unmounted\n * first (FUSE mounts don't survive pause) and reconciled again on start.\n *\n * Status management is handled by the base class.\n */\n async stop(): Promise<void> {\n // Unmount all filesystems before pausing\n // Collect keys first since unmount() mutates the map\n for (const mountPath of [...this.mounts.entries.keys()]) {\n try {\n await this.unmount(mountPath);\n } catch {\n // Best-effort unmount; sandbox may already be dead\n }\n }\n\n // Pause failures propagate — a sandbox that failed to pause is still\n // running (and billing), so callers must not assume it stopped.\n if (this._sandbox) {\n await this._sandbox.pause();\n this.logger.debug(`${LOG_PREFIX} Paused sandbox ${this._sandbox.sandboxId} for: ${this.id}`);\n } else {\n // Not attached in this process — pause by identity without resuming.\n const info = await this.lookupExistingSandboxInfo();\n if (info?.state === 'running') {\n await Sandbox.pause(info.sandboxId, this.connectionOpts);\n this.logger.debug(`${LOG_PREFIX} Paused detached sandbox ${info.sandboxId} for: ${this.id}`);\n }\n }\n\n this._sandbox = null;\n }\n\n /**\n * Destroy the E2B sandbox and clean up all resources.\n * Unmounts filesystems, kills the sandbox, and clears mount state.\n * Status management is handled by the base class.\n */\n async destroy(): Promise<void> {\n if (this._sandbox) {\n // Kill all background processes\n try {\n const procs = await this.processes.list();\n await Promise.all(procs.map(p => this.processes.kill(p.pid)));\n } catch {\n // Best-effort: sandbox may already be dead\n }\n\n // Unmount all filesystems\n // Collect keys first since unmount() mutates the map\n for (const mountPath of [...this.mounts.entries.keys()]) {\n try {\n await this.unmount(mountPath);\n } catch {\n // Ignore errors during cleanup\n }\n }\n\n // Kill failures propagate — a sandbox that failed to delete is still\n // alive, so callers must not assume cleanup completed.\n await this._sandbox.kill();\n\n this._sandbox = null;\n } else {\n // Not attached in this process — kill by identity without resuming.\n const info = await this.lookupExistingSandboxInfo();\n if (info) {\n await Sandbox.kill(info.sandboxId, this.connectionOpts);\n this.logger.debug(`${LOG_PREFIX} Killed detached sandbox ${info.sandboxId} for: ${this.id}`);\n }\n }\n\n this.mounts.clear();\n }\n\n async getInfo(): Promise<SandboxInfo> {\n return {\n id: this.id,\n name: this.name,\n provider: this.provider,\n status: this.status,\n createdAt: this._createdAt ?? new Date(),\n mounts: Array.from(this.mounts.entries).map(([path, entry]) => ({\n path,\n filesystem: entry.filesystem?.provider ?? entry.config?.type ?? 'unknown',\n })),\n metadata: {\n ...this.metadata,\n ...(this._sandbox && { sandboxId: this._sandbox.sandboxId }),\n },\n };\n }\n\n // ---------------------------------------------------------------------------\n // File Upload\n // ---------------------------------------------------------------------------\n\n /**\n * Bulk-write files into the sandbox filesystem via the SDK's native upload.\n *\n * Per-file permission modes are not supported; an explicit `mode` is\n * rejected rather than silently discarded.\n */\n async writeFiles(files: SandboxFileInput[]): Promise<void> {\n assertModesUnsupported(files, 'E2B');\n await this.ensureRunning();\n await this.e2b.files.write(\n files.map(f => ({\n path: f.path,\n data: typeof f.content === 'string' ? f.content : new Blob([new Uint8Array(f.content)]),\n })),\n );\n }\n\n /**\n * Get instructions describing this E2B sandbox.\n * Used by agents to understand the execution environment.\n */\n getInstructions(opts?: { requestContext?: RequestContext }): string {\n if (this._instructionsOverride === undefined) return this._getDefaultInstructions();\n if (typeof this._instructionsOverride === 'string') return this._instructionsOverride;\n const defaultInstructions = this._getDefaultInstructions();\n return this._instructionsOverride({ defaultInstructions, requestContext: opts?.requestContext });\n }\n\n private _getDefaultInstructions(): string {\n const mountCount = this.mounts.entries.size;\n const mountInfo = mountCount > 0 ? ` ${mountCount} filesystem(s) mounted via FUSE.` : '';\n return `Cloud sandbox.${mountInfo}`;\n }\n\n // ---------------------------------------------------------------------------\n // Mounting\n // ---------------------------------------------------------------------------\n\n /**\n * Mount a filesystem at a path in the sandbox.\n * Uses FUSE tools (s3fs, gcsfuse) to mount cloud storage.\n */\n async mount(filesystem: WorkspaceFilesystem, mountPath: string): Promise<MountResult> {\n validateMountPath(mountPath);\n\n if (!this._sandbox) {\n throw new SandboxNotReadyError(this.id);\n }\n\n this.logger.debug(`${LOG_PREFIX} Mounting \"${mountPath}\"...`);\n\n // Get mount config - MountManager validates this exists before calling mount()\n const config = filesystem.getMountConfig?.() as E2BMountConfig | undefined;\n if (!config) {\n const error = `Filesystem \"${filesystem.id}\" does not provide a mount config`;\n this.logger.error(`${LOG_PREFIX} ${error}`);\n this.mounts.set(mountPath, { filesystem, state: 'error', error });\n return { success: false, mountPath, error };\n }\n\n // Check if already mounted with matching config (e.g., when reconnecting to existing sandbox)\n const existingMount = await this.checkExistingMount(mountPath, config);\n if (existingMount === 'matching') {\n this.logger.debug(\n `${LOG_PREFIX} Detected existing mount for ${filesystem.provider} (\"${filesystem.id}\") at \"${mountPath}\" with correct config, skipping`,\n );\n this.mounts.set(mountPath, { state: 'mounted', config });\n return { success: true, mountPath };\n } else if (existingMount === 'mismatched') {\n // Different config - unmount and re-mount\n this.logger.debug(`${LOG_PREFIX} Config mismatch, unmounting to re-mount with new config...`);\n await this.unmount(mountPath);\n }\n this.logger.debug(`${LOG_PREFIX} Config type: ${config.type}`);\n\n // Mark as mounting (handles direct mount() calls; MountManager also sets this for processPending)\n this.mounts.set(mountPath, { filesystem, state: 'mounting', config });\n\n // Check if directory exists and is non-empty (would shadow existing files)\n try {\n const checkResult = await this._sandbox.commands.run(\n `[ -d \"${mountPath}\" ] && [ \"$(ls -A \"${mountPath}\" 2>/dev/null)\" ] && echo \"non-empty\" || echo \"ok\"`,\n );\n if (checkResult.stdout.trim() === 'non-empty') {\n const error = `Cannot mount at ${mountPath}: directory exists and is not empty. Mounting would hide existing files. Use a different path or empty the directory first.`;\n this.logger.error(`${LOG_PREFIX} ${error}`);\n this.mounts.set(mountPath, { filesystem, state: 'error', config, error });\n return { success: false, mountPath, error };\n }\n } catch {\n // Check failed, proceed anyway\n }\n\n // Create mount directory with sudo (for paths outside home dir like /data)\n // Then chown to current user so mount works without issues\n try {\n this.logger.debug(`${LOG_PREFIX} Creating mount directory for ${mountPath}...`);\n const mkdirCommand = `sudo mkdir -p \"${mountPath}\" && sudo chown $(id -u):$(id -g) \"${mountPath}\"`;\n\n this.logger.debug(`${LOG_PREFIX} Running command: ${mkdirCommand}`);\n const mkdirResult = await this._sandbox.commands.run(mkdirCommand);\n\n this.logger.debug(`${LOG_PREFIX} Created mount directory for mount path \"${mountPath}\":`, mkdirResult);\n } catch (mkdirError) {\n this.logger.debug(`${LOG_PREFIX} mkdir error for \"${mountPath}\":`, mkdirError);\n this.mounts.set(mountPath, { filesystem, state: 'error', config, error: String(mkdirError) });\n return { success: false, mountPath, error: String(mkdirError) };\n }\n\n // Create mount context for mount operations\n const mountCtx: MountContext = {\n sandbox: this._sandbox,\n logger: this.logger,\n };\n\n try {\n switch (config.type) {\n case 's3':\n this.logger.debug(`${LOG_PREFIX} Mounting S3 bucket at ${mountPath}...`);\n await mountS3(mountPath, config as E2BS3MountConfig, mountCtx);\n this.logger.debug(`${LOG_PREFIX} Mounted S3 bucket at ${mountPath}`);\n break;\n case 'gcs':\n this.logger.debug(`${LOG_PREFIX} Mounting GCS bucket at ${mountPath}...`);\n await mountGCS(mountPath, config as E2BGCSMountConfig, mountCtx);\n this.logger.debug(`${LOG_PREFIX} Mounted GCS bucket at ${mountPath}`);\n break;\n case 'azure-blob':\n this.logger.debug(`${LOG_PREFIX} Mounting Azure Blob container at ${mountPath}...`);\n await mountAzure(mountPath, config as E2BAzureBlobMountConfig, mountCtx);\n this.logger.debug(`${LOG_PREFIX} Mounted Azure Blob container at ${mountPath}`);\n break;\n default:\n this.mounts.set(mountPath, {\n filesystem,\n state: 'unsupported',\n config,\n error: `Unsupported mount type: ${(config as FilesystemMountConfig).type}`,\n });\n return {\n success: false,\n mountPath,\n error: `Unsupported mount type: ${(config as FilesystemMountConfig).type}`,\n };\n }\n } catch (error) {\n this.logger.error(\n `${LOG_PREFIX} Error mounting \"${filesystem.provider}\" (${filesystem.id}) at \"${mountPath}\":`,\n error,\n );\n this.mounts.set(mountPath, { filesystem, state: 'error', config, error: String(error) });\n\n // Clean up the directory we created since mount failed\n try {\n await this._sandbox!.commands.run(`sudo rmdir \"${mountPath}\" 2>/dev/null || true`);\n this.logger.debug(`${LOG_PREFIX} Cleaned up directory after failed mount: ${mountPath}`);\n } catch {\n // Ignore cleanup errors\n }\n\n return { success: false, mountPath, error: String(error) };\n }\n\n // Mark as mounted\n this.mounts.set(mountPath, { state: 'mounted', config });\n\n // Write marker file so we can detect config changes on reconnect\n await this.writeMarkerFile(mountPath);\n\n this.logger.debug(`${LOG_PREFIX} Mounted ${mountPath}`);\n return { success: true, mountPath };\n }\n\n /**\n * Unmount a filesystem from a path in the sandbox.\n */\n async unmount(mountPath: string): Promise<void> {\n validateMountPath(mountPath);\n\n if (!this._sandbox) {\n throw new SandboxNotReadyError(this.id);\n }\n\n this.logger.debug(`${LOG_PREFIX} Unmounting ${mountPath}...`);\n\n try {\n // Use fusermount for FUSE mounts, fall back to umount\n const result = await this._sandbox.commands.run(\n `sudo fusermount -u \"${mountPath}\" 2>/dev/null || sudo umount \"${mountPath}\"`,\n );\n if (result.exitCode !== 0) {\n this.logger.debug(`${LOG_PREFIX} Unmount warning: ${result.stderr || result.stdout}`);\n }\n } catch (error) {\n this.logger.debug(`${LOG_PREFIX} Unmount error:`, error);\n // Try lazy unmount as last resort\n await this._sandbox.commands.run(`sudo umount -l \"${mountPath}\" 2>/dev/null || true`);\n }\n\n this.mounts.delete(mountPath);\n\n // Clean up marker file\n const filename = this.mounts.markerFilename(mountPath);\n const markerPath = `/tmp/.mastra-mounts/${filename}`;\n await this._sandbox.commands.run(`rm -f \"${markerPath}\" 2>/dev/null || true`);\n\n // Remove empty mount directory (only if empty, rmdir fails on non-empty)\n // Use sudo since mount directories outside home (like /data) were created with sudo\n const rmdirResult = await this._sandbox.commands.run(`sudo rmdir \"${mountPath}\" 2>&1`);\n if (rmdirResult.exitCode === 0) {\n this.logger.debug(`${LOG_PREFIX} Unmounted and removed ${mountPath}`);\n } else {\n this.logger.debug(\n `${LOG_PREFIX} Unmounted ${mountPath} (directory not removed: ${rmdirResult.stderr?.trim() || 'not empty'})`,\n );\n }\n }\n\n /**\n * Unmount all stale mounts that are not in the expected mounts list.\n * Also cleans up orphaned directories and marker files from failed mount attempts.\n * Call this after reconnecting to an existing sandbox to clean up old mounts.\n */\n async reconcileMounts(expectedMountPaths: string[]): Promise<void> {\n if (!this._sandbox) {\n throw new SandboxNotReadyError(this.id);\n }\n\n this.logger.debug(`${LOG_PREFIX} Reconciling mounts. Expected paths:`, expectedMountPaths);\n\n // Get current FUSE mounts in the sandbox\n const mountsResult = await this._sandbox.commands.run(\n `grep -E 'fuse\\\\.(s3fs|gcsfuse|blobfuse2)' /proc/mounts | awk '{print $2}'`,\n );\n const currentMounts = mountsResult.stdout\n .trim()\n .split('\\n')\n .filter(p => p.length > 0);\n\n this.logger.debug(`${LOG_PREFIX} Current FUSE mounts in sandbox:`, currentMounts);\n\n // Read our marker files to know which mounts WE created\n const markersResult = await this._sandbox.commands.run(`ls /tmp/.mastra-mounts/ 2>/dev/null || echo \"\"`);\n const markerFiles = markersResult.stdout\n .trim()\n .split('\\n')\n .filter(f => f.length > 0 && SAFE_MARKER_NAME.test(f));\n\n // Build a map of mount paths → marker filenames for mounts WE created\n const managedMountPaths = new Map<string, string>();\n for (const markerFile of markerFiles) {\n const markerResult = await this._sandbox.commands.run(\n `cat \"/tmp/.mastra-mounts/${markerFile}\" 2>/dev/null || echo \"\"`,\n );\n const parsed = this.mounts.parseMarkerContent(markerResult.stdout.trim());\n if (parsed && SAFE_MOUNT_PATH.test(parsed.path)) {\n managedMountPaths.set(parsed.path, markerFile);\n }\n }\n\n // Find mounts that exist but shouldn't — only unmount if WE created them (have a marker)\n const staleMounts = currentMounts.filter(path => !expectedMountPaths.includes(path));\n\n for (const stalePath of staleMounts) {\n if (managedMountPaths.has(stalePath)) {\n this.logger.debug(`${LOG_PREFIX} Found stale managed FUSE mount at ${stalePath}, unmounting...`);\n await this.unmount(stalePath);\n } else {\n this.logger.debug(`${LOG_PREFIX} Found external FUSE mount at ${stalePath}, leaving untouched`);\n }\n }\n\n // Clean up orphaned marker files and empty directories from failed mounts\n try {\n const expectedMarkerFiles = new Set(expectedMountPaths.map(p => this.mounts.markerFilename(p)));\n\n // Build a reverse map: markerFile → mountPath\n const markerToPath = new Map<string, string>();\n for (const [path, file] of managedMountPaths) {\n markerToPath.set(file, path);\n }\n\n for (const markerFile of markerFiles) {\n // If this marker file doesn't correspond to an expected mount path, clean it up\n if (!expectedMarkerFiles.has(markerFile)) {\n const mountPath = markerToPath.get(markerFile);\n\n if (mountPath) {\n // Only clean up directory if not currently FUSE mounted\n if (!currentMounts.includes(mountPath)) {\n this.logger.debug(`${LOG_PREFIX} Cleaning up orphaned marker and directory for ${mountPath}`);\n\n // Remove marker file\n await this._sandbox.commands.run(`rm -f \"/tmp/.mastra-mounts/${markerFile}\" 2>/dev/null || true`);\n\n // Try to remove the directory (will fail if not empty or doesn't exist, which is fine)\n await this._sandbox.commands.run(`sudo rmdir \"${mountPath}\" 2>/dev/null || true`);\n }\n } else {\n // Malformed marker file - just delete it\n this.logger.debug(`${LOG_PREFIX} Removing malformed marker file: ${markerFile}`);\n await this._sandbox.commands.run(`rm -f \"/tmp/.mastra-mounts/${markerFile}\" 2>/dev/null || true`);\n }\n }\n }\n } catch {\n // Ignore errors during orphan cleanup\n this.logger.debug(`${LOG_PREFIX} Error during orphan cleanup (non-fatal)`);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Deprecated\n // ---------------------------------------------------------------------------\n\n /** @deprecated Use `e2b` instead. */\n get instance(): Sandbox {\n return this.e2b;\n }\n\n /** @deprecated Use `status === 'running'` instead. */\n async isReady(): Promise<boolean> {\n return this.status === 'running' && this._sandbox !== null;\n }\n\n // ---------------------------------------------------------------------------\n // Internal Helpers\n // ---------------------------------------------------------------------------\n\n private generateId(): string {\n return `e2b-sandbox-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n }\n\n /** Domain used to derive public sandbox hosts (self-hosted E2B or e2b.app). */\n private get sandboxDomain(): string {\n return this.connectionOpts.domain ?? process.env.E2B_DOMAIN ?? 'e2b.app';\n }\n\n /**\n * Look up an existing sandbox with matching mastra-sandbox-id metadata\n * WITHOUT connecting or resuming it. Returns its list info or null.\n */\n private async lookupExistingSandboxInfo(): Promise<E2BSandboxListInfo | null> {\n try {\n // Query E2B for existing sandbox with our logical ID in metadata\n const paginator = Sandbox.list({\n ...this.connectionOpts,\n query: {\n metadata: { 'mastra-sandbox-id': this.id },\n state: ['running', 'paused'],\n },\n });\n\n const sandboxes = await paginator.nextItems();\n\n this.logger.debug(`${LOG_PREFIX} sandboxes:`, sandboxes);\n\n // Sandbox.list only returns running/paused sandboxes, so no need to filter\n if (sandboxes.length > 0) {\n const existingSandbox = sandboxes[0]!;\n this.logger.debug(\n `${LOG_PREFIX} Found existing sandbox for ${this.id}: ${existingSandbox.sandboxId} (state: ${existingSandbox.state})`,\n );\n return existingSandbox;\n }\n } catch (e) {\n this.logger.debug(`${LOG_PREFIX} Error querying for existing sandbox:`, e);\n // Continue to create new sandbox\n }\n\n return null;\n }\n\n /**\n * Acquire an existing sandbox: try the preferred provider sandbox ID first\n * (deterministic reattach), then fall back to logical-id metadata discovery.\n */\n private async acquireExistingSandbox(): Promise<Sandbox | null> {\n if (this._preferredSandboxId) {\n const preferred = await this.connectToPreferredSandbox(this._preferredSandboxId);\n if (preferred) return preferred;\n }\n return this.findExistingSandbox();\n }\n\n /**\n * Deterministically reattach to a sandbox by its E2B provider ID.\n *\n * Fail-closed: only a typed \"sandbox gone\" error (not found / killed /\n * not running) returns null so the caller can fall through to logical-id\n * discovery or creation. Any other error (auth, quota, rate limit,\n * timeout, network) propagates so a duplicate sandbox is never created.\n *\n * Ownership is validated before connecting: a sandbox tagged with a\n * different `mastra-sandbox-id` is refused (without resuming it).\n * Sandboxes without the tag (created outside Mastra) are attachable.\n */\n private async connectToPreferredSandbox(preferredSandboxId: string): Promise<Sandbox | null> {\n let info: E2BSandboxListInfo;\n try {\n info = await Sandbox.getInfo(preferredSandboxId, this.connectionOpts);\n } catch (e) {\n if (this.isSandboxDeadError(e)) {\n this.logger.debug(\n `${LOG_PREFIX} Preferred sandbox ${preferredSandboxId} is gone, falling back to logical-id discovery:`,\n e,\n );\n return null;\n }\n throw e;\n }\n\n const owner = info.metadata?.['mastra-sandbox-id'];\n if (owner !== undefined && owner !== this.id) {\n throw new Error(\n `${LOG_PREFIX} Provider sandbox ${preferredSandboxId} belongs to logical sandbox id \"${owner}\", refusing to attach it to \"${this.id}\"`,\n );\n }\n\n try {\n return await Sandbox.connect(preferredSandboxId, { ...this.connectionOpts, timeoutMs: this.timeout });\n } catch (e) {\n // The sandbox can terminate between getInfo and connect.\n if (this.isSandboxDeadError(e)) {\n this.logger.debug(\n `${LOG_PREFIX} Preferred sandbox ${preferredSandboxId} vanished before connect, falling back:`,\n e,\n );\n return null;\n }\n throw e;\n }\n }\n\n /**\n * Find an existing sandbox with matching mastra-sandbox-id metadata.\n * Returns the connected sandbox if found, null otherwise.\n * Connecting to a paused sandbox resumes it.\n */\n private async findExistingSandbox(): Promise<Sandbox | null> {\n const info = await this.lookupExistingSandboxInfo();\n if (!info) return null;\n try {\n return await this.connectSdkSandbox(info.sandboxId, { ...this.connectionOpts, timeoutMs: this.timeout });\n } catch (e) {\n this.logger.debug(`${LOG_PREFIX} Error connecting to existing sandbox:`, e);\n return null;\n }\n }\n\n // ---------------------------------------------------------------------------\n // SDK Factory Hooks (subclass override points)\n // ---------------------------------------------------------------------------\n\n /**\n * Create a new SDK sandbox from a resolved template ID.\n *\n * Override point for providers layered on the E2B SDK whose `Sandbox`\n * class extends `e2b`'s (e.g. `@e2b/desktop`): override to call their\n * `Sandbox.create`. Connection options are already spread into `opts`.\n */\n protected async createSdkSandbox(templateId: string, opts: SandboxOpts): Promise<Sandbox> {\n return Sandbox.create(templateId, opts);\n }\n\n /**\n * Connect to (and resume) an existing SDK sandbox by its E2B sandbox ID.\n * Override point — see {@link createSdkSandbox}.\n */\n protected async connectSdkSandbox(sandboxId: string, opts: SandboxConnectOpts): Promise<Sandbox> {\n return Sandbox.connect(sandboxId, opts);\n }\n\n /**\n * Resolve the template specification to a template ID.\n *\n * - String: Use as-is (template ID)\n * - TemplateBuilder: Build and return the template ID\n * - Function: Apply to base mountable template, then build\n * - undefined: Use default mountable template (cached)\n *\n * Override point: subclasses with a different default template (e.g.\n * desktop sandboxes) override this and {@link buildDefaultTemplate}.\n */\n protected async resolveTemplate(): Promise<string> {\n // If already resolved, return cached ID\n if (this._resolvedTemplateId) {\n return this._resolvedTemplateId;\n }\n\n // No template specified - use default mountable template with caching\n if (!this.templateSpec) {\n return await this.buildOrReuseDefaultTemplate();\n }\n\n // String template ID - use directly\n if (typeof this.templateSpec === 'string') {\n this._resolvedTemplateId = this.templateSpec;\n return this.templateSpec;\n }\n\n // Named spec (e.g. createRepoTemplate) - lazy build-if-missing under a\n // deterministic name, with a fallback so a failed build degrades to a\n // cold start instead of a wedged session. A deferred spec (sha-less\n // createRepoTemplate) computes its name right before the exists check —\n // pinning to the repo's current default-branch head; a rejection there\n // degrades to the default mountable template like any other resolution\n // failure.\n let spec: Exclude<TemplateSpec, DeferredNamedTemplateSpec>;\n if (isDeferredNamedTemplateSpec(this.templateSpec)) {\n try {\n spec = await this.templateSpec.resolveSpec();\n this._resolvedNamedSpec = spec;\n } catch (error) {\n this.logger.warn(`${LOG_PREFIX} Deferred template spec resolution failed, falling back: ${error}`);\n return await this.resolveFallbackTemplate(undefined);\n }\n } else {\n spec = this.templateSpec;\n }\n if (isNamedTemplateSpec(spec)) {\n const { ref, template: namedTemplate, fallbackTemplate, staleRef, buildTags, buildResources } = spec;\n const buildOpts = {\n ...this.connectionOpts,\n ...(buildTags?.length ? { tags: buildTags } : {}),\n ...buildResources,\n };\n try {\n if (await Template.exists(ref, this.connectionOpts)) {\n this.logger.debug(`${LOG_PREFIX} Using cached template: ${ref}`);\n this._resolvedTemplateId = ref;\n return ref;\n }\n // Stale-build-first: when the exact ref is missing but a previous\n // build exists, boot from it immediately and rebuild the fresh ref\n // in the background — only a template's very first build ever\n // blocks a sandbox start. Runtime setup fast-forwards the slightly\n // stale checkout, so freshness never depends on the template.\n if (staleRef && staleRef !== ref && (await Template.exists(staleRef, this.connectionOpts))) {\n this.logger.debug(`${LOG_PREFIX} Using stale build ${staleRef}; rebuilding ${ref} in background`);\n this.triggerBackgroundBuild(namedTemplate as TemplateClass, ref, buildOpts);\n this._resolvedTemplateId = staleRef;\n return staleRef;\n }\n this.logger.debug(`${LOG_PREFIX} Building template: ${ref}...`);\n const buildResult = await Template.build(namedTemplate as TemplateClass, ref, buildOpts);\n this.logger.debug(`${LOG_PREFIX} Template built: ${buildResult.templateId}`);\n // Resolve to the ref, NOT the raw build id: creating a sandbox from\n // a bare template id looks up its `default` tag, which a\n // tag-qualified build (e.g. `name:sha-<sha>`) never assigns — the\n // create would 404 and needlessly ride the fallback ladder.\n this._resolvedTemplateId = ref;\n return ref;\n } catch (error) {\n this.logger.warn(`${LOG_PREFIX} Template '${ref}' resolution failed, falling back: ${error}`);\n return await this.resolveFallbackTemplate(fallbackTemplate);\n }\n }\n // TemplateBuilder or function - need to build\n let template: TemplateBuilder;\n let templateName: string;\n\n if (typeof spec === 'function') {\n // Apply customization function to base mountable template\n const { template: baseTemplate } = createDefaultMountableTemplate();\n template = spec(baseTemplate);\n // Custom templates get unique names since they're modified\n templateName = `mastra-custom-${this.id.replace(/[^a-zA-Z0-9-]/g, '-')}`;\n } else {\n // Use provided TemplateBuilder directly\n template = spec;\n templateName = `mastra-${this.id.replace(/[^a-zA-Z0-9-]/g, '-')}`;\n }\n\n // Build the template\n this.logger.debug(`${LOG_PREFIX} Building custom template: ${templateName}...`);\n const buildResult = await Template.build(template as TemplateClass, templateName, this.connectionOpts);\n this._resolvedTemplateId = buildResult.templateId;\n this.logger.debug(`${LOG_PREFIX} Template built: ${buildResult.templateId}`);\n\n return buildResult.templateId;\n }\n\n /**\n * Resolve the default mountable template: reuse when it exists, build once\n * when it does not.\n */\n /**\n * Resolve a named spec's fallback template. A named fallback gets its own\n * exists-then-build resolution; anything failing past that (including\n * specs without a fallback, e.g. repo templates) lands on the default\n * mountable template so a broken build never wedges a session.\n */\n /**\n * Trigger a non-blocking template rebuild via `Template.buildInBackground`\n * (the build runs on E2B's side, so it outlives this process). Deduped\n * per-process by ref so concurrent session starts on the same moved head\n * don't stack duplicate builds; a failed TRIGGER clears the guard so a\n * later start retries. A build that fails server-side simply never\n * registers the ref — the next start falls back to the stale build again\n * and re-triggers.\n */\n private triggerBackgroundBuild(template: TemplateClass, ref: string, buildOpts: Omit<BuildOptions, 'alias'>): void {\n if (inFlightBackgroundBuilds.has(ref)) return;\n inFlightBackgroundBuilds.add(ref);\n void Template.buildInBackground(template, ref, buildOpts)\n .then(result => {\n this.logger.debug(`${LOG_PREFIX} Background template build triggered: ${ref} (${result.buildId})`);\n })\n .catch(error => {\n inFlightBackgroundBuilds.delete(ref);\n this.logger.warn(`${LOG_PREFIX} Background template build trigger failed for '${ref}': ${error}`);\n });\n }\n\n private async resolveFallbackTemplate(fallbackTemplate: NamedTemplateSpec['fallbackTemplate']): Promise<string> {\n if (typeof fallbackTemplate === 'string') {\n this._resolvedTemplateId = fallbackTemplate;\n return fallbackTemplate;\n }\n if (fallbackTemplate && isNamedTemplateSpec(fallbackTemplate)) {\n try {\n if (await Template.exists(fallbackTemplate.ref, this.connectionOpts)) {\n this._resolvedTemplateId = fallbackTemplate.ref;\n return fallbackTemplate.ref;\n }\n const buildResult = await Template.build(fallbackTemplate.template as TemplateClass, fallbackTemplate.ref, {\n ...this.connectionOpts,\n ...fallbackTemplate.buildResources,\n });\n this._resolvedTemplateId = buildResult.templateId;\n return buildResult.templateId;\n } catch (error) {\n this.logger.warn(`${LOG_PREFIX} Fallback template '${fallbackTemplate.ref}' failed too: ${error}`);\n return await this.buildOrReuseDefaultTemplate();\n }\n }\n if (fallbackTemplate) {\n try {\n const buildResult = await Template.build(\n fallbackTemplate as unknown as TemplateClass,\n `mastra-fallback-${this.id.replace(/[^a-zA-Z0-9-]/g, '-')}`,\n this.connectionOpts,\n );\n this._resolvedTemplateId = buildResult.templateId;\n return buildResult.templateId;\n } catch (error) {\n this.logger.warn(`${LOG_PREFIX} Fallback template build failed, using default: ${error}`);\n return await this.buildOrReuseDefaultTemplate();\n }\n }\n return await this.buildOrReuseDefaultTemplate();\n }\n\n /**\n * Resources the configured template asked for. The default mountable\n * template honors them too, so a repo template that falls back never\n * silently downgrades the machine — a 2 GB session's setup would OOM in\n * the 1 GB default. Per-size default templates cost one extra build each.\n */\n private requestedBuildResources(): TemplateResources | undefined {\n const spec =\n this.templateSpec && isNamedTemplateSpec(this.templateSpec) ? this.templateSpec : this._resolvedNamedSpec;\n return spec?.buildResources;\n }\n\n private async buildOrReuseDefaultTemplate(): Promise<string> {\n const { template, id, resources } = createDefaultMountableTemplate(this.requestedBuildResources());\n\n const exists = await Template.exists(id, this.connectionOpts);\n if (exists) {\n this.logger.debug(`${LOG_PREFIX} Using cached mountable template: ${id}`);\n this._resolvedTemplateId = id;\n return id;\n }\n\n this.logger.debug(`${LOG_PREFIX} Building default mountable template: ${id}...`);\n const buildResult = await Template.build(template as TemplateClass, id, { ...this.connectionOpts, ...resources });\n this._resolvedTemplateId = buildResult.templateId;\n this.logger.debug(`${LOG_PREFIX} Template built and cached: ${buildResult.templateId}`);\n return buildResult.templateId;\n }\n\n /**\n * Build the default mountable template (bypasses exists check).\n *\n * Override point: called from the template-not-found retry path in\n * `start()` when no explicit template was configured.\n */\n protected async buildDefaultTemplate(): Promise<string> {\n const { template, id, resources } = createDefaultMountableTemplate(this.requestedBuildResources());\n this.logger.debug(`${LOG_PREFIX} Building default mountable template: ${id}...`);\n const buildResult = await Template.build(template as TemplateClass, id, { ...this.connectionOpts, ...resources });\n this._resolvedTemplateId = buildResult.templateId;\n this.logger.debug(`${LOG_PREFIX} Template built: ${buildResult.templateId}`);\n return buildResult.templateId;\n }\n\n /**\n * Write marker file for detecting config changes on reconnect.\n * Stores both the mount path and config hash in the file.\n */\n private async writeMarkerFile(mountPath: string): Promise<void> {\n if (!this._sandbox) return;\n\n const markerContent = this.mounts.getMarkerContent(mountPath);\n if (!markerContent) return;\n\n const filename = this.mounts.markerFilename(mountPath);\n const markerPath = `/tmp/.mastra-mounts/${filename}`;\n try {\n await this._sandbox.commands.run('mkdir -p /tmp/.mastra-mounts');\n await this._sandbox.files.write(markerPath, markerContent);\n } catch {\n // Non-fatal - marker is just for optimization\n this.logger.debug(`${LOG_PREFIX} Warning: Could not write marker file at ${markerPath}`);\n }\n }\n\n /**\n * Check if a path is already mounted and if the config matches.\n */\n private async checkExistingMount(\n mountPath: string,\n newConfig: E2BMountConfig,\n ): Promise<'not_mounted' | 'matching' | 'mismatched'> {\n if (!this._sandbox) throw new SandboxNotReadyError(this.id);\n\n // Check if path is a mount point\n const mountCheck = await this._sandbox.commands.run(\n `mountpoint -q \"${mountPath}\" && echo \"mounted\" || echo \"not mounted\"`,\n );\n\n if (mountCheck.stdout.trim() !== 'mounted') {\n return 'not_mounted';\n }\n\n // Path is mounted - check if config matches via marker file\n const filename = this.mounts.markerFilename(mountPath);\n const markerPath = `/tmp/.mastra-mounts/${filename}`;\n\n try {\n const markerResult = await this._sandbox.commands.run(`cat \"${markerPath}\" 2>/dev/null || echo \"\"`);\n const parsed = this.mounts.parseMarkerContent(markerResult.stdout.trim());\n\n if (!parsed) {\n return 'mismatched';\n }\n\n // Compute hash of the NEW config and compare with stored hash\n const newConfigHash = this.mounts.computeConfigHash(newConfig);\n this.logger.debug(\n `${LOG_PREFIX} Marker check - stored hash: \"${parsed.configHash}\", new config hash: \"${newConfigHash}\"`,\n );\n\n if (parsed.path === mountPath && parsed.configHash === newConfigHash) {\n return 'matching';\n }\n } catch {\n // Marker doesn't exist or can't be read - treat as mismatched\n }\n\n return 'mismatched';\n }\n\n /**\n * Check if an error indicates the sandbox itself is dead/gone.\n * Does NOT include code execution timeouts (those are the user's code taking too long).\n * Does NOT include \"port is not open\" - that needs sandbox kill, not reconnect.\n */\n private isSandboxDeadError(error: unknown): boolean {\n if (!error) return false;\n const errorStr = String(error);\n return (\n /\\b(?:paused\\s+)?sandbox(?:\\s+\\S+)?\\s+(?:was\\s+)?not found\\b/i.test(errorStr) ||\n errorStr.includes('Sandbox is probably not running') ||\n errorStr.includes('sandbox has been killed')\n );\n }\n\n /**\n * Handle sandbox timeout by clearing the instance and resetting state.\n *\n * Bypasses the normal stop() lifecycle because the sandbox is already dead —\n * we can't unmount filesystems or run cleanup commands. Instead we reset\n * mount states to 'pending' so they get re-mounted when start() runs again.\n */\n private handleSandboxTimeout(): void {\n this._sandbox = null;\n\n // Reset retryable entries to pending so they get re-mounted on restart.\n // A mount error belongs to the dead physical sandbox and must not prevent\n // the configured filesystem from being attempted in its replacement.\n for (const [path, entry] of this.mounts.entries) {\n if (entry.state === 'mounted' || entry.state === 'mounting' || entry.state === 'error') {\n this.mounts.set(path, { state: 'pending', error: undefined });\n }\n }\n\n this.status = 'stopped';\n }\n\n /**\n * Execute an operation with automatic retry if the sandbox is found to be dead.\n *\n * When the E2B sandbox times out or crashes mid-operation, this method\n * resets sandbox state, restarts it, and retries the operation once.\n *\n * @internal Used by E2BProcessManager (spawn) and E2BCodeModeTransport (file setup)\n * to handle dead sandboxes.\n */\n async retryOnDead<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n if (this.isSandboxDeadError(error) && !this._isRetrying) {\n this.handleSandboxTimeout();\n this._isRetrying = true;\n try {\n await this.ensureRunning();\n return await fn();\n } finally {\n this._isRetrying = false;\n }\n }\n throw error;\n }\n }\n}\n","import { createHash } from \"crypto\";\n//#region src/setup-marker.ts\n/**\n* Setup completion marker shared by repo templates and their consumers.\n*\n* A repo template writes this file beside the checkout as its last build\n* step, so it exists only in images where every setup command succeeded. Its\n* content is a digest of the setup commands the image ran, letting a sandbox\n* booted from the image tell whether the setup it is about to run already\n* happened. Relative to the template's build cwd, which is also the runtime\n* working directory the repo was cloned into.\n*/\nconst SETUP_MARKER_PATH = \".mastra-sandbox/setup\";\n/** Blank entries never become build steps, so they never count toward the digest either. */\nfunction normalizeSetupCommands(setupCommand) {\n\treturn (setupCommand === void 0 ? [] : Array.isArray(setupCommand) ? setupCommand : [setupCommand]).filter((command) => command.trim() !== \"\");\n}\n/** The marker content for a setup command list: `sha256:<hex>` over the commands joined by newlines. */\nfunction setupMarkerContent(setupCommand) {\n\treturn `sha256:${createHash(\"sha256\").update(normalizeSetupCommands(setupCommand).join(\"\\n\")).digest(\"hex\")}`;\n}\n/** Shell step that writes the marker relative to the cwd. `content` is a digest, so it is shell-safe. */\nfunction setupMarkerCommand(content) {\n\treturn `mkdir -p \"$(dirname \"${SETUP_MARKER_PATH}\")\" && printf '%s' '${content}' > \"${SETUP_MARKER_PATH}\"`;\n}\n//#endregion\n//#region src/repo-clone.ts\nfunction repoCloneCommand({ cloneUrl, destination, branch, tokenEnv }) {\n\treturn `git ${tokenEnv ? `${gitAuthFlag(tokenEnv)} ` : \"\"}clone --depth=1 --single-branch ${branch ? `--branch ${shellQuote(branch)} ` : \"\"}${shellQuote(cloneUrl)} ${shellQuote(destination)}`;\n}\n/** Per-invocation auth header; `-c` config never reaches `.git/config`. */\nfunction gitAuthFlag(tokenEnv) {\n\treturn `-c http.extraheader=\"AUTHORIZATION: basic $(printf 'x-access-token:%s' \"$${tokenEnv}\" | base64 -w0)\"`;\n}\nfunction shellQuote(value) {\n\treturn `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n//#endregion\nexport { SETUP_MARKER_PATH, normalizeSetupCommands, repoCloneCommand, setupMarkerCommand, setupMarkerContent };\n\n//# sourceMappingURL=index.js.map","/**\n * Sha-tagged repo templates.\n *\n * A repo template is an E2B template with the repository already cloned and\n * its dependencies installed at a known commit. Sessions started from it only\n * need `git fetch` + checkout of their actual ref plus setup drift, instead\n * of a cold clone + full install.\n *\n * There is exactly ONE template per (repo, setup command, repoDir): the\n * template name is a deterministic `mastra-repo-<hash>` over those inputs,\n * and the commit sha rides as a docker-style TAG on that name\n * (`mastra-repo-<hash>:sha-<sha>`). A moved default branch produces a new\n * tag via a rebuild-in-place of the same template — old sha tags remain as\n * prunable build history instead of accumulating stale template names.\n * Builds are lazy: the first `E2BSandbox.start()` that resolves a missing\n * tag triggers the build; nothing pre-builds templates for idle repos.\n *\n * Credential invariant: a build credential may enter the template\n * DEFINITION (via `setEnvs`, visible to build steps but not persisted into\n * runtime sandbox environments) and the build process — never the image\n * filesystem. Clones authenticate through an in-shell computed\n * `http.extraheader`, so no tokened remote URL or credential file can land\n * in a captured layer. Callers must supply a short-lived credential (a\n * GitHub App installation token, which self-expires); never a long-lived\n * PAT. Without a credential the clone is plain tokenless HTTPS — public\n * repos build fine; a private repo's build fails and the sandbox falls back\n * to the fallback template, with the session's runtime setup performing the\n * full clone using its runtime-injected credential instead.\n */\nimport { execFile } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport { promisify } from 'node:util';\nimport { repoCloneCommand, setupMarkerCommand, setupMarkerContent } from '@internal/workspace';\n\nimport { Template } from 'e2b';\nimport type { ConnectionOpts, TemplateClass } from 'e2b';\n\nimport { createDefaultMountableTemplate, DEFAULT_CPU_COUNT, DEFAULT_MEMORY_MB } from './template';\nimport type { DeferredNamedTemplateSpec, NamedTemplateSpec } from './template';\n\nconst execFileAsync = promisify(execFile);\n\n// Monotonic; never reuse a retired value. v4 added the machine resources\n// (cpuCount, memoryMB) to the identity hash — resources are baked into the\n// built template, so a resize must produce a new template rather than\n// silently reusing one built at the old size. v5 picked up the v3 default\n// mountable base (pinned current Node LTS + corepack) — base contents are\n// not part of this hash, so the bump is what forces existing repo\n// templates to rebuild on the new base.\nconst ALIAS_VERSION = 'v5';\n\n/**\n * Stable tag assigned to every successful repo-template build. Points at the\n * latest build regardless of sha, so a moved head can boot from the previous\n * build (`name:current`) while the fresh sha builds in the background.\n */\nconst CURRENT_TAG = 'current';\n\n/**\n * Env var carrying the repository credential during the build. The same\n * name a session installs before running setup, so a setup command sees the\n * same environment in both places. Set via `setEnvs`; the git auth header is\n * computed from it too.\n */\nconst BUILD_TOKEN_ENV = 'GH_TOKEN';\n\n/**\n * Clone URLs interpolate into build shell commands, so constrain them to\n * https plus plain host/path characters. This rejects shell metacharacters\n * outright rather than escaping them. Every regex here is a single anchored\n * character class, so matching stays linear on adversarial input; the\n * structural checks (scheme, host, path segments) go through WHATWG URL\n * parsing instead of one big backtracking pattern.\n */\nconst CLONE_URL_ALLOWED_CHARS = /^[a-z0-9:/._-]+$/i;\nconst CLONE_URL_HOST_PATTERN = /^[a-z0-9.-]+$/i;\nconst CLONE_URL_SEGMENT_PATTERN = /^[\\w.-]+$/;\nconst SHA_PATTERN = /^[0-9a-f]{7,40}$/i;\n\nfunction isValidCloneUrl(cloneUrl: string): boolean {\n // The RAW string is what reaches shell commands, so allowlist it directly:\n // URL normalization (backslash folding, percent-decoding) must not be able\n // to launder characters the raw string carries.\n if (cloneUrl.length > 2048 || !CLONE_URL_ALLOWED_CHARS.test(cloneUrl)) return false;\n let url: URL;\n try {\n url = new URL(cloneUrl);\n } catch {\n return false;\n }\n if (url.protocol !== 'https:' || url.username || url.password || url.search || url.hash) return false;\n if (!CLONE_URL_HOST_PATTERN.test(url.hostname)) return false;\n // At least one path segment, none empty — rejects bare hosts and\n // trailing slashes, exactly as the previous single-pattern check did.\n const segments = url.pathname.split('/').slice(1);\n return segments.length > 0 && segments.every(segment => CLONE_URL_SEGMENT_PATTERN.test(segment));\n}\n\n/**\n * Repository clone target plus an optional credential for it.\n *\n * Structurally identical to the factory capability of the same name, and\n * declared here so this package carries no factory dependency: a host can\n * pass its context accessor straight through.\n */\nexport interface RepositoryAccess {\n /** https clone URL, e.g. `https://github.com/acme/widgets.git`. */\n cloneUrl: string;\n /**\n * Credential for private repositories. `scheme` describes the credential\n * itself; git over https accepts only basic auth, so a bearer token is\n * presented as `x-access-token:<token>` (see {@link gitAuthFlag}).\n */\n authorization?: { scheme: 'bearer'; token: string };\n}\n\nexport interface RepoTemplateOptions {\n /**\n * Resolves the clone URL and, for private repositories, a SHORT-LIVED\n * credential (e.g. a GitHub App installation token). Called once per\n * template resolution: the credential authenticates the head lookup and,\n * when a build is needed, the build's clone (via `setEnvs` plus an\n * in-shell `http.extraheader` — it never touches the image filesystem,\n * and probing confirms `setEnvs` values do not persist into runtime\n * sandbox environments). Never supply a long-lived PAT: the value enters\n * the template definition, where only its expiry bounds the exposure. A\n * rejection degrades to tokenless behavior.\n *\n * Sole source of the clone URL, so what gets cloned and what the template\n * is identified by can never disagree. A public repository needs no\n * credential: `async () => ({ cloneUrl })`.\n *\n * The key is required so that passing a host context whose field was\n * renamed fails to compile instead of silently producing no template.\n * `undefined` means the session has no repository, and\n * {@link createRepoTemplate} then returns undefined.\n */\n getRepositoryAccess: (() => Promise<RepositoryAccess | undefined>) | undefined;\n /**\n * Setup command(s) run inside the checkout and hashed into the template name.\n * Array entries run as separate cached build steps.\n */\n setupCommand?: string | string[];\n /**\n * Extra environment for the build, available to every build step\n * including {@link RepoTemplateOptions.setupCommand}. Use it for the\n * credentials a setup command needs (registry tokens, private index\n * URLs) so the build reaches the same state a runtime setup would.\n *\n * Hashed into the template name (keys and values), because env that\n * changes what setup installs changes the image just as the setup command\n * does. Rotating a value therefore forces a rebuild — put credentials\n * that rotate often in {@link RepoTemplateOptions.getRepositoryAccess}\n * instead, which is excluded from identity.\n *\n * Values reach the template definition, so they must be short-lived or\n * non-secret.\n */\n buildEnv?: Record<string, string> | (() => Promise<Record<string, string>>);\n /**\n * vCPUs allocated to sandboxes created from this template. Resources are\n * a property of the built template, not of an individual sandbox, so this\n * is hashed into the template name — a resize builds a new template\n * instead of silently reusing one built at the old size. Defaults to the\n * SDK default (2). Account tier caps the maximum.\n */\n cpuCount?: number;\n /**\n * Memory in MB allocated to sandboxes created from this template. Hashed\n * into the template name for the same reason as {@link cpuCount}.\n * Defaults to the SDK default (1024).\n */\n memoryMB?: number;\n /**\n * Absolute parent for the checkout. Created by the build user, so its parent\n * must already be writable by that user. Becomes the build cwd, the runtime\n * cwd, and part of template identity; the repo lands at `<workingDirectory>/<repo>`.\n * Omit to use the base image's working directory for all of the above.\n */\n workingDirectory?: string;\n}\n\n/**\n * Identity inputs for a repo template, already resolved. Separate from\n * {@link RepoTemplateOptions} because identity must be computable without\n * awaiting anything, while the clone URL and credential arrive from an\n * async accessor.\n */\nexport interface RepoTemplateIdentity {\n /** https clone URL. Host is part of the identity. */\n cloneUrl: string;\n /** Resolved head sha. Becomes the template's tag. */\n sha?: string;\n setupCommand?: string | string[];\n buildEnv?: Record<string, string>;\n cpuCount?: number;\n memoryMB?: number;\n workingDirectory?: string;\n}\n\n/**\n * Compute the deterministic template ref for a set of repo template inputs\n * without constructing the builder: `mastra-repo-<hash>` named over\n * (clone URL, setup command, build env), tag-qualified with `:sha-<sha>`\n * when the sha is known. Exposed so callers (and proofs) can predict which\n * ref a sandbox will resolve.\n */\nexport function repoTemplateRef(identity: RepoTemplateIdentity): string {\n const name = repoTemplateName(identity);\n // The sha-less degrade also pins a tag (`current`) rather than the bare\n // name: `Template.exists(name)` is true whenever ANY tagged build exists,\n // but creating from a bare name resolves its `default` tag — which\n // sha-tagged builds never assign — so an untagged ref could pass the\n // exists check and still 404 on create.\n return identity.sha ? `${name}:${shaTag(identity.sha)}` : `${name}:${CURRENT_TAG}`;\n}\n\n// `sha` is excluded at the type level: the name is sha-independent by\n// design (the sha rides the tag), and the signature is what enforces it —\n// making the name sha-dependent would collapse every commit into its own\n// template and kill warm reuse.\nfunction repoTemplateName(identity: Omit<RepoTemplateIdentity, 'sha'>): string {\n const cloneUrl = normalizeCloneUrl(identity.cloneUrl);\n // Fixed key order, so a plain stringify is already canonical. Not a\n // replacer array: that filters keys at every level, which would drop the\n // build env's own keys from the hash.\n const config = [\n ALIAS_VERSION,\n cloneUrl,\n identity.setupCommand ?? null,\n // Sorted, since key order isn't identity. Values participate: env that\n // changes what setup installs changes the image.\n identity.buildEnv ? Object.entries(identity.buildEnv).sort(([a], [b]) => a.localeCompare(b)) : null,\n // Normalized to the defaults, so \"absent\" and \"explicitly default\" are\n // the same template.\n identity.cpuCount ?? DEFAULT_CPU_COUNT,\n identity.memoryMB ?? DEFAULT_MEMORY_MB,\n // Appended only when set, so templates predating the option keep their\n // existing names (and warm builds) instead of all rebuilding.\n ...(identity.workingDirectory !== undefined ? [identity.workingDirectory] : []),\n ];\n const hash = createHash('sha256').update(JSON.stringify(config)).digest('hex').slice(0, 8);\n // Readable name: the repo slug is right in the template name; the short\n // hash suffix keeps host/setup-command variants and sanitization\n // collisions distinct.\n const { owner, repo } = parseCloneUrl(cloneUrl);\n const slug = [owner, repo]\n .map(part =>\n (part ?? '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n // The previous replace collapsed runs, so at most one leading and\n // one trailing dash exist — no `+` needed, which keeps the pattern\n // linear on dash-heavy input.\n .replace(/^-/, '')\n .replace(/-$/, '')\n .slice(0, 24),\n )\n .filter(Boolean)\n .join('-');\n return `mastra-repo-${slug}-${hash}`;\n}\n\nfunction shaTag(sha: string): string {\n return `sha-${sha.slice(0, 12).toLowerCase()}`;\n}\n\n/**\n * Create a sha-tagged repo template spec for `E2BSandbox`.\n *\n * Returns undefined when {@link RepoTemplateOptions.getRepositoryAccess} is\n * absent, which is how a session with no repository asks for no template —\n * so a host can write `template: createRepoTemplate(ctx)` without a\n * conditional.\n *\n * Resolution is deferred: right before the exists-then-build check it\n * resolves the clone URL and credential, resolves the repository's current\n * default-branch head (`git ls-remote`, ~100ms, no clone), and keys the\n * template ref as `mastra-repo-<hash>:sha-<head>` — so a moved default\n * branch produces a fresh tagged build of the SAME template on the next new\n * session (rebuild-in-place), and an unmoved head reuses the existing\n * tagged build. When the head cannot be resolved the ref degrades to the\n * untagged name and the build clones whatever the default branch is at\n * build time.\n *\n * When the build itself fails — inaccessible repo, registry flake — the\n * sandbox falls back to its fallback template and the session's runtime\n * setup performs the full clone, so a broken build never wedges a session.\n */\nexport function createRepoTemplate(options: RepoTemplateOptions): DeferredNamedTemplateSpec | undefined {\n if (!options.getRepositoryAccess) return undefined;\n return {\n resolveSpec: async () => (await resolveSpecAtHead(options)).spec,\n };\n}\n\n/**\n * Resolve the clone URL and credential, resolve the current default-branch\n * head, and produce the concrete sha-tagged spec. Shared by the deferred\n * spec form and {@link refreshRepoTemplate}.\n *\n * A failed access call leaves no clone URL and throws, which the sandbox\n * turns into its default-template fallback rather than a failed start.\n */\nasync function resolveSpecAtHead(options: RepoTemplateOptions): Promise<{ spec: NamedTemplateSpec; sha?: string }> {\n const access = options.getRepositoryAccess ? await options.getRepositoryAccess().catch(() => undefined) : undefined;\n const cloneUrl = access?.cloneUrl;\n if (!cloneUrl) {\n throw new Error('Repo template has no clone URL: repository access returned none.');\n }\n assertCloneUrl(cloneUrl);\n const token = access?.authorization?.token;\n const buildEnv = typeof options.buildEnv === 'function' ? await options.buildEnv() : options.buildEnv;\n\n const resolved = await resolveDefaultBranchHead(cloneUrl, token).catch(() => undefined);\n const sha = resolved && SHA_PATTERN.test(resolved) ? resolved : undefined;\n\n const identity: RepoTemplateIdentity = {\n cloneUrl,\n ...(sha ? { sha } : {}),\n // Kept in its original shape (string vs array) so existing string-form\n // templates keep their hashes; omitted entirely when nothing would run.\n ...(normalizeSetupCommands(options.setupCommand).length > 0 ? { setupCommand: options.setupCommand } : {}),\n ...(buildEnv ? { buildEnv } : {}),\n ...(options.cpuCount !== undefined ? { cpuCount: options.cpuCount } : {}),\n ...(options.memoryMB !== undefined ? { memoryMB: options.memoryMB } : {}),\n ...(options.workingDirectory !== undefined\n ? { workingDirectory: trimTrailingSlashes(assertWorkingDirectory(options.workingDirectory)) }\n : {}),\n };\n return { spec: buildRepoTemplateSpec(identity, token), ...(sha ? { sha } : {}) };\n}\n\n/** Result of a {@link refreshRepoTemplate} call. */\nexport interface RefreshRepoTemplateResult {\n /** Template ref (`name:tag`) that is now current. */\n ref: string;\n /** Whether an up-to-date build already existed or a fresh build ran. */\n action: 'reused' | 'built';\n /** Resolved head sha, when it could be determined. */\n sha?: string;\n}\n\n/**\n * Ensure the repo template is built at the repository's current\n * default-branch head, building it (and moving the `current` tag) when it\n * is not. This is the same resolution the lazy sandbox-start path performs\n * — exposed standalone so template warming can be driven externally: call\n * it from a scheduled workflow (cron) or a merge-to-main event handler and\n * the next session boots warm instead of paying the build.\n *\n * The build is awaited; a build failure rejects so callers can observe it.\n * An unresolvable head degrades to the sha-less `name:current` form, same\n * as the lazy path.\n */\nexport async function refreshRepoTemplate(\n options: RepoTemplateOptions,\n connection?: ConnectionOpts,\n): Promise<RefreshRepoTemplateResult> {\n const { spec, sha } = await resolveSpecAtHead(options);\n const shaField = sha ? { sha } : {};\n if (await Template.exists(spec.ref, connection)) {\n return { ref: spec.ref, action: 'reused', ...shaField };\n }\n await Template.build(spec.template as TemplateClass, spec.ref, {\n ...connection,\n ...(spec.buildTags?.length ? { tags: spec.buildTags } : {}),\n ...spec.buildResources,\n });\n return { ref: spec.ref, action: 'built', ...shaField };\n}\n\n/**\n * The clone URL is the only untrusted input that reaches a build command,\n * so it is checked before it can be interpolated into one. The repoDir is\n * derived from it rather than supplied, so it needs no separate guard.\n */\n\nfunction assertCloneUrl(cloneUrl: string): void {\n if (!isValidCloneUrl(cloneUrl)) {\n throw new Error(`Invalid cloneUrl '${cloneUrl}': expected an https URL with a plain host and path`);\n }\n if (parseCloneUrl(cloneUrl).repo === '') {\n throw new Error(`Invalid cloneUrl '${cloneUrl}': expected a repository path such as https://host/owner/repo.git`);\n }\n}\n\n/**\n * In-shell git auth flag: computes a basic-auth header from the build env\n * var at execution time. The stored command contains only the env-var\n * REFERENCE — the token value never appears in the command string, and no\n * credential is written to the build filesystem.\n */\nfunction gitAuthFlag(): string {\n return `-c http.extraheader=\"AUTHORIZATION: basic $(printf 'x-access-token:%s' \"$${BUILD_TOKEN_ENV}\" | base64 -w0)\"`;\n}\n\nfunction buildRepoTemplateSpec(identity: RepoTemplateIdentity, token?: string): NamedTemplateSpec {\n const { sha, setupCommand, buildEnv, workingDirectory } = identity;\n const cloneUrl = normalizeCloneUrl(identity.cloneUrl);\n // Relative to the build cwd, which `setWorkdir` (or the base image) also\n // makes the runtime cwd, so the checkout sits at `<cwd>/<repo>` either way.\n const repoDir = repoDirName(cloneUrl);\n\n const auth = token ? `${gitAuthFlag()} ` : '';\n\n let template = createDefaultMountableTemplate().template;\n const env: Record<string, string> = { ...buildEnv };\n if (token) env[BUILD_TOKEN_ENV] = token;\n if (Object.keys(env).length > 0) {\n // Visible to build steps; probed to NOT persist into runtime sandbox\n // environments. Values must be short-lived — they stay in the template\n // definition until the next rebuild.\n template = template.setEnvs(env);\n }\n if (workingDirectory) {\n // Created by the build user so it is writable; `setWorkdir` then makes\n // it the cwd for the steps below and the runtime default, without\n // shell expansion.\n const dir = trimTrailingSlashes(workingDirectory);\n template = template.runCmd(`mkdir -p \"${dir}\"`).setWorkdir(dir);\n }\n // Each command gets its own cached build layer. Same shallow clone Factory\n // makes at session start when no image provided one, so both paths yield\n // the same checkout.\n template = template.runCmd(\n repoCloneCommand({ cloneUrl, destination: repoDir, ...(token ? { tokenEnv: BUILD_TOKEN_ENV } : {}) }),\n );\n if (sha) {\n // GitHub serves fetches of reachable shas, so pinning after a default\n // clone is reliable without full-history flags.\n template = template\n .runCmd(`git -C \"${repoDir}\" ${auth}fetch origin ${sha}`)\n .runCmd(`git -C \"${repoDir}\" checkout ${sha}`);\n }\n // Build steps use fresh shells, so each setup command needs its own `cd`.\n const setupCommands = normalizeSetupCommands(setupCommand);\n for (const command of setupCommands) {\n template = template.runCmd(`cd \"${repoDir}\" && ${command}`);\n }\n // Last, so it only exists in images where every step above succeeded.\n template = template.runCmd(setupMarkerCommand(setupMarkerContent(setupCommands)));\n\n return {\n ref: repoTemplateRef(identity),\n template,\n // A failed repo build degrades to the default mountable template; the\n // session's runtime cold clone into `$HOME` keeps working.\n //\n // Every successful build also moves the stable `current` tag; when a\n // moved head means the exact sha tag doesn't exist yet, the sandbox\n // boots from `name:current` immediately (runtime setup fast-forwards\n // the checkout) while the fresh sha builds in the background.\n staleRef: `${repoTemplateName(identity)}:${CURRENT_TAG}`,\n buildTags: [CURRENT_TAG],\n // Always explicit, so what gets built matches what got hashed.\n buildResources: {\n cpuCount: identity.cpuCount ?? DEFAULT_CPU_COUNT,\n memoryMB: identity.memoryMB ?? DEFAULT_MEMORY_MB,\n },\n };\n}\n\n/**\n * `owner/repo` for a github.com clone URL, else undefined. Only the public\n * host is API-resolvable: GitHub Enterprise and other forges keep the git\n * path.\n */\nfunction parseGithubRepo(cloneUrl: string): { owner: string; repo: string } | undefined {\n let url: URL;\n try {\n url = new URL(cloneUrl);\n } catch {\n return undefined;\n }\n if (url.hostname.toLowerCase() !== 'github.com') return undefined;\n const [owner, repo, ...rest] = url.pathname.split('/').filter(Boolean);\n if (!owner || !repo || rest.length > 0) return undefined;\n return { owner, repo: repo.replace(/\\.git$/i, '') };\n}\n\n/**\n * Resolve the repository's current default-branch head without cloning.\n * github.com repositories go through the REST API so resolution works\n * wherever the host runs, including images without a git binary; other\n * hosts use `git ls-remote <url> HEAD`, authenticated via an in-process\n * `http.extraheader` when a token is provided. Returns undefined when the\n * head cannot be resolved (inaccessible repo, offline, no git binary);\n * callers degrade to the untagged template ref.\n */\nasync function resolveDefaultBranchHead(cloneUrl: string, token?: string): Promise<string | undefined> {\n const github = parseGithubRepo(cloneUrl);\n if (github) {\n try {\n const response = await fetch(`https://api.github.com/repos/${github.owner}/${github.repo}/commits/HEAD`, {\n headers: {\n Accept: 'application/vnd.github.sha',\n 'X-GitHub-Api-Version': '2022-11-28',\n 'User-Agent': 'mastra-e2b',\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n },\n signal: AbortSignal.timeout(10_000),\n });\n if (!response.ok) return undefined;\n const sha = (await response.text()).trim();\n return SHA_PATTERN.test(sha) ? sha : undefined;\n } catch {\n return undefined;\n }\n }\n try {\n const authArgs = token\n ? ['-c', `http.extraheader=AUTHORIZATION: basic ${Buffer.from(`x-access-token:${token}`).toString('base64')}`]\n : [];\n // `--` makes the URL position unambiguous to git: even a hostile value\n // can never be read as an option such as `--upload-pack`.\n const { stdout } = await execFileAsync('git', [...authArgs, 'ls-remote', '--', cloneUrl, 'HEAD'], {\n timeout: 10_000,\n env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },\n });\n const sha = stdout.split(/\\s/, 1)[0];\n return sha && SHA_PATTERN.test(sha) ? sha : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Canonical form used for identity and for the build's clone: lowercase\n * host, no trailing `.git` or slash. Two spellings of one repository must\n * not produce two templates.\n */\nfunction normalizeCloneUrl(cloneUrl: string): string {\n // Avoid regex backtracking on long trailing-slash runs.\n let end = cloneUrl.length;\n while (end > 0 && cloneUrl[end - 1] === '/') end--;\n const withoutSuffix = cloneUrl.slice(0, end).replace(/\\.git$/i, '');\n return withoutSuffix.replace(/^(https:\\/\\/)([^/]+)/i, (_match, scheme: string, host: string) => {\n return `${scheme.toLowerCase()}${host.toLowerCase()}`;\n });\n}\n\n/**\n * Split a normalized clone URL into its host and trailing owner/repo pair.\n * Hosts that nest groups (GitLab subgroups) keep only the last two path\n * segments as owner/repo; the full URL still drives identity.\n */\nfunction parseCloneUrl(cloneUrl: string): { host: string; owner: string; repo: string } {\n const withoutScheme = normalizeCloneUrl(cloneUrl).replace(/^https:\\/\\//i, '');\n const [host = '', ...segments] = withoutScheme.split('/');\n const repo = segments.at(-1) ?? '';\n const owner = segments.length > 1 ? (segments.at(-2) ?? '') : '';\n return { host, owner, repo };\n}\n\n/** Normalize setup commands and drop blank entries that would produce invalid shell steps. */\nfunction normalizeSetupCommands(setupCommand: string | string[] | undefined): string[] {\n const list = setupCommand === undefined ? [] : Array.isArray(setupCommand) ? setupCommand : [setupCommand];\n return list.filter(command => command.trim() !== '');\n}\n\nfunction repoDirName(cloneUrl: string): string {\n const { repo } = parseCloneUrl(cloneUrl);\n return repo.replace(/[^\\w.-]/g, '-').replace(/^\\.+/, '') || 'repo';\n}\n\n// Avoid regex backtracking on long trailing-slash runs.\nfunction trimTrailingSlashes(path: string): string {\n let end = path.length;\n while (end > 1 && path[end - 1] === '/') end--;\n return path.slice(0, end);\n}\n\n/** Validate a literal absolute path before embedding it in shell build steps. */\nfunction assertWorkingDirectory(dir: string): string {\n const valid = /^\\/[A-Za-z0-9._/-]*$/.test(dir) && !dir.split('/').includes('..');\n if (!valid) {\n throw new Error(\n `Repo template workingDirectory must be an absolute path of plain path characters (got ${JSON.stringify(dir)}); ~ and $HOME are not expanded.`,\n );\n }\n return dir;\n}\n","/**\n * E2B sandbox provider descriptor for MastraEditor.\n *\n * @example\n * ```typescript\n * import { e2bSandboxProvider } from '@mastra/e2b';\n *\n * const editor = new MastraEditor({\n * sandboxes: [e2bSandboxProvider],\n * });\n * ```\n */\nimport type { SandboxProvider } from '@mastra/core/editor';\nimport { E2BSandbox } from './sandbox';\n\n/**\n * Serializable subset of E2BSandboxOptions for editor storage.\n * Non-serializable options (TemplateBuilder callbacks, runtime objects) are excluded.\n */\ninterface E2BProviderConfig {\n template?: string;\n timeout?: number;\n env?: Record<string, string>;\n metadata?: Record<string, unknown>;\n domain?: string;\n apiUrl?: string;\n apiKey?: string;\n accessToken?: string;\n}\n\nexport const e2bSandboxProvider: SandboxProvider<E2BProviderConfig> = {\n id: 'e2b',\n name: 'E2B Sandbox',\n description: 'Cloud sandbox powered by E2B',\n configSchema: {\n type: 'object',\n properties: {\n template: { type: 'string', description: 'Sandbox template ID' },\n timeout: { type: 'number', description: 'Execution timeout in milliseconds', default: 300000 },\n env: {\n type: 'object',\n description: 'Environment variables',\n additionalProperties: { type: 'string' },\n },\n metadata: {\n type: 'object',\n description: 'Custom metadata',\n additionalProperties: true,\n },\n domain: { type: 'string', description: 'Domain for self-hosted E2B' },\n apiUrl: { type: 'string', description: 'API URL for self-hosted E2B' },\n apiKey: { type: 'string', description: 'E2B API key' },\n accessToken: { type: 'string', description: 'E2B access token' },\n },\n },\n createSandbox: config => new E2BSandbox(config),\n};\n","/**\n * Code Mode — E2B transport\n *\n * The default {@link StdioCodeModeTransport} in `@mastra/core` writes the\n * runner/program files to the *host* tmpdir and spawns `node <hostPath>`. That\n * only works when the sandbox shares the host filesystem (e.g. `LocalSandbox`).\n * E2B runs the program in a remote micro-VM with its own filesystem, so the\n * host paths don't exist there and `node` exits immediately.\n *\n * `E2BCodeModeTransport` writes the runner/program *into* the sandbox via the\n * E2B files API and runs plain `node <runnerPath>` inside the VM. TypeScript is\n * stripped on the host with esbuild before upload, so it doesn't depend on the\n * sandbox's Node version (the core transport relies on\n * `node --experimental-strip-types`, which needs Node >= 22.6).\n *\n * The RPC frame protocol (host <-> runner) is unchanged: it reuses\n * `buildProgramModule`, `buildRunner`, and `FRAME_PREFIX` from\n * `@mastra/core/tools`.\n */\n\nimport { randomBytes } from 'node:crypto';\nimport { buildProgramModule, buildRunner, FRAME_PREFIX, sanitizeToolId } from '@mastra/core/tools';\nimport type { CodeModeRunnerFrame, CodeModeToolResult, CodeModeTransport } from '@mastra/core/tools';\nimport type { ProcessHandle } from '@mastra/core/workspace';\nimport { transformSync } from 'esbuild';\nimport { E2BSandbox } from '../sandbox';\n\n/** Base directory inside the E2B sandbox where Code Mode programs are written. */\nconst SANDBOX_TMP = '/home/user/mastra-code-mode';\n\n/**\n * Code Mode transport for {@link E2BSandbox}.\n *\n * Writes the generated program and runner into the sandbox filesystem, runs\n * `node` there, and bridges `external_*` RPC calls back to the host over the\n * process's stdout/stdin — the same frame protocol as the core stdio transport.\n *\n * @example\n * ```typescript\n * import { createCodeMode } from '@mastra/core/tools';\n * import { E2BSandbox, E2BCodeModeTransport } from '@mastra/e2b';\n *\n * const { tool, instructions } = createCodeMode(\n * { tools: { getWeather, getForecast }, sandbox: new E2BSandbox() },\n * new E2BCodeModeTransport(),\n * );\n * ```\n */\nexport class E2BCodeModeTransport implements CodeModeTransport {\n async run(opts: Parameters<CodeModeTransport['run']>[0]): Promise<CodeModeToolResult> {\n const { sandbox, program, toolIds, dispatch, timeout, abortSignal, onExternalCall, onExternalResult } = opts;\n\n if (!(sandbox instanceof E2BSandbox)) {\n throw new Error('E2BCodeModeTransport requires an E2BSandbox');\n }\n if (!sandbox.processes) {\n throw new Error('Sandbox has no process manager');\n }\n\n // Auto-start the sandbox so callers don't have to pre-start it. `start()`\n // is a no-op when already running.\n if (sandbox.status !== 'running') {\n await sandbox.start();\n }\n\n let e2b = sandbox.e2b;\n const externals = toolIds.map(toolId => ({ toolId, externalName: sanitizeToolId(toolId) }));\n const allowList = new Set(toolIds);\n\n const suffix = randomBytes(4).toString('hex');\n const dir = `${SANDBOX_TMP}/${suffix}`;\n const programPath = `${dir}/program-${suffix}.mjs`;\n const runnerPath = `${dir}/runner-${suffix}.mjs`;\n\n // Strip TypeScript on the host so the sandbox runs plain JS with no\n // experimental flag and no Node-version dependency.\n const programSource = transformSync(buildProgramModule(program), { loader: 'ts', target: 'es2022' }).code;\n const runnerSource = buildRunner({ programModule: `file://${programPath}`, externals });\n\n const logs: string[] = [];\n let stderr = '';\n let done: CodeModeToolResult | undefined;\n let stdoutBuffer = '';\n\n let resolveDone!: () => void;\n const donePromise = new Promise<void>(resolve => {\n resolveDone = resolve;\n });\n\n // Observer hooks are caller-supplied and best-effort: a throwing hook must\n // never prevent `respond()` from running, or the matching in-sandbox promise\n // would hang until the timeout.\n const notifyCall = (tool: string, args: unknown): void => {\n try {\n onExternalCall?.(tool, args);\n } catch {\n /* observer errors are non-fatal */\n }\n };\n const notifyResult = (tool: string, durationMs: number, error?: Error): void => {\n try {\n onExternalResult?.(tool, durationMs, error);\n } catch {\n /* observer errors are non-fatal */\n }\n };\n\n try {\n // `status` is a local field: E2B may have auto-paused the sandbox\n // server-side while it still reads 'running'. Retry the setup on a dead\n // sandbox (resume + reconnect). Only setup is retried so host tools are\n // never dispatched twice; `spawn()` below has its own retry.\n await sandbox.retryOnDead(async () => {\n e2b = sandbox.e2b;\n await e2b.files.makeDir(dir);\n await e2b.files.write(programPath, programSource);\n await e2b.files.write(runnerPath, runnerSource);\n });\n\n let handle: ProcessHandle;\n\n const respond = async (\n id: number,\n ok: boolean,\n result?: unknown,\n error?: { message: string; name?: string },\n ): Promise<void> => {\n await handle.sendStdin(JSON.stringify({ type: 'rpc-result', id, ok, result, error }) + '\\n');\n };\n\n const serveRpc = async (id: number, tool: string, args: unknown): Promise<void> => {\n const started = Date.now();\n notifyCall(tool, args);\n // Allow-list enforcement: never invoke a tool that wasn't exposed.\n if (!allowList.has(tool)) {\n notifyResult(tool, Date.now() - started, new Error('not allowed'));\n await respond(id, false, undefined, {\n message: `Tool \"${tool}\" is not available in Code Mode`,\n name: 'NotAllowedError',\n });\n return;\n }\n try {\n const result = await dispatch(tool, args);\n notifyResult(tool, Date.now() - started);\n await respond(id, true, result);\n } catch (error) {\n const err = error as { message?: string; name?: string };\n notifyResult(tool, Date.now() - started, error instanceof Error ? error : new Error(String(error)));\n await respond(id, false, undefined, {\n message: err?.message ?? String(error),\n name: err?.name,\n });\n }\n };\n\n const handleFrame = (frame: CodeModeRunnerFrame): void => {\n switch (frame.type) {\n case 'log':\n logs.push(frame.message);\n return;\n case 'done':\n done = frame.ok\n ? { success: true, result: frame.result, logs }\n : { success: false, error: frame.error, logs };\n resolveDone();\n return;\n case 'rpc':\n // `serveRpc` awaits `respond`, which writes to the child's stdin and\n // can reject if the process already exited/was killed. Swallow that\n // so it never surfaces as an unhandled rejection.\n void serveRpc(frame.id, frame.tool, frame.args).catch(() => {});\n return;\n }\n };\n\n handle = await sandbox.processes.spawn(`node ${runnerPath}`, {\n cwd: dir,\n abortSignal,\n // E2B failures are otherwise silent, which makes them painful to debug.\n // Capture stderr and surface it in Timeout/NoResult errors below.\n onStderr: (chunk: string) => {\n stderr += chunk;\n },\n onStdout: (chunk: string) => {\n stdoutBuffer += chunk;\n let idx: number;\n while ((idx = stdoutBuffer.indexOf('\\n')) >= 0) {\n const line = stdoutBuffer.slice(0, idx);\n stdoutBuffer = stdoutBuffer.slice(idx + 1);\n if (!line.startsWith(FRAME_PREFIX)) continue;\n let frame: CodeModeRunnerFrame;\n try {\n frame = JSON.parse(line.slice(FRAME_PREFIX.length));\n } catch {\n continue;\n }\n handleFrame(frame);\n }\n },\n });\n\n // Race completion against process exit and the timeout. Including process\n // exit means a runner that dies without emitting `done` resolves\n // immediately instead of waiting out the full timeout.\n let timer: NodeJS.Timeout | undefined;\n const timeoutPromise = new Promise<'timeout'>(resolve => {\n timer = setTimeout(() => resolve('timeout'), timeout);\n });\n const exitPromise = handle.wait().then(() => 'exited' as const);\n\n const outcome = await Promise.race([\n donePromise.then(() => 'done' as const),\n exitPromise.catch(() => 'exited' as const),\n timeoutPromise,\n ]);\n if (timer) clearTimeout(timer);\n\n if (outcome === 'timeout') {\n await handle.kill().catch(() => {});\n return {\n success: false,\n logs,\n error: {\n message: `Code Mode execution timed out after ${timeout}ms${stderr ? `\\nstderr: ${stderr}` : ''}`,\n name: 'TimeoutError',\n },\n };\n }\n\n // Either `done` arrived or the process exited. If we raced ahead of a\n // `done` frame still in flight, give it a brief beat to land.\n if (!done) {\n await exitPromise.catch(() => {});\n }\n\n return (\n done ?? {\n success: false,\n logs,\n error: {\n message: `Program exited without returning a result${stderr ? `\\nstderr: ${stderr}` : ''}`,\n name: 'NoResultError',\n },\n }\n );\n } finally {\n await e2b.files.remove(dir).catch(() => {});\n }\n }\n}\n"],"mappings":"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"}