@anvia/sandbox 1.1.4 → 1.1.5

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 CHANGED
@@ -32,6 +32,11 @@ Networking is explicit. Use `{ mode: "none" }` or `{ mode: "bridge", ports: [...
32
32
  bind only to `127.0.0.1`. Runtime methods use object arguments, propagate abort signals, and expose
33
33
  command and process output as bytes. Tool wrappers decode UTF-8 strictly and return structured values.
34
34
 
35
+ File paths and command working directories passed to agent tools may be workspace-relative (for
36
+ example `notes/result.txt`) or absolute paths inside the sandbox workdir (for example
37
+ `/workspace/notes/result.txt` with the default workdir). Paths outside the sandbox workdir are
38
+ rejected.
39
+
35
40
  With `exec.commands.mode: "allow"`, both `exec_command` and `start_process` reject known shell
36
41
  executables by default, including path-qualified names such as `/bin/sh`. To permit an allowlisted
37
42
  shell, set `exec.commands.allowShellInterpreters` to the boolean `true`. Omitted or `false` keeps the
package/dist/cli.d.ts CHANGED
@@ -58,5 +58,6 @@ interface SandboxImageCliDependencies {
58
58
  }) => Promise<void>;
59
59
  }
60
60
  declare function runCli(argv?: string[], cwd?: string, io?: SandboxImageCliIo, dependencies?: SandboxImageCliDependencies): Promise<number>;
61
+ declare function isCliEntryPoint(moduleUrl: string, invokedPath: string | undefined): boolean;
61
62
 
62
- export { type SandboxImageCliDependencies, type SandboxImageCliIo, type SandboxImagePromptResult, runCli };
63
+ export { type SandboxImageCliDependencies, type SandboxImageCliIo, type SandboxImagePromptResult, isCliEntryPoint, runCli };
package/dist/cli.js CHANGED
@@ -4,6 +4,7 @@ import {
4
4
  } from "./chunk-D5XZQ2ES.js";
5
5
 
6
6
  // src/cli.ts
7
+ import { realpathSync } from "fs";
7
8
  import { lstat, mkdir, readFile, rm, writeFile } from "fs/promises";
8
9
  import path from "path";
9
10
  import { fileURLToPath } from "url";
@@ -831,13 +832,21 @@ Examples:
831
832
  pnpm dlx @anvia/sandbox create-image --name reports --feature artifacts
832
833
  pnpm dlx @anvia/sandbox create-image --name browser --runtime bun --feature playwright`;
833
834
  }
