{"version":3,"file":"index.cjs","names":["ProcessHandle","UnsupportedStdinCloseError","SandboxProcessManager","MastraSandbox","SandboxNotReadyError","Daytona","SandboxState","DaytonaNotFoundError","DaytonaGoneError"],"sources":["../src/utils/compact.ts","../src/utils/shell-quote.ts","../src/sandbox/mounts/types.ts","../src/sandbox/mounts/s3-credentials.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"],"sourcesContent":["/**\n * Returns a shallow copy of the object with all undefined values removed.\n */\nexport function compact<T extends object>(obj: T): T {\n  return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined)) as T;\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","/**\n * Shared types for Daytona mount operations.\n */\n\nimport type { Sandbox } from '@daytonaio/sdk';\n\nimport type { DaytonaAzureBlobMountConfig } from './azure';\nimport type { DaytonaGCSMountConfig } from './gcs';\nimport type { DaytonaS3MountConfig } from './s3';\n\nexport const LOG_PREFIX = '[@mastra/daytona]';\n\n/**\n * Union of mount configs supported by Daytona sandbox.\n */\nexport type DaytonaMountConfig = DaytonaS3MountConfig | DaytonaGCSMountConfig | DaytonaAzureBlobMountConfig;\n\n/**\n * Context for mount operations.\n * Abstracts over the Daytona SDK so mount helpers stay SDK-agnostic.\n */\nexport interface MountContext {\n  run: (cmd: string, timeoutMs?: number) => Promise<{ exitCode: number; stdout: string; stderr: string }>;\n  writeFile: (path: string, content: string) => Promise<void>;\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\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 * Only http and https schemes are allowed.\n */\nexport function validateEndpoint(endpoint: string): void {\n  let parsed: URL;\n  try {\n    parsed = new URL(endpoint);\n  } catch {\n    throw new Error(`Invalid endpoint URL: \"${endpoint}\"`);\n  }\n  if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n    throw new Error(`Invalid endpoint URL scheme: \"${parsed.protocol}\". Only http: and https: are allowed.`);\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/**\n * Result of running a command in the Daytona sandbox.\n *\n * Note: Daytona's `executeCommand` returns a single combined string (stdout + stderr).\n * There is no separate stderr stream. If you need stderr isolated, redirect it in the\n * shell command itself (e.g. `2>/dev/null` or `2>&1`).\n */\nexport interface CommandResult {\n  exitCode: number;\n  /** Combined stdout/stderr output from the command. */\n  output: string;\n}\n\n/**\n * Run a command in the Daytona sandbox.\n *\n * Thin wrapper around `sandbox.process.executeCommand` that converts timeout\n * from milliseconds to seconds and null-coalesces the output string.\n *\n * Does NOT throw on non-zero exit codes — callers should check `exitCode`.\n */\nexport async function runCommand(\n  sandbox: Sandbox,\n  command: string,\n  options?: { timeout?: number },\n): Promise<CommandResult> {\n  const result = await sandbox.process.executeCommand(\n    command,\n    undefined, // cwd\n    undefined, // env\n    options?.timeout !== undefined ? Math.ceil(options.timeout / 1000) : undefined,\n  );\n\n  return {\n    exitCode: result.exitCode,\n    output: result.result ?? '',\n  };\n}\n","import { createHash } from 'node:crypto';\n\nimport { shellQuote } from '../../utils/shell-quote';\nimport { LOG_PREFIX } from './types';\nimport type { MountContext } from './types';\n\nexport function s3CredentialsPrefix(mountPath: string): string {\n  return `/tmp/.mastra-s3-${createHash('sha256').update(mountPath.replace(/\\/$/, '')).digest('hex')}-`;\n}\n\n/** Remove credentials only after their s3fs process has exited, including after reconnects. */\nexport async function cleanupS3Credentials(\n  mountPath: string,\n  ctx: Pick<MountContext, 'run' | 'logger'>,\n): Promise<void> {\n  // The path hash associates each attempt with its original mount, even if recovery moved it.\n  // Inspect processes, not just /proc/mounts: lazy unmount can leave a daemon using the file.\n  const script = `test -r /proc/self/comm || exit 1\ncredentials_in_use() {\n  for process in /proc/[0-9]*; do\n    test -d \"$process\" || continue\n    name=$(cat \"$process/comm\" 2>/dev/null) || {\n      test -d \"$process\" && return 0\n      continue\n    }\n    test \"$name\" = s3fs || continue\n    args=$(tr '\\\\000' '\\\\n' < \"$process/cmdline\") || {\n      test -d \"$process\" && return 0\n      continue\n    }\n    printf '%s\\\\n' \"$args\" | grep -Fxq -- \"passwd_file=$directory/credentials\" && return 0\n  done\n  return 1\n}\nresult=0\nfor directory in ${shellQuote(s3CredentialsPrefix(mountPath))}*; do\n  test -d \"$directory\" && test ! -L \"$directory\" || continue\n  attempt=0\n  while credentials_in_use && test \"$attempt\" -lt 20; do\n    sleep 0.25\n    attempt=$((attempt + 1))\n  done\n  if credentials_in_use; then\n    result=1\n    continue\n  fi\n  rm -f -- \"$directory/credentials\" && rmdir -- \"$directory\" || result=1\ndone\nexit \"$result\"`;\n  try {\n    const result = await ctx.run(`sh -c ${shellQuote(script)}`, 30_000);\n    if (result.exitCode !== 0) {\n      ctx.logger.warn(`${LOG_PREFIX} S3 credentials retained: daemon still active or cleanup could not be verified`);\n    }\n  } catch {\n    ctx.logger.warn(`${LOG_PREFIX} Could not clean up S3 credentials`);\n  }\n}\n","import { randomUUID } from 'node:crypto';\n\nimport type { FilesystemMountConfig } from '@mastra/core/workspace';\n\nimport { shellQuote } from '../../utils/shell-quote';\nimport { s3CredentialsPrefix } from './s3-credentials';\nimport { LOG_PREFIX, validateEndpoint, validatePrefix, validateS3BucketName } from './types';\nimport type { MountContext } from './types';\n\n/**\n * S3 mount config for Daytona (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 DaytonaS3MountConfig 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, R2, 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  /** Session token for temporary credentials. Not automatically refreshed after mounting. */\n  sessionToken?: 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: DaytonaS3MountConfig, ctx: MountContext): Promise<void> {\n  const { run, writeFile, logger } = ctx;\n\n  validateS3BucketName(config.bucket);\n  if (config.endpoint) {\n    validateEndpoint(config.endpoint);\n  }\n\n  const quotedMountPath = shellQuote(mountPath);\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  if (config.sessionToken && !hasCredentials) {\n    throw new Error('sessionToken requires accessKeyId and secretAccessKey.');\n  }\n\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  // For S3-compatible storage (R2, MinIO, etc.), check connectivity to the custom endpoint.\n  // AWS S3 endpoints are whitelisted in Daytona's proxy so no check needed for the default case.\n  if (config.endpoint) {\n    const endpoint = config.endpoint.replace(/\\/$/, '');\n    const connectivityCheck = await run(`curl -sS --max-time 5 ${shellQuote(endpoint)} 2>&1`, 10_000);\n    const checkOutput = connectivityCheck.stdout.trim();\n    if (\n      connectivityCheck.exitCode !== 0 ||\n      checkOutput.toLowerCase().includes('restricted') ||\n      checkOutput.toLowerCase().includes('blocked')\n    ) {\n      throw new Error(\n        `Cannot reach ${endpoint} from this sandbox. ` +\n          `S3-compatible storage mounting requires network access to the configured endpoint, ` +\n          `which may be blocked on Daytona's restricted tiers. ` +\n          `Upgrade to a tier with unrestricted internet access, or contact Daytona support to remove the network restriction.` +\n          (checkOutput ? `\\n\\nSandbox network response: ${checkOutput}` : ''),\n      );\n    }\n  }\n\n  // Install s3fs if not present\n  const checkResult = await run('which s3fs 2>/dev/null || echo \"not found\"', 30_000);\n  if (checkResult.stdout.includes('not found')) {\n    logger.warn(`${LOG_PREFIX} s3fs not found, attempting runtime installation...`);\n    logger.info(`${LOG_PREFIX} Tip: For faster startup, pre-install s3fs in your sandbox image`);\n\n    await run('sudo apt-get update -qq 2>&1', 60_000);\n\n    // The fuse package's post-install script may fail in containers (e.g. can't run modprobe,\n    // can't set SUID). Use || true so the overall command succeeds even if dpkg exits non-zero,\n    // then verify the binary is actually present below.\n    await run('sudo apt-get install -y s3fs fuse 2>&1 || sudo apt-get install -y s3fs-fuse fuse 2>&1 || true', 120_000);\n\n    // Verify installation\n    const s3fsCheck = await run('which s3fs 2>/dev/null || echo \"not found\"', 30_000);\n    if (s3fsCheck.stdout.includes('not found')) {\n      throw new Error('Failed to install s3fs: binary not found after install attempt');\n    }\n  }\n\n  // The fuse post-install script may fail to set the SUID bit on fusermount.\n  // Set it explicitly so non-root processes can call fusermount.\n  await run('sudo chmod u+s /usr/bin/fusermount3 /usr/bin/fusermount 2>/dev/null || true', 30_000);\n\n  // Get uid/gid for proper file ownership\n  const idResult = await run('id -u && id -g', 30_000);\n  const [uid, gid] = idResult.stdout.trim().split('\\n');\n  const validUidGid = uid && gid && /^\\d+$/.test(uid) && /^\\d+$/.test(gid);\n  if (!validUidGid) {\n    logger.warn(\n      `${LOG_PREFIX} Unexpected uid/gid format: \"${idResult.stdout.trim()}\" — mounted files will be owned by root`,\n    );\n  }\n\n  // A fresh private directory protects uploaded secrets even if the SDK replaces the file.\n  const credentialsDirectory = `${s3CredentialsPrefix(mountPath)}${randomUUID()}`;\n  const credentialsPath = `${credentialsDirectory}/credentials`;\n\n  // Allow non-root processes to use FUSE and the allow_other mount option.\n  // These are no-ops if already configured.\n  await run(\n    `sudo chmod a+rw /dev/fuse 2>/dev/null || true; ` +\n      `sudo bash -c 'grep -q \"^user_allow_other\" /etc/fuse.conf 2>/dev/null || echo \"user_allow_other\" >> /etc/fuse.conf' 2>/dev/null || true`,\n  );\n\n  let credentialsCreated = false;\n  let mountAttempted = false;\n  try {\n    if (config.accessKeyId && config.secretAccessKey) {\n      const prepared = await run(`mkdir -m 700 ${shellQuote(credentialsDirectory)}`, 30_000);\n      if (prepared.exitCode !== 0) {\n        throw new Error('Failed to create private S3 credentials directory');\n      }\n      credentialsCreated = true;\n      // s3fs's colon-delimited password format cannot carry a session token.\n      // Source a mount-specific environment file instead, keeping secrets out of commands and logs.\n      const credentials = config.sessionToken\n        ? [\n            `export AWS_ACCESS_KEY_ID=${shellQuote(config.accessKeyId)}`,\n            `export AWS_SECRET_ACCESS_KEY=${shellQuote(config.secretAccessKey)}`,\n            `export AWS_SESSION_TOKEN=${shellQuote(config.sessionToken)}`,\n          ].join('\\n')\n        : `${config.accessKeyId}:${config.secretAccessKey}`;\n      await writeFile(credentialsPath, credentials);\n      const protectedFile = await run(`chmod 600 ${shellQuote(credentialsPath)}`, 30_000);\n      if (protectedFile.exitCode !== 0) {\n        throw new Error('Failed to restrict S3 credentials file permissions');\n      }\n    }\n\n    const mountOptions: string[] = [];\n\n    if (hasCredentials) {\n      mountOptions.push(config.sessionToken ? 'use_session_token' : `passwd_file=${credentialsPath}`);\n    } else {\n      mountOptions.push('public_bucket=1');\n      logger.debug(`${LOG_PREFIX} No credentials provided, mounting as public bucket (read-only)`);\n    }\n\n    // allow_other: let other users (e.g. root for rmdir) access the mount.\n    // Requires user_allow_other in /etc/fuse.conf for non-root mounts.\n    mountOptions.push('allow_other');\n\n    if (validUidGid) {\n      mountOptions.push(`uid=${uid}`, `gid=${gid}`);\n    }\n\n    if (config.endpoint) {\n      const endpoint = config.endpoint.replace(/\\/$/, '');\n      mountOptions.push(`url=${shellQuote(endpoint)}`, 'use_path_request_style', 'sigv4', 'nomultipart');\n    }\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    // Run s3fs as the sandbox user (not root) so the FUSE connection is registered\n    // in the container's user namespace — allowing fusermount -u to unmount it later.\n    const credentialEnv = config.sessionToken ? `. ${shellQuote(credentialsPath)} && ` : '';\n    const mountCmd = `${credentialEnv}s3fs ${shellQuote(bucketArg)} ${quotedMountPath} -o ${mountOptions.join(' -o ')}`;\n    logger.debug(`${LOG_PREFIX} Mounting S3:`, hasCredentials ? mountCmd.replace(credentialsPath, '***') : mountCmd);\n\n    mountAttempted = true;\n    const result = await run(mountCmd, 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    // Check FUSE access without enumerating a potentially large remote directory.\n    // The daemon parent can exit successfully before a disconnected mount is detected.\n    const probe = await run(`timeout -k 5s 15s stat -L -- ${quotedMountPath} > /dev/null`, 30_000);\n    if (probe.exitCode !== 0) {\n      throw new Error(`S3 mount is not readable (exit ${probe.exitCode}): ${probe.stderr || probe.stdout}`);\n    }\n  } finally {\n    // Exported credentials live in the daemon environment; it never sources this staging file again.\n    // After a launch attempt, unmount cleanup verifies that s3fs no longer needs its password file.\n    if (credentialsCreated && (config.sessionToken || !mountAttempted)) {\n      try {\n        const cleanup = await run(\n          `rm -f ${shellQuote(credentialsPath)} && rmdir ${shellQuote(credentialsDirectory)}`,\n          30_000,\n        );\n        if (cleanup.exitCode !== 0) {\n          logger.warn(`${LOG_PREFIX} Failed to remove S3 credentials`);\n        }\n      } catch {\n        logger.warn(`${LOG_PREFIX} Failed to remove S3 credentials`);\n      }\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 Daytona (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 DaytonaGCSMountConfig 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   * Optional prefix (subdirectory) to mount instead of the entire bucket.\n   * Passed to gcsfuse as `--only-dir`. Leading/trailing slashes are normalized.\n   */\n  prefix?: string;\n}\n\n/**\n * Mount a GCS bucket using gcsfuse.\n */\nexport async function mountGCS(mountPath: string, config: DaytonaGCSMountConfig, ctx: MountContext): Promise<void> {\n  const { run, writeFile, logger } = ctx;\n\n  validateGCSBucketName(config.bucket);\n\n  const quotedMountPath = shellQuote(mountPath);\n\n  // gcsfuse needs to reach Google Cloud Storage APIs at runtime.\n  // Daytona's free/restricted tiers block access to Google services.\n  // Fail fast with a clear message instead of hanging on the mount command.\n  const connectivityCheck = await run('curl -sS --max-time 5 http://storage.googleapis.com 2>&1', 10_000);\n  const checkOutput = connectivityCheck.stdout.trim();\n  // Daytona's restricted tiers return HTTP 200 with a plain-text restriction message\n  // for HTTP requests, or reset the connection for HTTPS. Detect either case.\n  if (\n    connectivityCheck.exitCode !== 0 ||\n    checkOutput.toLowerCase().includes('restricted') ||\n    checkOutput.toLowerCase().includes('blocked')\n  ) {\n    throw new Error(\n      `Cannot reach Google Cloud Storage from this sandbox. ` +\n        `GCS mounting requires network access to storage.googleapis.com, ` +\n        `which may be blocked on Daytona's restricted tiers. ` +\n        `Upgrade to a tier with unrestricted internet access, or contact Daytona support to remove the network restriction.` +\n        (checkOutput ? `\\n\\nSandbox network response: ${checkOutput}` : ''),\n    );\n  }\n\n  // Install gcsfuse if not present\n  const checkResult = await run('which gcsfuse 2>/dev/null || echo \"not found\"', 30_000);\n  if (checkResult.stdout.includes('not found')) {\n    logger.warn(`${LOG_PREFIX} gcsfuse not found, attempting runtime installation...`);\n    logger.info(`${LOG_PREFIX} Tip: For faster startup, pre-install gcsfuse in your sandbox image`);\n\n    // Ensure curl and gpg are available for downloading the gcsfuse apt key.\n    // Do NOT pre-install fuse here — the fuse package post-install script fails in containers\n    // (can't run modprobe), leaving dpkg in a broken state that prevents gcsfuse from installing.\n    // The gcsfuse apt package handles the fuse/fuse3 dependency automatically when installed.\n    await run('sudo apt-get update -qq 2>&1', 60_000);\n    const prepResult = await run('sudo apt-get install -y curl gnupg 2>&1', 120_000);\n    if (prepResult.exitCode !== 0) {\n      throw new Error(\n        `Failed to install gcsfuse prerequisites (curl, gnupg): ${prepResult.stderr || prepResult.stdout}`,\n      );\n    }\n\n    // Detect distro ID and codename from /etc/os-release (more reliable than lsb_release).\n    // Google's gcsfuse apt repo only has packages for certain codenames (e.g. bookworm, jammy).\n    // If the detected codename has no repo (e.g. trixie, noble), fall back to a known-good\n    // codename for the distro family: bookworm for Debian, jammy for Ubuntu.\n    const distroIdResult = await run(\n      'cat /etc/os-release 2>/dev/null | grep \"^ID=\" | cut -d= -f2 || echo debian',\n      30_000,\n    );\n    const distroId = distroIdResult.stdout.trim().replace(/\"/g, '') || 'debian';\n\n    // Pick the appropriate known-good fallback for this distro family\n    const fallbackCodename = distroId === 'ubuntu' ? 'jammy' : 'bookworm';\n\n    const codenameResult = await run(\n      `cat /etc/os-release 2>/dev/null | grep \"^VERSION_CODENAME=\" | cut -d= -f2 || echo ${fallbackCodename}`,\n      30_000,\n    );\n    const detectedCodename = codenameResult.stdout.trim() || fallbackCodename;\n    if (!/^[a-z0-9][a-z0-9-]*$/.test(detectedCodename)) {\n      throw new Error(`Invalid distro codename for gcsfuse repo: \"${detectedCodename}\"`);\n    }\n\n    logger.debug(`${LOG_PREFIX} Detected distro: ${distroId}/${detectedCodename}, fallback: ${fallbackCodename}`);\n\n    // Set up the gcsfuse apt repository. Use separate curl + gpg steps (not piped)\n    // so a curl failure propagates as non-zero exit rather than being masked by gpg.\n    const repoSetup = await run(\n      'sudo mkdir -p /etc/apt/keyrings && ' +\n        'curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg -o /tmp/gcsfuse-key.gpg && ' +\n        'sudo gpg --batch --yes --dearmor -o /etc/apt/keyrings/gcsfuse.gpg /tmp/gcsfuse-key.gpg && ' +\n        `echo \"deb [signed-by=/etc/apt/keyrings/gcsfuse.gpg] https://packages.cloud.google.com/apt gcsfuse-${detectedCodename} main\" | sudo tee /etc/apt/sources.list.d/gcsfuse.list`,\n      30_000,\n    );\n    if (repoSetup.exitCode !== 0) {\n      throw new Error(`Failed to set up gcsfuse apt repository: ${repoSetup.stderr || repoSetup.stdout}`);\n    }\n\n    // apt-get update may fail on unrelated repos (e.g. broken keys); use || true and verify install separately\n    await run('sudo apt-get update -qq 2>&1 || true', 60_000);\n\n    let installResult = await run('sudo apt-get install -y gcsfuse 2>&1', 120_000);\n\n    // Fallback: if install failed with detected codename (e.g. trixie, noble — no repo yet),\n    // retry with a known-good codename for the distro family.\n    if (installResult.exitCode !== 0 && detectedCodename !== fallbackCodename) {\n      logger.warn(\n        `${LOG_PREFIX} gcsfuse install failed for \"${detectedCodename}\", retrying with \"${fallbackCodename}\" fallback`,\n      );\n      await run(\n        'sudo rm -f /etc/apt/sources.list.d/gcsfuse.list && ' +\n          `echo \"deb [signed-by=/etc/apt/keyrings/gcsfuse.gpg] https://packages.cloud.google.com/apt gcsfuse-${fallbackCodename} main\" | sudo tee /etc/apt/sources.list.d/gcsfuse.list`,\n        10_000,\n      );\n      await run('sudo apt-get update -qq 2>&1 || true', 60_000);\n      installResult = await run('sudo apt-get install -y gcsfuse 2>&1', 120_000);\n    }\n\n    // Verify installation by checking the binary directly.\n    // dpkg may report a non-zero exit if fuse's post-install script fails in containers\n    // (can't run modprobe), but gcsfuse is still unpacked and usable in that case.\n    const verifyResult = await run('which gcsfuse 2>/dev/null || echo \"not found\"', 30_000);\n    if (verifyResult.stdout.includes('not found')) {\n      throw new Error(`Failed to install gcsfuse: ${installResult.stderr || installResult.stdout}`);\n    }\n    if (installResult.exitCode !== 0) {\n      logger.warn(\n        `${LOG_PREFIX} gcsfuse install reported dpkg errors (likely fuse post-install in container) but binary is present — proceeding`,\n      );\n    }\n  }\n\n  // Get uid/gid for proper file ownership\n  const idResult = await run('id -u && id -g', 30_000);\n  const [uid, gid] = idResult.stdout.trim().split('\\n');\n  const validUidGid = uid && gid && /^\\d+$/.test(uid) && /^\\d+$/.test(gid);\n  if (!validUidGid) {\n    logger.warn(\n      `${LOG_PREFIX} Unexpected uid/gid format: \"${idResult.stdout.trim()}\" — mounted files will be owned by root`,\n    );\n  }\n  // Note: gcsfuse uses --uid/--gid flags, not -o uid=X style\n  const uidGidFlags = validUidGid ? `--uid=${uid} --gid=${gid}` : '';\n\n  // Allow non-root processes to use FUSE and the allow_other mount option.\n  // These are no-ops if already configured.\n  await run(\n    `sudo chmod a+rw /dev/fuse 2>/dev/null || true; ` +\n      `sudo bash -c 'grep -q \"^user_allow_other\" /etc/fuse.conf 2>/dev/null || echo \"user_allow_other\" >> /etc/fuse.conf' 2>/dev/null || true`,\n  );\n\n  // Scope the mount to a prefix (subdirectory) via gcsfuse --only-dir, so sandbox\n  // paths map to prefixed GCS keys instead of the bucket root. Mirrors the S3 mount.\n  let onlyDirFlag = '';\n  if (config.prefix) {\n    const normalizedPrefix = validatePrefix(config.prefix);\n    onlyDirFlag = `--only-dir=${shellQuote(normalizedPrefix)} `;\n  }\n\n  const hasCredentials = !!config.serviceAccountKey;\n  // Infer directories from object prefixes. GCS has no real directories — a\n  // \"folder\" only exists implicitly as a shared prefix of object names. Without\n  // --implicit-dirs, an object written to the bucket via the GCS API without a\n  // placeholder \"directory\" object (e.g. an SDK/gsutil upload of foo/bar.txt\n  // with no foo/ marker) is unreachable in the mount: it isn't listed, and it\n  // can't be read by full path. Common when the mount reads bucket contents\n  // produced by another process. See gcsfuse docs \"implicit directories\".\n  const implicitDirsFlag = '--implicit-dirs';\n  // Run gcsfuse as the sandbox user (not root) so the FUSE connection is registered\n  // in the container's user namespace — allowing fusermount -u to unmount it later.\n  let mountCmd: string;\n\n  if (hasCredentials) {\n    // Use a mount-specific key path to avoid races with concurrent mounts\n    const mountHash = createHash('md5').update(mountPath).digest('hex').slice(0, 8);\n    const keyPath = `/tmp/gcs-key-${mountHash}.json`;\n    await run(`sudo rm -f ${shellQuote(keyPath)}`, 30_000);\n    await writeFile(keyPath, config.serviceAccountKey!);\n    await run(`chmod 600 ${shellQuote(keyPath)}`, 30_000);\n\n    mountCmd = `gcsfuse --key-file=${shellQuote(keyPath)} ${implicitDirsFlag} ${onlyDirFlag}-o allow_other ${uidGidFlags} ${shellQuote(config.bucket)} ${quotedMountPath}`;\n  } else {\n    logger.debug(`${LOG_PREFIX} No credentials provided, mounting GCS as public bucket (read-only)`);\n    mountCmd = `gcsfuse --anonymous-access ${implicitDirsFlag} ${onlyDirFlag}-o allow_other ${uidGidFlags} ${shellQuote(config.bucket)} ${quotedMountPath}`;\n  }\n\n  logger.debug(`${LOG_PREFIX} Mounting GCS:`, mountCmd);\n\n  const result = await run(mountCmd, 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}\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 Daytona (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 DaytonaAzureBlobMountConfig 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.\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: DaytonaAzureBlobMountConfig): 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(\n  mountPath: string,\n  config: DaytonaAzureBlobMountConfig,\n  ctx: MountContext,\n): Promise<void> {\n  const { run, writeFile, logger } = ctx;\n\n  validateContainerName(config.container);\n  const auth = resolveAuth(config);\n  const prefix = config.prefix ? validatePrefix(config.prefix) : undefined;\n\n  const quotedMountPath = shellQuote(mountPath);\n\n  const curlCheck = await run('which curl 2>/dev/null || echo \"not found\"', 30_000);\n  if (curlCheck.stdout.includes('not found')) {\n    const curlInstall = await run('sudo apt-get update -qq 2>&1 && sudo apt-get install -y curl 2>&1', 120_000);\n    if (curlInstall.exitCode !== 0) {\n      throw new Error(\n        `Failed to install curl for Azure Blob reachability check: ${curlInstall.stderr || curlInstall.stdout}`,\n      );\n    }\n  }\n\n  // Verify network reachability to the blob endpoint. Daytona's restricted tiers\n  // block traffic to azure.com domains, which would otherwise hang the mount.\n  const probeUrl = auth.endpoint\n    ? auth.endpoint.replace(/\\/$/, '')\n    : `https://${auth.accountName}.blob.core.windows.net`;\n  const connectivityCheck = await run(`curl -sS --max-time 5 ${shellQuote(probeUrl)} 2>&1`, 10_000);\n  const checkOutput = connectivityCheck.stdout.trim();\n  if (\n    connectivityCheck.exitCode !== 0 ||\n    checkOutput.toLowerCase().includes('restricted') ||\n    checkOutput.toLowerCase().includes('blocked')\n  ) {\n    throw new Error(\n      `Cannot reach ${probeUrl} from this sandbox. ` +\n        `Azure Blob mounting requires network access to the storage endpoint, ` +\n        `which may be blocked on Daytona's restricted tiers. ` +\n        `Upgrade to a tier with unrestricted internet access, or contact Daytona support to remove the network restriction.` +\n        (checkOutput ? `\\n\\nSandbox network response: ${checkOutput}` : ''),\n    );\n  }\n\n  // Install blobfuse2 if not present\n  const checkResult = await run('which blobfuse2 2>/dev/null || echo \"not found\"', 30_000);\n  if (checkResult.stdout.includes('not found')) {\n    logger.warn(`${LOG_PREFIX} blobfuse2 not found, attempting runtime installation...`);\n    logger.info(`${LOG_PREFIX} Tip: For faster startup, pre-install blobfuse2 in your sandbox image`);\n\n    await run('sudo apt-get update -qq 2>&1', 60_000);\n    const prepResult = await run('sudo apt-get install -y curl gnupg 2>&1', 120_000);\n    if (prepResult.exitCode !== 0) {\n      throw new Error(\n        `Failed to install blobfuse2 prerequisites (curl, gnupg): ${prepResult.stderr || prepResult.stdout}`,\n      );\n    }\n\n    const osReleaseResult = await run('cat /etc/os-release 2>/dev/null || true', 30_000);\n    const repos = resolveMicrosoftAptRepos(osReleaseResult.stdout);\n\n    const repoSetup = await 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      30_000,\n    );\n\n    let installResult: { exitCode: number; stdout: string; stderr: string } | undefined;\n    if (repoSetup.exitCode === 0) {\n      for (const { repoUrl, suite } of repos) {\n        await 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          30_000,\n        );\n        await run('sudo apt-get update -qq 2>&1 || true', 60_000);\n        installResult = await run('sudo apt-get install -y blobfuse2 fuse3 2>&1', 120_000);\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 run('which blobfuse2 && blobfuse2 --version', 30_000);\n    if (verifyResult.exitCode !== 0) {\n      installResult = await 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        180_000,\n      );\n      verifyResult = await run('which blobfuse2 && blobfuse2 --version', 30_000);\n    }\n\n    if (!installResult || verifyResult.exitCode !== 0) {\n      throw new Error(\n        `Failed to install blobfuse2: ${\n          verifyResult.stderr ||\n          verifyResult.stdout ||\n          installResult?.stderr ||\n          installResult?.stdout ||\n          'unknown error'\n        }`,\n      );\n    }\n  }\n\n  // Get uid/gid for proper file ownership of the cache directory\n  const idResult = await run('id -u && id -g', 30_000);\n  const [uid, gid] = idResult.stdout.trim().split('\\n');\n  const validUidGid = uid && gid && /^\\d+$/.test(uid) && /^\\d+$/.test(gid);\n\n  // Allow non-root processes to use FUSE and the allow_other mount option.\n  await run(\n    `sudo chmod a+rw /dev/fuse 2>/dev/null || true; ` +\n      `sudo bash -c 'grep -q \"^user_allow_other\" /etc/fuse.conf 2>/dev/null || echo \"user_allow_other\" >> /etc/fuse.conf' 2>/dev/null || true`,\n  );\n\n  // Use a mount-specific config + cache path to avoid races with concurrent mounts.\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\n  const yaml = buildBlobfuseConfig(config.container, auth, cachePath, !!config.readOnly);\n\n  await run(`sudo rm -f ${shellQuote(configPath)}`, 30_000);\n  await writeFile(configPath, yaml);\n  await run(`chmod 600 ${shellQuote(configPath)}`, 30_000);\n\n  // blobfuse2 requires an empty cache directory when mounting.\n  await run(`sudo rm -rf ${shellQuote(cachePath)} && mkdir -p ${shellQuote(cachePath)}`, 30_000);\n  if (validUidGid) {\n    await run(`sudo chown ${uid}:${gid} ${shellQuote(cachePath)} 2>/dev/null || true`, 30_000);\n  }\n\n  // Run blobfuse2 as the sandbox user (not root) so the FUSE connection is registered\n  // in the user namespace — allowing fusermount -u to unmount it later.\n  const prefixFlags = prefix ? ` --virtual-directory=true --subdirectory=${shellQuote(prefix)}` : '';\n  const mountCmd = `blobfuse2 mount ${quotedMountPath} --config-file=${shellQuote(configPath)}${prefixFlags}`;\n  logger.debug(`${LOG_PREFIX} Mounting Azure Blob:`, mountCmd);\n\n  const result = await run(mountCmd, 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}\n","/**\n * Daytona Process Manager\n *\n * Implements SandboxProcessManager for Daytona cloud sandboxes.\n * Wraps the Daytona SDK's session API (createSession, executeSessionCommand,\n * getSessionCommandLogs, deleteSession) for background process management.\n *\n * Each spawn() creates a dedicated session with a single command.\n * The user command is wrapped in a subshell `(command)` so that:\n * - `exit N` exits the subshell, not the session shell\n * - Heredocs are contained within the subshell\n * - The session command finishes cleanly\n */\n\nimport type { Sandbox } from '@daytonaio/sdk';\nimport { ProcessHandle, UnsupportedStdinCloseError, SandboxProcessManager } from '@mastra/core/workspace';\nimport type { CommandResult, ProcessInfo, SpawnProcessOptions } from '@mastra/core/workspace';\nimport { shellQuote } from '../utils/shell-quote';\nimport type { DaytonaSandbox } from './index';\n\n// =============================================================================\n// Daytona Process Handle\n// =============================================================================\n\n/**\n * Wraps a Daytona session + command pair to conform to Mastra's ProcessHandle.\n * Not exported — internal to this module.\n */\nclass DaytonaProcessHandle extends ProcessHandle {\n  readonly pid: string;\n\n  private readonly _cmdId: string;\n  private readonly _sandbox: Sandbox;\n  private readonly _startTime: number;\n  private readonly _timeout?: number;\n\n  private _exitCode: number | undefined;\n  private _waitPromise: Promise<CommandResult> | null = null;\n  private _streamingPromise: Promise<void> | null = null;\n  private _killed = false;\n\n  constructor(sessionId: string, cmdId: string, sandbox: Sandbox, startTime: number, options?: SpawnProcessOptions) {\n    super(options);\n    this.pid = sessionId;\n    this._cmdId = cmdId;\n    this._sandbox = sandbox;\n    this._startTime = startTime;\n    this._timeout = options?.timeout;\n  }\n\n  get exitCode(): number | undefined {\n    return this._exitCode;\n  }\n\n  /** @internal Set by the process manager after streaming starts. */\n  set streamingPromise(p: Promise<void>) {\n    this._streamingPromise = p;\n\n    // Auto-resolve exit code when streaming ends (so exitCode is available without wait())\n    p.then(() => this._resolveExitCode()).catch(() => this._resolveExitCode());\n  }\n\n  /** Fetch the exit code from Daytona and set _exitCode. No-op if already set. */\n  private async _resolveExitCode(): Promise<void> {\n    if (this._exitCode !== undefined) return;\n    try {\n      const cmd = await this._sandbox.process.getSessionCommand(this.pid, this._cmdId);\n      this._exitCode = cmd.exitCode ?? 0;\n    } catch {\n      if (this._exitCode === undefined) {\n        this._exitCode = 1;\n      }\n    }\n  }\n\n  async wait(): Promise<CommandResult> {\n    // Idempotent — cache the promise so repeated calls return the same result\n    if (!this._waitPromise) {\n      this._waitPromise = this._doWait();\n    }\n    return this._waitPromise;\n  }\n\n  private async _doWait(): Promise<CommandResult> {\n    // Race streaming against timeout (if configured)\n    const streamDone = this._streamingPromise ?? Promise.resolve();\n\n    if (this._timeout) {\n      let timeoutId: ReturnType<typeof setTimeout> | undefined;\n      const timeoutPromise = new Promise<never>((_, reject) => {\n        timeoutId = setTimeout(() => reject(new Error(`Command timed out after ${this._timeout}ms`)), this._timeout);\n      });\n\n      try {\n        await Promise.race([streamDone, timeoutPromise]);\n      } catch (error) {\n        // On timeout, kill the process and return partial output\n        if (error instanceof Error && error.message.includes('timed out')) {\n          await this.kill();\n          this._exitCode = 124; // Standard timeout exit code\n          return {\n            success: false,\n            exitCode: 124,\n            stdout: this.stdout,\n            stderr: this.stderr || error.message,\n            executionTimeMs: Date.now() - this._startTime,\n            killed: true,\n            timedOut: true,\n          };\n        }\n        throw error;\n      } finally {\n        clearTimeout(timeoutId);\n      }\n    } else {\n      // No timeout — just wait for streaming to complete\n      await streamDone.catch(() => {});\n    }\n\n    // If killed during wait, return with kill exit code\n    if (this._killed) {\n      return {\n        success: false,\n        exitCode: this._exitCode ?? 137,\n        stdout: this.stdout,\n        stderr: this.stderr,\n        executionTimeMs: Date.now() - this._startTime,\n        killed: true,\n        timedOut: false,\n      };\n    }\n\n    // Ensure exit code is resolved\n    await this._resolveExitCode();\n\n    return {\n      success: this._exitCode === 0,\n      exitCode: this._exitCode ?? 1,\n      stdout: this.stdout,\n      stderr: this.stderr,\n      executionTimeMs: Date.now() - this._startTime,\n    };\n  }\n\n  async kill(): Promise<boolean> {\n    if (this._exitCode !== undefined) return false;\n    this._killed = true;\n    this._exitCode = 137; // SIGKILL\n    try {\n      await this._sandbox.process.deleteSession(this.pid);\n    } catch {\n      // Session may already be gone\n    }\n    return true;\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    await this._sandbox.process.sendSessionCommandInput(this.pid, this._cmdId, data);\n  }\n\n  async closeStdin(): Promise<void> {\n    throw new UnsupportedStdinCloseError('Daytona SDK does not expose a way to close stdin for a running process');\n  }\n}\n\n// =============================================================================\n// Daytona Process Manager\n// =============================================================================\n\nexport interface DaytonaProcessManagerOptions {\n  /** Default timeout in milliseconds for commands that don't specify one. */\n  defaultTimeout?: number;\n}\n\n/**\n * Daytona implementation of SandboxProcessManager.\n * Uses the Daytona SDK's session API with one session per spawned process.\n */\nexport class DaytonaProcessManager extends SandboxProcessManager<DaytonaSandbox> {\n  private _spawnCounter = 0;\n  private readonly _defaultTimeout?: number;\n\n  constructor(opts: DaytonaProcessManagerOptions = {}) {\n    super();\n    this._defaultTimeout = opts.defaultTimeout;\n  }\n\n  async spawn(command: string, options: SpawnProcessOptions = {}): Promise<ProcessHandle> {\n    // Apply default timeout and default cwd: per-command cwd wins, then an\n    // explicitly configured workingDirectory, then the first mount path so\n    // that relative paths resolve inside the FUSE mount instead of\n    // /home/daytona. The probe-filled base field deliberately does not\n    // participate — it just reports the session home.\n    const effectiveOptions = {\n      ...options,\n      timeout: options.timeout ?? this._defaultTimeout,\n      cwd: options.cwd ?? this.sandbox.explicitWorkingDirectory ?? this.sandbox.mounts?.entries?.keys().next().value,\n    };\n\n    // The base spawn wrapper already merged the sandbox env into options.env\n    const envs = Object.fromEntries(\n      Object.entries(effectiveOptions.env ?? {}).filter((entry): entry is [string, string] => entry[1] !== undefined),\n    );\n\n    // Validate/build before retryOnDead so user-controlled validation errors\n    // cannot be mistaken for Daytona dead-sandbox errors.\n    const sessionCommand = buildSpawnCommand(command, effectiveOptions.cwd, envs);\n\n    return this.sandbox.retryOnDead(async () => {\n      const sandbox = this.sandbox.daytona;\n\n      // Unique session ID per spawn — used as the PID\n      const sessionId = `mastra-proc-${Date.now().toString(36)}-${++this._spawnCounter}`;\n\n      await sandbox.process.createSession(sessionId);\n\n      const { cmdId } = await sandbox.process.executeSessionCommand(sessionId, {\n        command: sessionCommand,\n        runAsync: true,\n      });\n\n      const handle = new DaytonaProcessHandle(sessionId, cmdId, sandbox, Date.now(), effectiveOptions);\n\n      // Start streaming logs — route to handle's emitters\n      const streamingPromise = sandbox.process\n        .getSessionCommandLogs(\n          sessionId,\n          cmdId,\n          (chunk: string) => handle.emitStdout(chunk),\n          (chunk: string) => handle.emitStderr(chunk),\n        )\n        .catch(() => {\n          // Stream ends when session is deleted (e.g., after kill) — swallow the error\n        });\n\n      handle.streamingPromise = streamingPromise;\n\n      this._tracked.set(handle.pid, handle);\n      return handle;\n    });\n  }\n\n  async list(): Promise<ProcessInfo[]> {\n    const result: ProcessInfo[] = [];\n    for (const [pid, handle] of this._tracked) {\n      result.push({\n        pid,\n        command: handle.command,\n        running: handle.exitCode === undefined,\n        exitCode: handle.exitCode,\n      });\n    }\n    return result;\n  }\n}\n\n// =============================================================================\n// Command Building\n// =============================================================================\n\nconst SHELL_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\n/**\n * Build a shell command string that bakes in cwd and env vars.\n * Wraps the user command in a subshell `(command)` so that:\n * - `exit N` exits the subshell, not the session shell\n * - Heredocs work correctly within the subshell\n *\n * @example\n * buildSpawnCommand('npm test', '/app', { NODE_ENV: 'test' })\n * // → \"export NODE_ENV='test' && cd '/app' && (npm test)\"\n */\nfunction buildSpawnCommand(command: string, cwd: string | undefined, envs: Record<string, string>): string {\n  const parts: string[] = [];\n\n  for (const [k, v] of Object.entries(envs)) {\n    if (!SHELL_IDENTIFIER_PATTERN.test(k)) {\n      throw new Error(`Invalid environment variable name: ${JSON.stringify(k)}`);\n    }\n    parts.push(`export ${k}=${shellQuote(v)}`);\n  }\n\n  if (cwd) {\n    parts.push(`cd ${shellQuote(cwd)}`);\n  }\n\n  // Wrap in subshell to isolate exit codes and heredocs\n  parts.push(`(${command})`);\n\n  return parts.join(' && ');\n}\n","/**\n * Daytona Sandbox Provider\n *\n * A Daytona sandbox implementation for Mastra workspaces.\n * Supports command execution, environment variables, resource configuration,\n * snapshots, Daytona volumes, and FUSE-based cloud filesystem mounting (S3, GCS).\n *\n * @see https://www.daytona.io/docs\n */\n\nimport { Daytona, DaytonaGoneError, DaytonaNotFoundError, SandboxState } from '@daytonaio/sdk';\nimport type {\n  ComputerUse,\n  CreateSandboxFromImageParams,\n  CreateSandboxFromSnapshotParams,\n  Sandbox,\n  VolumeMount,\n} from '@daytonaio/sdk';\nimport type {\n  SandboxInfo,\n  ProviderStatus,\n  MastraSandboxOptions,\n  WorkspaceFilesystem,\n  MountResult,\n  FilesystemMountConfig,\n  MountManager,\n  CommandResult,\n  ExecuteCommandOptions,\n  SandboxComputer,\n  SandboxNetworking,\n  SandboxFileInput,\n  SandboxCloneOptions,\n  SandboxStartResult,\n} from '@mastra/core/workspace';\nimport { MastraSandbox, SandboxNotReadyError, assertModesUnsupported } from '@mastra/core/workspace';\n\nimport { compact } from '../utils/compact';\nimport { shellQuote } from '../utils/shell-quote';\nimport { mountS3, mountGCS, mountAzure, LOG_PREFIX, runCommand } from './mounts';\nimport type { DaytonaMountConfig, MountContext } from './mounts';\nimport { cleanupS3Credentials } from './mounts/s3-credentials';\nimport { DaytonaProcessManager } from './process-manager';\nimport type { DaytonaResources } from './types';\n\n/** Allowlist pattern for mount paths — absolute path with safe characters only. */\nconst SAFE_MOUNT_PATH = /^\\/[a-zA-Z0-9_.\\-/]+$/;\n\n/** Default timeout for mount lifecycle shell commands (mkdir, unmount, proc reads, etc.) */\nconst MOUNT_COMMAND_TIMEOUT_MS = 30_000;\n\n/** Convert an unknown error to a readable string. */\nfunction errorToString(error: unknown): string {\n  if (error instanceof Error) return error.message;\n  if (typeof error === 'string') return error;\n  if (error && typeof error === 'object' && 'message' in error) {\n    const maybeError = error as { message?: unknown };\n    if (typeof maybeError.message === 'string') {\n      return maybeError.message;\n    }\n  }\n  try {\n    return JSON.stringify(error);\n  } catch {\n    return String(error);\n  }\n}\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  const segments = mountPath.split('/');\n  if (mountPath.includes('//') || segments.some(segment => segment === '.' || segment === '..')) {\n    throw new Error(`Invalid mount path: ${mountPath}. Path traversal segments are not allowed.`);\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/** Default port of the noVNC web viewer started by Daytona computer use. */\nconst DEFAULT_NOVNC_PORT = 6080;\n\n/** Patterns indicating the sandbox is dead/gone (@daytonaio/sdk@0.143.0). */\nconst SANDBOX_DEAD_PATTERNS: RegExp[] = [\n  /sandbox is not running/i,\n  /sandbox already destroyed/i,\n  /sandbox.*not found/i,\n  /failed to resolve container IP/i,\n  /is the sandbox started/i,\n];\n\n// =============================================================================\n// Daytona Sandbox Options\n// =============================================================================\n\n/**\n * Daytona sandbox provider configuration.\n */\nexport interface DaytonaSandboxOptions extends Omit<MastraSandboxOptions, 'processes'> {\n  /** Unique identifier for this sandbox instance */\n  id?: string;\n  /** API key for authentication. Falls back to DAYTONA_API_KEY env var. */\n  apiKey?: string;\n  /** API URL. Falls back to DAYTONA_API_URL env var or https://app.daytona.io/api. */\n  apiUrl?: string;\n  /** Target runner region. Falls back to DAYTONA_TARGET env var. */\n  target?: string;\n  /**\n   * Default execution timeout in milliseconds.\n   * @default 300_000 // 5 minutes\n   */\n  timeout?: number;\n  /**\n   * Sandbox runtime language.\n   * @default 'typescript'\n   */\n  language?: 'typescript' | 'javascript' | 'python';\n  /** Resource allocation for the sandbox */\n  resources?: DaytonaResources;\n  /** Environment variables to set in the sandbox */\n  env?: Record<string, string>;\n  /** Custom metadata labels */\n  labels?: Record<string, string>;\n  /** Pre-built snapshot ID to create sandbox from. Takes precedence over resources/image. */\n  snapshot?: string;\n  /**\n   * Docker image to use for sandbox creation. When set, triggers image-based creation.\n   * Can optionally be combined with `resources` for custom resource allocation.\n   * Has no effect when `snapshot` is set.\n   */\n  image?: string;\n  /**\n   * Whether the sandbox should be ephemeral. If true, autoDeleteInterval will be set to 0\n   * (delete immediately on stop).\n   * @default false\n   */\n  ephemeral?: boolean;\n  /**\n   * Auto-stop interval in minutes (0 = disabled).\n   * @default 15\n   */\n  autoStopInterval?: number;\n  /**\n   * Auto-archive interval in minutes (0 = maximum interval, which is 7 days).\n   * @default 7 days\n   */\n  autoArchiveInterval?: number;\n  /**\n   * Daytona volumes to attach at creation.\n   * Volumes are configured at sandbox creation time, not mounted dynamically.\n   */\n  volumes?: Array<VolumeMount>;\n  /** Sandbox display name */\n  name?: string;\n  /** OS user to use for the sandbox */\n  user?: string;\n  /** Whether the sandbox port preview is public */\n  public?: boolean;\n  /**\n   * Auto-delete interval in minutes (negative = disabled, 0 = delete immediately on stop).\n   * @default disabled\n   */\n  autoDeleteInterval?: number;\n  /** Whether to block all network access for the sandbox */\n  networkBlockAll?: boolean;\n  /** Comma-separated list of allowed CIDR network addresses for the sandbox */\n  networkAllowList?: string;\n  /**\n   * Comma-separated list of allowed domains for the sandbox, e.g.\n   * `'registry.npmjs.org,*.githubusercontent.com'`.\n   *\n   * Use this instead of {@link networkAllowList} for services whose IP addresses\n   * change. Daytona defines and enforces the policy; this option selects it.\n   */\n  domainAllowList?: string;\n  /**\n   * Daytona Secrets to expose inside the sandbox, mapping environment variable\n   * names to Daytona Secret names (e.g. `{ GITHUB_TOKEN: 'github-token' }`).\n   *\n   * The environment variable holds an opaque placeholder; Daytona's egress\n   * proxy substitutes the real value into HTTPS request headers toward the\n   * Secret's allowed hosts, so the raw value never enters the sandbox.\n   * Secrets are created at the organization level (Daytona dashboard or SDK).\n   */\n  secrets?: Record<string, string>;\n  /**\n   * Computer-use (desktop) capability configuration.\n   *\n   * Set to `true` or provide an options object to expose the `computer`\n   * capability and emit the `mastra_workspace_computer_*` workspace tools.\n   * The desktop processes (Xvfb, xfce4, x11vnc, noVNC) are started lazily on\n   * the first computer operation.\n   *\n   * @default false\n   */\n  computerUse?:\n    | boolean\n    | {\n        /**\n         * Automatically start the desktop processes on the first computer\n         * operation. Set to `false` if you manage\n         * `sandbox.daytona.computerUse.start()` yourself.\n         * @default true\n         */\n        autoStart?: boolean;\n        /**\n         * Port of the noVNC web viewer inside the sandbox, used by\n         * `computer.streamUrl()`.\n         * @default 6080\n         */\n        noVncPort?: number;\n      };\n}\n\n// =============================================================================\n// Daytona Sandbox Implementation\n// =============================================================================\n\n/**\n * Daytona sandbox provider for Mastra workspaces.\n *\n * Features:\n * - Isolated cloud sandbox via Daytona SDK\n * - Multi-runtime support (TypeScript, JavaScript, Python)\n * - Resource configuration (CPU, memory, disk)\n * - Volume attachment at creation time\n * - FUSE-based cloud filesystem mounting (S3, GCS)\n * - Automatic sandbox timeout handling with retry\n *\n * @example Basic usage\n * ```typescript\n * import { Workspace } from '@mastra/core/workspace';\n * import { DaytonaSandbox } from '@mastra/daytona';\n *\n * const sandbox = new DaytonaSandbox({\n *   timeout: 60000,\n *   language: 'typescript',\n * });\n *\n * const workspace = new Workspace({ sandbox });\n * const result = await workspace.executeCode('console.log(\"Hello!\")');\n * ```\n *\n * @example With resources and volumes\n * ```typescript\n * const sandbox = new DaytonaSandbox({\n *   resources: { cpu: 2, memory: 4, disk: 6 },\n *   volumes: [{ volumeId: 'vol-123', mountPath: '/data' }],\n *   env: { NODE_ENV: 'production' },\n * });\n * ```\n */\nexport class DaytonaSandbox extends MastraSandbox {\n  readonly id: string;\n  readonly name = 'DaytonaSandbox';\n  readonly provider = 'daytona';\n\n  declare readonly mounts: MountManager; // Non-optional (initialized by base class when mount() exists)\n\n  /**\n   * Networking capability: public HTTPS URLs for sandbox ports.\n   * Daytona exposes ports through preview links (`getPreviewLink(port)`) —\n   * if the port is closed it is opened automatically. Private sandboxes\n   * require the preview token; pass `public: true` for tokenless URLs\n   * (required for sandbox deploys).\n   *\n   * When not attached in this process, the sandbox is looked up by identity\n   * (`daytona.get()` does not start it), so other processes can resolve\n   * deployments without waking a stopped sandbox.\n   */\n  readonly networking: SandboxNetworking = {\n    getPortUrl: async (port: number): Promise<string | null> => {\n      try {\n        const sandbox = this._sandbox ?? (await this.lookupDetachedSandbox());\n        if (!sandbox) return null;\n        const preview = await sandbox.getPreviewLink(port);\n        return preview?.url ?? null;\n      } catch {\n        return null;\n      }\n    },\n  };\n\n  /**\n   * Computer-use (desktop) capability: screenshot, mouse, and keyboard control\n   * of the sandbox's desktop environment via Daytona's computer use API.\n   *\n   * Available when the sandbox is constructed with `computerUse: true` or an\n   * options object. Desktop processes are started lazily on the first operation\n   * unless `computerUse.autoStart` is `false`.\n   */\n  declare readonly computer?: SandboxComputer;\n\n  status: ProviderStatus = 'pending';\n\n  private _daytona: Daytona | null = null;\n  private _sandbox: Sandbox | null = null;\n  private _createdAt: Date | null = null;\n  private _isRetrying = false;\n  private _computerUseStarted: Promise<void> | null = null;\n  private readonly computerUseAutoStart: boolean;\n  private readonly noVncPort: number;\n\n  private readonly timeout: number;\n  private readonly language: 'typescript' | 'javascript' | 'python';\n  private readonly resources?: DaytonaResources;\n\n  private readonly labels: Record<string, string>;\n  private readonly snapshotId?: string;\n  private readonly image?: string;\n  private readonly ephemeral: boolean;\n  private readonly autoStopInterval?: number;\n  private readonly autoArchiveInterval?: number;\n  private readonly autoDeleteInterval?: number;\n  private readonly volumeConfigs: Array<VolumeMount>;\n  private readonly sandboxName?: string;\n  private _daytonaSandboxId?: string;\n  private readonly sandboxUser?: string;\n  private readonly sandboxPublic?: boolean;\n  private readonly networkBlockAll?: boolean;\n  private readonly networkAllowList?: string;\n  private readonly domainAllowList?: string;\n  private readonly secrets?: Record<string, string>;\n  private readonly connectionOpts: { apiKey?: string; apiUrl?: string; target?: string };\n  private readonly _constructorOptions: DaytonaSandboxOptions;\n\n  /**\n   * The `workingDirectory` option as explicitly configured, as distinct from\n   * the probe-filled base field. The process manager's cwd fallback uses only\n   * this value so the runtime probe (which just reports the session home)\n   * never displaces the FUSE-mount default for relative paths.\n   * @internal\n   */\n  readonly explicitWorkingDirectory?: string;\n\n  constructor(options: DaytonaSandboxOptions = {}) {\n    super({\n      ...options,\n      name: 'DaytonaSandbox',\n      processes: new DaytonaProcessManager({\n        defaultTimeout: options.timeout ?? 300_000,\n      }),\n    });\n\n    this.id = options.id ?? this.generateId();\n    this.explicitWorkingDirectory = options.workingDirectory;\n    this.timeout = options.timeout ?? 300_000;\n    this.language = options.language ?? 'typescript';\n    this.resources = options.resources;\n    this.labels = options.labels ?? {};\n    this.snapshotId = options.snapshot;\n    this.image = options.image;\n    this.ephemeral = options.ephemeral ?? false;\n    this.autoStopInterval = options.autoStopInterval ?? 15;\n    this.autoArchiveInterval = options.autoArchiveInterval;\n    this.autoDeleteInterval = options.autoDeleteInterval;\n    this.volumeConfigs = options.volumes ?? [];\n    this.sandboxName = options.name ?? this.id;\n    this.sandboxUser = options.user;\n    this.sandboxPublic = options.public;\n    this.networkBlockAll = options.networkBlockAll;\n    this.networkAllowList = options.networkAllowList;\n    this.domainAllowList = options.domainAllowList;\n    this.secrets = options.secrets;\n\n    this.connectionOpts = {\n      ...(options.apiKey !== undefined && { apiKey: options.apiKey }),\n      ...(options.apiUrl !== undefined && { apiUrl: options.apiUrl }),\n      ...(options.target !== undefined && { target: options.target }),\n    };\n    this._constructorOptions = { ...options };\n\n    const computerUseOption = options.computerUse;\n    this.computerUseAutoStart = typeof computerUseOption === 'object' ? (computerUseOption.autoStart ?? true) : true;\n    this.noVncPort =\n      typeof computerUseOption === 'object' ? (computerUseOption.noVncPort ?? DEFAULT_NOVNC_PORT) : DEFAULT_NOVNC_PORT;\n    if (computerUseOption === true || typeof computerUseOption === 'object') {\n      this.computer = this.createComputer();\n    }\n  }\n\n  private generateId(): string {\n    return `daytona-sandbox-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n  }\n\n  /**\n   * Construct a sibling `DaytonaSandbox` that inherits this sandbox's\n   * configuration (credentials, snapshot/image, resources, network policy)\n   * with per-instance overrides.\n   *\n   * Performs no I/O — the sandbox clone provisions (or reconnects to an\n   * existing Daytona 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 Daytona's `autoStopInterval`\n   * (minutes); `options.sandboxId` is ignored because Daytona reconnects by\n   * logical `id`.\n   */\n  clone(options: SandboxCloneOptions = {}): DaytonaSandbox {\n    const { id: _id, name: _name, ...base } = this._constructorOptions;\n    return new DaytonaSandbox({\n      ...base,\n      ...(options.id !== undefined && { id: options.id }),\n      ...(options.env !== undefined && { env: options.env }),\n      ...(options.idleTimeoutMinutes !== undefined && { autoStopInterval: options.idleTimeoutMinutes }),\n    });\n  }\n\n  /**\n   * Get the underlying Daytona Sandbox instance for direct access to Daytona APIs.\n   *\n   * Use this when you need to access Daytona features not exposed through the\n   * WorkspaceSandbox interface (e.g., filesystem API, git operations, LSP).\n   *\n   * @throws {SandboxNotReadyError} If the sandbox has not been started\n   *\n   * @example Direct file operations\n   * ```typescript\n   * await sandbox.start();\n   * const daytonaSandbox = sandbox.daytona;\n   * await daytonaSandbox.fs.uploadFile(Buffer.from('Hello'), '/tmp/test.txt');\n   * ```\n   */\n  get daytona(): Sandbox {\n    if (!this._sandbox) {\n      throw new SandboxNotReadyError(this.id);\n    }\n    return this._sandbox;\n  }\n\n  /** @deprecated Use `daytona` instead. */\n  get instance(): Sandbox {\n    return this.daytona;\n  }\n\n  // ---------------------------------------------------------------------------\n  // Lifecycle\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Acquisition primitives (base-orchestrated start): the base derives\n   * `created` structurally from whether an existing sandbox was found, so\n   * reconnecting to one with the same logical ID reports `connected`.\n   * Lookup errors other than not-found propagate deliberately — creating a\n   * duplicate sandbox on a transient/auth error would be worse than failing.\n   */\n  protected override async find(): Promise<Sandbox | undefined> {\n    if (this._sandbox) {\n      return this._sandbox;\n    }\n\n    // Create Daytona client if not exists\n    if (!this._daytona) {\n      this._daytona = new Daytona(this.connectionOpts);\n    }\n\n    return (await this.findExistingSandbox()) ?? undefined;\n  }\n\n  protected override async connect(existing: Sandbox): Promise<void> {\n    if (existing === this._sandbox) {\n      return;\n    }\n\n    // Wake a stopped/archived sandbox before adopting it.\n    if (existing.state !== SandboxState.STARTED) {\n      this.logger.debug(`${LOG_PREFIX} Restarting sandbox ${existing.id} (state: ${existing.state})`);\n      await this.waitForStableStateAndStart(existing);\n    }\n\n    this._sandbox = existing;\n    this._daytonaSandboxId = existing.id;\n    this._createdAt = existing.createdAt ? new Date(existing.createdAt) : new Date();\n    this.logger.debug(`${LOG_PREFIX} Reconnected to existing sandbox ${existing.id} for: ${this.id}`);\n\n    // Reconcile FUSE mounts — clean up stale mounts from a previous session\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    await this.detectWorkingDir();\n  }\n\n  protected override async create(): Promise<void> {\n    // find() always runs first through the base ladder and constructs the\n    // client, so reaching here without one means create() was called directly.\n    if (!this._daytona) {\n      this._daytona = new Daytona(this.connectionOpts);\n    }\n\n    this.logger.debug(`${LOG_PREFIX} Creating sandbox for: ${this.id}`);\n\n    // Base params shared by both creation modes\n    const baseParams = compact({\n      language: this.language,\n      labels: { ...this.labels, 'mastra-sandbox-id': this.id },\n      ephemeral: this.ephemeral,\n      autoStopInterval: this.autoStopInterval,\n      autoArchiveInterval: this.autoArchiveInterval,\n      autoDeleteInterval: this.autoDeleteInterval,\n      volumes: this.volumeConfigs.length > 0 ? this.volumeConfigs : undefined,\n      name: this.sandboxName,\n      user: this.sandboxUser,\n      public: this.sandboxPublic,\n      networkBlockAll: this.networkBlockAll,\n      networkAllowList: this.networkAllowList,\n      domainAllowList: this.domainAllowList,\n      secrets: this.secrets,\n    });\n\n    // Snapshot takes precedence. Image alone (with optional resources) triggers image-based creation.\n    // Resources without image fall back to snapshot-based creation (resources are ignored).\n    if (this.resources && !this.image) {\n      this.logger.warn(\n        `${LOG_PREFIX} 'resources' option requires 'image' to take effect — falling back to snapshot-based creation without custom resources`,\n      );\n    }\n\n    const createParams: CreateSandboxFromSnapshotParams | CreateSandboxFromImageParams =\n      this.image && !this.snapshotId\n        ? (compact({\n            ...baseParams,\n            image: this.image,\n            resources: this.resources,\n          }) satisfies CreateSandboxFromImageParams)\n        : (compact({ ...baseParams, snapshot: this.snapshotId }) satisfies CreateSandboxFromSnapshotParams);\n\n    // Create sandbox\n    this._sandbox = await this._daytona.create(createParams);\n    this._daytonaSandboxId = this._sandbox.id;\n\n    this.logger.debug(`${LOG_PREFIX} Created sandbox ${this._sandbox.id} for logical ID: ${this.id}`);\n    this._createdAt = new Date();\n    await this.detectWorkingDir();\n  }\n\n  /**\n   * Stop the Daytona sandbox.\n   * Unmounts all filesystems, then stops the sandbox.\n   */\n  async stop(): Promise<void> {\n    if (!this._sandbox) {\n      // Not attached in this process — stop by identity without starting it.\n      try {\n        const existing = await this.lookupDetachedSandbox();\n        if (existing && existing.state === SandboxState.STARTED) {\n          await this._daytona!.stop(existing);\n        }\n      } catch {\n        // Best-effort stop; sandbox may not exist or may already be stopped\n      }\n      return;\n    }\n\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    if (this._daytona) {\n      try {\n        await this._daytona.stop(this._sandbox);\n      } catch {\n        // Best-effort stop; sandbox may already be stopped\n      }\n    }\n    this._sandbox = null;\n    this._computerUseStarted = null;\n  }\n\n  /**\n   * Destroy the Daytona sandbox and clean up all resources.\n   * Deletes the sandbox and clears all state.\n   */\n  async destroy(): Promise<void> {\n    if (this._sandbox && this._daytona) {\n      try {\n        await this._daytona.delete(this._sandbox);\n      } catch (error) {\n        if (!(error instanceof DaytonaNotFoundError) && !(error instanceof DaytonaGoneError)) {\n          throw error;\n        }\n      }\n    } else if (!this._sandbox) {\n      // Not attached in this process — delete by identity without starting it.\n      // Also covers orphan cleanup when _start() failed after the SDK created\n      // a server-side sandbox (e.g. bad image → BUILD_FAILED).\n      try {\n        const orphan = await this.lookupDetachedSandbox();\n        if (orphan) {\n          await this._daytona!.delete(orphan);\n        }\n      } catch (error) {\n        if (!(error instanceof DaytonaNotFoundError) && !(error instanceof DaytonaGoneError)) {\n          throw error;\n        }\n      }\n    }\n\n    this._sandbox = null;\n    this._daytonaSandboxId = undefined;\n    this._daytona = null;\n    this._computerUseStarted = null;\n    this.mounts?.clear();\n  }\n\n  /**\n   * Check if the sandbox is ready for operations.\n   */\n  async isReady(): Promise<boolean> {\n    return this.status === 'running' && this._sandbox !== null;\n  }\n\n  /**\n   * Get information about the current state of the sandbox.\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: this.mounts\n        ? Array.from(this.mounts.entries).map(([path, entry]) => ({\n            path,\n            filesystem: entry.filesystem?.provider ?? entry.config?.type ?? 'unknown',\n          }))\n        : [],\n      ...(this._sandbox && {\n        resources: {\n          cpuCores: this._sandbox.cpu,\n          memoryMB: this._sandbox.memory * 1024,\n          diskMB: this._sandbox.disk * 1024,\n        },\n      }),\n      metadata: {\n        language: this.language,\n        ephemeral: this.ephemeral,\n        ...(this.snapshotId && { snapshot: this.snapshotId }),\n        ...(this.image && { image: this.image }),\n        ...(this._sandbox && { target: this._sandbox.target }),\n      },\n    };\n  }\n\n  /**\n   * Get instructions describing this Daytona sandbox.\n   * Used by agents to understand the execution environment.\n   */\n  getInstructions(): string {\n    const parts: string[] = [];\n\n    const mountCount = this.mounts.entries.size;\n    const mountInfo = mountCount > 0 ? ` ${mountCount} filesystem(s) mounted via FUSE.` : '';\n    parts.push(`Cloud sandbox with isolated execution (${this.language} runtime).${mountInfo}`);\n\n    if (this.workingDirectory) {\n      parts.push(`Default working directory: ${this.workingDirectory}.`);\n    }\n\n    parts.push(`Command timeout: ${Math.ceil(this.timeout / 1000)}s.`);\n\n    parts.push(`Running as user: ${this.sandboxUser ?? 'daytona'}.`);\n\n    if (this.volumeConfigs.length > 0) {\n      parts.push(`${this.volumeConfigs.length} volume(s) attached.`);\n    }\n\n    if (this.networkBlockAll) {\n      parts.push(`Network access is blocked.`);\n    }\n\n    return parts.join(' ');\n  }\n\n  // ---------------------------------------------------------------------------\n  // Command Execution\n  // ---------------------------------------------------------------------------\n\n  // No executeCommand override: the base default (built from the process\n  // manager) releases the handle when the command settles. The override that\n  // used to live here never called pm.release, so it leaked handles.\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, 'Daytona');\n    await this.ensureRunning();\n    await this.daytona.fs.uploadFiles(\n      files.map(file => ({\n        source: Buffer.isBuffer(file.content) ? file.content : Buffer.from(file.content),\n        destination: file.path,\n      })),\n    );\n  }\n\n  // ---------------------------------------------------------------------------\n  // Computer Use\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Ensure the Daytona computer use processes (Xvfb, xfce4, x11vnc, noVNC)\n   * are running. Memoized per attached sandbox; the memo is reset when the\n   * sandbox stops, dies, or is destroyed so a fresh sandbox restarts them.\n   */\n  private async ensureComputerUseStarted(): Promise<void> {\n    if (!this.computerUseAutoStart) return;\n    if (!this._computerUseStarted) {\n      this._computerUseStarted = this.daytona.computerUse\n        .start()\n        .then(() => undefined)\n        .catch((error: unknown) => {\n          this._computerUseStarted = null;\n          throw error;\n        });\n    }\n    return this._computerUseStarted;\n  }\n\n  /**\n   * Build the {@link SandboxComputer} capability backed by Daytona's\n   * computer use API (`sandbox.computerUse`).\n   *\n   * Every operation ensures the sandbox is running and the desktop processes\n   * are started, and retries once if the sandbox died (mirroring command\n   * execution behavior).\n   */\n  private createComputer(): SandboxComputer {\n    const run = async <T>(fn: (computerUse: ComputerUse) => Promise<T>): Promise<T> => {\n      await this.ensureRunning();\n      return this.retryOnDead(async () => {\n        await this.ensureComputerUseStarted();\n        return fn(this.daytona.computerUse);\n      });\n    };\n\n    return {\n      screenshot: async () => {\n        const response = await run(computerUse => computerUse.screenshot.takeFullScreen());\n        if (!response.screenshot) {\n          throw new Error(`${LOG_PREFIX} Daytona returned an empty screenshot response`);\n        }\n        return {\n          data: new Uint8Array(Buffer.from(response.screenshot, 'base64')),\n          mediaType: 'image/png' as const,\n        };\n      },\n      leftClick: async (x, y) => {\n        await run(computerUse => computerUse.mouse.click(x, y, 'left'));\n      },\n      rightClick: async (x, y) => {\n        await run(computerUse => computerUse.mouse.click(x, y, 'right'));\n      },\n      doubleClick: async (x, y) => {\n        await run(computerUse => computerUse.mouse.click(x, y, 'left', true));\n      },\n      moveMouse: async (x, y) => {\n        await run(computerUse => computerUse.mouse.move(x, y));\n      },\n      drag: async (from, to) => {\n        await run(computerUse => computerUse.mouse.drag(from.x, from.y, to.x, to.y));\n      },\n      scroll: async (direction, amount) => {\n        // Daytona scrolls at explicit coordinates — use the current cursor position.\n        await run(async computerUse => {\n          const position = await computerUse.mouse.getPosition();\n          return computerUse.mouse.scroll(position.x ?? 0, position.y ?? 0, direction, amount);\n        });\n      },\n      type: async text => {\n        await run(computerUse => computerUse.keyboard.type(text));\n      },\n      press: async key => {\n        // Daytona's hotkey API takes a '+'-joined combination (e.g. 'ctrl+s').\n        await run(computerUse =>\n          Array.isArray(key) ? computerUse.keyboard.hotkey(key.join('+')) : computerUse.keyboard.press(key),\n        );\n      },\n      getScreenSize: async () => {\n        const info = await run(computerUse => computerUse.display.getInfo());\n        const display = info.displays?.find(d => d.isActive) ?? info.displays?.[0];\n        if (!display || display.width === undefined || display.height === undefined) {\n          throw new Error(`${LOG_PREFIX} Daytona did not return display information`);\n        }\n        return { width: display.width, height: display.height };\n      },\n      getCursorPosition: async () => {\n        const position = await run(computerUse => computerUse.mouse.getPosition());\n        return { x: position.x ?? 0, y: position.y ?? 0 };\n      },\n      streamUrl: async () => {\n        try {\n          // Ensure the desktop (and its noVNC process) is up before resolving the link.\n          const preview = await run(() => this.daytona.getPreviewLink(this.noVncPort));\n          return preview?.url ?? null;\n        } catch {\n          return null;\n        }\n      },\n    };\n  }\n\n  // ---------------------------------------------------------------------------\n  // Mount Support\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    const sandbox = this._sandbox;\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 DaytonaMountConfig | 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 at \"${mountPath}\", unmounting to re-mount with new config...`);\n      await this.unmount(mountPath);\n    } else if (existingMount === 'unmanaged') {\n      const error = `Mount path \"${mountPath}\" is already mounted by an unmanaged source`;\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\n    // Mark as mounting (handles direct mount() calls; MountManager also sets this for processPending)\n    this.mounts.set(mountPath, { filesystem, state: 'mounting', config });\n    this.logger.debug(`${LOG_PREFIX} Config type: ${config.type}`);\n\n    // Reject non-empty directories — mounting would shadow existing files.\n    // Skip the check if the path is already a mount point (stuck FUSE from a failed\n    // prior unmount): its contents are remote objects, not local files to protect.\n    try {\n      const quotedPath = shellQuote(mountPath);\n      const checkResult = await runCommand(\n        sandbox,\n        `[ -d ${quotedPath} ] && ! mountpoint -q ${quotedPath} 2>/dev/null && ` +\n          `[ \"$(ls -A ${quotedPath} 2>/dev/null)\" ] && echo \"non-empty\" || echo \"ok\"`,\n        { timeout: MOUNT_COMMAND_TIMEOUT_MS },\n      );\n      if (checkResult.output.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/prepare the mount directory.\n    // If the path is already a FUSE mount (stuck from a failed prior unmount), overlay\n    // it with a tmpfs first. New FUSE-on-existing-FUSE fails because the kernel asks the\n    // existing daemon to resolve the mount point path, which returns ENOENT. A tmpfs\n    // overlay is kernel-native and doesn't involve the FUSE driver.\n    this.logger.debug(`${LOG_PREFIX} Creating mount directory for \"${mountPath}\"...`);\n    try {\n      const quotedPath = shellQuote(mountPath);\n      const mkdirResult = await runCommand(\n        sandbox,\n        `mountpoint -q ${quotedPath} 2>/dev/null && sudo mount -t tmpfs tmpfs ${quotedPath} 2>/dev/null; ` +\n          `sudo mkdir -p ${quotedPath} 2>/dev/null; ` +\n          `sudo chown $(id -u):$(id -g) ${quotedPath}`,\n        { timeout: MOUNT_COMMAND_TIMEOUT_MS },\n      );\n      if (mkdirResult.exitCode !== 0) {\n        const error = mkdirResult.output || 'Failed to create mount directory';\n        this.logger.debug(`${LOG_PREFIX} mkdir error for \"${mountPath}\":`, error);\n        this.mounts.set(mountPath, { filesystem, state: 'error', config, error });\n        return { success: false, mountPath, error };\n      }\n    } catch (err) {\n      const error = `Failed to create mount directory: ${err}`;\n      this.mounts.set(mountPath, { filesystem, state: 'error', config, error });\n      return { success: false, mountPath, error };\n    }\n\n    // Build mount context for SDK-agnostic mount helpers\n    const mountCtx: MountContext = {\n      run: async (cmd, timeoutMs) => {\n        const result = await runCommand(sandbox, cmd, timeoutMs !== undefined ? { timeout: timeoutMs } : undefined);\n        return {\n          exitCode: result.exitCode,\n          stdout: result.output,\n          stderr: result.exitCode !== 0 ? result.output : '',\n        };\n      },\n      writeFile: async (path, content) => {\n        await sandbox.fs.uploadFile(Buffer.from(content), path);\n      },\n      logger: this.logger,\n    };\n\n    try {\n      switch (config.type) {\n        case 's3':\n          this.logger.debug(`${LOG_PREFIX} Mounting S3 at \"${mountPath}\"...`);\n          await mountS3(mountPath, config, 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 at \"${mountPath}\"...`);\n          await mountGCS(mountPath, config, 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 at \"${mountPath}\"...`);\n          await mountAzure(mountPath, config, mountCtx);\n          this.logger.debug(`${LOG_PREFIX} Mounted Azure Blob container at ${mountPath}`);\n          break;\n        default: {\n          const error = `Unsupported mount type: ${(config as FilesystemMountConfig).type}`;\n          this.mounts.set(mountPath, { filesystem, state: 'unsupported', config, error });\n          return { success: false, mountPath, error };\n        }\n      }\n    } catch (error) {\n      this.logger.error(\n        `${LOG_PREFIX} Error mounting \"${filesystem.provider}\" (${filesystem.id}) at \"${mountPath}\":`,\n        error,\n      );\n      if (config.type === 's3') {\n        // The daemon may have mounted successfully before its readiness check failed.\n        // Detach it before retrying, otherwise the missing marker makes it look unmanaged.\n        try {\n          await this.unmount(mountPath);\n        } catch (cleanupError) {\n          this.logger.warn(`${LOG_PREFIX} Could not unmount failed S3 mount at ${mountPath}:`, cleanupError);\n        }\n      }\n      // unmount() removes the registry entry; retain the original failure for callers.\n      this.mounts.set(mountPath, { filesystem, state: 'error', config, error: errorToString(error) });\n      if (config.type !== 's3') {\n        await runCommand(sandbox, `sudo rmdir ${shellQuote(mountPath)} 2>/dev/null || true`, {\n          timeout: MOUNT_COMMAND_TIMEOUT_MS,\n        });\n      }\n      return { success: false, mountPath, error: errorToString(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    const sandbox = this._sandbox;\n\n    this.logger.debug(`${LOG_PREFIX} Unmounting \"${mountPath}\"...`);\n\n    // Try fusermount first (user-space), then lazy umount as fallback.\n    // Do NOT pkill the FUSE daemon — a killed daemon leaves a stale mount\n    // (ENOTCONN) that blocks subsequent mkdir/stat on the path.\n    const quotedPath = shellQuote(mountPath);\n    // Validation rejects repeated slashes, so at most one trailing slash remains.\n    const normalizedMountPath = mountPath.endsWith('/') ? mountPath.slice(0, -1) : mountPath;\n    await runCommand(\n      sandbox,\n      `sudo fusermount -u ${quotedPath} 2>/dev/null; ` +\n        `sudo umount -l ${quotedPath} 2>/dev/null; ` +\n        // Dead FUSE mounts can make mountpoint fail with ENOTCONN. Read the kernel table\n        // instead so the existing move-aside fallback also handles disconnected mounts.\n        `grep -Fq -- ${shellQuote(` ${normalizedMountPath || '/'} `)} /proc/mounts && ` +\n        `{ _p=\"/tmp/.mastra-defunct-$$\"; sudo mkdir -p \"$_p\" && sudo mount --move ${quotedPath} \"$_p\" 2>/dev/null; sudo umount -l \"$_p\" 2>/dev/null; sudo rmdir \"$_p\" 2>/dev/null; }`,\n      { timeout: MOUNT_COMMAND_TIMEOUT_MS },\n    );\n\n    await cleanupS3Credentials(mountPath, {\n      run: async (cmd, timeout) => {\n        const result = await runCommand(sandbox, cmd, { timeout: timeout ?? MOUNT_COMMAND_TIMEOUT_MS });\n        return { exitCode: result.exitCode, stdout: result.output, stderr: '' };\n      },\n      logger: this.logger,\n    });\n    this.mounts.delete(mountPath);\n\n    // Clean up marker file and mount directory in one round-trip.\n    // rm -f always exits 0, so the combined exit code reflects rmdir.\n    const markerPath = `/tmp/.mastra-mounts/${this.mounts.markerFilename(mountPath)}`;\n    const rmdirResult = await runCommand(\n      sandbox,\n      `rm -f ${shellQuote(markerPath)} 2>/dev/null; sudo rmdir ${quotedPath} 2>&1`,\n      {\n        timeout: MOUNT_COMMAND_TIMEOUT_MS,\n      },\n    );\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.output.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) return;\n    const sandbox = this._sandbox;\n\n    this.logger.debug(`${LOG_PREFIX} Reconciling mounts. Expected paths:`, expectedMountPaths);\n\n    // Get current FUSE mounts\n    let currentMounts: string[] = [];\n    try {\n      const mountsResult = await runCommand(\n        sandbox,\n        `grep -E 'fuse\\\\.(s3fs|gcsfuse|blobfuse2)' /proc/mounts | awk '{print $2}'`,\n        { timeout: MOUNT_COMMAND_TIMEOUT_MS },\n      );\n      currentMounts = mountsResult.output\n        .trim()\n        .split('\\n')\n        .filter(p => p.length > 0);\n    } catch (err) {\n      this.logger.debug(`${LOG_PREFIX} Could not read /proc/mounts: ${err}`);\n      return;\n    }\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    let markerFiles: string[] = [];\n    try {\n      const markersResult = await runCommand(sandbox, 'ls /tmp/.mastra-mounts/ 2>/dev/null || echo \"\"', {\n        timeout: MOUNT_COMMAND_TIMEOUT_MS,\n      });\n      markerFiles = markersResult.output\n        .trim()\n        .split('\\n')\n        .filter(f => f.length > 0 && SAFE_MARKER_NAME.test(f));\n    } catch (err) {\n      this.logger.debug(`${LOG_PREFIX} Could not read marker files: ${err}`);\n    }\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 runCommand(sandbox, `cat \"/tmp/.mastra-mounts/${markerFile}\" 2>/dev/null || echo \"\"`, {\n        timeout: MOUNT_COMMAND_TIMEOUT_MS,\n      });\n      const parsed = this.mounts.parseMarkerContent(markerResult.output.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        try {\n          await this.unmount(stalePath);\n        } catch (err) {\n          this.logger.debug(`${LOG_PREFIX} Failed to unmount stale mount at \"${stalePath}\": ${err}`);\n        }\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              await runCommand(\n                sandbox,\n                `rm -f \"/tmp/.mastra-mounts/${markerFile}\" 2>/dev/null; sudo rmdir ${shellQuote(mountPath)} 2>/dev/null`,\n                { timeout: MOUNT_COMMAND_TIMEOUT_MS },\n              );\n            }\n          } else {\n            // Malformed marker file - just delete it\n            this.logger.debug(`${LOG_PREFIX} Removing malformed marker file: ${markerFile}`);\n            await runCommand(sandbox, `rm -f \"/tmp/.mastra-mounts/${markerFile}\" 2>/dev/null || true`, {\n              timeout: MOUNT_COMMAND_TIMEOUT_MS,\n            });\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   * 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 runCommand(this._sandbox, 'mkdir -p /tmp/.mastra-mounts', { timeout: MOUNT_COMMAND_TIMEOUT_MS });\n      await this._sandbox.fs.uploadFile(Buffer.from(markerContent, 'utf-8'), markerPath);\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 whether the config matches.\n   *\n   * @param mountPath - The mount path to check\n   * @param newConfig - The new config to compare against the stored config\n   * @returns 'not_mounted' | 'matching' | 'mismatched' | 'unmanaged'\n   */\n  private async checkExistingMount(\n    mountPath: string,\n    newConfig: DaytonaMountConfig,\n  ): Promise<'not_mounted' | 'matching' | 'mismatched' | 'unmanaged'> {\n    if (!this._sandbox) throw new SandboxNotReadyError(this.id);\n    const sandbox = this._sandbox;\n\n    // Check if path is a mount point\n    try {\n      const mountCheck = await runCommand(\n        sandbox,\n        `mountpoint -q ${shellQuote(mountPath)} && echo \"mounted\" || echo \"not mounted\"`,\n        { timeout: MOUNT_COMMAND_TIMEOUT_MS },\n      );\n      if (mountCheck.output.trim() !== 'mounted') {\n        return 'not_mounted';\n      }\n    } catch {\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    let parsed;\n    try {\n      const markerResult = await runCommand(sandbox, `cat ${shellQuote(markerPath)} 2>/dev/null || echo \"\"`, {\n        timeout: MOUNT_COMMAND_TIMEOUT_MS,\n      });\n      parsed = this.mounts.parseMarkerContent(markerResult.output.trim());\n    } catch {\n      // Marker doesn't exist or can't be read - treat as unmanaged\n      return 'unmanaged';\n    }\n\n    if (!parsed) return 'unmanaged';\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\n    return 'mismatched';\n  }\n\n  // ---------------------------------------------------------------------------\n  // Internal Helpers\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Try to find and reconnect to an existing Daytona sandbox by ID.\n   * Returns the sandbox if found and usable, or null if a fresh one should\n   * be created.\n   */\n  private async detectWorkingDir(): Promise<void> {\n    if (!this._sandbox) return;\n    // An explicit workingDirectory option wins; the probe only fills the\n    // default in when nothing was configured.\n    if (this.explicitWorkingDirectory !== undefined) return;\n    try {\n      const result = await runCommand(this._sandbox, 'pwd', { timeout: MOUNT_COMMAND_TIMEOUT_MS });\n      const dir = result.output?.trim();\n      if (dir) {\n        this.setWorkingDirectory(dir);\n        this.logger.debug(`${LOG_PREFIX} Detected working directory: ${dir}`);\n      }\n    } catch {\n      this.logger.debug(`${LOG_PREFIX} Could not detect working directory, will omit from instructions`);\n    }\n  }\n\n  /**\n   * Look up the existing Daytona sandbox by identity WITHOUT starting it.\n   * Used for detached (cross-process) networking/stop/destroy so those\n   * operations never wake a stopped sandbox. Returns null when not found.\n   */\n  private async lookupDetachedSandbox(): Promise<Sandbox | null> {\n    const lookupKey = this._daytonaSandboxId ?? this.sandboxName;\n    if (!lookupKey) {\n      return null;\n    }\n    if (!this._daytona) {\n      this._daytona = new Daytona(this.connectionOpts);\n    }\n    try {\n      return await this._daytona.get(lookupKey);\n    } catch (error) {\n      if (error instanceof DaytonaNotFoundError) {\n        return null;\n      }\n      throw error;\n    }\n  }\n\n  private async findExistingSandbox(): Promise<Sandbox | null> {\n    const DEAD_STATES: SandboxState[] = [\n      SandboxState.DESTROYED,\n      SandboxState.DESTROYING,\n      SandboxState.ERROR,\n      SandboxState.BUILD_FAILED,\n    ];\n\n    // Prefer the stored Daytona ID (same-process stop→start); fall back to name\n    // for cross-process reconnection (e.g. process restart).\n    const lookupKey = this._daytonaSandboxId ?? this.sandboxName;\n    if (!lookupKey) {\n      return null;\n    }\n\n    let sandbox: Sandbox;\n\n    try {\n      sandbox = await this._daytona!.get(lookupKey);\n    } catch (error) {\n      if (error instanceof DaytonaNotFoundError) {\n        this._daytonaSandboxId = undefined;\n        return null;\n      }\n      // Any other error (auth, transient, network) — propagate so the caller\n      // can handle or retry rather than silently creating a duplicate sandbox.\n      throw error;\n    }\n\n    const state = sandbox.state;\n\n    if (state && DEAD_STATES.includes(state)) {\n      this.logger.debug(`${LOG_PREFIX} Existing sandbox ${sandbox.id} is dead (${state}), deleting and creating fresh`);\n      try {\n        await this._daytona!.delete(sandbox);\n      } catch {\n        // Best-effort cleanup of dead sandbox\n      }\n      return null;\n    }\n\n    // Note: a stopped-but-alive sandbox is returned as-is — waking it is\n    // connect()'s job, not the lookup's.\n    return sandbox;\n  }\n\n  /**\n   * Transitional states where the Daytona API will reject start() with\n   * \"State change in progress\". We poll until the sandbox reaches a stable\n   * state before attempting start().\n   */\n  private static readonly TRANSITIONAL_STATES: SandboxState[] = [\n    SandboxState.STARTING,\n    SandboxState.STOPPING,\n    SandboxState.CREATING,\n    SandboxState.RESTORING,\n    SandboxState.ARCHIVING,\n    SandboxState.RESIZING,\n    SandboxState.PULLING_SNAPSHOT,\n    SandboxState.BUILDING_SNAPSHOT,\n  ];\n\n  /**\n   * Wait for the sandbox to leave a transitional state, then start it if needed.\n   * Polls every 2s for up to 120s. If the sandbox reaches STARTED on its own\n   * (e.g. it was STARTING), we skip the start() call. If start() still fails\n   * with \"State change in progress\", we retry with backoff.\n   */\n  private async waitForStableStateAndStart(sandbox: Sandbox): Promise<void> {\n    const MAX_WAIT_MS = 120_000;\n    const POLL_INTERVAL_MS = 2_000;\n    const deadline = Date.now() + MAX_WAIT_MS;\n\n    let current = sandbox;\n\n    // Phase 1: Poll until the reported state is no longer transitional\n    while (current.state && DaytonaSandbox.TRANSITIONAL_STATES.includes(current.state) && Date.now() < deadline) {\n      this.logger.debug(`${LOG_PREFIX} Sandbox ${current.id} is in transitional state (${current.state}), waiting...`);\n      await new Promise(r => setTimeout(r, POLL_INTERVAL_MS));\n      current = await this._daytona!.get(current.id);\n    }\n\n    if (current.state === SandboxState.STARTED) {\n      // Reached STARTED on its own — update the reference and return\n      Object.assign(sandbox, current);\n      return;\n    }\n\n    // Phase 2: Attempt start() with retries for \"State change in progress\"\n    while (Date.now() < deadline) {\n      try {\n        await this._daytona!.start(current);\n        return;\n      } catch (error) {\n        const msg = error instanceof Error ? error.message : String(error);\n        if (msg.includes('State change in progress') && Date.now() < deadline) {\n          this.logger.debug(`${LOG_PREFIX} start() returned \"State change in progress\", retrying...`);\n          await new Promise(r => setTimeout(r, POLL_INTERVAL_MS));\n          current = await this._daytona!.get(current.id);\n          if (current.state === SandboxState.STARTED) {\n            Object.assign(sandbox, current);\n            return;\n          }\n          continue;\n        }\n        throw error;\n      }\n    }\n\n    // Last-ditch attempt after deadline\n    await this._daytona!.start(current);\n  }\n\n  /**\n   * Check if an error indicates the sandbox is dead/gone.\n   * Uses DaytonaNotFoundError from the SDK when available,\n   * with string fallback for edge cases.\n   *\n   * String patterns observed in @daytonaio/sdk@0.143.0 error messages.\n   * Update if SDK error messages change in future versions.\n   */\n  private isSandboxDeadError(error: unknown): boolean {\n    if (!error) return false;\n    if (error instanceof DaytonaNotFoundError) return true;\n    const errorStr = String(error);\n    return SANDBOX_DEAD_PATTERNS.some(pattern => pattern.test(errorStr));\n  }\n\n  /**\n   * Handle sandbox timeout by clearing the instance and resetting state.\n   */\n  private handleSandboxTimeout(): void {\n    this._sandbox = null;\n    this._computerUseStarted = null;\n\n    // Reset mounted entries to pending so they get re-mounted on restart\n    if (this.mounts) {\n      for (const [path, entry] of this.mounts.entries) {\n        if (entry.state === 'mounted' || entry.state === 'mounting') {\n          this.mounts.set(path, { state: 'pending' });\n        }\n      }\n    }\n\n    this.status = 'stopped';\n  }\n\n  // ---------------------------------------------------------------------------\n  // Retry on Dead\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Execute a function, retrying once if the sandbox is found to be dead.\n   * Used by DaytonaProcessManager to handle stale sandboxes transparently.\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"],"mappings":"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"}