@mastra/docker 0.9.0-alpha.0 → 0.9.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/abort.d.ts +7 -0
- package/dist/abort.d.ts.map +1 -0
- package/dist/index.cjs +211 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +211 -47
- package/dist/index.js.map +1 -1
- package/dist/sandbox/index.d.ts +8 -3
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/kill-helper-exit.fixture.d.ts +2 -0
- package/dist/sandbox/kill-helper-exit.fixture.d.ts.map +1 -0
- package/dist/sandbox/process-manager.d.ts.map +1 -1
- package/dist/template/build-session.d.ts +1 -1
- package/dist/template/build-session.d.ts.map +1 -1
- package/dist/template/index.d.ts +1 -1
- package/dist/template/index.d.ts.map +1 -1
- package/dist/template/repo-template.d.ts +8 -4
- package/dist/template/repo-template.d.ts.map +1 -1
- package/dist/template/template.d.ts +2 -0
- package/dist/template/template.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["ProcessHandle","SandboxProcessManager","timeoutMs","MastraSandbox","Docker","SandboxNotReadyError","SandboxAbortError","posixPath","SandboxError","isImageNotFoundError","path","Server","ServerCredentials","#baseImage","#operations","#dockerOptions","#secrets","#clone","#append","posixPath","#docker","Docker","#inFlight","#build","#getDocker","#built","#resolveSecrets","#buildWithSecrets","#followBuild","execFile"],"sources":["../src/sandbox/process-manager.ts","../src/sandbox/index.ts","../src/provider.ts","../src/template/build-session.ts","../src/template/dockerfile.ts","../src/template/template.ts","../../../packages/_internals/workspace/dist/index.js","../src/template/repo-template.ts"],"sourcesContent":["/**\n * Docker Process Manager\n *\n * Implements SandboxProcessManager for Docker containers.\n * Uses `container.exec()` to run commands inside a long-lived container.\n * Each spawned process gets a dedicated exec instance with separate\n * stdout/stderr streams.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type { Duplex } from 'node:stream';\n\nimport { ProcessHandle, SandboxProcessManager } from '@mastra/core/workspace';\nimport type { CommandResult, ProcessInfo, SpawnProcessOptions } from '@mastra/core/workspace';\nimport type { Container, Exec, ExecInspectInfo } from 'dockerode';\n\n/**\n * Directory (inside the container) where each spawned process records the PGID\n * of its process group. Created with mode 700 so only the (root) exec user can\n * write the PGID files.\n */\nconst PROC_DIR = '/tmp/.mastra-proc';\n\n/**\n * Wrapper (run as the exec command) that places the user command in its own\n * process group and records the group's PGID so kill() can signal the whole\n * group later.\n *\n * Docker's exec-inspect `Pid` is a host/daemon-namespace PID and cannot be used\n * with an in-container `kill`, so we need a container-namespace identity. We use\n * a *kernel-enforced* process group as that identity:\n *\n * 1. `setsid -w` re-execs the command as a new session/process-group leader,\n * so its PID == PGID. Every descendant inherits that PGID (unless it calls\n * `setsid` itself) and stays reachable even if it re-parents to PID 1.\n * `-w` keeps the wrapper (and thus the exec) alive for the whole lifetime\n * and propagates the child's exit status — without it `setsid` forks and\n * returns immediately, so the exec would appear to finish while the real\n * work keeps running.\n * 2. The leader writes its own PID (`$$`) — the PGID — to a private file that\n * only this process wrote, so the identity is kernel-owned and cannot be\n * forged by another container process.\n *\n * If `setsid -w` is unavailable in the image (e.g. BusyBox), we degrade\n * gracefully: the command runs directly and we record its PID so kill() can\n * still signal it (descendant coverage is then best-effort). The probe\n * `setsid -w true` also covers images without setsid at all.\n *\n * Positional args: $1 = pgid file path, $2 = user command. The script text is a\n * static constant; runtime values travel only as argv, never interpolated into\n * the command string.\n */\nconst SPAWN_WRAPPER = `\numask 077\nd=\"\\${1%/*}\"\nmkdir -p \"$d\" 2>/dev/null\nchmod 700 \"$d\" 2>/dev/null\nif setsid -w true >/dev/null 2>&1; then\n exec setsid -w sh -c 'echo $$ > \"$1\" || exit 126; sh -c \"$2\"; ret=$?; rm -f \"$1\" 2>/dev/null; exit $ret' sh \"$1\" \"$2\"\nfi\necho $$ > \"$1\" || exit 126\nsh -c \"$2\"\nret=$?\nrm -f \"$1\" 2>/dev/null\nexit $ret\n`;\n\n/**\n * Kill script: read the recorded PGID and SIGKILL the whole process group.\n * A negative PID targets the kernel-owned process group, so descendants that\n * re-parented to PID 1 are still caught. We SIGSTOP the\n * group first to freeze fork races, then SIGKILL. The file may not exist yet if\n * kill races the leader's first write, so we briefly wait for it.\n *\n * Positional arg: $1 = pgid file path (static script; no interpolation).\n */\nconst KILL_SCRIPT = `\nf=\"$1\"\ni=0\nwhile [ ! -r \"$f\" ] && [ \"$i\" -lt 40 ]; do sleep 0.05; i=$((i + 1)); done\n# If the PGID was never recorded (file absent/unreadable after the wait, or\n# empty), we have no group to signal or verify — report failure rather than\n# falsely claiming the tree was terminated.\n[ -r \"$f\" ] || exit 1\npgid=$(cat \"$f\" 2>/dev/null)\nrm -f \"$f\" 2>/dev/null\n[ -n \"$pgid\" ] || exit 1\nkill -STOP -\"$pgid\" 2>/dev/null\nkill -KILL -\"$pgid\" 2>/dev/null\n# Fallback for images without setsid: the leader is not a group leader, so also\n# signal it directly.\nkill -KILL \"$pgid\" 2>/dev/null\n# Verify the group is actually gone before reporting success. kill -0 probes\n# for the group's existence without sending a signal, and we poll while it\n# still reports the group alive. When the probe finally fails we must inspect\n# why: ESRCH (\"no such process\") means every member was reaped, so report\n# success; EPERM or any other error means termination is unconfirmed (e.g. a\n# member dropped privileges and became unsignalable), so exit nonzero and let\n# kill() report failure instead of falsely claiming the tree was terminated.\nj=0\nwhile err=$(kill -0 -\"$pgid\" 2>&1); do\n j=$((j + 1))\n [ \"$j\" -ge 40 ] && exit 1\n sleep 0.05\ndone\ncase \"$err\" in\n *[Ss]uch\\\\ process*) exit 0 ;;\n *) exit 1 ;;\nesac\n`;\n\n// =============================================================================\n// Docker Process Handle\n// =============================================================================\n\n/**\n * Wraps a Docker exec instance to conform to Mastra's ProcessHandle.\n * Not exported — internal to this module.\n *\n * Listener dispatch is handled by the base class. The manager's spawn()\n * method wires Docker stream callbacks to handle.emitStdout/emitStderr.\n */\nclass DockerProcessHandle extends ProcessHandle {\n readonly pid: string;\n\n private readonly _exec: Exec;\n private readonly _container: Container;\n private readonly _startTime: number;\n private _exitCode: number | undefined;\n /** @internal Set by kill() and timeout to distinguish forced termination from natural exit */\n _killed = false;\n /** @internal Set by the timeout path to distinguish timeout kills from explicit kills */\n _timedOut = false;\n private _waitPromise: Promise<CommandResult> | null = null;\n private _stdinStream: Duplex | null = null;\n private _execStream: NodeJS.ReadWriteStream | null = null;\n /** @internal Container path of the file holding this process group's PGID. */\n readonly _pgidFile: string;\n\n constructor(\n exec: Exec,\n container: Container,\n startTime: number,\n stdinStream: Duplex | null,\n pgidFile: string,\n options?: SpawnProcessOptions,\n ) {\n super(options);\n this.pid = exec.id;\n this._exec = exec;\n this._container = container;\n this._startTime = startTime;\n this._stdinStream = stdinStream;\n this._pgidFile = pgidFile;\n }\n\n get exitCode(): number | undefined {\n return this._exitCode;\n }\n\n /** @internal Set exit code when stream closes */\n _setExitCode(code: number): void {\n this._exitCode = code;\n }\n\n /** @internal Set the wait promise from spawn */\n _setWaitPromise(p: Promise<CommandResult>): void {\n this._waitPromise = p;\n }\n\n /** @internal Set the exec stream so kill() can destroy it */\n _setExecStream(stream: NodeJS.ReadWriteStream): void {\n this._execStream = stream;\n }\n\n async wait(): Promise<CommandResult> {\n if (this._waitPromise) {\n return this._waitPromise;\n }\n\n // If no wait promise set yet, poll exec inspect\n const info = await this._inspectExec();\n return {\n success: (info.ExitCode ?? 1) === 0,\n exitCode: info.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\n try {\n // Kill the process group inside the *container's* PID namespace. We must\n // not use exec.inspect().Pid here: that is the host/daemon-namespace PID\n // and does not correspond to PIDs an in-container `kill` can address. The\n // recorded PGID targets a kernel-owned group, so descendants that were\n // re-parented to PID 1 are still caught.\n const killExec = await this._container.exec({\n // Static script; the pgid file path is passed as $1 (sh sets $0='sh',\n // $1=path) so no runtime value is ever interpolated into the command.\n Cmd: ['sh', '-c', KILL_SCRIPT, 'sh', this._pgidFile],\n AttachStdout: false,\n AttachStderr: false,\n });\n await killExec.start({});\n\n // Exec.start() resolves when the exec stream is opened, not when the\n // helper script exits. Poll inspect() until it finishes so we only report\n // success once the process tree has actually been killed — otherwise\n // wait() could resolve with exit 137 while targets are still running.\n let killInfo = await killExec.inspect();\n while (killInfo.Running) {\n await new Promise(resolve => setTimeout(resolve, 10));\n killInfo = await killExec.inspect();\n }\n if (killInfo.ExitCode !== 0) {\n throw new Error(`kill helper exited with code ${killInfo.ExitCode}`);\n }\n\n // Mark as killed and destroy stream so wait() resolves.\n // Docker exec streams don't close automatically when the process is killed externally.\n this._killed = true;\n this._destroyStream();\n return true;\n } catch (error: unknown) {\n // ESRCH / \"no such process\" is expected if the process exited between inspect and kill\n const msg = error instanceof Error ? error.message.toLowerCase() : '';\n if (!msg.includes('no such process') && !msg.includes('esrch')) {\n // Unexpected error — not fatal but worth noting for debugging\n console.warn(`[DockerProcessManager] kill(${this.pid}) failed unexpectedly:`, error);\n }\n return false;\n }\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 if (!this._stdinStream) {\n throw new Error(`Process ${this.pid} was not started with stdin support`);\n }\n return new Promise<void>((resolve, reject) => {\n this._stdinStream!.write(data, error => (error ? reject(error) : resolve()));\n });\n }\n\n async closeStdin(): Promise<void> {\n if (this._exitCode !== undefined) {\n throw new Error(`Process ${this.pid} has already exited with code ${this._exitCode}`);\n }\n if (!this._stdinStream) {\n throw new Error(`Process ${this.pid} was not started with stdin support`);\n }\n const stream = this._stdinStream;\n if (stream.writableEnded) return;\n await new Promise<void>(resolve => stream.end(resolve));\n }\n\n /** @internal Force-close the exec stream to unblock wait(). */\n _destroyStream(): void {\n const stream = this._execStream as unknown as { destroy?: () => void } | null;\n if (stream && typeof stream.destroy === 'function') {\n stream.destroy();\n this._execStream = null;\n }\n }\n\n private async _inspectExec(): Promise<ExecInspectInfo> {\n return this._exec.inspect();\n }\n}\n\n// =============================================================================\n// Docker Process Manager\n// =============================================================================\n\n/**\n * Docker implementation of SandboxProcessManager.\n * Uses `container.exec()` with stream-based I/O.\n */\nexport class DockerProcessManager extends SandboxProcessManager {\n private _container: Container | null = null;\n private readonly _defaultTimeout: number;\n\n constructor(options: { defaultTimeout?: number } = {}) {\n super();\n this._defaultTimeout = options.defaultTimeout ?? 0;\n }\n\n /** @internal Called by DockerSandbox after container is ready */\n setContainer(container: Container): void {\n this._container = container;\n }\n\n /** Get the container, throwing if not set */\n private get container(): Container {\n if (!this._container) {\n throw new Error('Docker container not available. Has the sandbox been started?');\n }\n return this._container;\n }\n\n async spawn(command: string, options: SpawnProcessOptions = {}): Promise<ProcessHandle> {\n const container = this.container;\n\n // Private file (unguessable name) where the command's process group records\n // its PGID, so kill() can signal the whole kernel-owned group later.\n const pgidFile = `${PROC_DIR}/${randomUUID()}`;\n const envArray = Object.entries({ ...options.env })\n .filter((entry): entry is [string, string] => entry[1] !== undefined)\n .map(([k, v]) => `${k}=${v}`);\n\n // Create exec instance. The command is wrapped so it runs in its own process\n // group (via setsid) and records its PGID; args travel positionally so the\n // wrapper text stays a static constant.\n const exec = await container.exec({\n Cmd: ['sh', '-c', SPAWN_WRAPPER, 'sh', pgidFile, command],\n AttachStdout: true,\n AttachStderr: true,\n AttachStdin: true,\n Tty: false,\n Env: envArray.length > 0 ? envArray : undefined,\n WorkingDir: options.cwd,\n });\n\n // Start exec and get the multiplexed stream\n const stream = await exec.start({ hijack: true, stdin: true });\n\n const startTime = Date.now();\n const handle = new DockerProcessHandle(exec, container, startTime, stream, pgidFile, options);\n handle._setExecStream(stream);\n\n // Create the wait promise that resolves when the stream ends\n const waitPromise = new Promise<CommandResult>(resolve => {\n // Demux the multiplexed stream into stdout/stderr\n // Docker multiplexes stdout/stderr into a single stream with 8-byte headers\n // when Tty is false. We need to parse these headers.\n const buffer: Buffer[] = [];\n\n stream.on('data', (chunk: Buffer) => {\n buffer.push(chunk);\n // Process all complete frames in the buffer\n let combined = Buffer.concat(buffer);\n buffer.length = 0;\n\n while (combined.length >= 8) {\n const type = combined[0]; // 1 = stdout, 2 = stderr\n const size = combined.readUInt32BE(4);\n\n if (combined.length < 8 + size) {\n // Incomplete frame, save for next chunk\n buffer.push(combined);\n break;\n }\n\n const payload = combined.subarray(8, 8 + size).toString('utf-8');\n if (type === 1) {\n handle.emitStdout(payload);\n } else if (type === 2) {\n handle.emitStderr(payload);\n }\n\n combined = combined.subarray(8 + size);\n }\n\n // Save any remaining partial data\n if (combined.length > 0 && buffer.length === 0) {\n buffer.push(combined);\n }\n });\n\n stream.on('end', async () => {\n // Get exit code from exec inspect\n try {\n const info = await exec.inspect();\n const exitCode = info.ExitCode ?? 1;\n handle._setExitCode(exitCode);\n resolve({\n success: exitCode === 0,\n exitCode,\n stdout: handle.stdout,\n stderr: handle.stderr,\n executionTimeMs: Date.now() - startTime,\n });\n } catch {\n handle._setExitCode(1);\n resolve({\n success: false,\n exitCode: 1,\n stdout: handle.stdout,\n stderr: handle.stderr,\n executionTimeMs: Date.now() - startTime,\n });\n }\n });\n\n // 'close' fires when stream.destroy() is called (e.g., from kill or timeout).\n // Only resolve with SIGKILL exit code when the process was explicitly killed;\n // natural stream close should be handled by the 'end' event above.\n // Note: Docker multiplexed streams always emit 'end' before 'close' for\n // natural exits, so the !_killed guard won't silently drop natural closes.\n stream.on('close', () => {\n if (handle.exitCode !== undefined) return; // Already resolved via 'end'\n if (!handle._killed) return; // Natural close — 'end' handles it\n handle._setExitCode(137); // SIGKILL\n resolve({\n success: false,\n exitCode: 137,\n stdout: handle.stdout,\n stderr: handle.stderr,\n executionTimeMs: Date.now() - startTime,\n killed: true,\n timedOut: handle._timedOut,\n });\n });\n\n stream.on('error', () => {\n if (handle.exitCode !== undefined) return; // Already resolved\n handle._setExitCode(1);\n resolve({\n success: false,\n exitCode: 1,\n stdout: handle.stdout,\n stderr: handle.stderr || 'Stream error',\n executionTimeMs: Date.now() - startTime,\n });\n });\n });\n\n // Wire up timeout: kill the process and destroy the stream after the timeout period.\n // Per-spawn timeout takes precedence; falls back to the sandbox-level default.\n const resolvedTimeout = options.timeout ?? this._defaultTimeout;\n if (resolvedTimeout > 0) {\n const timeoutMs = resolvedTimeout;\n const timer = setTimeout(() => {\n if (handle.exitCode === undefined) {\n handle._killed = true;\n handle._timedOut = true;\n // Await kill() so the process tree is actually terminated before the\n // stream is torn down. Destroying the stream first would resolve\n // wait() with exit 137 while the targets are still running — the exact\n // bug this fix addresses. Only force-destroy the stream if kill()\n // fails to make progress, as a last resort to unblock wait().\n const forceClose = () => {\n if (handle.exitCode === undefined) {\n handle._killed = true;\n handle._destroyStream();\n }\n };\n handle\n .kill()\n .then(killed => {\n if (!killed) forceClose();\n })\n .catch(forceClose);\n }\n }, timeoutMs);\n // Clear timer when process exits naturally\n void waitPromise.then(() => clearTimeout(timer));\n }\n\n handle._setWaitPromise(waitPromise);\n this._tracked.set(handle.pid, handle);\n return handle;\n }\n\n /** Clear all tracked process handles and release the container reference (e.g., after container stop/destroy) */\n reset(): void {\n this._tracked.clear();\n this._container = null;\n }\n\n async list(): Promise<ProcessInfo[]> {\n const results: ProcessInfo[] = [];\n\n for (const [pid, handle] of this._tracked) {\n results.push({\n pid,\n command: handle.command,\n running: handle.exitCode === undefined,\n exitCode: handle.exitCode,\n });\n }\n\n return results;\n }\n}\n","/**\n * Docker Sandbox Provider\n *\n * A Docker-based sandbox implementation that uses long-lived containers\n * with `docker exec` for command execution. Targets local development,\n * CI/CD, air-gapped deployments, and cost-sensitive scenarios where\n * cloud sandboxes are overkill.\n *\n * @see https://docs.docker.com/engine/api/\n */\n\nimport { posix as posixPath } from 'node:path';\nimport { isDeepStrictEqual } from 'node:util';\nimport type { RequestContext } from '@mastra/core/di';\nimport type {\n SandboxInfo,\n ProviderStatus,\n MastraSandboxOptions,\n SandboxCloneOptions,\n SandboxFileInput,\n WriteFilesOptions,\n} from '@mastra/core/workspace';\nimport {\n MastraSandbox,\n SandboxAbortError,\n SandboxError,\n SandboxNotReadyError,\n validateSandboxFileMode,\n} from '@mastra/core/workspace';\nimport Docker from 'dockerode';\nimport type { Container, ContainerInfo } from 'dockerode';\nimport { pack as tarPack } from 'tar-stream';\nimport type { DockerTemplate } from '../template/template';\nimport { DockerProcessManager } from './process-manager';\n\nconst LOG_PREFIX = '[DockerSandbox]';\n\n/** A prepared template, or a resolver producing one (see `DockerSandboxOptions.template`). */\nexport type DockerTemplateSpec = DockerTemplate | (() => DockerTemplate | Promise<DockerTemplate>);\n\n/**\n * Inlined from `@mastra/core/workspace` to avoid requiring a newer core peer dep.\n * Canonical type: packages/core/src/workspace/sandbox/mastra-sandbox.ts\n * TODO: Remove once minimum peer dep includes InstructionsOption export.\n */\ntype InstructionsOption = string | ((opts: { defaultInstructions: string; requestContext?: RequestContext }) => string);\n\ntype DockerSandboxUlimit = {\n name: string;\n soft: number;\n hard: number;\n};\n\ntype DockerSandboxTmpfs = Record<string, string>;\n\n/** Options applied to a `volume` mount. */\ntype DockerSandboxVolumeMount = {\n type: 'volume';\n /** Absolute path of the mount inside the container. */\n target: string;\n /** Named volume to mount. */\n source: string;\n /** Mount read-only. */\n readOnly?: boolean;\n /** Options applied to the named volume. */\n volumeOptions?: {\n /** Mount a subdirectory of the named volume (Docker Engine 26.0+). */\n subpath?: string;\n /** Disable copying data from the container path into the volume. */\n noCopy?: boolean;\n /** Labels applied to the volume when it is created. */\n labels?: Record<string, string>;\n };\n};\n\n/** Options applied to a `bind` mount. */\ntype DockerSandboxBindMount = {\n type: 'bind';\n /** Absolute path of the mount inside the container. */\n target: string;\n /** Host path to bind into the container. */\n source: string;\n /** Mount read-only. */\n readOnly?: boolean;\n /** Options applied to the bind mount. */\n bindOptions?: {\n /** Bind propagation mode. */\n propagation?: 'private' | 'rprivate' | 'shared' | 'rshared' | 'slave' | 'rslave';\n };\n};\n\n/** Options applied to a `tmpfs` mount. */\ntype DockerSandboxTmpfsMount = {\n type: 'tmpfs';\n /** Absolute path of the mount inside the container. */\n target: string;\n /** Mount read-only. */\n readOnly?: boolean;\n /** Options applied to the tmpfs mount. */\n tmpfsOptions?: {\n /** Size of the tmpfs mount in bytes. */\n sizeBytes?: number;\n /** File mode of the tmpfs mount, in octal (e.g. 0o1777). */\n mode?: number;\n };\n};\n\n/**\n * A single Docker mount, mapped 1:1 onto an entry of `HostConfig.Mounts`.\n *\n * Unlike `volumes` (which maps to `HostConfig.Binds` / the `-v` syntax), mounts\n * can express options that `Binds` cannot — most notably `volumeOptions.subpath`,\n * which mounts a subdirectory of a named volume. Requires Docker Engine 26.0+\n * (API v1.45+) for `subpath` support.\n *\n * This is a discriminated union on `type`: `volume` and `bind` mounts require a\n * `source` and only accept their own option group, while `tmpfs` mounts take no\n * `source`. These invariants mirror what Docker enforces at container creation.\n */\nexport type DockerSandboxMount = DockerSandboxVolumeMount | DockerSandboxBindMount | DockerSandboxTmpfsMount;\n\n// =============================================================================\n// Docker Sandbox Options\n// =============================================================================\n\nexport interface DockerSandboxOptions extends Omit<MastraSandboxOptions, 'processes'> {\n /** Unique identifier for this sandbox instance. Used for label-based reconnection. */\n id?: string;\n /**\n * Container display name passed to Docker as `--name`.\n * Characters outside `[a-zA-Z0-9_.-]` are replaced with `-` and the result\n * is prefixed if it would not start with an alphanumeric character.\n * @default the sandbox `id`\n */\n name?: string;\n /** Docker image to use.\n * @default 'node:22-slim'\n */\n image?: string;\n /**\n * Prepared baseline to boot from, as an alternative to `image`. The\n * template is built (or its cached image reused) lazily on `start()`, and\n * the container boots from the resulting image. A function form is resolved\n * once per `start()` that creates a container, so head-pinned repo\n * templates can re-resolve on each new sandbox.\n *\n * When `workingDirectory` is not set, the template's last `setWorkdir`\n * becomes the sandbox working directory. Mutually exclusive with `image`.\n */\n template?: DockerTemplateSpec;\n /** Container entrypoint command. Must keep the container alive.\n * @default ['sleep', 'infinity']\n */\n command?: string[];\n /** Environment variables to set in the container */\n env?: Record<string, string>;\n /** Host-to-container bind mounts (e.g., `{ '/host/path': '/container/path' }`) */\n volumes?: Record<string, string>;\n /** Docker network to join */\n network?: string;\n /** Run in privileged mode\n * @default false\n */\n privileged?: boolean;\n /** Memory limit in bytes (HostConfig.Memory). Docker treats 0 as unlimited. */\n memory?: number;\n /** Total memory plus swap in bytes (HostConfig.MemorySwap). */\n memorySwap?: number;\n /** CPU shares relative weight (HostConfig.CpuShares). */\n cpuShares?: number;\n /** CPU quota in microseconds per period (HostConfig.CpuQuota). */\n cpuQuota?: number;\n /** CPU period in microseconds (HostConfig.CpuPeriod). */\n cpuPeriod?: number;\n /** Maximum number of PIDs in the container (HostConfig.PidsLimit). */\n pidsLimit?: number;\n /**\n * Run an init process (tini) as PID 1 to reap zombie children (HostConfig.Init).\n * Without this, processes orphaned by a command (e.g. after a timeout/kill) remain\n * as zombies and keep counting against `pidsLimit`.\n * @default true\n */\n init?: boolean;\n /** Mount the container root filesystem as read-only (HostConfig.ReadonlyRootfs). */\n readonlyRootfs?: boolean;\n /** Linux capabilities to drop (HostConfig.CapDrop), e.g. ['ALL']. */\n capDrop?: string[];\n /** Linux capabilities to add (HostConfig.CapAdd). */\n capAdd?: string[];\n /** Security options (HostConfig.SecurityOpt), e.g. ['no-new-privileges:true']. */\n securityOpt?: string[];\n /** Ulimit entries for Docker HostConfig.Ulimits. */\n ulimits?: DockerSandboxUlimit[];\n /** tmpfs mount paths with options (HostConfig.Tmpfs). */\n tmpfs?: DockerSandboxTmpfs;\n /**\n * Mounts mapped 1:1 onto `HostConfig.Mounts`.\n *\n * Use this instead of `volumes` when you need mount options that Docker's\n * `-v`/`HostConfig.Binds` syntax cannot express — in particular\n * `volumeOptions.subpath` (mount a subdirectory of a named volume). `volumes`\n * and `mounts` may be combined; both are passed through to Docker.\n */\n mounts?: DockerSandboxMount[];\n /** Default command timeout in milliseconds\n * @default 300_000 // 5 minutes\n */\n timeout?: number;\n /** Working directory inside the container\n * @default '/workspace'\n * @deprecated Use `workingDirectory` (the base sandbox option) instead.\n * When both are set, `workingDirectory` wins.\n */\n workingDir?: string;\n /** Container labels for filtering and identification */\n labels?: Record<string, string>;\n /** Pass-through dockerode connection options (socket path, host, TLS certs) */\n dockerOptions?: Docker.DockerOptions;\n /**\n * Custom instructions that override the default instructions\n * returned by `getInstructions()`.\n *\n * - `string` — Fully replaces the default instructions.\n * Pass an empty string to suppress instructions entirely.\n * - `(opts) => string` — Receives the default instructions and\n * optional request context so you can extend or customise per-request.\n */\n instructions?: InstructionsOption;\n}\n\n// =============================================================================\n// Docker Sandbox Implementation\n// =============================================================================\n\n/**\n * Docker sandbox implementation using long-lived containers.\n *\n * Features:\n * - Long-lived container with `docker exec` for commands\n * - Bind mount support via Docker volumes\n * - Reconnection to existing containers by ID/name\n * - Container label tracking for discovery\n *\n * @example Basic usage\n * ```typescript\n * import { Workspace } from '@mastra/core/workspace';\n * import { DockerSandbox } from '@mastra/docker';\n *\n * const sandbox = new DockerSandbox({\n * image: 'node:22-slim',\n * timeout: 60000,\n * });\n *\n * const workspace = new Workspace({ sandbox });\n * const result = await workspace.executeCode('console.log(\"Hello!\")');\n * ```\n *\n * @example With bind mounts\n * ```typescript\n * const sandbox = new DockerSandbox({\n * image: 'node:22-slim',\n * volumes: { '/my/project': '/workspace/project' },\n * });\n * ```\n */\nexport class DockerSandbox extends MastraSandbox {\n readonly id: string;\n readonly name = 'DockerSandbox';\n readonly provider = 'docker';\n status: ProviderStatus = 'pending';\n\n declare readonly processes: DockerProcessManager;\n\n /** Underlying Docker client */\n private readonly _docker: Docker;\n\n /** Container reference (set after start) */\n private _container: Container | null = null;\n\n /** Configuration */\n private readonly _containerName: string;\n /** Image the container boots from; rewritten by a template resolution on `start()`. */\n private _image: string;\n private readonly _templateSpec?: DockerTemplateSpec;\n private readonly _workingDirectoryWasSet: boolean;\n private readonly _command: string[];\n private readonly _env: Record<string, string>;\n private readonly _volumes: Record<string, string>;\n private readonly _network?: string;\n private readonly _privileged: boolean;\n private readonly _privilegedWasSet: boolean;\n private readonly _memory?: number;\n private readonly _memorySwap?: number;\n private readonly _cpuShares?: number;\n private readonly _cpuQuota?: number;\n private readonly _cpuPeriod?: number;\n private readonly _pidsLimit?: number;\n private readonly _init: boolean;\n private readonly _readonlyRootfs?: boolean;\n private readonly _capDrop?: string[];\n private readonly _capAdd?: string[];\n private readonly _securityOpt?: string[];\n private readonly _ulimits?: DockerSandboxUlimit[];\n private readonly _tmpfs?: DockerSandboxTmpfs;\n private readonly _mounts?: DockerSandboxMount[];\n private readonly _labels: Record<string, string>;\n private readonly _instructionsOverride?: InstructionsOption;\n private readonly _constructorOptions: DockerSandboxOptions;\n\n /**\n * The effective container working directory. Narrowed to `string`: the\n * constructor always resolves a value (option, deprecated alias, or\n * `/workspace`), so unlike the base getter this never returns `undefined`.\n */\n override get workingDirectory(): string {\n return this._workingDirectory!;\n }\n\n constructor(options: DockerSandboxOptions = {}) {\n const processManager = new DockerProcessManager({\n defaultTimeout: options.timeout ?? 300_000,\n });\n\n super({\n ...options,\n name: 'DockerSandbox',\n processes: processManager,\n });\n\n this.id = options.id ?? this._generateId();\n this._containerName = sanitizeContainerName(options.name ?? this.id);\n if (options.image !== undefined && options.template !== undefined) {\n throw new TypeError('DockerSandbox: `image` and `template` are mutually exclusive');\n }\n this._templateSpec = options.template;\n this._image = options.image ?? 'node:22-slim';\n this._workingDirectoryWasSet = options.workingDirectory !== undefined || options.workingDir !== undefined;\n this._command = options.command ?? ['sleep', 'infinity'];\n this._env = options.env ?? {};\n this._volumes = options.volumes ?? {};\n this._network = options.network;\n this._privileged = options.privileged ?? false;\n this._privilegedWasSet = options.privileged !== undefined;\n this._memory = options.memory;\n this._memorySwap = options.memorySwap;\n this._cpuShares = options.cpuShares;\n this._cpuQuota = options.cpuQuota;\n this._cpuPeriod = options.cpuPeriod;\n this._pidsLimit = options.pidsLimit;\n this._init = options.init ?? true;\n this._readonlyRootfs = options.readonlyRootfs;\n this._capDrop = options.capDrop;\n this._capAdd = options.capAdd;\n this._securityOpt = options.securityOpt;\n this._ulimits = options.ulimits;\n this._tmpfs = options.tmpfs;\n this._mounts = options.mounts;\n this.setWorkingDirectory(options.workingDirectory ?? options.workingDir ?? '/workspace');\n this._labels = {\n ...options.labels,\n 'mastra.sandbox': 'true',\n 'mastra.sandbox.id': this.id,\n };\n this._instructionsOverride = options.instructions;\n this._docker = new Docker(options.dockerOptions);\n this._constructorOptions = { ...options };\n }\n\n /**\n * Construct a sibling `DockerSandbox` that inherits this sandbox's\n * configuration (image, resource limits, security options, labels,\n * connection options) with per-instance overrides.\n *\n * Performs no I/O — the sandbox clone provisions (or reconnects to an\n * existing container labelled with the same logical `id`) on its own\n * `start()`. Use it when one configured sandbox acts as the template for a\n * fleet of independent sandboxes (e.g. one per project).\n *\n * `options.idleTimeoutMinutes` is ignored (Docker containers have no\n * provider-side idle teardown; `timeout` here is a command timeout), and\n * `options.sandboxId` is ignored because reconnection is by logical `id`.\n */\n clone(options: SandboxCloneOptions = {}): DockerSandbox {\n const { id: _id, name: _name, ...base } = this._constructorOptions;\n return new DockerSandbox({\n ...base,\n ...(options.id !== undefined && { id: options.id }),\n ...(options.env !== undefined && { env: options.env }),\n ...(options.workingDirectory !== undefined && { workingDirectory: options.workingDirectory }),\n });\n }\n\n /**\n * Get the underlying Docker container for direct access.\n * @throws {SandboxNotReadyError} If the sandbox has not been started.\n */\n get container(): Container {\n if (!this._container) {\n throw new SandboxNotReadyError(this.id);\n }\n return this._container;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n async start(): Promise<void> {\n this.logger.debug(`${LOG_PREFIX} Starting sandbox ${this.id}...`);\n\n // Try to reconnect to existing container\n const existing = await this._findExistingContainer();\n if (existing) {\n this.logger.debug(`${LOG_PREFIX} Found existing container ${existing.Id}`);\n this._container = this._docker.getContainer(existing.Id);\n\n // Use inspect() to get authoritative container state — listContainers() state\n // can be stale immediately after stop() returns but before container fully exits\n const info = await this._container.inspect();\n // On reconnect, actual HostConfig controls whether hardening is effective.\n this._warnOnPrivilegedHardeningConflict(info.HostConfig?.Privileged ?? this._privileged);\n this._warnOnReconnectedHostConfigMismatch(existing.Id, info.HostConfig);\n const actualState = info.State?.Running ? 'running' : 'stopped';\n\n if (actualState !== 'running') {\n this.logger.debug(`${LOG_PREFIX} Container exists but not running (${actualState}), starting...`);\n await this._container.start();\n }\n\n // The container was created with a working directory (possibly derived\n // from a template); keep resolving relative paths against it rather than\n // this instance's default.\n const reconnectedWorkingDir = info.Config?.WorkingDir;\n if (!this._workingDirectoryWasSet && reconnectedWorkingDir) {\n this.setWorkingDirectory(reconnectedWorkingDir);\n }\n\n // Provide container reference to process manager\n this.processes.setContainer(this._container);\n\n this.logger.debug(`${LOG_PREFIX} Reconnected to container ${existing.Id}`);\n return;\n }\n\n this._warnOnPrivilegedHardeningConflict(this._privileged);\n\n await this._resolveTemplate();\n\n // Pull image if not available locally\n await this._ensureImage();\n\n // Build environment array for Docker API\n const envArray = Object.entries(this._env).map(([k, v]) => `${k}=${v}`);\n\n // Build bind mount array\n const binds = Object.entries(this._volumes).map(([host, container]) => `${host}:${container}`);\n\n // Create container\n this.logger.debug(`${LOG_PREFIX} Creating container with image ${this._image}...`);\n this._container = await this._docker.createContainer({\n name: this._containerName,\n Image: this._image,\n Cmd: this._command,\n Env: envArray,\n WorkingDir: this.workingDirectory,\n Labels: this._labels,\n HostConfig: {\n Binds: binds.length > 0 ? binds : undefined,\n NetworkMode: this._network,\n Privileged: this._privileged,\n Memory: this._memory,\n MemorySwap: this._memorySwap,\n CpuShares: this._cpuShares,\n CpuQuota: this._cpuQuota,\n CpuPeriod: this._cpuPeriod,\n PidsLimit: this._pidsLimit,\n Init: this._init,\n ReadonlyRootfs: this._readonlyRootfs,\n CapDrop: this._capDrop,\n CapAdd: this._capAdd,\n SecurityOpt: this._securityOpt,\n Ulimits: this._ulimits?.map(toDockerUlimit),\n Tmpfs: this._tmpfs,\n Mounts: this._mounts?.map(toDockerMount),\n },\n // Keep stdin open for interactive use\n OpenStdin: true,\n Tty: false,\n });\n\n // Start container\n await this._container.start();\n\n // Provide container reference to process manager\n this.processes.setContainer(this._container);\n\n this.logger.debug(`${LOG_PREFIX} Container started: ${this._container.id}`);\n }\n\n private _warnOnPrivilegedHardeningConflict(effectivePrivileged: boolean | undefined): void {\n if (!effectivePrivileged) return;\n\n // Privileged mode makes capability and security-option controls ineffective.\n // ReadonlyRootfs, ulimits, tmpfs, memory, CPU, and PID limits still apply.\n const conflictedHostConfigFields = [\n this._capDrop && this._capDrop.length > 0 ? 'CapDrop' : undefined,\n this._capAdd && this._capAdd.length > 0 ? 'CapAdd' : undefined,\n this._securityOpt && this._securityOpt.length > 0 ? 'SecurityOpt' : undefined,\n ].filter((field): field is keyof Docker.HostConfig => field !== undefined);\n\n if (conflictedHostConfigFields.length === 0) return;\n\n const optionNames = conflictedHostConfigFields.map(toDockerSandboxOptionName);\n\n this.logger.warn(\n `${LOG_PREFIX} Privileged containers can bypass some requested hardening controls: ${optionNames.join(', ')}`,\n { fields: optionNames, hostConfigFields: conflictedHostConfigFields },\n );\n }\n\n private _warnOnReconnectedHostConfigMismatch(containerId: string, hostConfig?: Docker.HostConfig): void {\n if (!hostConfig) return;\n\n const mismatchedHostConfigFields = this._requestedHardeningHostConfigEntries(hostConfig)\n .filter(([field, requestedValue]) => !isHostConfigValueEqual(field, hostConfig[field], requestedValue))\n .map(([field]) => field);\n\n if (mismatchedHostConfigFields.length === 0) return;\n\n if (\n !this._privilegedWasSet &&\n hostConfig.Privileged === true &&\n mismatchedHostConfigFields.includes('Privileged')\n ) {\n this.logger.warn(\n `${LOG_PREFIX} Reconnected to existing container ${containerId}; the existing container is privileged, but this DockerSandbox did not request privileged mode. Destroy and recreate the sandbox to apply the default non-privileged mode.`,\n { containerId, fields: ['privileged'], hostConfigFields: ['Privileged'] },\n );\n }\n\n const remainingMismatchedHostConfigFields = mismatchedHostConfigFields.filter(\n field => field !== 'Privileged' || this._privilegedWasSet,\n );\n\n if (remainingMismatchedHostConfigFields.length === 0) return;\n\n const mismatchedOptions = remainingMismatchedHostConfigFields.map(toDockerSandboxOptionName);\n\n this.logger.warn(\n `${LOG_PREFIX} Reconnected to existing container ${containerId}; requested Docker option(s) ${mismatchedOptions.join(\n ', ',\n )} differ from inspected HostConfig field(s) ${remainingMismatchedHostConfigFields.join(\n ', ',\n )} and cannot be applied to the existing container. Destroy and recreate the sandbox to apply them.`,\n { containerId, fields: mismatchedOptions, hostConfigFields: remainingMismatchedHostConfigFields },\n );\n }\n\n private _requestedHardeningHostConfigEntries(\n hostConfig?: Docker.HostConfig,\n ): Array<[keyof Docker.HostConfig, unknown]> {\n const entries: Array<[keyof Docker.HostConfig, unknown]> = [\n ['Memory', this._memory],\n ['MemorySwap', this._memorySwap],\n ['CpuShares', this._cpuShares],\n ['CpuQuota', this._cpuQuota],\n ['CpuPeriod', this._cpuPeriod],\n ['PidsLimit', this._pidsLimit],\n ['ReadonlyRootfs', this._readonlyRootfs],\n ['CapDrop', this._capDrop],\n ['CapAdd', this._capAdd],\n ['SecurityOpt', this._securityOpt],\n ['Ulimits', this._ulimits],\n ['Tmpfs', this._tmpfs],\n ['Mounts', this._mounts?.map(toDockerMount)],\n ];\n\n if (this._privilegedWasSet || hostConfig?.Privileged === true) {\n entries.unshift(['Privileged', this._privileged]);\n }\n\n return entries.filter((entry): entry is [keyof Docker.HostConfig, unknown] => isPresentHostConfigValue(entry[1]));\n }\n\n async stop(): Promise<void> {\n const container = await this._resolveContainer();\n if (!container) return;\n\n this.logger.debug(`${LOG_PREFIX} Stopping container ${container.id}...`);\n try {\n await container.stop({ t: 10 });\n } catch (error: unknown) {\n // Container may already be stopped\n if (!isContainerNotRunningError(error)) {\n throw error;\n }\n }\n this.processes.reset();\n this.logger.debug(`${LOG_PREFIX} Container stopped`);\n }\n\n async destroy(): Promise<void> {\n const container = await this._resolveContainer();\n if (!container) return;\n\n this.logger.debug(`${LOG_PREFIX} Destroying container ${container.id}...`);\n try {\n await container.remove({ force: true, v: true });\n } catch (error: unknown) {\n // Container may already be removed\n if (!isContainerNotFoundError(error)) {\n throw error;\n }\n }\n this.processes.reset();\n this._container = null;\n this.logger.debug(`${LOG_PREFIX} Container destroyed`);\n }\n\n // ---------------------------------------------------------------------------\n // File Upload\n // ---------------------------------------------------------------------------\n\n /**\n * Bulk-write files into the container's filesystem using Docker's native\n * archive upload (`putArchive`), the same mechanism as `docker cp`.\n *\n * Behavior:\n * - Requires a started sandbox. Throws {@link SandboxNotReadyError} otherwise\n * (Docker containers are not auto-started by this method).\n * - Absolute paths are used as-is; relative paths resolve against\n * {@link workingDirectory}.\n * - Missing parent directories are created automatically.\n * - Existing destinations are overwritten (contents and mode).\n * - Exact bytes are preserved for both `string` and `Buffer` content,\n * including empty files and binary data.\n * - New files use the per-file `mode` when provided (validated integer\n * `0o001`–`0o777`), otherwise `0644`; directories created implicitly default\n * to Docker's `0755`. Overwriting a file replaces its mode with the\n * requested `mode` (or `0644` when omitted).\n * - Not atomic across files: on failure the promise rejects and earlier or\n * partially written files may remain.\n *\n * Cancellation (`options.abortSignal`):\n * - If the signal is already aborted, rejects with {@link SandboxAbortError}\n * before creating the archive or starting the upload.\n * - If the signal aborts during transfer, the underlying `putArchive` request\n * is terminated by destroying the tar stream (which ends the request body),\n * and the promise rejects with {@link SandboxAbortError}.\n * - Upload and cancellation race: an upload that completes before the abort is\n * observed resolves normally.\n * - No rollback: files Docker already received or extracted may remain. The\n * daemon may continue extraction after rejection, so the caller is\n * responsible for any cleanup or sandbox disposal.\n * - Behavior is unchanged when no signal is supplied.\n *\n * @throws {SandboxNotReadyError} If the sandbox has not been started.\n * @throws {SandboxAbortError} If the write is cancelled via `options.abortSignal`.\n * @throws {SandboxError} If the archive upload fails.\n */\n async writeFiles(files: SandboxFileInput[], options?: WriteFilesOptions): Promise<void> {\n const container = this.container;\n\n const signal = options?.abortSignal;\n if (signal?.aborted) throw new SandboxAbortError('writeFiles');\n\n if (files.length === 0) return;\n\n const pack = tarPack();\n for (const file of files) {\n if (file.mode !== undefined) validateSandboxFileMode(file.mode);\n const resolved = posixPath.isAbsolute(file.path)\n ? posixPath.normalize(file.path)\n : posixPath.resolve(this.workingDirectory, file.path);\n const data = Buffer.isBuffer(file.content) ? file.content : Buffer.from(file.content);\n const mode = file.mode ?? 0o644;\n // tar entries are relative; strip the leading slash so extraction at `/`\n // lands the file at its intended absolute path.\n pack.entry({ name: resolved.replace(/^\\/+/, ''), size: data.length, mode }, data);\n }\n pack.finalize();\n\n // Destroying the tar stream ends the putArchive request body, which\n // terminates the in-flight HTTP upload to the Docker daemon. The\n // abortSignal is also forwarded to putArchive for transports that observe\n // it; it is harmless when ignored.\n const onAbort = () => pack.destroy();\n if (signal) signal.addEventListener('abort', onAbort, { once: true });\n\n try {\n await container.putArchive(pack, { path: '/', abortSignal: signal });\n } catch (error) {\n if (signal?.aborted) throw new SandboxAbortError('writeFiles');\n throw new SandboxError(\n `Failed to write files to sandbox: ${error instanceof Error ? error.message : String(error)}`,\n 'EXECUTION_FAILED',\n { reason: 'write_files_failed' },\n );\n } finally {\n if (signal) signal.removeEventListener('abort', onAbort);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Instructions\n // ---------------------------------------------------------------------------\n\n getInstructions(opts?: { requestContext?: RequestContext }): string {\n const defaultInstructions = [\n `You are working inside a Docker container (image: ${this._image}).`,\n `The working directory is ${this.workingDirectory}.`,\n 'You can execute shell commands using executeCommand().',\n 'You can spawn background processes using processes.spawn().',\n ].join('\\n');\n\n if (this._instructionsOverride === undefined) return defaultInstructions;\n if (typeof this._instructionsOverride === 'string') return this._instructionsOverride;\n return this._instructionsOverride({ defaultInstructions, requestContext: opts?.requestContext });\n }\n\n // ---------------------------------------------------------------------------\n // Info\n // ---------------------------------------------------------------------------\n\n async getInfo(): Promise<SandboxInfo> {\n const info: SandboxInfo = {\n id: this.id,\n name: this.name,\n provider: this.provider,\n status: this.status,\n createdAt: new Date(),\n metadata: {\n image: this._image,\n workingDir: this.workingDirectory,\n labels: this._labels,\n },\n };\n\n if (this._container) {\n try {\n const inspect = await this._container.inspect();\n info.createdAt = new Date(inspect.Created);\n info.metadata = {\n ...info.metadata,\n containerId: inspect.Id,\n containerName: inspect.Name,\n state: inspect.State.Status,\n };\n } catch {\n // Container may have been removed\n }\n }\n\n return info;\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n private _generateId(): string {\n return `docker-sandbox-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n }\n\n /**\n * Resolve the container reference, looking up by label if `_container` is unset.\n * This ensures `stop()` and `destroy()` work even when the instance was created\n * with an existing container's ID but `start()` was never called.\n */\n private async _resolveContainer(): Promise<Container | null> {\n if (this._container) return this._container;\n const existing = await this._findExistingContainer();\n if (!existing) return null;\n this._container = this._docker.getContainer(existing.Id);\n return this._container;\n }\n\n /**\n * Find an existing container matching this sandbox's ID via labels.\n */\n private async _findExistingContainer(): Promise<ContainerInfo | null> {\n try {\n const containers = await this._docker.listContainers({\n all: true,\n filters: {\n label: [`mastra.sandbox.id=${this.id}`],\n },\n });\n return containers[0] ?? null;\n } catch (error) {\n // Log and re-throw infrastructure errors (daemon unreachable, auth, etc.)\n this.logger.debug(\n `${LOG_PREFIX} Failed to list containers: ${error instanceof Error ? error.message : String(error)}`,\n );\n throw error;\n }\n }\n\n /**\n * Resolve the `template` option (if any) into the image to boot from,\n * building it when no cached image exists. Runs on every `start()` that\n * creates a container, so a resolver-form template re-resolves each time.\n * Adopts the template's workdir unless the sandbox was given one explicitly.\n */\n private async _resolveTemplate(): Promise<void> {\n if (!this._templateSpec) return;\n const template = typeof this._templateSpec === 'function' ? await this._templateSpec() : this._templateSpec;\n // Build on this sandbox's daemon, which may differ from the template's default.\n const result = await template.build({ docker: this._docker });\n if (result.status !== 'ready') {\n throw new SandboxError(`Docker template build failed: ${result.error ?? 'unknown error'}`, 'START_FAILED', {\n templateId: result.templateId,\n reason: 'template_build_failed',\n });\n }\n this._image = result.templateId;\n if (!this._workingDirectoryWasSet && template.workdir !== undefined) {\n this.setWorkingDirectory(template.workdir);\n }\n }\n\n /**\n * Ensure the Docker image is available locally. Pulls if needed.\n */\n private async _ensureImage(): Promise<void> {\n try {\n await this._docker.getImage(this._image).inspect();\n this.logger.debug(`${LOG_PREFIX} Image ${this._image} available locally`);\n } catch (error) {\n // Only attempt pull if the image doesn't exist (404).\n // Re-throw infrastructure errors (daemon unreachable, auth, etc.)\n if (!isImageNotFoundError(error)) {\n throw error;\n }\n\n this.logger.debug(`${LOG_PREFIX} Pulling image ${this._image}...`);\n try {\n const stream = await this._docker.pull(this._image);\n await new Promise<void>((resolve, reject) => {\n this._docker.modem.followProgress(stream, (err: Error | null) => {\n if (err) reject(err);\n else resolve();\n });\n });\n this.logger.debug(`${LOG_PREFIX} Image ${this._image} pulled successfully`);\n } catch (error) {\n throw new SandboxError(\n `Failed to pull Docker image '${this._image}': ${error instanceof Error ? error.message : String(error)}`,\n 'NOT_READY',\n { image: this._image, reason: 'image_pull_failed' },\n );\n }\n }\n }\n}\n\n// =============================================================================\n// Error detection helpers\n// =============================================================================\n\n// Docker container name regex (`^[a-zA-Z0-9][a-zA-Z0-9_.-]+$`) — first char must be\n// alphanumeric, remaining chars from `[a-zA-Z0-9_.-]`, total length ≥ 2.\nfunction sanitizeContainerName(value: string): string {\n const replaced = value.replace(/[^a-zA-Z0-9_.-]/g, '-');\n const withLeading = /^[a-zA-Z0-9]/.test(replaced) ? replaced : `s-${replaced}`;\n return withLeading.length >= 2 ? withLeading : `${withLeading}-sandbox`;\n}\n\nfunction isContainerNotRunningError(error: unknown): boolean {\n if (error instanceof Error) {\n return error.message.includes('is not running') || error.message.includes('container already stopped');\n }\n return false;\n}\n\nfunction isContainerNotFoundError(error: unknown): boolean {\n if (error instanceof Error) {\n const msg = error.message.toLowerCase();\n return msg.includes('no such container') || (msg.includes('removal') && msg.includes('is already in progress'));\n }\n return false;\n}\n\nfunction isImageNotFoundError(error: unknown): boolean {\n if (error instanceof Error) {\n return error.message.toLowerCase().includes('no such image');\n }\n return false;\n}\n\nfunction isHostConfigValueEqual(field: keyof Docker.HostConfig, actual: unknown, expected: unknown): boolean {\n // Structural equality for the Docker HostConfig shapes exposed by DockerSandboxOptions.\n return isDeepStrictEqual(normalizeHostConfigValue(field, actual), normalizeHostConfigValue(field, expected));\n}\n\nfunction normalizeHostConfigValue(field: keyof Docker.HostConfig, value: unknown): unknown {\n if (value == null) return undefined;\n\n if ((field === 'CapAdd' || field === 'CapDrop') && Array.isArray(value)) {\n if (value.length === 0) return undefined;\n return value.map(normalizeCapability).sort();\n }\n\n if (field === 'SecurityOpt' && Array.isArray(value)) {\n if (value.length === 0) return undefined;\n return value.map(normalizeSecurityOpt).sort();\n }\n\n if (field === 'Tmpfs' && value && typeof value === 'object' && !Array.isArray(value)) {\n if (Object.keys(value).length === 0) return undefined;\n return Object.fromEntries(\n Object.entries(value)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([path, options]) => [path, typeof options === 'string' ? normalizeTmpfsOptions(options) : options]),\n );\n }\n\n if (Array.isArray(value)) {\n if (field === 'Ulimits' && value.length === 0) return undefined;\n return value\n .map(nestedValue => normalizeHostConfigValue(field, nestedValue))\n .sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)));\n }\n\n if (field === 'Ulimits' && value && typeof value === 'object') {\n return normalizeUlimit(value);\n }\n\n if (value && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, nestedValue]) => [key, normalizeHostConfigValue(field, nestedValue)]),\n );\n }\n\n return value;\n}\n\nfunction isPresentHostConfigValue(value: unknown): boolean {\n if (value == null) return false;\n if (Array.isArray(value)) return value.length > 0;\n if (value && typeof value === 'object') return Object.keys(value).length > 0;\n return true;\n}\n\nfunction normalizeCapability(capability: unknown): unknown {\n return typeof capability === 'string' ? capability.toUpperCase().replace(/^CAP_/, '') : capability;\n}\n\nfunction normalizeTmpfsOptions(options: string): string {\n return options\n .split(',')\n .map(option => option.trim())\n .filter(Boolean)\n .sort()\n .join(',');\n}\n\nfunction normalizeSecurityOpt(option: unknown): unknown {\n if (typeof option !== 'string') return option;\n\n const noNewPrivileges = option.match(/^no-new-privileges[:=](.+)$/i);\n if (noNewPrivileges) {\n return `no-new-privileges=${noNewPrivileges[1]}`;\n }\n\n return option;\n}\n\nfunction normalizeUlimit(value: object): unknown {\n const record = value as Record<string, unknown>;\n return {\n name: record.name ?? record.Name,\n soft: record.soft ?? record.Soft,\n hard: record.hard ?? record.Hard,\n };\n}\n\nfunction toDockerUlimit(ulimit: DockerSandboxUlimit): Docker.Ulimit {\n return {\n Name: ulimit.name,\n Soft: ulimit.soft,\n Hard: ulimit.hard,\n };\n}\n\nfunction toDockerMount(mount: DockerSandboxMount): Docker.MountSettings {\n const settings: Docker.MountSettings = {\n Type: mount.type,\n Target: mount.target,\n Source: mount.type === 'tmpfs' ? '' : mount.source,\n };\n\n if (mount.readOnly !== undefined) settings.ReadOnly = mount.readOnly;\n\n if (mount.type === 'volume' && mount.volumeOptions) {\n const { subpath, noCopy, labels } = mount.volumeOptions;\n // The @types/dockerode VolumeOptions marks NoCopy/Labels/DriverConfig as\n // required, but the Docker API treats them as optional; build a partial.\n const volumeOptions: Record<string, unknown> = {};\n if (subpath !== undefined) volumeOptions.Subpath = subpath;\n if (noCopy !== undefined) volumeOptions.NoCopy = noCopy;\n if (labels !== undefined) volumeOptions.Labels = labels;\n if (Object.keys(volumeOptions).length > 0) {\n settings.VolumeOptions = volumeOptions as Docker.MountSettings['VolumeOptions'];\n }\n }\n\n if (mount.type === 'bind' && mount.bindOptions?.propagation !== undefined) {\n settings.BindOptions = { Propagation: mount.bindOptions.propagation };\n }\n\n if (mount.type === 'tmpfs' && mount.tmpfsOptions) {\n const { sizeBytes, mode } = mount.tmpfsOptions;\n const tmpfsOptions: Record<string, unknown> = {};\n if (sizeBytes !== undefined) tmpfsOptions.SizeBytes = sizeBytes;\n if (mode !== undefined) tmpfsOptions.Mode = mode;\n if (Object.keys(tmpfsOptions).length > 0) {\n settings.TmpfsOptions = tmpfsOptions as Docker.MountSettings['TmpfsOptions'];\n }\n }\n\n return settings;\n}\n\nfunction toDockerSandboxOptionName(field: keyof Docker.HostConfig): string {\n const optionNames: Partial<Record<keyof Docker.HostConfig, string>> = {\n Privileged: 'privileged',\n Memory: 'memory',\n MemorySwap: 'memorySwap',\n CpuShares: 'cpuShares',\n CpuQuota: 'cpuQuota',\n CpuPeriod: 'cpuPeriod',\n PidsLimit: 'pidsLimit',\n ReadonlyRootfs: 'readonlyRootfs',\n CapDrop: 'capDrop',\n CapAdd: 'capAdd',\n SecurityOpt: 'securityOpt',\n Ulimits: 'ulimits',\n Tmpfs: 'tmpfs',\n Mounts: 'mounts',\n };\n\n return optionNames[field] ?? String(field);\n}\n","/**\n * Docker Sandbox Provider Descriptor\n *\n * Enables registration with MastraEditor for UI-driven sandbox configuration.\n */\n\nimport type { SandboxProvider } from '@mastra/core/editor';\nimport { DockerSandbox } from './sandbox';\nimport type { DockerSandboxOptions } from './sandbox';\n\n/**\n * Serializable config for the Docker sandbox provider.\n * This is the subset of DockerSandboxOptions that can be stored in a config file\n * and rendered in a UI form.\n */\nexport interface DockerProviderConfig {\n /** Docker image to use */\n image?: string;\n /** Default command timeout in milliseconds */\n timeout?: number;\n /** Environment variables */\n env?: Record<string, string>;\n /** Host-to-container bind mounts */\n volumes?: Record<string, string>;\n /** Docker network to join */\n network?: string;\n /** Working directory inside the container */\n workingDir?: string;\n /** Run in privileged mode */\n privileged?: boolean;\n /** Memory limit in bytes */\n memory?: number;\n /** Total memory plus swap in bytes */\n memorySwap?: number;\n /** CPU shares relative weight */\n cpuShares?: number;\n /** CPU quota in microseconds per period */\n cpuQuota?: number;\n /** CPU period in microseconds */\n cpuPeriod?: number;\n /** Maximum number of PIDs in the container */\n pidsLimit?: number;\n /** Mount the container root filesystem as read-only */\n readonlyRootfs?: boolean;\n /** Linux capabilities to drop */\n capDrop?: string[];\n /** Linux capabilities to add */\n capAdd?: string[];\n /** Docker security options */\n securityOpt?: string[];\n /** Ulimit entries for Docker HostConfig.Ulimits */\n ulimits?: DockerSandboxOptions['ulimits'];\n /** tmpfs mount paths with options */\n tmpfs?: DockerSandboxOptions['tmpfs'];\n /** Mounts mapped 1:1 onto Docker HostConfig.Mounts (supports volume subpath) */\n mounts?: DockerSandboxOptions['mounts'];\n}\n\nexport const dockerSandboxProvider: SandboxProvider<DockerProviderConfig> = {\n id: 'docker',\n name: 'Docker Sandbox',\n description: 'Local container sandbox powered by Docker',\n configSchema: {\n type: 'object',\n properties: {\n image: {\n type: 'string',\n description: 'Docker image to use',\n default: 'node:22-slim',\n },\n timeout: {\n type: 'number',\n description: 'Default command timeout in milliseconds',\n default: 300_000,\n },\n env: {\n type: 'object',\n description: 'Environment variables',\n additionalProperties: { type: 'string' },\n },\n volumes: {\n type: 'object',\n description: 'Host-to-container bind mounts (host path → container path)',\n additionalProperties: { type: 'string' },\n },\n network: {\n type: 'string',\n description: 'Docker network to join',\n },\n workingDir: {\n type: 'string',\n description: 'Working directory inside the container',\n default: '/workspace',\n },\n privileged: {\n type: 'boolean',\n description: 'Run in privileged mode',\n default: false,\n },\n memory: {\n type: 'number',\n description: 'Memory limit in bytes',\n },\n memorySwap: {\n type: 'number',\n description: 'Total memory plus swap in bytes',\n },\n cpuShares: {\n type: 'number',\n description: 'CPU shares relative weight',\n },\n cpuQuota: {\n type: 'number',\n description: 'CPU quota in microseconds per period',\n },\n cpuPeriod: {\n type: 'number',\n description: 'CPU period in microseconds',\n },\n pidsLimit: {\n type: 'number',\n description: 'Maximum number of PIDs in the container',\n },\n readonlyRootfs: {\n type: 'boolean',\n description: 'Mount the container root filesystem as read-only',\n },\n capDrop: {\n type: 'array',\n description: 'Linux capabilities to drop',\n items: { type: 'string' },\n },\n capAdd: {\n type: 'array',\n description: 'Linux capabilities to add',\n items: { type: 'string' },\n },\n securityOpt: {\n type: 'array',\n description: 'Docker security options',\n items: { type: 'string' },\n },\n ulimits: {\n type: 'array',\n description: 'Ulimit entries for Docker HostConfig.Ulimits',\n items: {\n type: 'object',\n required: ['name', 'soft', 'hard'],\n additionalProperties: false,\n properties: {\n name: { type: 'string' },\n soft: { type: 'number' },\n hard: { type: 'number' },\n },\n },\n },\n tmpfs: {\n type: 'object',\n description: 'tmpfs mount paths with options',\n additionalProperties: { type: 'string' },\n },\n mounts: {\n type: 'array',\n description: 'Mounts mapped 1:1 onto Docker HostConfig.Mounts (supports volume subpath)',\n items: {\n oneOf: [\n {\n type: 'object',\n required: ['type', 'target', 'source'],\n additionalProperties: false,\n properties: {\n type: { const: 'volume' },\n target: { type: 'string' },\n source: { type: 'string' },\n readOnly: { type: 'boolean' },\n volumeOptions: {\n type: 'object',\n additionalProperties: false,\n properties: {\n subpath: { type: 'string' },\n noCopy: { type: 'boolean' },\n labels: { type: 'object', additionalProperties: { type: 'string' } },\n },\n },\n },\n },\n {\n type: 'object',\n required: ['type', 'target', 'source'],\n additionalProperties: false,\n properties: {\n type: { const: 'bind' },\n target: { type: 'string' },\n source: { type: 'string' },\n readOnly: { type: 'boolean' },\n bindOptions: {\n type: 'object',\n additionalProperties: false,\n properties: {\n propagation: {\n type: 'string',\n enum: ['private', 'rprivate', 'shared', 'rshared', 'slave', 'rslave'],\n },\n },\n },\n },\n },\n {\n type: 'object',\n required: ['type', 'target'],\n additionalProperties: false,\n properties: {\n type: { const: 'tmpfs' },\n target: { type: 'string' },\n readOnly: { type: 'boolean' },\n tmpfsOptions: {\n type: 'object',\n additionalProperties: false,\n properties: {\n sizeBytes: { type: 'number' },\n mode: { type: 'number' },\n },\n },\n },\n },\n ],\n },\n },\n },\n },\n createSandbox: (config: DockerProviderConfig) => new DockerSandbox(config as DockerSandboxOptions),\n};\n","/**\n * BuildKit session that serves build secrets to the daemon.\n *\n * `docker build` with BuildKit (`version=2`) can attach a long-lived gRPC\n * \"session\" that the daemon calls back into for things it needs mid-build.\n * `RUN --mount=type=secret,id=X` is resolved by calling\n * `/moby.buildkit.secrets.v1.Secrets/GetSecret` on that session, so the value\n * exists only in the tmpfs mount for the duration of that one RUN — never as a\n * build arg, layer, history entry, or cache metadata.\n *\n * dockerode's own session helper only registers the registry-auth service and\n * overwrites any `session` id passed to `buildImage`, so this module dials the\n * hijacked `/session` endpoint itself and registers both services.\n */\nimport { randomUUID } from 'node:crypto';\nimport { Server, ServerCredentials, type ServiceDefinition, type UntypedServiceImplementation } from '@grpc/grpc-js';\nimport type Docker from 'dockerode';\n\nexport const SECRETS_GET_METHOD = '/moby.buildkit.secrets.v1.Secrets/GetSecret';\nconst AUTH_CREDENTIALS_METHOD = '/moby.filesync.v1.Auth/Credentials';\n\nexport interface BuildSession {\n id: string;\n close(): void;\n}\n\n/**\n * Open a session that answers `GetSecret` from `secrets`. The returned id must\n * be sent as the `session` query parameter of the build request.\n */\nexport function openBuildSession(docker: Docker, secrets: Record<string, string>): Promise<BuildSession> {\n const id = randomUUID();\n return new Promise((resolve, reject) => {\n docker.modem.dial(\n {\n method: 'POST',\n path: '/session',\n hijack: true,\n headers: {\n Upgrade: 'h2c',\n 'X-Docker-Expose-Session-Uuid': id,\n 'X-Docker-Expose-Session-Name': 'mastra-docker-template',\n // The daemon only calls methods the client advertises.\n 'X-Docker-Expose-Session-Grpc-Method': [SECRETS_GET_METHOD, AUTH_CREDENTIALS_METHOD],\n },\n statusCodes: { 200: true, 500: 'server error' },\n },\n (err: Error | null, socket: unknown) => {\n if (err) {\n reject(err);\n return;\n }\n const server = new Server();\n server.createConnectionInjector(ServerCredentials.createInsecure()).injectConnection(socket as never);\n server.addService(secretsService, {\n GetSecret(\n call: { request: GetSecretRequest },\n callback: (err: Error | null, res?: GetSecretResponse) => void,\n ) {\n const value = Object.hasOwn(secrets, call.request.id) ? secrets[call.request.id] : undefined;\n if (value === undefined) {\n callback(\n Object.assign(new Error(`no build secret registered with id '${call.request.id}'`), { code: 5 }),\n );\n return;\n }\n callback(null, { data: Buffer.from(value, 'utf8') });\n },\n } as UntypedServiceImplementation);\n server.addService(authService, {\n Credentials(_call: unknown, callback: (err: Error | null, res?: Record<string, never>) => void) {\n callback(null, {});\n },\n } as UntypedServiceImplementation);\n resolve({\n id,\n close() {\n server.forceShutdown();\n (socket as { end(): void }).end();\n },\n });\n },\n );\n });\n}\n\n// ---------------------------------------------------------------------------\n// Wire format\n//\n// The two messages involved are small enough that hand-rolling the protobuf\n// encoding beats loading .proto files at runtime (which would not survive\n// bundling).\n//\n// message GetSecretRequest { string ID = 1; map<string,string> annotations = 2; }\n// message GetSecretResponse { bytes data = 1; }\n// message CredentialsResponse { string Username = 1; string Secret = 2; }\n// ---------------------------------------------------------------------------\n\nexport interface GetSecretRequest {\n id: string;\n}\nexport interface GetSecretResponse {\n data: Buffer;\n}\n\n/** @internal exported for tests */\nexport function decodeGetSecretRequest(buffer: Buffer): GetSecretRequest {\n let offset = 0;\n let id = '';\n const readVarint = (): number => {\n let result = 0;\n let shift = 0;\n for (;;) {\n if (offset >= buffer.length) throw new Error('truncated varint');\n const byte = buffer[offset++]!;\n result += (byte & 0x7f) * 2 ** shift;\n if ((byte & 0x80) === 0) return result;\n shift += 7;\n }\n };\n while (offset < buffer.length) {\n const key = readVarint();\n const field = Math.floor(key / 8);\n const wireType = key % 8;\n switch (wireType) {\n case 0:\n readVarint();\n break;\n case 1:\n offset += 8;\n break;\n case 5:\n offset += 4;\n break;\n case 2: {\n const length = readVarint();\n const value = buffer.subarray(offset, offset + length);\n offset += length;\n if (field === 1) id = value.toString('utf8');\n break;\n }\n default:\n throw new Error(`unsupported protobuf wire type ${wireType}`);\n }\n }\n return { id };\n}\n\n/** @internal exported for tests */\nexport function encodeGetSecretResponse(response: GetSecretResponse): Buffer {\n return Buffer.concat([Buffer.from([0x0a]), encodeVarint(response.data.length), response.data]);\n}\n\nfunction encodeVarint(value: number): Buffer {\n const bytes: number[] = [];\n let remaining = value;\n while (remaining >= 0x80) {\n bytes.push((remaining % 0x80) | 0x80);\n remaining = Math.floor(remaining / 0x80);\n }\n bytes.push(remaining);\n return Buffer.from(bytes);\n}\n\nconst secretsService: ServiceDefinition = {\n GetSecret: {\n path: SECRETS_GET_METHOD,\n requestStream: false,\n responseStream: false,\n requestSerialize: () => {\n throw new Error('server does not serialize requests');\n },\n requestDeserialize: decodeGetSecretRequest,\n responseSerialize: encodeGetSecretResponse,\n responseDeserialize: () => {\n throw new Error('server does not deserialize responses');\n },\n },\n};\n\nconst authService: ServiceDefinition = {\n Credentials: {\n path: AUTH_CREDENTIALS_METHOD,\n requestStream: false,\n responseStream: false,\n requestSerialize: () => {\n throw new Error('server does not serialize requests');\n },\n requestDeserialize: () => ({}),\n // Empty message: anonymous registry access.\n responseSerialize: () => Buffer.alloc(0),\n responseDeserialize: () => {\n throw new Error('server does not deserialize responses');\n },\n },\n};\n","/**\n * Pure Dockerfile synthesis and content-addressed identity for DockerTemplate.\n *\n * A `DockerTemplate` records an ordered list of operations (setWorkdir, setEnvs,\n * runCmd, runWithSecrets, aptInstall, pipInstall, npmInstall) over a base image. This module\n * turns that ordered list into a deterministic Dockerfile string and a stable\n * content hash. It performs no I/O, so it is fully unit-testable without a\n * Docker daemon.\n */\n\nimport { createHash } from 'node:crypto';\n\n// =============================================================================\n// Operations\n// =============================================================================\n\nexport interface AptInstallOptions {\n /** Pass `--no-install-recommends` to `apt-get install`. */\n noInstallRecommends?: boolean;\n /** Pass `--fix-missing` to `apt-get install`. */\n fixMissing?: boolean;\n}\n\nexport interface PipInstallOptions {\n /** Install system-wide (default). `false` installs for the current user (`--user`). */\n g?: boolean;\n}\n\nexport interface NpmInstallOptions {\n /** Install globally (`npm install -g`). */\n g?: boolean;\n /** Include dev dependencies (`--include=dev`). Ignored when `packages` is set. */\n dev?: boolean;\n}\n\nexport interface RunWithSecretsOptions {\n /**\n * Names of environment variables whose values are read from the building\n * process's `process.env` at `build()` time and exposed to the command. Only\n * the names participate in the template identity.\n */\n secrets: string[];\n /**\n * Absolute path produced by the command. Only this path is copied into the\n * template image; everything else the command does (including the secret\n * values) stays in a throwaway build stage.\n */\n output: string;\n}\n\nexport type DockerTemplateOperation =\n | { method: 'setWorkdir'; args: [string] }\n | { method: 'setEnvs'; args: [Record<string, string>] }\n | { method: 'runCmd'; args: [string | string[]] }\n | { method: 'runWithSecrets'; args: [string | string[], RunWithSecretsOptions] }\n | { method: 'aptInstall'; args: [string | string[], AptInstallOptions?] }\n | { method: 'pipInstall'; args: [(string | string[])?, PipInstallOptions?] }\n | { method: 'npmInstall'; args: [(string | string[])?, NpmInstallOptions?] };\n\n/** A fully-resolved template definition: the base image and the ordered operations. */\nexport interface DockerTemplateDefinition {\n baseImage: string;\n operations: readonly DockerTemplateOperation[];\n}\n\n// =============================================================================\n// Dockerfile synthesis\n// =============================================================================\n\nfunction toCommandList(command: string | string[]): string[] {\n return Array.isArray(command) ? command : [command];\n}\n\nfunction sortedEntries(record: Record<string, string>): Array<[string, string]> {\n return Object.entries(record).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));\n}\n\nfunction renderEnvLine(envs: Record<string, string>): string | undefined {\n const pairs = sortedEntries(envs);\n if (pairs.length === 0) return undefined;\n // Deterministic order so identical envs always render identically.\n return `ENV ${pairs.map(([key, value]) => `${key}=${JSON.stringify(value)}`).join(' ')}`;\n}\n\nfunction renderAptInstall(packages: string | string[], options?: AptInstallOptions): string {\n const flags: string[] = [];\n if (options?.noInstallRecommends) flags.push('--no-install-recommends');\n if (options?.fixMissing) flags.push('--fix-missing');\n const flagStr = flags.length > 0 ? `${flags.join(' ')} ` : '';\n const pkgs = toCommandList(packages).join(' ');\n return `RUN apt-get update && apt-get install -y ${flagStr}${pkgs} && rm -rf /var/lib/apt/lists/*`;\n}\n\nfunction renderPipInstall(packages?: string | string[], options?: PipInstallOptions): string {\n const userFlag = options?.g === false ? ' --user' : '';\n const target = packages === undefined ? '.' : toCommandList(packages).join(' ');\n return `RUN pip install${userFlag} ${target}`;\n}\n\nfunction renderNpmInstall(packages?: string | string[], options?: NpmInstallOptions): string {\n const flags: string[] = [];\n if (options?.g) flags.push('-g');\n if (packages === undefined) {\n if (options?.dev) flags.push('--include=dev');\n const flagStr = flags.length > 0 ? ` ${flags.join(' ')}` : '';\n return `RUN npm install${flagStr}`;\n }\n const flagStr = flags.length > 0 ? ` ${flags.join(' ')}` : '';\n const pkgs = toCommandList(packages).join(' ');\n return `RUN npm install${flagStr} ${pkgs}`;\n}\n\nfunction secretStageName(index: number): string {\n return `mastra-secret-${index}`;\n}\n\nfunction mainStageName(index: number): string {\n return `mastra-main-${index}`;\n}\n\n/**\n * Render a deterministic Dockerfile from a template definition.\n *\n * Operations accumulate in a chain of \"main\" stages. Every `runWithSecrets`\n * operation forks a throwaway stage from the main stage as it stands at that\n * point (so it sees earlier WORKDIR/ENV/installs) and runs the command with\n * each secret exposed through a BuildKit secret mount, exported into the\n * command's environment for that single RUN. The next main stage then starts\n * from the same pre-secret snapshot and `COPY --from`s only the declared\n * output path. Secret mounts are tmpfs-backed and never part of a layer, its\n * history, or the build cache; the throwaway stage additionally keeps anything\n * else the command wrote (caches, logs) out of the template image.\n */\n/**\n * `RUN --mount=type=secret,id=X,mode=0444 ... export X=\"$(cat /run/secrets/X)\" && <command>`.\n * Reading the file into a shell variable keeps the value visible only to this\n * RUN's process tree, without depending on the newer `env=` mount option.\n * `mode=0444` because BuildKit's default is `0400 root`, which a base image\n * with a non-root `USER` cannot read; world-readable within the RUN is no\n * wider than the exported variable already is.\n */\nfunction renderSecretRun(command: string | string[], secrets: string[]): string {\n const names = [...secrets].sort();\n const mounts = names.map(name => `--mount=type=secret,id=${name},mode=0444`);\n const exports = names.map(name => `${name}=\"$(cat /run/secrets/${name})\"`);\n const prefix = names.length > 0 ? [`export ${exports.join(' ')}`] : [];\n return `RUN ${[...mounts, ''].join(' ')}${[...prefix, ...toCommandList(command)].join(' && ')}`;\n}\n\nexport function synthesizeDockerfile(definition: DockerTemplateDefinition): string {\n const lines: string[] = [];\n let mainIndex = 0;\n const openMain = (from: string) => {\n lines.push(`FROM ${from} AS ${mainStageName(mainIndex)}`);\n };\n openMain(definition.baseImage);\n\n definition.operations.forEach((operation, index) => {\n switch (operation.method) {\n case 'setWorkdir':\n lines.push(`WORKDIR ${operation.args[0]}`);\n break;\n case 'setEnvs': {\n const line = renderEnvLine(operation.args[0]);\n if (line) lines.push(line);\n break;\n }\n case 'runCmd':\n lines.push(`RUN ${toCommandList(operation.args[0]).join(' && ')}`);\n break;\n case 'runWithSecrets': {\n const [command, { secrets, output }] = operation.args;\n const snapshot = mainStageName(mainIndex);\n const stage = secretStageName(index);\n lines.push(`FROM ${snapshot} AS ${stage}`, renderSecretRun(command, secrets));\n mainIndex += 1;\n openMain(snapshot);\n lines.push(`COPY --from=${stage} ${output} ${output}`);\n break;\n }\n case 'aptInstall':\n lines.push(renderAptInstall(operation.args[0], operation.args[1]));\n break;\n case 'pipInstall':\n lines.push(renderPipInstall(operation.args[0], operation.args[1]));\n break;\n case 'npmInstall':\n lines.push(renderNpmInstall(operation.args[0], operation.args[1]));\n break;\n }\n });\n\n return `${lines.join('\\n')}\\n`;\n}\n\n/** Names of every secret referenced by `runWithSecrets` operations, deduplicated and sorted. */\nexport function secretNames(definition: DockerTemplateDefinition): string[] {\n const names = new Set<string>();\n for (const operation of definition.operations) {\n if (operation.method === 'runWithSecrets') {\n for (const name of operation.args[1].secrets) names.add(name);\n }\n }\n return [...names].sort();\n}\n\n// =============================================================================\n// Content-addressed identity\n// =============================================================================\n\n/** Prefix for template image tags built locally. */\nexport const TEMPLATE_IMAGE_REPO = 'mastra-template';\n\nfunction canonicalOperation(operation: DockerTemplateOperation): unknown {\n switch (operation.method) {\n case 'setEnvs':\n return { method: 'setEnvs', args: [sortedEntries(operation.args[0])] };\n case 'runWithSecrets': {\n const [command, { secrets, output }] = operation.args;\n return { method: 'runWithSecrets', args: [command, { secrets: [...secrets].sort(), output }] };\n }\n default:\n return operation;\n }\n}\n\n/**\n * Stable content hash over the base image and ordered operations. Env records\n * and secret name lists are canonicalized so insertion order does not change\n * the identity. Secret *values* never enter the definition, so the same\n * definition built with different credentials resolves to the same image tag.\n */\nexport function templateIdentity(definition: DockerTemplateDefinition): string {\n const canonical = JSON.stringify({\n schemaVersion: 1,\n baseImage: definition.baseImage,\n operations: definition.operations.map(canonicalOperation),\n });\n return createHash('sha256').update(canonical).digest('hex').slice(0, 24);\n}\n\n/** Full `mastra-template:<hash>` tag for a definition. */\nexport function templateImageTag(definition: DockerTemplateDefinition): string {\n return `${TEMPLATE_IMAGE_REPO}:${templateIdentity(definition)}`;\n}\n","/**\n * DockerTemplate — a reusable prepared baseline for the local Docker sandbox.\n *\n * Prepare an environment once (base image + ordered setup commands + env +\n * package installs), `build()` it into a content-addressed local image, then\n * spawn multiple disposable `DockerSandbox`es from that image. Each sandbox is a\n * fresh container with its own writable layer over the shared read-only image,\n * so their filesystems are independent. The built image's lifecycle is\n * controlled by `dispose()`, independent of any sandbox's `destroy()`.\n *\n * Unlike `docker commit` (which cannot capture mounted volumes and skips layer\n * caching), the baseline is produced by synthesizing a Dockerfile and running\n * `docker build`, so repo/setup content is baked into reproducible, cached\n * image layers.\n *\n * @example Prepare once, spawn many\n * ```typescript\n * import { DockerTemplate } from '@mastra/docker';\n *\n * const template = new DockerTemplate({ baseImage: 'node:22-slim' })\n * .runCmd('git clone --depth=1 https://example.com/repo /workspace/app')\n * .setWorkdir('/workspace/app')\n * .runCmd('npm ci');\n *\n * const result = await template.build();\n * if (result.status !== 'ready') throw new Error(result.error);\n *\n * const a = await template.createSandbox();\n * const b = await template.createSandbox(); // independent writable filesystem\n * ```\n */\n\nimport posixPath from 'node:path/posix';\nimport Docker from 'dockerode';\nimport { pack as tarPack } from 'tar-stream';\nimport { DockerSandbox, type DockerSandboxOptions } from '../sandbox';\nimport { openBuildSession, type BuildSession } from './build-session';\nimport {\n type AptInstallOptions,\n type DockerTemplateDefinition,\n type DockerTemplateOperation,\n type NpmInstallOptions,\n type PipInstallOptions,\n type RunWithSecretsOptions,\n secretNames,\n synthesizeDockerfile,\n templateImageTag,\n} from './dockerfile';\n\nconst MAX_OPERATIONS = 256;\nconst MAX_STRING_LENGTH = 32 * 1024;\nconst MAX_COLLECTION_ITEMS = 512;\n\nexport interface DockerTemplateOptions {\n /**\n * Base image for the template.\n * @default 'node:22-slim'\n */\n baseImage?: string;\n /** Pass-through dockerode connection options (socket path, host, TLS certs). */\n dockerOptions?: Docker.DockerOptions;\n /**\n * Values for the secrets named by {@link DockerTemplate.runWithSecrets}.\n * Supplying them here (rather than via `process.env`) keeps concurrent\n * builds with different credentials from racing on shared process state.\n * Not part of the template identity.\n */\n secrets?: DockerTemplateSecrets;\n}\n\n/**\n * Values for the secrets named by `runWithSecrets`, keyed by name. Either a\n * record or a function producing one (called once per real build, so rotated\n * credentials are picked up without rebuilding the template object).\n */\nexport type DockerTemplateSecrets =\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>);\n\nexport interface DockerTemplateBuildOptions {\n /**\n * Rebuild even if an image with the computed tag already exists locally,\n * re-executing every step instead of reusing the daemon's layer cache (the\n * cache does not key on secret values or on what `git clone`/`npm install`\n * would fetch today).\n */\n force?: boolean;\n /**\n * Build on this Docker client instead of the template's own. A sandbox\n * passes its client so the image lands on the daemon that will run it.\n */\n docker?: Docker;\n /**\n * Secret values for this build. Overrides the template-level `secrets`\n * source for names it provides. Names still missing after both sources are\n * read from `process.env` as a last resort.\n */\n secrets?: DockerTemplateSecrets;\n}\n\nexport interface DockerTemplateBuildResult {\n status: 'ready' | 'failed';\n /** The local image tag (`mastra-template:<hash>`) the template resolves to. */\n templateId: string;\n /** Failure detail when `status` is `'failed'`. */\n error?: string;\n}\n\n/**\n * Immutable, chainable builder + build/lifecycle for a local Docker template.\n * Operation methods return a new instance (like the platform `Template()`\n * builder); `build`/`createSandbox`/`dispose` operate against the daemon.\n */\nexport class DockerTemplate {\n readonly #baseImage: string;\n readonly #operations: readonly DockerTemplateOperation[];\n readonly #dockerOptions: Docker.DockerOptions | undefined;\n readonly #secrets: DockerTemplateSecrets | undefined;\n #docker: Docker | undefined;\n #built = false;\n #inFlight: Promise<DockerTemplateBuildResult> | undefined;\n\n constructor(options: DockerTemplateOptions = {}, state?: DockerTemplateState) {\n this.#baseImage = state ? state.baseImage : validateString(options.baseImage ?? 'node:22-slim', 'baseImage');\n this.#operations = state?.operations ?? [];\n this.#dockerOptions = options.dockerOptions;\n this.#secrets = options.secrets;\n }\n\n #clone(next: Partial<DockerTemplateState>): DockerTemplate {\n return new DockerTemplate(\n { dockerOptions: this.#dockerOptions, secrets: this.#secrets },\n {\n baseImage: next.baseImage ?? this.#baseImage,\n operations: next.operations ?? this.#operations,\n },\n );\n }\n\n #append(operation: DockerTemplateOperation): DockerTemplate {\n if (this.#operations.length >= MAX_OPERATIONS) {\n throw new RangeError(`Docker template cannot contain more than ${MAX_OPERATIONS} operations`);\n }\n return this.#clone({ operations: [...this.#operations, operation] });\n }\n\n /** Set the base image. */\n from(image: string): DockerTemplate {\n return this.#clone({ baseImage: validateString(image, 'image') });\n }\n\n /** Set the working directory for subsequent steps and the runtime container. */\n setWorkdir(path: string): DockerTemplate {\n return this.#append({ method: 'setWorkdir', args: [validateString(path, 'path')] });\n }\n\n /**\n * Set environment variables. They are baked into the image via `ENV` and\n * participate in the template identity, so never put secrets here — use\n * {@link runWithSecrets} for anything that must not persist in the image.\n */\n setEnvs(envs: Record<string, string>): DockerTemplate {\n return this.#append({ method: 'setEnvs', args: [validateStringRecord(envs, 'envs')] });\n }\n\n /** Run a command (or `&&`-joined list of commands) as a build step. */\n runCmd(command: string | string[]): DockerTemplate {\n return this.#append({ method: 'runCmd', args: [validateStringOrStrings(command, 'command')] });\n }\n\n /**\n * Run a command that needs build-time secrets, without persisting them.\n *\n * The command runs in a throwaway build stage forked from the template as it\n * stands at that point, so earlier WORKDIR/ENV/installs apply and later\n * steps see the copied `output`. The named secrets are resolved when\n * `build()` runs — from `build({ secrets })`, then the template's `secrets`\n * option, then `process.env` — and exposed to the command as environment\n * variables. Values reach the daemon through a BuildKit secret mount\n * (`RUN --mount=type=secret`), which is tmpfs-backed and scoped to that one\n * RUN — never a build arg, layer, history entry, or cache metadata. Only\n * `output` is copied into the template image. Builds that use secrets\n * require a BuildKit-capable daemon (Docker 20.10+).\n */\n runWithSecrets(command: string | string[], options: RunWithSecretsOptions): DockerTemplate {\n if (!Array.isArray(options.secrets)) throw new TypeError('secrets must be an array of strings');\n if (options.secrets.length > MAX_COLLECTION_ITEMS) {\n throw new RangeError(`secrets cannot contain more than ${MAX_COLLECTION_ITEMS} items`);\n }\n const secrets = options.secrets.map(name => {\n if (typeof name !== 'string' || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {\n throw new TypeError(`secrets must be environment variable names, got ${JSON.stringify(name)}`);\n }\n return name;\n });\n const output = validateString(options.output, 'output');\n if (!output.startsWith('/')) throw new TypeError('output must be an absolute path');\n return this.#append({\n method: 'runWithSecrets',\n args: [validateStringOrStrings(command, 'command'), { secrets, output }],\n });\n }\n\n /** Install apt packages. */\n aptInstall(packages: string | string[], options?: AptInstallOptions): DockerTemplate {\n return this.#append({ method: 'aptInstall', args: [validateStringOrStrings(packages, 'packages'), options] });\n }\n\n /** Install pip packages (or `pip install .` for the current workdir when omitted). */\n pipInstall(packages?: string | string[], options?: PipInstallOptions): DockerTemplate {\n const validated = packages === undefined ? undefined : validateStringOrStrings(packages, 'packages');\n return this.#append({ method: 'pipInstall', args: [validated, options] });\n }\n\n /** Install npm packages (or run `npm install` for the current workdir when omitted). */\n npmInstall(packages?: string | string[], options?: NpmInstallOptions): DockerTemplate {\n const validated = packages === undefined ? undefined : validateStringOrStrings(packages, 'packages');\n return this.#append({ method: 'npmInstall', args: [validated, options] });\n }\n\n /** The resolved definition (base image + ordered operations). */\n get definition(): DockerTemplateDefinition {\n return { baseImage: this.#baseImage, operations: this.#operations };\n }\n\n /** The synthesized Dockerfile for this template. */\n get dockerfile(): string {\n return synthesizeDockerfile(this.definition);\n }\n\n /** The content-addressed local image tag this template resolves to. */\n get templateId(): string {\n return templateImageTag(this.definition);\n }\n\n /**\n * The working directory the built image ends up with, i.e. the last\n * `setWorkdir` in the chain (resolved against earlier ones when relative).\n * `undefined` when the template never sets one, in which case the base\n * image's `WORKDIR` (or the sandbox default) applies.\n */\n get workdir(): string | undefined {\n let current: string | undefined;\n for (const op of this.#operations) {\n if (op.method !== 'setWorkdir') continue;\n const next = op.args[0];\n current = next.startsWith('/') || current === undefined ? next : posixPath.join(current, next);\n }\n return current;\n }\n\n #getDocker(): Docker {\n if (!this.#docker) {\n this.#docker = new Docker(this.#dockerOptions);\n }\n return this.#docker;\n }\n\n /**\n * Build (or reuse) the template's image. Idempotent: if an image with the\n * computed tag already exists locally and `force` is not set, returns\n * `ready` without rebuilding. Otherwise synthesizes a Dockerfile, runs\n * `docker build`, and surfaces any build-step failure as `status: 'failed'`.\n *\n * @throws if a secret named by `runWithSecrets` cannot be resolved from\n * `options.secrets`, the template's `secrets` option, or `process.env`.\n */\n async build(options: DockerTemplateBuildOptions = {}): Promise<DockerTemplateBuildResult> {\n // Many sandboxes starting concurrently from one template must share a\n // single `docker build` rather than racing to build the same tag. Only a\n // plain request may join an in-flight build; a forced build, different\n // secrets, or a different daemon is queued behind it instead.\n const isPlain = !options.force && options.secrets === undefined && options.docker === undefined;\n if (isPlain && this.#inFlight) return this.#inFlight;\n const previous = this.#inFlight?.catch(() => undefined) ?? Promise.resolve();\n const run = previous.then(() => this.#build(options));\n this.#inFlight = run;\n run\n .finally(() => {\n if (this.#inFlight === run) this.#inFlight = undefined;\n })\n .catch(() => undefined);\n return run;\n }\n\n async #build(options: DockerTemplateBuildOptions): Promise<DockerTemplateBuildResult> {\n const docker = options.docker ?? this.#getDocker();\n const tag = this.templateId;\n\n if (!options.force) {\n try {\n await docker.getImage(tag).inspect();\n this.#built = true;\n return { status: 'ready', templateId: tag };\n } catch (error) {\n if (!isImageNotFoundError(error)) throw error;\n }\n }\n\n // Only a real build needs the secret values; reusing a cached image must not\n // require the original credentials to still be present.\n const secrets = await this.#resolveSecrets(options.secrets);\n\n const context = tarPack();\n context.entry({ name: 'Dockerfile' }, this.dockerfile);\n context.finalize();\n\n try {\n const nocache = options.force === true;\n if (secrets) {\n const { stream, session } = await this.#buildWithSecrets(docker, context, tag, secrets, nocache);\n try {\n await this.#followBuild(docker, stream);\n } finally {\n // The daemon calls GetSecret only while the build runs; drop the\n // session however the output stream settled (end, error, or close).\n session.close();\n }\n } else {\n await this.#followBuild(docker, await docker.buildImage(context, { t: tag, nocache }));\n }\n } catch (error) {\n this.#built = false;\n return { status: 'failed', templateId: tag, error: error instanceof Error ? error.message : String(error) };\n }\n\n this.#built = true;\n return { status: 'ready', templateId: tag };\n }\n\n async #resolveSecrets(override: DockerTemplateSecrets | undefined): Promise<Record<string, string> | undefined> {\n const names = secretNames(this.definition);\n if (names.length === 0) return undefined;\n const fromBuild = await readSecrets(override);\n const fromTemplate = await readSecrets(this.#secrets);\n const resolved: Record<string, string> = {};\n for (const name of names) {\n const value = fromBuild[name] ?? fromTemplate[name] ?? process.env[name];\n if (value === undefined) {\n throw new Error(\n `Docker template secret ${name} was not provided (secrets option) and is not set in the environment`,\n );\n }\n resolved[name] = value;\n }\n return resolved;\n }\n\n /**\n * BuildKit build with a session serving the secret mounts. Dials `/build`\n * directly because `docker.buildImage` replaces any session id with its own\n * auth-only session when `version` is `'2'`.\n */\n async #buildWithSecrets(\n docker: Docker,\n context: NodeJS.ReadableStream,\n tag: string,\n secrets: Record<string, string>,\n nocache: boolean,\n ): Promise<{ stream: NodeJS.ReadableStream; session: BuildSession }> {\n const session = await openBuildSession(docker, secrets);\n let stream: NodeJS.ReadableStream;\n try {\n stream = await new Promise<NodeJS.ReadableStream>((resolve, reject) => {\n docker.modem.dial(\n {\n path: '/build?',\n method: 'POST',\n file: context,\n options: { t: tag, version: '2', session: session.id, nocache },\n isStream: true,\n statusCodes: { 200: true, 500: 'server error' },\n },\n (err: Error | null, data: unknown) => (err ? reject(err) : resolve(data as NodeJS.ReadableStream)),\n );\n });\n } catch (error) {\n session.close();\n throw error;\n }\n return { stream, session };\n }\n\n #followBuild(docker: Docker, stream: NodeJS.ReadableStream): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n docker.modem.followProgress(stream, (err: Error | null, output: Array<Record<string, unknown>>) => {\n if (err) {\n reject(err);\n return;\n }\n const failure = output?.find(entry => entry && (entry.error !== undefined || entry.errorDetail !== undefined));\n if (failure) {\n const detail = failure.errorDetail as { message?: string } | undefined;\n reject(new Error(String(detail?.message ?? failure.error ?? 'docker build failed')));\n return;\n }\n resolve();\n });\n });\n }\n\n /**\n * Create a `DockerSandbox` bound to the built image. Lazily builds the\n * template if it has not been built yet. Each call returns a fresh sandbox\n * with an independent writable layer. Invocation-specific `env`/config passed\n * via `options` reaches only the container and is never baked into the image.\n *\n * The sandbox's working directory follows the template's last `setWorkdir`\n * unless `options.workingDirectory` overrides it, so relative paths resolve\n * against the same directory the image was prepared in.\n *\n * @throws if the (lazy) build fails.\n */\n async createSandbox(options: Omit<DockerSandboxOptions, 'image' | 'template'> = {}): Promise<DockerSandbox> {\n if (!this.#built) {\n const result = await this.build();\n if (result.status !== 'ready') {\n throw new Error(`Docker template build failed: ${result.error ?? 'unknown error'}`);\n }\n }\n // Same wiring as `new DockerSandbox({ template })`; the build above just\n // surfaces failures here instead of at `start()`.\n const workingDirectory = options.workingDirectory ?? options.workingDir ?? this.workdir;\n return new DockerSandbox({\n ...options,\n ...(workingDirectory !== undefined && { workingDirectory }),\n template: this,\n dockerOptions: options.dockerOptions ?? this.#dockerOptions,\n });\n }\n\n /**\n * Remove the built image (`docker rmi`). Tolerant of an already-removed\n * image. Independent of any sandbox created from this template, but the\n * daemon refuses to remove an image that a container (running or stopped)\n * still references, so destroy those sandboxes first.\n */\n async dispose(): Promise<void> {\n const docker = this.#getDocker();\n try {\n await docker.getImage(this.templateId).remove();\n } catch (error) {\n if (!isImageNotFoundError(error)) throw error;\n }\n this.#built = false;\n }\n}\n\ninterface DockerTemplateState {\n baseImage: string;\n operations: readonly DockerTemplateOperation[];\n}\n\n// =============================================================================\n// Validation (mirrors platform template validation)\n// =============================================================================\n\nfunction validateString(value: unknown, name: string): string {\n if (typeof value !== 'string') throw new TypeError(`${name} must be a string`);\n if (value.length === 0) throw new TypeError(`${name} must not be empty`);\n if (value.length > MAX_STRING_LENGTH) {\n throw new RangeError(`${name} cannot exceed ${MAX_STRING_LENGTH} characters`);\n }\n return value;\n}\n\nfunction validateStringOrStrings(value: unknown, name: string): string | string[] {\n if (typeof value === 'string') return validateString(value, name);\n if (!Array.isArray(value)) throw new TypeError(`${name} must be a string or an array of strings`);\n if (value.length === 0) throw new TypeError(`${name} must not be empty`);\n if (value.length > MAX_COLLECTION_ITEMS) {\n throw new RangeError(`${name} cannot contain more than ${MAX_COLLECTION_ITEMS} items`);\n }\n return value.map((item, index) => validateString(item, `${name}[${index}]`));\n}\n\nfunction validateStringRecord(value: unknown, name: string): Record<string, string> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new TypeError(`${name} must be a plain object`);\n }\n const entries = Object.entries(value);\n if (entries.length > MAX_COLLECTION_ITEMS) {\n throw new RangeError(`${name} cannot contain more than ${MAX_COLLECTION_ITEMS} items`);\n }\n return Object.fromEntries(\n entries.map(([key, item]) => {\n if (typeof item !== 'string') throw new TypeError(`${name}.${key} must be a string`);\n return [validateString(key, `${name} key`), item];\n }),\n );\n}\n\nasync function readSecrets(source: DockerTemplateSecrets | undefined): Promise<Record<string, string>> {\n if (!source) return {};\n return typeof source === 'function' ? await source() : source;\n}\n\nfunction isImageNotFoundError(error: unknown): boolean {\n if (error instanceof Error) {\n const msg = error.message.toLowerCase();\n return msg.includes('no such image') || msg.includes('404');\n }\n return false;\n}\n","import { createHash } from \"crypto\";\n//#region src/setup-marker.ts\n/**\n* Setup completion marker shared by repo templates and their consumers.\n*\n* A repo template writes this file beside the checkout as its last build\n* step, so it exists only in images where every setup command succeeded. Its\n* content is a digest of the setup commands the image ran, letting a sandbox\n* booted from the image tell whether the setup it is about to run already\n* happened. Relative to the template's build cwd, which is also the runtime\n* working directory the repo was cloned into.\n*/\nconst SETUP_MARKER_PATH = \".mastra-sandbox/setup\";\n/** Blank entries never become build steps, so they never count toward the digest either. */\nfunction normalizeSetupCommands(setupCommand) {\n\treturn (setupCommand === void 0 ? [] : Array.isArray(setupCommand) ? setupCommand : [setupCommand]).filter((command) => command.trim() !== \"\");\n}\n/** The marker content for a setup command list: `sha256:<hex>` over the commands joined by newlines. */\nfunction setupMarkerContent(setupCommand) {\n\treturn `sha256:${createHash(\"sha256\").update(normalizeSetupCommands(setupCommand).join(\"\\n\")).digest(\"hex\")}`;\n}\n/** Shell step that writes the marker relative to the cwd. `content` is a digest, so it is shell-safe. */\nfunction setupMarkerCommand(content) {\n\treturn `mkdir -p \"$(dirname \"${SETUP_MARKER_PATH}\")\" && printf '%s' '${content}' > \"${SETUP_MARKER_PATH}\"`;\n}\n//#endregion\n//#region src/repo-clone.ts\nfunction repoCloneCommand({ cloneUrl, destination, branch, tokenEnv }) {\n\treturn `git ${tokenEnv ? `${gitAuthFlag(tokenEnv)} ` : \"\"}clone --depth=1 --single-branch ${branch ? `--branch ${shellQuote(branch)} ` : \"\"}${shellQuote(cloneUrl)} ${shellQuote(destination)}`;\n}\n/** Per-invocation auth header; `-c` config never reaches `.git/config`. */\nfunction gitAuthFlag(tokenEnv) {\n\treturn `-c http.extraheader=\"AUTHORIZATION: basic $(printf 'x-access-token:%s' \"$${tokenEnv}\" | base64 -w0)\"`;\n}\nfunction shellQuote(value) {\n\treturn `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n//#endregion\nexport { SETUP_MARKER_PATH, normalizeSetupCommands, repoCloneCommand, setupMarkerCommand, setupMarkerContent };\n\n//# sourceMappingURL=index.js.map","/**\n * createDockerRepoTemplate — a repo checkout plus setup commands as a\n * reusable, content-addressed local image, with the same contract as the\n * E2B and platform repo templates (`getRepositoryAccess`, `setupCommand`,\n * `buildEnv`, `workingDirectory`).\n *\n * Returns a template RESOLVER for `DockerSandbox`'s `template` option rather\n * than a fixed template: each resolution calls `getRepositoryAccess`, looks up\n * the current head of `ref` (`git ls-remote`, no clone) and pins that sha into\n * the template identity. A moved branch therefore yields a fresh image on the\n * next new sandbox, and an unmoved one reuses the cached image. When the head\n * cannot be resolved the resolver rejects: an unpinned clone cached under a\n * stable tag would otherwise serve stale repository state forever.\n *\n * The clone runs in a throwaway build stage; the credential is passed by value\n * to that stage only and never enters the template identity or the image.\n *\n * @example\n * ```typescript\n * const sandbox = new DockerSandbox({\n * template: createDockerRepoTemplate({\n * getRepositoryAccess: async () => ({ cloneUrl: 'https://github.com/acme/app.git' }),\n * setupCommand: ['npm ci', 'npm run build'],\n * }),\n * });\n * ```\n */\n\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { normalizeSetupCommands, setupMarkerCommand, setupMarkerContent } from '@internal/workspace';\nimport type { DockerOptions } from 'dockerode';\nimport { DockerTemplate } from './template';\n\nconst execFileAsync = promisify(execFile);\n\n/** Env var the build's clone reads the credential from (see `cloneFull`). */\nconst BUILD_TOKEN_ENV = 'GH_TOKEN';\nconst DEFAULT_BASE_IMAGE = 'node:22-slim';\nconst DEFAULT_WORKING_DIRECTORY = '/workspace';\n// Only a full sha is unambiguous; a short hex string may be a branch or tag.\nconst FULL_SHA_PATTERN = /^[0-9a-f]{40}$/i;\nconst SHA_PATTERN = /^[0-9a-f]{40}$/i;\n\nconst CLONE_URL_ALLOWED_CHARS = /^[a-z0-9:/._-]+$/i;\nconst CLONE_URL_HOST_PATTERN = /^[a-z0-9.-]+$/i;\nconst CLONE_URL_SEGMENT_PATTERN = /^[\\w.-]+$/;\n/** Refs interpolate into shell too; git ref names are already restricted, so allowlist tightly. */\nconst REF_PATTERN = /^[\\w./-]+$/;\n\n/**\n * Repository clone target plus an optional credential. Structurally identical\n * to the E2B/platform type of the same name so a host can pass its context\n * accessor straight through.\n */\nexport interface RepositoryAccess {\n /** https clone URL, e.g. `https://github.com/acme/widgets.git`. */\n cloneUrl: string;\n /** Credential for private repositories; presented to git as `x-access-token:<token>` basic auth. */\n authorization?: { scheme: 'bearer'; token: string };\n}\n\nexport interface DockerRepoTemplateOptions {\n /**\n * Resolves the clone URL and, for private repositories, a short-lived\n * credential. Called once per template resolution (each container-creating\n * `start()`): the credential authenticates the head lookup and the build's\n * clone. It is passed to the build by value, never through `process.env`,\n * and is excluded from the template identity so rotation does not rebuild.\n *\n * Pass `undefined` for the function itself to mean \"no repository\":\n * {@link createDockerRepoTemplate} then returns undefined so\n * `template: createDockerRepoTemplate(ctx)` needs no conditional. If the\n * function resolves to `undefined` at start time, the resolver rejects.\n */\n getRepositoryAccess: (() => Promise<RepositoryAccess | undefined>) | undefined;\n /**\n * Branch, tag, or commit to prepare. The current head of a branch/tag is\n * resolved at each template resolution and pinned into the identity.\n * @default the remote's default branch\n */\n ref?: string;\n /** Setup command(s) run inside the checkout as separate cached build steps. */\n setupCommand?: string | string[];\n /**\n * Extra environment for every build step, including `setupCommand`. Baked\n * into the image via `ENV` and hashed into the identity (keys and values),\n * so it must be non-secret; put rotating credentials in\n * {@link getRepositoryAccess} instead.\n */\n buildEnv?: Record<string, string> | (() => Promise<Record<string, string>>);\n /**\n * Absolute parent for the checkout; the repo lands at\n * `<workingDirectory>/<repo>`, which becomes the build and runtime cwd.\n * @default '/workspace'\n */\n workingDirectory?: string;\n /**\n * Base image. A custom base must provide `git` and `ca-certificates`; the\n * default has them apt-installed as the first (cached) layer.\n * @default 'node:22-slim'\n */\n baseImage?: string;\n /** Pass-through dockerode connection options. */\n dockerOptions?: DockerOptions;\n}\n\n/** A resolver producing a fresh, head-pinned template on each call. */\nexport type DockerRepoTemplateResolver = () => Promise<DockerTemplate>;\n\nexport function createDockerRepoTemplate(options: DockerRepoTemplateOptions): DockerRepoTemplateResolver | undefined {\n if (!options.getRepositoryAccess) return undefined;\n if (options.ref !== undefined && !REF_PATTERN.test(options.ref)) {\n throw new Error(`Invalid ref '${options.ref}': expected a git ref name`);\n }\n const workingDirectory = trimTrailingSlashes(options.workingDirectory ?? DEFAULT_WORKING_DIRECTORY);\n if (!workingDirectory.startsWith('/')) {\n throw new Error(`workingDirectory must be an absolute path, got '${options.workingDirectory}'`);\n }\n return () => resolveRepoTemplate(options, workingDirectory);\n}\n\nasync function resolveRepoTemplate(\n options: DockerRepoTemplateOptions,\n workingDirectory: string,\n): Promise<DockerTemplate> {\n const access = await options.getRepositoryAccess!();\n const cloneUrl = access?.cloneUrl;\n if (!cloneUrl) {\n throw new Error('Repo template has no clone URL: repository access returned none.');\n }\n assertCloneUrl(cloneUrl);\n const token = access?.authorization?.token;\n const buildEnv = typeof options.buildEnv === 'function' ? await options.buildEnv() : options.buildEnv;\n const sha = await resolveHead(cloneUrl, options.ref, token);\n if (!sha) {\n throw new Error(\n `Could not resolve ${options.ref ?? 'HEAD'} of ${cloneUrl} with git ls-remote; check the ref, the credential and network access`,\n );\n }\n\n return buildRepoTemplate({\n cloneUrl,\n sha,\n token,\n buildEnv,\n setupCommand: options.setupCommand,\n workingDirectory,\n baseImage: options.baseImage,\n dockerOptions: options.dockerOptions,\n });\n}\n\ninterface RepoTemplateInputs {\n cloneUrl: string;\n sha: string;\n token?: string;\n buildEnv?: Record<string, string>;\n setupCommand?: string | string[];\n workingDirectory: string;\n baseImage?: string;\n dockerOptions?: DockerOptions;\n}\n\n/**\n * Pure assembly of the template from already-resolved inputs. Exported for\n * tests so the Dockerfile can be asserted without a network head lookup.\n * @internal\n */\nexport function buildRepoTemplate(inputs: RepoTemplateInputs): DockerTemplate {\n const { cloneUrl, sha, token, buildEnv } = inputs;\n const destination = `${trimTrailingSlashes(inputs.workingDirectory)}/${repoDirName(cloneUrl)}`;\n\n let template = new DockerTemplate({\n baseImage: inputs.baseImage ?? DEFAULT_BASE_IMAGE,\n dockerOptions: inputs.dockerOptions,\n ...(token ? { secrets: { [BUILD_TOKEN_ENV]: token } } : {}),\n });\n\n if (inputs.baseImage === undefined) {\n // The slim default ships without git; a custom base is expected to bring its own.\n template = template.aptInstall(['git', 'ca-certificates']);\n }\n\n if (buildEnv && Object.keys(buildEnv).length > 0) {\n template = template.setEnvs(buildEnv);\n }\n\n const tokenEnv = token ? BUILD_TOKEN_ENV : undefined;\n const clone = [\n // Full clone so an arbitrary commit is reachable, then pin to it. The\n // sha is in the command, so it is part of the template identity.\n cloneFull({ cloneUrl, destination, tokenEnv }),\n `git -C ${shellQuote(destination)} checkout --detach ${shellQuote(sha)}`,\n ];\n\n template = template\n .runWithSecrets(clone, { secrets: tokenEnv ? [tokenEnv] : [], output: destination })\n .setWorkdir(destination);\n\n const setupCommands = normalizeSetupCommands(inputs.setupCommand);\n for (const command of setupCommands) {\n template = template.runCmd(command);\n }\n if (setupCommands.length > 0) {\n // Written last, so the marker exists only when every setup step succeeded.\n template = template.runCmd(setupMarkerCommand(setupMarkerContent(setupCommands)));\n }\n return template;\n}\n\n/**\n * Resolve `ref` (or the default branch) to a commit sha with `git ls-remote`\n * on the host, without cloning. A full sha is returned as is. Any failure\n * yields undefined; the caller decides how to surface it.\n * @internal exported for tests.\n */\nexport async function resolveHead(\n cloneUrl: string,\n ref: string | undefined,\n token: string | undefined,\n): Promise<string | undefined> {\n if (ref && FULL_SHA_PATTERN.test(ref)) return ref.toLowerCase();\n try {\n // The credential goes through GIT_CONFIG_* (git >= 2.31) rather than `-c`\n // so it never appears in the process argv, which other local users can read.\n const authEnv = token\n ? {\n GIT_CONFIG_COUNT: '1',\n GIT_CONFIG_KEY_0: 'http.extraheader',\n GIT_CONFIG_VALUE_0: `AUTHORIZATION: basic ${Buffer.from(`x-access-token:${token}`).toString('base64')}`,\n }\n : {};\n // `--` keeps even a hostile URL from being read as an option.\n const { stdout } = await execFileAsync('git', ['ls-remote', '--', cloneUrl, ref ?? 'HEAD'], {\n timeout: 10_000,\n env: { ...process.env, ...authEnv, GIT_TERMINAL_PROMPT: '0' },\n });\n // Prefer the peeled tag object (`refs/tags/x^{}`) when present.\n const lines = stdout\n .split('\\n')\n .filter(Boolean)\n .map(line => line.split('\\t'));\n const peeled = lines.find(([, name]) => name?.endsWith('^{}'));\n const sha = (peeled ?? lines[0])?.[0]?.trim();\n return sha && SHA_PATTERN.test(sha) ? sha.toLowerCase() : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction cloneFull({ cloneUrl, destination, tokenEnv }: { cloneUrl: string; destination: string; tokenEnv?: string }) {\n // Mirrors `repoCloneCommand` from @internal/workspace, minus the shallow flags.\n const auth = tokenEnv\n ? `-c http.extraheader=\"AUTHORIZATION: basic $(printf 'x-access-token:%s' \"$${tokenEnv}\" | base64 -w0)\" `\n : '';\n return `git ${auth}clone ${shellQuote(cloneUrl)} ${shellQuote(destination)}`;\n}\n\nfunction assertCloneUrl(cloneUrl: string): void {\n if (cloneUrl.length > 2048 || !CLONE_URL_ALLOWED_CHARS.test(cloneUrl)) {\n throw new Error(`Invalid cloneUrl '${cloneUrl}': expected an https URL with a plain host and path`);\n }\n let url: URL;\n try {\n url = new URL(cloneUrl);\n } catch {\n throw new Error(`Invalid cloneUrl '${cloneUrl}': not a URL`);\n }\n const segments = url.pathname.split('/').slice(1);\n const ok =\n url.protocol === 'https:' &&\n !url.username &&\n !url.password &&\n !url.search &&\n !url.hash &&\n CLONE_URL_HOST_PATTERN.test(url.hostname) &&\n segments.length > 0 &&\n segments.every(segment => CLONE_URL_SEGMENT_PATTERN.test(segment));\n if (!ok) {\n throw new Error(`Invalid cloneUrl '${cloneUrl}': expected an https URL such as https://host/owner/repo.git`);\n }\n}\n\nfunction repoDirName(cloneUrl: string): string {\n const last = trimTrailingSlashes(cloneUrl).split('/').at(-1) ?? '';\n return (\n last\n .replace(/\\.git$/i, '')\n .replace(/[^\\w.-]/g, '-')\n .replace(/^\\.+/, '') || 'repo'\n );\n}\n\nfunction trimTrailingSlashes(path: string): string {\n let end = path.length;\n while (end > 1 && path[end - 1] === '/') end--;\n return path.slice(0, end);\n}\n\nfunction shellQuote(value: string): string {\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["SandboxAbortError","ProcessHandle","SandboxProcessManager","timeoutMs","MastraSandbox","Docker","SandboxNotReadyError","SandboxAbortError","posixPath","SandboxError","isImageNotFoundError","path","Server","ServerCredentials","#baseImage","#operations","#dockerOptions","#secrets","#clone","#append","posixPath","#docker","Docker","#plainBuild","#waitForBuild","#queueTail","#build","#getDocker","#built","#resolveSecrets","#buildWithSecrets","#followBuild","execFile"],"sources":["../src/abort.ts","../src/sandbox/process-manager.ts","../src/sandbox/index.ts","../src/provider.ts","../src/template/build-session.ts","../src/template/dockerfile.ts","../src/template/template.ts","../../../packages/_internals/workspace/dist/index.js","../src/template/repo-template.ts"],"sourcesContent":["import { SandboxAbortError } from '@mastra/core/workspace';\n\nexport function createAbortError(signal: AbortSignal, operation: string): SandboxAbortError {\n return new SandboxAbortError(operation, signal.reason);\n}\n\nexport function throwIfAborted(signal: AbortSignal | undefined, operation: string): void {\n if (signal?.aborted) throw createAbortError(signal, operation);\n}\n\nexport function isAbortError(error: unknown): boolean {\n return (\n error instanceof SandboxAbortError ||\n (error instanceof Error && (error.name === 'AbortError' || ('code' in error && error.code === 'ABORT_ERR')))\n );\n}\n\nexport function normalizeAbortError(error: unknown, operation: string): unknown {\n return error instanceof SandboxAbortError\n ? error\n : isAbortError(error)\n ? new SandboxAbortError(operation, error)\n : error;\n}\n\nexport function waitForAbortable<T>(\n promise: Promise<T>,\n signal: AbortSignal | undefined,\n operation: string,\n onAbort?: () => void,\n): Promise<T> {\n throwIfAborted(signal, operation);\n if (!signal) return promise;\n\n return new Promise<T>((resolve, reject) => {\n const abort = () => {\n onAbort?.();\n reject(new SandboxAbortError(operation, signal.reason));\n };\n signal.addEventListener('abort', abort, { once: true });\n promise.then(\n value => {\n signal.removeEventListener('abort', abort);\n resolve(value);\n },\n error => {\n signal.removeEventListener('abort', abort);\n reject(normalizeAbortError(error, operation));\n },\n );\n });\n}\n","/**\n * Docker Process Manager\n *\n * Implements SandboxProcessManager for Docker containers.\n * Uses `container.exec()` to run commands inside a long-lived container.\n * Each spawned process gets a dedicated exec instance with separate\n * stdout/stderr streams.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type { Duplex } from 'node:stream';\n\nimport { ProcessHandle, SandboxProcessManager } from '@mastra/core/workspace';\nimport type { CommandResult, ProcessInfo, SpawnProcessOptions } from '@mastra/core/workspace';\nimport type { Container, Exec, ExecInspectInfo } from 'dockerode';\n\n/**\n * Directory (inside the container) where each spawned process records the PGID\n * of its process group. Created with mode 700 so only the (root) exec user can\n * write the PGID files.\n */\nconst PROC_DIR = '/tmp/.mastra-proc';\n\n/**\n * Wrapper (run as the exec command) that places the user command in its own\n * process group and records the group's PGID so kill() can signal the whole\n * group later.\n *\n * Docker's exec-inspect `Pid` is a host/daemon-namespace PID and cannot be used\n * with an in-container `kill`, so we need a container-namespace identity. We use\n * a *kernel-enforced* process group as that identity:\n *\n * 1. `setsid -w` re-execs the command as a new session/process-group leader,\n * so its PID == PGID. Every descendant inherits that PGID (unless it calls\n * `setsid` itself) and stays reachable even if it re-parents to PID 1.\n * `-w` keeps the wrapper (and thus the exec) alive for the whole lifetime\n * and propagates the child's exit status — without it `setsid` forks and\n * returns immediately, so the exec would appear to finish while the real\n * work keeps running.\n * 2. The leader writes its own PID (`$$`) — the PGID — to a private file that\n * only this process wrote, so the identity is kernel-owned and cannot be\n * forged by another container process.\n *\n * If `setsid -w` is unavailable in the image (e.g. BusyBox), we degrade\n * gracefully: the command runs directly and we record its PID so kill() can\n * still signal it (descendant coverage is then best-effort). The probe\n * `setsid -w true` also covers images without setsid at all.\n *\n * Positional args: $1 = pgid file path, $2 = user command. The script text is a\n * static constant; runtime values travel only as argv, never interpolated into\n * the command string.\n */\nconst SPAWN_WRAPPER = `\numask 077\nd=\"\\${1%/*}\"\nmkdir -p \"$d\" 2>/dev/null\nchmod 700 \"$d\" 2>/dev/null\nif setsid -w true >/dev/null 2>&1; then\n exec setsid -w sh -c 'echo $$ > \"$1\" || exit 126; sh -c \"$2\"; ret=$?; rm -f \"$1\" 2>/dev/null; exit $ret' sh \"$1\" \"$2\"\nfi\necho $$ > \"$1\" || exit 126\nsh -c \"$2\"\nret=$?\nrm -f \"$1\" 2>/dev/null\nexit $ret\n`;\n\n/**\n * Kill script: read the recorded PGID and SIGKILL the whole process group.\n * A negative PID targets the kernel-owned process group, so descendants that\n * re-parented to PID 1 are still caught. We SIGSTOP the\n * group first to freeze fork races, then SIGKILL. The file may not exist yet if\n * kill races the leader's first write, so we briefly wait for it.\n *\n * Positional arg: $1 = pgid file path (static script; no interpolation).\n */\nconst KILL_SCRIPT = `\nf=\"$1\"\ni=0\nwhile [ ! -r \"$f\" ] && [ \"$i\" -lt 40 ]; do sleep 0.05; i=$((i + 1)); done\n# If the PGID was never recorded (file absent/unreadable after the wait, or\n# empty), we have no group to signal or verify — report failure rather than\n# falsely claiming the tree was terminated.\n[ -r \"$f\" ] || exit 1\npgid=$(cat \"$f\" 2>/dev/null)\nrm -f \"$f\" 2>/dev/null\n[ -n \"$pgid\" ] || exit 1\nkill -STOP -\"$pgid\" 2>/dev/null\nkill -KILL -\"$pgid\" 2>/dev/null\n# Fallback for images without setsid: the leader is not a group leader, so also\n# signal it directly.\nkill -KILL \"$pgid\" 2>/dev/null\n# Verify the group is actually gone before reporting success. kill -0 probes\n# for the group's existence without sending a signal, and we poll while it\n# still reports the group alive. When the probe finally fails we must inspect\n# why: ESRCH (\"no such process\") means every member was reaped, so report\n# success; EPERM or any other error means termination is unconfirmed (e.g. a\n# member dropped privileges and became unsignalable), so exit nonzero and let\n# kill() report failure instead of falsely claiming the tree was terminated.\nj=0\nwhile err=$(kill -0 -\"$pgid\" 2>&1); do\n j=$((j + 1))\n [ \"$j\" -ge 40 ] && exit 1\n sleep 0.05\ndone\ncase \"$err\" in\n *[Ss]uch\\\\ process*) exit 0 ;;\n *) exit 1 ;;\nesac\n`;\n\n// =============================================================================\n// Docker Process Handle\n// =============================================================================\n\n/**\n * Wraps a Docker exec instance to conform to Mastra's ProcessHandle.\n * Not exported — internal to this module.\n *\n * Listener dispatch is handled by the base class. The manager's spawn()\n * method wires Docker stream callbacks to handle.emitStdout/emitStderr.\n */\nclass DockerProcessHandle extends ProcessHandle {\n readonly pid: string;\n\n private readonly _exec: Exec;\n private readonly _container: Container;\n private readonly _startTime: number;\n private _exitCode: number | undefined;\n /** @internal Set by kill() and timeout to distinguish forced termination from natural exit */\n _killed = false;\n /** @internal Set by the timeout path to distinguish timeout kills from explicit kills */\n _timedOut = false;\n private _waitPromise: Promise<CommandResult> | null = null;\n private _stdinStream: Duplex | null = null;\n private _execStream: NodeJS.ReadWriteStream | null = null;\n /** @internal Container path of the file holding this process group's PGID. */\n readonly _pgidFile: string;\n\n constructor(\n exec: Exec,\n container: Container,\n startTime: number,\n stdinStream: Duplex | null,\n pgidFile: string,\n options?: SpawnProcessOptions,\n ) {\n super(options);\n this.pid = exec.id;\n this._exec = exec;\n this._container = container;\n this._startTime = startTime;\n this._stdinStream = stdinStream;\n this._pgidFile = pgidFile;\n }\n\n get exitCode(): number | undefined {\n return this._exitCode;\n }\n\n /** @internal Set exit code when stream closes */\n _setExitCode(code: number): void {\n this._exitCode = code;\n }\n\n /** @internal Set the wait promise from spawn */\n _setWaitPromise(p: Promise<CommandResult>): void {\n this._waitPromise = p;\n }\n\n /** @internal Set the exec stream so kill() can destroy it */\n _setExecStream(stream: NodeJS.ReadWriteStream): void {\n this._execStream = stream;\n }\n\n async wait(): Promise<CommandResult> {\n if (this._waitPromise) {\n return this._waitPromise;\n }\n\n // If no wait promise set yet, poll exec inspect\n const info = await this._inspectExec();\n return {\n success: (info.ExitCode ?? 1) === 0,\n exitCode: info.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\n try {\n // Kill the process group inside the *container's* PID namespace. We must\n // not use exec.inspect().Pid here: that is the host/daemon-namespace PID\n // and does not correspond to PIDs an in-container `kill` can address. The\n // recorded PGID targets a kernel-owned group, so descendants that were\n // re-parented to PID 1 are still caught.\n const killExec = await this._container.exec({\n // Static script; the pgid file path is passed as $1 (sh sets $0='sh',\n // $1=path) so no runtime value is ever interpolated into the command.\n Cmd: ['sh', '-c', KILL_SCRIPT, 'sh', this._pgidFile],\n AttachStdout: false,\n AttachStderr: false,\n });\n const killStream = await killExec.start({});\n\n try {\n // Exec.start() resolves when the exec stream is opened, not when the\n // helper script exits. Poll inspect() until it finishes so we only report\n // success once the process tree has actually been killed — otherwise\n // wait() could resolve with exit 137 while targets are still running.\n let killInfo = await killExec.inspect();\n while (killInfo.Running) {\n await new Promise(resolve => setTimeout(resolve, 10));\n killInfo = await killExec.inspect();\n }\n if (killInfo.ExitCode !== 0) {\n throw new Error(`kill helper exited with code ${killInfo.ExitCode}`);\n }\n\n // Mark as killed and destroy stream so wait() resolves.\n // Docker exec streams don't close automatically when the process is killed externally.\n this._killed = true;\n this._destroyStream();\n return true;\n } finally {\n killStream.destroy();\n }\n } catch (error: unknown) {\n // ESRCH / \"no such process\" is expected if the process exited between inspect and kill\n const msg = error instanceof Error ? error.message.toLowerCase() : '';\n if (!msg.includes('no such process') && !msg.includes('esrch')) {\n // Unexpected error — not fatal but worth noting for debugging\n console.warn(`[DockerProcessManager] kill(${this.pid}) failed unexpectedly:`, error);\n }\n return false;\n }\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 if (!this._stdinStream) {\n throw new Error(`Process ${this.pid} was not started with stdin support`);\n }\n return new Promise<void>((resolve, reject) => {\n this._stdinStream!.write(data, error => (error ? reject(error) : resolve()));\n });\n }\n\n async closeStdin(): Promise<void> {\n if (this._exitCode !== undefined) {\n throw new Error(`Process ${this.pid} has already exited with code ${this._exitCode}`);\n }\n if (!this._stdinStream) {\n throw new Error(`Process ${this.pid} was not started with stdin support`);\n }\n const stream = this._stdinStream;\n if (stream.writableEnded) return;\n await new Promise<void>(resolve => stream.end(resolve));\n }\n\n /** @internal Force-close the exec stream to unblock wait(). */\n _destroyStream(): void {\n const stream = this._execStream as unknown as { destroy?: () => void } | null;\n if (stream && typeof stream.destroy === 'function') {\n stream.destroy();\n this._execStream = null;\n }\n }\n\n private async _inspectExec(): Promise<ExecInspectInfo> {\n return this._exec.inspect();\n }\n}\n\n// =============================================================================\n// Docker Process Manager\n// =============================================================================\n\n/**\n * Docker implementation of SandboxProcessManager.\n * Uses `container.exec()` with stream-based I/O.\n */\nexport class DockerProcessManager extends SandboxProcessManager {\n private _container: Container | null = null;\n private readonly _defaultTimeout: number;\n\n constructor(options: { defaultTimeout?: number } = {}) {\n super();\n this._defaultTimeout = options.defaultTimeout ?? 0;\n }\n\n /** @internal Called by DockerSandbox after container is ready */\n setContainer(container: Container): void {\n this._container = container;\n }\n\n /** Get the container, throwing if not set */\n private get container(): Container {\n if (!this._container) {\n throw new Error('Docker container not available. Has the sandbox been started?');\n }\n return this._container;\n }\n\n async spawn(command: string, options: SpawnProcessOptions = {}): Promise<ProcessHandle> {\n const container = this.container;\n\n // Private file (unguessable name) where the command's process group records\n // its PGID, so kill() can signal the whole kernel-owned group later.\n const pgidFile = `${PROC_DIR}/${randomUUID()}`;\n const envArray = Object.entries({ ...options.env })\n .filter((entry): entry is [string, string] => entry[1] !== undefined)\n .map(([k, v]) => `${k}=${v}`);\n\n // `stdinMode: 'ignore'` leaves stdin unattached so the command sees EOF. A\n // command that reads stdin (a bare `rg`/`grep`/`cat` with no path argument)\n // blocks forever when stdin is attached but nothing ever writes to it.\n const attachStdin = options.stdinMode !== 'ignore';\n\n // Create exec instance. The command is wrapped so it runs in its own process\n // group (via setsid) and records its PGID; args travel positionally so the\n // wrapper text stays a static constant.\n const exec = await container.exec({\n Cmd: ['sh', '-c', SPAWN_WRAPPER, 'sh', pgidFile, command],\n AttachStdout: true,\n AttachStderr: true,\n AttachStdin: attachStdin,\n Tty: false,\n Env: envArray.length > 0 ? envArray : undefined,\n WorkingDir: options.cwd,\n });\n\n // Start exec and get the multiplexed stream\n const stream = await exec.start({ hijack: true, stdin: attachStdin });\n\n const startTime = Date.now();\n // A null stdin stream makes sendStdin/closeStdin report the process was not\n // started with stdin support, matching `stdinMode: 'ignore'`.\n const handle = new DockerProcessHandle(exec, container, startTime, attachStdin ? stream : null, pgidFile, options);\n handle._setExecStream(stream);\n\n // Create the wait promise that resolves when the stream ends\n const waitPromise = new Promise<CommandResult>(resolve => {\n // Demux the multiplexed stream into stdout/stderr\n // Docker multiplexes stdout/stderr into a single stream with 8-byte headers\n // when Tty is false. We need to parse these headers.\n const buffer: Buffer[] = [];\n\n stream.on('data', (chunk: Buffer) => {\n buffer.push(chunk);\n // Process all complete frames in the buffer\n let combined = Buffer.concat(buffer);\n buffer.length = 0;\n\n while (combined.length >= 8) {\n const type = combined[0]; // 1 = stdout, 2 = stderr\n const size = combined.readUInt32BE(4);\n\n if (combined.length < 8 + size) {\n // Incomplete frame, save for next chunk\n buffer.push(combined);\n break;\n }\n\n const payload = combined.subarray(8, 8 + size).toString('utf-8');\n if (type === 1) {\n handle.emitStdout(payload);\n } else if (type === 2) {\n handle.emitStderr(payload);\n }\n\n combined = combined.subarray(8 + size);\n }\n\n // Save any remaining partial data\n if (combined.length > 0 && buffer.length === 0) {\n buffer.push(combined);\n }\n });\n\n stream.on('end', async () => {\n // Get exit code from exec inspect\n try {\n const info = await exec.inspect();\n const exitCode = info.ExitCode ?? 1;\n handle._setExitCode(exitCode);\n resolve({\n success: exitCode === 0,\n exitCode,\n stdout: handle.stdout,\n stderr: handle.stderr,\n executionTimeMs: Date.now() - startTime,\n });\n } catch {\n handle._setExitCode(1);\n resolve({\n success: false,\n exitCode: 1,\n stdout: handle.stdout,\n stderr: handle.stderr,\n executionTimeMs: Date.now() - startTime,\n });\n }\n });\n\n // 'close' fires when stream.destroy() is called (e.g., from kill or timeout).\n // Only resolve with SIGKILL exit code when the process was explicitly killed;\n // natural stream close should be handled by the 'end' event above.\n // Note: Docker multiplexed streams always emit 'end' before 'close' for\n // natural exits, so the !_killed guard won't silently drop natural closes.\n stream.on('close', () => {\n if (handle.exitCode !== undefined) return; // Already resolved via 'end'\n if (!handle._killed) return; // Natural close — 'end' handles it\n handle._setExitCode(137); // SIGKILL\n resolve({\n success: false,\n exitCode: 137,\n stdout: handle.stdout,\n stderr: handle.stderr,\n executionTimeMs: Date.now() - startTime,\n killed: true,\n timedOut: handle._timedOut,\n });\n });\n\n stream.on('error', () => {\n if (handle.exitCode !== undefined) return; // Already resolved\n handle._setExitCode(1);\n resolve({\n success: false,\n exitCode: 1,\n stdout: handle.stdout,\n stderr: handle.stderr || 'Stream error',\n executionTimeMs: Date.now() - startTime,\n });\n });\n });\n\n // Wire up timeout: kill the process and destroy the stream after the timeout period.\n // Per-spawn timeout takes precedence; falls back to the sandbox-level default.\n const resolvedTimeout = options.timeout ?? this._defaultTimeout;\n if (resolvedTimeout > 0) {\n const timeoutMs = resolvedTimeout;\n const timer = setTimeout(() => {\n if (handle.exitCode === undefined) {\n handle._killed = true;\n handle._timedOut = true;\n // Await kill() so the process tree is actually terminated before the\n // stream is torn down. Destroying the stream first would resolve\n // wait() with exit 137 while the targets are still running — the exact\n // bug this fix addresses. Only force-destroy the stream if kill()\n // fails to make progress, as a last resort to unblock wait().\n const forceClose = () => {\n if (handle.exitCode === undefined) {\n handle._killed = true;\n handle._destroyStream();\n }\n };\n handle\n .kill()\n .then(killed => {\n if (!killed) forceClose();\n })\n .catch(forceClose);\n }\n }, timeoutMs);\n // Clear timer when process exits naturally\n void waitPromise.then(() => clearTimeout(timer));\n }\n\n handle._setWaitPromise(waitPromise);\n this._tracked.set(handle.pid, handle);\n return handle;\n }\n\n /** Clear all tracked process handles and release the container reference (e.g., after container stop/destroy) */\n reset(): void {\n this._tracked.clear();\n this._container = null;\n }\n\n async list(): Promise<ProcessInfo[]> {\n const results: ProcessInfo[] = [];\n\n for (const [pid, handle] of this._tracked) {\n results.push({\n pid,\n command: handle.command,\n running: handle.exitCode === undefined,\n exitCode: handle.exitCode,\n });\n }\n\n return results;\n }\n}\n","/**\n * Docker Sandbox Provider\n *\n * A Docker-based sandbox implementation that uses long-lived containers\n * with `docker exec` for command execution. Targets local development,\n * CI/CD, air-gapped deployments, and cost-sensitive scenarios where\n * cloud sandboxes are overkill.\n *\n * @see https://docs.docker.com/engine/api/\n */\n\nimport { posix as posixPath } from 'node:path';\nimport { isDeepStrictEqual } from 'node:util';\nimport type { RequestContext } from '@mastra/core/di';\nimport type {\n SandboxInfo,\n ProviderStatus,\n MastraSandboxOptions,\n SandboxCloneOptions,\n SandboxFileInput,\n SandboxStartOptions,\n WriteFilesOptions,\n} from '@mastra/core/workspace';\nimport {\n MastraSandbox,\n SandboxAbortError,\n SandboxError,\n SandboxNotReadyError,\n validateSandboxFileMode,\n} from '@mastra/core/workspace';\nimport Docker from 'dockerode';\nimport type { Container, ContainerInfo } from 'dockerode';\nimport { pack as tarPack } from 'tar-stream';\nimport { normalizeAbortError, throwIfAborted } from '../abort';\nimport type { DockerRepoTemplateResolveOptions } from '../template/repo-template';\nimport type { DockerTemplate } from '../template/template';\nimport { DockerProcessManager } from './process-manager';\n\nconst LOG_PREFIX = '[DockerSandbox]';\n\nexport interface DockerSandboxStartOptions extends SandboxStartOptions {\n /** Cancel repository-template resolution or a lazy template build. */\n abortSignal?: AbortSignal;\n}\n\n/** A prepared template, or a resolver producing one (see `DockerSandboxOptions.template`). */\nexport type DockerTemplateSpec =\n | DockerTemplate\n | ((options?: DockerRepoTemplateResolveOptions) => DockerTemplate | Promise<DockerTemplate>);\n\n/**\n * Inlined from `@mastra/core/workspace` to avoid requiring a newer core peer dep.\n * Canonical type: packages/core/src/workspace/sandbox/mastra-sandbox.ts\n * TODO: Remove once minimum peer dep includes InstructionsOption export.\n */\ntype InstructionsOption = string | ((opts: { defaultInstructions: string; requestContext?: RequestContext }) => string);\n\ntype DockerSandboxUlimit = {\n name: string;\n soft: number;\n hard: number;\n};\n\ntype DockerSandboxTmpfs = Record<string, string>;\n\n/** Options applied to a `volume` mount. */\ntype DockerSandboxVolumeMount = {\n type: 'volume';\n /** Absolute path of the mount inside the container. */\n target: string;\n /** Named volume to mount. */\n source: string;\n /** Mount read-only. */\n readOnly?: boolean;\n /** Options applied to the named volume. */\n volumeOptions?: {\n /** Mount a subdirectory of the named volume (Docker Engine 26.0+). */\n subpath?: string;\n /** Disable copying data from the container path into the volume. */\n noCopy?: boolean;\n /** Labels applied to the volume when it is created. */\n labels?: Record<string, string>;\n };\n};\n\n/** Options applied to a `bind` mount. */\ntype DockerSandboxBindMount = {\n type: 'bind';\n /** Absolute path of the mount inside the container. */\n target: string;\n /** Host path to bind into the container. */\n source: string;\n /** Mount read-only. */\n readOnly?: boolean;\n /** Options applied to the bind mount. */\n bindOptions?: {\n /** Bind propagation mode. */\n propagation?: 'private' | 'rprivate' | 'shared' | 'rshared' | 'slave' | 'rslave';\n };\n};\n\n/** Options applied to a `tmpfs` mount. */\ntype DockerSandboxTmpfsMount = {\n type: 'tmpfs';\n /** Absolute path of the mount inside the container. */\n target: string;\n /** Mount read-only. */\n readOnly?: boolean;\n /** Options applied to the tmpfs mount. */\n tmpfsOptions?: {\n /** Size of the tmpfs mount in bytes. */\n sizeBytes?: number;\n /** File mode of the tmpfs mount, in octal (e.g. 0o1777). */\n mode?: number;\n };\n};\n\n/**\n * A single Docker mount, mapped 1:1 onto an entry of `HostConfig.Mounts`.\n *\n * Unlike `volumes` (which maps to `HostConfig.Binds` / the `-v` syntax), mounts\n * can express options that `Binds` cannot — most notably `volumeOptions.subpath`,\n * which mounts a subdirectory of a named volume. Requires Docker Engine 26.0+\n * (API v1.45+) for `subpath` support.\n *\n * This is a discriminated union on `type`: `volume` and `bind` mounts require a\n * `source` and only accept their own option group, while `tmpfs` mounts take no\n * `source`. These invariants mirror what Docker enforces at container creation.\n */\nexport type DockerSandboxMount = DockerSandboxVolumeMount | DockerSandboxBindMount | DockerSandboxTmpfsMount;\n\n// =============================================================================\n// Docker Sandbox Options\n// =============================================================================\n\nexport interface DockerSandboxOptions extends Omit<MastraSandboxOptions, 'processes'> {\n /** Unique identifier for this sandbox instance. Used for label-based reconnection. */\n id?: string;\n /**\n * Container display name passed to Docker as `--name`.\n * Characters outside `[a-zA-Z0-9_.-]` are replaced with `-` and the result\n * is prefixed if it would not start with an alphanumeric character.\n * @default the sandbox `id`\n */\n name?: string;\n /** Docker image to use.\n * @default 'node:22-slim'\n */\n image?: string;\n /**\n * Prepared baseline to boot from, as an alternative to `image`. The\n * template is built (or its cached image reused) lazily on `start()`, and\n * the container boots from the resulting image. A function form is resolved\n * once per `start()` that creates a container, so head-pinned repo\n * templates can re-resolve on each new sandbox.\n *\n * When `workingDirectory` is not set, the template's last `setWorkdir`\n * becomes the sandbox working directory. Mutually exclusive with `image`.\n */\n template?: DockerTemplateSpec;\n /** Container entrypoint command. Must keep the container alive.\n * @default ['sleep', 'infinity']\n */\n command?: string[];\n /** Environment variables to set in the container */\n env?: Record<string, string>;\n /** Host-to-container bind mounts (e.g., `{ '/host/path': '/container/path' }`) */\n volumes?: Record<string, string>;\n /** Docker network to join */\n network?: string;\n /** Run in privileged mode\n * @default false\n */\n privileged?: boolean;\n /** Memory limit in bytes (HostConfig.Memory). Docker treats 0 as unlimited. */\n memory?: number;\n /** Total memory plus swap in bytes (HostConfig.MemorySwap). */\n memorySwap?: number;\n /** CPU shares relative weight (HostConfig.CpuShares). */\n cpuShares?: number;\n /** CPU quota in microseconds per period (HostConfig.CpuQuota). */\n cpuQuota?: number;\n /** CPU period in microseconds (HostConfig.CpuPeriod). */\n cpuPeriod?: number;\n /** Maximum number of PIDs in the container (HostConfig.PidsLimit). */\n pidsLimit?: number;\n /**\n * Run an init process (tini) as PID 1 to reap zombie children (HostConfig.Init).\n * Without this, processes orphaned by a command (e.g. after a timeout/kill) remain\n * as zombies and keep counting against `pidsLimit`.\n * @default true\n */\n init?: boolean;\n /** Mount the container root filesystem as read-only (HostConfig.ReadonlyRootfs). */\n readonlyRootfs?: boolean;\n /** Linux capabilities to drop (HostConfig.CapDrop), e.g. ['ALL']. */\n capDrop?: string[];\n /** Linux capabilities to add (HostConfig.CapAdd). */\n capAdd?: string[];\n /** Security options (HostConfig.SecurityOpt), e.g. ['no-new-privileges:true']. */\n securityOpt?: string[];\n /** Ulimit entries for Docker HostConfig.Ulimits. */\n ulimits?: DockerSandboxUlimit[];\n /** tmpfs mount paths with options (HostConfig.Tmpfs). */\n tmpfs?: DockerSandboxTmpfs;\n /**\n * Mounts mapped 1:1 onto `HostConfig.Mounts`.\n *\n * Use this instead of `volumes` when you need mount options that Docker's\n * `-v`/`HostConfig.Binds` syntax cannot express — in particular\n * `volumeOptions.subpath` (mount a subdirectory of a named volume). `volumes`\n * and `mounts` may be combined; both are passed through to Docker.\n */\n mounts?: DockerSandboxMount[];\n /** Default command timeout in milliseconds\n * @default 300_000 // 5 minutes\n */\n timeout?: number;\n /** Working directory inside the container\n * @default '/workspace'\n * @deprecated Use `workingDirectory` (the base sandbox option) instead.\n * When both are set, `workingDirectory` wins.\n */\n workingDir?: string;\n /** Container labels for filtering and identification */\n labels?: Record<string, string>;\n /** Pass-through dockerode connection options (socket path, host, TLS certs) */\n dockerOptions?: Docker.DockerOptions;\n /**\n * Custom instructions that override the default instructions\n * returned by `getInstructions()`.\n *\n * - `string` — Fully replaces the default instructions.\n * Pass an empty string to suppress instructions entirely.\n * - `(opts) => string` — Receives the default instructions and\n * optional request context so you can extend or customise per-request.\n */\n instructions?: InstructionsOption;\n}\n\n// =============================================================================\n// Docker Sandbox Implementation\n// =============================================================================\n\n/**\n * Docker sandbox implementation using long-lived containers.\n *\n * Features:\n * - Long-lived container with `docker exec` for commands\n * - Bind mount support via Docker volumes\n * - Reconnection to existing containers by ID/name\n * - Container label tracking for discovery\n *\n * @example Basic usage\n * ```typescript\n * import { Workspace } from '@mastra/core/workspace';\n * import { DockerSandbox } from '@mastra/docker';\n *\n * const sandbox = new DockerSandbox({\n * image: 'node:22-slim',\n * timeout: 60000,\n * });\n *\n * const workspace = new Workspace({ sandbox });\n * const result = await workspace.executeCode('console.log(\"Hello!\")');\n * ```\n *\n * @example With bind mounts\n * ```typescript\n * const sandbox = new DockerSandbox({\n * image: 'node:22-slim',\n * volumes: { '/my/project': '/workspace/project' },\n * });\n * ```\n */\nexport class DockerSandbox extends MastraSandbox {\n readonly id: string;\n readonly name = 'DockerSandbox';\n readonly provider = 'docker';\n status: ProviderStatus = 'pending';\n\n declare readonly processes: DockerProcessManager;\n\n /** Underlying Docker client */\n private readonly _docker: Docker;\n\n /** Container reference (set after start) */\n private _container: Container | null = null;\n\n /** Configuration */\n private readonly _containerName: string;\n /** Image the container boots from; rewritten by a template resolution on `start()`. */\n private _image: string;\n private readonly _templateSpec?: DockerTemplateSpec;\n private readonly _workingDirectoryWasSet: boolean;\n private readonly _command: string[];\n private readonly _env: Record<string, string>;\n private readonly _volumes: Record<string, string>;\n private readonly _network?: string;\n private readonly _privileged: boolean;\n private readonly _privilegedWasSet: boolean;\n private readonly _memory?: number;\n private readonly _memorySwap?: number;\n private readonly _cpuShares?: number;\n private readonly _cpuQuota?: number;\n private readonly _cpuPeriod?: number;\n private readonly _pidsLimit?: number;\n private readonly _init: boolean;\n private readonly _readonlyRootfs?: boolean;\n private readonly _capDrop?: string[];\n private readonly _capAdd?: string[];\n private readonly _securityOpt?: string[];\n private readonly _ulimits?: DockerSandboxUlimit[];\n private readonly _tmpfs?: DockerSandboxTmpfs;\n private readonly _mounts?: DockerSandboxMount[];\n private readonly _labels: Record<string, string>;\n private readonly _instructionsOverride?: InstructionsOption;\n private readonly _constructorOptions: DockerSandboxOptions;\n\n /**\n * The effective container working directory. Narrowed to `string`: the\n * constructor always resolves a value (option, deprecated alias, or\n * `/workspace`), so unlike the base getter this never returns `undefined`.\n */\n override get workingDirectory(): string {\n return this._workingDirectory!;\n }\n\n constructor(options: DockerSandboxOptions = {}) {\n const processManager = new DockerProcessManager({\n defaultTimeout: options.timeout ?? 300_000,\n });\n\n super({\n ...options,\n name: 'DockerSandbox',\n processes: processManager,\n });\n\n this.id = options.id ?? this._generateId();\n this._containerName = sanitizeContainerName(options.name ?? this.id);\n if (options.image !== undefined && options.template !== undefined) {\n throw new TypeError('DockerSandbox: `image` and `template` are mutually exclusive');\n }\n this._templateSpec = options.template;\n this._image = options.image ?? 'node:22-slim';\n this._workingDirectoryWasSet = options.workingDirectory !== undefined || options.workingDir !== undefined;\n this._command = options.command ?? ['sleep', 'infinity'];\n this._env = options.env ?? {};\n this._volumes = options.volumes ?? {};\n this._network = options.network;\n this._privileged = options.privileged ?? false;\n this._privilegedWasSet = options.privileged !== undefined;\n this._memory = options.memory;\n this._memorySwap = options.memorySwap;\n this._cpuShares = options.cpuShares;\n this._cpuQuota = options.cpuQuota;\n this._cpuPeriod = options.cpuPeriod;\n this._pidsLimit = options.pidsLimit;\n this._init = options.init ?? true;\n this._readonlyRootfs = options.readonlyRootfs;\n this._capDrop = options.capDrop;\n this._capAdd = options.capAdd;\n this._securityOpt = options.securityOpt;\n this._ulimits = options.ulimits;\n this._tmpfs = options.tmpfs;\n this._mounts = options.mounts;\n this.setWorkingDirectory(options.workingDirectory ?? options.workingDir ?? '/workspace');\n this._labels = {\n ...options.labels,\n 'mastra.sandbox': 'true',\n 'mastra.sandbox.id': this.id,\n };\n this._instructionsOverride = options.instructions;\n this._docker = new Docker(options.dockerOptions);\n this._constructorOptions = { ...options };\n }\n\n /**\n * Construct a sibling `DockerSandbox` that inherits this sandbox's\n * configuration (image, resource limits, security options, labels,\n * connection options) with per-instance overrides.\n *\n * Performs no I/O — the sandbox clone provisions (or reconnects to an\n * existing container labelled with the same logical `id`) on its own\n * `start()`. Use it when one configured sandbox acts as the template for a\n * fleet of independent sandboxes (e.g. one per project).\n *\n * `options.idleTimeoutMinutes` is ignored (Docker containers have no\n * provider-side idle teardown; `timeout` here is a command timeout), and\n * `options.sandboxId` is ignored because reconnection is by logical `id`.\n */\n clone(options: SandboxCloneOptions = {}): DockerSandbox {\n const { id: _id, name: _name, ...base } = this._constructorOptions;\n return new DockerSandbox({\n ...base,\n ...(options.id !== undefined && { id: options.id }),\n ...(options.env !== undefined && { env: options.env }),\n ...(options.workingDirectory !== undefined && { workingDirectory: options.workingDirectory }),\n });\n }\n\n /**\n * Get the underlying Docker container for direct access.\n * @throws {SandboxNotReadyError} If the sandbox has not been started.\n */\n get container(): Container {\n if (!this._container) {\n throw new SandboxNotReadyError(this.id);\n }\n return this._container;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n async start(options: DockerSandboxStartOptions = {}): Promise<void> {\n const { abortSignal } = options;\n throwIfAborted(abortSignal, 'start Docker sandbox');\n this.logger.debug(`${LOG_PREFIX} Starting sandbox ${this.id}...`);\n\n // Try to reconnect to existing container\n const existing = await this._findExistingContainer();\n if (existing) {\n this.logger.debug(`${LOG_PREFIX} Found existing container ${existing.Id}`);\n this._container = this._docker.getContainer(existing.Id);\n\n // Use inspect() to get authoritative container state — listContainers() state\n // can be stale immediately after stop() returns but before container fully exits\n const info = await this._container.inspect();\n // On reconnect, actual HostConfig controls whether hardening is effective.\n this._warnOnPrivilegedHardeningConflict(info.HostConfig?.Privileged ?? this._privileged);\n this._warnOnReconnectedHostConfigMismatch(existing.Id, info.HostConfig);\n const actualState = info.State?.Running ? 'running' : 'stopped';\n\n if (actualState !== 'running') {\n this.logger.debug(`${LOG_PREFIX} Container exists but not running (${actualState}), starting...`);\n await this._container.start();\n }\n\n // The container was created with a working directory (possibly derived\n // from a template); keep resolving relative paths against it rather than\n // this instance's default.\n const reconnectedWorkingDir = info.Config?.WorkingDir;\n if (!this._workingDirectoryWasSet && reconnectedWorkingDir) {\n this.setWorkingDirectory(reconnectedWorkingDir);\n }\n\n // Provide container reference to process manager\n this.processes.setContainer(this._container);\n\n this.logger.debug(`${LOG_PREFIX} Reconnected to container ${existing.Id}`);\n return;\n }\n\n this._warnOnPrivilegedHardeningConflict(this._privileged);\n\n await this._resolveTemplate(abortSignal);\n\n // Pull image if not available locally\n await this._ensureImage();\n\n // Build environment array for Docker API\n const envArray = Object.entries(this._env).map(([k, v]) => `${k}=${v}`);\n\n // Build bind mount array\n const binds = Object.entries(this._volumes).map(([host, container]) => `${host}:${container}`);\n\n // Create container\n this.logger.debug(`${LOG_PREFIX} Creating container with image ${this._image}...`);\n this._container = await this._docker.createContainer({\n name: this._containerName,\n Image: this._image,\n Cmd: this._command,\n Env: envArray,\n WorkingDir: this.workingDirectory,\n Labels: this._labels,\n HostConfig: {\n Binds: binds.length > 0 ? binds : undefined,\n NetworkMode: this._network,\n Privileged: this._privileged,\n Memory: this._memory,\n MemorySwap: this._memorySwap,\n CpuShares: this._cpuShares,\n CpuQuota: this._cpuQuota,\n CpuPeriod: this._cpuPeriod,\n PidsLimit: this._pidsLimit,\n Init: this._init,\n ReadonlyRootfs: this._readonlyRootfs,\n CapDrop: this._capDrop,\n CapAdd: this._capAdd,\n SecurityOpt: this._securityOpt,\n Ulimits: this._ulimits?.map(toDockerUlimit),\n Tmpfs: this._tmpfs,\n Mounts: this._mounts?.map(toDockerMount),\n },\n // Keep stdin open for interactive use\n OpenStdin: true,\n Tty: false,\n });\n\n // Start container\n await this._container.start();\n\n // Provide container reference to process manager\n this.processes.setContainer(this._container);\n\n this.logger.debug(`${LOG_PREFIX} Container started: ${this._container.id}`);\n }\n\n private _warnOnPrivilegedHardeningConflict(effectivePrivileged: boolean | undefined): void {\n if (!effectivePrivileged) return;\n\n // Privileged mode makes capability and security-option controls ineffective.\n // ReadonlyRootfs, ulimits, tmpfs, memory, CPU, and PID limits still apply.\n const conflictedHostConfigFields = [\n this._capDrop && this._capDrop.length > 0 ? 'CapDrop' : undefined,\n this._capAdd && this._capAdd.length > 0 ? 'CapAdd' : undefined,\n this._securityOpt && this._securityOpt.length > 0 ? 'SecurityOpt' : undefined,\n ].filter((field): field is keyof Docker.HostConfig => field !== undefined);\n\n if (conflictedHostConfigFields.length === 0) return;\n\n const optionNames = conflictedHostConfigFields.map(toDockerSandboxOptionName);\n\n this.logger.warn(\n `${LOG_PREFIX} Privileged containers can bypass some requested hardening controls: ${optionNames.join(', ')}`,\n { fields: optionNames, hostConfigFields: conflictedHostConfigFields },\n );\n }\n\n private _warnOnReconnectedHostConfigMismatch(containerId: string, hostConfig?: Docker.HostConfig): void {\n if (!hostConfig) return;\n\n const mismatchedHostConfigFields = this._requestedHardeningHostConfigEntries(hostConfig)\n .filter(([field, requestedValue]) => !isHostConfigValueEqual(field, hostConfig[field], requestedValue))\n .map(([field]) => field);\n\n if (mismatchedHostConfigFields.length === 0) return;\n\n if (\n !this._privilegedWasSet &&\n hostConfig.Privileged === true &&\n mismatchedHostConfigFields.includes('Privileged')\n ) {\n this.logger.warn(\n `${LOG_PREFIX} Reconnected to existing container ${containerId}; the existing container is privileged, but this DockerSandbox did not request privileged mode. Destroy and recreate the sandbox to apply the default non-privileged mode.`,\n { containerId, fields: ['privileged'], hostConfigFields: ['Privileged'] },\n );\n }\n\n const remainingMismatchedHostConfigFields = mismatchedHostConfigFields.filter(\n field => field !== 'Privileged' || this._privilegedWasSet,\n );\n\n if (remainingMismatchedHostConfigFields.length === 0) return;\n\n const mismatchedOptions = remainingMismatchedHostConfigFields.map(toDockerSandboxOptionName);\n\n this.logger.warn(\n `${LOG_PREFIX} Reconnected to existing container ${containerId}; requested Docker option(s) ${mismatchedOptions.join(\n ', ',\n )} differ from inspected HostConfig field(s) ${remainingMismatchedHostConfigFields.join(\n ', ',\n )} and cannot be applied to the existing container. Destroy and recreate the sandbox to apply them.`,\n { containerId, fields: mismatchedOptions, hostConfigFields: remainingMismatchedHostConfigFields },\n );\n }\n\n private _requestedHardeningHostConfigEntries(\n hostConfig?: Docker.HostConfig,\n ): Array<[keyof Docker.HostConfig, unknown]> {\n const entries: Array<[keyof Docker.HostConfig, unknown]> = [\n ['Memory', this._memory],\n ['MemorySwap', this._memorySwap],\n ['CpuShares', this._cpuShares],\n ['CpuQuota', this._cpuQuota],\n ['CpuPeriod', this._cpuPeriod],\n ['PidsLimit', this._pidsLimit],\n ['ReadonlyRootfs', this._readonlyRootfs],\n ['CapDrop', this._capDrop],\n ['CapAdd', this._capAdd],\n ['SecurityOpt', this._securityOpt],\n ['Ulimits', this._ulimits],\n ['Tmpfs', this._tmpfs],\n ['Mounts', this._mounts?.map(toDockerMount)],\n ];\n\n if (this._privilegedWasSet || hostConfig?.Privileged === true) {\n entries.unshift(['Privileged', this._privileged]);\n }\n\n return entries.filter((entry): entry is [keyof Docker.HostConfig, unknown] => isPresentHostConfigValue(entry[1]));\n }\n\n async stop(): Promise<void> {\n const container = await this._resolveContainer();\n if (!container) return;\n\n this.logger.debug(`${LOG_PREFIX} Stopping container ${container.id}...`);\n try {\n await container.stop({ t: 10 });\n } catch (error: unknown) {\n // Container may already be stopped\n if (!isContainerNotRunningError(error)) {\n throw error;\n }\n }\n this.processes.reset();\n this.logger.debug(`${LOG_PREFIX} Container stopped`);\n }\n\n async destroy(): Promise<void> {\n const container = await this._resolveContainer();\n if (!container) return;\n\n this.logger.debug(`${LOG_PREFIX} Destroying container ${container.id}...`);\n try {\n await container.remove({ force: true, v: true });\n } catch (error: unknown) {\n // Container may already be removed\n if (!isContainerNotFoundError(error)) {\n throw error;\n }\n }\n this.processes.reset();\n this._container = null;\n this.logger.debug(`${LOG_PREFIX} Container destroyed`);\n }\n\n // ---------------------------------------------------------------------------\n // File Upload\n // ---------------------------------------------------------------------------\n\n /**\n * Bulk-write files into the container's filesystem using Docker's native\n * archive upload (`putArchive`), the same mechanism as `docker cp`.\n *\n * Behavior:\n * - Requires a started sandbox. Throws {@link SandboxNotReadyError} otherwise\n * (Docker containers are not auto-started by this method).\n * - Absolute paths are used as-is; relative paths resolve against\n * {@link workingDirectory}.\n * - Missing parent directories are created automatically.\n * - Existing destinations are overwritten (contents and mode).\n * - Exact bytes are preserved for both `string` and `Buffer` content,\n * including empty files and binary data.\n * - New files use the per-file `mode` when provided (validated integer\n * `0o001`–`0o777`), otherwise `0644`; directories created implicitly default\n * to Docker's `0755`. Overwriting a file replaces its mode with the\n * requested `mode` (or `0644` when omitted).\n * - Not atomic across files: on failure the promise rejects and earlier or\n * partially written files may remain.\n *\n * Cancellation (`options.abortSignal`):\n * - If the signal is already aborted, rejects with {@link SandboxAbortError}\n * before creating the archive or starting the upload.\n * - If the signal aborts during transfer, the underlying `putArchive` request\n * is terminated by destroying the tar stream (which ends the request body),\n * and the promise rejects with {@link SandboxAbortError}.\n * - Upload and cancellation race: an upload that completes before the abort is\n * observed resolves normally.\n * - No rollback: files Docker already received or extracted may remain. The\n * daemon may continue extraction after rejection, so the caller is\n * responsible for any cleanup or sandbox disposal.\n * - Behavior is unchanged when no signal is supplied.\n *\n * @throws {SandboxNotReadyError} If the sandbox has not been started.\n * @throws {SandboxAbortError} If the write is cancelled via `options.abortSignal`.\n * @throws {SandboxError} If the archive upload fails.\n */\n async writeFiles(files: SandboxFileInput[], options?: WriteFilesOptions): Promise<void> {\n const container = this.container;\n\n const signal = options?.abortSignal;\n if (signal?.aborted) throw new SandboxAbortError('writeFiles');\n\n if (files.length === 0) return;\n\n const pack = tarPack();\n for (const file of files) {\n if (file.mode !== undefined) validateSandboxFileMode(file.mode);\n const resolved = posixPath.isAbsolute(file.path)\n ? posixPath.normalize(file.path)\n : posixPath.resolve(this.workingDirectory, file.path);\n const data = Buffer.isBuffer(file.content) ? file.content : Buffer.from(file.content);\n const mode = file.mode ?? 0o644;\n // tar entries are relative; strip the leading slash so extraction at `/`\n // lands the file at its intended absolute path.\n pack.entry({ name: resolved.replace(/^\\/+/, ''), size: data.length, mode }, data);\n }\n pack.finalize();\n\n // Destroying the tar stream ends the putArchive request body, which\n // terminates the in-flight HTTP upload to the Docker daemon. The\n // abortSignal is also forwarded to putArchive for transports that observe\n // it; it is harmless when ignored.\n const onAbort = () => pack.destroy();\n if (signal) signal.addEventListener('abort', onAbort, { once: true });\n\n try {\n await container.putArchive(pack, { path: '/', abortSignal: signal });\n } catch (error) {\n if (signal?.aborted) throw new SandboxAbortError('writeFiles');\n throw new SandboxError(\n `Failed to write files to sandbox: ${error instanceof Error ? error.message : String(error)}`,\n 'EXECUTION_FAILED',\n { reason: 'write_files_failed' },\n );\n } finally {\n if (signal) signal.removeEventListener('abort', onAbort);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Instructions\n // ---------------------------------------------------------------------------\n\n getInstructions(opts?: { requestContext?: RequestContext }): string {\n const defaultInstructions = [\n `You are working inside a Docker container (image: ${this._image}).`,\n `The working directory is ${this.workingDirectory}.`,\n 'You can execute shell commands using executeCommand().',\n 'You can spawn background processes using processes.spawn().',\n ].join('\\n');\n\n if (this._instructionsOverride === undefined) return defaultInstructions;\n if (typeof this._instructionsOverride === 'string') return this._instructionsOverride;\n return this._instructionsOverride({ defaultInstructions, requestContext: opts?.requestContext });\n }\n\n // ---------------------------------------------------------------------------\n // Info\n // ---------------------------------------------------------------------------\n\n async getInfo(): Promise<SandboxInfo> {\n const info: SandboxInfo = {\n id: this.id,\n name: this.name,\n provider: this.provider,\n status: this.status,\n createdAt: new Date(),\n metadata: {\n image: this._image,\n workingDir: this.workingDirectory,\n labels: this._labels,\n },\n };\n\n if (this._container) {\n try {\n const inspect = await this._container.inspect();\n info.createdAt = new Date(inspect.Created);\n info.metadata = {\n ...info.metadata,\n containerId: inspect.Id,\n containerName: inspect.Name,\n state: inspect.State.Status,\n };\n } catch {\n // Container may have been removed\n }\n }\n\n return info;\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n private _generateId(): string {\n return `docker-sandbox-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n }\n\n /**\n * Resolve the container reference, looking up by label if `_container` is unset.\n * This ensures `stop()` and `destroy()` work even when the instance was created\n * with an existing container's ID but `start()` was never called.\n */\n private async _resolveContainer(): Promise<Container | null> {\n if (this._container) return this._container;\n const existing = await this._findExistingContainer();\n if (!existing) return null;\n this._container = this._docker.getContainer(existing.Id);\n return this._container;\n }\n\n /**\n * Find an existing container matching this sandbox's ID via labels.\n */\n private async _findExistingContainer(): Promise<ContainerInfo | null> {\n try {\n const containers = await this._docker.listContainers({\n all: true,\n filters: {\n label: [`mastra.sandbox.id=${this.id}`],\n },\n });\n return containers[0] ?? null;\n } catch (error) {\n // Log and re-throw infrastructure errors (daemon unreachable, auth, etc.)\n this.logger.debug(\n `${LOG_PREFIX} Failed to list containers: ${error instanceof Error ? error.message : String(error)}`,\n );\n throw error;\n }\n }\n\n /**\n * Resolve the `template` option (if any) into the image to boot from,\n * building it when no cached image exists. Runs on every `start()` that\n * creates a container, so a resolver-form template re-resolves each time.\n * Adopts the template's workdir unless the sandbox was given one explicitly.\n */\n private async _resolveTemplate(abortSignal?: AbortSignal): Promise<void> {\n if (!this._templateSpec) return;\n throwIfAborted(abortSignal, 'start Docker sandbox');\n let template: DockerTemplate;\n try {\n template =\n typeof this._templateSpec === 'function' ? await this._templateSpec({ abortSignal }) : this._templateSpec;\n } catch (error) {\n throw normalizeAbortError(error, 'start Docker sandbox');\n }\n throwIfAborted(abortSignal, 'start Docker sandbox');\n // Build on this sandbox's daemon, which may differ from the template's default.\n const result = await template.build({ docker: this._docker, abortSignal });\n if (result.status !== 'ready') {\n throw new SandboxError(`Docker template build failed: ${result.error ?? 'unknown error'}`, 'START_FAILED', {\n templateId: result.templateId,\n reason: 'template_build_failed',\n });\n }\n this._image = result.templateId;\n if (!this._workingDirectoryWasSet && template.workdir !== undefined) {\n this.setWorkingDirectory(template.workdir);\n }\n }\n\n /**\n * Ensure the Docker image is available locally. Pulls if needed.\n */\n private async _ensureImage(): Promise<void> {\n try {\n await this._docker.getImage(this._image).inspect();\n this.logger.debug(`${LOG_PREFIX} Image ${this._image} available locally`);\n } catch (error) {\n // Only attempt pull if the image doesn't exist (404).\n // Re-throw infrastructure errors (daemon unreachable, auth, etc.)\n if (!isImageNotFoundError(error)) {\n throw error;\n }\n\n this.logger.debug(`${LOG_PREFIX} Pulling image ${this._image}...`);\n try {\n const stream = await this._docker.pull(this._image);\n await new Promise<void>((resolve, reject) => {\n this._docker.modem.followProgress(stream, (err: Error | null) => {\n if (err) reject(err);\n else resolve();\n });\n });\n this.logger.debug(`${LOG_PREFIX} Image ${this._image} pulled successfully`);\n } catch (error) {\n throw new SandboxError(\n `Failed to pull Docker image '${this._image}': ${error instanceof Error ? error.message : String(error)}`,\n 'NOT_READY',\n { image: this._image, reason: 'image_pull_failed' },\n );\n }\n }\n }\n}\n\n// =============================================================================\n// Error detection helpers\n// =============================================================================\n\n// Docker container name regex (`^[a-zA-Z0-9][a-zA-Z0-9_.-]+$`) — first char must be\n// alphanumeric, remaining chars from `[a-zA-Z0-9_.-]`, total length ≥ 2.\nfunction sanitizeContainerName(value: string): string {\n const replaced = value.replace(/[^a-zA-Z0-9_.-]/g, '-');\n const withLeading = /^[a-zA-Z0-9]/.test(replaced) ? replaced : `s-${replaced}`;\n return withLeading.length >= 2 ? withLeading : `${withLeading}-sandbox`;\n}\n\nfunction isContainerNotRunningError(error: unknown): boolean {\n if (error instanceof Error) {\n return error.message.includes('is not running') || error.message.includes('container already stopped');\n }\n return false;\n}\n\nfunction isContainerNotFoundError(error: unknown): boolean {\n if (error instanceof Error) {\n const msg = error.message.toLowerCase();\n return msg.includes('no such container') || (msg.includes('removal') && msg.includes('is already in progress'));\n }\n return false;\n}\n\nfunction isImageNotFoundError(error: unknown): boolean {\n if (error instanceof Error) {\n return error.message.toLowerCase().includes('no such image');\n }\n return false;\n}\n\nfunction isHostConfigValueEqual(field: keyof Docker.HostConfig, actual: unknown, expected: unknown): boolean {\n // Structural equality for the Docker HostConfig shapes exposed by DockerSandboxOptions.\n return isDeepStrictEqual(normalizeHostConfigValue(field, actual), normalizeHostConfigValue(field, expected));\n}\n\nfunction normalizeHostConfigValue(field: keyof Docker.HostConfig, value: unknown): unknown {\n if (value == null) return undefined;\n\n if ((field === 'CapAdd' || field === 'CapDrop') && Array.isArray(value)) {\n if (value.length === 0) return undefined;\n return value.map(normalizeCapability).sort();\n }\n\n if (field === 'SecurityOpt' && Array.isArray(value)) {\n if (value.length === 0) return undefined;\n return value.map(normalizeSecurityOpt).sort();\n }\n\n if (field === 'Tmpfs' && value && typeof value === 'object' && !Array.isArray(value)) {\n if (Object.keys(value).length === 0) return undefined;\n return Object.fromEntries(\n Object.entries(value)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([path, options]) => [path, typeof options === 'string' ? normalizeTmpfsOptions(options) : options]),\n );\n }\n\n if (Array.isArray(value)) {\n if (field === 'Ulimits' && value.length === 0) return undefined;\n return value\n .map(nestedValue => normalizeHostConfigValue(field, nestedValue))\n .sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)));\n }\n\n if (field === 'Ulimits' && value && typeof value === 'object') {\n return normalizeUlimit(value);\n }\n\n if (value && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, nestedValue]) => [key, normalizeHostConfigValue(field, nestedValue)]),\n );\n }\n\n return value;\n}\n\nfunction isPresentHostConfigValue(value: unknown): boolean {\n if (value == null) return false;\n if (Array.isArray(value)) return value.length > 0;\n if (value && typeof value === 'object') return Object.keys(value).length > 0;\n return true;\n}\n\nfunction normalizeCapability(capability: unknown): unknown {\n return typeof capability === 'string' ? capability.toUpperCase().replace(/^CAP_/, '') : capability;\n}\n\nfunction normalizeTmpfsOptions(options: string): string {\n return options\n .split(',')\n .map(option => option.trim())\n .filter(Boolean)\n .sort()\n .join(',');\n}\n\nfunction normalizeSecurityOpt(option: unknown): unknown {\n if (typeof option !== 'string') return option;\n\n const noNewPrivileges = option.match(/^no-new-privileges[:=](.+)$/i);\n if (noNewPrivileges) {\n return `no-new-privileges=${noNewPrivileges[1]}`;\n }\n\n return option;\n}\n\nfunction normalizeUlimit(value: object): unknown {\n const record = value as Record<string, unknown>;\n return {\n name: record.name ?? record.Name,\n soft: record.soft ?? record.Soft,\n hard: record.hard ?? record.Hard,\n };\n}\n\nfunction toDockerUlimit(ulimit: DockerSandboxUlimit): Docker.Ulimit {\n return {\n Name: ulimit.name,\n Soft: ulimit.soft,\n Hard: ulimit.hard,\n };\n}\n\nfunction toDockerMount(mount: DockerSandboxMount): Docker.MountSettings {\n const settings: Docker.MountSettings = {\n Type: mount.type,\n Target: mount.target,\n Source: mount.type === 'tmpfs' ? '' : mount.source,\n };\n\n if (mount.readOnly !== undefined) settings.ReadOnly = mount.readOnly;\n\n if (mount.type === 'volume' && mount.volumeOptions) {\n const { subpath, noCopy, labels } = mount.volumeOptions;\n // The @types/dockerode VolumeOptions marks NoCopy/Labels/DriverConfig as\n // required, but the Docker API treats them as optional; build a partial.\n const volumeOptions: Record<string, unknown> = {};\n if (subpath !== undefined) volumeOptions.Subpath = subpath;\n if (noCopy !== undefined) volumeOptions.NoCopy = noCopy;\n if (labels !== undefined) volumeOptions.Labels = labels;\n if (Object.keys(volumeOptions).length > 0) {\n settings.VolumeOptions = volumeOptions as Docker.MountSettings['VolumeOptions'];\n }\n }\n\n if (mount.type === 'bind' && mount.bindOptions?.propagation !== undefined) {\n settings.BindOptions = { Propagation: mount.bindOptions.propagation };\n }\n\n if (mount.type === 'tmpfs' && mount.tmpfsOptions) {\n const { sizeBytes, mode } = mount.tmpfsOptions;\n const tmpfsOptions: Record<string, unknown> = {};\n if (sizeBytes !== undefined) tmpfsOptions.SizeBytes = sizeBytes;\n if (mode !== undefined) tmpfsOptions.Mode = mode;\n if (Object.keys(tmpfsOptions).length > 0) {\n settings.TmpfsOptions = tmpfsOptions as Docker.MountSettings['TmpfsOptions'];\n }\n }\n\n return settings;\n}\n\nfunction toDockerSandboxOptionName(field: keyof Docker.HostConfig): string {\n const optionNames: Partial<Record<keyof Docker.HostConfig, string>> = {\n Privileged: 'privileged',\n Memory: 'memory',\n MemorySwap: 'memorySwap',\n CpuShares: 'cpuShares',\n CpuQuota: 'cpuQuota',\n CpuPeriod: 'cpuPeriod',\n PidsLimit: 'pidsLimit',\n ReadonlyRootfs: 'readonlyRootfs',\n CapDrop: 'capDrop',\n CapAdd: 'capAdd',\n SecurityOpt: 'securityOpt',\n Ulimits: 'ulimits',\n Tmpfs: 'tmpfs',\n Mounts: 'mounts',\n };\n\n return optionNames[field] ?? String(field);\n}\n","/**\n * Docker Sandbox Provider Descriptor\n *\n * Enables registration with MastraEditor for UI-driven sandbox configuration.\n */\n\nimport type { SandboxProvider } from '@mastra/core/editor';\nimport { DockerSandbox } from './sandbox';\nimport type { DockerSandboxOptions } from './sandbox';\n\n/**\n * Serializable config for the Docker sandbox provider.\n * This is the subset of DockerSandboxOptions that can be stored in a config file\n * and rendered in a UI form.\n */\nexport interface DockerProviderConfig {\n /** Docker image to use */\n image?: string;\n /** Default command timeout in milliseconds */\n timeout?: number;\n /** Environment variables */\n env?: Record<string, string>;\n /** Host-to-container bind mounts */\n volumes?: Record<string, string>;\n /** Docker network to join */\n network?: string;\n /** Working directory inside the container */\n workingDir?: string;\n /** Run in privileged mode */\n privileged?: boolean;\n /** Memory limit in bytes */\n memory?: number;\n /** Total memory plus swap in bytes */\n memorySwap?: number;\n /** CPU shares relative weight */\n cpuShares?: number;\n /** CPU quota in microseconds per period */\n cpuQuota?: number;\n /** CPU period in microseconds */\n cpuPeriod?: number;\n /** Maximum number of PIDs in the container */\n pidsLimit?: number;\n /** Mount the container root filesystem as read-only */\n readonlyRootfs?: boolean;\n /** Linux capabilities to drop */\n capDrop?: string[];\n /** Linux capabilities to add */\n capAdd?: string[];\n /** Docker security options */\n securityOpt?: string[];\n /** Ulimit entries for Docker HostConfig.Ulimits */\n ulimits?: DockerSandboxOptions['ulimits'];\n /** tmpfs mount paths with options */\n tmpfs?: DockerSandboxOptions['tmpfs'];\n /** Mounts mapped 1:1 onto Docker HostConfig.Mounts (supports volume subpath) */\n mounts?: DockerSandboxOptions['mounts'];\n}\n\nexport const dockerSandboxProvider: SandboxProvider<DockerProviderConfig> = {\n id: 'docker',\n name: 'Docker Sandbox',\n description: 'Local container sandbox powered by Docker',\n configSchema: {\n type: 'object',\n properties: {\n image: {\n type: 'string',\n description: 'Docker image to use',\n default: 'node:22-slim',\n },\n timeout: {\n type: 'number',\n description: 'Default command timeout in milliseconds',\n default: 300_000,\n },\n env: {\n type: 'object',\n description: 'Environment variables',\n additionalProperties: { type: 'string' },\n },\n volumes: {\n type: 'object',\n description: 'Host-to-container bind mounts (host path → container path)',\n additionalProperties: { type: 'string' },\n },\n network: {\n type: 'string',\n description: 'Docker network to join',\n },\n workingDir: {\n type: 'string',\n description: 'Working directory inside the container',\n default: '/workspace',\n },\n privileged: {\n type: 'boolean',\n description: 'Run in privileged mode',\n default: false,\n },\n memory: {\n type: 'number',\n description: 'Memory limit in bytes',\n },\n memorySwap: {\n type: 'number',\n description: 'Total memory plus swap in bytes',\n },\n cpuShares: {\n type: 'number',\n description: 'CPU shares relative weight',\n },\n cpuQuota: {\n type: 'number',\n description: 'CPU quota in microseconds per period',\n },\n cpuPeriod: {\n type: 'number',\n description: 'CPU period in microseconds',\n },\n pidsLimit: {\n type: 'number',\n description: 'Maximum number of PIDs in the container',\n },\n readonlyRootfs: {\n type: 'boolean',\n description: 'Mount the container root filesystem as read-only',\n },\n capDrop: {\n type: 'array',\n description: 'Linux capabilities to drop',\n items: { type: 'string' },\n },\n capAdd: {\n type: 'array',\n description: 'Linux capabilities to add',\n items: { type: 'string' },\n },\n securityOpt: {\n type: 'array',\n description: 'Docker security options',\n items: { type: 'string' },\n },\n ulimits: {\n type: 'array',\n description: 'Ulimit entries for Docker HostConfig.Ulimits',\n items: {\n type: 'object',\n required: ['name', 'soft', 'hard'],\n additionalProperties: false,\n properties: {\n name: { type: 'string' },\n soft: { type: 'number' },\n hard: { type: 'number' },\n },\n },\n },\n tmpfs: {\n type: 'object',\n description: 'tmpfs mount paths with options',\n additionalProperties: { type: 'string' },\n },\n mounts: {\n type: 'array',\n description: 'Mounts mapped 1:1 onto Docker HostConfig.Mounts (supports volume subpath)',\n items: {\n oneOf: [\n {\n type: 'object',\n required: ['type', 'target', 'source'],\n additionalProperties: false,\n properties: {\n type: { const: 'volume' },\n target: { type: 'string' },\n source: { type: 'string' },\n readOnly: { type: 'boolean' },\n volumeOptions: {\n type: 'object',\n additionalProperties: false,\n properties: {\n subpath: { type: 'string' },\n noCopy: { type: 'boolean' },\n labels: { type: 'object', additionalProperties: { type: 'string' } },\n },\n },\n },\n },\n {\n type: 'object',\n required: ['type', 'target', 'source'],\n additionalProperties: false,\n properties: {\n type: { const: 'bind' },\n target: { type: 'string' },\n source: { type: 'string' },\n readOnly: { type: 'boolean' },\n bindOptions: {\n type: 'object',\n additionalProperties: false,\n properties: {\n propagation: {\n type: 'string',\n enum: ['private', 'rprivate', 'shared', 'rshared', 'slave', 'rslave'],\n },\n },\n },\n },\n },\n {\n type: 'object',\n required: ['type', 'target'],\n additionalProperties: false,\n properties: {\n type: { const: 'tmpfs' },\n target: { type: 'string' },\n readOnly: { type: 'boolean' },\n tmpfsOptions: {\n type: 'object',\n additionalProperties: false,\n properties: {\n sizeBytes: { type: 'number' },\n mode: { type: 'number' },\n },\n },\n },\n },\n ],\n },\n },\n },\n },\n createSandbox: (config: DockerProviderConfig) => new DockerSandbox(config as DockerSandboxOptions),\n};\n","/**\n * BuildKit session that serves build secrets to the daemon.\n *\n * `docker build` with BuildKit (`version=2`) can attach a long-lived gRPC\n * \"session\" that the daemon calls back into for things it needs mid-build.\n * `RUN --mount=type=secret,id=X` is resolved by calling\n * `/moby.buildkit.secrets.v1.Secrets/GetSecret` on that session, so the value\n * exists only in the tmpfs mount for the duration of that one RUN — never as a\n * build arg, layer, history entry, or cache metadata.\n *\n * dockerode's own session helper only registers the registry-auth service and\n * overwrites any `session` id passed to `buildImage`, so this module dials the\n * hijacked `/session` endpoint itself and registers both services.\n */\nimport { randomUUID } from 'node:crypto';\nimport { Server, ServerCredentials, type ServiceDefinition, type UntypedServiceImplementation } from '@grpc/grpc-js';\nimport type Docker from 'dockerode';\nimport { createAbortError, throwIfAborted } from '../abort';\n\nexport const SECRETS_GET_METHOD = '/moby.buildkit.secrets.v1.Secrets/GetSecret';\nconst AUTH_CREDENTIALS_METHOD = '/moby.filesync.v1.Auth/Credentials';\n\nexport interface BuildSession {\n id: string;\n close(): void;\n}\n\n/**\n * Open a session that answers `GetSecret` from `secrets`. The returned id must\n * be sent as the `session` query parameter of the build request.\n */\nexport function openBuildSession(\n docker: Docker,\n secrets: Record<string, string>,\n abortSignal?: AbortSignal,\n): Promise<BuildSession> {\n throwIfAborted(abortSignal, 'build Docker template');\n const id = randomUUID();\n return new Promise((resolve, reject) => {\n let settled = false;\n const abort = () => {\n if (settled || !abortSignal) return;\n settled = true;\n reject(createAbortError(abortSignal, 'build Docker template'));\n };\n abortSignal?.addEventListener('abort', abort, { once: true });\n docker.modem.dial(\n {\n method: 'POST',\n path: '/session',\n hijack: true,\n headers: {\n Upgrade: 'h2c',\n 'X-Docker-Expose-Session-Uuid': id,\n 'X-Docker-Expose-Session-Name': 'mastra-docker-template',\n // The daemon only calls methods the client advertises.\n 'X-Docker-Expose-Session-Grpc-Method': [SECRETS_GET_METHOD, AUTH_CREDENTIALS_METHOD],\n },\n statusCodes: { 200: true, 500: 'server error' },\n },\n (err: Error | null, socket: unknown) => {\n if (settled) {\n (socket as { end?(): void } | undefined)?.end?.();\n return;\n }\n settled = true;\n abortSignal?.removeEventListener('abort', abort);\n if (err) {\n reject(abortSignal?.aborted ? createAbortError(abortSignal, 'build Docker template') : err);\n return;\n }\n const server = new Server();\n server.createConnectionInjector(ServerCredentials.createInsecure()).injectConnection(socket as never);\n server.addService(secretsService, {\n GetSecret(\n call: { request: GetSecretRequest },\n callback: (err: Error | null, res?: GetSecretResponse) => void,\n ) {\n const value = Object.hasOwn(secrets, call.request.id) ? secrets[call.request.id] : undefined;\n if (value === undefined) {\n callback(\n Object.assign(new Error(`no build secret registered with id '${call.request.id}'`), { code: 5 }),\n );\n return;\n }\n callback(null, { data: Buffer.from(value, 'utf8') });\n },\n } as UntypedServiceImplementation);\n server.addService(authService, {\n Credentials(_call: unknown, callback: (err: Error | null, res?: Record<string, never>) => void) {\n callback(null, {});\n },\n } as UntypedServiceImplementation);\n resolve({\n id,\n close() {\n server.forceShutdown();\n (socket as { end(): void }).end();\n },\n });\n },\n );\n });\n}\n\n// ---------------------------------------------------------------------------\n// Wire format\n//\n// The two messages involved are small enough that hand-rolling the protobuf\n// encoding beats loading .proto files at runtime (which would not survive\n// bundling).\n//\n// message GetSecretRequest { string ID = 1; map<string,string> annotations = 2; }\n// message GetSecretResponse { bytes data = 1; }\n// message CredentialsResponse { string Username = 1; string Secret = 2; }\n// ---------------------------------------------------------------------------\n\nexport interface GetSecretRequest {\n id: string;\n}\nexport interface GetSecretResponse {\n data: Buffer;\n}\n\n/** @internal exported for tests */\nexport function decodeGetSecretRequest(buffer: Buffer): GetSecretRequest {\n let offset = 0;\n let id = '';\n const readVarint = (): number => {\n let result = 0;\n let shift = 0;\n for (;;) {\n if (offset >= buffer.length) throw new Error('truncated varint');\n const byte = buffer[offset++]!;\n result += (byte & 0x7f) * 2 ** shift;\n if ((byte & 0x80) === 0) return result;\n shift += 7;\n }\n };\n while (offset < buffer.length) {\n const key = readVarint();\n const field = Math.floor(key / 8);\n const wireType = key % 8;\n switch (wireType) {\n case 0:\n readVarint();\n break;\n case 1:\n offset += 8;\n break;\n case 5:\n offset += 4;\n break;\n case 2: {\n const length = readVarint();\n const value = buffer.subarray(offset, offset + length);\n offset += length;\n if (field === 1) id = value.toString('utf8');\n break;\n }\n default:\n throw new Error(`unsupported protobuf wire type ${wireType}`);\n }\n }\n return { id };\n}\n\n/** @internal exported for tests */\nexport function encodeGetSecretResponse(response: GetSecretResponse): Buffer {\n return Buffer.concat([Buffer.from([0x0a]), encodeVarint(response.data.length), response.data]);\n}\n\nfunction encodeVarint(value: number): Buffer {\n const bytes: number[] = [];\n let remaining = value;\n while (remaining >= 0x80) {\n bytes.push((remaining % 0x80) | 0x80);\n remaining = Math.floor(remaining / 0x80);\n }\n bytes.push(remaining);\n return Buffer.from(bytes);\n}\n\nconst secretsService: ServiceDefinition = {\n GetSecret: {\n path: SECRETS_GET_METHOD,\n requestStream: false,\n responseStream: false,\n requestSerialize: () => {\n throw new Error('server does not serialize requests');\n },\n requestDeserialize: decodeGetSecretRequest,\n responseSerialize: encodeGetSecretResponse,\n responseDeserialize: () => {\n throw new Error('server does not deserialize responses');\n },\n },\n};\n\nconst authService: ServiceDefinition = {\n Credentials: {\n path: AUTH_CREDENTIALS_METHOD,\n requestStream: false,\n responseStream: false,\n requestSerialize: () => {\n throw new Error('server does not serialize requests');\n },\n requestDeserialize: () => ({}),\n // Empty message: anonymous registry access.\n responseSerialize: () => Buffer.alloc(0),\n responseDeserialize: () => {\n throw new Error('server does not deserialize responses');\n },\n },\n};\n","/**\n * Pure Dockerfile synthesis and content-addressed identity for DockerTemplate.\n *\n * A `DockerTemplate` records an ordered list of operations (setWorkdir, setEnvs,\n * runCmd, runWithSecrets, aptInstall, pipInstall, npmInstall) over a base image. This module\n * turns that ordered list into a deterministic Dockerfile string and a stable\n * content hash. It performs no I/O, so it is fully unit-testable without a\n * Docker daemon.\n */\n\nimport { createHash } from 'node:crypto';\n\n// =============================================================================\n// Operations\n// =============================================================================\n\nexport interface AptInstallOptions {\n /** Pass `--no-install-recommends` to `apt-get install`. */\n noInstallRecommends?: boolean;\n /** Pass `--fix-missing` to `apt-get install`. */\n fixMissing?: boolean;\n}\n\nexport interface PipInstallOptions {\n /** Install system-wide (default). `false` installs for the current user (`--user`). */\n g?: boolean;\n}\n\nexport interface NpmInstallOptions {\n /** Install globally (`npm install -g`). */\n g?: boolean;\n /** Include dev dependencies (`--include=dev`). Ignored when `packages` is set. */\n dev?: boolean;\n}\n\nexport interface RunWithSecretsOptions {\n /**\n * Names of environment variables whose values are read from the building\n * process's `process.env` at `build()` time and exposed to the command. Only\n * the names participate in the template identity.\n */\n secrets: string[];\n /**\n * Absolute path produced by the command. Only this path is copied into the\n * template image; everything else the command does (including the secret\n * values) stays in a throwaway build stage.\n */\n output: string;\n}\n\nexport type DockerTemplateOperation =\n | { method: 'setWorkdir'; args: [string] }\n | { method: 'setEnvs'; args: [Record<string, string>] }\n | { method: 'runCmd'; args: [string | string[]] }\n | { method: 'runWithSecrets'; args: [string | string[], RunWithSecretsOptions] }\n | { method: 'aptInstall'; args: [string | string[], AptInstallOptions?] }\n | { method: 'pipInstall'; args: [(string | string[])?, PipInstallOptions?] }\n | { method: 'npmInstall'; args: [(string | string[])?, NpmInstallOptions?] };\n\n/** A fully-resolved template definition: the base image and the ordered operations. */\nexport interface DockerTemplateDefinition {\n baseImage: string;\n operations: readonly DockerTemplateOperation[];\n}\n\n// =============================================================================\n// Dockerfile synthesis\n// =============================================================================\n\nfunction toCommandList(command: string | string[]): string[] {\n return Array.isArray(command) ? command : [command];\n}\n\nfunction sortedEntries(record: Record<string, string>): Array<[string, string]> {\n return Object.entries(record).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));\n}\n\nfunction renderEnvLine(envs: Record<string, string>): string | undefined {\n const pairs = sortedEntries(envs);\n if (pairs.length === 0) return undefined;\n // Deterministic order so identical envs always render identically.\n return `ENV ${pairs.map(([key, value]) => `${key}=${JSON.stringify(value)}`).join(' ')}`;\n}\n\nfunction renderAptInstall(packages: string | string[], options?: AptInstallOptions): string {\n const flags: string[] = [];\n if (options?.noInstallRecommends) flags.push('--no-install-recommends');\n if (options?.fixMissing) flags.push('--fix-missing');\n const flagStr = flags.length > 0 ? `${flags.join(' ')} ` : '';\n const pkgs = toCommandList(packages).join(' ');\n return `RUN apt-get update && apt-get install -y ${flagStr}${pkgs} && rm -rf /var/lib/apt/lists/*`;\n}\n\nfunction renderPipInstall(packages?: string | string[], options?: PipInstallOptions): string {\n const userFlag = options?.g === false ? ' --user' : '';\n const target = packages === undefined ? '.' : toCommandList(packages).join(' ');\n return `RUN pip install${userFlag} ${target}`;\n}\n\nfunction renderNpmInstall(packages?: string | string[], options?: NpmInstallOptions): string {\n const flags: string[] = [];\n if (options?.g) flags.push('-g');\n if (packages === undefined) {\n if (options?.dev) flags.push('--include=dev');\n const flagStr = flags.length > 0 ? ` ${flags.join(' ')}` : '';\n return `RUN npm install${flagStr}`;\n }\n const flagStr = flags.length > 0 ? ` ${flags.join(' ')}` : '';\n const pkgs = toCommandList(packages).join(' ');\n return `RUN npm install${flagStr} ${pkgs}`;\n}\n\nfunction secretStageName(index: number): string {\n return `mastra-secret-${index}`;\n}\n\nfunction mainStageName(index: number): string {\n return `mastra-main-${index}`;\n}\n\n/**\n * Render a deterministic Dockerfile from a template definition.\n *\n * Operations accumulate in a chain of \"main\" stages. Every `runWithSecrets`\n * operation forks a throwaway stage from the main stage as it stands at that\n * point (so it sees earlier WORKDIR/ENV/installs) and runs the command with\n * each secret exposed through a BuildKit secret mount, exported into the\n * command's environment for that single RUN. The next main stage then starts\n * from the same pre-secret snapshot and `COPY --from`s only the declared\n * output path. Secret mounts are tmpfs-backed and never part of a layer, its\n * history, or the build cache; the throwaway stage additionally keeps anything\n * else the command wrote (caches, logs) out of the template image.\n */\n/**\n * `RUN --mount=type=secret,id=X,mode=0444 ... export X=\"$(cat /run/secrets/X)\" && <command>`.\n * Reading the file into a shell variable keeps the value visible only to this\n * RUN's process tree, without depending on the newer `env=` mount option.\n * `mode=0444` because BuildKit's default is `0400 root`, which a base image\n * with a non-root `USER` cannot read; world-readable within the RUN is no\n * wider than the exported variable already is.\n */\nfunction renderSecretRun(command: string | string[], secrets: string[]): string {\n const names = [...secrets].sort();\n const mounts = names.map(name => `--mount=type=secret,id=${name},mode=0444`);\n const exports = names.map(name => `${name}=\"$(cat /run/secrets/${name})\"`);\n const prefix = names.length > 0 ? [`export ${exports.join(' ')}`] : [];\n return `RUN ${[...mounts, ''].join(' ')}${[...prefix, ...toCommandList(command)].join(' && ')}`;\n}\n\nexport function synthesizeDockerfile(definition: DockerTemplateDefinition): string {\n const lines: string[] = [];\n let mainIndex = 0;\n const openMain = (from: string) => {\n lines.push(`FROM ${from} AS ${mainStageName(mainIndex)}`);\n };\n openMain(definition.baseImage);\n\n definition.operations.forEach((operation, index) => {\n switch (operation.method) {\n case 'setWorkdir':\n lines.push(`WORKDIR ${operation.args[0]}`);\n break;\n case 'setEnvs': {\n const line = renderEnvLine(operation.args[0]);\n if (line) lines.push(line);\n break;\n }\n case 'runCmd':\n lines.push(`RUN ${toCommandList(operation.args[0]).join(' && ')}`);\n break;\n case 'runWithSecrets': {\n const [command, { secrets, output }] = operation.args;\n const snapshot = mainStageName(mainIndex);\n const stage = secretStageName(index);\n lines.push(`FROM ${snapshot} AS ${stage}`, renderSecretRun(command, secrets));\n mainIndex += 1;\n openMain(snapshot);\n lines.push(`COPY --from=${stage} ${output} ${output}`);\n break;\n }\n case 'aptInstall':\n lines.push(renderAptInstall(operation.args[0], operation.args[1]));\n break;\n case 'pipInstall':\n lines.push(renderPipInstall(operation.args[0], operation.args[1]));\n break;\n case 'npmInstall':\n lines.push(renderNpmInstall(operation.args[0], operation.args[1]));\n break;\n }\n });\n\n return `${lines.join('\\n')}\\n`;\n}\n\n/** Names of every secret referenced by `runWithSecrets` operations, deduplicated and sorted. */\nexport function secretNames(definition: DockerTemplateDefinition): string[] {\n const names = new Set<string>();\n for (const operation of definition.operations) {\n if (operation.method === 'runWithSecrets') {\n for (const name of operation.args[1].secrets) names.add(name);\n }\n }\n return [...names].sort();\n}\n\n// =============================================================================\n// Content-addressed identity\n// =============================================================================\n\n/** Prefix for template image tags built locally. */\nexport const TEMPLATE_IMAGE_REPO = 'mastra-template';\n\nfunction canonicalOperation(operation: DockerTemplateOperation): unknown {\n switch (operation.method) {\n case 'setEnvs':\n return { method: 'setEnvs', args: [sortedEntries(operation.args[0])] };\n case 'runWithSecrets': {\n const [command, { secrets, output }] = operation.args;\n return { method: 'runWithSecrets', args: [command, { secrets: [...secrets].sort(), output }] };\n }\n default:\n return operation;\n }\n}\n\n/**\n * Stable content hash over the base image and ordered operations. Env records\n * and secret name lists are canonicalized so insertion order does not change\n * the identity. Secret *values* never enter the definition, so the same\n * definition built with different credentials resolves to the same image tag.\n */\nexport function templateIdentity(definition: DockerTemplateDefinition): string {\n const canonical = JSON.stringify({\n schemaVersion: 1,\n baseImage: definition.baseImage,\n operations: definition.operations.map(canonicalOperation),\n });\n return createHash('sha256').update(canonical).digest('hex').slice(0, 24);\n}\n\n/** Full `mastra-template:<hash>` tag for a definition. */\nexport function templateImageTag(definition: DockerTemplateDefinition): string {\n return `${TEMPLATE_IMAGE_REPO}:${templateIdentity(definition)}`;\n}\n","/**\n * DockerTemplate — a reusable prepared baseline for the local Docker sandbox.\n *\n * Prepare an environment once (base image + ordered setup commands + env +\n * package installs), `build()` it into a content-addressed local image, then\n * spawn multiple disposable `DockerSandbox`es from that image. Each sandbox is a\n * fresh container with its own writable layer over the shared read-only image,\n * so their filesystems are independent. The built image's lifecycle is\n * controlled by `dispose()`, independent of any sandbox's `destroy()`.\n *\n * Unlike `docker commit` (which cannot capture mounted volumes and skips layer\n * caching), the baseline is produced by synthesizing a Dockerfile and running\n * `docker build`, so repo/setup content is baked into reproducible, cached\n * image layers.\n *\n * @example Prepare once, spawn many\n * ```typescript\n * import { DockerTemplate } from '@mastra/docker';\n *\n * const template = new DockerTemplate({ baseImage: 'node:22-slim' })\n * .runCmd('git clone --depth=1 https://example.com/repo /workspace/app')\n * .setWorkdir('/workspace/app')\n * .runCmd('npm ci');\n *\n * const result = await template.build();\n * if (result.status !== 'ready') throw new Error(result.error);\n *\n * const a = await template.createSandbox();\n * const b = await template.createSandbox(); // independent writable filesystem\n * ```\n */\n\nimport posixPath from 'node:path/posix';\nimport Docker from 'dockerode';\nimport { pack as tarPack } from 'tar-stream';\nimport { createAbortError, normalizeAbortError, throwIfAborted, waitForAbortable } from '../abort';\nimport { DockerSandbox, type DockerSandboxOptions } from '../sandbox';\nimport { openBuildSession, type BuildSession } from './build-session';\nimport {\n type AptInstallOptions,\n type DockerTemplateDefinition,\n type DockerTemplateOperation,\n type NpmInstallOptions,\n type PipInstallOptions,\n type RunWithSecretsOptions,\n secretNames,\n synthesizeDockerfile,\n templateImageTag,\n} from './dockerfile';\n\nconst MAX_OPERATIONS = 256;\nconst MAX_STRING_LENGTH = 32 * 1024;\nconst MAX_COLLECTION_ITEMS = 512;\n\nexport interface DockerTemplateOptions {\n /**\n * Base image for the template.\n * @default 'node:22-slim'\n */\n baseImage?: string;\n /** Pass-through dockerode connection options (socket path, host, TLS certs). */\n dockerOptions?: Docker.DockerOptions;\n /**\n * Values for the secrets named by {@link DockerTemplate.runWithSecrets}.\n * Supplying them here (rather than via `process.env`) keeps concurrent\n * builds with different credentials from racing on shared process state.\n * Not part of the template identity.\n */\n secrets?: DockerTemplateSecrets;\n}\n\n/**\n * Values for the secrets named by `runWithSecrets`, keyed by name. Either a\n * record or a function producing one (called once per real build, so rotated\n * credentials are picked up without rebuilding the template object).\n */\nexport type DockerTemplateSecrets =\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>);\n\nexport interface DockerTemplateBuildOptions {\n /**\n * Rebuild even if an image with the computed tag already exists locally,\n * re-executing every step instead of reusing the daemon's layer cache (the\n * cache does not key on secret values or on what `git clone`/`npm install`\n * would fetch today).\n */\n force?: boolean;\n /**\n * Build on this Docker client instead of the template's own. A sandbox\n * passes its client so the image lands on the daemon that will run it.\n */\n docker?: Docker;\n /**\n * Secret values for this build. Overrides the template-level `secrets`\n * source for names it provides. Names still missing after both sources are\n * read from `process.env` as a last resort.\n */\n secrets?: DockerTemplateSecrets;\n /** Cancel this caller's wait for preparation. */\n abortSignal?: AbortSignal;\n}\n\nexport interface DockerTemplateBuildResult {\n status: 'ready' | 'failed';\n /** The local image tag (`mastra-template:<hash>`) the template resolves to. */\n templateId: string;\n /** Failure detail when `status` is `'failed'`. */\n error?: string;\n}\n\ninterface InFlightBuild {\n promise: Promise<DockerTemplateBuildResult>;\n controller: AbortController;\n waiters: number;\n}\n\n/**\n * Immutable, chainable builder + build/lifecycle for a local Docker template.\n * Operation methods return a new instance (like the platform `Template()`\n * builder); `build`/`createSandbox`/`dispose` operate against the daemon.\n */\nexport class DockerTemplate {\n readonly #baseImage: string;\n readonly #operations: readonly DockerTemplateOperation[];\n readonly #dockerOptions: Docker.DockerOptions | undefined;\n readonly #secrets: DockerTemplateSecrets | undefined;\n #docker: Docker | undefined;\n #built = false;\n #queueTail: InFlightBuild | undefined;\n #plainBuild: InFlightBuild | undefined;\n\n constructor(options: DockerTemplateOptions = {}, state?: DockerTemplateState) {\n this.#baseImage = state ? state.baseImage : validateString(options.baseImage ?? 'node:22-slim', 'baseImage');\n this.#operations = state?.operations ?? [];\n this.#dockerOptions = options.dockerOptions;\n this.#secrets = options.secrets;\n }\n\n #clone(next: Partial<DockerTemplateState>): DockerTemplate {\n return new DockerTemplate(\n { dockerOptions: this.#dockerOptions, secrets: this.#secrets },\n {\n baseImage: next.baseImage ?? this.#baseImage,\n operations: next.operations ?? this.#operations,\n },\n );\n }\n\n #append(operation: DockerTemplateOperation): DockerTemplate {\n if (this.#operations.length >= MAX_OPERATIONS) {\n throw new RangeError(`Docker template cannot contain more than ${MAX_OPERATIONS} operations`);\n }\n return this.#clone({ operations: [...this.#operations, operation] });\n }\n\n /** Set the base image. */\n from(image: string): DockerTemplate {\n return this.#clone({ baseImage: validateString(image, 'image') });\n }\n\n /** Set the working directory for subsequent steps and the runtime container. */\n setWorkdir(path: string): DockerTemplate {\n return this.#append({ method: 'setWorkdir', args: [validateString(path, 'path')] });\n }\n\n /**\n * Set environment variables. They are baked into the image via `ENV` and\n * participate in the template identity, so never put secrets here — use\n * {@link runWithSecrets} for anything that must not persist in the image.\n */\n setEnvs(envs: Record<string, string>): DockerTemplate {\n return this.#append({ method: 'setEnvs', args: [validateStringRecord(envs, 'envs')] });\n }\n\n /** Run a command (or `&&`-joined list of commands) as a build step. */\n runCmd(command: string | string[]): DockerTemplate {\n return this.#append({ method: 'runCmd', args: [validateStringOrStrings(command, 'command')] });\n }\n\n /**\n * Run a command that needs build-time secrets, without persisting them.\n *\n * The command runs in a throwaway build stage forked from the template as it\n * stands at that point, so earlier WORKDIR/ENV/installs apply and later\n * steps see the copied `output`. The named secrets are resolved when\n * `build()` runs — from `build({ secrets })`, then the template's `secrets`\n * option, then `process.env` — and exposed to the command as environment\n * variables. Values reach the daemon through a BuildKit secret mount\n * (`RUN --mount=type=secret`), which is tmpfs-backed and scoped to that one\n * RUN — never a build arg, layer, history entry, or cache metadata. Only\n * `output` is copied into the template image. Builds that use secrets\n * require a BuildKit-capable daemon (Docker 20.10+).\n */\n runWithSecrets(command: string | string[], options: RunWithSecretsOptions): DockerTemplate {\n if (!Array.isArray(options.secrets)) throw new TypeError('secrets must be an array of strings');\n if (options.secrets.length > MAX_COLLECTION_ITEMS) {\n throw new RangeError(`secrets cannot contain more than ${MAX_COLLECTION_ITEMS} items`);\n }\n const secrets = options.secrets.map(name => {\n if (typeof name !== 'string' || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {\n throw new TypeError(`secrets must be environment variable names, got ${JSON.stringify(name)}`);\n }\n return name;\n });\n const output = validateString(options.output, 'output');\n if (!output.startsWith('/')) throw new TypeError('output must be an absolute path');\n return this.#append({\n method: 'runWithSecrets',\n args: [validateStringOrStrings(command, 'command'), { secrets, output }],\n });\n }\n\n /** Install apt packages. */\n aptInstall(packages: string | string[], options?: AptInstallOptions): DockerTemplate {\n return this.#append({ method: 'aptInstall', args: [validateStringOrStrings(packages, 'packages'), options] });\n }\n\n /** Install pip packages (or `pip install .` for the current workdir when omitted). */\n pipInstall(packages?: string | string[], options?: PipInstallOptions): DockerTemplate {\n const validated = packages === undefined ? undefined : validateStringOrStrings(packages, 'packages');\n return this.#append({ method: 'pipInstall', args: [validated, options] });\n }\n\n /** Install npm packages (or run `npm install` for the current workdir when omitted). */\n npmInstall(packages?: string | string[], options?: NpmInstallOptions): DockerTemplate {\n const validated = packages === undefined ? undefined : validateStringOrStrings(packages, 'packages');\n return this.#append({ method: 'npmInstall', args: [validated, options] });\n }\n\n /** The resolved definition (base image + ordered operations). */\n get definition(): DockerTemplateDefinition {\n return { baseImage: this.#baseImage, operations: this.#operations };\n }\n\n /** The synthesized Dockerfile for this template. */\n get dockerfile(): string {\n return synthesizeDockerfile(this.definition);\n }\n\n /** The content-addressed local image tag this template resolves to. */\n get templateId(): string {\n return templateImageTag(this.definition);\n }\n\n /**\n * The working directory the built image ends up with, i.e. the last\n * `setWorkdir` in the chain (resolved against earlier ones when relative).\n * `undefined` when the template never sets one, in which case the base\n * image's `WORKDIR` (or the sandbox default) applies.\n */\n get workdir(): string | undefined {\n let current: string | undefined;\n for (const op of this.#operations) {\n if (op.method !== 'setWorkdir') continue;\n const next = op.args[0];\n current = next.startsWith('/') || current === undefined ? next : posixPath.join(current, next);\n }\n return current;\n }\n\n #getDocker(): Docker {\n if (!this.#docker) {\n this.#docker = new Docker(this.#dockerOptions);\n }\n return this.#docker;\n }\n\n /**\n * Build (or reuse) the template's image. Idempotent: if an image with the\n * computed tag already exists locally and `force` is not set, returns\n * `ready` without rebuilding. Otherwise synthesizes a Dockerfile, runs\n * `docker build`, and surfaces any build-step failure as `status: 'failed'`.\n *\n * @throws if a secret named by `runWithSecrets` cannot be resolved from\n * `options.secrets`, the template's `secrets` option, or `process.env`.\n */\n async build(options: DockerTemplateBuildOptions = {}): Promise<DockerTemplateBuildResult> {\n throwIfAborted(options.abortSignal, 'build Docker template');\n // Many sandboxes starting concurrently from one template must share a\n // single `docker build` rather than racing to build the same tag. Only a\n // plain request may join an in-flight build; a forced build, different\n // secrets, or a different daemon is queued behind it instead.\n const isPlain = !options.force && options.secrets === undefined && options.docker === undefined;\n if (isPlain && this.#plainBuild) return this.#waitForBuild(this.#plainBuild, options.abortSignal);\n\n const previous = this.#queueTail?.promise.catch(() => undefined) ?? Promise.resolve();\n const controller = new AbortController();\n const run: InFlightBuild = {\n controller,\n waiters: 0,\n promise: previous.then(() => {\n throwIfAborted(controller.signal, 'build Docker template');\n return this.#build({ ...options, abortSignal: controller.signal });\n }),\n };\n this.#queueTail = run;\n if (isPlain) this.#plainBuild = run;\n run.promise\n .finally(() => {\n if (this.#queueTail === run) this.#queueTail = undefined;\n if (this.#plainBuild === run) this.#plainBuild = undefined;\n })\n .catch(() => undefined);\n return this.#waitForBuild(run, options.abortSignal);\n }\n\n #waitForBuild(run: InFlightBuild, abortSignal: AbortSignal | undefined): Promise<DockerTemplateBuildResult> {\n run.waiters += 1;\n let settled = false;\n const release = (aborted: boolean) => {\n if (settled) return;\n settled = true;\n run.waiters -= 1;\n if (aborted && run.waiters === 0) run.controller.abort();\n };\n return waitForAbortable(run.promise, abortSignal, 'build Docker template', () => release(true)).finally(() =>\n release(false),\n );\n }\n\n async #build(options: DockerTemplateBuildOptions): Promise<DockerTemplateBuildResult> {\n const docker = options.docker ?? this.#getDocker();\n const tag = this.templateId;\n const { abortSignal } = options;\n throwIfAborted(abortSignal, 'build Docker template');\n\n if (!options.force) {\n try {\n await docker.getImage(tag).inspect();\n throwIfAborted(abortSignal, 'build Docker template');\n this.#built = true;\n return { status: 'ready', templateId: tag };\n } catch (error) {\n if (!isImageNotFoundError(error)) throw error;\n }\n }\n\n // Only a real build needs the secret values; reusing a cached image must not\n // require the original credentials to still be present.\n const secrets = await this.#resolveSecrets(options.secrets);\n throwIfAborted(abortSignal, 'build Docker template');\n\n const context = tarPack();\n context.entry({ name: 'Dockerfile' }, this.dockerfile);\n context.finalize();\n\n try {\n const nocache = options.force === true;\n if (secrets) {\n const { stream, session } = await this.#buildWithSecrets(docker, context, tag, secrets, nocache, abortSignal);\n try {\n await this.#followBuild(docker, stream, abortSignal);\n } finally {\n // The daemon calls GetSecret only while the build runs; drop the\n // session however the output stream settled (end, error, or close).\n session.close();\n }\n } else {\n const build = docker.buildImage(context, { t: tag, nocache }).then(stream => {\n if (abortSignal?.aborted) {\n (stream as NodeJS.ReadableStream & { destroy?(error?: Error): void }).destroy?.();\n throw createAbortError(abortSignal, 'build Docker template');\n }\n return stream;\n });\n const stream = await waitForAbortable(build, abortSignal, 'build Docker template', () => {\n (context as NodeJS.ReadableStream & { destroy?(error?: Error): void }).destroy?.();\n });\n await this.#followBuild(docker, stream, abortSignal);\n }\n } catch (error) {\n this.#built = false;\n if (abortSignal?.aborted) throw normalizeAbortError(error, 'build Docker template');\n return { status: 'failed', templateId: tag, error: error instanceof Error ? error.message : String(error) };\n }\n\n this.#built = true;\n return { status: 'ready', templateId: tag };\n }\n\n async #resolveSecrets(override: DockerTemplateSecrets | undefined): Promise<Record<string, string> | undefined> {\n const names = secretNames(this.definition);\n if (names.length === 0) return undefined;\n const fromBuild = await readSecrets(override);\n const fromTemplate = await readSecrets(this.#secrets);\n const resolved: Record<string, string> = {};\n for (const name of names) {\n const value = fromBuild[name] ?? fromTemplate[name] ?? process.env[name];\n if (value === undefined) {\n throw new Error(\n `Docker template secret ${name} was not provided (secrets option) and is not set in the environment`,\n );\n }\n resolved[name] = value;\n }\n return resolved;\n }\n\n /**\n * BuildKit build with a session serving the secret mounts. Dials `/build`\n * directly because `docker.buildImage` replaces any session id with its own\n * auth-only session when `version` is `'2'`.\n */\n async #buildWithSecrets(\n docker: Docker,\n context: NodeJS.ReadableStream,\n tag: string,\n secrets: Record<string, string>,\n nocache: boolean,\n abortSignal?: AbortSignal,\n ): Promise<{ stream: NodeJS.ReadableStream; session: BuildSession }> {\n throwIfAborted(abortSignal, 'build Docker template');\n const session = await openBuildSession(docker, secrets, abortSignal);\n let stream: NodeJS.ReadableStream;\n try {\n stream = await new Promise<NodeJS.ReadableStream>((resolve, reject) => {\n let settled = false;\n let request: { destroy?(error?: Error): void } | undefined;\n const finish = (error?: unknown, data?: unknown) => {\n if (settled) {\n if (data) (data as NodeJS.ReadableStream & { destroy?(error?: Error): void }).destroy?.();\n return;\n }\n settled = true;\n abortSignal?.removeEventListener('abort', abort);\n error === undefined ? resolve(data as NodeJS.ReadableStream) : reject(error);\n };\n const abort = () => {\n (context as NodeJS.ReadableStream & { destroy?(error?: Error): void }).destroy?.();\n request?.destroy?.();\n session.close();\n if (abortSignal) finish(createAbortError(abortSignal, 'build Docker template'));\n };\n abortSignal?.addEventListener('abort', abort, { once: true });\n if (abortSignal?.aborted) {\n abort();\n return;\n }\n request = docker.modem.dial(\n {\n path: '/build?',\n method: 'POST',\n file: context,\n options: { t: tag, version: '2', session: session.id, nocache },\n isStream: true,\n statusCodes: { 200: true, 500: 'server error' },\n },\n (err: Error | null, data: unknown) => finish(err ?? undefined, data),\n ) as unknown as { destroy?(error?: Error): void } | undefined;\n });\n } catch (error) {\n session.close();\n throw error;\n }\n return { stream, session };\n }\n\n #followBuild(docker: Docker, stream: NodeJS.ReadableStream, abortSignal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n let settled = false;\n const finish = (error?: unknown) => {\n if (settled) return;\n settled = true;\n abortSignal?.removeEventListener('abort', abort);\n error === undefined ? resolve() : reject(error);\n };\n const abort = () => {\n (stream as NodeJS.ReadableStream & { destroy?(error?: Error): void }).destroy?.();\n if (abortSignal) finish(createAbortError(abortSignal, 'build Docker template'));\n };\n abortSignal?.addEventListener('abort', abort, { once: true });\n if (abortSignal?.aborted) {\n abort();\n return;\n }\n docker.modem.followProgress(stream, (err: Error | null, output: Array<Record<string, unknown>>) => {\n if (err) {\n finish(err);\n return;\n }\n const failure = output?.find(entry => entry && (entry.error !== undefined || entry.errorDetail !== undefined));\n if (failure) {\n const detail = failure.errorDetail as { message?: string } | undefined;\n finish(new Error(String(detail?.message ?? failure.error ?? 'docker build failed')));\n return;\n }\n finish();\n });\n });\n }\n\n /**\n * Create a `DockerSandbox` bound to the built image. Lazily builds the\n * template if it has not been built yet. Each call returns a fresh sandbox\n * with an independent writable layer. Invocation-specific `env`/config passed\n * via `options` reaches only the container and is never baked into the image.\n *\n * The sandbox's working directory follows the template's last `setWorkdir`\n * unless `options.workingDirectory` overrides it, so relative paths resolve\n * against the same directory the image was prepared in.\n *\n * @throws if the (lazy) build fails.\n */\n async createSandbox(options: Omit<DockerSandboxOptions, 'image' | 'template'> = {}): Promise<DockerSandbox> {\n if (!this.#built) {\n const result = await this.build();\n if (result.status !== 'ready') {\n throw new Error(`Docker template build failed: ${result.error ?? 'unknown error'}`);\n }\n }\n // Same wiring as `new DockerSandbox({ template })`; the build above just\n // surfaces failures here instead of at `start()`.\n const workingDirectory = options.workingDirectory ?? options.workingDir ?? this.workdir;\n return new DockerSandbox({\n ...options,\n ...(workingDirectory !== undefined && { workingDirectory }),\n template: this,\n dockerOptions: options.dockerOptions ?? this.#dockerOptions,\n });\n }\n\n /**\n * Remove the built image (`docker rmi`). Tolerant of an already-removed\n * image. Independent of any sandbox created from this template, but the\n * daemon refuses to remove an image that a container (running or stopped)\n * still references, so destroy those sandboxes first.\n */\n async dispose(): Promise<void> {\n const docker = this.#getDocker();\n try {\n await docker.getImage(this.templateId).remove();\n } catch (error) {\n if (!isImageNotFoundError(error)) throw error;\n }\n this.#built = false;\n }\n}\n\ninterface DockerTemplateState {\n baseImage: string;\n operations: readonly DockerTemplateOperation[];\n}\n\n// =============================================================================\n// Validation (mirrors platform template validation)\n// =============================================================================\n\nfunction validateString(value: unknown, name: string): string {\n if (typeof value !== 'string') throw new TypeError(`${name} must be a string`);\n if (value.length === 0) throw new TypeError(`${name} must not be empty`);\n if (value.length > MAX_STRING_LENGTH) {\n throw new RangeError(`${name} cannot exceed ${MAX_STRING_LENGTH} characters`);\n }\n return value;\n}\n\nfunction validateStringOrStrings(value: unknown, name: string): string | string[] {\n if (typeof value === 'string') return validateString(value, name);\n if (!Array.isArray(value)) throw new TypeError(`${name} must be a string or an array of strings`);\n if (value.length === 0) throw new TypeError(`${name} must not be empty`);\n if (value.length > MAX_COLLECTION_ITEMS) {\n throw new RangeError(`${name} cannot contain more than ${MAX_COLLECTION_ITEMS} items`);\n }\n return value.map((item, index) => validateString(item, `${name}[${index}]`));\n}\n\nfunction validateStringRecord(value: unknown, name: string): Record<string, string> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new TypeError(`${name} must be a plain object`);\n }\n const entries = Object.entries(value);\n if (entries.length > MAX_COLLECTION_ITEMS) {\n throw new RangeError(`${name} cannot contain more than ${MAX_COLLECTION_ITEMS} items`);\n }\n return Object.fromEntries(\n entries.map(([key, item]) => {\n if (typeof item !== 'string') throw new TypeError(`${name}.${key} must be a string`);\n return [validateString(key, `${name} key`), item];\n }),\n );\n}\n\nasync function readSecrets(source: DockerTemplateSecrets | undefined): Promise<Record<string, string>> {\n if (!source) return {};\n return typeof source === 'function' ? await source() : source;\n}\n\nfunction isImageNotFoundError(error: unknown): boolean {\n if (error instanceof Error) {\n const msg = error.message.toLowerCase();\n return msg.includes('no such image') || msg.includes('404');\n }\n return false;\n}\n","import { createHash } from \"crypto\";\n//#region src/setup-marker.ts\n/**\n* Setup completion marker shared by repo templates and their consumers.\n*\n* A repo template writes this file beside the checkout as its last build\n* step, so it exists only in images where every setup command succeeded. Its\n* content is a digest of the setup commands the image ran, letting a sandbox\n* booted from the image tell whether the setup it is about to run already\n* happened. Relative to the template's build cwd, which is also the runtime\n* working directory the repo was cloned into.\n*/\nconst SETUP_MARKER_PATH = \".mastra-sandbox/setup\";\n/** Blank entries never become build steps, so they never count toward the digest either. */\nfunction normalizeSetupCommands(setupCommand) {\n\treturn (setupCommand === void 0 ? [] : Array.isArray(setupCommand) ? setupCommand : [setupCommand]).filter((command) => command.trim() !== \"\");\n}\n/** The marker content for a setup command list: `sha256:<hex>` over the commands joined by newlines. */\nfunction setupMarkerContent(setupCommand) {\n\treturn `sha256:${createHash(\"sha256\").update(normalizeSetupCommands(setupCommand).join(\"\\n\")).digest(\"hex\")}`;\n}\n/** Shell step that writes the marker relative to the cwd. `content` is a digest, so it is shell-safe. */\nfunction setupMarkerCommand(content) {\n\treturn `mkdir -p \"$(dirname \"${SETUP_MARKER_PATH}\")\" && printf '%s' '${content}' > \"${SETUP_MARKER_PATH}\"`;\n}\n//#endregion\n//#region src/repo-clone.ts\nfunction repoCloneCommand({ cloneUrl, destination, branch, tokenEnv }) {\n\treturn `git ${tokenEnv ? `${gitAuthFlag(tokenEnv)} ` : \"\"}clone --depth=1 --single-branch ${branch ? `--branch ${shellQuote(branch)} ` : \"\"}${shellQuote(cloneUrl)} ${shellQuote(destination)}`;\n}\n/** Per-invocation auth header; `-c` config never reaches `.git/config`. */\nfunction gitAuthFlag(tokenEnv) {\n\treturn `-c http.extraheader=\"AUTHORIZATION: basic $(printf 'x-access-token:%s' \"$${tokenEnv}\" | base64 -w0)\"`;\n}\nfunction shellQuote(value) {\n\treturn `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n//#endregion\nexport { SETUP_MARKER_PATH, normalizeSetupCommands, repoCloneCommand, setupMarkerCommand, setupMarkerContent };\n\n//# sourceMappingURL=index.js.map","/**\n * createDockerRepoTemplate — a repo checkout plus setup commands as a\n * reusable, content-addressed local image, with the same contract as the\n * E2B and platform repo templates (`getRepositoryAccess`, `setupCommand`,\n * `buildEnv`, `workingDirectory`).\n *\n * Returns a template RESOLVER for `DockerSandbox`'s `template` option rather\n * than a fixed template: each resolution calls `getRepositoryAccess`, looks up\n * the current head of `ref` (`git ls-remote`, no clone) and pins that sha into\n * the template identity. A moved branch therefore yields a fresh image on the\n * next new sandbox, and an unmoved one reuses the cached image. When the head\n * cannot be resolved the resolver rejects: an unpinned clone cached under a\n * stable tag would otherwise serve stale repository state forever.\n *\n * The clone runs in a throwaway build stage; the credential is passed by value\n * to that stage only and never enters the template identity or the image.\n *\n * @example\n * ```typescript\n * const sandbox = new DockerSandbox({\n * template: createDockerRepoTemplate({\n * getRepositoryAccess: async () => ({ cloneUrl: 'https://github.com/acme/app.git' }),\n * setupCommand: ['npm ci', 'npm run build'],\n * }),\n * });\n * ```\n */\n\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { normalizeSetupCommands, setupMarkerCommand, setupMarkerContent } from '@internal/workspace';\nimport type { DockerOptions } from 'dockerode';\nimport { normalizeAbortError, throwIfAborted } from '../abort';\nimport { DockerTemplate } from './template';\n\nconst execFileAsync = promisify(execFile);\n\n/** Env var the build's clone reads the credential from (see `cloneFull`). */\nconst BUILD_TOKEN_ENV = 'GH_TOKEN';\nconst DEFAULT_BASE_IMAGE = 'node:22-slim';\nconst DEFAULT_WORKING_DIRECTORY = '/workspace';\n// Only a full sha is unambiguous; a short hex string may be a branch or tag.\nconst FULL_SHA_PATTERN = /^[0-9a-f]{40}$/i;\nconst SHA_PATTERN = /^[0-9a-f]{40}$/i;\n\nconst CLONE_URL_ALLOWED_CHARS = /^[a-z0-9:/._-]+$/i;\nconst CLONE_URL_HOST_PATTERN = /^[a-z0-9.-]+$/i;\nconst CLONE_URL_SEGMENT_PATTERN = /^[\\w.-]+$/;\n/** Refs interpolate into shell too; git ref names are already restricted, so allowlist tightly. */\nconst REF_PATTERN = /^[\\w./-]+$/;\n\n/**\n * Repository clone target plus an optional credential. Structurally identical\n * to the E2B/platform type of the same name so a host can pass its context\n * accessor straight through.\n */\nexport interface RepositoryAccess {\n /** https clone URL, e.g. `https://github.com/acme/widgets.git`. */\n cloneUrl: string;\n /** Credential for private repositories; presented to git as `x-access-token:<token>` basic auth. */\n authorization?: { scheme: 'bearer'; token: string };\n}\n\nexport interface DockerRepoTemplateOptions {\n /**\n * Resolves the clone URL and, for private repositories, a short-lived\n * credential. Called once per template resolution (each container-creating\n * `start()`): the credential authenticates the head lookup and the build's\n * clone. It is passed to the build by value, never through `process.env`,\n * and is excluded from the template identity so rotation does not rebuild.\n *\n * Pass `undefined` for the function itself to mean \"no repository\":\n * {@link createDockerRepoTemplate} then returns undefined so\n * `template: createDockerRepoTemplate(ctx)` needs no conditional. If the\n * function resolves to `undefined` at start time, the resolver rejects.\n */\n getRepositoryAccess:\n | ((options?: DockerRepoTemplateResolveOptions) => Promise<RepositoryAccess | undefined>)\n | undefined;\n /**\n * Branch, tag, or commit to prepare. The current head of a branch/tag is\n * resolved at each template resolution and pinned into the identity.\n * @default the remote's default branch\n */\n ref?: string;\n /** Setup command(s) run inside the checkout as separate cached build steps. */\n setupCommand?: string | string[];\n /**\n * Extra environment for every build step, including `setupCommand`. Baked\n * into the image via `ENV` and hashed into the identity (keys and values),\n * so it must be non-secret; put rotating credentials in\n * {@link getRepositoryAccess} instead.\n */\n buildEnv?: Record<string, string> | ((options?: DockerRepoTemplateResolveOptions) => Promise<Record<string, string>>);\n /**\n * Absolute parent for the checkout; the repo lands at\n * `<workingDirectory>/<repo>`, which becomes the build and runtime cwd.\n * @default '/workspace'\n */\n workingDirectory?: string;\n /**\n * Base image. A custom base must provide `git` and `ca-certificates`; the\n * default has them apt-installed as the first (cached) layer.\n * @default 'node:22-slim'\n */\n baseImage?: string;\n /** Pass-through dockerode connection options. */\n dockerOptions?: DockerOptions;\n}\n\nexport interface DockerRepoTemplateResolveOptions {\n /** Cancel repository access, build-environment resolution, or head lookup. */\n abortSignal?: AbortSignal;\n}\n\n/** A resolver producing a fresh, head-pinned template on each call. */\nexport type DockerRepoTemplateResolver = (options?: DockerRepoTemplateResolveOptions) => Promise<DockerTemplate>;\n\nexport function createDockerRepoTemplate(options: DockerRepoTemplateOptions): DockerRepoTemplateResolver | undefined {\n if (!options.getRepositoryAccess) return undefined;\n if (options.ref !== undefined && !REF_PATTERN.test(options.ref)) {\n throw new Error(`Invalid ref '${options.ref}': expected a git ref name`);\n }\n const workingDirectory = trimTrailingSlashes(options.workingDirectory ?? DEFAULT_WORKING_DIRECTORY);\n if (!workingDirectory.startsWith('/')) {\n throw new Error(`workingDirectory must be an absolute path, got '${options.workingDirectory}'`);\n }\n return resolveOptions => resolveRepoTemplate(options, workingDirectory, resolveOptions);\n}\n\nasync function resolveRepoTemplate(\n options: DockerRepoTemplateOptions,\n workingDirectory: string,\n resolveOptions: DockerRepoTemplateResolveOptions = {},\n): Promise<DockerTemplate> {\n const { abortSignal } = resolveOptions;\n throwIfAborted(abortSignal, 'resolve Docker repository template');\n let access: RepositoryAccess | undefined;\n try {\n access = await options.getRepositoryAccess!(resolveOptions);\n } catch (error) {\n throw normalizeAbortError(error, 'resolve Docker repository template');\n }\n throwIfAborted(abortSignal, 'resolve Docker repository template');\n const cloneUrl = access?.cloneUrl;\n if (!cloneUrl) {\n throw new Error('Repo template has no clone URL: repository access returned none.');\n }\n assertCloneUrl(cloneUrl);\n const token = access?.authorization?.token;\n let buildEnv: Record<string, string> | undefined;\n try {\n buildEnv = typeof options.buildEnv === 'function' ? await options.buildEnv(resolveOptions) : options.buildEnv;\n } catch (error) {\n throw normalizeAbortError(error, 'resolve Docker repository template');\n }\n throwIfAborted(abortSignal, 'resolve Docker repository template');\n const sha = await resolveHead(cloneUrl, options.ref, token, abortSignal);\n throwIfAborted(abortSignal, 'resolve Docker repository template');\n if (!sha) {\n throw new Error(\n `Could not resolve ${options.ref ?? 'HEAD'} of ${cloneUrl} with git ls-remote; check the ref, the credential and network access`,\n );\n }\n\n return buildRepoTemplate({\n cloneUrl,\n sha,\n token,\n buildEnv,\n setupCommand: options.setupCommand,\n workingDirectory,\n baseImage: options.baseImage,\n dockerOptions: options.dockerOptions,\n });\n}\n\ninterface RepoTemplateInputs {\n cloneUrl: string;\n sha: string;\n token?: string;\n buildEnv?: Record<string, string>;\n setupCommand?: string | string[];\n workingDirectory: string;\n baseImage?: string;\n dockerOptions?: DockerOptions;\n}\n\n/**\n * Pure assembly of the template from already-resolved inputs. Exported for\n * tests so the Dockerfile can be asserted without a network head lookup.\n * @internal\n */\nexport function buildRepoTemplate(inputs: RepoTemplateInputs): DockerTemplate {\n const { cloneUrl, sha, token, buildEnv } = inputs;\n const destination = `${trimTrailingSlashes(inputs.workingDirectory)}/${repoDirName(cloneUrl)}`;\n\n let template = new DockerTemplate({\n baseImage: inputs.baseImage ?? DEFAULT_BASE_IMAGE,\n dockerOptions: inputs.dockerOptions,\n ...(token ? { secrets: { [BUILD_TOKEN_ENV]: token } } : {}),\n });\n\n if (inputs.baseImage === undefined) {\n // The slim default ships without git; a custom base is expected to bring its own.\n template = template.aptInstall(['git', 'ca-certificates']);\n }\n\n if (buildEnv && Object.keys(buildEnv).length > 0) {\n template = template.setEnvs(buildEnv);\n }\n\n const tokenEnv = token ? BUILD_TOKEN_ENV : undefined;\n const clone = [\n // Full clone so an arbitrary commit is reachable, then pin to it. The\n // sha is in the command, so it is part of the template identity.\n cloneFull({ cloneUrl, destination, tokenEnv }),\n `git -C ${shellQuote(destination)} checkout --detach ${shellQuote(sha)}`,\n ];\n\n template = template\n .runWithSecrets(clone, { secrets: tokenEnv ? [tokenEnv] : [], output: destination })\n .setWorkdir(destination);\n\n const setupCommands = normalizeSetupCommands(inputs.setupCommand);\n for (const command of setupCommands) {\n template = template.runCmd(command);\n }\n if (setupCommands.length > 0) {\n // Written last, so the marker exists only when every setup step succeeded.\n template = template.runCmd(setupMarkerCommand(setupMarkerContent(setupCommands)));\n }\n return template;\n}\n\n/**\n * Resolve `ref` (or the default branch) to a commit sha with `git ls-remote`\n * on the host, without cloning. A full sha is returned as is. Any failure\n * yields undefined; the caller decides how to surface it.\n * @internal exported for tests.\n */\nexport async function resolveHead(\n cloneUrl: string,\n ref: string | undefined,\n token: string | undefined,\n abortSignal?: AbortSignal,\n): Promise<string | undefined> {\n throwIfAborted(abortSignal, 'resolve Docker repository template');\n if (ref && FULL_SHA_PATTERN.test(ref)) return ref.toLowerCase();\n try {\n // The credential goes through GIT_CONFIG_* (git >= 2.31) rather than `-c`\n // so it never appears in the process argv, which other local users can read.\n const authEnv = token\n ? {\n GIT_CONFIG_COUNT: '1',\n GIT_CONFIG_KEY_0: 'http.extraheader',\n GIT_CONFIG_VALUE_0: `AUTHORIZATION: basic ${Buffer.from(`x-access-token:${token}`).toString('base64')}`,\n }\n : {};\n // `--` keeps even a hostile URL from being read as an option.\n const { stdout } = await execFileAsync('git', ['ls-remote', '--', cloneUrl, ref ?? 'HEAD'], {\n timeout: 10_000,\n signal: abortSignal,\n env: { ...process.env, ...authEnv, GIT_TERMINAL_PROMPT: '0' },\n });\n // Prefer the peeled tag object (`refs/tags/x^{}`) when present.\n const lines = stdout\n .split('\\n')\n .filter(Boolean)\n .map(line => line.split('\\t'));\n const peeled = lines.find(([, name]) => name?.endsWith('^{}'));\n const sha = (peeled ?? lines[0])?.[0]?.trim();\n return sha && SHA_PATTERN.test(sha) ? sha.toLowerCase() : undefined;\n } catch (error) {\n if (abortSignal?.aborted) throw normalizeAbortError(error, 'resolve Docker repository template');\n return undefined;\n }\n}\n\nfunction cloneFull({ cloneUrl, destination, tokenEnv }: { cloneUrl: string; destination: string; tokenEnv?: string }) {\n // Mirrors `repoCloneCommand` from @internal/workspace, minus the shallow flags.\n const auth = tokenEnv\n ? `-c http.extraheader=\"AUTHORIZATION: basic $(printf 'x-access-token:%s' \"$${tokenEnv}\" | base64 -w0)\" `\n : '';\n return `git ${auth}clone ${shellQuote(cloneUrl)} ${shellQuote(destination)}`;\n}\n\nfunction assertCloneUrl(cloneUrl: string): void {\n if (cloneUrl.length > 2048 || !CLONE_URL_ALLOWED_CHARS.test(cloneUrl)) {\n throw new Error(`Invalid cloneUrl '${cloneUrl}': expected an https URL with a plain host and path`);\n }\n let url: URL;\n try {\n url = new URL(cloneUrl);\n } catch {\n throw new Error(`Invalid cloneUrl '${cloneUrl}': not a URL`);\n }\n const segments = url.pathname.split('/').slice(1);\n const ok =\n url.protocol === 'https:' &&\n !url.username &&\n !url.password &&\n !url.search &&\n !url.hash &&\n CLONE_URL_HOST_PATTERN.test(url.hostname) &&\n segments.length > 0 &&\n segments.every(segment => CLONE_URL_SEGMENT_PATTERN.test(segment));\n if (!ok) {\n throw new Error(`Invalid cloneUrl '${cloneUrl}': expected an https URL such as https://host/owner/repo.git`);\n }\n}\n\nfunction repoDirName(cloneUrl: string): string {\n const last = trimTrailingSlashes(cloneUrl).split('/').at(-1) ?? '';\n return (\n last\n .replace(/\\.git$/i, '')\n .replace(/[^\\w.-]/g, '-')\n .replace(/^\\.+/, '') || 'repo'\n );\n}\n\nfunction trimTrailingSlashes(path: string): string {\n let end = path.length;\n while (end > 1 && path[end - 1] === '/') end--;\n return path.slice(0, end);\n}\n\nfunction shellQuote(value: string): string {\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n"],"mappings":"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"}
|