834
- var invokedPath = process.argv[1] === void 0 ? void 0 : path.resolve(process.argv[1]);
835
- if (invokedPath !== void 0 && invokedPath === fileURLToPath(import.meta.url)) {
835
+ function isCliEntryPoint(moduleUrl, invokedPath) {
836
+ if (invokedPath === void 0) return false;
837
+ try {
838
+ return realpathSync(path.resolve(invokedPath)) === realpathSync(fileURLToPath(moduleUrl));
839
+ } catch {
840
+ return false;
841
+ }
842
+ }
843
+ if (isCliEntryPoint(import.meta.url, process.argv[1])) {
836
844
  runCli().then((code) => {
837
845
  process.exitCode = code;
838
846
  });
839
847
  }
840
848
  export {
849
+ isCliEntryPoint,
841
850
  runCli
842
851
  };
843
852
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/image-builder.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { lstat, mkdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { assertDockerCli } from \"./docker-cli\";\nimport {\n renderSandboxImageContext,\n resolveSandboxImageSpec,\n type SandboxImageFeature,\n type SandboxImageInput,\n type SandboxImageManifest,\n type SandboxImageRuntime,\n type SandboxImageVersions,\n unpinnedSandboxImagePackages,\n} from \"./image-builder\";\n\ninterface CliOptions {\n command?: string;\n name?: string;\n tag?: string;\n output?: string;\n runtimes: SandboxImageRuntime[];\n features: SandboxImageFeature[];\n apt: string[];\n npm: string[];\n uv: string[];\n versions: Partial<SandboxImageVersions>;\n dockerPath: string;\n build: boolean;\n buildExplicit: boolean;\n dryRun: boolean;\n force: boolean;\n help: boolean;\n}\n\nexport interface SandboxImageCliIo {\n log(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n stdout(chunk: Uint8Array): void;\n stderr(chunk: Uint8Array): void;\n}\n\nexport interface SandboxImagePromptResult {\n name: string;\n runtimes: SandboxImageRuntime[];\n features: SandboxImageFeature[];\n apt: string[];\n npm: string[];\n uv: string[];\n tag?: string;\n output?: string;\n build: boolean;\n}\n\nexport interface SandboxImageCliDependencies {\n isTTY?: boolean;\n packageVersion?: string;\n prompt?: (options: Readonly<CliOptions>) => Promise<SandboxImagePromptResult | undefined>;\n buildImage?: (input: {\n contextPath: string;\n tag: string;\n dockerPath: string;\n io: SandboxImageCliIo;\n }) => Promise<void>;\n}\n\nconst generatedFileNames = new Set([\n \".dockerignore\",\n \"Dockerfile\",\n \"anvia-sandbox.json\",\n \"package.json\",\n \"pyproject.toml\",\n]);\n\nconst commonAptPackages = [\n { value: \"git\", label: \"Git\", hint: \"Source control and repository operations\" },\n { value: \"curl\", label: \"curl\", hint: \"HTTP downloads and API debugging\" },\n { value: \"jq\", label: \"jq\", hint: \"JSON processing from the shell\" },\n { value: \"ffmpeg\", label: \"FFmpeg\", hint: \"Audio and video processing\" },\n { value: \"imagemagick\", label: \"ImageMagick\", hint: \"Image conversion and editing\" },\n { value: \"poppler-utils\", label: \"Poppler tools\", hint: \"PDF inspection and conversion\" },\n { value: \"libreoffice\", label: \"LibreOffice\", hint: \"Large; office document conversion\" },\n] as const;\n\nconst commonNpmPackages = [\n { value: \"pdfkit@0.19.1\", label: \"PDFKit\", hint: \"Generate PDF documents\" },\n { value: \"sharp@0.35.3\", label: \"Sharp\", hint: \"Resize and transform images\" },\n { value: \"exceljs@4.4.0\", label: \"ExcelJS\", hint: \"Read and write Excel workbooks\" },\n { value: \"docx@9.7.1\", label: \"docx\", hint: \"Generate Word documents\" },\n { value: \"pptxgenjs@4.0.1\", label: \"PptxGenJS\", hint: \"Generate PowerPoint presentations\" },\n] as const;\n\nconst commonUvPackages = [\n { value: \"httpx==0.28.1\", label: \"HTTPX\", hint: \"Modern HTTP client\" },\n { value: \"beautifulsoup4==4.15.0\", label: \"Beautiful Soup\", hint: \"HTML and XML parsing\" },\n { value: \"scipy==1.18.0\", label: \"SciPy\", hint: \"Scientific computing\" },\n { value: \"scikit-learn==1.9.0\", label: \"scikit-learn\", hint: \"Machine learning utilities\" },\n { value: \"polars==1.42.1\", label: \"Polars\", hint: \"Fast dataframe processing\" },\n] as const;\n\nconst defaultIo: SandboxImageCliIo = {\n log: console.log,\n warn: console.warn,\n error: console.error,\n stdout: (chunk) => process.stdout.write(chunk),\n stderr: (chunk) => process.stderr.write(chunk),\n};\n\nexport async function runCli(\n argv: string[] = process.argv.slice(2),\n cwd = process.cwd(),\n io: SandboxImageCliIo = defaultIo,\n dependencies: SandboxImageCliDependencies = {},\n): Promise<number> {\n let options: CliOptions;\n try {\n options = parseArgs(argv);\n } catch (error) {\n io.error(errorMessage(error));\n io.log(helpText());\n return 1;\n }\n\n if (options.help || options.command === undefined) {\n io.log(helpText());\n return 0;\n }\n if (options.command !== \"create-image\") {\n io.error(`Unknown command: ${options.command}`);\n io.log(helpText());\n return 1;\n }\n\n try {\n const shouldPrompt =\n options.name === undefined ||\n (options.runtimes.length === 0 &&\n options.features.length === 0 &&\n options.npm.length === 0 &&\n options.uv.length === 0);\n if (shouldPrompt) {\n const isTTY = dependencies.isTTY ?? (process.stdin.isTTY && process.stdout.isTTY);\n if (!isTTY) {\n throw new Error(\n \"Non-interactive create-image requires --name and at least one --runtime or --feature.\",\n );\n }\n const prompt = dependencies.prompt ?? promptForImage;\n const result = await prompt(options);\n if (result === undefined) return 130;\n options = applyPromptResult(options, result);\n }\n\n const input: SandboxImageInput = {\n name: required(options.name, \"Image name is required.\"),\n runtimes: options.runtimes,\n features: options.features,\n packages: {\n apt: options.apt,\n npm: options.npm,\n uv: options.uv,\n },\n versions: options.versions,\n };\n if (options.tag !== undefined) input.tag = options.tag;\n\n const spec = resolveSandboxImageSpec(input);\n const packageVersion = dependencies.packageVersion ?? (await readPackageVersion());\n const context = renderSandboxImageContext(spec, packageVersion);\n const outputPath = path.resolve(\n cwd,\n options.output ?? path.join(\".anvia\", \"sandbox-images\", spec.name),\n );\n const displayPath = relativeDisplayPath(cwd, outputPath);\n const unpinned = unpinnedSandboxImagePackages(spec);\n if (unpinned.length > 0) {\n io.warn(`Unpinned custom packages may change on rebuild: ${unpinned.join(\", \")}`);\n }\n\n if (options.dryRun) {\n printDryRun(context.files, displayPath, spec.tag, io);\n return 0;\n }\n\n await writeImageContext(outputPath, context.manifest, context.files, options.force);\n io.log(`Created ${displayPath}`);\n\n if (!options.build) {\n io.log(\"\");\n io.log(\"Build later:\");\n io.log(` ${shellCommand([options.dockerPath, \"build\", \"--tag\", spec.tag, displayPath])}`);\n printUsageSnippet(spec.tag, io);\n return 0;\n }\n\n const buildImage = dependencies.buildImage ?? buildDockerImage;\n await buildImage({\n contextPath: outputPath,\n tag: spec.tag,\n dockerPath: options.dockerPath,\n io,\n });\n io.log(`Built ${spec.tag}`);\n printUsageSnippet(spec.tag, io);\n return 0;\n } catch (error) {\n io.error(errorMessage(error));\n return 1;\n }\n}\n\nasync function promptForImage(\n options: Readonly<CliOptions>,\n): Promise<SandboxImagePromptResult | undefined> {\n assertInteractiveNodeVersion();\n const prompts = await import(\"@clack/prompts\");\n prompts.intro(\"Create an Anvia sandbox image\");\n\n const nameResult =\n options.name ??\n (await prompts.text({\n message: \"Image name\",\n placeholder: \"reports\",\n validate: (value) =>\n /^[a-z0-9][a-z0-9-]{0,62}$/.test(value ?? \"\")\n ? undefined\n : \"Use 1-63 lowercase letters, numbers, or hyphens.\",\n }));\n if (prompts.isCancel(nameResult)) return cancelPrompt(prompts);\n const name = promptString(nameResult, \"Image name\");\n\n let runtimes = [...options.runtimes];\n let features = [...options.features];\n if (\n runtimes.length === 0 &&\n features.length === 0 &&\n options.npm.length === 0 &&\n options.uv.length === 0\n ) {\n const capabilities = await prompts.multiselect<SandboxImageRuntime | SandboxImageFeature>({\n message: \"Select runtimes and features\",\n required: true,\n options: [\n { value: \"node\", label: \"Node.js\", hint: \"Includes npm and pnpm\" },\n { value: \"bun\", label: \"Bun\", hint: \"Includes bun and bunx\" },\n { value: \"python\", label: \"Python\", hint: \"Includes uv and uvx\" },\n { value: \"artifacts\", label: \"Reporting and artifacts\", hint: \"Adds Python automatically\" },\n { value: \"playwright\", label: \"Playwright + Chromium\", hint: \"Adds Node.js automatically\" },\n ],\n });\n if (prompts.isCancel(capabilities)) return cancelPrompt(prompts);\n runtimes = capabilities.filter(isRuntime);\n features = capabilities.filter(isFeature);\n }\n\n const aptResult = await selectCommonPackages(\n prompts,\n \"Select common apt tools (optional)\",\n commonAptPackages,\n options.apt,\n );\n if (aptResult === undefined) return cancelPrompt(prompts);\n const npmResult = await selectCommonPackages(\n prompts,\n \"Select common npm libraries (optional)\",\n commonNpmPackages,\n options.npm,\n );\n if (npmResult === undefined) return cancelPrompt(prompts);\n const uvResult = await selectCommonPackages(\n prompts,\n \"Select common Python libraries with uv (optional)\",\n commonUvPackages,\n options.uv,\n );\n if (uvResult === undefined) return cancelPrompt(prompts);\n\n const tagResult =\n options.tag ??\n (await prompts.text({\n message: \"Docker image tag\",\n initialValue: `anvia-sandbox-${name}:latest`,\n }));\n if (prompts.isCancel(tagResult)) return cancelPrompt(prompts);\n const outputResult =\n options.output ??\n (await prompts.text({\n message: \"Generated source directory\",\n initialValue: path.join(\".anvia\", \"sandbox-images\", name),\n }));\n if (prompts.isCancel(outputResult)) return cancelPrompt(prompts);\n\n const buildResult = options.buildExplicit\n ? options.build\n : await prompts.confirm({ message: \"Build the image now?\", initialValue: true });\n if (prompts.isCancel(buildResult)) return cancelPrompt(prompts);\n const confirmed = await prompts.confirm({\n message: \"Create this sandbox image?\",\n initialValue: true,\n });\n if (prompts.isCancel(confirmed) || !confirmed) return cancelPrompt(prompts);\n\n prompts.outro(\"Configuration ready\");\n return {\n name,\n runtimes,\n features,\n apt: aptResult,\n npm: npmResult,\n uv: uvResult,\n tag: promptString(tagResult, \"Docker image tag\"),\n output: promptString(outputResult, \"Generated source directory\"),\n build: promptBoolean(buildResult, \"Build selection\"),\n };\n}\n\nasync function selectCommonPackages(\n prompts: typeof import(\"@clack/prompts\"),\n message: string,\n options: readonly { value: string; label: string; hint: string }[],\n existing: readonly string[],\n): Promise<string[] | undefined> {\n const commonValues = new Set(options.map((option) => option.value));\n const result = await prompts.multiselect<string>({\n message,\n required: false,\n options: [...options],\n initialValues: existing.filter((value) => commonValues.has(value)),\n });\n if (prompts.isCancel(result)) return undefined;\n return [...new Set([...existing, ...result])];\n}\n\nfunction cancelPrompt(prompts: typeof import(\"@clack/prompts\")): undefined {\n prompts.cancel(\"Image creation cancelled.\");\n return undefined;\n}\n\nasync function buildDockerImage(input: {\n contextPath: string;\n tag: string;\n dockerPath: string;\n io: SandboxImageCliIo;\n}): Promise<void> {\n await assertDockerCli([\"build\", \"--tag\", input.tag, input.contextPath], {\n dockerPath: input.dockerPath,\n onStdout: input.io.stdout,\n onStderr: input.io.stderr,\n });\n}\n\nasync function writeImageContext(\n outputPath: string,\n manifest: SandboxImageManifest,\n files: ReadonlyMap<string, string>,\n force: boolean,\n): Promise<void> {\n const outputStat = await safeLstat(outputPath);\n if (outputStat?.isSymbolicLink()) {\n throw new Error(`Refusing to write through symlink: ${outputPath}`);\n }\n\n if (outputStat !== undefined) {\n if (!outputStat.isDirectory()) throw new Error(`Output path is not a directory: ${outputPath}`);\n const previousManifest = await readGeneratedManifest(outputPath);\n if (previousManifest === undefined) {\n throw new Error(\n `Output directory already exists but was not generated by @anvia/sandbox: ${outputPath}`,\n );\n }\n if (!force) throw new Error(`Output directory already exists. Use --force to regenerate it.`);\n\n for (const filename of previousManifest.generatedFiles) {\n const target = path.join(outputPath, filename);\n const targetStat = await safeLstat(target);\n if (targetStat?.isSymbolicLink()) throw new Error(`Refusing to replace symlink: ${target}`);\n if (targetStat !== undefined) await rm(target);\n }\n } else {\n await mkdir(outputPath, { recursive: true });\n }\n\n for (const [filename, content] of files) {\n if (!generatedFileNames.has(filename))\n throw new Error(`Unexpected generated filename: ${filename}`);\n const target = path.join(outputPath, filename);\n const targetStat = await safeLstat(target);\n if (targetStat?.isSymbolicLink()) throw new Error(`Refusing to replace symlink: ${target}`);\n await writeFile(target, content, \"utf8\");\n }\n\n if (!files.has(\"anvia-sandbox.json\") || manifest.generatedFiles.length !== files.size) {\n throw new Error(\"Generated image context manifest is inconsistent.\");\n }\n}\n\nasync function readGeneratedManifest(\n outputPath: string,\n): Promise<SandboxImageManifest | undefined> {\n const manifestPath = path.join(outputPath, \"anvia-sandbox.json\");\n const stat = await safeLstat(manifestPath);\n if (stat === undefined) return undefined;\n if (stat.isSymbolicLink() || !stat.isFile()) {\n throw new Error(`Invalid generated manifest: ${manifestPath}`);\n }\n\n let value: unknown;\n try {\n value = JSON.parse(await readFile(manifestPath, \"utf8\"));\n } catch (error) {\n throw new Error(`Unable to read generated manifest: ${manifestPath}`, { cause: error });\n }\n if (!isGeneratedManifest(value)) {\n throw new Error(\n `Output manifest is not recognized as an @anvia/sandbox manifest: ${manifestPath}`,\n );\n }\n return value;\n}\n\nfunction isGeneratedManifest(value: unknown): value is SandboxImageManifest {\n if (typeof value !== \"object\" || value === null) return false;\n const record = value as Record<string, unknown>;\n const generatedBy = record.generatedBy as Record<string, unknown> | undefined;\n const files = record.generatedFiles;\n return (\n record.schemaVersion === 1 &&\n generatedBy?.package === \"@anvia/sandbox\" &&\n Array.isArray(files) &&\n files.every((file) => typeof file === \"string\" && generatedFileNames.has(file))\n );\n}\n\nasync function safeLstat(target: string) {\n try {\n return await lstat(target);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw error;\n }\n}\n\nfunction printDryRun(\n files: ReadonlyMap<string, string>,\n outputPath: string,\n tag: string,\n io: SandboxImageCliIo,\n): void {\n io.log(`Would create ${outputPath}`);\n for (const [filename, content] of files) {\n io.log(\"\");\n io.log(`--- ${filename}`);\n io.log(content.trimEnd());\n }\n io.log(\"\");\n io.log(`Would build ${tag}`);\n}\n\nfunction printUsageSnippet(tag: string, io: SandboxImageCliIo): void {\n io.log(\"\");\n io.log(\"Use with @anvia/sandbox:\");\n io.log(' import { DockerSandboxClient } from \"@anvia/sandbox\";');\n io.log(\"\");\n io.log(\" const client = new DockerSandboxClient();\");\n io.log(\" await using sandbox = await client.createSandbox({\");\n io.log(` image: ${JSON.stringify(tag)},`);\n io.log(' workspace: { type: \"ephemeral\" },');\n io.log(' network: { mode: \"none\" },');\n io.log(\" });\");\n}\n\nfunction applyPromptResult(options: CliOptions, result: SandboxImagePromptResult): CliOptions {\n const next: CliOptions = {\n ...options,\n name: result.name,\n runtimes: result.runtimes,\n features: result.features,\n apt: result.apt,\n npm: result.npm,\n uv: result.uv,\n build: result.build,\n buildExplicit: true,\n };\n if (result.tag !== undefined) next.tag = result.tag;\n if (result.output !== undefined) next.output = result.output;\n return next;\n}\n\nfunction parseArgs(argv: string[]): CliOptions {\n const options: CliOptions = {\n runtimes: [],\n features: [],\n apt: [],\n npm: [],\n uv: [],\n versions: {},\n dockerPath: \"docker\",\n build: true,\n buildExplicit: false,\n dryRun: false,\n force: false,\n help: false,\n };\n\n for (let index = 0; index < argv.length; index += 1) {\n const argument = argv[index] ?? \"\";\n if (!argument.startsWith(\"-\")) {\n if (options.command !== undefined) throw new Error(`Unexpected argument: ${argument}`);\n options.command = argument;\n continue;\n }\n\n const [flag, inlineValue] = splitFlag(argument);\n const value = () => inlineValue ?? required(argv[++index], `${flag} requires a value.`);\n switch (flag) {\n case \"-h\":\n case \"--help\":\n options.help = true;\n break;\n case \"--name\":\n options.name = value();\n break;\n case \"--tag\":\n options.tag = value();\n break;\n case \"--output\":\n options.output = value();\n break;\n case \"--runtime\":\n options.runtimes.push(parseRuntime(value()));\n break;\n case \"--feature\":\n options.features.push(parseFeature(value()));\n break;\n case \"--apt\":\n options.apt.push(value());\n break;\n case \"--npm\":\n options.npm.push(value());\n break;\n case \"--uv\":\n options.uv.push(value());\n break;\n case \"--node-version\":\n options.versions.node = value();\n break;\n case \"--pnpm-version\":\n options.versions.pnpm = value();\n break;\n case \"--bun-version\":\n options.versions.bun = value();\n break;\n case \"--python-version\":\n options.versions.python = value();\n break;\n case \"--uv-version\":\n options.versions.uv = value();\n break;\n case \"--playwright-version\":\n options.versions.playwright = value();\n break;\n case \"--docker-path\":\n options.dockerPath = value();\n break;\n case \"--no-build\":\n rejectInlineValue(flag, inlineValue);\n options.build = false;\n options.buildExplicit = true;\n break;\n case \"--dry-run\":\n rejectInlineValue(flag, inlineValue);\n options.dryRun = true;\n break;\n case \"--force\":\n rejectInlineValue(flag, inlineValue);\n options.force = true;\n break;\n default:\n throw new Error(`Unknown option: ${flag}`);\n }\n }\n return options;\n}\n\nfunction splitFlag(argument: string): [string, string | undefined] {\n const separator = argument.indexOf(\"=\");\n return separator === -1\n ? [argument, undefined]\n : [argument.slice(0, separator), argument.slice(separator + 1)];\n}\n\nfunction rejectInlineValue(flag: string, value: string | undefined): void {\n if (value !== undefined) throw new Error(`${flag} does not accept a value.`);\n}\n\nfunction parseRuntime(value: string): SandboxImageRuntime {\n if (isRuntime(value)) return value;\n throw new Error(`Unknown runtime: ${value}. Expected node, bun, or python.`);\n}\n\nfunction parseFeature(value: string): SandboxImageFeature {\n if (isFeature(value)) return value;\n throw new Error(`Unknown feature: ${value}. Expected artifacts or playwright.`);\n}\n\nfunction isRuntime(value: string): value is SandboxImageRuntime {\n return value === \"node\" || value === \"bun\" || value === \"python\";\n}\n\nfunction isFeature(value: string): value is SandboxImageFeature {\n return value === \"artifacts\" || value === \"playwright\";\n}\n\nfunction assertInteractiveNodeVersion(): void {\n const [major = 0, minor = 0] = process.versions.node.split(\".\").map(Number);\n if (major < 20 || (major === 20 && minor < 12)) {\n throw new Error(\"The interactive create-image wizard requires Node.js 20.12 or newer.\");\n }\n}\n\nasync function readPackageVersion(): Promise<string> {\n const packageJson = JSON.parse(\n await readFile(new URL(\"../package.json\", import.meta.url), \"utf8\"),\n ) as {\n version?: unknown;\n };\n return typeof packageJson.version === \"string\" ? packageJson.version : \"unknown\";\n}\n\nfunction relativeDisplayPath(cwd: string, target: string): string {\n const relative = path.relative(cwd, target);\n return relative && !relative.startsWith(\"..\") ? relative : target;\n}\n\nfunction shellCommand(args: readonly string[]): string {\n return args.map(shellArgument).join(\" \");\n}\n\nfunction shellArgument(value: string): string {\n if (/^[a-zA-Z0-9_./:@+-]+$/.test(value)) return value;\n return `'${value.replaceAll(\"'\", `'\"'\"'`)}'`;\n}\n\nfunction required<T>(value: T | undefined, message: string): T {\n if (value === undefined || value === \"\") throw new Error(message);\n return value;\n}\n\nfunction promptString(value: unknown, name: string): string {\n if (typeof value !== \"string\") throw new TypeError(`${name} must be a string.`);\n return value;\n}\n\nfunction promptBoolean(value: unknown, name: string): boolean {\n if (typeof value !== \"boolean\") throw new TypeError(`${name} must be a boolean.`);\n return value;\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : \"Unknown sandbox CLI error\";\n}\n\nfunction helpText(): string {\n return `Usage:\n pnpm dlx @anvia/sandbox create-image [options]\n\nOptions:\n --name <slug> Image profile name\n --runtime <node|bun|python> Runtime to include; repeatable\n --feature <artifacts|playwright>\n Curated feature to include; repeatable\n --apt <package> Additional apt package; repeatable\n --npm <package[@version]> Additional npm package; repeatable\n --uv <requirement> Additional Python package installed with uv; repeatable\n --tag <tag> Local image tag\n --output <directory> Generated context directory\n --node-version <version> Override Node.js version\n --pnpm-version <version> Override pnpm version\n --bun-version <version> Override Bun version\n --python-version <version> Override Python version\n --uv-version <version> Override uv version\n --playwright-version <version> Override Playwright and browser image version\n --docker-path <path> Docker CLI path (default: docker)\n --no-build Generate files without building\n --dry-run Print generated files without writing or building\n --force Regenerate a context previously created by this CLI\n -h, --help Show this help\n\nExamples:\n pnpm dlx @anvia/sandbox create-image\n pnpm dlx @anvia/sandbox create-image --name reports --feature artifacts\n pnpm dlx @anvia/sandbox create-image --name browser --runtime bun --feature playwright`;\n}\n\nconst invokedPath = process.argv[1] === undefined ? undefined : path.resolve(process.argv[1]);\nif (invokedPath !== undefined && invokedPath === fileURLToPath(import.meta.url)) {\n runCli().then((code) => {\n process.exitCode = code;\n });\n}\n","export type SandboxImageRuntime = \"node\" | \"bun\" | \"python\";\nexport type SandboxImageFeature = \"artifacts\" | \"playwright\";\n\nexport interface SandboxImageVersions {\n node: string;\n pnpm: string;\n bun: string;\n python: string;\n uv: string;\n playwright: string;\n}\n\nexport interface SandboxImagePackages {\n apt: string[];\n npm: string[];\n uv: string[];\n}\n\nexport interface SandboxImageInput {\n name: string;\n tag?: string;\n runtimes?: readonly SandboxImageRuntime[];\n features?: readonly SandboxImageFeature[];\n packages?: Partial<SandboxImagePackages>;\n versions?: Partial<SandboxImageVersions>;\n}\n\nexport interface SandboxImageSpec {\n name: string;\n tag: string;\n runtimes: SandboxImageRuntime[];\n features: SandboxImageFeature[];\n packages: SandboxImagePackages;\n versions: SandboxImageVersions;\n}\n\nexport interface SandboxImageManifest extends SandboxImageSpec {\n schemaVersion: 1;\n generatedBy: {\n package: \"@anvia/sandbox\";\n version: string;\n };\n generatedFiles: string[];\n}\n\nexport interface SandboxImageContext {\n manifest: SandboxImageManifest;\n files: ReadonlyMap<string, string>;\n}\n\nexport const defaultSandboxImageVersions: Readonly<SandboxImageVersions> = {\n node: \"24.18.0\",\n pnpm: \"11.0.4\",\n bun: \"1.3.14\",\n python: \"3.13.14\",\n uv: \"0.11.29\",\n playwright: \"1.62.1\",\n};\n\nexport const artifactPythonPackages = [\n \"matplotlib==3.11.1\",\n \"seaborn==0.13.2\",\n \"Pillow==12.3.0\",\n \"ReportLab==5.0.0\",\n \"pypdf==6.14.2\",\n \"pandas==3.0.3\",\n \"openpyxl==3.1.5\",\n \"XlsxWriter==3.2.9\",\n \"python-docx==1.2.0\",\n] as const;\n\nconst runtimeOrder: SandboxImageRuntime[] = [\"node\", \"bun\", \"python\"];\nconst featureOrder: SandboxImageFeature[] = [\"artifacts\", \"playwright\"];\nconst commonAptPackages = [\"bash\", \"ca-certificates\", \"findutils\", \"libstdc++6\", \"procps\"];\n\nexport function resolveSandboxImageSpec(input: SandboxImageInput): SandboxImageSpec {\n validateName(input.name);\n\n const runtimes = new Set(input.runtimes ?? []);\n const features = new Set(input.features ?? []);\n const packages: SandboxImagePackages = {\n apt: unique(input.packages?.apt ?? []),\n npm: unique(input.packages?.npm ?? []),\n uv: unique(input.packages?.uv ?? []),\n };\n\n for (const runtime of runtimes) validateRuntime(runtime);\n for (const feature of features) validateFeature(feature);\n for (const packageName of packages.apt) validateAptPackage(packageName);\n for (const packageSpec of packages.npm) parseNpmPackageSpec(packageSpec);\n for (const requirement of packages.uv) validateUvRequirement(requirement);\n\n if (features.has(\"artifacts\") || packages.uv.length > 0) runtimes.add(\"python\");\n if (features.has(\"playwright\")) runtimes.add(\"node\");\n if (packages.npm.length > 0 && !runtimes.has(\"node\") && !runtimes.has(\"bun\")) {\n runtimes.add(\"node\");\n }\n\n if (runtimes.size === 0) {\n throw new Error(\"Select at least one runtime or feature.\");\n }\n\n const versions = { ...defaultSandboxImageVersions, ...input.versions };\n for (const [name, version] of Object.entries(versions)) validateVersion(name, version);\n\n const tag = input.tag ?? `anvia-sandbox-${input.name}:latest`;\n validateImageTag(tag);\n\n return {\n name: input.name,\n tag,\n runtimes: runtimeOrder.filter((runtime) => runtimes.has(runtime)),\n features: featureOrder.filter((feature) => features.has(feature)),\n packages,\n versions,\n };\n}\n\nexport function renderSandboxImageContext(\n spec: SandboxImageSpec,\n generatorVersion: string,\n): SandboxImageContext {\n const files = new Map<string, string>();\n const pythonRequirements = [...spec.packages.uv];\n if (spec.features.includes(\"artifacts\")) {\n pythonRequirements.unshift(...artifactPythonPackages);\n }\n const npmDependencies = npmDependenciesFor(spec);\n\n files.set(\"Dockerfile\", `${renderDockerfile(spec, pythonRequirements, npmDependencies)}\\n`);\n files.set(\n \".dockerignore\",\n renderDockerignore(pythonRequirements.length > 0, npmDependencies.size > 0),\n );\n\n if (pythonRequirements.length > 0) {\n files.set(\"pyproject.toml\", renderPythonProject(spec, unique(pythonRequirements)));\n }\n if (npmDependencies.size > 0) {\n files.set(\n \"package.json\",\n `${JSON.stringify(\n {\n private: true,\n description: `Generated dependencies for ${spec.name}`,\n dependencies: Object.fromEntries(npmDependencies),\n },\n null,\n 2,\n )}\\n`,\n );\n }\n\n const generatedFiles = [...files.keys(), \"anvia-sandbox.json\"].sort();\n const manifest: SandboxImageManifest = {\n schemaVersion: 1,\n generatedBy: {\n package: \"@anvia/sandbox\",\n version: generatorVersion,\n },\n ...spec,\n generatedFiles,\n };\n files.set(\"anvia-sandbox.json\", `${JSON.stringify(manifest, null, 2)}\\n`);\n\n return { manifest, files };\n}\n\nexport function unpinnedSandboxImagePackages(spec: SandboxImageSpec): string[] {\n const unpinned: string[] = [];\n for (const value of spec.packages.npm) {\n if (parseNpmPackageSpec(value).version === \"latest\") unpinned.push(value);\n }\n for (const value of spec.packages.uv) {\n if (!/===|==|@\\s*https?:/i.test(value)) unpinned.push(value);\n }\n return unpinned;\n}\n\nfunction renderDockerfile(\n spec: SandboxImageSpec,\n pythonRequirements: readonly string[],\n npmDependencies: ReadonlyMap<string, string>,\n): string {\n const hasNode = spec.runtimes.includes(\"node\");\n const hasBun = spec.runtimes.includes(\"bun\");\n const hasPython = spec.runtimes.includes(\"python\");\n const hasPlaywright = spec.features.includes(\"playwright\");\n const lines = [\n \"# Generated by @anvia/sandbox. Edit the manifest and regenerate instead of editing this file.\",\n ];\n\n if (hasNode) lines.push(`FROM node:${spec.versions.node}-bookworm-slim AS node-runtime`);\n if (hasPython) lines.push(`FROM python:${spec.versions.python}-slim-bookworm AS python-runtime`);\n if (hasBun) lines.push(`FROM oven/bun:${spec.versions.bun}-slim AS bun-runtime`);\n if (hasPython) lines.push(`FROM ghcr.io/astral-sh/uv:${spec.versions.uv} AS uv-runtime`);\n\n if (hasPlaywright) {\n lines.push(`FROM mcr.microsoft.com/playwright:v${spec.versions.playwright}-noble AS final`);\n } else if (hasPython) {\n lines.push(\"FROM python-runtime AS final\");\n } else if (hasNode) {\n lines.push(\"FROM node-runtime AS final\");\n } else {\n lines.push(\"FROM bun-runtime AS final\");\n }\n\n lines.push(\"\", \"USER root\");\n\n if (hasPython && (hasPlaywright || !isFinalRuntime(spec, \"python\"))) {\n lines.push(\"COPY --from=python-runtime /usr/local/ /usr/local/\");\n }\n if (hasNode && (hasPlaywright || !isFinalRuntime(spec, \"node\"))) {\n lines.push(\"COPY --from=node-runtime /usr/local/bin/ /usr/local/bin/\");\n lines.push(\n \"COPY --from=node-runtime /usr/local/lib/node_modules/ /usr/local/lib/node_modules/\",\n );\n }\n if (hasBun && !isFinalRuntime(spec, \"bun\")) {\n lines.push(\"COPY --from=bun-runtime /usr/local/bin/bun /usr/local/bin/bun\");\n lines.push(\"RUN ln -sf /usr/local/bin/bun /usr/local/bin/bunx\");\n }\n if (hasPython) {\n lines.push(\"COPY --from=uv-runtime /uv /uvx /usr/local/bin/\");\n }\n\n const requestedAptPackages = [...commonAptPackages];\n if (spec.features.includes(\"artifacts\")) requestedAptPackages.push(\"fonts-dejavu-core\");\n requestedAptPackages.push(...spec.packages.apt);\n const aptPackages = unique(requestedAptPackages).sort();\n lines.push(\n \"\",\n \"RUN apt-get update \\\\\",\n ` && apt-get install -y --no-install-recommends ${aptPackages.map(shellQuote).join(\" \")} \\\\`,\n \" && rm -rf /var/lib/apt/lists/*\",\n );\n\n if (hasNode) {\n lines.push(\n \"\",\n `RUN npm install --global ${shellQuote(`pnpm@${spec.versions.pnpm}`)} --no-audit --no-fund \\\\`,\n \" && npm cache clean --force\",\n );\n }\n\n if (pythonRequirements.length > 0) {\n lines.push(\n \"\",\n \"COPY pyproject.toml /opt/anvia-python/pyproject.toml\",\n \"RUN cd /opt/anvia-python \\\\\",\n \" && uv sync --no-dev --no-cache --no-install-project\",\n \"ENV VIRTUAL_ENV=/opt/anvia-python/.venv\",\n \"ENV PATH=/opt/anvia-python/.venv/bin:$PATH\",\n );\n }\n\n if (npmDependencies.size > 0) {\n lines.push(\"\", \"COPY package.json /opt/anvia-js/package.json\");\n if (hasNode) {\n lines.push(\n \"RUN npm install --prefix /opt/anvia-js --omit=dev --no-audit --no-fund \\\\\",\n \" && ln -s /opt/anvia-js/node_modules /node_modules \\\\\",\n \" && npm cache clean --force\",\n );\n } else {\n lines.push(\n \"RUN cd /opt/anvia-js \\\\\",\n \" && bun install --production --no-save \\\\\",\n \" && ln -s /opt/anvia-js/node_modules /node_modules\",\n );\n }\n lines.push(\"ENV NODE_PATH=/opt/anvia-js/node_modules\");\n lines.push(\"ENV PATH=/opt/anvia-js/node_modules/.bin:$PATH\");\n }\n\n lines.push(\"\");\n if (hasPlaywright) lines.push(\"ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright\");\n lines.push(\n \"RUN mkdir -p /workspace\",\n \"WORKDIR /workspace\",\n \"ENTRYPOINT []\",\n 'CMD [\"sh\", \"-c\", \"trap \\'exit 0\\' TERM INT; while :; do sleep 3600 & wait $!; done\"]',\n );\n\n return lines.join(\"\\n\");\n}\n\nfunction renderDockerignore(hasPython: boolean, hasNpm: boolean): string {\n const lines = [\"**\", \"!Dockerfile\", \"!.dockerignore\", \"!anvia-sandbox.json\"];\n if (hasPython) lines.push(\"!pyproject.toml\");\n if (hasNpm) lines.push(\"!package.json\");\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\nfunction renderPythonProject(spec: SandboxImageSpec, requirements: readonly string[]): string {\n const [major, minor] = spec.versions.python.split(\".\");\n return [\n \"[project]\",\n `name = ${JSON.stringify(`anvia-sandbox-${spec.name}`)}`,\n 'version = \"0.0.0\"',\n `requires-python = ${JSON.stringify(`>=${major}.${minor}`)}`,\n \"dependencies = [\",\n ...requirements.map((requirement) => ` ${JSON.stringify(requirement)},`),\n \"]\",\n \"\",\n ].join(\"\\n\");\n}\n\nfunction npmDependenciesFor(spec: SandboxImageSpec): Map<string, string> {\n const dependencies = new Map<string, string>();\n if (spec.features.includes(\"playwright\")) {\n dependencies.set(\"playwright\", spec.versions.playwright);\n }\n for (const packageSpec of spec.packages.npm) {\n const parsed = parseNpmPackageSpec(packageSpec);\n if (dependencies.has(parsed.name)) {\n throw new Error(`Duplicate npm package: ${parsed.name}`);\n }\n dependencies.set(parsed.name, parsed.version);\n }\n return new Map([...dependencies.entries()].sort(([left], [right]) => left.localeCompare(right)));\n}\n\nfunction isFinalRuntime(spec: SandboxImageSpec, runtime: SandboxImageRuntime): boolean {\n if (spec.features.includes(\"playwright\")) return false;\n if (spec.runtimes.includes(\"python\")) return runtime === \"python\";\n if (spec.runtimes.includes(\"node\")) return runtime === \"node\";\n return runtime === \"bun\";\n}\n\nfunction validateName(name: string): void {\n if (!/^[a-z0-9][a-z0-9-]{0,62}$/.test(name)) {\n throw new Error(\n \"Image name must be 1-63 lowercase letters, numbers, or hyphens and cannot start with a hyphen.\",\n );\n }\n}\n\nfunction validateRuntime(runtime: string): asserts runtime is SandboxImageRuntime {\n if (!runtimeOrder.includes(runtime as SandboxImageRuntime)) {\n throw new Error(`Unknown runtime: ${runtime}. Expected node, bun, or python.`);\n }\n}\n\nfunction validateFeature(feature: string): asserts feature is SandboxImageFeature {\n if (!featureOrder.includes(feature as SandboxImageFeature)) {\n throw new Error(`Unknown feature: ${feature}. Expected artifacts or playwright.`);\n }\n}\n\nfunction validateAptPackage(packageName: string): void {\n if (!/^[a-zA-Z0-9][a-zA-Z0-9.+:~=-]*$/.test(packageName)) {\n throw new Error(`Invalid apt package: ${packageName}`);\n }\n}\n\nfunction parseNpmPackageSpec(packageSpec: string): { name: string; version: string } {\n if (/\\s/.test(packageSpec) || hasControlCharacter(packageSpec)) {\n throw new Error(`Invalid npm package spec: ${packageSpec}`);\n }\n\n const separator = packageSpec.startsWith(\"@\")\n ? packageSpec.indexOf(\"@\", packageSpec.indexOf(\"/\") + 1)\n : packageSpec.indexOf(\"@\");\n const name = separator === -1 ? packageSpec : packageSpec.slice(0, separator);\n const version = separator === -1 ? \"latest\" : packageSpec.slice(separator + 1);\n\n if (!/^(?:@[a-z0-9][a-z0-9._-]*\\/)?[a-z0-9][a-z0-9._-]*$/i.test(name) || !version) {\n throw new Error(`Invalid npm package spec: ${packageSpec}`);\n }\n if (/[\\s'\"`$;&|<>\\\\]/.test(version) || hasControlCharacter(version)) {\n throw new Error(`Invalid npm package version in: ${packageSpec}`);\n }\n return { name, version };\n}\n\nfunction validateUvRequirement(requirement: string): void {\n if (!requirement || requirement.startsWith(\"-\") || hasControlCharacter(requirement)) {\n throw new Error(`Invalid uv package requirement: ${requirement}`);\n }\n}\n\nfunction validateVersion(name: string, version: string): void {\n if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(version)) {\n throw new Error(`Invalid ${name} version: ${version}`);\n }\n}\n\nfunction validateImageTag(tag: string): void {\n if (\n !tag ||\n tag.startsWith(\"-\") ||\n tag.includes(\"@\") ||\n /\\s/.test(tag) ||\n hasControlCharacter(tag)\n ) {\n throw new Error(`Invalid Docker image tag: ${tag}`);\n }\n}\n\nfunction unique(values: readonly string[]): string[] {\n return [...new Set(values)];\n}\n\nfunction hasControlCharacter(value: string): boolean {\n return [...value].some((character) => character.charCodeAt(0) < 32);\n}\n\nfunction shellQuote(value: string): string {\n return `'${value.replaceAll(\"'\", `'\"'\"'`)}'`;\n}\n"],"mappings":"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","names":["commonAptPackages"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/image-builder.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { realpathSync } from \"node:fs\";\nimport { lstat, mkdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { assertDockerCli } from \"./docker-cli\";\nimport {\n renderSandboxImageContext,\n resolveSandboxImageSpec,\n type SandboxImageFeature,\n type SandboxImageInput,\n type SandboxImageManifest,\n type SandboxImageRuntime,\n type SandboxImageVersions,\n unpinnedSandboxImagePackages,\n} from \"./image-builder\";\n\ninterface CliOptions {\n command?: string;\n name?: string;\n tag?: string;\n output?: string;\n runtimes: SandboxImageRuntime[];\n features: SandboxImageFeature[];\n apt: string[];\n npm: string[];\n uv: string[];\n versions: Partial<SandboxImageVersions>;\n dockerPath: string;\n build: boolean;\n buildExplicit: boolean;\n dryRun: boolean;\n force: boolean;\n help: boolean;\n}\n\nexport interface SandboxImageCliIo {\n log(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n stdout(chunk: Uint8Array): void;\n stderr(chunk: Uint8Array): void;\n}\n\nexport interface SandboxImagePromptResult {\n name: string;\n runtimes: SandboxImageRuntime[];\n features: SandboxImageFeature[];\n apt: string[];\n npm: string[];\n uv: string[];\n tag?: string;\n output?: string;\n build: boolean;\n}\n\nexport interface SandboxImageCliDependencies {\n isTTY?: boolean;\n packageVersion?: string;\n prompt?: (options: Readonly<CliOptions>) => Promise<SandboxImagePromptResult | undefined>;\n buildImage?: (input: {\n contextPath: string;\n tag: string;\n dockerPath: string;\n io: SandboxImageCliIo;\n }) => Promise<void>;\n}\n\nconst generatedFileNames = new Set([\n \".dockerignore\",\n \"Dockerfile\",\n \"anvia-sandbox.json\",\n \"package.json\",\n \"pyproject.toml\",\n]);\n\nconst commonAptPackages = [\n { value: \"git\", label: \"Git\", hint: \"Source control and repository operations\" },\n { value: \"curl\", label: \"curl\", hint: \"HTTP downloads and API debugging\" },\n { value: \"jq\", label: \"jq\", hint: \"JSON processing from the shell\" },\n { value: \"ffmpeg\", label: \"FFmpeg\", hint: \"Audio and video processing\" },\n { value: \"imagemagick\", label: \"ImageMagick\", hint: \"Image conversion and editing\" },\n { value: \"poppler-utils\", label: \"Poppler tools\", hint: \"PDF inspection and conversion\" },\n { value: \"libreoffice\", label: \"LibreOffice\", hint: \"Large; office document conversion\" },\n] as const;\n\nconst commonNpmPackages = [\n { value: \"pdfkit@0.19.1\", label: \"PDFKit\", hint: \"Generate PDF documents\" },\n { value: \"sharp@0.35.3\", label: \"Sharp\", hint: \"Resize and transform images\" },\n { value: \"exceljs@4.4.0\", label: \"ExcelJS\", hint: \"Read and write Excel workbooks\" },\n { value: \"docx@9.7.1\", label: \"docx\", hint: \"Generate Word documents\" },\n { value: \"pptxgenjs@4.0.1\", label: \"PptxGenJS\", hint: \"Generate PowerPoint presentations\" },\n] as const;\n\nconst commonUvPackages = [\n { value: \"httpx==0.28.1\", label: \"HTTPX\", hint: \"Modern HTTP client\" },\n { value: \"beautifulsoup4==4.15.0\", label: \"Beautiful Soup\", hint: \"HTML and XML parsing\" },\n { value: \"scipy==1.18.0\", label: \"SciPy\", hint: \"Scientific computing\" },\n { value: \"scikit-learn==1.9.0\", label: \"scikit-learn\", hint: \"Machine learning utilities\" },\n { value: \"polars==1.42.1\", label: \"Polars\", hint: \"Fast dataframe processing\" },\n] as const;\n\nconst defaultIo: SandboxImageCliIo = {\n log: console.log,\n warn: console.warn,\n error: console.error,\n stdout: (chunk) => process.stdout.write(chunk),\n stderr: (chunk) => process.stderr.write(chunk),\n};\n\nexport async function runCli(\n argv: string[] = process.argv.slice(2),\n cwd = process.cwd(),\n io: SandboxImageCliIo = defaultIo,\n dependencies: SandboxImageCliDependencies = {},\n): Promise<number> {\n let options: CliOptions;\n try {\n options = parseArgs(argv);\n } catch (error) {\n io.error(errorMessage(error));\n io.log(helpText());\n return 1;\n }\n\n if (options.help || options.command === undefined) {\n io.log(helpText());\n return 0;\n }\n if (options.command !== \"create-image\") {\n io.error(`Unknown command: ${options.command}`);\n io.log(helpText());\n return 1;\n }\n\n try {\n const shouldPrompt =\n options.name === undefined ||\n (options.runtimes.length === 0 &&\n options.features.length === 0 &&\n options.npm.length === 0 &&\n options.uv.length === 0);\n if (shouldPrompt) {\n const isTTY = dependencies.isTTY ?? (process.stdin.isTTY && process.stdout.isTTY);\n if (!isTTY) {\n throw new Error(\n \"Non-interactive create-image requires --name and at least one --runtime or --feature.\",\n );\n }\n const prompt = dependencies.prompt ?? promptForImage;\n const result = await prompt(options);\n if (result === undefined) return 130;\n options = applyPromptResult(options, result);\n }\n\n const input: SandboxImageInput = {\n name: required(options.name, \"Image name is required.\"),\n runtimes: options.runtimes,\n features: options.features,\n packages: {\n apt: options.apt,\n npm: options.npm,\n uv: options.uv,\n },\n versions: options.versions,\n };\n if (options.tag !== undefined) input.tag = options.tag;\n\n const spec = resolveSandboxImageSpec(input);\n const packageVersion = dependencies.packageVersion ?? (await readPackageVersion());\n const context = renderSandboxImageContext(spec, packageVersion);\n const outputPath = path.resolve(\n cwd,\n options.output ?? path.join(\".anvia\", \"sandbox-images\", spec.name),\n );\n const displayPath = relativeDisplayPath(cwd, outputPath);\n const unpinned = unpinnedSandboxImagePackages(spec);\n if (unpinned.length > 0) {\n io.warn(`Unpinned custom packages may change on rebuild: ${unpinned.join(\", \")}`);\n }\n\n if (options.dryRun) {\n printDryRun(context.files, displayPath, spec.tag, io);\n return 0;\n }\n\n await writeImageContext(outputPath, context.manifest, context.files, options.force);\n io.log(`Created ${displayPath}`);\n\n if (!options.build) {\n io.log(\"\");\n io.log(\"Build later:\");\n io.log(` ${shellCommand([options.dockerPath, \"build\", \"--tag\", spec.tag, displayPath])}`);\n printUsageSnippet(spec.tag, io);\n return 0;\n }\n\n const buildImage = dependencies.buildImage ?? buildDockerImage;\n await buildImage({\n contextPath: outputPath,\n tag: spec.tag,\n dockerPath: options.dockerPath,\n io,\n });\n io.log(`Built ${spec.tag}`);\n printUsageSnippet(spec.tag, io);\n return 0;\n } catch (error) {\n io.error(errorMessage(error));\n return 1;\n }\n}\n\nasync function promptForImage(\n options: Readonly<CliOptions>,\n): Promise<SandboxImagePromptResult | undefined> {\n assertInteractiveNodeVersion();\n const prompts = await import(\"@clack/prompts\");\n prompts.intro(\"Create an Anvia sandbox image\");\n\n const nameResult =\n options.name ??\n (await prompts.text({\n message: \"Image name\",\n placeholder: \"reports\",\n validate: (value) =>\n /^[a-z0-9][a-z0-9-]{0,62}$/.test(value ?? \"\")\n ? undefined\n : \"Use 1-63 lowercase letters, numbers, or hyphens.\",\n }));\n if (prompts.isCancel(nameResult)) return cancelPrompt(prompts);\n const name = promptString(nameResult, \"Image name\");\n\n let runtimes = [...options.runtimes];\n let features = [...options.features];\n if (\n runtimes.length === 0 &&\n features.length === 0 &&\n options.npm.length === 0 &&\n options.uv.length === 0\n ) {\n const capabilities = await prompts.multiselect<SandboxImageRuntime | SandboxImageFeature>({\n message: \"Select runtimes and features\",\n required: true,\n options: [\n { value: \"node\", label: \"Node.js\", hint: \"Includes npm and pnpm\" },\n { value: \"bun\", label: \"Bun\", hint: \"Includes bun and bunx\" },\n { value: \"python\", label: \"Python\", hint: \"Includes uv and uvx\" },\n { value: \"artifacts\", label: \"Reporting and artifacts\", hint: \"Adds Python automatically\" },\n { value: \"playwright\", label: \"Playwright + Chromium\", hint: \"Adds Node.js automatically\" },\n ],\n });\n if (prompts.isCancel(capabilities)) return cancelPrompt(prompts);\n runtimes = capabilities.filter(isRuntime);\n features = capabilities.filter(isFeature);\n }\n\n const aptResult = await selectCommonPackages(\n prompts,\n \"Select common apt tools (optional)\",\n commonAptPackages,\n options.apt,\n );\n if (aptResult === undefined) return cancelPrompt(prompts);\n const npmResult = await selectCommonPackages(\n prompts,\n \"Select common npm libraries (optional)\",\n commonNpmPackages,\n options.npm,\n );\n if (npmResult === undefined) return cancelPrompt(prompts);\n const uvResult = await selectCommonPackages(\n prompts,\n \"Select common Python libraries with uv (optional)\",\n commonUvPackages,\n options.uv,\n );\n if (uvResult === undefined) return cancelPrompt(prompts);\n\n const tagResult =\n options.tag ??\n (await prompts.text({\n message: \"Docker image tag\",\n initialValue: `anvia-sandbox-${name}:latest`,\n }));\n if (prompts.isCancel(tagResult)) return cancelPrompt(prompts);\n const outputResult =\n options.output ??\n (await prompts.text({\n message: \"Generated source directory\",\n initialValue: path.join(\".anvia\", \"sandbox-images\", name),\n }));\n if (prompts.isCancel(outputResult)) return cancelPrompt(prompts);\n\n const buildResult = options.buildExplicit\n ? options.build\n : await prompts.confirm({ message: \"Build the image now?\", initialValue: true });\n if (prompts.isCancel(buildResult)) return cancelPrompt(prompts);\n const confirmed = await prompts.confirm({\n message: \"Create this sandbox image?\",\n initialValue: true,\n });\n if (prompts.isCancel(confirmed) || !confirmed) return cancelPrompt(prompts);\n\n prompts.outro(\"Configuration ready\");\n return {\n name,\n runtimes,\n features,\n apt: aptResult,\n npm: npmResult,\n uv: uvResult,\n tag: promptString(tagResult, \"Docker image tag\"),\n output: promptString(outputResult, \"Generated source directory\"),\n build: promptBoolean(buildResult, \"Build selection\"),\n };\n}\n\nasync function selectCommonPackages(\n prompts: typeof import(\"@clack/prompts\"),\n message: string,\n options: readonly { value: string; label: string; hint: string }[],\n existing: readonly string[],\n): Promise<string[] | undefined> {\n const commonValues = new Set(options.map((option) => option.value));\n const result = await prompts.multiselect<string>({\n message,\n required: false,\n options: [...options],\n initialValues: existing.filter((value) => commonValues.has(value)),\n });\n if (prompts.isCancel(result)) return undefined;\n return [...new Set([...existing, ...result])];\n}\n\nfunction cancelPrompt(prompts: typeof import(\"@clack/prompts\")): undefined {\n prompts.cancel(\"Image creation cancelled.\");\n return undefined;\n}\n\nasync function buildDockerImage(input: {\n contextPath: string;\n tag: string;\n dockerPath: string;\n io: SandboxImageCliIo;\n}): Promise<void> {\n await assertDockerCli([\"build\", \"--tag\", input.tag, input.contextPath], {\n dockerPath: input.dockerPath,\n onStdout: input.io.stdout,\n onStderr: input.io.stderr,\n });\n}\n\nasync function writeImageContext(\n outputPath: string,\n manifest: SandboxImageManifest,\n files: ReadonlyMap<string, string>,\n force: boolean,\n): Promise<void> {\n const outputStat = await safeLstat(outputPath);\n if (outputStat?.isSymbolicLink()) {\n throw new Error(`Refusing to write through symlink: ${outputPath}`);\n }\n\n if (outputStat !== undefined) {\n if (!outputStat.isDirectory()) throw new Error(`Output path is not a directory: ${outputPath}`);\n const previousManifest = await readGeneratedManifest(outputPath);\n if (previousManifest === undefined) {\n throw new Error(\n `Output directory already exists but was not generated by @anvia/sandbox: ${outputPath}`,\n );\n }\n if (!force) throw new Error(`Output directory already exists. Use --force to regenerate it.`);\n\n for (const filename of previousManifest.generatedFiles) {\n const target = path.join(outputPath, filename);\n const targetStat = await safeLstat(target);\n if (targetStat?.isSymbolicLink()) throw new Error(`Refusing to replace symlink: ${target}`);\n if (targetStat !== undefined) await rm(target);\n }\n } else {\n await mkdir(outputPath, { recursive: true });\n }\n\n for (const [filename, content] of files) {\n if (!generatedFileNames.has(filename))\n throw new Error(`Unexpected generated filename: ${filename}`);\n const target = path.join(outputPath, filename);\n const targetStat = await safeLstat(target);\n if (targetStat?.isSymbolicLink()) throw new Error(`Refusing to replace symlink: ${target}`);\n await writeFile(target, content, \"utf8\");\n }\n\n if (!files.has(\"anvia-sandbox.json\") || manifest.generatedFiles.length !== files.size) {\n throw new Error(\"Generated image context manifest is inconsistent.\");\n }\n}\n\nasync function readGeneratedManifest(\n outputPath: string,\n): Promise<SandboxImageManifest | undefined> {\n const manifestPath = path.join(outputPath, \"anvia-sandbox.json\");\n const stat = await safeLstat(manifestPath);\n if (stat === undefined) return undefined;\n if (stat.isSymbolicLink() || !stat.isFile()) {\n throw new Error(`Invalid generated manifest: ${manifestPath}`);\n }\n\n let value: unknown;\n try {\n value = JSON.parse(await readFile(manifestPath, \"utf8\"));\n } catch (error) {\n throw new Error(`Unable to read generated manifest: ${manifestPath}`, { cause: error });\n }\n if (!isGeneratedManifest(value)) {\n throw new Error(\n `Output manifest is not recognized as an @anvia/sandbox manifest: ${manifestPath}`,\n );\n }\n return value;\n}\n\nfunction isGeneratedManifest(value: unknown): value is SandboxImageManifest {\n if (typeof value !== \"object\" || value === null) return false;\n const record = value as Record<string, unknown>;\n const generatedBy = record.generatedBy as Record<string, unknown> | undefined;\n const files = record.generatedFiles;\n return (\n record.schemaVersion === 1 &&\n generatedBy?.package === \"@anvia/sandbox\" &&\n Array.isArray(files) &&\n files.every((file) => typeof file === \"string\" && generatedFileNames.has(file))\n );\n}\n\nasync function safeLstat(target: string) {\n try {\n return await lstat(target);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw error;\n }\n}\n\nfunction printDryRun(\n files: ReadonlyMap<string, string>,\n outputPath: string,\n tag: string,\n io: SandboxImageCliIo,\n): void {\n io.log(`Would create ${outputPath}`);\n for (const [filename, content] of files) {\n io.log(\"\");\n io.log(`--- ${filename}`);\n io.log(content.trimEnd());\n }\n io.log(\"\");\n io.log(`Would build ${tag}`);\n}\n\nfunction printUsageSnippet(tag: string, io: SandboxImageCliIo): void {\n io.log(\"\");\n io.log(\"Use with @anvia/sandbox:\");\n io.log(' import { DockerSandboxClient } from \"@anvia/sandbox\";');\n io.log(\"\");\n io.log(\" const client = new DockerSandboxClient();\");\n io.log(\" await using sandbox = await client.createSandbox({\");\n io.log(` image: ${JSON.stringify(tag)},`);\n io.log(' workspace: { type: \"ephemeral\" },');\n io.log(' network: { mode: \"none\" },');\n io.log(\" });\");\n}\n\nfunction applyPromptResult(options: CliOptions, result: SandboxImagePromptResult): CliOptions {\n const next: CliOptions = {\n ...options,\n name: result.name,\n runtimes: result.runtimes,\n features: result.features,\n apt: result.apt,\n npm: result.npm,\n uv: result.uv,\n build: result.build,\n buildExplicit: true,\n };\n if (result.tag !== undefined) next.tag = result.tag;\n if (result.output !== undefined) next.output = result.output;\n return next;\n}\n\nfunction parseArgs(argv: string[]): CliOptions {\n const options: CliOptions = {\n runtimes: [],\n features: [],\n apt: [],\n npm: [],\n uv: [],\n versions: {},\n dockerPath: \"docker\",\n build: true,\n buildExplicit: false,\n dryRun: false,\n force: false,\n help: false,\n };\n\n for (let index = 0; index < argv.length; index += 1) {\n const argument = argv[index] ?? \"\";\n if (!argument.startsWith(\"-\")) {\n if (options.command !== undefined) throw new Error(`Unexpected argument: ${argument}`);\n options.command = argument;\n continue;\n }\n\n const [flag, inlineValue] = splitFlag(argument);\n const value = () => inlineValue ?? required(argv[++index], `${flag} requires a value.`);\n switch (flag) {\n case \"-h\":\n case \"--help\":\n options.help = true;\n break;\n case \"--name\":\n options.name = value();\n break;\n case \"--tag\":\n options.tag = value();\n break;\n case \"--output\":\n options.output = value();\n break;\n case \"--runtime\":\n options.runtimes.push(parseRuntime(value()));\n break;\n case \"--feature\":\n options.features.push(parseFeature(value()));\n break;\n case \"--apt\":\n options.apt.push(value());\n break;\n case \"--npm\":\n options.npm.push(value());\n break;\n case \"--uv\":\n options.uv.push(value());\n break;\n case \"--node-version\":\n options.versions.node = value();\n break;\n case \"--pnpm-version\":\n options.versions.pnpm = value();\n break;\n case \"--bun-version\":\n options.versions.bun = value();\n break;\n case \"--python-version\":\n options.versions.python = value();\n break;\n case \"--uv-version\":\n options.versions.uv = value();\n break;\n case \"--playwright-version\":\n options.versions.playwright = value();\n break;\n case \"--docker-path\":\n options.dockerPath = value();\n break;\n case \"--no-build\":\n rejectInlineValue(flag, inlineValue);\n options.build = false;\n options.buildExplicit = true;\n break;\n case \"--dry-run\":\n rejectInlineValue(flag, inlineValue);\n options.dryRun = true;\n break;\n case \"--force\":\n rejectInlineValue(flag, inlineValue);\n options.force = true;\n break;\n default:\n throw new Error(`Unknown option: ${flag}`);\n }\n }\n return options;\n}\n\nfunction splitFlag(argument: string): [string, string | undefined] {\n const separator = argument.indexOf(\"=\");\n return separator === -1\n ? [argument, undefined]\n : [argument.slice(0, separator), argument.slice(separator + 1)];\n}\n\nfunction rejectInlineValue(flag: string, value: string | undefined): void {\n if (value !== undefined) throw new Error(`${flag} does not accept a value.`);\n}\n\nfunction parseRuntime(value: string): SandboxImageRuntime {\n if (isRuntime(value)) return value;\n throw new Error(`Unknown runtime: ${value}. Expected node, bun, or python.`);\n}\n\nfunction parseFeature(value: string): SandboxImageFeature {\n if (isFeature(value)) return value;\n throw new Error(`Unknown feature: ${value}. Expected artifacts or playwright.`);\n}\n\nfunction isRuntime(value: string): value is SandboxImageRuntime {\n return value === \"node\" || value === \"bun\" || value === \"python\";\n}\n\nfunction isFeature(value: string): value is SandboxImageFeature {\n return value === \"artifacts\" || value === \"playwright\";\n}\n\nfunction assertInteractiveNodeVersion(): void {\n const [major = 0, minor = 0] = process.versions.node.split(\".\").map(Number);\n if (major < 20 || (major === 20 && minor < 12)) {\n throw new Error(\"The interactive create-image wizard requires Node.js 20.12 or newer.\");\n }\n}\n\nasync function readPackageVersion(): Promise<string> {\n const packageJson = JSON.parse(\n await readFile(new URL(\"../package.json\", import.meta.url), \"utf8\"),\n ) as {\n version?: unknown;\n };\n return typeof packageJson.version === \"string\" ? packageJson.version : \"unknown\";\n}\n\nfunction relativeDisplayPath(cwd: string, target: string): string {\n const relative = path.relative(cwd, target);\n return relative && !relative.startsWith(\"..\") ? relative : target;\n}\n\nfunction shellCommand(args: readonly string[]): string {\n return args.map(shellArgument).join(\" \");\n}\n\nfunction shellArgument(value: string): string {\n if (/^[a-zA-Z0-9_./:@+-]+$/.test(value)) return value;\n return `'${value.replaceAll(\"'\", `'\"'\"'`)}'`;\n}\n\nfunction required<T>(value: T | undefined, message: string): T {\n if (value === undefined || value === \"\") throw new Error(message);\n return value;\n}\n\nfunction promptString(value: unknown, name: string): string {\n if (typeof value !== \"string\") throw new TypeError(`${name} must be a string.`);\n return value;\n}\n\nfunction promptBoolean(value: unknown, name: string): boolean {\n if (typeof value !== \"boolean\") throw new TypeError(`${name} must be a boolean.`);\n return value;\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : \"Unknown sandbox CLI error\";\n}\n\nfunction helpText(): string {\n return `Usage:\n pnpm dlx @anvia/sandbox create-image [options]\n\nOptions:\n --name <slug> Image profile name\n --runtime <node|bun|python> Runtime to include; repeatable\n --feature <artifacts|playwright>\n Curated feature to include; repeatable\n --apt <package> Additional apt package; repeatable\n --npm <package[@version]> Additional npm package; repeatable\n --uv <requirement> Additional Python package installed with uv; repeatable\n --tag <tag> Local image tag\n --output <directory> Generated context directory\n --node-version <version> Override Node.js version\n --pnpm-version <version> Override pnpm version\n --bun-version <version> Override Bun version\n --python-version <version> Override Python version\n --uv-version <version> Override uv version\n --playwright-version <version> Override Playwright and browser image version\n --docker-path <path> Docker CLI path (default: docker)\n --no-build Generate files without building\n --dry-run Print generated files without writing or building\n --force Regenerate a context previously created by this CLI\n -h, --help Show this help\n\nExamples:\n pnpm dlx @anvia/sandbox create-image\n pnpm dlx @anvia/sandbox create-image --name reports --feature artifacts\n pnpm dlx @anvia/sandbox create-image --name browser --runtime bun --feature playwright`;\n}\n\nexport function isCliEntryPoint(moduleUrl: string, invokedPath: string | undefined): boolean {\n if (invokedPath === undefined) return false;\n try {\n return realpathSync(path.resolve(invokedPath)) === realpathSync(fileURLToPath(moduleUrl));\n } catch {\n return false;\n }\n}\n\nif (isCliEntryPoint(import.meta.url, process.argv[1])) {\n runCli().then((code) => {\n process.exitCode = code;\n });\n}\n","export type SandboxImageRuntime = \"node\" | \"bun\" | \"python\";\nexport type SandboxImageFeature = \"artifacts\" | \"playwright\";\n\nexport interface SandboxImageVersions {\n node: string;\n pnpm: string;\n bun: string;\n python: string;\n uv: string;\n playwright: string;\n}\n\nexport interface SandboxImagePackages {\n apt: string[];\n npm: string[];\n uv: string[];\n}\n\nexport interface SandboxImageInput {\n name: string;\n tag?: string;\n runtimes?: readonly SandboxImageRuntime[];\n features?: readonly SandboxImageFeature[];\n packages?: Partial<SandboxImagePackages>;\n versions?: Partial<SandboxImageVersions>;\n}\n\nexport interface SandboxImageSpec {\n name: string;\n tag: string;\n runtimes: SandboxImageRuntime[];\n features: SandboxImageFeature[];\n packages: SandboxImagePackages;\n versions: SandboxImageVersions;\n}\n\nexport interface SandboxImageManifest extends SandboxImageSpec {\n schemaVersion: 1;\n generatedBy: {\n package: \"@anvia/sandbox\";\n version: string;\n };\n generatedFiles: string[];\n}\n\nexport interface SandboxImageContext {\n manifest: SandboxImageManifest;\n files: ReadonlyMap<string, string>;\n}\n\nexport const defaultSandboxImageVersions: Readonly<SandboxImageVersions> = {\n node: \"24.18.0\",\n pnpm: \"11.0.4\",\n bun: \"1.3.14\",\n python: \"3.13.14\",\n uv: \"0.11.29\",\n playwright: \"1.62.1\",\n};\n\nexport const artifactPythonPackages = [\n \"matplotlib==3.11.1\",\n \"seaborn==0.13.2\",\n \"Pillow==12.3.0\",\n \"ReportLab==5.0.0\",\n \"pypdf==6.14.2\",\n \"pandas==3.0.3\",\n \"openpyxl==3.1.5\",\n \"XlsxWriter==3.2.9\",\n \"python-docx==1.2.0\",\n] as const;\n\nconst runtimeOrder: SandboxImageRuntime[] = [\"node\", \"bun\", \"python\"];\nconst featureOrder: SandboxImageFeature[] = [\"artifacts\", \"playwright\"];\nconst commonAptPackages = [\"bash\", \"ca-certificates\", \"findutils\", \"libstdc++6\", \"procps\"];\n\nexport function resolveSandboxImageSpec(input: SandboxImageInput): SandboxImageSpec {\n validateName(input.name);\n\n const runtimes = new Set(input.runtimes ?? []);\n const features = new Set(input.features ?? []);\n const packages: SandboxImagePackages = {\n apt: unique(input.packages?.apt ?? []),\n npm: unique(input.packages?.npm ?? []),\n uv: unique(input.packages?.uv ?? []),\n };\n\n for (const runtime of runtimes) validateRuntime(runtime);\n for (const feature of features) validateFeature(feature);\n for (const packageName of packages.apt) validateAptPackage(packageName);\n for (const packageSpec of packages.npm) parseNpmPackageSpec(packageSpec);\n for (const requirement of packages.uv) validateUvRequirement(requirement);\n\n if (features.has(\"artifacts\") || packages.uv.length > 0) runtimes.add(\"python\");\n if (features.has(\"playwright\")) runtimes.add(\"node\");\n if (packages.npm.length > 0 && !runtimes.has(\"node\") && !runtimes.has(\"bun\")) {\n runtimes.add(\"node\");\n }\n\n if (runtimes.size === 0) {\n throw new Error(\"Select at least one runtime or feature.\");\n }\n\n const versions = { ...defaultSandboxImageVersions, ...input.versions };\n for (const [name, version] of Object.entries(versions)) validateVersion(name, version);\n\n const tag = input.tag ?? `anvia-sandbox-${input.name}:latest`;\n validateImageTag(tag);\n\n return {\n name: input.name,\n tag,\n runtimes: runtimeOrder.filter((runtime) => runtimes.has(runtime)),\n features: featureOrder.filter((feature) => features.has(feature)),\n packages,\n versions,\n };\n}\n\nexport function renderSandboxImageContext(\n spec: SandboxImageSpec,\n generatorVersion: string,\n): SandboxImageContext {\n const files = new Map<string, string>();\n const pythonRequirements = [...spec.packages.uv];\n if (spec.features.includes(\"artifacts\")) {\n pythonRequirements.unshift(...artifactPythonPackages);\n }\n const npmDependencies = npmDependenciesFor(spec);\n\n files.set(\"Dockerfile\", `${renderDockerfile(spec, pythonRequirements, npmDependencies)}\\n`);\n files.set(\n \".dockerignore\",\n renderDockerignore(pythonRequirements.length > 0, npmDependencies.size > 0),\n );\n\n if (pythonRequirements.length > 0) {\n files.set(\"pyproject.toml\", renderPythonProject(spec, unique(pythonRequirements)));\n }\n if (npmDependencies.size > 0) {\n files.set(\n \"package.json\",\n `${JSON.stringify(\n {\n private: true,\n description: `Generated dependencies for ${spec.name}`,\n dependencies: Object.fromEntries(npmDependencies),\n },\n null,\n 2,\n )}\\n`,\n );\n }\n\n const generatedFiles = [...files.keys(), \"anvia-sandbox.json\"].sort();\n const manifest: SandboxImageManifest = {\n schemaVersion: 1,\n generatedBy: {\n package: \"@anvia/sandbox\",\n version: generatorVersion,\n },\n ...spec,\n generatedFiles,\n };\n files.set(\"anvia-sandbox.json\", `${JSON.stringify(manifest, null, 2)}\\n`);\n\n return { manifest, files };\n}\n\nexport function unpinnedSandboxImagePackages(spec: SandboxImageSpec): string[] {\n const unpinned: string[] = [];\n for (const value of spec.packages.npm) {\n if (parseNpmPackageSpec(value).version === \"latest\") unpinned.push(value);\n }\n for (const value of spec.packages.uv) {\n if (!/===|==|@\\s*https?:/i.test(value)) unpinned.push(value);\n }\n return unpinned;\n}\n\nfunction renderDockerfile(\n spec: SandboxImageSpec,\n pythonRequirements: readonly string[],\n npmDependencies: ReadonlyMap<string, string>,\n): string {\n const hasNode = spec.runtimes.includes(\"node\");\n const hasBun = spec.runtimes.includes(\"bun\");\n const hasPython = spec.runtimes.includes(\"python\");\n const hasPlaywright = spec.features.includes(\"playwright\");\n const lines = [\n \"# Generated by @anvia/sandbox. Edit the manifest and regenerate instead of editing this file.\",\n ];\n\n if (hasNode) lines.push(`FROM node:${spec.versions.node}-bookworm-slim AS node-runtime`);\n if (hasPython) lines.push(`FROM python:${spec.versions.python}-slim-bookworm AS python-runtime`);\n if (hasBun) lines.push(`FROM oven/bun:${spec.versions.bun}-slim AS bun-runtime`);\n if (hasPython) lines.push(`FROM ghcr.io/astral-sh/uv:${spec.versions.uv} AS uv-runtime`);\n\n if (hasPlaywright) {\n lines.push(`FROM mcr.microsoft.com/playwright:v${spec.versions.playwright}-noble AS final`);\n } else if (hasPython) {\n lines.push(\"FROM python-runtime AS final\");\n } else if (hasNode) {\n lines.push(\"FROM node-runtime AS final\");\n } else {\n lines.push(\"FROM bun-runtime AS final\");\n }\n\n lines.push(\"\", \"USER root\");\n\n if (hasPython && (hasPlaywright || !isFinalRuntime(spec, \"python\"))) {\n lines.push(\"COPY --from=python-runtime /usr/local/ /usr/local/\");\n }\n if (hasNode && (hasPlaywright || !isFinalRuntime(spec, \"node\"))) {\n lines.push(\"COPY --from=node-runtime /usr/local/bin/ /usr/local/bin/\");\n lines.push(\n \"COPY --from=node-runtime /usr/local/lib/node_modules/ /usr/local/lib/node_modules/\",\n );\n }\n if (hasBun && !isFinalRuntime(spec, \"bun\")) {\n lines.push(\"COPY --from=bun-runtime /usr/local/bin/bun /usr/local/bin/bun\");\n lines.push(\"RUN ln -sf /usr/local/bin/bun /usr/local/bin/bunx\");\n }\n if (hasPython) {\n lines.push(\"COPY --from=uv-runtime /uv /uvx /usr/local/bin/\");\n }\n\n const requestedAptPackages = [...commonAptPackages];\n if (spec.features.includes(\"artifacts\")) requestedAptPackages.push(\"fonts-dejavu-core\");\n requestedAptPackages.push(...spec.packages.apt);\n const aptPackages = unique(requestedAptPackages).sort();\n lines.push(\n \"\",\n \"RUN apt-get update \\\\\",\n ` && apt-get install -y --no-install-recommends ${aptPackages.map(shellQuote).join(\" \")} \\\\`,\n \" && rm -rf /var/lib/apt/lists/*\",\n );\n\n if (hasNode) {\n lines.push(\n \"\",\n `RUN npm install --global ${shellQuote(`pnpm@${spec.versions.pnpm}`)} --no-audit --no-fund \\\\`,\n \" && npm cache clean --force\",\n );\n }\n\n if (pythonRequirements.length > 0) {\n lines.push(\n \"\",\n \"COPY pyproject.toml /opt/anvia-python/pyproject.toml\",\n \"RUN cd /opt/anvia-python \\\\\",\n \" && uv sync --no-dev --no-cache --no-install-project\",\n \"ENV VIRTUAL_ENV=/opt/anvia-python/.venv\",\n \"ENV PATH=/opt/anvia-python/.venv/bin:$PATH\",\n );\n }\n\n if (npmDependencies.size > 0) {\n lines.push(\"\", \"COPY package.json /opt/anvia-js/package.json\");\n if (hasNode) {\n lines.push(\n \"RUN npm install --prefix /opt/anvia-js --omit=dev --no-audit --no-fund \\\\\",\n \" && ln -s /opt/anvia-js/node_modules /node_modules \\\\\",\n \" && npm cache clean --force\",\n );\n } else {\n lines.push(\n \"RUN cd /opt/anvia-js \\\\\",\n \" && bun install --production --no-save \\\\\",\n \" && ln -s /opt/anvia-js/node_modules /node_modules\",\n );\n }\n lines.push(\"ENV NODE_PATH=/opt/anvia-js/node_modules\");\n lines.push(\"ENV PATH=/opt/anvia-js/node_modules/.bin:$PATH\");\n }\n\n lines.push(\"\");\n if (hasPlaywright) lines.push(\"ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright\");\n lines.push(\n \"RUN mkdir -p /workspace\",\n \"WORKDIR /workspace\",\n \"ENTRYPOINT []\",\n 'CMD [\"sh\", \"-c\", \"trap \\'exit 0\\' TERM INT; while :; do sleep 3600 & wait $!; done\"]',\n );\n\n return lines.join(\"\\n\");\n}\n\nfunction renderDockerignore(hasPython: boolean, hasNpm: boolean): string {\n const lines = [\"**\", \"!Dockerfile\", \"!.dockerignore\", \"!anvia-sandbox.json\"];\n if (hasPython) lines.push(\"!pyproject.toml\");\n if (hasNpm) lines.push(\"!package.json\");\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\nfunction renderPythonProject(spec: SandboxImageSpec, requirements: readonly string[]): string {\n const [major, minor] = spec.versions.python.split(\".\");\n return [\n \"[project]\",\n `name = ${JSON.stringify(`anvia-sandbox-${spec.name}`)}`,\n 'version = \"0.0.0\"',\n `requires-python = ${JSON.stringify(`>=${major}.${minor}`)}`,\n \"dependencies = [\",\n ...requirements.map((requirement) => ` ${JSON.stringify(requirement)},`),\n \"]\",\n \"\",\n ].join(\"\\n\");\n}\n\nfunction npmDependenciesFor(spec: SandboxImageSpec): Map<string, string> {\n const dependencies = new Map<string, string>();\n if (spec.features.includes(\"playwright\")) {\n dependencies.set(\"playwright\", spec.versions.playwright);\n }\n for (const packageSpec of spec.packages.npm) {\n const parsed = parseNpmPackageSpec(packageSpec);\n if (dependencies.has(parsed.name)) {\n throw new Error(`Duplicate npm package: ${parsed.name}`);\n }\n dependencies.set(parsed.name, parsed.version);\n }\n return new Map([...dependencies.entries()].sort(([left], [right]) => left.localeCompare(right)));\n}\n\nfunction isFinalRuntime(spec: SandboxImageSpec, runtime: SandboxImageRuntime): boolean {\n if (spec.features.includes(\"playwright\")) return false;\n if (spec.runtimes.includes(\"python\")) return runtime === \"python\";\n if (spec.runtimes.includes(\"node\")) return runtime === \"node\";\n return runtime === \"bun\";\n}\n\nfunction validateName(name: string): void {\n if (!/^[a-z0-9][a-z0-9-]{0,62}$/.test(name)) {\n throw new Error(\n \"Image name must be 1-63 lowercase letters, numbers, or hyphens and cannot start with a hyphen.\",\n );\n }\n}\n\nfunction validateRuntime(runtime: string): asserts runtime is SandboxImageRuntime {\n if (!runtimeOrder.includes(runtime as SandboxImageRuntime)) {\n throw new Error(`Unknown runtime: ${runtime}. Expected node, bun, or python.`);\n }\n}\n\nfunction validateFeature(feature: string): asserts feature is SandboxImageFeature {\n if (!featureOrder.includes(feature as SandboxImageFeature)) {\n throw new Error(`Unknown feature: ${feature}. Expected artifacts or playwright.`);\n }\n}\n\nfunction validateAptPackage(packageName: string): void {\n if (!/^[a-zA-Z0-9][a-zA-Z0-9.+:~=-]*$/.test(packageName)) {\n throw new Error(`Invalid apt package: ${packageName}`);\n }\n}\n\nfunction parseNpmPackageSpec(packageSpec: string): { name: string; version: string } {\n if (/\\s/.test(packageSpec) || hasControlCharacter(packageSpec)) {\n throw new Error(`Invalid npm package spec: ${packageSpec}`);\n }\n\n const separator = packageSpec.startsWith(\"@\")\n ? packageSpec.indexOf(\"@\", packageSpec.indexOf(\"/\") + 1)\n : packageSpec.indexOf(\"@\");\n const name = separator === -1 ? packageSpec : packageSpec.slice(0, separator);\n const version = separator === -1 ? \"latest\" : packageSpec.slice(separator + 1);\n\n if (!/^(?:@[a-z0-9][a-z0-9._-]*\\/)?[a-z0-9][a-z0-9._-]*$/i.test(name) || !version) {\n throw new Error(`Invalid npm package spec: ${packageSpec}`);\n }\n if (/[\\s'\"`$;&|<>\\\\]/.test(version) || hasControlCharacter(version)) {\n throw new Error(`Invalid npm package version in: ${packageSpec}`);\n }\n return { name, version };\n}\n\nfunction validateUvRequirement(requirement: string): void {\n if (!requirement || requirement.startsWith(\"-\") || hasControlCharacter(requirement)) {\n throw new Error(`Invalid uv package requirement: ${requirement}`);\n }\n}\n\nfunction validateVersion(name: string, version: string): void {\n if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(version)) {\n throw new Error(`Invalid ${name} version: ${version}`);\n }\n}\n\nfunction validateImageTag(tag: string): void {\n if (\n !tag ||\n tag.startsWith(\"-\") ||\n tag.includes(\"@\") ||\n /\\s/.test(tag) ||\n hasControlCharacter(tag)\n ) {\n throw new Error(`Invalid Docker image tag: ${tag}`);\n }\n}\n\nfunction unique(values: readonly string[]): string[] {\n return [...new Set(values)];\n}\n\nfunction hasControlCharacter(value: string): boolean {\n return [...value].some((character) => character.charCodeAt(0) < 32);\n}\n\nfunction shellQuote(value: string): string {\n return `'${value.replaceAll(\"'\", `'\"'\"'`)}'`;\n}\n"],"mappings":";;;;;;AACA,SAAS,oBAAoB;AAC7B,SAAS,OAAO,OAAO,UAAU,IAAI,iBAAiB;AACtD,OAAO,UAAU;AACjB,SAAS,qBAAqB;;;AC8CvB,IAAM,8BAA8D;AAAA,EACzE,MAAM;AAAA,EACN,MAAM;AAAA,EACN,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,IAAI;AAAA,EACJ,YAAY;AACd;AAEO,IAAM,yBAAyB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,eAAsC,CAAC,QAAQ,OAAO,QAAQ;AACpE,IAAM,eAAsC,CAAC,aAAa,YAAY;AACtE,IAAM,oBAAoB,CAAC,QAAQ,mBAAmB,aAAa,cAAc,QAAQ;AAElF,SAAS,wBAAwB,OAA4C;AAClF,eAAa,MAAM,IAAI;AAEvB,QAAM,WAAW,IAAI,IAAI,MAAM,YAAY,CAAC,CAAC;AAC7C,QAAM,WAAW,IAAI,IAAI,MAAM,YAAY,CAAC,CAAC;AAC7C,QAAM,WAAiC;AAAA,IACrC,KAAK,OAAO,MAAM,UAAU,OAAO,CAAC,CAAC;AAAA,IACrC,KAAK,OAAO,MAAM,UAAU,OAAO,CAAC,CAAC;AAAA,IACrC,IAAI,OAAO,MAAM,UAAU,MAAM,CAAC,CAAC;AAAA,EACrC;AAEA,aAAW,WAAW,SAAU,iBAAgB,OAAO;AACvD,aAAW,WAAW,SAAU,iBAAgB,OAAO;AACvD,aAAW,eAAe,SAAS,IAAK,oBAAmB,WAAW;AACtE,aAAW,eAAe,SAAS,IAAK,qBAAoB,WAAW;AACvE,aAAW,eAAe,SAAS,GAAI,uBAAsB,WAAW;AAExE,MAAI,SAAS,IAAI,WAAW,KAAK,SAAS,GAAG,SAAS,EAAG,UAAS,IAAI,QAAQ;AAC9E,MAAI,SAAS,IAAI,YAAY,EAAG,UAAS,IAAI,MAAM;AACnD,MAAI,SAAS,IAAI,SAAS,KAAK,CAAC,SAAS,IAAI,MAAM,KAAK,CAAC,SAAS,IAAI,KAAK,GAAG;AAC5E,aAAS,IAAI,MAAM;AAAA,EACrB;AAEA,MAAI,SAAS,SAAS,GAAG;AACvB,UAAM,IAAI,MAAM,yCAAyC;AAAA,EAC3D;AAEA,QAAM,WAAW,EAAE,GAAG,6BAA6B,GAAG,MAAM,SAAS;AACrE,aAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,QAAQ,EAAG,iBAAgB,MAAM,OAAO;AAErF,QAAM,MAAM,MAAM,OAAO,iBAAiB,MAAM,IAAI;AACpD,mBAAiB,GAAG;AAEpB,SAAO;AAAA,IACL,MAAM,MAAM;AAAA,IACZ;AAAA,IACA,UAAU,aAAa,OAAO,CAAC,YAAY,SAAS,IAAI,OAAO,CAAC;AAAA,IAChE,UAAU,aAAa,OAAO,CAAC,YAAY,SAAS,IAAI,OAAO,CAAC;AAAA,IAChE;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,0BACd,MACA,kBACqB;AACrB,QAAM,QAAQ,oBAAI,IAAoB;AACtC,QAAM,qBAAqB,CAAC,GAAG,KAAK,SAAS,EAAE;AAC/C,MAAI,KAAK,SAAS,SAAS,WAAW,GAAG;AACvC,uBAAmB,QAAQ,GAAG,sBAAsB;AAAA,EACtD;AACA,QAAM,kBAAkB,mBAAmB,IAAI;AAE/C,QAAM,IAAI,cAAc,GAAG,iBAAiB,MAAM,oBAAoB,eAAe,CAAC;AAAA,CAAI;AAC1F,QAAM;AAAA,IACJ;AAAA,IACA,mBAAmB,mBAAmB,SAAS,GAAG,gBAAgB,OAAO,CAAC;AAAA,EAC5E;AAEA,MAAI,mBAAmB,SAAS,GAAG;AACjC,UAAM,IAAI,kBAAkB,oBAAoB,MAAM,OAAO,kBAAkB,CAAC,CAAC;AAAA,EACnF;AACA,MAAI,gBAAgB,OAAO,GAAG;AAC5B,UAAM;AAAA,MACJ;AAAA,MACA,GAAG,KAAK;AAAA,QACN;AAAA,UACE,SAAS;AAAA,UACT,aAAa,8BAA8B,KAAK,IAAI;AAAA,UACpD,cAAc,OAAO,YAAY,eAAe;AAAA,QAClD;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA;AAAA,IACH;AAAA,EACF;AAEA,QAAM,iBAAiB,CAAC,GAAG,MAAM,KAAK,GAAG,oBAAoB,EAAE,KAAK;AACpE,QAAM,WAAiC;AAAA,IACrC,eAAe;AAAA,IACf,aAAa;AAAA,MACX,SAAS;AAAA,MACT,SAAS;AAAA,IACX;AAAA,IACA,GAAG;AAAA,IACH;AAAA,EACF;AACA,QAAM,IAAI,sBAAsB,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,CAAI;AAExE,SAAO,EAAE,UAAU,MAAM;AAC3B;AAEO,SAAS,6BAA6B,MAAkC;AAC7E,QAAM,WAAqB,CAAC;AAC5B,aAAW,SAAS,KAAK,SAAS,KAAK;AACrC,QAAI,oBAAoB,KAAK,EAAE,YAAY,SAAU,UAAS,KAAK,KAAK;AAAA,EAC1E;AACA,aAAW,SAAS,KAAK,SAAS,IAAI;AACpC,QAAI,CAAC,sBAAsB,KAAK,KAAK,EAAG,UAAS,KAAK,KAAK;AAAA,EAC7D;AACA,SAAO;AACT;AAEA,SAAS,iBACP,MACA,oBACA,iBACQ;AACR,QAAM,UAAU,KAAK,SAAS,SAAS,MAAM;AAC7C,QAAM,SAAS,KAAK,SAAS,SAAS,KAAK;AAC3C,QAAM,YAAY,KAAK,SAAS,SAAS,QAAQ;AACjD,QAAM,gBAAgB,KAAK,SAAS,SAAS,YAAY;AACzD,QAAM,QAAQ;AAAA,IACZ;AAAA,EACF;AAEA,MAAI,QAAS,OAAM,KAAK,aAAa,KAAK,SAAS,IAAI,gCAAgC;AACvF,MAAI,UAAW,OAAM,KAAK,eAAe,KAAK,SAAS,MAAM,kCAAkC;AAC/F,MAAI,OAAQ,OAAM,KAAK,iBAAiB,KAAK,SAAS,GAAG,sBAAsB;AAC/E,MAAI,UAAW,OAAM,KAAK,6BAA6B,KAAK,SAAS,EAAE,gBAAgB;AAEvF,MAAI,eAAe;AACjB,UAAM,KAAK,sCAAsC,KAAK,SAAS,UAAU,iBAAiB;AAAA,EAC5F,WAAW,WAAW;AACpB,UAAM,KAAK,8BAA8B;AAAA,EAC3C,WAAW,SAAS;AAClB,UAAM,KAAK,4BAA4B;AAAA,EACzC,OAAO;AACL,UAAM,KAAK,2BAA2B;AAAA,EACxC;AAEA,QAAM,KAAK,IAAI,WAAW;AAE1B,MAAI,cAAc,iBAAiB,CAAC,eAAe,MAAM,QAAQ,IAAI;AACnE,UAAM,KAAK,oDAAoD;AAAA,EACjE;AACA,MAAI,YAAY,iBAAiB,CAAC,eAAe,MAAM,MAAM,IAAI;AAC/D,UAAM,KAAK,0DAA0D;AACrE,UAAM;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AACA,MAAI,UAAU,CAAC,eAAe,MAAM,KAAK,GAAG;AAC1C,UAAM,KAAK,+DAA+D;AAC1E,UAAM,KAAK,mDAAmD;AAAA,EAChE;AACA,MAAI,WAAW;AACb,UAAM,KAAK,iDAAiD;AAAA,EAC9D;AAEA,QAAM,uBAAuB,CAAC,GAAG,iBAAiB;AAClD,MAAI,KAAK,SAAS,SAAS,WAAW,EAAG,sBAAqB,KAAK,mBAAmB;AACtF,uBAAqB,KAAK,GAAG,KAAK,SAAS,GAAG;AAC9C,QAAM,cAAc,OAAO,oBAAoB,EAAE,KAAK;AACtD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,mDAAmD,YAAY,IAAI,UAAU,EAAE,KAAK,GAAG,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,MAAI,SAAS;AACX,UAAM;AAAA,MACJ;AAAA,MACA,4BAA4B,WAAW,QAAQ,KAAK,SAAS,IAAI,EAAE,CAAC;AAAA,MACpE;AAAA,IACF;AAAA,EACF;AAEA,MAAI,mBAAmB,SAAS,GAAG;AACjC,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,gBAAgB,OAAO,GAAG;AAC5B,UAAM,KAAK,IAAI,8CAA8C;AAC7D,QAAI,SAAS;AACX,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,OAAO;AACL,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,UAAM,KAAK,0CAA0C;AACrD,UAAM,KAAK,gDAAgD;AAAA,EAC7D;AAEA,QAAM,KAAK,EAAE;AACb,MAAI,cAAe,OAAM,KAAK,6CAA6C;AAC3E,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,mBAAmB,WAAoB,QAAyB;AACvE,QAAM,QAAQ,CAAC,MAAM,eAAe,kBAAkB,qBAAqB;AAC3E,MAAI,UAAW,OAAM,KAAK,iBAAiB;AAC3C,MAAI,OAAQ,OAAM,KAAK,eAAe;AACtC,QAAM,KAAK,EAAE;AACb,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,oBAAoB,MAAwB,cAAyC;AAC5F,QAAM,CAAC,OAAO,KAAK,IAAI,KAAK,SAAS,OAAO,MAAM,GAAG;AACrD,SAAO;AAAA,IACL;AAAA,IACA,UAAU,KAAK,UAAU,iBAAiB,KAAK,IAAI,EAAE,CAAC;AAAA,IACtD;AAAA,IACA,qBAAqB,KAAK,UAAU,KAAK,KAAK,IAAI,KAAK,EAAE,CAAC;AAAA,IAC1D;AAAA,IACA,GAAG,aAAa,IAAI,CAAC,gBAAgB,KAAK,KAAK,UAAU,WAAW,CAAC,GAAG;AAAA,IACxE;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEA,SAAS,mBAAmB,MAA6C;AACvE,QAAM,eAAe,oBAAI,IAAoB;AAC7C,MAAI,KAAK,SAAS,SAAS,YAAY,GAAG;AACxC,iBAAa,IAAI,cAAc,KAAK,SAAS,UAAU;AAAA,EACzD;AACA,aAAW,eAAe,KAAK,SAAS,KAAK;AAC3C,UAAM,SAAS,oBAAoB,WAAW;AAC9C,QAAI,aAAa,IAAI,OAAO,IAAI,GAAG;AACjC,YAAM,IAAI,MAAM,0BAA0B,OAAO,IAAI,EAAE;AAAA,IACzD;AACA,iBAAa,IAAI,OAAO,MAAM,OAAO,OAAO;AAAA,EAC9C;AACA,SAAO,IAAI,IAAI,CAAC,GAAG,aAAa,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,MAAM,KAAK,cAAc,KAAK,CAAC,CAAC;AACjG;AAEA,SAAS,eAAe,MAAwB,SAAuC;AACrF,MAAI,KAAK,SAAS,SAAS,YAAY,EAAG,QAAO;AACjD,MAAI,KAAK,SAAS,SAAS,QAAQ,EAAG,QAAO,YAAY;AACzD,MAAI,KAAK,SAAS,SAAS,MAAM,EAAG,QAAO,YAAY;AACvD,SAAO,YAAY;AACrB;AAEA,SAAS,aAAa,MAAoB;AACxC,MAAI,CAAC,4BAA4B,KAAK,IAAI,GAAG;AAC3C,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB,SAAyD;AAChF,MAAI,CAAC,aAAa,SAAS,OAA8B,GAAG;AAC1D,UAAM,IAAI,MAAM,oBAAoB,OAAO,kCAAkC;AAAA,EAC/E;AACF;AAEA,SAAS,gBAAgB,SAAyD;AAChF,MAAI,CAAC,aAAa,SAAS,OAA8B,GAAG;AAC1D,UAAM,IAAI,MAAM,oBAAoB,OAAO,qCAAqC;AAAA,EAClF;AACF;AAEA,SAAS,mBAAmB,aAA2B;AACrD,MAAI,CAAC,kCAAkC,KAAK,WAAW,GAAG;AACxD,UAAM,IAAI,MAAM,wBAAwB,WAAW,EAAE;AAAA,EACvD;AACF;AAEA,SAAS,oBAAoB,aAAwD;AACnF,MAAI,KAAK,KAAK,WAAW,KAAK,oBAAoB,WAAW,GAAG;AAC9D,UAAM,IAAI,MAAM,6BAA6B,WAAW,EAAE;AAAA,EAC5D;AAEA,QAAM,YAAY,YAAY,WAAW,GAAG,IACxC,YAAY,QAAQ,KAAK,YAAY,QAAQ,GAAG,IAAI,CAAC,IACrD,YAAY,QAAQ,GAAG;AAC3B,QAAM,OAAO,cAAc,KAAK,cAAc,YAAY,MAAM,GAAG,SAAS;AAC5E,QAAM,UAAU,cAAc,KAAK,WAAW,YAAY,MAAM,YAAY,CAAC;AAE7E,MAAI,CAAC,sDAAsD,KAAK,IAAI,KAAK,CAAC,SAAS;AACjF,UAAM,IAAI,MAAM,6BAA6B,WAAW,EAAE;AAAA,EAC5D;AACA,MAAI,kBAAkB,KAAK,OAAO,KAAK,oBAAoB,OAAO,GAAG;AACnE,UAAM,IAAI,MAAM,mCAAmC,WAAW,EAAE;AAAA,EAClE;AACA,SAAO,EAAE,MAAM,QAAQ;AACzB;AAEA,SAAS,sBAAsB,aAA2B;AACxD,MAAI,CAAC,eAAe,YAAY,WAAW,GAAG,KAAK,oBAAoB,WAAW,GAAG;AACnF,UAAM,IAAI,MAAM,mCAAmC,WAAW,EAAE;AAAA,EAClE;AACF;AAEA,SAAS,gBAAgB,MAAc,SAAuB;AAC5D,MAAI,CAAC,+BAA+B,KAAK,OAAO,GAAG;AACjD,UAAM,IAAI,MAAM,WAAW,IAAI,aAAa,OAAO,EAAE;AAAA,EACvD;AACF;AAEA,SAAS,iBAAiB,KAAmB;AAC3C,MACE,CAAC,OACD,IAAI,WAAW,GAAG,KAClB,IAAI,SAAS,GAAG,KAChB,KAAK,KAAK,GAAG,KACb,oBAAoB,GAAG,GACvB;AACA,UAAM,IAAI,MAAM,6BAA6B,GAAG,EAAE;AAAA,EACpD;AACF;AAEA,SAAS,OAAO,QAAqC;AACnD,SAAO,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC;AAC5B;AAEA,SAAS,oBAAoB,OAAwB;AACnD,SAAO,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,cAAc,UAAU,WAAW,CAAC,IAAI,EAAE;AACpE;AAEA,SAAS,WAAW,OAAuB;AACzC,SAAO,IAAI,MAAM,WAAW,KAAK,OAAO,CAAC;AAC3C;;;ADvVA,IAAM,qBAAqB,oBAAI,IAAI;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAMA,qBAAoB;AAAA,EACxB,EAAE,OAAO,OAAO,OAAO,OAAO,MAAM,2CAA2C;AAAA,EAC/E,EAAE,OAAO,QAAQ,OAAO,QAAQ,MAAM,mCAAmC;AAAA,EACzE,EAAE,OAAO,MAAM,OAAO,MAAM,MAAM,iCAAiC;AAAA,EACnE,EAAE,OAAO,UAAU,OAAO,UAAU,MAAM,6BAA6B;AAAA,EACvE,EAAE,OAAO,eAAe,OAAO,eAAe,MAAM,+BAA+B;AAAA,EACnF,EAAE,OAAO,iBAAiB,OAAO,iBAAiB,MAAM,gCAAgC;AAAA,EACxF,EAAE,OAAO,eAAe,OAAO,eAAe,MAAM,oCAAoC;AAC1F;AAEA,IAAM,oBAAoB;AAAA,EACxB,EAAE,OAAO,iBAAiB,OAAO,UAAU,MAAM,yBAAyB;AAAA,EAC1E,EAAE,OAAO,gBAAgB,OAAO,SAAS,MAAM,8BAA8B;AAAA,EAC7E,EAAE,OAAO,iBAAiB,OAAO,WAAW,MAAM,iCAAiC;AAAA,EACnF,EAAE,OAAO,cAAc,OAAO,QAAQ,MAAM,0BAA0B;AAAA,EACtE,EAAE,OAAO,mBAAmB,OAAO,aAAa,MAAM,oCAAoC;AAC5F;AAEA,IAAM,mBAAmB;AAAA,EACvB,EAAE,OAAO,iBAAiB,OAAO,SAAS,MAAM,qBAAqB;AAAA,EACrE,EAAE,OAAO,0BAA0B,OAAO,kBAAkB,MAAM,uBAAuB;AAAA,EACzF,EAAE,OAAO,iBAAiB,OAAO,SAAS,MAAM,uBAAuB;AAAA,EACvE,EAAE,OAAO,uBAAuB,OAAO,gBAAgB,MAAM,6BAA6B;AAAA,EAC1F,EAAE,OAAO,kBAAkB,OAAO,UAAU,MAAM,4BAA4B;AAChF;AAEA,IAAM,YAA+B;AAAA,EACnC,KAAK,QAAQ;AAAA,EACb,MAAM,QAAQ;AAAA,EACd,OAAO,QAAQ;AAAA,EACf,QAAQ,CAAC,UAAU,QAAQ,OAAO,MAAM,KAAK;AAAA,EAC7C,QAAQ,CAAC,UAAU,QAAQ,OAAO,MAAM,KAAK;AAC/C;AAEA,eAAsB,OACpB,OAAiB,QAAQ,KAAK,MAAM,CAAC,GACrC,MAAM,QAAQ,IAAI,GAClB,KAAwB,WACxB,eAA4C,CAAC,GAC5B;AACjB,MAAI;AACJ,MAAI;AACF,cAAU,UAAU,IAAI;AAAA,EAC1B,SAAS,OAAO;AACd,OAAG,MAAM,aAAa,KAAK,CAAC;AAC5B,OAAG,IAAI,SAAS,CAAC;AACjB,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ,QAAQ,QAAQ,YAAY,QAAW;AACjD,OAAG,IAAI,SAAS,CAAC;AACjB,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,YAAY,gBAAgB;AACtC,OAAG,MAAM,oBAAoB,QAAQ,OAAO,EAAE;AAC9C,OAAG,IAAI,SAAS,CAAC;AACjB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,eACJ,QAAQ,SAAS,UAChB,QAAQ,SAAS,WAAW,KAC3B,QAAQ,SAAS,WAAW,KAC5B,QAAQ,IAAI,WAAW,KACvB,QAAQ,GAAG,WAAW;AAC1B,QAAI,cAAc;AAChB,YAAM,QAAQ,aAAa,UAAU,QAAQ,MAAM,SAAS,QAAQ,OAAO;AAC3E,UAAI,CAAC,OAAO;AACV,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AACA,YAAM,SAAS,aAAa,UAAU;AACtC,YAAM,SAAS,MAAM,OAAO,OAAO;AACnC,UAAI,WAAW,OAAW,QAAO;AACjC,gBAAU,kBAAkB,SAAS,MAAM;AAAA,IAC7C;AAEA,UAAM,QAA2B;AAAA,MAC/B,MAAM,SAAS,QAAQ,MAAM,yBAAyB;AAAA,MACtD,UAAU,QAAQ;AAAA,MAClB,UAAU,QAAQ;AAAA,MAClB,UAAU;AAAA,QACR,KAAK,QAAQ;AAAA,QACb,KAAK,QAAQ;AAAA,QACb,IAAI,QAAQ;AAAA,MACd;AAAA,MACA,UAAU,QAAQ;AAAA,IACpB;AACA,QAAI,QAAQ,QAAQ,OAAW,OAAM,MAAM,QAAQ;AAEnD,UAAM,OAAO,wBAAwB,KAAK;AAC1C,UAAM,iBAAiB,aAAa,kBAAmB,MAAM,mBAAmB;AAChF,UAAM,UAAU,0BAA0B,MAAM,cAAc;AAC9D,UAAM,aAAa,KAAK;AAAA,MACtB;AAAA,MACA,QAAQ,UAAU,KAAK,KAAK,UAAU,kBAAkB,KAAK,IAAI;AAAA,IACnE;AACA,UAAM,cAAc,oBAAoB,KAAK,UAAU;AACvD,UAAM,WAAW,6BAA6B,IAAI;AAClD,QAAI,SAAS,SAAS,GAAG;AACvB,SAAG,KAAK,mDAAmD,SAAS,KAAK,IAAI,CAAC,EAAE;AAAA,IAClF;AAEA,QAAI,QAAQ,QAAQ;AAClB,kBAAY,QAAQ,OAAO,aAAa,KAAK,KAAK,EAAE;AACpD,aAAO;AAAA,IACT;AAEA,UAAM,kBAAkB,YAAY,QAAQ,UAAU,QAAQ,OAAO,QAAQ,KAAK;AAClF,OAAG,IAAI,WAAW,WAAW,EAAE;AAE/B,QAAI,CAAC,QAAQ,OAAO;AAClB,SAAG,IAAI,EAAE;AACT,SAAG,IAAI,cAAc;AACrB,SAAG,IAAI,KAAK,aAAa,CAAC,QAAQ,YAAY,SAAS,SAAS,KAAK,KAAK,WAAW,CAAC,CAAC,EAAE;AACzF,wBAAkB,KAAK,KAAK,EAAE;AAC9B,aAAO;AAAA,IACT;AAEA,UAAM,aAAa,aAAa,cAAc;AAC9C,UAAM,WAAW;AAAA,MACf,aAAa;AAAA,MACb,KAAK,KAAK;AAAA,MACV,YAAY,QAAQ;AAAA,MACpB;AAAA,IACF,CAAC;AACD,OAAG,IAAI,SAAS,KAAK,GAAG,EAAE;AAC1B,sBAAkB,KAAK,KAAK,EAAE;AAC9B,WAAO;AAAA,EACT,SAAS,OAAO;AACd,OAAG,MAAM,aAAa,KAAK,CAAC;AAC5B,WAAO;AAAA,EACT;AACF;AAEA,eAAe,eACb,SAC+C;AAC/C,+BAA6B;AAC7B,QAAM,UAAU,MAAM,OAAO,gBAAgB;AAC7C,UAAQ,MAAM,+BAA+B;AAE7C,QAAM,aACJ,QAAQ,QACP,MAAM,QAAQ,KAAK;AAAA,IAClB,SAAS;AAAA,IACT,aAAa;AAAA,IACb,UAAU,CAAC,UACT,4BAA4B,KAAK,SAAS,EAAE,IACxC,SACA;AAAA,EACR,CAAC;AACH,MAAI,QAAQ,SAAS,UAAU,EAAG,QAAO,aAAa,OAAO;AAC7D,QAAM,OAAO,aAAa,YAAY,YAAY;AAElD,MAAI,WAAW,CAAC,GAAG,QAAQ,QAAQ;AACnC,MAAI,WAAW,CAAC,GAAG,QAAQ,QAAQ;AACnC,MACE,SAAS,WAAW,KACpB,SAAS,WAAW,KACpB,QAAQ,IAAI,WAAW,KACvB,QAAQ,GAAG,WAAW,GACtB;AACA,UAAM,eAAe,MAAM,QAAQ,YAAuD;AAAA,MACxF,SAAS;AAAA,MACT,UAAU;AAAA,MACV,SAAS;AAAA,QACP,EAAE,OAAO,QAAQ,OAAO,WAAW,MAAM,wBAAwB;AAAA,QACjE,EAAE,OAAO,OAAO,OAAO,OAAO,MAAM,wBAAwB;AAAA,QAC5D,EAAE,OAAO,UAAU,OAAO,UAAU,MAAM,sBAAsB;AAAA,QAChE,EAAE,OAAO,aAAa,OAAO,2BAA2B,MAAM,4BAA4B;AAAA,QAC1F,EAAE,OAAO,cAAc,OAAO,yBAAyB,MAAM,6BAA6B;AAAA,MAC5F;AAAA,IACF,CAAC;AACD,QAAI,QAAQ,SAAS,YAAY,EAAG,QAAO,aAAa,OAAO;AAC/D,eAAW,aAAa,OAAO,SAAS;AACxC,eAAW,aAAa,OAAO,SAAS;AAAA,EAC1C;AAEA,QAAM,YAAY,MAAM;AAAA,IACtB;AAAA,IACA;AAAA,IACAA;AAAA,IACA,QAAQ;AAAA,EACV;AACA,MAAI,cAAc,OAAW,QAAO,aAAa,OAAO;AACxD,QAAM,YAAY,MAAM;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,EACV;AACA,MAAI,cAAc,OAAW,QAAO,aAAa,OAAO;AACxD,QAAM,WAAW,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,EACV;AACA,MAAI,aAAa,OAAW,QAAO,aAAa,OAAO;AAEvD,QAAM,YACJ,QAAQ,OACP,MAAM,QAAQ,KAAK;AAAA,IAClB,SAAS;AAAA,IACT,cAAc,iBAAiB,IAAI;AAAA,EACrC,CAAC;AACH,MAAI,QAAQ,SAAS,SAAS,EAAG,QAAO,aAAa,OAAO;AAC5D,QAAM,eACJ,QAAQ,UACP,MAAM,QAAQ,KAAK;AAAA,IAClB,SAAS;AAAA,IACT,cAAc,KAAK,KAAK,UAAU,kBAAkB,IAAI;AAAA,EAC1D,CAAC;AACH,MAAI,QAAQ,SAAS,YAAY,EAAG,QAAO,aAAa,OAAO;AAE/D,QAAM,cAAc,QAAQ,gBACxB,QAAQ,QACR,MAAM,QAAQ,QAAQ,EAAE,SAAS,wBAAwB,cAAc,KAAK,CAAC;AACjF,MAAI,QAAQ,SAAS,WAAW,EAAG,QAAO,aAAa,OAAO;AAC9D,QAAM,YAAY,MAAM,QAAQ,QAAQ;AAAA,IACtC,SAAS;AAAA,IACT,cAAc;AAAA,EAChB,CAAC;AACD,MAAI,QAAQ,SAAS,SAAS,KAAK,CAAC,UAAW,QAAO,aAAa,OAAO;AAE1E,UAAQ,MAAM,qBAAqB;AACnC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,IAAI;AAAA,IACJ,KAAK,aAAa,WAAW,kBAAkB;AAAA,IAC/C,QAAQ,aAAa,cAAc,4BAA4B;AAAA,IAC/D,OAAO,cAAc,aAAa,iBAAiB;AAAA,EACrD;AACF;AAEA,eAAe,qBACb,SACA,SACA,SACA,UAC+B;AAC/B,QAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,CAAC,WAAW,OAAO,KAAK,CAAC;AAClE,QAAM,SAAS,MAAM,QAAQ,YAAoB;AAAA,IAC/C;AAAA,IACA,UAAU;AAAA,IACV,SAAS,CAAC,GAAG,OAAO;AAAA,IACpB,eAAe,SAAS,OAAO,CAAC,UAAU,aAAa,IAAI,KAAK,CAAC;AAAA,EACnE,CAAC;AACD,MAAI,QAAQ,SAAS,MAAM,EAAG,QAAO;AACrC,SAAO,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,UAAU,GAAG,MAAM,CAAC,CAAC;AAC9C;AAEA,SAAS,aAAa,SAAqD;AACzE,UAAQ,OAAO,2BAA2B;AAC1C,SAAO;AACT;AAEA,eAAe,iBAAiB,OAKd;AAChB,QAAM,gBAAgB,CAAC,SAAS,SAAS,MAAM,KAAK,MAAM,WAAW,GAAG;AAAA,IACtE,YAAY,MAAM;AAAA,IAClB,UAAU,MAAM,GAAG;AAAA,IACnB,UAAU,MAAM,GAAG;AAAA,EACrB,CAAC;AACH;AAEA,eAAe,kBACb,YACA,UACA,OACA,OACe;AACf,QAAM,aAAa,MAAM,UAAU,UAAU;AAC7C,MAAI,YAAY,eAAe,GAAG;AAChC,UAAM,IAAI,MAAM,sCAAsC,UAAU,EAAE;AAAA,EACpE;AAEA,MAAI,eAAe,QAAW;AAC5B,QAAI,CAAC,WAAW,YAAY,EAAG,OAAM,IAAI,MAAM,mCAAmC,UAAU,EAAE;AAC9F,UAAM,mBAAmB,MAAM,sBAAsB,UAAU;AAC/D,QAAI,qBAAqB,QAAW;AAClC,YAAM,IAAI;AAAA,QACR,4EAA4E,UAAU;AAAA,MACxF;AAAA,IACF;AACA,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,gEAAgE;AAE5F,eAAW,YAAY,iBAAiB,gBAAgB;AACtD,YAAM,SAAS,KAAK,KAAK,YAAY,QAAQ;AAC7C,YAAM,aAAa,MAAM,UAAU,MAAM;AACzC,UAAI,YAAY,eAAe,EAAG,OAAM,IAAI,MAAM,gCAAgC,MAAM,EAAE;AAC1F,UAAI,eAAe,OAAW,OAAM,GAAG,MAAM;AAAA,IAC/C;AAAA,EACF,OAAO;AACL,UAAM,MAAM,YAAY,EAAE,WAAW,KAAK,CAAC;AAAA,EAC7C;AAEA,aAAW,CAAC,UAAU,OAAO,KAAK,OAAO;AACvC,QAAI,CAAC,mBAAmB,IAAI,QAAQ;AAClC,YAAM,IAAI,MAAM,kCAAkC,QAAQ,EAAE;AAC9D,UAAM,SAAS,KAAK,KAAK,YAAY,QAAQ;AAC7C,UAAM,aAAa,MAAM,UAAU,MAAM;AACzC,QAAI,YAAY,eAAe,EAAG,OAAM,IAAI,MAAM,gCAAgC,MAAM,EAAE;AAC1F,UAAM,UAAU,QAAQ,SAAS,MAAM;AAAA,EACzC;AAEA,MAAI,CAAC,MAAM,IAAI,oBAAoB,KAAK,SAAS,eAAe,WAAW,MAAM,MAAM;AACrF,UAAM,IAAI,MAAM,mDAAmD;AAAA,EACrE;AACF;AAEA,eAAe,sBACb,YAC2C;AAC3C,QAAM,eAAe,KAAK,KAAK,YAAY,oBAAoB;AAC/D,QAAM,OAAO,MAAM,UAAU,YAAY;AACzC,MAAI,SAAS,OAAW,QAAO;AAC/B,MAAI,KAAK,eAAe,KAAK,CAAC,KAAK,OAAO,GAAG;AAC3C,UAAM,IAAI,MAAM,+BAA+B,YAAY,EAAE;AAAA,EAC/D;AAEA,MAAI;AACJ,MAAI;AACF,YAAQ,KAAK,MAAM,MAAM,SAAS,cAAc,MAAM,CAAC;AAAA,EACzD,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,sCAAsC,YAAY,IAAI,EAAE,OAAO,MAAM,CAAC;AAAA,EACxF;AACA,MAAI,CAAC,oBAAoB,KAAK,GAAG;AAC/B,UAAM,IAAI;AAAA,MACR,oEAAoE,YAAY;AAAA,IAClF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,OAA+C;AAC1E,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,SAAS;AACf,QAAM,cAAc,OAAO;AAC3B,QAAM,QAAQ,OAAO;AACrB,SACE,OAAO,kBAAkB,KACzB,aAAa,YAAY,oBACzB,MAAM,QAAQ,KAAK,KACnB,MAAM,MAAM,CAAC,SAAS,OAAO,SAAS,YAAY,mBAAmB,IAAI,IAAI,CAAC;AAElF;AAEA,eAAe,UAAU,QAAgB;AACvC,MAAI;AACF,WAAO,MAAM,MAAM,MAAM;AAAA,EAC3B,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,SAAU,QAAO;AAC/D,UAAM;AAAA,EACR;AACF;AAEA,SAAS,YACP,OACA,YACA,KACA,IACM;AACN,KAAG,IAAI,gBAAgB,UAAU,EAAE;AACnC,aAAW,CAAC,UAAU,OAAO,KAAK,OAAO;AACvC,OAAG,IAAI,EAAE;AACT,OAAG,IAAI,OAAO,QAAQ,EAAE;AACxB,OAAG,IAAI,QAAQ,QAAQ,CAAC;AAAA,EAC1B;AACA,KAAG,IAAI,EAAE;AACT,KAAG,IAAI,eAAe,GAAG,EAAE;AAC7B;AAEA,SAAS,kBAAkB,KAAa,IAA6B;AACnE,KAAG,IAAI,EAAE;AACT,KAAG,IAAI,0BAA0B;AACjC,KAAG,IAAI,yDAAyD;AAChE,KAAG,IAAI,EAAE;AACT,KAAG,IAAI,6CAA6C;AACpD,KAAG,IAAI,sDAAsD;AAC7D,KAAG,IAAI,cAAc,KAAK,UAAU,GAAG,CAAC,GAAG;AAC3C,KAAG,IAAI,uCAAuC;AAC9C,KAAG,IAAI,gCAAgC;AACvC,KAAG,IAAI,OAAO;AAChB;AAEA,SAAS,kBAAkB,SAAqB,QAA8C;AAC5F,QAAM,OAAmB;AAAA,IACvB,GAAG;AAAA,IACH,MAAM,OAAO;AAAA,IACb,UAAU,OAAO;AAAA,IACjB,UAAU,OAAO;AAAA,IACjB,KAAK,OAAO;AAAA,IACZ,KAAK,OAAO;AAAA,IACZ,IAAI,OAAO;AAAA,IACX,OAAO,OAAO;AAAA,IACd,eAAe;AAAA,EACjB;AACA,MAAI,OAAO,QAAQ,OAAW,MAAK,MAAM,OAAO;AAChD,MAAI,OAAO,WAAW,OAAW,MAAK,SAAS,OAAO;AACtD,SAAO;AACT;AAEA,SAAS,UAAU,MAA4B;AAC7C,QAAM,UAAsB;AAAA,IAC1B,UAAU,CAAC;AAAA,IACX,UAAU,CAAC;AAAA,IACX,KAAK,CAAC;AAAA,IACN,KAAK,CAAC;AAAA,IACN,IAAI,CAAC;AAAA,IACL,UAAU,CAAC;AAAA,IACX,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,eAAe;AAAA,IACf,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAEA,WAAS,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS,GAAG;AACnD,UAAM,WAAW,KAAK,KAAK,KAAK;AAChC,QAAI,CAAC,SAAS,WAAW,GAAG,GAAG;AAC7B,UAAI,QAAQ,YAAY,OAAW,OAAM,IAAI,MAAM,wBAAwB,QAAQ,EAAE;AACrF,cAAQ,UAAU;AAClB;AAAA,IACF;AAEA,UAAM,CAAC,MAAM,WAAW,IAAI,UAAU,QAAQ;AAC9C,UAAM,QAAQ,MAAM,eAAe,SAAS,KAAK,EAAE,KAAK,GAAG,GAAG,IAAI,oBAAoB;AACtF,YAAQ,MAAM;AAAA,MACZ,KAAK;AAAA,MACL,KAAK;AACH,gBAAQ,OAAO;AACf;AAAA,MACF,KAAK;AACH,gBAAQ,OAAO,MAAM;AACrB;AAAA,MACF,KAAK;AACH,gBAAQ,MAAM,MAAM;AACpB;AAAA,MACF,KAAK;AACH,gBAAQ,SAAS,MAAM;AACvB;AAAA,MACF,KAAK;AACH,gBAAQ,SAAS,KAAK,aAAa,MAAM,CAAC,CAAC;AAC3C;AAAA,MACF,KAAK;AACH,gBAAQ,SAAS,KAAK,aAAa,MAAM,CAAC,CAAC;AAC3C;AAAA,MACF,KAAK;AACH,gBAAQ,IAAI,KAAK,MAAM,CAAC;AACxB;AAAA,MACF,KAAK;AACH,gBAAQ,IAAI,KAAK,MAAM,CAAC;AACxB;AAAA,MACF,KAAK;AACH,gBAAQ,GAAG,KAAK,MAAM,CAAC;AACvB;AAAA,MACF,KAAK;AACH,gBAAQ,SAAS,OAAO,MAAM;AAC9B;AAAA,MACF,KAAK;AACH,gBAAQ,SAAS,OAAO,MAAM;AAC9B;AAAA,MACF,KAAK;AACH,gBAAQ,SAAS,MAAM,MAAM;AAC7B;AAAA,MACF,KAAK;AACH,gBAAQ,SAAS,SAAS,MAAM;AAChC;AAAA,MACF,KAAK;AACH,gBAAQ,SAAS,KAAK,MAAM;AAC5B;AAAA,MACF,KAAK;AACH,gBAAQ,SAAS,aAAa,MAAM;AACpC;AAAA,MACF,KAAK;AACH,gBAAQ,aAAa,MAAM;AAC3B;AAAA,MACF,KAAK;AACH,0BAAkB,MAAM,WAAW;AACnC,gBAAQ,QAAQ;AAChB,gBAAQ,gBAAgB;AACxB;AAAA,MACF,KAAK;AACH,0BAAkB,MAAM,WAAW;AACnC,gBAAQ,SAAS;AACjB;AAAA,MACF,KAAK;AACH,0BAAkB,MAAM,WAAW;AACnC,gBAAQ,QAAQ;AAChB;AAAA,MACF;AACE,cAAM,IAAI,MAAM,mBAAmB,IAAI,EAAE;AAAA,IAC7C;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,UAAU,UAAgD;AACjE,QAAM,YAAY,SAAS,QAAQ,GAAG;AACtC,SAAO,cAAc,KACjB,CAAC,UAAU,MAAS,IACpB,CAAC,SAAS,MAAM,GAAG,SAAS,GAAG,SAAS,MAAM,YAAY,CAAC,CAAC;AAClE;AAEA,SAAS,kBAAkB,MAAc,OAAiC;AACxE,MAAI,UAAU,OAAW,OAAM,IAAI,MAAM,GAAG,IAAI,2BAA2B;AAC7E;AAEA,SAAS,aAAa,OAAoC;AACxD,MAAI,UAAU,KAAK,EAAG,QAAO;AAC7B,QAAM,IAAI,MAAM,oBAAoB,KAAK,kCAAkC;AAC7E;AAEA,SAAS,aAAa,OAAoC;AACxD,MAAI,UAAU,KAAK,EAAG,QAAO;AAC7B,QAAM,IAAI,MAAM,oBAAoB,KAAK,qCAAqC;AAChF;AAEA,SAAS,UAAU,OAA6C;AAC9D,SAAO,UAAU,UAAU,UAAU,SAAS,UAAU;AAC1D;AAEA,SAAS,UAAU,OAA6C;AAC9D,SAAO,UAAU,eAAe,UAAU;AAC5C;AAEA,SAAS,+BAAqC;AAC5C,QAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC,IAAI,QAAQ,SAAS,KAAK,MAAM,GAAG,EAAE,IAAI,MAAM;AAC1E,MAAI,QAAQ,MAAO,UAAU,MAAM,QAAQ,IAAK;AAC9C,UAAM,IAAI,MAAM,sEAAsE;AAAA,EACxF;AACF;AAEA,eAAe,qBAAsC;AACnD,QAAM,cAAc,KAAK;AAAA,IACvB,MAAM,SAAS,IAAI,IAAI,mBAAmB,YAAY,GAAG,GAAG,MAAM;AAAA,EACpE;AAGA,SAAO,OAAO,YAAY,YAAY,WAAW,YAAY,UAAU;AACzE;AAEA,SAAS,oBAAoB,KAAa,QAAwB;AAChE,QAAM,WAAW,KAAK,SAAS,KAAK,MAAM;AAC1C,SAAO,YAAY,CAAC,SAAS,WAAW,IAAI,IAAI,WAAW;AAC7D;AAEA,SAAS,aAAa,MAAiC;AACrD,SAAO,KAAK,IAAI,aAAa,EAAE,KAAK,GAAG;AACzC;AAEA,SAAS,cAAc,OAAuB;AAC5C,MAAI,wBAAwB,KAAK,KAAK,EAAG,QAAO;AAChD,SAAO,IAAI,MAAM,WAAW,KAAK,OAAO,CAAC;AAC3C;AAEA,SAAS,SAAY,OAAsB,SAAoB;AAC7D,MAAI,UAAU,UAAa,UAAU,GAAI,OAAM,IAAI,MAAM,OAAO;AAChE,SAAO;AACT;AAEA,SAAS,aAAa,OAAgB,MAAsB;AAC1D,MAAI,OAAO,UAAU,SAAU,OAAM,IAAI,UAAU,GAAG,IAAI,oBAAoB;AAC9E,SAAO;AACT;AAEA,SAAS,cAAc,OAAgB,MAAuB;AAC5D,MAAI,OAAO,UAAU,UAAW,OAAM,IAAI,UAAU,GAAG,IAAI,qBAAqB;AAChF,SAAO;AACT;AAEA,SAAS,aAAa,OAAwB;AAC5C,SAAO,iBAAiB,QAAQ,MAAM,UAAU;AAClD;AAEA,SAAS,WAAmB;AAC1B,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA6BT;AAEO,SAAS,gBAAgB,WAAmB,aAA0C;AAC3F,MAAI,gBAAgB,OAAW,QAAO;AACtC,MAAI;AACF,WAAO,aAAa,KAAK,QAAQ,WAAW,CAAC,MAAM,aAAa,cAAc,SAAS,CAAC;AAAA,EAC1F,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,IAAI,gBAAgB,YAAY,KAAK,QAAQ,KAAK,CAAC,CAAC,GAAG;AACrD,SAAO,EAAE,KAAK,CAAC,SAAS;AACtB,YAAQ,WAAW;AAAA,EACrB,CAAC;AACH;","names":["commonAptPackages"]}
package/dist/index.js CHANGED
@@ -24,9 +24,13 @@ function normalizeSandboxPath(input, options = {}) {
24
24
  if (input.includes("\0")) {
25
25
  throw new DockerSandboxError("Sandbox path cannot contain null bytes.", "invalid_path");
26
26
  }
27
- const normalized = path.posix.normalize(input.replaceAll("\\", "/"));
27
+ let normalized = path.posix.normalize(input.replaceAll("\\", "/"));
28
28
  if (path.posix.isAbsolute(normalized)) {
29
- throw new DockerSandboxError(`Sandbox path must be relative: ${input}`, "invalid_path");
29
+ const workdir = options.workdir;
30
+ if (workdir === void 0 || !path.posix.isAbsolute(workdir)) {
31
+ throw new DockerSandboxError(`Sandbox path must be relative: ${input}`, "invalid_path");
32
+ }
33
+ normalized = path.posix.relative(path.posix.normalize(workdir), normalized) || ".";
30
34
  }
31
35
  if (normalized === ".." || normalized.startsWith("../")) {
32
36
  throw new DockerSandboxError(
@@ -2016,7 +2020,7 @@ var allToolNames = [
2016
2020
  var execCommandInput = z.object({
2017
2021
  command: z.string().min(1),
2018
2022
  args: z.array(z.string()).optional(),
2019
- cwd: z.string().optional(),
2023
+ cwd: z.string().describe("Workspace-relative directory or an absolute directory inside the sandbox workdir.").optional(),
2020
2024
  env: z.record(z.string(), z.string()).optional(),
2021
2025
  timeoutMs: z.number().int().positive().max(3e5).optional(),
2022
2026
  input: z.string().optional()
@@ -2041,7 +2045,7 @@ var execResultOutput = z.discriminatedUnion("status", [
2041
2045
  })
2042
2046
  ]);
2043
2047
  var readFileInput = z.object({
2044
- path: z.string().min(1),
2048
+ path: z.string().min(1).describe("Workspace-relative path or an absolute path inside the sandbox workdir."),
2045
2049
  startLine: z.number().int().positive().optional(),
2046
2050
  lineCount: z.number().int().positive().max(1e4).optional()
2047
2051
  });
@@ -2054,14 +2058,16 @@ var readFileOutput = z.object({
2054
2058
  truncatedBy: z.enum(["lines", "bytes"]).nullable()
2055
2059
  });
2056
2060
  var writeFileInput = z.object({
2057
- path: z.string().min(1),
2061
+ path: z.string().min(1).describe("Workspace-relative path or an absolute path inside the sandbox workdir."),
2058
2062
  content: z.string()
2059
2063
  });
2060
2064
  var writeFileOutput = z.object({
2061
2065
  path: z.string(),
2062
2066
  bytesWritten: z.number().int().nonnegative()
2063
2067
  });
2064
- var listFilesInput = z.object({ path: z.string().optional() });
2068
+ var listFilesInput = z.object({
2069
+ path: z.string().describe("Workspace-relative directory or an absolute directory inside the sandbox workdir.").optional()
2070
+ });
2065
2071
  var fileEntryOutput = z.object({
2066
2072
  path: z.string(),
2067
2073
  type: z.enum(["file", "directory", "symlink", "other"]),
@@ -2082,7 +2088,7 @@ var listPortsOutput = z.object({ ports: z.array(publishedPortOutput) });
2082
2088
  var startProcessInput = z.object({
2083
2089
  command: z.string().min(1),
2084
2090
  args: z.array(z.string()).optional(),
2085
- cwd: z.string().optional(),
2091
+ cwd: z.string().describe("Workspace-relative directory or an absolute directory inside the sandbox workdir.").optional(),
2086
2092
  env: z.record(z.string(), z.string()).optional()
2087
2093
  });
2088
2094
  var processInfoOutput = z.object({
@@ -2154,7 +2160,9 @@ function createExecCommandTool(options) {
2154
2160
  command
2155
2161
  };
2156
2162
  if (args !== void 0) execOptions = { ...execOptions, args };
2157
- if (cwd !== void 0) execOptions = { ...execOptions, cwd };
2163
+ if (cwd !== void 0) {
2164
+ execOptions = { ...execOptions, cwd: normalizeToolPath(options.sandbox, cwd, true) };
2165
+ }
2158
2166
  if (env !== void 0) execOptions = { ...execOptions, env };
2159
2167
  if (effectiveTimeoutMs !== void 0) {
2160
2168
  execOptions = { ...execOptions, timeoutMs: effectiveTimeoutMs };
@@ -2182,7 +2190,7 @@ function createReadFileTool(options) {
2182
2190
  );
2183
2191
  }
2184
2192
  let readOptions = {
2185
- path: path3,
2193
+ path: normalizeToolPath(options.sandbox, path3),
2186
2194
  startLine: startLine ?? 1,
2187
2195
  lineCount: effectiveLineCount,
2188
2196
  maxBytes: limits.maxBytes
@@ -2206,15 +2214,16 @@ function createWriteFileTool(options) {
2206
2214
  if (maxBytes !== void 0 && bytesWritten > maxBytes) {
2207
2215
  throw toolPolicyError(`File content exceeds policy (${bytesWritten} > ${maxBytes}).`);
2208
2216
  }
2217
+ const normalizedPath = normalizeToolPath(options.sandbox, path3);
2209
2218
  let writeOptions = {
2210
- path: path3,
2219
+ path: normalizedPath,
2211
2220
  text: content
2212
2221
  };
2213
2222
  if (context.abortSignal !== void 0) {
2214
2223
  writeOptions = { ...writeOptions, abortSignal: context.abortSignal };
2215
2224
  }
2216
2225
  await options.sandbox.writeTextFile(writeOptions);
2217
- return { path: path3, bytesWritten };
2226
+ return { path: normalizedPath, bytesWritten };
2218
2227
  }
2219
2228
  });
2220
2229
  }
@@ -2225,12 +2234,13 @@ function createListFilesTool(sandbox) {
2225
2234
  inputSchema: listFilesInput,
2226
2235
  outputSchema: listFilesOutput,
2227
2236
  execute: async ({ path: path3 }, context) => {
2237
+ const normalizedPath = path3 === void 0 ? "." : normalizeToolPath(sandbox, path3, true);
2228
2238
  let listOptions = {};
2229
- if (path3 !== void 0) listOptions = { ...listOptions, path: path3 };
2239
+ if (path3 !== void 0) listOptions = { ...listOptions, path: normalizedPath };
2230
2240
  if (context.abortSignal !== void 0) {
2231
2241
  listOptions = { ...listOptions, abortSignal: context.abortSignal };
2232
2242
  }
2233
- return { path: path3 ?? ".", entries: [...await sandbox.listFiles(listOptions)] };
2243
+ return { path: normalizedPath, entries: [...await sandbox.listFiles(listOptions)] };
2234
2244
  }
2235
2245
  });
2236
2246
  }
@@ -2253,7 +2263,9 @@ function createStartProcessTool(options) {
2253
2263
  assertCommandAllowed(command, options.exec?.commands);
2254
2264
  let startOptions = { command };
2255
2265
  if (args !== void 0) startOptions = { ...startOptions, args };
2256
- if (cwd !== void 0) startOptions = { ...startOptions, cwd };
2266
+ if (cwd !== void 0) {
2267
+ startOptions = { ...startOptions, cwd: normalizeToolPath(options.sandbox, cwd, true) };
2268
+ }
2257
2269
  if (env !== void 0) startOptions = { ...startOptions, env };
2258
2270
  if (context.abortSignal !== void 0) {
2259
2271
  startOptions = { ...startOptions, abortSignal: context.abortSignal };
@@ -2376,6 +2388,9 @@ function serializeProcessInfo(process) {
2376
2388
  if (process.endedAt !== void 0) serialized = { ...serialized, endedAt: process.endedAt };
2377
2389
  return serialized;
2378
2390
  }
2391
+ function normalizeToolPath(sandbox, input, allowRoot = false) {
2392
+ return normalizeSandboxPath(input, { allowRoot, workdir: sandbox.workdir });
2393
+ }
2379
2394
  function validateFactoryOptions(options) {
2380
2395
  if (!isRecord2(options)) {
2381
2396
  throw new TypeError("options must be an object.");