ppio-sandbox 2.1.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-GFQFOIS4.mjs → chunk-M7G3KDGF.mjs} +4 -4
- package/dist/{chunk-GFQFOIS4.mjs.map → chunk-M7G3KDGF.mjs.map} +1 -1
- package/dist/{chunk-GOSA2RSG.mjs → chunk-NRHSODSZ.mjs} +2 -2
- package/dist/{chunk-NRVME35H.mjs → chunk-RIWYGA3J.mjs} +2 -2
- package/dist/code-interpreter.js +1 -1
- package/dist/code-interpreter.js.map +1 -1
- package/dist/code-interpreter.mjs +2 -2
- package/dist/desktop.js +1 -1
- package/dist/desktop.js.map +1 -1
- package/dist/desktop.mjs +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/sandbox-5PUSVOHB.mjs +8 -0
- package/dist/sandbox-VBQLLX3L.mjs +8 -0
- package/package.json +1 -1
- package/dist/sandbox-7DONHEV2.mjs +0 -8
- package/dist/sandbox-FGY2BWMG.mjs +0 -8
- /package/dist/{chunk-GOSA2RSG.mjs.map → chunk-NRHSODSZ.mjs.map} +0 -0
- /package/dist/{chunk-NRVME35H.mjs.map → chunk-RIWYGA3J.mjs.map} +0 -0
- /package/dist/{sandbox-7DONHEV2.mjs.map → sandbox-5PUSVOHB.mjs.map} +0 -0
- /package/dist/{sandbox-FGY2BWMG.mjs.map → sandbox-VBQLLX3L.mjs.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../package.json","../src/core/utils.ts","../src/core/api/metadata.ts","../src/core/errors.ts","../src/core/logs.ts","../src/core/api/index.ts","../src/core/connectionConfig.ts","../src/core/envd/api.ts","../src/core/envd/process/process_pb.ts","../src/core/envd/versions.ts","../src/core/envd/rpc.ts","../src/core/sandbox/commands/commandHandle.ts","../src/core/sandbox/commands/pty.ts","../src/core/sandbox/commands/index.ts","../src/core/envd/filesystem/filesystem_pb.ts","../src/core/sandbox/filesystem/watchHandle.ts","../src/core/sandbox/filesystem/index.ts","../src/core/sandbox/git/utils.ts","../src/core/sandbox/git/index.ts","../src/core/secret/index.ts","../src/core/sandbox/sandboxApi.ts","../src/core/sandbox/signature.ts","../src/core/sandbox/index.ts","../src/core/template/logger.ts","../src/core/template/consts.ts","../src/core/template/utils.ts","../src/core/template/buildApi.ts","../src/core/template/readycmd.ts","../src/core/template/dockerfileParser.ts","../src/core/template/envFiles.ts","../src/core/template/imageConfig.ts","../src/core/template/types.ts","../src/core/template/index.ts","../src/core/volume/index.ts","../src/code-interpreter/messaging.ts","../src/code-interpreter/utils.ts","../src/code-interpreter/consts.ts","../src/code-interpreter/sandbox.ts","../src/desktop/utils.ts","../src/desktop/sandbox.ts","../src/core/client.ts","../src/core/sandbox/network.ts","../src/core/index.ts","../src/code-interpreter/index.ts"],"sourcesContent":["{\n \"name\": \"ppio-sandbox\",\n \"version\": \"2.1.0\",\n \"description\": \"PPIO Sandbox SDK for JavaScript/TypeScript - A comprehensive SDK for code execution, desktop automation, and cloud computing environments\",\n \"main\": \"dist/index.js\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.js\"\n },\n \"./code-interpreter\": {\n \"types\": \"./dist/code-interpreter.d.ts\",\n \"import\": \"./dist/code-interpreter.mjs\",\n \"require\": \"./dist/code-interpreter.js\"\n },\n \"./desktop\": {\n \"types\": \"./dist/desktop.d.ts\",\n \"import\": \"./dist/desktop.mjs\",\n \"require\": \"./dist/desktop.js\"\n }\n },\n \"files\": [\n \"dist/**/*\",\n \"README.md\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"check-deps\": \"knip\",\n \"update-deps\": \"ncu -u && pnpm i\",\n \"build\": \"tsc --noEmit && tsup\",\n \"dev\": \"tsup --watch\",\n \"lint:fix\": \"eslint src/**/*.ts --fix\",\n \"lint\": \"eslint src/**/*.ts tests/**/*.ts\",\n \"format\": \"prettier --write src/**/*.ts\",\n \"clean\": \"rimraf dist\",\n \"prepublishOnly\": \"pnpm build\",\n \"test:core\": \"vitest run ./src/core/ --reporter verbose --run\",\n \"test:code-interpreter\": \"vitest run ./src/code-interpreter/ --reporter verbose --run\",\n \"test:desktop\": \"vitest run ./src/desktop/ --reporter verbose --run\",\n \"generate:api\": \"python ./spec/remove_extra_tags.py sandboxes templates auth && openapi-typescript ./spec/openapi_generated.yml -x api_key --array-length --alphabetize --output src/core/api/schema.gen.ts\",\n \"generate:envd-api\": \"openapi-typescript ./spec/envd/envd.yaml -x api_key --array-length --alphabetize --output src/core/envd/schema.gen.ts\"\n },\n \"keywords\": [\n \"ppio\",\n \"ai-agent\",\n \"sandbox\",\n \"sdk\",\n \"typescript\",\n \"javascript\",\n \"code-interpreter\",\n \"desktop-automation\",\n \"cloud-computing\",\n \"remote-execution\",\n \"api-client\"\n ],\n \"author\": {\n \"name\": \"PPIO\",\n \"url\": \"https://ppio.com\"\n },\n \"engines\": {\n \"node\": \">=20\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^20.0.0\",\n \"@types/platform\": \"^1.3.6\",\n \"@types/react\": \"^19.1.12\",\n \"@typescript-eslint/eslint-plugin\": \"^6.0.0\",\n \"@typescript-eslint/parser\": \"^6.0.0\",\n \"eslint\": \"^8.0.0\",\n \"eslint-config-prettier\": \"^9.0.0\",\n \"eslint-plugin-prettier\": \"^5.0.0\",\n \"knip\": \"^5.43.6\",\n \"prettier\": \"^3.0.0\",\n \"react\": \"^18.3.1\",\n \"rimraf\": \"^5.0.0\",\n \"ts-jest\": \"^29.1.0\",\n \"ts-node\": \"^10.9.0\",\n \"typescript\": \"^5.0.0\",\n \"vitest\": \"^3.1.1\",\n \"tsup\": \"^8.4.0\",\n \"openapi-typescript\": \"^7.6.1\"\n },\n \"dependencies\": {\n \"@bufbuild/protobuf\": \"^2.6.2\",\n \"@connectrpc/connect\": \"2.0.0-rc.3\",\n \"@connectrpc/connect-web\": \"2.0.0-rc.3\",\n \"chalk\": \"^5.3.0\",\n \"compare-versions\": \"^6.1.0\",\n \"dockerfile-ast\": \"^0.7.1\",\n \"glob\": \"^11.1.0\",\n \"openapi-fetch\": \"^0.14.1\",\n \"platform\": \"^1.3.6\",\n \"tar\": \"^7.5.11\"\n },\n \"bugs\": {\n \"url\": \"https://ppio.com/about?index=2\"\n },\n \"homepage\": \"https://ppio.com/ai-computing/sandbox\",\n \"packageManager\": \"pnpm@10.17.0+sha512.fce8a3dd29a4ed2ec566fb53efbb04d8c44a0f05bc6f24a73046910fb9c3ce7afa35a0980500668fa3573345bd644644fa98338fa168235c80f4aa17aa17fbef\"\n}\n","import platform from 'platform'\n\ndeclare let window: any\n\ntype Runtime =\n | 'node'\n | 'browser'\n | 'deno'\n | 'bun'\n | 'vercel-edge'\n | 'cloudflare-worker'\n | 'unknown'\n\nfunction getRuntime(): { runtime: Runtime; version: string } {\n // @ts-ignore\n if ((globalThis as any).Bun) {\n // @ts-ignore\n return { runtime: 'bun', version: globalThis.Bun.version }\n }\n\n // @ts-ignore\n if ((globalThis as any).Deno) {\n // @ts-ignore\n return { runtime: 'deno', version: globalThis.Deno.version.deno }\n }\n\n if ((globalThis as any).process?.release?.name === 'node') {\n return { runtime: 'node', version: platform.version || 'unknown' }\n }\n\n // @ts-ignore\n if (typeof EdgeRuntime === 'string') {\n return { runtime: 'vercel-edge', version: 'unknown' }\n }\n\n if ((globalThis as any).navigator?.userAgent === 'Cloudflare-Workers') {\n return { runtime: 'cloudflare-worker', version: 'unknown' }\n }\n\n if (typeof window !== 'undefined') {\n return { runtime: 'browser', version: platform.version || 'unknown' }\n }\n\n return { runtime: 'unknown', version: 'unknown' }\n}\n\nexport const { runtime, version: runtimeVersion } = getRuntime()\n\nexport async function sha256(data: string): Promise<string> {\n // Use WebCrypto API if available\n if (typeof crypto !== 'undefined') {\n const encoder = new TextEncoder()\n const dataBuffer = encoder.encode(data)\n const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer)\n const hashArray = new Uint8Array(hashBuffer)\n return btoa(String.fromCharCode(...hashArray))\n }\n\n // Use Node.js crypto if WebCrypto is not available\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const { createHash } = require('node:crypto')\n const hash = createHash('sha256').update(data, 'utf8').digest()\n return hash.toString('base64')\n}\n\nexport function timeoutToSeconds(timeout: number): number {\n return Math.ceil(timeout / 1000)\n}\n\nexport function dynamicRequire<T>(module: string): T {\n if (runtime === 'browser') {\n throw new Error('Browser runtime is not supported for require')\n }\n\n return require(module)\n}\n\nexport async function dynamicImport<T>(module: string): Promise<T> {\n if (runtime === 'browser') {\n throw new Error('Browser runtime is not supported for dynamic import')\n }\n\n // @ts-ignore\n return await import(module)\n}\n\n// Source: https://github.com/chalk/ansi-regex/blob/main/index.js\nfunction ansiRegex({ onlyFirst = false } = {}) {\n // Valid string terminator sequences are BEL, ESC\\, and 0x9c\n const ST = '(?:\\\\u0007|\\\\u001B\\\\u005C|\\\\u009C)'\n // OSC sequences only: ESC ] ... ST (non-greedy until the first ST)\n const osc = `(?:\\\\u001B\\\\][\\\\s\\\\S]*?${ST})`\n // CSI and related: ESC/C1, optional intermediates, optional params (supports ; and :) then final byte\n const csi =\n '[\\\\u001B\\\\u009B][[\\\\]()#;?]*(?:\\\\d{1,4}(?:[;:]\\\\d{0,4})*)?[\\\\dA-PR-TZcf-nq-uy=><~]'\n\n const pattern = `${osc}|${csi}`\n\n return new RegExp(pattern, onlyFirst ? undefined : 'g')\n}\n\nexport function stripAnsi(text: string): string {\n return text.replace(ansiRegex(), '')\n}\n\nexport async function wait(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n/**\n * Convert data to a Blob, avoiding unnecessary conversions when possible.\n */\nexport function toBlob(\n data: string | ArrayBuffer | Blob | ReadableStream\n): Blob | Promise<Blob> {\n // Already a Blob - use directly\n if (data instanceof Blob) {\n return data\n }\n // String or ArrayBuffer - create Blob\n if (typeof data === 'string' || data instanceof ArrayBuffer) {\n return new Blob([data])\n }\n // ReadableStream - must consume to get Blob\n return new Response(data).blob()\n}\n\n/**\n * Escape a string for safe inclusion in a single-quoted shell argument.\n * Equivalent to Python's shlex.quote().\n */\nexport function shellQuote(s: string): string {\n return \"'\" + s.replace(/'/g, \"'\\\\''\") + \"'\"\n}\n\n/**\n * Prepare data for upload as a BodyInit, optionally gzip-compressed.\n * When gzip is enabled, compresses the data and returns a Blob.\n */\nexport async function toUploadBody(\n data: string | ArrayBuffer | Blob | ReadableStream,\n gzip?: boolean\n): Promise<BodyInit> {\n if (gzip) {\n const stream =\n data instanceof ReadableStream\n ? data\n : data instanceof Blob\n ? data.stream()\n : new Blob([data]).stream()\n const compressed = stream.pipeThrough(new CompressionStream('gzip'))\n return new Response(compressed).blob()\n }\n\n return toBlob(data)\n}\n","import platform from 'platform'\n\nimport { version } from '../../../package.json'\nimport { runtime, runtimeVersion } from '../utils'\n\nexport { version }\n\nexport const defaultHeaders = {\n browser: (typeof window !== 'undefined' && platform.name) || 'unknown',\n lang: 'js',\n lang_version: runtimeVersion,\n package_version: version,\n publisher: 'ppio',\n sdk_runtime: runtime,\n system: platform.os?.family || 'unknown',\n}\n\nexport function getEnvVar(name: string) {\n if (runtime === 'deno') {\n // @ts-ignore\n return Deno.env.get(name)\n }\n\n if (typeof process === 'undefined') {\n return ''\n }\n\n return process.env[name]\n}\n","// This is the message for the sandbox timeout error when the response code is 502/Unavailable\nexport function formatSandboxTimeoutError(message: string) {\n return new TimeoutError(\n `${message}: This error is likely due to sandbox timeout. You can modify the sandbox timeout by passing 'timeoutMs' when starting the sandbox or calling '.setTimeout' on the sandbox with the desired timeout.`\n )\n}\n\n/**\n * Base class for all sandbox errors.\n *\n * Thrown when general sandbox errors occur.\n */\nexport class SandboxError extends Error {\n constructor(message?: string, stackTrace?: string) {\n super(message)\n this.name = 'SandboxError'\n if (stackTrace) {\n this.stack = stackTrace\n }\n }\n}\n\n/**\n * Thrown when a timeout error occurs.\n *\n * The [unavailable] error type is caused by sandbox timeout.\n *\n * The [canceled] error type is caused by exceeding request timeout.\n *\n * The [deadline_exceeded] error type is caused by exceeding the timeout for command execution, watch, etc.\n *\n * The [unknown] error type is sometimes caused by the sandbox timeout when the request is not processed correctly.\n */\nexport class TimeoutError extends SandboxError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'TimeoutError'\n }\n}\n\n/**\n * Thrown when an invalid argument is provided.\n */\nexport class InvalidArgumentError extends SandboxError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'InvalidArgumentError'\n }\n}\n\n/**\n * Thrown when there is not enough disk space.\n */\nexport class NotEnoughSpaceError extends SandboxError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'NotEnoughSpaceError'\n }\n}\n\n/**\n * Thrown when a resource is not found.\n *\n * @deprecated Use {@link FileNotFoundError} or {@link SandboxNotFoundError} instead. This class will be removed in the next major version.\n */\nexport class NotFoundError extends SandboxError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'NotFoundError'\n }\n}\n\n/**\n * Thrown when a file or directory is not found inside a sandbox.\n */\nexport class FileNotFoundError extends NotFoundError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'FileNotFoundError'\n }\n}\n\n/**\n * Thrown when a sandbox is not found (e.g. it doesn't exist or is no longer running).\n */\nexport class SandboxNotFoundError extends NotFoundError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'SandboxNotFoundError'\n }\n}\n\n/**\n * Thrown when authentication fails.\n */\nexport class AuthenticationError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'AuthenticationError'\n }\n}\n\n/**\n * Thrown when git authentication fails.\n */\nexport class GitAuthError extends AuthenticationError {\n constructor(message: string) {\n super(message)\n this.name = 'GitAuthError'\n }\n}\n\n/**\n * Thrown when git upstream tracking is missing.\n */\nexport class GitUpstreamError extends SandboxError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'GitUpstreamError'\n }\n}\n\n/**\n * Thrown when the template uses old envd version. It isn't compatible with the new SDK.\n */\nexport class TemplateError extends SandboxError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'TemplateError'\n }\n}\n\n/**\n * Thrown when the API rate limit is exceeded.\n */\nexport class RateLimitError extends SandboxError {\n constructor(message: string) {\n super(message)\n this.name = 'RateLimitError'\n }\n}\n\n/**\n * Thrown when the build fails.\n */\nexport class BuildError extends Error {\n constructor(message: string, stackTrace?: string) {\n super(message)\n this.name = 'BuildError'\n if (stackTrace) {\n this.stack = stackTrace\n }\n }\n}\n\n/**\n * Thrown when the file upload fails.\n */\nexport class FileUploadError extends BuildError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'FileUploadError'\n }\n}\n\n/**\n * Base class for all volume errors.\n *\n * Thrown when general volume errors occur.\n */\nexport class VolumeError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'VolumeError'\n }\n}\n\n/**\n * Thrown when secret-related operations fail.\n */\nexport class SecretError extends SandboxError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'SecretError'\n }\n}\n","import type { Interceptor } from '@connectrpc/connect'\nimport type { Middleware } from 'openapi-fetch'\n\n/**\n * Logger interface compatible with {@link console} used for logging Sandbox messages.\n */\nexport interface Logger {\n /**\n * Debug level logging method.\n */\n debug?: (...args: any[]) => void\n /**\n * Info level logging method.\n */\n info?: (...args: any[]) => void\n /**\n * Warn level logging method.\n */\n warn?: (...args: any[]) => void\n /**\n * Error level logging method.\n */\n error?: (...args: any[]) => void\n}\n\nfunction formatLog(log: any) {\n return JSON.parse(JSON.stringify(log))\n}\n\nexport function createRpcLogger(logger: Logger): Interceptor {\n async function* logEach(stream: AsyncIterable<any>) {\n for await (const m of stream) {\n logger.debug?.('Response stream:', formatLog(m))\n yield m\n }\n }\n\n return (next) => async (req) => {\n logger.info?.(`Request: POST ${req.url}`)\n\n const res = await next(req)\n if (res.stream) {\n return {\n ...res,\n message: logEach(res.message),\n }\n } else {\n logger.info?.('Response:', formatLog(res.message))\n }\n\n return res\n }\n}\n\nexport function createApiLogger(logger: Logger): Middleware {\n return {\n async onRequest({ request }) {\n logger.info?.(`Request ${request.method} ${request.url}`)\n return request\n },\n async onResponse({ response }) {\n if (response.status >= 400) {\n logger.error?.('Response:', response.status, response.statusText)\n } else {\n logger.info?.('Response:', response.status, response.statusText)\n }\n\n return response\n },\n }\n}\n","import createClient, { FetchResponse } from 'openapi-fetch'\n\nimport type { components, paths } from './schema.gen'\nimport { defaultHeaders } from './metadata'\nimport { ConnectionConfig } from '../connectionConfig'\nimport { AuthenticationError, RateLimitError, SandboxError } from '../errors'\nimport { createApiLogger } from '../logs'\n\nexport function handleApiError(\n response: FetchResponse<any, any, any>,\n errorClass: new (\n message: string,\n stackTrace?: string\n ) => Error = SandboxError,\n stackTrace?: string\n): Error | undefined {\n // openapi-fetch returns empty string for error when response body is empty,\n // so we check !== undefined instead of truthiness\n if (response.error === undefined) {\n return\n }\n\n if (response.response.status === 401) {\n const message = 'Unauthorized, please check your credentials.'\n const content = response.error?.message ?? response.error\n\n if (content) {\n return new AuthenticationError(`${message} - ${content}`)\n }\n return new AuthenticationError(message)\n }\n\n if (response.response.status === 429) {\n const message = 'Rate limit exceeded, please try again later'\n const content = response.error?.message ?? response.error\n\n if (content) {\n return new RateLimitError(`${message} - ${content}`)\n }\n return new RateLimitError(message)\n }\n\n const message = response.error?.message ?? response.error\n return new errorClass(`${response.response.status}: ${message}`, stackTrace)\n}\n\n/**\n * Client for interacting with the PPIO sandbox API.\n */\nclass ApiClient {\n readonly api: ReturnType<typeof createClient<paths>>\n\n constructor(\n config: ConnectionConfig,\n opts: {\n requireAccessToken?: boolean\n requireApiKey?: boolean\n } = { requireAccessToken: false, requireApiKey: false }\n ) {\n if (opts?.requireApiKey && !config.apiKey) {\n throw new AuthenticationError(\n 'API key is required, please visit the Team tab at https://ppio.com/settings/key-management to get your API key. ' +\n 'You can either set the environment variable `PPIO_API_KEY` ' +\n \"or you can pass it directly to the sandbox like Sandbox.create({ apiKey: 'ppio_...' })\"\n )\n }\n\n if (opts?.requireAccessToken && !config.accessToken) {\n throw new AuthenticationError(\n 'Access token is required, please visit the Personal tab at https://ppio.com/settings/key-management to get your access token. ' +\n 'You can set the environment variable `PPIO_ACCESS_TOKEN` or pass the `accessToken` in options.'\n )\n }\n\n this.api = createClient<paths>({\n baseUrl: config.apiUrl,\n // In HTTP 1.1, all connections are considered persistent unless declared otherwise\n // keepalive: true,\n headers: {\n ...defaultHeaders,\n ...(config.apiKey && { 'X-API-KEY': config.apiKey }),\n ...(config.accessToken && {\n Authorization: `Bearer ${config.accessToken}`,\n }),\n ...config.headers,\n },\n querySerializer: {\n array: {\n style: 'form',\n explode: false,\n },\n },\n })\n\n if (config.logger) {\n this.api.use(createApiLogger(config.logger))\n }\n }\n}\n\nexport type { components, paths }\nexport { ApiClient }\n","import { Logger } from './logs'\nimport { getEnvVar, version } from './api/metadata'\n\nexport const REQUEST_TIMEOUT_MS = 60_000 // 60 seconds\nexport const LEGACY_REQUEST_TIMEOUT_MS = 1_800_000 // 30 minutes\nexport const DEFAULT_SANDBOX_TIMEOUT_MS = 300_000 // 300 seconds\nexport const KEEPALIVE_PING_INTERVAL_SEC = 50 // 50 seconds\n\nexport const KEEPALIVE_PING_HEADER = 'Keepalive-Ping-Interval'\n\nconst LEGACY_DOMAINS = [\n 'sandbox.ppio.cn',\n 'sandbox-test.ppio.cn',\n]\nconst DEFAULT_PPIO_API_URLS: Record<string, string> = {\n 'cn-beijing-1.sandbox.ppio.com':\n 'https://api.cn-beijing-1.sandbox.ppio.com',\n}\n\nexport function isLegacyDomain(domain?: string) {\n return domain ? LEGACY_DOMAINS.includes(domain) : true // use legacy domain by default\n}\n\ntype ErrorConstructor = new (message: string) => Error\n\nexport function raiseIfLegacy(\n config: ConnectionConfig,\n feature: string,\n ErrorType: ErrorConstructor = Error\n) {\n if (config.isLegacyDomain) {\n throw new ErrorType(`${feature} is not supported on legacy domains`)\n }\n}\n\nexport function validateDomain(domain: string) {\n if (!domain) {\n throw new Error('Domain cannot be empty')\n }\n}\n\nexport function normalizeApiUrl(apiUrl?: string): string | undefined {\n if (!apiUrl) return apiUrl\n return /^[a-z][a-z\\d+.-]*:\\/\\//i.test(apiUrl) ? apiUrl : `https://${apiUrl}`\n}\n\nexport function getDefaultApiUrl(domain: string, debug: boolean) {\n if (debug) {\n return 'http://localhost:3000'\n }\n return DEFAULT_PPIO_API_URLS[domain] ?? `https://api.${domain}`\n}\n\n/**\n * Connection options for requests to the API.\n */\nexport interface ConnectionOpts {\n secure?: boolean\n allowPublicTraffic?: boolean\n /**\n * PPIO sandbox API key to use for authentication.\n *\n * @default PPIO_API_KEY // environment variable\n */\n apiKey?: string\n /**\n * PPIO sandbox access token to use for authentication.\n *\n * @default PPIO_ACCESS_TOKEN // environment variable\n */\n accessToken?: string\n /**\n * Domain to use for the API.\n *\n * @default PPIO_DOMAIN // environment variable or `sandbox.ppio.cn`\n */\n domain?: string\n /**\n * API Url to use for the API.\n * @internal\n * @default PPIO_API_URL // environment variable or the default API URL for the selected domain\n */\n apiUrl?: string\n /**\n * Sandbox Url to use for the API.\n * @internal\n * @default PPIO_SANDBOX_URL // environment variable or `https://${port}-${sandboxID}.${domain}`\n */\n sandboxUrl?: string\n /**\n * If true the SDK starts in the debug mode and connects to the local envd API server.\n * @internal\n * @default PPIO_DEBUG // environment variable or `false`\n */\n debug?: boolean\n /**\n * Timeout for requests to the API in **milliseconds**.\n *\n * @default 60_000 // 60 seconds\n */\n requestTimeoutMs?: number\n /**\n * Logger to use for logging messages. It can accept any object that implements `Logger` interface—for example, {@link console}.\n */\n logger?: Logger\n\n /**\n * Additional headers to send with the request.\n */\n headers?: Record<string, string>\n\n /**\n * If true, the legacy pause endpoint waits until sandbox pause succeeds.\n * Ignored by modern domains, only used for legacy domains\n *\n * @deprecated Only used for legacy domains; ignored by modern domains.\n */\n sync?: boolean\n}\n\n/**\n * Configuration for connecting to the API.\n */\nexport class ConnectionConfig {\n public static envdPort = 49983\n\n readonly debug: boolean\n readonly domain: string\n readonly isLegacyDomain: boolean\n readonly apiUrl: string\n readonly sandboxUrl?: string\n readonly logger?: Logger\n\n readonly requestTimeoutMs: number\n\n readonly apiKey?: string\n readonly accessToken?: string\n\n readonly headers?: Record<string, string>\n\n constructor(opts?: ConnectionOpts) {\n this.apiKey = opts?.apiKey || ConnectionConfig.apiKey\n this.debug = opts?.debug || ConnectionConfig.debug\n this.domain = opts?.domain || ConnectionConfig.domain\n this.isLegacyDomain = isLegacyDomain(this.domain)\n this.accessToken = opts?.accessToken || ConnectionConfig.accessToken\n this.requestTimeoutMs =\n opts?.requestTimeoutMs ??\n (this.isLegacyDomain ? LEGACY_REQUEST_TIMEOUT_MS : REQUEST_TIMEOUT_MS)\n this.logger = opts?.logger\n this.headers = opts?.headers || {}\n this.headers['User-Agent'] = `ppio-sandbox-sdk-js/${version}`\n\n this.apiUrl =\n normalizeApiUrl(opts?.apiUrl) ||\n normalizeApiUrl(ConnectionConfig.apiUrl) ||\n getDefaultApiUrl(this.domain, this.debug)\n\n this.sandboxUrl = opts?.sandboxUrl || ConnectionConfig.sandboxUrl\n }\n\n private static get domain() {\n return getEnvVar('PPIO_DOMAIN') || 'sandbox.ppio.cn'\n }\n\n private static get apiUrl() {\n return getEnvVar('PPIO_API_URL')\n }\n\n private static get sandboxUrl() {\n return getEnvVar('PPIO_SANDBOX_URL')\n }\n\n private static get debug() {\n return (getEnvVar('PPIO_DEBUG') || 'false').toLowerCase() === 'true'\n }\n\n private static get apiKey() {\n return getEnvVar('PPIO_API_KEY')\n }\n\n private static get accessToken() {\n return getEnvVar('PPIO_ACCESS_TOKEN')\n }\n\n getSignal(requestTimeoutMs?: number) {\n const timeout = requestTimeoutMs ?? this.requestTimeoutMs\n\n return timeout ? AbortSignal.timeout(timeout) : undefined\n }\n\n getSandboxUrl(\n sandboxId: string,\n opts: { sandboxDomain: string; envdPort: number }\n ) {\n if (this.sandboxUrl) {\n return this.sandboxUrl\n }\n\n return `${this.debug ? 'http' : 'https'}://${this.getHost(sandboxId, opts.envdPort, opts.sandboxDomain)}`\n }\n\n getHost(sandboxId: string, port: number, sandboxDomain: string) {\n if (this.debug) {\n return `localhost:${port}`\n }\n\n return `${port}-${sandboxId}.${sandboxDomain ?? this.domain}`\n }\n}\n\n/**\n * User used for the operation in the sandbox.\n */\n\nexport const defaultUsername: Username = 'user'\nexport type Username = string\n","import createClient from 'openapi-fetch'\n\nimport type { components, paths } from './schema.gen'\nimport { ConnectionConfig } from '../connectionConfig'\nimport { createApiLogger } from '../logs'\nimport {\n SandboxError,\n InvalidArgumentError,\n NotFoundError,\n NotEnoughSpaceError,\n SandboxNotFoundError,\n formatSandboxTimeoutError,\n AuthenticationError,\n} from '../errors'\nimport { StartResponse, ConnectResponse } from './process/process_pb'\nimport { Code, ConnectError } from '@connectrpc/connect'\nimport { WatchDirResponse } from './filesystem/filesystem_pb'\n\ntype ApiError = { message?: string } | string\n\nconst DEFAULT_ERROR_MAP: Record<number, (message: string) => Error> = {\n 400: (message) => new InvalidArgumentError(message),\n 401: (message) => new AuthenticationError(message),\n 404: (message) => new NotFoundError(message),\n 429: (message) =>\n new SandboxError(`${message}: The requests are being rate limited.`),\n 502: formatSandboxTimeoutError,\n 507: (message) => new NotEnoughSpaceError(message),\n}\n\n/**\n * Handles errors from envd API responses by mapping HTTP status codes to specific error types.\n *\n * @param res - The API response object containing an optional error and the raw `Response`.\n * @param errorMap - Optional map of HTTP status codes to error factory functions that override the defaults.\n * @returns The corresponding `Error` instance if an error is present, or `undefined` if the response is successful.\n */\nexport async function handleEnvdApiError(\n res: {\n error?: ApiError\n response: Response\n },\n errorMap?: Record<number, (message: string) => Error>\n) {\n if (!res.error) {\n return\n }\n\n const message: string =\n typeof res.error == 'string'\n ? res.error\n : res.error?.message || (await res.response.text())\n\n // Check if a custom error mapping is provided for this error code\n if (errorMap && res.response.status in errorMap) {\n return errorMap[res.response.status]?.(message)\n }\n\n // Check if there is a default error mapping for this error code\n if (res.response.status in DEFAULT_ERROR_MAP) {\n return DEFAULT_ERROR_MAP[res.response.status]?.(message)\n }\n\n // Fallback to a generic SandboxError if no specific mapping is found\n return new SandboxError(`${res.response.status}: ${message}`)\n}\n\nexport async function handleProcessStartEvent(\n events: AsyncIterable<StartResponse | ConnectResponse>\n) {\n let startEvent: StartResponse | ConnectResponse\n\n try {\n startEvent = (await events[Symbol.asyncIterator]().next()).value\n } catch (err) {\n if (err instanceof ConnectError) {\n if (err.code === Code.Unavailable) {\n throw new SandboxNotFoundError(\n 'Sandbox is probably not running anymore'\n )\n }\n }\n\n throw err\n }\n if (startEvent.event?.event.case !== 'start') {\n throw new Error('Expected start event')\n }\n\n return startEvent.event.event.value.pid\n}\n\nexport async function handleWatchDirStartEvent(\n events: AsyncIterable<WatchDirResponse>\n) {\n let startEvent: WatchDirResponse\n\n try {\n startEvent = (await events[Symbol.asyncIterator]().next()).value\n } catch (err) {\n if (err instanceof ConnectError) {\n if (err.code === Code.Unavailable) {\n throw new SandboxNotFoundError(\n 'Sandbox is probably not running anymore'\n )\n }\n }\n\n throw err\n }\n if (startEvent.event?.case !== 'start') {\n throw new Error('Expected start event')\n }\n\n return startEvent.event.value\n}\n\nclass EnvdApiClient {\n readonly api: ReturnType<typeof createClient<paths>>\n readonly version: string\n\n constructor(\n config: Pick<ConnectionConfig, 'apiUrl' | 'logger' | 'accessToken'> & {\n fetch?: (request: Request) => ReturnType<typeof fetch>\n headers?: Record<string, string>\n },\n metadata: {\n version: string\n }\n ) {\n this.api = createClient({\n baseUrl: config.apiUrl,\n fetch: config?.fetch,\n headers: config?.headers,\n // In HTTP 1.1, all connections are considered persistent unless declared otherwise\n // keepalive: true,\n })\n this.version = metadata.version\n\n if (config.logger) {\n this.api.use(createApiLogger(config.logger))\n }\n }\n}\n\nexport type { components, paths }\nexport { EnvdApiClient }\n","// @generated by protoc-gen-es v2.6.2 with parameter \"target=ts\"\n// @generated from file process/process.proto (package process, syntax proto3)\n/* eslint-disable */\n\nimport type {\n GenEnum,\n GenFile,\n GenMessage,\n GenService,\n} from '@bufbuild/protobuf/codegenv2'\nimport {\n enumDesc,\n fileDesc,\n messageDesc,\n serviceDesc,\n} from '@bufbuild/protobuf/codegenv2'\nimport type { Message } from '@bufbuild/protobuf'\n\n/**\n * Describes the file process/process.proto.\n */\nexport const file_process_process: GenFile =\n /*@__PURE__*/\n fileDesc(\n 'ChVwcm9jZXNzL3Byb2Nlc3MucHJvdG8SB3Byb2Nlc3MiSgoDUFRZEh8KBHNpemUYASABKAsyES5wcm9jZXNzLlBUWS5TaXplGiIKBFNpemUSDAoEY29scxgBIAEoDRIMCgRyb3dzGAIgASgNIqEBCg1Qcm9jZXNzQ29uZmlnEgsKA2NtZBgBIAEoCRIMCgRhcmdzGAIgAygJEi4KBGVudnMYAyADKAsyIC5wcm9jZXNzLlByb2Nlc3NDb25maWcuRW52c0VudHJ5EhAKA2N3ZBgEIAEoCUgAiAEBGisKCUVudnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBQgYKBF9jd2QiDQoLTGlzdFJlcXVlc3QiXAoLUHJvY2Vzc0luZm8SJgoGY29uZmlnGAEgASgLMhYucHJvY2Vzcy5Qcm9jZXNzQ29uZmlnEgsKA3BpZBgCIAEoDRIQCgN0YWcYAyABKAlIAIgBAUIGCgRfdGFnIjcKDExpc3RSZXNwb25zZRInCglwcm9jZXNzZXMYASADKAsyFC5wcm9jZXNzLlByb2Nlc3NJbmZvIpcBCgxTdGFydFJlcXVlc3QSJwoHcHJvY2VzcxgBIAEoCzIWLnByb2Nlc3MuUHJvY2Vzc0NvbmZpZxIeCgNwdHkYAiABKAsyDC5wcm9jZXNzLlBUWUgAiAEBEhAKA3RhZxgDIAEoCUgBiAEBEhIKBXN0ZGluGAQgASgISAKIAQFCBgoEX3B0eUIGCgRfdGFnQggKBl9zdGRpbiJiCg1VcGRhdGVSZXF1ZXN0EikKB3Byb2Nlc3MYASABKAsyGC5wcm9jZXNzLlByb2Nlc3NTZWxlY3RvchIeCgNwdHkYAiABKAsyDC5wcm9jZXNzLlBUWUgAiAEBQgYKBF9wdHkiEAoOVXBkYXRlUmVzcG9uc2UirwMKDFByb2Nlc3NFdmVudBIxCgVzdGFydBgBIAEoCzIgLnByb2Nlc3MuUHJvY2Vzc0V2ZW50LlN0YXJ0RXZlbnRIABIvCgRkYXRhGAIgASgLMh8ucHJvY2Vzcy5Qcm9jZXNzRXZlbnQuRGF0YUV2ZW50SAASLQoDZW5kGAMgASgLMh4ucHJvY2Vzcy5Qcm9jZXNzRXZlbnQuRW5kRXZlbnRIABI0CglrZWVwYWxpdmUYBCABKAsyHy5wcm9jZXNzLlByb2Nlc3NFdmVudC5LZWVwQWxpdmVIABoZCgpTdGFydEV2ZW50EgsKA3BpZBgBIAEoDRpICglEYXRhRXZlbnQSEAoGc3Rkb3V0GAEgASgMSAASEAoGc3RkZXJyGAIgASgMSAASDQoDcHR5GAMgASgMSABCCAoGb3V0cHV0GlsKCEVuZEV2ZW50EhEKCWV4aXRfY29kZRgBIAEoERIOCgZleGl0ZWQYAiABKAgSDgoGc3RhdHVzGAMgASgJEhIKBWVycm9yGAQgASgJSACIAQFCCAoGX2Vycm9yGgsKCUtlZXBBbGl2ZUIHCgVldmVudCI1Cg1TdGFydFJlc3BvbnNlEiQKBWV2ZW50GAEgASgLMhUucHJvY2Vzcy5Qcm9jZXNzRXZlbnQiNwoPQ29ubmVjdFJlc3BvbnNlEiQKBWV2ZW50GAEgASgLMhUucHJvY2Vzcy5Qcm9jZXNzRXZlbnQiYwoQU2VuZElucHV0UmVxdWVzdBIpCgdwcm9jZXNzGAEgASgLMhgucHJvY2Vzcy5Qcm9jZXNzU2VsZWN0b3ISJAoFaW5wdXQYAiABKAsyFS5wcm9jZXNzLlByb2Nlc3NJbnB1dCITChFTZW5kSW5wdXRSZXNwb25zZSI3CgxQcm9jZXNzSW5wdXQSDwoFc3RkaW4YASABKAxIABINCgNwdHkYAiABKAxIAEIHCgVpbnB1dCLCAgoSU3RyZWFtSW5wdXRSZXF1ZXN0EjcKBXN0YXJ0GAEgASgLMiYucHJvY2Vzcy5TdHJlYW1JbnB1dFJlcXVlc3QuU3RhcnRFdmVudEgAEjUKBGRhdGEYAiABKAsyJS5wcm9jZXNzLlN0cmVhbUlucHV0UmVxdWVzdC5EYXRhRXZlbnRIABI6CglrZWVwYWxpdmUYAyABKAsyJS5wcm9jZXNzLlN0cmVhbUlucHV0UmVxdWVzdC5LZWVwQWxpdmVIABo3CgpTdGFydEV2ZW50EikKB3Byb2Nlc3MYASABKAsyGC5wcm9jZXNzLlByb2Nlc3NTZWxlY3RvchoxCglEYXRhRXZlbnQSJAoFaW5wdXQYAiABKAsyFS5wcm9jZXNzLlByb2Nlc3NJbnB1dBoLCglLZWVwQWxpdmVCBwoFZXZlbnQiFQoTU3RyZWFtSW5wdXRSZXNwb25zZSJfChFTZW5kU2lnbmFsUmVxdWVzdBIpCgdwcm9jZXNzGAEgASgLMhgucHJvY2Vzcy5Qcm9jZXNzU2VsZWN0b3ISHwoGc2lnbmFsGAIgASgOMg8ucHJvY2Vzcy5TaWduYWwiFAoSU2VuZFNpZ25hbFJlc3BvbnNlIj4KEUNsb3NlU3RkaW5SZXF1ZXN0EikKB3Byb2Nlc3MYASABKAsyGC5wcm9jZXNzLlByb2Nlc3NTZWxlY3RvciIUChJDbG9zZVN0ZGluUmVzcG9uc2UiOwoOQ29ubmVjdFJlcXVlc3QSKQoHcHJvY2VzcxgBIAEoCzIYLnByb2Nlc3MuUHJvY2Vzc1NlbGVjdG9yIjsKD1Byb2Nlc3NTZWxlY3RvchINCgNwaWQYASABKA1IABINCgN0YWcYAiABKAlIAEIKCghzZWxlY3RvcipICgZTaWduYWwSFgoSU0lHTkFMX1VOU1BFQ0lGSUVEEAASEgoOU0lHTkFMX1NJR1RFUk0QDxISCg5TSUdOQUxfU0lHS0lMTBAJMpEECgdQcm9jZXNzEjMKBExpc3QSFC5wcm9jZXNzLkxpc3RSZXF1ZXN0GhUucHJvY2Vzcy5MaXN0UmVzcG9uc2USPgoHQ29ubmVjdBIXLnByb2Nlc3MuQ29ubmVjdFJlcXVlc3QaGC5wcm9jZXNzLkNvbm5lY3RSZXNwb25zZTABEjgKBVN0YXJ0EhUucHJvY2Vzcy5TdGFydFJlcXVlc3QaFi5wcm9jZXNzLlN0YXJ0UmVzcG9uc2UwARI5CgZVcGRhdGUSFi5wcm9jZXNzLlVwZGF0ZVJlcXVlc3QaFy5wcm9jZXNzLlVwZGF0ZVJlc3BvbnNlEkoKC1N0cmVhbUlucHV0EhsucHJvY2Vzcy5TdHJlYW1JbnB1dFJlcXVlc3QaHC5wcm9jZXNzLlN0cmVhbUlucHV0UmVzcG9uc2UoARJCCglTZW5kSW5wdXQSGS5wcm9jZXNzLlNlbmRJbnB1dFJlcXVlc3QaGi5wcm9jZXNzLlNlbmRJbnB1dFJlc3BvbnNlEkUKClNlbmRTaWduYWwSGi5wcm9jZXNzLlNlbmRTaWduYWxSZXF1ZXN0GhsucHJvY2Vzcy5TZW5kU2lnbmFsUmVzcG9uc2USRQoKQ2xvc2VTdGRpbhIaLnByb2Nlc3MuQ2xvc2VTdGRpblJlcXVlc3QaGy5wcm9jZXNzLkNsb3NlU3RkaW5SZXNwb25zZUJXCgtjb20ucHJvY2Vzc0IMUHJvY2Vzc1Byb3RvUAGiAgNQWFiqAgdQcm9jZXNzygIHUHJvY2Vzc+ICE1Byb2Nlc3NcR1BCTWV0YWRhdGHqAgdQcm9jZXNzYgZwcm90bzM'\n )\n\n/**\n * @generated from message process.PTY\n */\nexport type PTY = Message<'process.PTY'> & {\n /**\n * @generated from field: process.PTY.Size size = 1;\n */\n size?: PTY_Size\n}\n\n/**\n * Describes the message process.PTY.\n * Use `create(PTYSchema)` to create a new message.\n */\nexport const PTYSchema: GenMessage<PTY> =\n /*@__PURE__*/\n messageDesc(file_process_process, 0)\n\n/**\n * @generated from message process.PTY.Size\n */\nexport type PTY_Size = Message<'process.PTY.Size'> & {\n /**\n * @generated from field: uint32 cols = 1;\n */\n cols: number\n\n /**\n * @generated from field: uint32 rows = 2;\n */\n rows: number\n}\n\n/**\n * Describes the message process.PTY.Size.\n * Use `create(PTY_SizeSchema)` to create a new message.\n */\nexport const PTY_SizeSchema: GenMessage<PTY_Size> =\n /*@__PURE__*/\n messageDesc(file_process_process, 0, 0)\n\n/**\n * @generated from message process.ProcessConfig\n */\nexport type ProcessConfig = Message<'process.ProcessConfig'> & {\n /**\n * @generated from field: string cmd = 1;\n */\n cmd: string\n\n /**\n * @generated from field: repeated string args = 2;\n */\n args: string[]\n\n /**\n * @generated from field: map<string, string> envs = 3;\n */\n envs: { [key: string]: string }\n\n /**\n * @generated from field: optional string cwd = 4;\n */\n cwd?: string\n}\n\n/**\n * Describes the message process.ProcessConfig.\n * Use `create(ProcessConfigSchema)` to create a new message.\n */\nexport const ProcessConfigSchema: GenMessage<ProcessConfig> =\n /*@__PURE__*/\n messageDesc(file_process_process, 1)\n\n/**\n * @generated from message process.ListRequest\n */\nexport type ListRequest = Message<'process.ListRequest'> & {}\n\n/**\n * Describes the message process.ListRequest.\n * Use `create(ListRequestSchema)` to create a new message.\n */\nexport const ListRequestSchema: GenMessage<ListRequest> =\n /*@__PURE__*/\n messageDesc(file_process_process, 2)\n\n/**\n * @generated from message process.ProcessInfo\n */\nexport type ProcessInfo = Message<'process.ProcessInfo'> & {\n /**\n * @generated from field: process.ProcessConfig config = 1;\n */\n config?: ProcessConfig\n\n /**\n * @generated from field: uint32 pid = 2;\n */\n pid: number\n\n /**\n * @generated from field: optional string tag = 3;\n */\n tag?: string\n}\n\n/**\n * Describes the message process.ProcessInfo.\n * Use `create(ProcessInfoSchema)` to create a new message.\n */\nexport const ProcessInfoSchema: GenMessage<ProcessInfo> =\n /*@__PURE__*/\n messageDesc(file_process_process, 3)\n\n/**\n * @generated from message process.ListResponse\n */\nexport type ListResponse = Message<'process.ListResponse'> & {\n /**\n * @generated from field: repeated process.ProcessInfo processes = 1;\n */\n processes: ProcessInfo[]\n}\n\n/**\n * Describes the message process.ListResponse.\n * Use `create(ListResponseSchema)` to create a new message.\n */\nexport const ListResponseSchema: GenMessage<ListResponse> =\n /*@__PURE__*/\n messageDesc(file_process_process, 4)\n\n/**\n * @generated from message process.StartRequest\n */\nexport type StartRequest = Message<'process.StartRequest'> & {\n /**\n * @generated from field: process.ProcessConfig process = 1;\n */\n process?: ProcessConfig\n\n /**\n * @generated from field: optional process.PTY pty = 2;\n */\n pty?: PTY\n\n /**\n * @generated from field: optional string tag = 3;\n */\n tag?: string\n\n /**\n * @generated from field: optional bool stdin = 4;\n */\n stdin?: boolean\n}\n\n/**\n * Describes the message process.StartRequest.\n * Use `create(StartRequestSchema)` to create a new message.\n */\nexport const StartRequestSchema: GenMessage<StartRequest> =\n /*@__PURE__*/\n messageDesc(file_process_process, 5)\n\n/**\n * @generated from message process.UpdateRequest\n */\nexport type UpdateRequest = Message<'process.UpdateRequest'> & {\n /**\n * @generated from field: process.ProcessSelector process = 1;\n */\n process?: ProcessSelector\n\n /**\n * @generated from field: optional process.PTY pty = 2;\n */\n pty?: PTY\n}\n\n/**\n * Describes the message process.UpdateRequest.\n * Use `create(UpdateRequestSchema)` to create a new message.\n */\nexport const UpdateRequestSchema: GenMessage<UpdateRequest> =\n /*@__PURE__*/\n messageDesc(file_process_process, 6)\n\n/**\n * @generated from message process.UpdateResponse\n */\nexport type UpdateResponse = Message<'process.UpdateResponse'> & {}\n\n/**\n * Describes the message process.UpdateResponse.\n * Use `create(UpdateResponseSchema)` to create a new message.\n */\nexport const UpdateResponseSchema: GenMessage<UpdateResponse> =\n /*@__PURE__*/\n messageDesc(file_process_process, 7)\n\n/**\n * @generated from message process.ProcessEvent\n */\nexport type ProcessEvent = Message<'process.ProcessEvent'> & {\n /**\n * @generated from oneof process.ProcessEvent.event\n */\n event:\n | {\n /**\n * @generated from field: process.ProcessEvent.StartEvent start = 1;\n */\n value: ProcessEvent_StartEvent\n case: 'start'\n }\n | {\n /**\n * @generated from field: process.ProcessEvent.DataEvent data = 2;\n */\n value: ProcessEvent_DataEvent\n case: 'data'\n }\n | {\n /**\n * @generated from field: process.ProcessEvent.EndEvent end = 3;\n */\n value: ProcessEvent_EndEvent\n case: 'end'\n }\n | {\n /**\n * @generated from field: process.ProcessEvent.KeepAlive keepalive = 4;\n */\n value: ProcessEvent_KeepAlive\n case: 'keepalive'\n }\n | { case: undefined; value?: undefined }\n}\n\n/**\n * Describes the message process.ProcessEvent.\n * Use `create(ProcessEventSchema)` to create a new message.\n */\nexport const ProcessEventSchema: GenMessage<ProcessEvent> =\n /*@__PURE__*/\n messageDesc(file_process_process, 8)\n\n/**\n * @generated from message process.ProcessEvent.StartEvent\n */\nexport type ProcessEvent_StartEvent =\n Message<'process.ProcessEvent.StartEvent'> & {\n /**\n * @generated from field: uint32 pid = 1;\n */\n pid: number\n }\n\n/**\n * Describes the message process.ProcessEvent.StartEvent.\n * Use `create(ProcessEvent_StartEventSchema)` to create a new message.\n */\nexport const ProcessEvent_StartEventSchema: GenMessage<ProcessEvent_StartEvent> =\n /*@__PURE__*/\n messageDesc(file_process_process, 8, 0)\n\n/**\n * @generated from message process.ProcessEvent.DataEvent\n */\nexport type ProcessEvent_DataEvent =\n Message<'process.ProcessEvent.DataEvent'> & {\n /**\n * @generated from oneof process.ProcessEvent.DataEvent.output\n */\n output:\n | {\n /**\n * @generated from field: bytes stdout = 1;\n */\n value: Uint8Array\n case: 'stdout'\n }\n | {\n /**\n * @generated from field: bytes stderr = 2;\n */\n value: Uint8Array\n case: 'stderr'\n }\n | {\n /**\n * @generated from field: bytes pty = 3;\n */\n value: Uint8Array\n case: 'pty'\n }\n | { case: undefined; value?: undefined }\n }\n\n/**\n * Describes the message process.ProcessEvent.DataEvent.\n * Use `create(ProcessEvent_DataEventSchema)` to create a new message.\n */\nexport const ProcessEvent_DataEventSchema: GenMessage<ProcessEvent_DataEvent> =\n /*@__PURE__*/\n messageDesc(file_process_process, 8, 1)\n\n/**\n * @generated from message process.ProcessEvent.EndEvent\n */\nexport type ProcessEvent_EndEvent = Message<'process.ProcessEvent.EndEvent'> & {\n /**\n * @generated from field: sint32 exit_code = 1;\n */\n exitCode: number\n\n /**\n * @generated from field: bool exited = 2;\n */\n exited: boolean\n\n /**\n * @generated from field: string status = 3;\n */\n status: string\n\n /**\n * @generated from field: optional string error = 4;\n */\n error?: string\n}\n\n/**\n * Describes the message process.ProcessEvent.EndEvent.\n * Use `create(ProcessEvent_EndEventSchema)` to create a new message.\n */\nexport const ProcessEvent_EndEventSchema: GenMessage<ProcessEvent_EndEvent> =\n /*@__PURE__*/\n messageDesc(file_process_process, 8, 2)\n\n/**\n * @generated from message process.ProcessEvent.KeepAlive\n */\nexport type ProcessEvent_KeepAlive =\n Message<'process.ProcessEvent.KeepAlive'> & {}\n\n/**\n * Describes the message process.ProcessEvent.KeepAlive.\n * Use `create(ProcessEvent_KeepAliveSchema)` to create a new message.\n */\nexport const ProcessEvent_KeepAliveSchema: GenMessage<ProcessEvent_KeepAlive> =\n /*@__PURE__*/\n messageDesc(file_process_process, 8, 3)\n\n/**\n * @generated from message process.StartResponse\n */\nexport type StartResponse = Message<'process.StartResponse'> & {\n /**\n * @generated from field: process.ProcessEvent event = 1;\n */\n event?: ProcessEvent\n}\n\n/**\n * Describes the message process.StartResponse.\n * Use `create(StartResponseSchema)` to create a new message.\n */\nexport const StartResponseSchema: GenMessage<StartResponse> =\n /*@__PURE__*/\n messageDesc(file_process_process, 9)\n\n/**\n * @generated from message process.ConnectResponse\n */\nexport type ConnectResponse = Message<'process.ConnectResponse'> & {\n /**\n * @generated from field: process.ProcessEvent event = 1;\n */\n event?: ProcessEvent\n}\n\n/**\n * Describes the message process.ConnectResponse.\n * Use `create(ConnectResponseSchema)` to create a new message.\n */\nexport const ConnectResponseSchema: GenMessage<ConnectResponse> =\n /*@__PURE__*/\n messageDesc(file_process_process, 10)\n\n/**\n * @generated from message process.SendInputRequest\n */\nexport type SendInputRequest = Message<'process.SendInputRequest'> & {\n /**\n * @generated from field: process.ProcessSelector process = 1;\n */\n process?: ProcessSelector\n\n /**\n * @generated from field: process.ProcessInput input = 2;\n */\n input?: ProcessInput\n}\n\n/**\n * Describes the message process.SendInputRequest.\n * Use `create(SendInputRequestSchema)` to create a new message.\n */\nexport const SendInputRequestSchema: GenMessage<SendInputRequest> =\n /*@__PURE__*/\n messageDesc(file_process_process, 11)\n\n/**\n * @generated from message process.SendInputResponse\n */\nexport type SendInputResponse = Message<'process.SendInputResponse'> & {}\n\n/**\n * Describes the message process.SendInputResponse.\n * Use `create(SendInputResponseSchema)` to create a new message.\n */\nexport const SendInputResponseSchema: GenMessage<SendInputResponse> =\n /*@__PURE__*/\n messageDesc(file_process_process, 12)\n\n/**\n * @generated from message process.ProcessInput\n */\nexport type ProcessInput = Message<'process.ProcessInput'> & {\n /**\n * @generated from oneof process.ProcessInput.input\n */\n input:\n | {\n /**\n * @generated from field: bytes stdin = 1;\n */\n value: Uint8Array\n case: 'stdin'\n }\n | {\n /**\n * @generated from field: bytes pty = 2;\n */\n value: Uint8Array\n case: 'pty'\n }\n | { case: undefined; value?: undefined }\n}\n\n/**\n * Describes the message process.ProcessInput.\n * Use `create(ProcessInputSchema)` to create a new message.\n */\nexport const ProcessInputSchema: GenMessage<ProcessInput> =\n /*@__PURE__*/\n messageDesc(file_process_process, 13)\n\n/**\n * @generated from message process.StreamInputRequest\n */\nexport type StreamInputRequest = Message<'process.StreamInputRequest'> & {\n /**\n * @generated from oneof process.StreamInputRequest.event\n */\n event:\n | {\n /**\n * @generated from field: process.StreamInputRequest.StartEvent start = 1;\n */\n value: StreamInputRequest_StartEvent\n case: 'start'\n }\n | {\n /**\n * @generated from field: process.StreamInputRequest.DataEvent data = 2;\n */\n value: StreamInputRequest_DataEvent\n case: 'data'\n }\n | {\n /**\n * @generated from field: process.StreamInputRequest.KeepAlive keepalive = 3;\n */\n value: StreamInputRequest_KeepAlive\n case: 'keepalive'\n }\n | { case: undefined; value?: undefined }\n}\n\n/**\n * Describes the message process.StreamInputRequest.\n * Use `create(StreamInputRequestSchema)` to create a new message.\n */\nexport const StreamInputRequestSchema: GenMessage<StreamInputRequest> =\n /*@__PURE__*/\n messageDesc(file_process_process, 14)\n\n/**\n * @generated from message process.StreamInputRequest.StartEvent\n */\nexport type StreamInputRequest_StartEvent =\n Message<'process.StreamInputRequest.StartEvent'> & {\n /**\n * @generated from field: process.ProcessSelector process = 1;\n */\n process?: ProcessSelector\n }\n\n/**\n * Describes the message process.StreamInputRequest.StartEvent.\n * Use `create(StreamInputRequest_StartEventSchema)` to create a new message.\n */\nexport const StreamInputRequest_StartEventSchema: GenMessage<StreamInputRequest_StartEvent> =\n /*@__PURE__*/\n messageDesc(file_process_process, 14, 0)\n\n/**\n * @generated from message process.StreamInputRequest.DataEvent\n */\nexport type StreamInputRequest_DataEvent =\n Message<'process.StreamInputRequest.DataEvent'> & {\n /**\n * @generated from field: process.ProcessInput input = 2;\n */\n input?: ProcessInput\n }\n\n/**\n * Describes the message process.StreamInputRequest.DataEvent.\n * Use `create(StreamInputRequest_DataEventSchema)` to create a new message.\n */\nexport const StreamInputRequest_DataEventSchema: GenMessage<StreamInputRequest_DataEvent> =\n /*@__PURE__*/\n messageDesc(file_process_process, 14, 1)\n\n/**\n * @generated from message process.StreamInputRequest.KeepAlive\n */\nexport type StreamInputRequest_KeepAlive =\n Message<'process.StreamInputRequest.KeepAlive'> & {}\n\n/**\n * Describes the message process.StreamInputRequest.KeepAlive.\n * Use `create(StreamInputRequest_KeepAliveSchema)` to create a new message.\n */\nexport const StreamInputRequest_KeepAliveSchema: GenMessage<StreamInputRequest_KeepAlive> =\n /*@__PURE__*/\n messageDesc(file_process_process, 14, 2)\n\n/**\n * @generated from message process.StreamInputResponse\n */\nexport type StreamInputResponse = Message<'process.StreamInputResponse'> & {}\n\n/**\n * Describes the message process.StreamInputResponse.\n * Use `create(StreamInputResponseSchema)` to create a new message.\n */\nexport const StreamInputResponseSchema: GenMessage<StreamInputResponse> =\n /*@__PURE__*/\n messageDesc(file_process_process, 15)\n\n/**\n * @generated from message process.SendSignalRequest\n */\nexport type SendSignalRequest = Message<'process.SendSignalRequest'> & {\n /**\n * @generated from field: process.ProcessSelector process = 1;\n */\n process?: ProcessSelector\n\n /**\n * @generated from field: process.Signal signal = 2;\n */\n signal: Signal\n}\n\n/**\n * Describes the message process.SendSignalRequest.\n * Use `create(SendSignalRequestSchema)` to create a new message.\n */\nexport const SendSignalRequestSchema: GenMessage<SendSignalRequest> =\n /*@__PURE__*/\n messageDesc(file_process_process, 16)\n\n/**\n * @generated from message process.SendSignalResponse\n */\nexport type SendSignalResponse = Message<'process.SendSignalResponse'> & {}\n\n/**\n * Describes the message process.SendSignalResponse.\n * Use `create(SendSignalResponseSchema)` to create a new message.\n */\nexport const SendSignalResponseSchema: GenMessage<SendSignalResponse> =\n /*@__PURE__*/\n messageDesc(file_process_process, 17)\n\n/**\n * @generated from message process.CloseStdinRequest\n */\nexport type CloseStdinRequest = Message<'process.CloseStdinRequest'> & {\n /**\n * @generated from field: process.ProcessSelector process = 1;\n */\n process?: ProcessSelector\n}\n\n/**\n * Describes the message process.CloseStdinRequest.\n * Use `create(CloseStdinRequestSchema)` to create a new message.\n */\nexport const CloseStdinRequestSchema: GenMessage<CloseStdinRequest> =\n /*@__PURE__*/\n messageDesc(file_process_process, 18)\n\n/**\n * @generated from message process.CloseStdinResponse\n */\nexport type CloseStdinResponse = Message<'process.CloseStdinResponse'> & {}\n\n/**\n * Describes the message process.CloseStdinResponse.\n * Use `create(CloseStdinResponseSchema)` to create a new message.\n */\nexport const CloseStdinResponseSchema: GenMessage<CloseStdinResponse> =\n /*@__PURE__*/\n messageDesc(file_process_process, 19)\n\n/**\n * @generated from message process.ConnectRequest\n */\nexport type ConnectRequest = Message<'process.ConnectRequest'> & {\n /**\n * @generated from field: process.ProcessSelector process = 1;\n */\n process?: ProcessSelector\n}\n\n/**\n * Describes the message process.ConnectRequest.\n * Use `create(ConnectRequestSchema)` to create a new message.\n */\nexport const ConnectRequestSchema: GenMessage<ConnectRequest> =\n /*@__PURE__*/\n messageDesc(file_process_process, 20)\n\n/**\n * @generated from message process.ProcessSelector\n */\nexport type ProcessSelector = Message<'process.ProcessSelector'> & {\n /**\n * @generated from oneof process.ProcessSelector.selector\n */\n selector:\n | {\n /**\n * @generated from field: uint32 pid = 1;\n */\n value: number\n case: 'pid'\n }\n | {\n /**\n * @generated from field: string tag = 2;\n */\n value: string\n case: 'tag'\n }\n | { case: undefined; value?: undefined }\n}\n\n/**\n * Describes the message process.ProcessSelector.\n * Use `create(ProcessSelectorSchema)` to create a new message.\n */\nexport const ProcessSelectorSchema: GenMessage<ProcessSelector> =\n /*@__PURE__*/\n messageDesc(file_process_process, 21)\n\n/**\n * @generated from enum process.Signal\n */\nexport enum Signal {\n /**\n * @generated from enum value: SIGNAL_UNSPECIFIED = 0;\n */\n UNSPECIFIED = 0,\n\n /**\n * @generated from enum value: SIGNAL_SIGTERM = 15;\n */\n SIGTERM = 15,\n\n /**\n * @generated from enum value: SIGNAL_SIGKILL = 9;\n */\n SIGKILL = 9,\n}\n\n/**\n * Describes the enum process.Signal.\n */\nexport const SignalSchema: GenEnum<Signal> =\n /*@__PURE__*/\n enumDesc(file_process_process, 0)\n\n/**\n * @generated from service process.Process\n */\nexport const Process: GenService<{\n /**\n * @generated from rpc process.Process.List\n */\n list: {\n methodKind: 'unary'\n input: typeof ListRequestSchema\n output: typeof ListResponseSchema\n }\n /**\n * @generated from rpc process.Process.Connect\n */\n connect: {\n methodKind: 'server_streaming'\n input: typeof ConnectRequestSchema\n output: typeof ConnectResponseSchema\n }\n /**\n * @generated from rpc process.Process.Start\n */\n start: {\n methodKind: 'server_streaming'\n input: typeof StartRequestSchema\n output: typeof StartResponseSchema\n }\n /**\n * @generated from rpc process.Process.Update\n */\n update: {\n methodKind: 'unary'\n input: typeof UpdateRequestSchema\n output: typeof UpdateResponseSchema\n }\n /**\n * Client input stream ensures ordering of messages\n *\n * @generated from rpc process.Process.StreamInput\n */\n streamInput: {\n methodKind: 'client_streaming'\n input: typeof StreamInputRequestSchema\n output: typeof StreamInputResponseSchema\n }\n /**\n * @generated from rpc process.Process.SendInput\n */\n sendInput: {\n methodKind: 'unary'\n input: typeof SendInputRequestSchema\n output: typeof SendInputResponseSchema\n }\n /**\n * @generated from rpc process.Process.SendSignal\n */\n sendSignal: {\n methodKind: 'unary'\n input: typeof SendSignalRequestSchema\n output: typeof SendSignalResponseSchema\n }\n /**\n * Close stdin to signal EOF to the process.\n * Only works for non-PTY processes. For PTY, send Ctrl+D (0x04) instead.\n *\n * @generated from rpc process.Process.CloseStdin\n */\n closeStdin: {\n methodKind: 'unary'\n input: typeof CloseStdinRequestSchema\n output: typeof CloseStdinResponseSchema\n }\n}> = /*@__PURE__*/ serviceDesc(file_process_process, 0)\n","export const ENVD_VERSION_RECURSIVE_WATCH = '0.1.4'\nexport const ENVD_DEBUG_FALLBACK = '99.99.99'\nexport const ENVD_COMMANDS_STDIN = '0.3.0'\nexport const ENVD_DEFAULT_USER = '0.4.0'\nexport const ENVD_ENVD_CLOSE = '0.5.2'\nexport const ENVD_OCTET_STREAM_UPLOAD = '0.5.7'\n","import { Code, ConnectError } from '@connectrpc/connect'\nimport { runtime } from '../utils'\n\nimport { compareVersions } from 'compare-versions'\nimport { defaultUsername } from '../connectionConfig'\nimport {\n AuthenticationError,\n formatSandboxTimeoutError,\n InvalidArgumentError,\n NotFoundError,\n SandboxError,\n TimeoutError,\n} from '../errors'\nimport { ENVD_DEFAULT_USER } from './versions'\n\nconst DEFAULT_ERROR_MAP: Partial<Record<Code, (message: string) => Error>> = {\n [Code.InvalidArgument]: (message) => new InvalidArgumentError(message),\n [Code.Unauthenticated]: (message) => new AuthenticationError(message),\n [Code.NotFound]: (message) => new NotFoundError(message),\n [Code.Unavailable]: formatSandboxTimeoutError,\n [Code.Canceled]: (message) =>\n new TimeoutError(\n `${message}: This error is likely due to exceeding 'requestTimeoutMs'. You can pass the request timeout value as an option when making the request.`\n ),\n [Code.DeadlineExceeded]: (message) =>\n new TimeoutError(\n `${message}: This error is likely due to exceeding 'timeoutMs' — the total time a long running request (like command execution or directory watch) can be active. It can be modified by passing 'timeoutMs' when making the request. Use '0' to disable the timeout.`\n ),\n}\n\n/**\n * Handles errors from envd RPC calls by mapping gRPC status codes to specific error types.\n *\n * @param err - The caught error, expected to be a `ConnectError` from the gRPC transport.\n * @param errorMap - Optional map of gRPC `Code` values to error factory functions that override the defaults.\n * @returns The corresponding `Error` instance mapped from the gRPC status code, or the original error if it is not a `ConnectError`.\n */\nexport function handleRpcError(\n err: unknown,\n errorMap?: Partial<Record<Code, (message: string) => Error>>\n): Error {\n if (err instanceof ConnectError) {\n // Check if a custom error mapping is provided for this error code\n if (errorMap && err.code in errorMap) {\n return errorMap[err.code]!(err.message)\n }\n\n // Check if there is a default error mapping for this error code\n if (err.code in DEFAULT_ERROR_MAP) {\n return DEFAULT_ERROR_MAP[err.code]!(err.message)\n }\n\n // Fallback to a generic SandboxError if no specific mapping is found\n return new SandboxError(`${err.code}: ${err.message}`)\n }\n\n return err as Error\n}\n\nfunction encode64(value: string): string {\n switch (runtime) {\n case 'deno':\n return btoa(value)\n case 'node':\n return Buffer.from(value).toString('base64')\n case 'bun':\n return Buffer.from(value).toString('base64')\n default:\n return btoa(value)\n }\n}\n\nexport function authenticationHeader(\n envdVersion: string,\n username: string | undefined\n): Record<string, string> {\n if (\n username == undefined &&\n compareVersions(envdVersion, ENVD_DEFAULT_USER) < 0\n ) {\n username = defaultUsername\n }\n\n if (!username) {\n return {}\n }\n\n const value = `${username}:`\n\n const encoded = encode64(value)\n\n return { Authorization: `Basic ${encoded}` }\n}\n","import { handleRpcError } from '../../envd/rpc'\nimport { SandboxError } from '../../errors'\nimport { ConnectResponse, StartResponse } from '../../envd/process/process_pb'\n\ndeclare const __brand: unique symbol\ntype Brand<B> = { [__brand]: B }\nexport type Branded<T, B> = T & Brand<B>\n\nexport type Stdout = Branded<string, 'stdout'>\nexport type Stderr = Branded<string, 'stderr'>\nexport type PtyOutput = Branded<Uint8Array, 'pty'>\n\n/**\n * Command execution result.\n */\nexport interface CommandResult {\n /**\n * Command execution exit code.\n * `0` if the command finished successfully.\n */\n exitCode: number\n /**\n * Error message from command execution if it failed.\n */\n error?: string\n /**\n * Command stdout output.\n */\n stdout: string\n /**\n * Command stderr output.\n */\n stderr: string\n}\n\n/**\n * Error thrown when a command exits with a non-zero exit code.\n */\nexport class CommandExitError extends SandboxError implements CommandResult {\n constructor(private readonly result: CommandResult) {\n super(result.error)\n this.name = 'CommandExitError'\n }\n\n /**\n * Command execution exit code.\n * `0` if the command finished successfully.\n */\n get exitCode() {\n return this.result.exitCode\n }\n\n /**\n * Error message from command execution.\n */\n get error() {\n return this.result.error\n }\n\n /**\n * Command execution stdout output.\n */\n get stdout() {\n return this.result.stdout\n }\n\n /**\n * Command execution stderr output.\n */\n get stderr() {\n return this.result.stderr\n }\n}\n\n/**\n * Command execution handle.\n *\n * It provides methods for waiting for the command to finish, retrieving stdout/stderr, and killing the command.\n *\n * @property {number} pid process ID of the command.\n */\nexport class CommandHandle\n implements\n Omit<CommandResult, 'exitCode' | 'error'>,\n Partial<Pick<CommandResult, 'exitCode' | 'error'>>\n{\n private _stdout = ''\n private _stderr = ''\n\n private result?: CommandResult\n private iterationError?: Error\n\n private readonly _wait: Promise<void>\n\n /**\n * @hidden\n * @internal\n * @access protected\n */\n constructor(\n readonly pid: number,\n private readonly handleDisconnect: () => void,\n private readonly handleKill: () => Promise<boolean>,\n private readonly events: AsyncIterable<ConnectResponse | StartResponse>,\n private readonly onStdout?: (stdout: string) => void | Promise<void>,\n private readonly onStderr?: (stderr: string) => void | Promise<void>,\n private readonly onPty?: (pty: Uint8Array) => void | Promise<void>\n ) {\n this._wait = this.handleEvents()\n }\n\n /**\n * Command execution exit code.\n * `0` if the command finished successfully.\n *\n * It is `undefined` if the command is still running.\n */\n get exitCode() {\n return this.result?.exitCode\n }\n\n /**\n * Error message from command execution.\n */\n get error() {\n return this.result?.error\n }\n\n /**\n * Command execution stderr output.\n */\n get stderr() {\n return this._stderr\n }\n\n /**\n * Command execution stdout output.\n */\n get stdout() {\n return this._stdout\n }\n\n /**\n * Wait for the command to finish and return the result.\n * If the command exits with a non-zero exit code, it throws a `CommandExitError`.\n *\n * @returns `CommandResult` result of command execution.\n */\n async wait() {\n await this._wait\n\n if (this.iterationError) {\n throw this.iterationError\n }\n\n if (!this.result) {\n throw new SandboxError('Process exited without a result')\n }\n\n if (this.result.exitCode !== 0) {\n throw new CommandExitError(this.result)\n }\n\n return this.result\n }\n\n /**\n * Disconnect from the command.\n *\n * The command is not killed, but SDK stops receiving events from the command.\n * You can reconnect to the command using {@link Commands.connect}.\n */\n async disconnect() {\n this.handleDisconnect()\n }\n\n /**\n * Kill the command.\n * It uses `SIGKILL` signal to kill the command.\n *\n * @returns `true` if the command was killed successfully, `false` if the command was not found.\n */\n async kill() {\n return await this.handleKill()\n }\n\n private async *iterateEvents(): AsyncGenerator<\n [Stdout, null, null] | [null, Stderr, null] | [null, null, PtyOutput]\n > {\n for await (const event of this.events) {\n const e = event?.event?.event\n let out: string | undefined\n\n switch (e?.case) {\n case 'data':\n switch (e.value.output.case) {\n case 'stdout':\n out = new TextDecoder().decode(e.value.output.value)\n this._stdout += out\n yield [out as Stdout, null, null]\n break\n case 'stderr':\n out = new TextDecoder().decode(e.value.output.value)\n this._stderr += out\n yield [null, out as Stderr, null]\n break\n case 'pty':\n yield [null, null, e.value.output.value as PtyOutput]\n break\n }\n break\n case 'end':\n this.result = {\n exitCode: e.value.exitCode,\n error: e.value.error,\n stdout: this.stdout,\n stderr: this.stderr,\n }\n break\n }\n // TODO: Handle empty events like in python SDK\n }\n }\n\n private async handleEvents() {\n try {\n for await (const [stdout, stderr, pty] of this.iterateEvents()) {\n if (stdout !== null) {\n this.onStdout?.(stdout)\n } else if (stderr !== null) {\n this.onStderr?.(stderr)\n } else if (pty) {\n this.onPty?.(pty)\n }\n }\n } catch (e) {\n this.iterationError = handleRpcError(e)\n }\n }\n}\n","import {\n Code,\n ConnectError,\n createClient,\n Client,\n Transport,\n} from '@connectrpc/connect'\n\nimport {\n Signal,\n Process as ProcessService,\n} from '../../envd/process/process_pb'\nimport {\n ConnectionConfig,\n ConnectionOpts,\n Username,\n KEEPALIVE_PING_HEADER,\n KEEPALIVE_PING_INTERVAL_SEC,\n} from '../../connectionConfig'\nimport { CommandHandle } from './commandHandle'\nimport { authenticationHeader, handleRpcError } from '../../envd/rpc'\nimport { handleProcessStartEvent } from '../../envd/api'\n\nexport interface PtyCreateOpts\n extends Pick<ConnectionOpts, 'requestTimeoutMs'> {\n /**\n * Number of columns for the PTY.\n */\n cols: number\n /**\n * Number of rows for the PTY.\n */\n rows: number\n /**\n * Callback to handle PTY data.\n */\n onData: (data: Uint8Array) => void | Promise<void>\n /**\n * Timeout for the PTY in **milliseconds**.\n *\n * @default 60_000 // 60 seconds\n */\n timeoutMs?: number\n /**\n * User to use for the PTY.\n *\n * @default `default Sandbox user (as specified in the template)`\n */\n user?: Username\n /**\n * Environment variables for the PTY.\n *\n * @default {}\n */\n envs?: Record<string, string>\n /**\n * Working directory for the PTY.\n *\n * @default // home directory of the user used to start the PTY\n */\n cwd?: string\n}\n\n/**\n * Options for connecting to a command.\n */\nexport type PtyConnectOpts = Pick<PtyCreateOpts, 'onData' | 'timeoutMs'> &\n Pick<ConnectionOpts, 'requestTimeoutMs'>\n\n/**\n * Module for interacting with PTYs (pseudo-terminals) in the sandbox.\n */\nexport class Pty {\n private readonly rpc: Client<typeof ProcessService>\n private readonly envdVersion: string\n\n private readonly defaultPtyConnectionTimeout = 60_000 // 60 seconds\n\n constructor(\n private readonly transport: Transport,\n private readonly connectionConfig: ConnectionConfig,\n metadata: {\n version: string\n }\n ) {\n this.rpc = createClient(ProcessService, this.transport)\n this.envdVersion = metadata.version\n }\n\n /**\n * Create a new PTY (pseudo-terminal).\n *\n * @param opts options for creating the PTY.\n *\n * @returns handle to interact with the PTY.\n */\n async create(opts: PtyCreateOpts) {\n const requestTimeoutMs =\n opts?.requestTimeoutMs ?? this.connectionConfig.requestTimeoutMs\n const envs = opts?.envs ?? {}\n envs.TERM = envs.TERM ?? 'xterm-256color'\n envs.LANG = envs.LANG ?? 'C.UTF-8'\n envs.LC_ALL = envs.LC_ALL ?? 'C.UTF-8'\n const controller = new AbortController()\n\n const reqTimeout = setTimeout(() => {\n controller.abort()\n }, requestTimeoutMs)\n\n const events = this.rpc.start(\n {\n process: {\n cmd: '/bin/bash',\n args: ['-i', '-l'],\n envs: envs,\n cwd: opts?.cwd,\n },\n pty: {\n size: {\n cols: opts.cols,\n rows: opts.rows,\n },\n },\n },\n {\n headers: {\n ...authenticationHeader(this.envdVersion, opts?.user),\n [KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString(),\n },\n signal: controller.signal,\n timeoutMs: opts?.timeoutMs ?? this.defaultPtyConnectionTimeout,\n }\n )\n\n try {\n const pid = await handleProcessStartEvent(events)\n\n clearTimeout(reqTimeout)\n\n return new CommandHandle(\n pid,\n () => controller.abort(),\n () => this.kill(pid),\n events,\n undefined,\n undefined,\n opts.onData\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Connect to a running PTY.\n *\n * @param pid process ID of the PTY to connect to. You can get the list of running PTYs using {@link Commands.list}.\n * @param opts connection options.\n *\n * @returns handle to interact with the PTY.\n */\n async connect(pid: number, opts?: PtyConnectOpts): Promise<CommandHandle> {\n const requestTimeoutMs =\n opts?.requestTimeoutMs ?? this.connectionConfig.requestTimeoutMs\n\n const controller = new AbortController()\n\n const reqTimeout = requestTimeoutMs\n ? setTimeout(() => {\n controller.abort()\n }, requestTimeoutMs)\n : undefined\n\n const events = this.rpc.connect(\n {\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n },\n {\n signal: controller.signal,\n headers: {\n [KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString(),\n },\n timeoutMs: opts?.timeoutMs ?? this.defaultPtyConnectionTimeout,\n }\n )\n\n try {\n const pid = await handleProcessStartEvent(events)\n\n clearTimeout(reqTimeout)\n\n return new CommandHandle(\n pid,\n () => controller.abort(),\n () => this.kill(pid),\n events,\n undefined,\n undefined,\n opts?.onData\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Send input to a PTY.\n *\n * @param pid process ID of the PTY.\n * @param data input data to send to the PTY.\n * @param opts connection options.\n */\n async sendInput(\n pid: number,\n data: Uint8Array,\n opts?: Pick<ConnectionOpts, 'requestTimeoutMs'>\n ): Promise<void> {\n try {\n await this.rpc.sendInput(\n {\n input: {\n input: {\n case: 'pty',\n value: data,\n },\n },\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n },\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Resize PTY.\n * Call this when the terminal window is resized and the number of columns and rows has changed.\n *\n * @param pid process ID of the PTY.\n * @param size new size of the PTY.\n * @param opts connection options.\n */\n async resize(\n pid: number,\n size: {\n cols: number\n rows: number\n },\n opts?: Pick<ConnectionOpts, 'requestTimeoutMs'>\n ): Promise<void> {\n try {\n await this.rpc.update(\n {\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n pty: {\n size,\n },\n },\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Kill a running PTY specified by process ID.\n * It uses `SIGKILL` signal to kill the PTY.\n *\n * @param pid process ID of the PTY.\n * @param opts connection options.\n *\n * @returns `true` if the PTY was killed, `false` if the PTY was not found.\n */\n async kill(\n pid: number,\n opts?: Pick<ConnectionOpts, 'requestTimeoutMs'>\n ): Promise<boolean> {\n try {\n await this.rpc.sendSignal(\n {\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n signal: Signal.SIGKILL,\n },\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n return true\n } catch (err) {\n if (err instanceof ConnectError) {\n if (err.code === Code.NotFound) {\n return false\n }\n }\n\n throw handleRpcError(err)\n }\n }\n}\n","import {\n Client,\n Code,\n ConnectError,\n Transport,\n createClient,\n} from '@connectrpc/connect'\n\nimport { compareVersions } from 'compare-versions'\nimport {\n ConnectionConfig,\n ConnectionOpts,\n KEEPALIVE_PING_HEADER,\n KEEPALIVE_PING_INTERVAL_SEC,\n Username,\n} from '../../connectionConfig'\nimport { handleProcessStartEvent } from '../../envd/api'\nimport {\n Process as ProcessService,\n Signal,\n} from '../../envd/process/process_pb'\nimport { authenticationHeader, handleRpcError } from '../../envd/rpc'\nimport { ENVD_COMMANDS_STDIN, ENVD_ENVD_CLOSE } from '../../envd/versions'\nimport { SandboxError } from '../../errors'\nimport { CommandHandle, CommandResult } from './commandHandle'\nexport { Pty } from './pty'\n\n/**\n * Options for sending a command request.\n */\nexport interface CommandRequestOpts\n extends Partial<Pick<ConnectionOpts, 'requestTimeoutMs'>> {}\n\n/**\n * Options for starting a new command.\n */\nexport interface CommandStartOpts extends CommandRequestOpts {\n /**\n * If true, starts command in the background and the method returns immediately.\n * You can use {@link CommandHandle.wait} to wait for the command to finish.\n */\n background?: boolean\n /**\n * Working directory for the command.\n *\n * @default // home directory of the user used to start the command\n */\n cwd?: string\n /**\n * User to run the command as.\n *\n * @default `default Sandbox user (as specified in the template)`\n */\n user?: Username\n /**\n * Environment variables used for the command.\n *\n * This overrides the default environment variables from `Sandbox` constructor.\n *\n * @default `{}`\n */\n envs?: Record<string, string>\n /**\n * Callback for command stdout output.\n */\n onStdout?: (data: string) => void | Promise<void>\n /**\n * Callback for command stderr output.\n */\n onStderr?: (data: string) => void | Promise<void>\n /**\n * If true, command stdin is kept open and you can send data to it using {@link Commands.sendStdin} or {@link CommandHandle.sendStdin}.\n * @default false\n */\n stdin?: boolean\n /**\n * Timeout for the command in **milliseconds**.\n *\n * @default 60_000 // 60 seconds\n */\n timeoutMs?: number\n}\n\n/**\n * Options for connecting to a command.\n */\nexport type CommandConnectOpts = Pick<\n CommandStartOpts,\n 'onStderr' | 'onStdout' | 'timeoutMs'\n> &\n CommandRequestOpts\n\n/**\n * Information about a command, PTY session or start command running in the sandbox as process.\n */\nexport interface ProcessInfo {\n /**\n * Process ID.\n */\n pid: number\n /**\n * Custom tag used for identifying special commands like start command in the custom template.\n */\n tag?: string\n /**\n * Command that was executed.\n */\n cmd: string\n /**\n * Command arguments.\n */\n args: string[]\n /**\n * Environment variables used for the command.\n */\n envs: Record<string, string>\n /**\n * Executed command working directory.\n */\n cwd?: string\n}\n\n/**\n * Module for starting and interacting with commands in the sandbox.\n */\nexport class Commands {\n protected readonly rpc: Client<typeof ProcessService>\n\n private readonly defaultProcessConnectionTimeout = 60_000 // 60 seconds\n private readonly envdVersion: string\n\n constructor(\n transport: Transport,\n private readonly connectionConfig: ConnectionConfig,\n metadata: {\n version: string\n }\n ) {\n this.rpc = createClient(ProcessService, transport)\n this.envdVersion = metadata.version\n }\n\n /**\n * @hidden\n * @internal\n */\n get supportsStdinClose(): boolean {\n return compareVersions(this.envdVersion, ENVD_ENVD_CLOSE) >= 0\n }\n\n /**\n * List all running commands and PTY sessions.\n *\n * @param opts connection options.\n *\n * @returns list of running commands and PTY sessions.\n */\n async list(opts?: CommandRequestOpts): Promise<ProcessInfo[]> {\n try {\n const res = await this.rpc.list(\n {},\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n return res.processes.map((p) => ({\n pid: p.pid,\n ...(p.tag && { tag: p.tag }),\n args: p.config!.args,\n envs: p.config!.envs,\n cmd: p.config!.cmd,\n ...(p.config!.cwd && { cwd: p.config!.cwd }),\n }))\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Send data to command stdin.\n *\n * @param pid process ID of the command. You can get the list of running commands using {@link Commands.list}.\n * @param data data to send to the command.\n * @param opts connection options.\n */\n async sendStdin(\n pid: number,\n data: string | Uint8Array,\n opts?: CommandRequestOpts\n ): Promise<void> {\n try {\n const payload =\n typeof data === 'string' ? new TextEncoder().encode(data) : data\n\n await this.rpc.sendInput(\n {\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n input: {\n input: {\n case: 'stdin',\n value: payload,\n },\n },\n },\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * @hidden\n * @internal\n */\n async closeStdin(pid: number, opts?: CommandRequestOpts): Promise<void> {\n if (!this.supportsStdinClose) {\n throw new SandboxError(\n `Sandbox envd version ${this.envdVersion} doesn't support closeStdin. Please rebuild your template to pick up the latest sandbox version.`\n )\n }\n\n try {\n await this.rpc.closeStdin(\n {\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n },\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Kill a running command specified by its process ID.\n * It uses `SIGKILL` signal to kill the command.\n *\n * @param pid process ID of the command. You can get the list of running commands using {@link Commands.list}.\n * @param opts connection options.\n *\n * @returns `true` if the command was killed, `false` if the command was not found.\n */\n async kill(pid: number, opts?: CommandRequestOpts): Promise<boolean> {\n try {\n await this.rpc.sendSignal(\n {\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n signal: Signal.SIGKILL,\n },\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n return true\n } catch (err) {\n if (err instanceof ConnectError) {\n if (err.code === Code.NotFound) {\n return false\n }\n }\n\n throw handleRpcError(err)\n }\n }\n\n /**\n * Connect to a running command.\n * You can use {@link CommandHandle.wait} to wait for the command to finish and get execution results.\n *\n * @param pid process ID of the command to connect to. You can get the list of running commands using {@link Commands.list}.\n * @param opts connection options.\n *\n * @returns `CommandHandle` handle to interact with the running command.\n */\n async connect(\n pid: number,\n opts?: CommandConnectOpts\n ): Promise<CommandHandle> {\n const requestTimeoutMs =\n opts?.requestTimeoutMs ?? this.connectionConfig.requestTimeoutMs\n\n const controller = new AbortController()\n\n const reqTimeout = requestTimeoutMs\n ? setTimeout(() => {\n controller.abort()\n }, requestTimeoutMs)\n : undefined\n\n const events = this.rpc.connect(\n {\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n },\n {\n signal: controller.signal,\n headers: {\n [KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString(),\n },\n timeoutMs: opts?.timeoutMs ?? this.defaultProcessConnectionTimeout,\n }\n )\n\n try {\n const pid = await handleProcessStartEvent(events)\n\n clearTimeout(reqTimeout)\n\n return new CommandHandle(\n pid,\n () => controller.abort(),\n () => this.kill(pid),\n events,\n opts?.onStdout,\n opts?.onStderr,\n undefined\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Start a new command and wait until it finishes executing.\n *\n * @param cmd command to execute.\n * @param opts options for starting the command.\n *\n * @returns `CommandResult` result of the command execution.\n */\n async run(\n cmd: string,\n opts?: CommandStartOpts & { background?: false }\n ): Promise<CommandResult>\n\n /**\n * Start a new command in the background.\n * You can use {@link CommandHandle.wait} to wait for the command to finish and get its result.\n *\n * @param cmd command to execute.\n * @param opts options for starting the command\n *\n * @returns `CommandHandle` handle to interact with the running command.\n */\n async run(\n cmd: string,\n opts: CommandStartOpts & { background: true }\n ): Promise<CommandHandle>\n\n // NOTE - The following overload seems redundant, but it's required to make the type inference work correctly.\n\n /**\n * Start a new command.\n *\n * @param cmd command to execute.\n * @param opts options for starting the command.\n * - `opts.background: true` - runs in background, returns `CommandHandle`\n * - `opts.background: false | undefined` - waits for completion, returns `CommandResult`\n *\n * @returns Either a `CommandHandle` or a `CommandResult` (depending on `opts.background`).\n */\n async run(\n cmd: string,\n opts?: CommandStartOpts & { background?: boolean }\n ): Promise<CommandHandle | CommandResult>\n async run(\n cmd: string,\n opts?: CommandStartOpts & { background?: boolean }\n ): Promise<CommandHandle | CommandResult> {\n const proc = await this.start(cmd, opts)\n\n return opts?.background ? proc : proc.wait()\n }\n\n private async start(\n cmd: string,\n opts?: CommandStartOpts\n ): Promise<CommandHandle> {\n const requestTimeoutMs =\n opts?.requestTimeoutMs ?? this.connectionConfig.requestTimeoutMs\n\n const controller = new AbortController()\n\n const reqTimeout = requestTimeoutMs\n ? setTimeout(() => {\n controller.abort()\n }, requestTimeoutMs)\n : undefined\n\n if (\n opts?.stdin === false &&\n compareVersions(this.envdVersion, ENVD_COMMANDS_STDIN) < 0\n ) {\n throw new SandboxError(\n `Sandbox envd version ${this.envdVersion} can't specify stdin, it's always turned on. Please rebuild your template if you need this feature.`\n )\n }\n\n const events = this.rpc.start(\n {\n process: {\n cmd: '/bin/bash',\n cwd: opts?.cwd,\n envs: opts?.envs,\n args: ['-l', '-c', cmd],\n },\n stdin: opts?.stdin || false,\n },\n {\n headers: {\n ...authenticationHeader(this.envdVersion, opts?.user),\n [KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString(),\n },\n signal: controller.signal,\n timeoutMs: opts?.timeoutMs ?? this.defaultProcessConnectionTimeout,\n }\n )\n\n try {\n const pid = await handleProcessStartEvent(events)\n\n clearTimeout(reqTimeout)\n\n return new CommandHandle(\n pid,\n () => controller.abort(),\n () => this.kill(pid),\n events,\n opts?.onStdout,\n opts?.onStderr,\n undefined\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n}\n","// @generated by protoc-gen-es v2.6.2 with parameter \"target=ts\"\n// @generated from file filesystem/filesystem.proto (package filesystem, syntax proto3)\n/* eslint-disable */\n\nimport type {\n GenEnum,\n GenFile,\n GenMessage,\n GenService,\n} from '@bufbuild/protobuf/codegenv2'\nimport {\n enumDesc,\n fileDesc,\n messageDesc,\n serviceDesc,\n} from '@bufbuild/protobuf/codegenv2'\nimport type { Timestamp } from '@bufbuild/protobuf/wkt'\nimport { file_google_protobuf_timestamp } from '@bufbuild/protobuf/wkt'\nimport type { Message } from '@bufbuild/protobuf'\n\n/**\n * Describes the file filesystem/filesystem.proto.\n */\nexport const file_filesystem_filesystem: GenFile =\n /*@__PURE__*/\n fileDesc(\n 'ChtmaWxlc3lzdGVtL2ZpbGVzeXN0ZW0ucHJvdG8SCmZpbGVzeXN0ZW0iMgoLTW92ZVJlcXVlc3QSDgoGc291cmNlGAEgASgJEhMKC2Rlc3RpbmF0aW9uGAIgASgJIjQKDE1vdmVSZXNwb25zZRIkCgVlbnRyeRgBIAEoCzIVLmZpbGVzeXN0ZW0uRW50cnlJbmZvIh4KDk1ha2VEaXJSZXF1ZXN0EgwKBHBhdGgYASABKAkiNwoPTWFrZURpclJlc3BvbnNlEiQKBWVudHJ5GAEgASgLMhUuZmlsZXN5c3RlbS5FbnRyeUluZm8iHQoNUmVtb3ZlUmVxdWVzdBIMCgRwYXRoGAEgASgJIhAKDlJlbW92ZVJlc3BvbnNlIhsKC1N0YXRSZXF1ZXN0EgwKBHBhdGgYASABKAkiNAoMU3RhdFJlc3BvbnNlEiQKBWVudHJ5GAEgASgLMhUuZmlsZXN5c3RlbS5FbnRyeUluZm8i/QEKCUVudHJ5SW5mbxIMCgRuYW1lGAEgASgJEiIKBHR5cGUYAiABKA4yFC5maWxlc3lzdGVtLkZpbGVUeXBlEgwKBHBhdGgYAyABKAkSDAoEc2l6ZRgEIAEoAxIMCgRtb2RlGAUgASgNEhMKC3Blcm1pc3Npb25zGAYgASgJEg0KBW93bmVyGAcgASgJEg0KBWdyb3VwGAggASgJEjEKDW1vZGlmaWVkX3RpbWUYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhsKDnN5bWxpbmtfdGFyZ2V0GAogASgJSACIAQFCEQoPX3N5bWxpbmtfdGFyZ2V0Ii0KDkxpc3REaXJSZXF1ZXN0EgwKBHBhdGgYASABKAkSDQoFZGVwdGgYAiABKA0iOQoPTGlzdERpclJlc3BvbnNlEiYKB2VudHJpZXMYASADKAsyFS5maWxlc3lzdGVtLkVudHJ5SW5mbyIyCg9XYXRjaERpclJlcXVlc3QSDAoEcGF0aBgBIAEoCRIRCglyZWN1cnNpdmUYAiABKAgiRAoPRmlsZXN5c3RlbUV2ZW50EgwKBG5hbWUYASABKAkSIwoEdHlwZRgCIAEoDjIVLmZpbGVzeXN0ZW0uRXZlbnRUeXBlIuABChBXYXRjaERpclJlc3BvbnNlEjgKBXN0YXJ0GAEgASgLMicuZmlsZXN5c3RlbS5XYXRjaERpclJlc3BvbnNlLlN0YXJ0RXZlbnRIABIxCgpmaWxlc3lzdGVtGAIgASgLMhsuZmlsZXN5c3RlbS5GaWxlc3lzdGVtRXZlbnRIABI7CglrZWVwYWxpdmUYAyABKAsyJi5maWxlc3lzdGVtLldhdGNoRGlyUmVzcG9uc2UuS2VlcEFsaXZlSAAaDAoKU3RhcnRFdmVudBoLCglLZWVwQWxpdmVCBwoFZXZlbnQiNwoUQ3JlYXRlV2F0Y2hlclJlcXVlc3QSDAoEcGF0aBgBIAEoCRIRCglyZWN1cnNpdmUYAiABKAgiKwoVQ3JlYXRlV2F0Y2hlclJlc3BvbnNlEhIKCndhdGNoZXJfaWQYASABKAkiLQoXR2V0V2F0Y2hlckV2ZW50c1JlcXVlc3QSEgoKd2F0Y2hlcl9pZBgBIAEoCSJHChhHZXRXYXRjaGVyRXZlbnRzUmVzcG9uc2USKwoGZXZlbnRzGAEgAygLMhsuZmlsZXN5c3RlbS5GaWxlc3lzdGVtRXZlbnQiKgoUUmVtb3ZlV2F0Y2hlclJlcXVlc3QSEgoKd2F0Y2hlcl9pZBgBIAEoCSIXChVSZW1vdmVXYXRjaGVyUmVzcG9uc2UqUgoIRmlsZVR5cGUSGQoVRklMRV9UWVBFX1VOU1BFQ0lGSUVEEAASEgoORklMRV9UWVBFX0ZJTEUQARIXChNGSUxFX1RZUEVfRElSRUNUT1JZEAIqmAEKCUV2ZW50VHlwZRIaChZFVkVOVF9UWVBFX1VOU1BFQ0lGSUVEEAASFQoRRVZFTlRfVFlQRV9DUkVBVEUQARIUChBFVkVOVF9UWVBFX1dSSVRFEAISFQoRRVZFTlRfVFlQRV9SRU1PVkUQAxIVChFFVkVOVF9UWVBFX1JFTkFNRRAEEhQKEEVWRU5UX1RZUEVfQ0hNT0QQBTKfBQoKRmlsZXN5c3RlbRI5CgRTdGF0EhcuZmlsZXN5c3RlbS5TdGF0UmVxdWVzdBoYLmZpbGVzeXN0ZW0uU3RhdFJlc3BvbnNlEkIKB01ha2VEaXISGi5maWxlc3lzdGVtLk1ha2VEaXJSZXF1ZXN0GhsuZmlsZXN5c3RlbS5NYWtlRGlyUmVzcG9uc2USOQoETW92ZRIXLmZpbGVzeXN0ZW0uTW92ZVJlcXVlc3QaGC5maWxlc3lzdGVtLk1vdmVSZXNwb25zZRJCCgdMaXN0RGlyEhouZmlsZXN5c3RlbS5MaXN0RGlyUmVxdWVzdBobLmZpbGVzeXN0ZW0uTGlzdERpclJlc3BvbnNlEj8KBlJlbW92ZRIZLmZpbGVzeXN0ZW0uUmVtb3ZlUmVxdWVzdBoaLmZpbGVzeXN0ZW0uUmVtb3ZlUmVzcG9uc2USRwoIV2F0Y2hEaXISGy5maWxlc3lzdGVtLldhdGNoRGlyUmVxdWVzdBocLmZpbGVzeXN0ZW0uV2F0Y2hEaXJSZXNwb25zZTABElQKDUNyZWF0ZVdhdGNoZXISIC5maWxlc3lzdGVtLkNyZWF0ZVdhdGNoZXJSZXF1ZXN0GiEuZmlsZXN5c3RlbS5DcmVhdGVXYXRjaGVyUmVzcG9uc2USXQoQR2V0V2F0Y2hlckV2ZW50cxIjLmZpbGVzeXN0ZW0uR2V0V2F0Y2hlckV2ZW50c1JlcXVlc3QaJC5maWxlc3lzdGVtLkdldFdhdGNoZXJFdmVudHNSZXNwb25zZRJUCg1SZW1vdmVXYXRjaGVyEiAuZmlsZXN5c3RlbS5SZW1vdmVXYXRjaGVyUmVxdWVzdBohLmZpbGVzeXN0ZW0uUmVtb3ZlV2F0Y2hlclJlc3BvbnNlQmkKDmNvbS5maWxlc3lzdGVtQg9GaWxlc3lzdGVtUHJvdG9QAaICA0ZYWKoCCkZpbGVzeXN0ZW3KAgpGaWxlc3lzdGVt4gIWRmlsZXN5c3RlbVxHUEJNZXRhZGF0YeoCCkZpbGVzeXN0ZW1iBnByb3RvMw',\n [file_google_protobuf_timestamp]\n )\n\n/**\n * @generated from message filesystem.MoveRequest\n */\nexport type MoveRequest = Message<'filesystem.MoveRequest'> & {\n /**\n * @generated from field: string source = 1;\n */\n source: string\n\n /**\n * @generated from field: string destination = 2;\n */\n destination: string\n}\n\n/**\n * Describes the message filesystem.MoveRequest.\n * Use `create(MoveRequestSchema)` to create a new message.\n */\nexport const MoveRequestSchema: GenMessage<MoveRequest> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 0)\n\n/**\n * @generated from message filesystem.MoveResponse\n */\nexport type MoveResponse = Message<'filesystem.MoveResponse'> & {\n /**\n * @generated from field: filesystem.EntryInfo entry = 1;\n */\n entry?: EntryInfo\n}\n\n/**\n * Describes the message filesystem.MoveResponse.\n * Use `create(MoveResponseSchema)` to create a new message.\n */\nexport const MoveResponseSchema: GenMessage<MoveResponse> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 1)\n\n/**\n * @generated from message filesystem.MakeDirRequest\n */\nexport type MakeDirRequest = Message<'filesystem.MakeDirRequest'> & {\n /**\n * @generated from field: string path = 1;\n */\n path: string\n}\n\n/**\n * Describes the message filesystem.MakeDirRequest.\n * Use `create(MakeDirRequestSchema)` to create a new message.\n */\nexport const MakeDirRequestSchema: GenMessage<MakeDirRequest> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 2)\n\n/**\n * @generated from message filesystem.MakeDirResponse\n */\nexport type MakeDirResponse = Message<'filesystem.MakeDirResponse'> & {\n /**\n * @generated from field: filesystem.EntryInfo entry = 1;\n */\n entry?: EntryInfo\n}\n\n/**\n * Describes the message filesystem.MakeDirResponse.\n * Use `create(MakeDirResponseSchema)` to create a new message.\n */\nexport const MakeDirResponseSchema: GenMessage<MakeDirResponse> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 3)\n\n/**\n * @generated from message filesystem.RemoveRequest\n */\nexport type RemoveRequest = Message<'filesystem.RemoveRequest'> & {\n /**\n * @generated from field: string path = 1;\n */\n path: string\n}\n\n/**\n * Describes the message filesystem.RemoveRequest.\n * Use `create(RemoveRequestSchema)` to create a new message.\n */\nexport const RemoveRequestSchema: GenMessage<RemoveRequest> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 4)\n\n/**\n * @generated from message filesystem.RemoveResponse\n */\nexport type RemoveResponse = Message<'filesystem.RemoveResponse'> & {}\n\n/**\n * Describes the message filesystem.RemoveResponse.\n * Use `create(RemoveResponseSchema)` to create a new message.\n */\nexport const RemoveResponseSchema: GenMessage<RemoveResponse> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 5)\n\n/**\n * @generated from message filesystem.StatRequest\n */\nexport type StatRequest = Message<'filesystem.StatRequest'> & {\n /**\n * @generated from field: string path = 1;\n */\n path: string\n}\n\n/**\n * Describes the message filesystem.StatRequest.\n * Use `create(StatRequestSchema)` to create a new message.\n */\nexport const StatRequestSchema: GenMessage<StatRequest> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 6)\n\n/**\n * @generated from message filesystem.StatResponse\n */\nexport type StatResponse = Message<'filesystem.StatResponse'> & {\n /**\n * @generated from field: filesystem.EntryInfo entry = 1;\n */\n entry?: EntryInfo\n}\n\n/**\n * Describes the message filesystem.StatResponse.\n * Use `create(StatResponseSchema)` to create a new message.\n */\nexport const StatResponseSchema: GenMessage<StatResponse> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 7)\n\n/**\n * @generated from message filesystem.EntryInfo\n */\nexport type EntryInfo = Message<'filesystem.EntryInfo'> & {\n /**\n * @generated from field: string name = 1;\n */\n name: string\n\n /**\n * @generated from field: filesystem.FileType type = 2;\n */\n type: FileType\n\n /**\n * @generated from field: string path = 3;\n */\n path: string\n\n /**\n * @generated from field: int64 size = 4;\n */\n size: bigint\n\n /**\n * @generated from field: uint32 mode = 5;\n */\n mode: number\n\n /**\n * @generated from field: string permissions = 6;\n */\n permissions: string\n\n /**\n * @generated from field: string owner = 7;\n */\n owner: string\n\n /**\n * @generated from field: string group = 8;\n */\n group: string\n\n /**\n * @generated from field: google.protobuf.Timestamp modified_time = 9;\n */\n modifiedTime?: Timestamp\n\n /**\n * If the entry is a symlink, this field contains the target of the symlink.\n *\n * @generated from field: optional string symlink_target = 10;\n */\n symlinkTarget?: string\n}\n\n/**\n * Describes the message filesystem.EntryInfo.\n * Use `create(EntryInfoSchema)` to create a new message.\n */\nexport const EntryInfoSchema: GenMessage<EntryInfo> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 8)\n\n/**\n * @generated from message filesystem.ListDirRequest\n */\nexport type ListDirRequest = Message<'filesystem.ListDirRequest'> & {\n /**\n * @generated from field: string path = 1;\n */\n path: string\n\n /**\n * @generated from field: uint32 depth = 2;\n */\n depth: number\n}\n\n/**\n * Describes the message filesystem.ListDirRequest.\n * Use `create(ListDirRequestSchema)` to create a new message.\n */\nexport const ListDirRequestSchema: GenMessage<ListDirRequest> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 9)\n\n/**\n * @generated from message filesystem.ListDirResponse\n */\nexport type ListDirResponse = Message<'filesystem.ListDirResponse'> & {\n /**\n * @generated from field: repeated filesystem.EntryInfo entries = 1;\n */\n entries: EntryInfo[]\n}\n\n/**\n * Describes the message filesystem.ListDirResponse.\n * Use `create(ListDirResponseSchema)` to create a new message.\n */\nexport const ListDirResponseSchema: GenMessage<ListDirResponse> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 10)\n\n/**\n * @generated from message filesystem.WatchDirRequest\n */\nexport type WatchDirRequest = Message<'filesystem.WatchDirRequest'> & {\n /**\n * @generated from field: string path = 1;\n */\n path: string\n\n /**\n * @generated from field: bool recursive = 2;\n */\n recursive: boolean\n}\n\n/**\n * Describes the message filesystem.WatchDirRequest.\n * Use `create(WatchDirRequestSchema)` to create a new message.\n */\nexport const WatchDirRequestSchema: GenMessage<WatchDirRequest> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 11)\n\n/**\n * @generated from message filesystem.FilesystemEvent\n */\nexport type FilesystemEvent = Message<'filesystem.FilesystemEvent'> & {\n /**\n * @generated from field: string name = 1;\n */\n name: string\n\n /**\n * @generated from field: filesystem.EventType type = 2;\n */\n type: EventType\n}\n\n/**\n * Describes the message filesystem.FilesystemEvent.\n * Use `create(FilesystemEventSchema)` to create a new message.\n */\nexport const FilesystemEventSchema: GenMessage<FilesystemEvent> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 12)\n\n/**\n * @generated from message filesystem.WatchDirResponse\n */\nexport type WatchDirResponse = Message<'filesystem.WatchDirResponse'> & {\n /**\n * @generated from oneof filesystem.WatchDirResponse.event\n */\n event:\n | {\n /**\n * @generated from field: filesystem.WatchDirResponse.StartEvent start = 1;\n */\n value: WatchDirResponse_StartEvent\n case: 'start'\n }\n | {\n /**\n * @generated from field: filesystem.FilesystemEvent filesystem = 2;\n */\n value: FilesystemEvent\n case: 'filesystem'\n }\n | {\n /**\n * @generated from field: filesystem.WatchDirResponse.KeepAlive keepalive = 3;\n */\n value: WatchDirResponse_KeepAlive\n case: 'keepalive'\n }\n | { case: undefined; value?: undefined }\n}\n\n/**\n * Describes the message filesystem.WatchDirResponse.\n * Use `create(WatchDirResponseSchema)` to create a new message.\n */\nexport const WatchDirResponseSchema: GenMessage<WatchDirResponse> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 13)\n\n/**\n * @generated from message filesystem.WatchDirResponse.StartEvent\n */\nexport type WatchDirResponse_StartEvent =\n Message<'filesystem.WatchDirResponse.StartEvent'> & {}\n\n/**\n * Describes the message filesystem.WatchDirResponse.StartEvent.\n * Use `create(WatchDirResponse_StartEventSchema)` to create a new message.\n */\nexport const WatchDirResponse_StartEventSchema: GenMessage<WatchDirResponse_StartEvent> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 13, 0)\n\n/**\n * @generated from message filesystem.WatchDirResponse.KeepAlive\n */\nexport type WatchDirResponse_KeepAlive =\n Message<'filesystem.WatchDirResponse.KeepAlive'> & {}\n\n/**\n * Describes the message filesystem.WatchDirResponse.KeepAlive.\n * Use `create(WatchDirResponse_KeepAliveSchema)` to create a new message.\n */\nexport const WatchDirResponse_KeepAliveSchema: GenMessage<WatchDirResponse_KeepAlive> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 13, 1)\n\n/**\n * @generated from message filesystem.CreateWatcherRequest\n */\nexport type CreateWatcherRequest =\n Message<'filesystem.CreateWatcherRequest'> & {\n /**\n * @generated from field: string path = 1;\n */\n path: string\n\n /**\n * @generated from field: bool recursive = 2;\n */\n recursive: boolean\n }\n\n/**\n * Describes the message filesystem.CreateWatcherRequest.\n * Use `create(CreateWatcherRequestSchema)` to create a new message.\n */\nexport const CreateWatcherRequestSchema: GenMessage<CreateWatcherRequest> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 14)\n\n/**\n * @generated from message filesystem.CreateWatcherResponse\n */\nexport type CreateWatcherResponse =\n Message<'filesystem.CreateWatcherResponse'> & {\n /**\n * @generated from field: string watcher_id = 1;\n */\n watcherId: string\n }\n\n/**\n * Describes the message filesystem.CreateWatcherResponse.\n * Use `create(CreateWatcherResponseSchema)` to create a new message.\n */\nexport const CreateWatcherResponseSchema: GenMessage<CreateWatcherResponse> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 15)\n\n/**\n * @generated from message filesystem.GetWatcherEventsRequest\n */\nexport type GetWatcherEventsRequest =\n Message<'filesystem.GetWatcherEventsRequest'> & {\n /**\n * @generated from field: string watcher_id = 1;\n */\n watcherId: string\n }\n\n/**\n * Describes the message filesystem.GetWatcherEventsRequest.\n * Use `create(GetWatcherEventsRequestSchema)` to create a new message.\n */\nexport const GetWatcherEventsRequestSchema: GenMessage<GetWatcherEventsRequest> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 16)\n\n/**\n * @generated from message filesystem.GetWatcherEventsResponse\n */\nexport type GetWatcherEventsResponse =\n Message<'filesystem.GetWatcherEventsResponse'> & {\n /**\n * @generated from field: repeated filesystem.FilesystemEvent events = 1;\n */\n events: FilesystemEvent[]\n }\n\n/**\n * Describes the message filesystem.GetWatcherEventsResponse.\n * Use `create(GetWatcherEventsResponseSchema)` to create a new message.\n */\nexport const GetWatcherEventsResponseSchema: GenMessage<GetWatcherEventsResponse> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 17)\n\n/**\n * @generated from message filesystem.RemoveWatcherRequest\n */\nexport type RemoveWatcherRequest =\n Message<'filesystem.RemoveWatcherRequest'> & {\n /**\n * @generated from field: string watcher_id = 1;\n */\n watcherId: string\n }\n\n/**\n * Describes the message filesystem.RemoveWatcherRequest.\n * Use `create(RemoveWatcherRequestSchema)` to create a new message.\n */\nexport const RemoveWatcherRequestSchema: GenMessage<RemoveWatcherRequest> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 18)\n\n/**\n * @generated from message filesystem.RemoveWatcherResponse\n */\nexport type RemoveWatcherResponse =\n Message<'filesystem.RemoveWatcherResponse'> & {}\n\n/**\n * Describes the message filesystem.RemoveWatcherResponse.\n * Use `create(RemoveWatcherResponseSchema)` to create a new message.\n */\nexport const RemoveWatcherResponseSchema: GenMessage<RemoveWatcherResponse> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 19)\n\n/**\n * @generated from enum filesystem.FileType\n */\nexport enum FileType {\n /**\n * @generated from enum value: FILE_TYPE_UNSPECIFIED = 0;\n */\n UNSPECIFIED = 0,\n\n /**\n * @generated from enum value: FILE_TYPE_FILE = 1;\n */\n FILE = 1,\n\n /**\n * @generated from enum value: FILE_TYPE_DIRECTORY = 2;\n */\n DIRECTORY = 2,\n}\n\n/**\n * Describes the enum filesystem.FileType.\n */\nexport const FileTypeSchema: GenEnum<FileType> =\n /*@__PURE__*/\n enumDesc(file_filesystem_filesystem, 0)\n\n/**\n * @generated from enum filesystem.EventType\n */\nexport enum EventType {\n /**\n * @generated from enum value: EVENT_TYPE_UNSPECIFIED = 0;\n */\n UNSPECIFIED = 0,\n\n /**\n * @generated from enum value: EVENT_TYPE_CREATE = 1;\n */\n CREATE = 1,\n\n /**\n * @generated from enum value: EVENT_TYPE_WRITE = 2;\n */\n WRITE = 2,\n\n /**\n * @generated from enum value: EVENT_TYPE_REMOVE = 3;\n */\n REMOVE = 3,\n\n /**\n * @generated from enum value: EVENT_TYPE_RENAME = 4;\n */\n RENAME = 4,\n\n /**\n * @generated from enum value: EVENT_TYPE_CHMOD = 5;\n */\n CHMOD = 5,\n}\n\n/**\n * Describes the enum filesystem.EventType.\n */\nexport const EventTypeSchema: GenEnum<EventType> =\n /*@__PURE__*/\n enumDesc(file_filesystem_filesystem, 1)\n\n/**\n * @generated from service filesystem.Filesystem\n */\nexport const Filesystem: GenService<{\n /**\n * @generated from rpc filesystem.Filesystem.Stat\n */\n stat: {\n methodKind: 'unary'\n input: typeof StatRequestSchema\n output: typeof StatResponseSchema\n }\n /**\n * @generated from rpc filesystem.Filesystem.MakeDir\n */\n makeDir: {\n methodKind: 'unary'\n input: typeof MakeDirRequestSchema\n output: typeof MakeDirResponseSchema\n }\n /**\n * @generated from rpc filesystem.Filesystem.Move\n */\n move: {\n methodKind: 'unary'\n input: typeof MoveRequestSchema\n output: typeof MoveResponseSchema\n }\n /**\n * @generated from rpc filesystem.Filesystem.ListDir\n */\n listDir: {\n methodKind: 'unary'\n input: typeof ListDirRequestSchema\n output: typeof ListDirResponseSchema\n }\n /**\n * @generated from rpc filesystem.Filesystem.Remove\n */\n remove: {\n methodKind: 'unary'\n input: typeof RemoveRequestSchema\n output: typeof RemoveResponseSchema\n }\n /**\n * @generated from rpc filesystem.Filesystem.WatchDir\n */\n watchDir: {\n methodKind: 'server_streaming'\n input: typeof WatchDirRequestSchema\n output: typeof WatchDirResponseSchema\n }\n /**\n * Non-streaming versions of WatchDir\n *\n * @generated from rpc filesystem.Filesystem.CreateWatcher\n */\n createWatcher: {\n methodKind: 'unary'\n input: typeof CreateWatcherRequestSchema\n output: typeof CreateWatcherResponseSchema\n }\n /**\n * @generated from rpc filesystem.Filesystem.GetWatcherEvents\n */\n getWatcherEvents: {\n methodKind: 'unary'\n input: typeof GetWatcherEventsRequestSchema\n output: typeof GetWatcherEventsResponseSchema\n }\n /**\n * @generated from rpc filesystem.Filesystem.RemoveWatcher\n */\n removeWatcher: {\n methodKind: 'unary'\n input: typeof RemoveWatcherRequestSchema\n output: typeof RemoveWatcherResponseSchema\n }\n}> = /*@__PURE__*/ serviceDesc(file_filesystem_filesystem, 0)\n","import { handleRpcError } from '../../envd/rpc'\nimport {\n EventType,\n WatchDirResponse,\n} from '../../envd/filesystem/filesystem_pb'\n\n/**\n * Sandbox filesystem event types.\n */\nexport enum FilesystemEventType {\n /**\n * Filesystem object permissions were changed.\n */\n CHMOD = 'chmod',\n /**\n * Filesystem object was created.\n */\n CREATE = 'create',\n /**\n * Filesystem object was removed.\n */\n REMOVE = 'remove',\n /**\n * Filesystem object was renamed.\n */\n RENAME = 'rename',\n /**\n * Filesystem object was written to.\n */\n WRITE = 'write',\n}\n\nfunction mapEventType(type: EventType) {\n switch (type) {\n case EventType.CHMOD:\n return FilesystemEventType.CHMOD\n case EventType.CREATE:\n return FilesystemEventType.CREATE\n case EventType.REMOVE:\n return FilesystemEventType.REMOVE\n case EventType.RENAME:\n return FilesystemEventType.RENAME\n case EventType.WRITE:\n return FilesystemEventType.WRITE\n }\n}\n\n/**\n * Information about a filesystem event.\n */\nexport interface FilesystemEvent {\n /**\n * Relative path to the filesystem object.\n */\n name: string\n /**\n * Filesystem operation event type.\n */\n type: FilesystemEventType\n}\n\n/**\n * Handle for watching a directory in the sandbox filesystem.\n *\n * Use {@link WatchHandle.stop} to stop watching the directory.\n */\nexport class WatchHandle {\n constructor(\n private readonly handleStop: () => void,\n private readonly events: AsyncIterable<WatchDirResponse>,\n private readonly onEvent?: (event: FilesystemEvent) => void | Promise<void>,\n private readonly onExit?: (err?: Error) => void | Promise<void>\n ) {\n this.handleEvents()\n }\n\n /**\n * Stop watching the directory.\n */\n async stop() {\n this.handleStop()\n }\n\n private async *iterateEvents() {\n try {\n for await (const event of this.events) {\n switch (event.event.case) {\n case 'filesystem':\n yield event.event\n break\n }\n }\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n private async handleEvents() {\n try {\n for await (const event of this.iterateEvents()) {\n const eventType = mapEventType(event.value.type)\n if (eventType === undefined) {\n continue\n }\n\n this.onEvent?.({\n name: event.value.name,\n type: eventType,\n })\n }\n this.onExit?.()\n } catch (err) {\n this.onExit?.(err as Error)\n }\n }\n}\n","import {\n Client,\n Code,\n ConnectError,\n createClient,\n Transport,\n} from '@connectrpc/connect'\nimport {\n ConnectionConfig,\n ConnectionOpts,\n defaultUsername,\n KEEPALIVE_PING_HEADER,\n KEEPALIVE_PING_INTERVAL_SEC,\n Username,\n} from '../../connectionConfig'\n\nimport { handleEnvdApiError, handleWatchDirStartEvent } from '../../envd/api'\nimport { authenticationHeader, handleRpcError } from '../../envd/rpc'\n\nimport { EnvdApiClient } from '../../envd/api'\nimport {\n Filesystem as FilesystemService,\n FileType as FsFileType,\n} from '../../envd/filesystem/filesystem_pb'\n\nimport { FilesystemEvent, WatchHandle } from './watchHandle'\n\nimport type { Timestamp } from '@bufbuild/protobuf/wkt'\nimport { compareVersions } from 'compare-versions'\nimport {\n ENVD_DEFAULT_USER,\n ENVD_OCTET_STREAM_UPLOAD,\n ENVD_VERSION_RECURSIVE_WATCH,\n} from '../../envd/versions'\nimport {\n FileNotFoundError,\n InvalidArgumentError,\n TemplateError,\n} from '../../errors'\nimport { toBlob, toUploadBody } from '../../utils'\n\nconst FILESYSTEM_HTTP_ERROR_MAP: Record<number, (message: string) => Error> = {\n 404: (message: string) => new FileNotFoundError(message),\n}\n\nconst FILESYSTEM_RPC_ERROR_MAP: Partial<\n Record<Code, (message: string) => Error>\n> = {\n [Code.NotFound]: (message: string) => new FileNotFoundError(message),\n}\n\nfunction handleFilesystemRpcError(err: unknown): Error {\n return handleRpcError(err, FILESYSTEM_RPC_ERROR_MAP)\n}\n\nfunction handleFilesystemEnvdApiError(res: {\n error?: { message?: string } | string\n response: Response\n}) {\n return handleEnvdApiError(res, FILESYSTEM_HTTP_ERROR_MAP)\n}\n\n/**\n * Sandbox filesystem object information.\n */\nexport interface WriteInfo {\n /**\n * Name of the filesystem object.\n */\n name: string\n /**\n * Type of the filesystem object.\n */\n type?: FileType\n /**\n * Path to the filesystem object.\n */\n path: string\n}\n\nexport interface EntryInfo extends WriteInfo {\n /**\n * Size of the filesystem object in bytes.\n */\n size: number\n\n /**\n * File mode and permission bits.\n */\n mode: number\n\n /**\n * String representation of file permissions (e.g. 'rwxr-xr-x').\n */\n permissions: string\n\n /**\n * Owner of the filesystem object.\n */\n owner: string\n\n /**\n * Group owner of the filesystem object.\n */\n group: string\n\n /**\n * Last modification time of the filesystem object.\n */\n modifiedTime?: Date\n\n /**\n * If the filesystem object is a symlink, this is the target of the symlink.\n */\n symlinkTarget?: string\n}\n\n/**\n * Sandbox filesystem object type.\n */\nexport enum FileType {\n /**\n * Filesystem object is a file.\n */\n FILE = 'file',\n /**\n * Filesystem object is a directory.\n */\n DIR = 'dir',\n}\n\nexport type WriteEntry = {\n path: string\n data: string | ArrayBuffer | Blob | ReadableStream\n}\n\nfunction mapFileType(fileType: FsFileType) {\n switch (fileType) {\n case FsFileType.DIRECTORY:\n return FileType.DIR\n case FsFileType.FILE:\n return FileType.FILE\n }\n}\n\nfunction mapModifiedTime(modifiedTime: Timestamp | undefined) {\n if (!modifiedTime) return undefined\n\n return new Date(\n Number(modifiedTime.seconds) * 1000 +\n Math.floor(modifiedTime.nanos / 1_000_000)\n )\n}\n\n/**\n * Options for the sandbox filesystem operations.\n */\nexport interface FilesystemRequestOpts\n extends Partial<Pick<ConnectionOpts, 'requestTimeoutMs'>> {\n /**\n * User to use for the operation in the sandbox.\n * This affects the resolution of relative paths and ownership of the created filesystem objects.\n */\n user?: Username\n}\n\n/**\n * Options for writing files to the sandbox filesystem.\n */\nexport interface FilesystemWriteOpts extends FilesystemRequestOpts {\n /**\n * When true, the upload will be gzip-compressed.\n */\n gzip?: boolean\n}\n\n/**\n * Options for reading files from the sandbox filesystem.\n */\nexport interface FilesystemReadOpts extends FilesystemRequestOpts {\n /**\n * When true, the download will request gzip-encoded responses.\n */\n gzip?: boolean\n}\n\nexport interface FilesystemListOpts extends FilesystemRequestOpts {\n /**\n * Depth of the directory to list.\n */\n depth?: number\n}\n\n/**\n * Options for watching a directory.\n */\nexport interface WatchOpts extends FilesystemRequestOpts {\n /**\n * Timeout for the watch operation in **milliseconds**.\n * You can pass `0` to disable the timeout.\n *\n * @default 60_000 // 60 seconds\n */\n timeoutMs?: number\n /**\n * Callback to call when the watch operation stops.\n */\n onExit?: (err?: Error) => void | Promise<void>\n /**\n * Watch the directory recursively\n */\n recursive?: boolean\n}\n\n/**\n * Module for interacting with the sandbox filesystem.\n */\nexport class Filesystem {\n private readonly rpc: Client<typeof FilesystemService>\n\n private readonly defaultWatchTimeout = 60_000 // 60 seconds\n private readonly defaultWatchRecursive = false\n\n constructor(\n transport: Transport,\n private readonly envdApi: EnvdApiClient,\n private readonly connectionConfig: ConnectionConfig\n ) {\n this.rpc = createClient(FilesystemService, transport)\n }\n\n /**\n * Read file content as a `string`.\n *\n * You can pass `text`, `bytes`, `blob`, or `stream` to `opts.format` to change the return type.\n *\n * @param path path to the file.\n * @param opts connection options.\n * @param [opts.format] format of the file content—`text` by default.\n *\n * @returns file content as string\n */\n async read(\n path: string,\n opts?: FilesystemReadOpts & { format?: 'text' }\n ): Promise<string>\n /**\n * Read file content as a `Uint8Array`.\n *\n * You can pass `text`, `bytes`, `blob`, or `stream` to `opts.format` to change the return type.\n *\n * @param path path to the file.\n * @param opts connection options.\n * @param [opts.format] format of the file content—`bytes`.\n *\n * @returns file content as `Uint8Array`\n */\n async read(\n path: string,\n opts?: FilesystemReadOpts & { format: 'bytes' }\n ): Promise<Uint8Array>\n /**\n * Read file content as a `Blob`.\n *\n * You can pass `text`, `bytes`, `blob`, or `stream` to `opts.format` to change the return type.\n *\n * @param path path to the file.\n * @param opts connection options.\n * @param [opts.format] format of the file content—`blob`.\n *\n * @returns file content as `Blob`\n */\n async read(\n path: string,\n opts?: FilesystemReadOpts & { format: 'blob' }\n ): Promise<Blob>\n /**\n * Read file content as a `ReadableStream`.\n *\n * You can pass `text`, `bytes`, `blob`, or `stream` to `opts.format` to change the return type.\n *\n * @param path path to the file.\n * @param opts connection options.\n * @param [opts.format] format of the file content—`stream`.\n *\n * @returns file content as `ReadableStream`\n */\n async read(\n path: string,\n opts?: FilesystemReadOpts & { format: 'stream' }\n ): Promise<ReadableStream<Uint8Array>>\n async read(\n path: string,\n opts?: FilesystemReadOpts & {\n format?: 'text' | 'bytes' | 'blob' | 'stream'\n }\n ): Promise<unknown> {\n const format = opts?.format ?? 'text'\n\n let user = opts?.user\n if (\n user == undefined &&\n compareVersions(this.envdApi.version, ENVD_DEFAULT_USER) < 0\n ) {\n user = defaultUsername\n }\n\n const headers: Record<string, string> = {}\n if (opts?.gzip) {\n headers['Accept-Encoding'] = 'gzip'\n }\n\n const res = await this.envdApi.api.GET('/files', {\n params: {\n query: {\n path,\n username: user,\n },\n },\n parseAs: format === 'bytes' ? 'arrayBuffer' : format,\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n headers,\n })\n\n const err = await handleFilesystemEnvdApiError(res)\n if (err) {\n throw err\n }\n\n if (format === 'bytes') {\n return new Uint8Array(res.data as ArrayBuffer)\n }\n\n // When the file is empty, res.data is parsed as `{}`. This is a workaround to return an empty string.\n if (res.response.headers.get('content-length') === '0') {\n if (format === 'blob') {\n return new Blob([])\n }\n\n return ''\n }\n\n return res.data\n }\n\n /**\n * Write content to a file.\n *\n *\n * Writing to a file that doesn't exist creates the file.\n *\n * Writing to a file that already exists overwrites the file.\n *\n * Writing to a file at path that doesn't exist creates the necessary directories.\n *\n * @param path path to file.\n * @param data data to write to the file. Data can be a string, `ArrayBuffer`, `Blob`, or `ReadableStream`.\n * @param opts connection options.\n *\n * @returns information about the written file\n */\n async write(\n path: string,\n data: string | ArrayBuffer | Blob | ReadableStream,\n opts?: FilesystemWriteOpts\n ): Promise<WriteInfo>\n async write(\n files: WriteEntry[],\n opts?: FilesystemWriteOpts\n ): Promise<WriteInfo[]>\n async write(\n pathOrFiles: string | WriteEntry[],\n dataOrOpts?:\n | string\n | ArrayBuffer\n | Blob\n | ReadableStream\n | FilesystemWriteOpts,\n opts?: FilesystemWriteOpts\n ): Promise<WriteInfo | WriteInfo[]> {\n if (typeof pathOrFiles !== 'string' && !Array.isArray(pathOrFiles)) {\n throw new Error('Path or files are required')\n }\n\n if (typeof pathOrFiles === 'string' && Array.isArray(dataOrOpts)) {\n throw new Error(\n 'Cannot specify both path and array of files. You have to specify either path and data for a single file or an array for multiple files.'\n )\n }\n\n const { path, writeOpts, writeFiles } =\n typeof pathOrFiles === 'string'\n ? {\n path: pathOrFiles,\n writeOpts: opts as FilesystemWriteOpts,\n writeFiles: [\n {\n data: dataOrOpts as\n | string\n | ArrayBuffer\n | Blob\n | ReadableStream,\n },\n ],\n }\n : {\n path: undefined,\n writeOpts: dataOrOpts as FilesystemWriteOpts,\n writeFiles: pathOrFiles as WriteEntry[],\n }\n\n if (writeFiles.length === 0) return [] as WriteInfo[]\n\n let user = writeOpts?.user\n if (\n user == undefined &&\n compareVersions(this.envdApi.version, ENVD_DEFAULT_USER) < 0\n ) {\n user = defaultUsername\n }\n\n const useOctetStream =\n compareVersions(this.envdApi.version, ENVD_OCTET_STREAM_UPLOAD) >= 0\n\n const results: WriteInfo[] = []\n\n const useGzip = writeOpts?.gzip === true\n\n if (useOctetStream) {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/octet-stream',\n }\n if (useGzip) {\n headers['Content-Encoding'] = 'gzip'\n }\n\n const uploadResults = await Promise.all(\n writeFiles.map(async (file) => {\n const filePath = path ?? (file as WriteEntry).path\n const body = await toUploadBody(file.data, useGzip)\n\n const res = await this.envdApi.api.POST('/files', {\n params: {\n query: {\n path: filePath,\n username: user,\n },\n },\n bodySerializer: () => body,\n headers,\n signal: this.connectionConfig.getSignal(\n writeOpts?.requestTimeoutMs\n ),\n body: {},\n })\n\n const err = await handleFilesystemEnvdApiError(res)\n if (err) {\n throw err\n }\n\n const files = res.data as WriteInfo[]\n if (!files || files.length === 0) {\n throw new Error(\n 'Expected to receive information about written file'\n )\n }\n\n return files\n })\n )\n\n for (const files of uploadResults) {\n results.push(...files)\n }\n } else {\n const formData = new FormData()\n for (const file of writeFiles) {\n formData.append(\n 'file',\n await toBlob(file.data),\n (file as WriteEntry).path ?? path!\n )\n }\n\n const res = await this.envdApi.api.POST('/files', {\n params: {\n query: {\n path,\n username: user,\n },\n },\n bodySerializer: () => formData,\n signal: this.connectionConfig.getSignal(writeOpts?.requestTimeoutMs),\n body: {},\n })\n\n const err = await handleFilesystemEnvdApiError(res)\n if (err) {\n throw err\n }\n\n const files = res.data as WriteInfo[]\n if (!files || files.length === 0) {\n throw new Error('Expected to receive information about written file')\n }\n\n results.push(...files)\n }\n\n return results.length === 1 && path ? results[0] : results\n }\n\n /**\n * Write multiple files.\n *\n *\n * Writing to a file that doesn't exist creates the file.\n *\n * Writing to a file that already exists overwrites the file.\n *\n * Writing to a file at path that doesn't exist creates the necessary directories.\n *\n * @param files list of files to write as `WriteEntry` objects, each containing `path` and `data`.\n * @param opts connection options.\n *\n * @returns information about the written files\n */\n async writeFiles(\n files: WriteEntry[],\n opts?: FilesystemWriteOpts\n ): Promise<WriteInfo[]> {\n return this.write(files, opts) as Promise<WriteInfo[]>\n }\n\n /**\n * List entries in a directory.\n *\n * @param path path to the directory.\n * @param opts connection options.\n *\n * @returns list of entries in the sandbox filesystem directory.\n */\n async list(path: string, opts?: FilesystemListOpts): Promise<EntryInfo[]> {\n if (typeof opts?.depth === 'number' && opts.depth < 1) {\n throw new InvalidArgumentError('depth should be at least one')\n }\n\n try {\n const res = await this.rpc.listDir(\n {\n path,\n depth: opts?.depth ?? 1,\n },\n {\n headers: authenticationHeader(this.envdApi.version, opts?.user),\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n const entries: EntryInfo[] = []\n\n for (const e of res.entries) {\n const type = mapFileType(e.type)\n\n if (type) {\n entries.push({\n name: e.name,\n type,\n path: e.path,\n size: Number(e.size),\n mode: e.mode,\n permissions: e.permissions,\n owner: e.owner,\n group: e.group,\n modifiedTime: mapModifiedTime(e.modifiedTime),\n symlinkTarget: e.symlinkTarget,\n })\n }\n }\n\n return entries\n } catch (err) {\n throw handleFilesystemRpcError(err)\n }\n }\n\n /**\n * Create a new directory and all directories along the way if needed on the specified path.\n *\n * @param path path to a new directory. For example '/dirA/dirB' when creating 'dirB'.\n * @param opts connection options.\n *\n * @returns `true` if the directory was created, `false` if it already exists.\n */\n async makeDir(path: string, opts?: FilesystemRequestOpts): Promise<boolean> {\n try {\n await this.rpc.makeDir(\n { path },\n {\n headers: authenticationHeader(this.envdApi.version, opts?.user),\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n return true\n } catch (err) {\n if (err instanceof ConnectError) {\n if (err.code === Code.AlreadyExists) {\n return false\n }\n }\n\n throw handleFilesystemRpcError(err)\n }\n }\n\n /**\n * Rename a file or directory.\n *\n * @param oldPath path to the file or directory to rename.\n * @param newPath new path for the file or directory.\n * @param opts connection options.\n *\n * @returns information about renamed file or directory.\n */\n async rename(\n oldPath: string,\n newPath: string,\n opts?: FilesystemRequestOpts\n ): Promise<EntryInfo> {\n try {\n const res = await this.rpc.move(\n {\n source: oldPath,\n destination: newPath,\n },\n {\n headers: authenticationHeader(this.envdApi.version, opts?.user),\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n const entry = res.entry\n if (!entry) {\n throw new Error('Expected to receive information about moved object')\n }\n\n return {\n name: entry.name,\n type: mapFileType(entry.type),\n path: entry.path,\n size: Number(entry.size),\n mode: entry.mode,\n permissions: entry.permissions,\n owner: entry.owner,\n group: entry.group,\n modifiedTime: mapModifiedTime(entry.modifiedTime),\n symlinkTarget: entry.symlinkTarget,\n }\n } catch (err) {\n throw handleFilesystemRpcError(err)\n }\n }\n\n /**\n * Remove a file or directory.\n *\n * @param path path to a file or directory.\n * @param opts connection options.\n */\n async remove(path: string, opts?: FilesystemRequestOpts): Promise<void> {\n try {\n await this.rpc.remove(\n { path },\n {\n headers: authenticationHeader(this.envdApi.version, opts?.user),\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n } catch (err) {\n throw handleFilesystemRpcError(err)\n }\n }\n\n /**\n * Check if a file or a directory exists.\n *\n * @param path path to a file or a directory\n * @param opts connection options.\n *\n * @returns `true` if the file or directory exists, `false` otherwise\n */\n async exists(path: string, opts?: FilesystemRequestOpts): Promise<boolean> {\n try {\n await this.rpc.stat(\n { path },\n {\n headers: authenticationHeader(this.envdApi.version, opts?.user),\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n return true\n } catch (err) {\n if (err instanceof ConnectError) {\n if (err.code === Code.NotFound) {\n return false\n }\n }\n\n throw handleFilesystemRpcError(err)\n }\n }\n\n /**\n * Get information about a file or directory.\n *\n * @param path path to a file or directory.\n * @param opts connection options.\n *\n * @returns information about the file or directory like name, type, and path.\n */\n async getInfo(\n path: string,\n opts?: FilesystemRequestOpts\n ): Promise<EntryInfo> {\n try {\n const res = await this.rpc.stat(\n { path },\n {\n headers: authenticationHeader(this.envdApi.version, opts?.user),\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n if (!res.entry) {\n throw new Error(\n 'Expected to receive information about the file or directory'\n )\n }\n\n return {\n name: res.entry.name,\n type: mapFileType(res.entry.type),\n path: res.entry.path,\n size: Number(res.entry.size),\n mode: res.entry.mode,\n permissions: res.entry.permissions,\n owner: res.entry.owner,\n group: res.entry.group,\n modifiedTime: mapModifiedTime(res.entry.modifiedTime),\n symlinkTarget: res.entry.symlinkTarget,\n }\n } catch (err) {\n throw handleFilesystemRpcError(err)\n }\n }\n\n /**\n * Start watching a directory for filesystem events.\n *\n * @param path path to directory to watch.\n * @param onEvent callback to call when an event in the directory occurs.\n * @param opts connection options.\n *\n * @returns `WatchHandle` object for stopping watching directory.\n */\n async watchDir(\n path: string,\n onEvent: (event: FilesystemEvent) => void | Promise<void>,\n opts?: WatchOpts & {\n onExit?: (err?: Error) => void | Promise<void>\n }\n ): Promise<WatchHandle> {\n if (\n opts?.recursive &&\n this.envdApi.version &&\n compareVersions(this.envdApi.version, ENVD_VERSION_RECURSIVE_WATCH) < 0\n ) {\n throw new TemplateError(\n 'You need to update the template to use recursive watching. ' +\n 'You can do this by running `ppio template build` in the directory with the template.'\n )\n }\n\n const requestTimeoutMs =\n opts?.requestTimeoutMs ?? this.connectionConfig.requestTimeoutMs\n\n const controller = new AbortController()\n\n const reqTimeout = requestTimeoutMs\n ? setTimeout(() => {\n controller.abort()\n }, requestTimeoutMs)\n : undefined\n\n const events = this.rpc.watchDir(\n {\n path,\n recursive: opts?.recursive ?? this.defaultWatchRecursive,\n },\n {\n headers: {\n ...authenticationHeader(this.envdApi.version, opts?.user),\n [KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString(),\n },\n signal: controller.signal,\n timeoutMs: opts?.timeoutMs ?? this.defaultWatchTimeout,\n }\n )\n\n try {\n await handleWatchDirStartEvent(events)\n\n clearTimeout(reqTimeout)\n\n return new WatchHandle(\n () => controller.abort(),\n events,\n onEvent,\n opts?.onExit\n )\n } catch (err) {\n throw handleFilesystemRpcError(err)\n }\n }\n}\n","import { InvalidArgumentError } from '../../errors'\nimport { CommandExitError } from '../commands/commandHandle'\n\n/**\n * Parsed git status entry for a file.\n */\nexport interface GitFileStatus {\n /**\n * Path relative to the repository root.\n */\n name: string\n /**\n * Normalized status string (for example, `\"modified\"` or `\"added\"`).\n */\n status: GitStatusLabel\n /**\n * Index status character from porcelain output.\n */\n indexStatus: string\n /**\n * Working tree status character from porcelain output.\n */\n workingTreeStatus: string\n /**\n * Whether the change is staged.\n */\n staged: boolean\n /**\n * Original path when the file was renamed.\n */\n renamedFrom?: string\n}\n\n/**\n * Supported normalized git status labels.\n */\nexport type GitStatusLabel =\n | 'conflict'\n | 'renamed'\n | 'copied'\n | 'deleted'\n | 'added'\n | 'modified'\n | 'typechange'\n | 'untracked'\n | 'unknown'\n\n/**\n * Scope for git config operations.\n */\nexport type GitConfigScope = 'global' | 'local' | 'system'\n\n/**\n * Parsed git repository status.\n */\nexport interface GitStatus {\n /**\n * Current branch name, if available.\n */\n currentBranch?: string\n /**\n * Upstream branch name, if available.\n */\n upstream?: string\n /**\n * Number of commits the branch is ahead of upstream.\n */\n ahead: number\n /**\n * Number of commits the branch is behind upstream.\n */\n behind: number\n /**\n * Whether HEAD is detached.\n */\n detached: boolean\n /**\n * List of file status entries.\n */\n fileStatus: GitFileStatus[]\n /**\n * Whether the repository has no tracked or untracked file changes.\n */\n isClean: boolean\n /**\n * Whether the repository has any tracked or untracked file changes.\n */\n hasChanges: boolean\n /**\n * Whether there are staged changes.\n */\n hasStaged: boolean\n /**\n * Whether there are untracked files.\n */\n hasUntracked: boolean\n /**\n * Whether there are merge conflicts.\n */\n hasConflicts: boolean\n /**\n * Total number of changed files.\n */\n totalCount: number\n /**\n * Number of files with staged changes.\n */\n stagedCount: number\n /**\n * Number of files with unstaged changes.\n */\n unstagedCount: number\n /**\n * Number of untracked files.\n */\n untrackedCount: number\n /**\n * Number of files with merge conflicts.\n */\n conflictCount: number\n}\n\n/**\n * Parsed git branch list.\n */\nexport interface GitBranches {\n /**\n * List of branch names.\n */\n branches: string[]\n /**\n * Current branch name, if available.\n */\n currentBranch?: string\n}\n\n/**\n * Escape a string for safe use in a shell command.\n *\n * This uses single-quoted shell escaping and safely handles embedded single quotes.\n */\nexport function shellEscape(value: string): string {\n return `'${value.replace(/'/g, \"'\\\"'\\\"'\")}'`\n}\n\n/**\n * Add HTTP(S) credentials to a Git URL.\n *\n * @param url Git repository URL.\n * @param username Username for HTTP(S) authentication.\n * @param password Password or token for HTTP(S) authentication.\n * @returns URL with embedded credentials.\n */\nexport function withCredentials(\n url: string,\n username?: string,\n password?: string\n): string {\n if (!username && !password) {\n return url\n }\n\n if (!username || !password) {\n throw new InvalidArgumentError(\n 'Both username and password are required when using Git credentials.'\n )\n }\n\n let parsed: URL\n try {\n parsed = new URL(url)\n } catch {\n throw new InvalidArgumentError(`Invalid Git URL: ${url}`)\n }\n\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw new InvalidArgumentError(\n 'Only http(s) Git URLs support username/password credentials.'\n )\n }\n\n parsed.username = username\n parsed.password = password\n\n return parsed.toString()\n}\n\n/**\n * Strip HTTP(S) credentials from a Git URL.\n *\n * @param url Git repository URL.\n * @returns URL without embedded credentials.\n */\nexport function stripCredentials(url: string): string {\n let parsed: URL\n try {\n parsed = new URL(url)\n } catch {\n return url\n }\n\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n return url\n }\n\n if (!parsed.username && !parsed.password) {\n return url\n }\n\n parsed.username = ''\n parsed.password = ''\n return parsed.toString()\n}\n\n/**\n * Derive the default repository directory name from a Git URL.\n *\n * @param url Git repository URL.\n * @returns Repository directory name, if it can be determined.\n */\nexport function deriveRepoDirFromUrl(url: string): string | undefined {\n let parsed: URL\n try {\n parsed = new URL(url)\n } catch {\n return undefined\n }\n\n const trimmedPath = parsed.pathname.replace(/\\/+$/, '')\n const lastSegment = trimmedPath.split('/').pop()\n if (!lastSegment) {\n return undefined\n }\n\n return lastSegment.endsWith('.git') ? lastSegment.slice(0, -4) : lastSegment\n}\n\n/**\n * Build a shell-safe git command string.\n *\n * @param args Git command arguments.\n * @param repoPath Repository path for `git -C`, if provided.\n * @returns Shell-safe git command.\n */\nexport function buildGitCommand(args: string[], repoPath?: string): string {\n const parts = ['git']\n if (repoPath) {\n parts.push('-C', repoPath)\n }\n parts.push(...args)\n\n return parts.map((part) => shellEscape(part)).join(' ')\n}\n\ntype GitPushArgsOptions = {\n remote?: string\n branch?: string\n setUpstream: boolean\n}\n\nexport function buildPushArgs(\n remoteName: string | undefined,\n opts: GitPushArgsOptions\n): string[] {\n const { remote, branch, setUpstream } = opts\n const args = ['push']\n const targetRemote = remoteName ?? remote\n if (setUpstream && targetRemote) {\n args.push('--set-upstream')\n }\n if (targetRemote) {\n args.push(targetRemote)\n }\n if (branch) {\n args.push(branch)\n }\n return args\n}\n\nfunction parseAheadBehind(segment?: string): { ahead: number; behind: number } {\n if (!segment) {\n return { ahead: 0, behind: 0 }\n }\n\n let ahead = 0\n let behind = 0\n\n if (segment.includes('ahead')) {\n try {\n ahead = Number.parseInt(\n segment.split('ahead')[1].split(',')[0].trim(),\n 10\n )\n } catch {\n ahead = 0\n }\n }\n\n if (segment.includes('behind')) {\n try {\n behind = Number.parseInt(\n segment.split('behind')[1].split(',')[0].trim(),\n 10\n )\n } catch {\n behind = 0\n }\n }\n\n return { ahead, behind }\n}\n\nfunction normalizeBranchName(name: string): string {\n if (name.startsWith('HEAD (detached at ')) {\n return name.replace('HEAD (detached at ', '').replace(/\\)$/, '')\n }\n\n return name\n .replace('HEAD (no branch)', 'HEAD')\n .replace('No commits yet on ', '')\n .replace('Initial commit on ', '')\n}\n\nfunction deriveStatus(\n indexStatus: string,\n workingStatus: string\n): GitStatusLabel {\n const statuses = new Set([indexStatus, workingStatus])\n\n if (statuses.has('U')) return 'conflict'\n if (statuses.has('R')) return 'renamed'\n if (statuses.has('C')) return 'copied'\n if (statuses.has('D')) return 'deleted'\n if (statuses.has('A')) return 'added'\n if (statuses.has('M')) return 'modified'\n if (statuses.has('T')) return 'typechange'\n if (statuses.has('?')) return 'untracked'\n\n return 'unknown'\n}\n\n/**\n * Parse `git status --porcelain=1 -b` output into a structured object.\n *\n * @param output Git status output.\n * @returns Parsed {@link GitStatus}.\n */\nexport function parseGitStatus(output: string): GitStatus {\n const lines = output\n .split('\\n')\n .map((line) => line.replace(/\\r$/, ''))\n .filter((line) => line.trim().length > 0)\n\n let currentBranch: string | undefined\n let upstream: string | undefined\n let ahead = 0\n let behind = 0\n let detached = false\n const fileStatus: GitFileStatus[] = []\n\n if (lines.length === 0) {\n return {\n currentBranch,\n upstream,\n ahead,\n behind,\n detached,\n fileStatus,\n isClean: true,\n hasChanges: false,\n hasStaged: false,\n hasUntracked: false,\n hasConflicts: false,\n totalCount: 0,\n stagedCount: 0,\n unstagedCount: 0,\n untrackedCount: 0,\n conflictCount: 0,\n }\n }\n\n const branchLine = lines[0]\n if (branchLine.startsWith('## ')) {\n const branchInfo = branchLine.slice(3)\n const aheadStart = branchInfo.indexOf(' [')\n const branchPart =\n aheadStart === -1 ? branchInfo : branchInfo.slice(0, aheadStart)\n const aheadPart =\n aheadStart === -1 ? undefined : branchInfo.slice(aheadStart + 2, -1)\n const normalizedBranch = normalizeBranchName(branchPart)\n const rawBranch = branchPart\n const isDetached =\n rawBranch.startsWith('HEAD (detached at ') ||\n rawBranch.includes('detached')\n\n if (isDetached || normalizedBranch.startsWith('HEAD')) {\n detached = true\n } else if (normalizedBranch.includes('...')) {\n const [branch, upstreamBranch] = normalizedBranch.split('...')\n currentBranch = branch || undefined\n upstream = upstreamBranch || undefined\n } else {\n currentBranch = normalizedBranch || undefined\n }\n\n const aheadBehind = parseAheadBehind(aheadPart)\n ahead = aheadBehind.ahead\n behind = aheadBehind.behind\n }\n\n for (const line of lines.slice(1)) {\n if (line.startsWith('?? ')) {\n const name = line.slice(3)\n fileStatus.push({\n name,\n status: 'untracked',\n indexStatus: '?',\n workingTreeStatus: '?',\n staged: false,\n })\n continue\n }\n\n if (line.length < 3) {\n continue\n }\n\n const indexStatus = line[0]\n const workingTreeStatus = line[1]\n const path = line.slice(3)\n\n let renamedFrom: string | undefined\n let name = path\n\n if (path.includes(' -> ')) {\n const parts = path.split(' -> ')\n renamedFrom = parts[0]\n name = parts.slice(1).join(' -> ')\n }\n\n fileStatus.push({\n name,\n status: deriveStatus(indexStatus, workingTreeStatus),\n indexStatus,\n workingTreeStatus,\n staged: indexStatus !== ' ' && indexStatus !== '?',\n ...(renamedFrom ? { renamedFrom } : {}),\n })\n }\n\n const totalCount = fileStatus.length\n const stagedCount = fileStatus.filter((item) => item.staged).length\n const untrackedCount = fileStatus.filter(\n (item) => item.status === 'untracked'\n ).length\n const conflictCount = fileStatus.filter(\n (item) => item.status === 'conflict'\n ).length\n const unstagedCount = totalCount - stagedCount\n\n return {\n currentBranch,\n upstream,\n ahead,\n behind,\n detached,\n fileStatus,\n isClean: totalCount === 0,\n hasChanges: totalCount > 0,\n hasStaged: stagedCount > 0,\n hasUntracked: untrackedCount > 0,\n hasConflicts: conflictCount > 0,\n totalCount,\n stagedCount,\n unstagedCount,\n untrackedCount,\n conflictCount,\n }\n}\n\n/**\n * Parse `git branch --format=%(refname:short)\\t%(HEAD)` output.\n *\n * @param output Git branch output.\n * @returns Parsed {@link GitBranches}.\n */\nexport function parseGitBranches(output: string): GitBranches {\n const branches: string[] = []\n let currentBranch: string | undefined\n\n const lines = output\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n\n for (const line of lines) {\n const parts = line.split('\\t')\n const name = parts[0]\n branches.push(name)\n if (parts.length > 1 && parts[1] === '*') {\n currentBranch = name\n }\n }\n\n return { branches, currentBranch }\n}\n\nexport function isAuthFailure(err: unknown): boolean {\n if (!(err instanceof CommandExitError)) {\n return false\n }\n\n const message = `${err.stderr}\\n${err.stdout}`.toLowerCase()\n const authSnippets = [\n 'authentication failed',\n 'terminal prompts disabled',\n 'could not read username',\n 'invalid username or password',\n 'access denied',\n 'permission denied',\n 'not authorized',\n ]\n\n return authSnippets.some((snippet) => message.includes(snippet))\n}\n\nexport function getScopeFlag(scope: GitConfigScope): `--${GitConfigScope}` {\n if (scope !== 'global' && scope !== 'local' && scope !== 'system') {\n throw new InvalidArgumentError(\n 'Git config scope must be one of: global, local, system.'\n )\n }\n return `--${scope}`\n}\n\nexport function isMissingUpstream(err: unknown): boolean {\n if (!(err instanceof CommandExitError)) {\n return false\n }\n\n const message = `${err.stderr}\\n${err.stdout}`.toLowerCase()\n const upstreamSnippets = [\n 'has no upstream branch',\n 'no upstream branch',\n 'no upstream configured',\n 'no tracking information for the current branch',\n 'no tracking information',\n 'set the remote as upstream',\n 'set the upstream branch',\n 'please specify which branch you want to merge with',\n ]\n\n return upstreamSnippets.some((snippet) => message.includes(snippet))\n}\n\nexport function buildAuthErrorMessage(\n action: 'clone' | 'push' | 'pull',\n missingPassword: boolean\n): string {\n if (missingPassword) {\n return `Git ${action} requires a password/token for private repositories.`\n }\n return `Git ${action} requires credentials for private repositories.`\n}\n\nexport function buildUpstreamErrorMessage(action: 'push' | 'pull'): string {\n if (action === 'push') {\n return (\n 'Git push failed because no upstream branch is configured. ' +\n 'Set upstream once with { setUpstream: true } (and optional remote/branch), ' +\n 'or pass remote and branch explicitly.'\n )\n }\n\n return (\n 'Git pull failed because no upstream branch is configured. ' +\n 'Pass remote and branch explicitly, or set upstream once (push with { setUpstream: true } ' +\n 'or run: git branch --set-upstream-to=origin/<branch> <branch>).'\n )\n}\n\nexport function getRepoPathForScope(\n scope: GitConfigScope,\n path?: string\n): string | undefined {\n if (scope !== 'local') {\n return undefined\n }\n if (!path) {\n throw new InvalidArgumentError(\n 'A repository path is required when using scope \"local\".'\n )\n }\n return path\n}\n","import {\n GitAuthError,\n GitUpstreamError,\n InvalidArgumentError,\n} from '../../errors'\nimport type { CommandStartOpts } from '../commands'\nimport type { CommandResult } from '../commands/commandHandle'\nimport { Commands } from '../commands'\nimport {\n buildAuthErrorMessage,\n buildGitCommand,\n buildPushArgs,\n buildUpstreamErrorMessage,\n GitBranches,\n GitConfigScope,\n GitStatus,\n getRepoPathForScope,\n getScopeFlag,\n isAuthFailure,\n isMissingUpstream,\n parseGitBranches,\n parseGitStatus,\n shellEscape,\n stripCredentials,\n deriveRepoDirFromUrl,\n withCredentials,\n} from './utils'\n\nconst DEFAULT_GIT_ENV: Record<string, string> = {\n GIT_TERMINAL_PROMPT: '0',\n}\n\n/**\n * Options for git operations in the sandbox.\n */\nexport interface GitRequestOpts\n extends Partial<\n Pick<\n CommandStartOpts,\n 'envs' | 'user' | 'cwd' | 'timeoutMs' | 'requestTimeoutMs'\n >\n > {}\n\n/**\n * Options for cloning a repository.\n */\nexport interface GitCloneOpts extends GitRequestOpts {\n /**\n * Destination path for the clone.\n */\n path?: string\n /**\n * Branch to check out.\n */\n branch?: string\n /**\n * If set, perform a shallow clone with this depth.\n */\n depth?: number\n /**\n * Username for HTTP(S) authentication.\n */\n username?: string\n /**\n * Password or token for HTTP(S) authentication.\n */\n password?: string\n /**\n * Store credentials in the cloned repository when `true`.\n *\n * @default false\n */\n dangerouslyStoreCredentials?: boolean\n}\n\n/**\n * Options for initializing a repository.\n */\nexport interface GitInitOpts extends GitRequestOpts {\n /**\n * Create a bare repository when `true`.\n */\n bare?: boolean\n /**\n * Initial branch name (for example, `\"main\"`).\n */\n initialBranch?: string\n}\n\n/**\n * Options for adding a git remote.\n */\nexport interface GitRemoteAddOpts extends GitRequestOpts {\n /**\n * Fetch the remote after adding it when `true`.\n */\n fetch?: boolean\n /**\n * Overwrite the remote URL if the remote already exists when `true`.\n */\n overwrite?: boolean\n}\n\n/**\n * Options for creating a commit.\n */\nexport interface GitCommitOpts extends GitRequestOpts {\n /**\n * Commit author name.\n */\n authorName?: string\n /**\n * Commit author email.\n */\n authorEmail?: string\n /**\n * Allow empty commits when `true`.\n */\n allowEmpty?: boolean\n}\n\n/**\n * Options for staging files.\n */\nexport interface GitAddOpts extends GitRequestOpts {\n /**\n * Files to add; when omitted, adds the current directory.\n */\n files?: string[]\n /**\n * When `true` and `files` is omitted, stage all changes.\n */\n all?: boolean\n}\n\n/**\n * Supported reset modes.\n */\nexport type GitResetMode = 'soft' | 'mixed' | 'hard' | 'merge' | 'keep'\n\n/**\n * Options for resetting a repository.\n */\nexport interface GitResetOpts extends GitRequestOpts {\n /**\n * Reset mode to use.\n */\n mode?: GitResetMode\n /**\n * Commit, branch, or ref to reset to (defaults to HEAD).\n */\n target?: string\n /**\n * Paths to reset.\n */\n paths?: string[]\n}\n\n/**\n * Options for restoring files or unstaging changes.\n */\nexport interface GitRestoreOpts extends GitRequestOpts {\n /**\n * Paths to restore (use `['.']` for all).\n */\n paths: string[]\n /**\n * Restore the index (unstage).\n */\n staged?: boolean\n /**\n * Restore working tree files.\n */\n worktree?: boolean\n /**\n * Restore from the given source (commit, branch, or ref).\n */\n source?: string\n}\n/**\n * Options for deleting a branch.\n */\nexport interface GitDeleteBranchOpts extends GitRequestOpts {\n /**\n * Force deletion with `-D` when `true`.\n */\n force?: boolean\n}\n\n/**\n * Options for pushing commits.\n */\nexport interface GitPushOpts extends GitRequestOpts {\n /**\n * Remote name (for example, `\"origin\"`).\n */\n remote?: string\n /**\n * Branch name to push.\n */\n branch?: string\n /**\n * Set upstream tracking when `true`.\n */\n setUpstream?: boolean\n /**\n * Username for HTTP(S) authentication.\n */\n username?: string\n /**\n * Password or token for HTTP(S) authentication.\n */\n password?: string\n}\n\n/**\n * Options for pulling commits.\n */\nexport interface GitPullOpts extends GitRequestOpts {\n /**\n * Remote name (for example, `\"origin\"`).\n */\n remote?: string\n /**\n * Branch name to pull.\n */\n branch?: string\n /**\n * Username for HTTP(S) authentication.\n */\n username?: string\n /**\n * Password or token for HTTP(S) authentication.\n */\n password?: string\n}\n\n/**\n * Supported scopes for git config operations.\n */\n/**\n * Options for git config operations.\n */\nexport interface GitConfigOpts extends GitRequestOpts {\n /**\n * Scope for the git config command.\n *\n * @default \"global\"\n */\n scope?: GitConfigScope\n /**\n * Repository path required when `scope` is `\"local\"`.\n */\n path?: string\n}\n\n/**\n * Options for dangerously authenticating git globally via the credential helper.\n */\nexport interface GitDangerouslyAuthenticateOpts extends GitRequestOpts {\n /**\n * Username for HTTP(S) authentication.\n */\n username: string\n /**\n * Password or token for HTTP(S) authentication.\n */\n password: string\n /**\n * Host to authenticate for.\n *\n * @default \"github.com\"\n */\n host?: string\n /**\n * Protocol to authenticate for.\n *\n * @default \"https\"\n */\n protocol?: string\n}\n\n/**\n * Module for running git operations in the sandbox.\n */\nexport class Git {\n constructor(private readonly commands: Commands) {}\n\n /**\n * Clone a git repository into the sandbox.\n *\n * @param url Git repository URL.\n * @param opts Clone options.\n * @returns Command result from the command runner.\n */\n async clone(url: string, opts?: GitCloneOpts): Promise<CommandResult> {\n const {\n username,\n password,\n branch,\n depth,\n path,\n dangerouslyStoreCredentials,\n ...rest\n } = opts ?? {}\n\n if (password && !username) {\n throw new InvalidArgumentError(\n 'Username is required when using a password or token for git clone.'\n )\n }\n\n const attemptClone = async (\n authUsername?: string,\n authPassword?: string\n ): Promise<CommandResult> => {\n const urlWithCreds =\n authUsername && authPassword\n ? withCredentials(url, authUsername, authPassword)\n : url\n\n const sanitizedUrl = stripCredentials(urlWithCreds)\n const stripInlineCreds =\n !dangerouslyStoreCredentials && sanitizedUrl !== urlWithCreds\n\n const repoPath = stripInlineCreds\n ? (path ?? deriveRepoDirFromUrl(url))\n : path\n\n if (stripInlineCreds && !repoPath) {\n throw new InvalidArgumentError(\n 'A destination path is required when using credentials without storing them.'\n )\n }\n\n const args = ['clone', urlWithCreds]\n\n if (branch) args.push('--branch', branch, '--single-branch')\n if (depth) args.push('--depth', depth.toString())\n if (repoPath) args.push(repoPath)\n\n const result = await this.runGit(args, undefined, rest)\n\n if (stripInlineCreds) {\n await this.runGit(\n ['remote', 'set-url', 'origin', sanitizedUrl],\n repoPath,\n rest\n )\n }\n\n return result\n }\n\n try {\n return await attemptClone(username, password)\n } catch (err) {\n if (isAuthFailure(err)) {\n throw new GitAuthError(\n buildAuthErrorMessage('clone', Boolean(username) && !password)\n )\n }\n throw err\n }\n }\n\n /**\n * Initialize a new git repository.\n *\n * @param path Destination path for the repository.\n * @param opts Init options.\n * @returns Command result from the command runner.\n */\n async init(path: string, opts?: GitInitOpts): Promise<CommandResult> {\n const { bare, initialBranch, ...rest } = opts ?? {}\n const args = ['init']\n\n if (initialBranch) {\n args.push('--initial-branch', initialBranch)\n }\n if (bare) {\n args.push('--bare')\n }\n\n args.push(path)\n return this.runGit(args, undefined, rest)\n }\n\n /**\n * Add (or update) a remote for a repository.\n *\n * @param path Repository path.\n * @param name Remote name (for example, `\"origin\"`).\n * @param url Remote URL.\n * @param opts Remote add options.\n * @returns Command result from the command runner.\n */\n async remoteAdd(\n path: string,\n name: string,\n url: string,\n opts?: GitRemoteAddOpts\n ): Promise<CommandResult> {\n if (!name || !url) {\n throw new InvalidArgumentError(\n 'Both remote name and URL are required to add a git remote.'\n )\n }\n\n const { fetch, overwrite, ...rest } = opts ?? {}\n const addArgs = ['remote', 'add']\n\n if (fetch) {\n addArgs.push('-f')\n }\n\n addArgs.push(name, url)\n\n if (!overwrite) {\n return this.runGit(addArgs, path, rest)\n }\n\n const addCmd = buildGitCommand(addArgs, path)\n const setUrlCmd = buildGitCommand(['remote', 'set-url', name, url], path)\n let cmd = `${addCmd} || ${setUrlCmd}`\n if (fetch) {\n const fetchCmd = buildGitCommand(['fetch', name], path)\n cmd = `(${cmd}) && ${fetchCmd}`\n }\n return this.runShell(cmd, rest)\n }\n\n /**\n * Get the URL for a git remote.\n *\n * Returns `undefined` when the remote does not exist.\n *\n * @param path Repository path.\n * @param name Remote name (for example, `\"origin\"`).\n * @param opts Command execution options.\n * @returns Remote URL if present.\n */\n async remoteGet(\n path: string,\n name: string,\n opts?: GitRequestOpts\n ): Promise<string | undefined> {\n if (!name) {\n throw new InvalidArgumentError('Remote name is required.')\n }\n\n const cmd = `${buildGitCommand(['remote', 'get-url', name], path)} || true`\n const result = await this.runShell(cmd, opts)\n const trimmed = result.stdout.trim()\n return trimmed.length > 0 ? trimmed : undefined\n }\n\n /**\n * Get repository status information.\n *\n * @param path Repository path.\n * @param opts Command execution options.\n * @returns Parsed git status.\n */\n async status(path: string, opts?: GitRequestOpts): Promise<GitStatus> {\n const result = await this.runGit(\n ['status', '--porcelain=1', '-b'],\n path,\n opts\n )\n return parseGitStatus(result.stdout)\n }\n\n /**\n * List branches in a repository.\n *\n * @param path Repository path.\n * @param opts Command execution options.\n * @returns Parsed branch list.\n */\n async branches(path: string, opts?: GitRequestOpts): Promise<GitBranches> {\n const result = await this.runGit(\n ['branch', '--format=%(refname:short)\\t%(HEAD)'],\n path,\n opts\n )\n return parseGitBranches(result.stdout)\n }\n\n /**\n * Create and check out a new branch.\n *\n * @param path Repository path.\n * @param branch Branch name to create.\n * @param opts Command execution options.\n * @returns Command result from the command runner.\n */\n async createBranch(\n path: string,\n branch: string,\n opts?: GitRequestOpts\n ): Promise<CommandResult> {\n return this.runGit(['checkout', '-b', branch], path, opts)\n }\n\n /**\n * Check out an existing branch.\n *\n * @param path Repository path.\n * @param branch Branch name to check out.\n * @param opts Command execution options.\n * @returns Command result from the command runner.\n */\n async checkoutBranch(\n path: string,\n branch: string,\n opts?: GitRequestOpts\n ): Promise<CommandResult> {\n return this.runGit(['checkout', branch], path, opts)\n }\n\n /**\n * Delete a branch.\n *\n * @param path Repository path.\n * @param branch Branch name to delete.\n * @param opts Delete options.\n * @returns Command result from the command runner.\n */\n async deleteBranch(\n path: string,\n branch: string,\n opts?: GitDeleteBranchOpts\n ): Promise<CommandResult> {\n const { force, ...rest } = opts ?? {}\n const args = ['branch', force ? '-D' : '-d', branch]\n return this.runGit(args, path, rest)\n }\n\n /**\n * Stage files for commit.\n *\n * @param path Repository path.\n * @param opts Add options.\n * @returns Command result from the command runner.\n */\n async add(path: string, opts?: GitAddOpts): Promise<CommandResult> {\n const { files, all = true, ...rest } = opts ?? {}\n const args = ['add']\n\n if (!files || files.length === 0) {\n args.push(all ? '-A' : '.')\n } else {\n args.push('--', ...files)\n }\n\n return this.runGit(args, path, rest)\n }\n\n /**\n * Create a commit in the repository.\n *\n * @param path Repository path.\n * @param message Commit message.\n * @param opts Commit options.\n * @returns Command result from the command runner.\n */\n async commit(\n path: string,\n message: string,\n opts?: GitCommitOpts\n ): Promise<CommandResult> {\n const { authorName, authorEmail, allowEmpty, ...rest } = opts ?? {}\n const args = ['commit', '-m', message]\n\n if (allowEmpty) {\n args.push('--allow-empty')\n }\n\n const authorArgs: string[] = []\n if (authorName) {\n authorArgs.push('-c', `user.name=${authorName}`)\n }\n if (authorEmail) {\n authorArgs.push('-c', `user.email=${authorEmail}`)\n }\n\n return this.runGit([...authorArgs, ...args], path, rest)\n }\n\n /**\n * Reset the current HEAD to a specified state.\n *\n * @param path Repository path.\n * @param opts Reset options.\n * @returns Command result from the command runner.\n */\n async reset(path: string, opts?: GitResetOpts): Promise<CommandResult> {\n const { mode, target, paths, ...rest } = opts ?? {}\n const allowedModes: GitResetMode[] = [\n 'soft',\n 'mixed',\n 'hard',\n 'merge',\n 'keep',\n ]\n\n if (mode && !allowedModes.includes(mode)) {\n throw new InvalidArgumentError(\n `Reset mode must be one of ${allowedModes.join(', ')}.`\n )\n }\n\n const args = ['reset']\n if (mode) {\n args.push(`--${mode}`)\n }\n if (target) {\n args.push(target)\n }\n if (paths && paths.length > 0) {\n args.push('--', ...paths)\n }\n\n return this.runGit(args, path, rest)\n }\n\n /**\n * Restore working tree files or unstage changes.\n *\n * @param path Repository path.\n * @param opts Restore options.\n * @returns Command result from the command runner.\n */\n async restore(path: string, opts: GitRestoreOpts): Promise<CommandResult> {\n const { paths, staged, worktree, source, ...rest } = opts\n\n if (!paths || paths.length === 0) {\n throw new InvalidArgumentError('At least one path is required.')\n }\n\n let resolvedStaged = staged\n let resolvedWorktree = worktree\n\n if (staged === undefined && worktree === undefined) {\n resolvedWorktree = true\n } else if (staged === true && worktree === undefined) {\n resolvedWorktree = false\n } else if (staged === undefined && worktree !== undefined) {\n resolvedStaged = false\n }\n\n if (resolvedStaged === false && resolvedWorktree === false) {\n throw new InvalidArgumentError(\n 'At least one of staged or worktree must be true.'\n )\n }\n\n const args = ['restore']\n if (resolvedWorktree) {\n args.push('--worktree')\n }\n if (resolvedStaged) {\n args.push('--staged')\n }\n if (source) {\n args.push('--source', source)\n }\n args.push('--', ...paths)\n\n return this.runGit(args, path, rest)\n }\n\n /**\n * Push commits to a remote.\n *\n * @param path Repository path.\n * @param opts Push options.\n * @returns Command result from the command runner.\n */\n async push(path: string, opts?: GitPushOpts): Promise<CommandResult> {\n const {\n remote,\n branch,\n setUpstream = true,\n username,\n password,\n ...rest\n } = opts ?? {}\n\n if (password && !username) {\n throw new InvalidArgumentError(\n 'Username is required when using a password or token for git push.'\n )\n }\n\n if (username && password) {\n const remoteName = await this.resolveRemoteName(path, remote, rest)\n return this.withRemoteCredentials(\n path,\n remoteName,\n username,\n password,\n rest,\n () =>\n this.runGit(\n buildPushArgs(remoteName, { remote, branch, setUpstream }),\n path,\n rest\n )\n )\n }\n\n try {\n return await this.runGit(\n buildPushArgs(undefined, { remote, branch, setUpstream }),\n path,\n rest\n )\n } catch (err) {\n if (isAuthFailure(err)) {\n throw new GitAuthError(\n buildAuthErrorMessage('push', Boolean(username) && !password)\n )\n }\n if (isMissingUpstream(err)) {\n throw new GitUpstreamError(buildUpstreamErrorMessage('push'))\n }\n throw err\n }\n }\n\n /**\n * Pull changes from a remote.\n *\n * @param path Repository path.\n * @param opts Pull options.\n * @returns Command result from the command runner.\n */\n async pull(path: string, opts?: GitPullOpts): Promise<CommandResult> {\n const { remote, branch, username, password, ...rest } = opts ?? {}\n if (password && !username) {\n throw new InvalidArgumentError(\n 'Username is required when using a password or token for git pull.'\n )\n }\n\n if (!remote && !branch) {\n const hasUpstream = await this.hasUpstream(path, rest)\n if (!hasUpstream) {\n throw new GitUpstreamError(buildUpstreamErrorMessage('pull'))\n }\n }\n\n const buildArgs = (remoteName?: string) => {\n const args = ['pull']\n const targetRemote = remoteName ?? remote\n if (targetRemote) {\n args.push(targetRemote)\n }\n if (branch) {\n args.push(branch)\n }\n return args\n }\n\n if (username && password) {\n const remoteName = await this.resolveRemoteName(path, remote, rest)\n return this.withRemoteCredentials(\n path,\n remoteName,\n username,\n password,\n rest,\n () => this.runGit(buildArgs(remoteName), path, rest)\n )\n }\n\n try {\n return await this.runGit(buildArgs(), path, rest)\n } catch (err) {\n if (isAuthFailure(err)) {\n throw new GitAuthError(\n buildAuthErrorMessage('pull', Boolean(username) && !password)\n )\n }\n if (isMissingUpstream(err)) {\n throw new GitUpstreamError(buildUpstreamErrorMessage('pull'))\n }\n throw err\n }\n }\n\n /**\n * Set a git config value.\n *\n * Use `scope: \"local\"` together with `path` to configure a specific repository.\n *\n * @param key Git config key (for example, `\"pull.rebase\"`).\n * @param value Git config value.\n * @param opts Config options.\n * @returns Command result from the command runner.\n */\n async setConfig(\n key: string,\n value: string,\n opts?: GitConfigOpts\n ): Promise<CommandResult> {\n if (!key) {\n throw new InvalidArgumentError('Git config key is required.')\n }\n\n const scope = opts?.scope ?? 'global'\n const scopeFlag = getScopeFlag(scope)\n const repoPath = getRepoPathForScope(scope, opts?.path)\n\n return this.runGit(['config', scopeFlag, key, value], repoPath, opts)\n }\n\n /**\n * Get a git config value.\n *\n * Returns `undefined` when the key is not set in the requested scope.\n *\n * @param key Git config key (for example, `\"pull.rebase\"`).\n * @param opts Config options.\n * @returns The config value if present.\n */\n async getConfig(\n key: string,\n opts?: GitConfigOpts\n ): Promise<string | undefined> {\n if (!key) {\n throw new InvalidArgumentError('Git config key is required.')\n }\n\n const scope = opts?.scope ?? 'global'\n const scopeFlag = getScopeFlag(scope)\n const repoPath = getRepoPathForScope(scope, opts?.path)\n const cmd = `${buildGitCommand(['config', scopeFlag, '--get', key], repoPath)} || true`\n const result = await this.runShell(cmd, opts)\n const trimmed = result.stdout.trim()\n return trimmed.length > 0 ? trimmed : undefined\n }\n\n /**\n * Dangerously authenticate git globally via the credential helper.\n *\n * This persists credentials in the credential store.\n * Prefer short-lived credentials when possible.\n *\n * @param opts Authentication options.\n * @returns Command result from the command runner.\n */\n async dangerouslyAuthenticate(\n opts: GitDangerouslyAuthenticateOpts\n ): Promise<CommandResult> {\n const { username, password, host, protocol, ...rest } = opts\n\n if (!username || !password) {\n throw new InvalidArgumentError(\n 'Both username and password are required to authenticate git.'\n )\n }\n\n const targetHost = (host ?? 'github.com').trim()\n const targetProtocol = (protocol ?? 'https').trim()\n const credentialInput = [\n `protocol=${targetProtocol}`,\n `host=${targetHost}`,\n `username=${username}`,\n `password=${password}`,\n '',\n '',\n ].join('\\n')\n\n await this.runGit(\n ['config', '--global', 'credential.helper', 'store'],\n undefined,\n rest\n )\n\n const approveCmd = `printf %s ${shellEscape(credentialInput)} | ${buildGitCommand(\n ['credential', 'approve']\n )}`\n\n return this.runShell(approveCmd, rest)\n }\n\n /**\n * Configure git user name and email.\n *\n * @param name Git user name.\n * @param email Git user email.\n * @param opts Config options.\n * @returns Command result from the command runner.\n */\n async configureUser(\n name: string,\n email: string,\n opts?: GitConfigOpts\n ): Promise<CommandResult> {\n if (!name || !email) {\n throw new InvalidArgumentError('Both name and email are required.')\n }\n\n const scope = opts?.scope ?? 'global'\n const configOpts = { ...opts, scope }\n\n await this.setConfig('user.name', name, configOpts)\n return this.setConfig('user.email', email, configOpts)\n }\n\n /**\n * Build and execute a git command inside the sandbox.\n *\n * @param args Git arguments to pass to the git binary.\n * @param repoPath Repository path used with `git -C`, if provided.\n * @param opts Command execution options.\n * @returns Command result from the command runner.\n */\n private async runGit(\n args: string[],\n repoPath?: string,\n opts?: GitRequestOpts\n ): Promise<CommandResult> {\n const { envs, ...rest } = opts ?? {}\n const cmd = buildGitCommand(args, repoPath)\n const mergedEnvs = { ...DEFAULT_GIT_ENV, ...(envs ?? {}) }\n\n return this.commands.run(cmd, {\n ...rest,\n envs: mergedEnvs,\n })\n }\n\n /**\n * Execute a raw shell command while applying default git environment variables.\n *\n Note: We can likely just modify runGit later to allow appending commands to the git but for now it's separate.\n */\n private async runShell(\n cmd: string,\n opts?: GitRequestOpts\n ): Promise<CommandResult> {\n const { envs, ...rest } = opts ?? {}\n const mergedEnvs = { ...DEFAULT_GIT_ENV, ...(envs ?? {}) }\n\n return this.commands.run(cmd, {\n ...rest,\n envs: mergedEnvs,\n })\n }\n\n private async getRemoteUrl(\n path: string,\n remote: string,\n opts?: GitRequestOpts\n ): Promise<string> {\n const result = await this.runGit(['remote', 'get-url', remote], path, opts)\n const url = result.stdout.trim()\n if (!url) {\n throw new InvalidArgumentError(\n `Remote \"${remote}\" URL not found in repository.`\n )\n }\n return url\n }\n\n private async resolveRemoteName(\n path: string,\n remote: string | undefined,\n opts?: GitRequestOpts\n ): Promise<string> {\n if (remote) {\n return remote\n }\n\n const result = await this.runGit(['remote'], path, opts)\n const remotes = result.stdout\n .split('\\n')\n .map((line) => line.trim())\n .filter(Boolean)\n\n if (remotes.length === 1) {\n return remotes[0]\n }\n\n throw new InvalidArgumentError(\n 'Remote is required when using username/password and the repository has multiple remotes.'\n )\n }\n\n private async withRemoteCredentials<T>(\n path: string,\n remote: string,\n username: string,\n password: string,\n opts: GitRequestOpts | undefined,\n operation: () => Promise<T>\n ): Promise<T> {\n const originalUrl = await this.getRemoteUrl(path, remote, opts)\n const credentialUrl = withCredentials(originalUrl, username, password)\n\n await this.runGit(['remote', 'set-url', remote, credentialUrl], path, opts)\n\n let result: T | undefined\n let operationError: unknown\n try {\n result = await operation()\n } catch (err) {\n operationError = err\n }\n\n let restoreError: unknown\n try {\n await this.runGit(['remote', 'set-url', remote, originalUrl], path, opts)\n } catch (err) {\n restoreError = err\n }\n\n if (operationError) {\n throw operationError\n }\n if (restoreError) {\n throw restoreError\n }\n\n return result as T\n }\n\n private async hasUpstream(\n path: string,\n opts?: GitRequestOpts\n ): Promise<boolean> {\n try {\n const result = await this.runGit(\n ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'],\n path,\n opts\n )\n return result.stdout.trim().length > 0\n } catch {\n return false\n }\n }\n}\n\nexport type {\n GitBranches,\n GitConfigScope,\n GitFileStatus,\n GitStatus,\n} from './utils'\n","import {\n ConnectionConfig,\n ConnectionOpts,\n raiseIfLegacy,\n} from '../connectionConfig'\nimport { InvalidArgumentError, SecretError } from '../errors'\n\nconst SECRET_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/\nconst ENV_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/\nconst HOST_PATTERN =\n /^(\\*\\.)?[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?(?:\\.[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/\n\nexport function validateSecretEnvs(\n secretEnvs?: Record<string, string>,\n envs?: Record<string, string>\n): Record<string, string> {\n if (!secretEnvs) {\n return {}\n }\n\n if (typeof secretEnvs !== 'object' || Array.isArray(secretEnvs)) {\n throw new InvalidArgumentError('secretEnvs must be a mapping')\n }\n\n const envNames = new Set(Object.keys(envs ?? {}))\n const validated: Record<string, string> = {}\n\n for (const [envName, secretName] of Object.entries(secretEnvs)) {\n if (!ENV_NAME_PATTERN.test(envName)) {\n throw new InvalidArgumentError(\n `secretEnvs key ${JSON.stringify(envName)} must be a valid sandbox environment variable name`\n )\n }\n if (envNames.has(envName)) {\n throw new InvalidArgumentError(\n `envs and secretEnvs both define ${JSON.stringify(envName)}`\n )\n }\n validateSecretName(secretName)\n validated[envName] = secretName\n }\n\n return validated\n}\n\nexport type SecretBinding = {\n name: string\n hosts: string[]\n placeholder: string\n description: string | null\n hasSecret: boolean\n status: string\n updatedAt?: string | null\n}\n\nexport type SecretWriteParams = {\n name: string\n value: string\n hosts: string[]\n description?: string | null\n}\n\ntype SecretBindingResponse = {\n name: string\n hosts?: string[]\n placeholder: string\n description?: string | null\n hasSecret: boolean\n status: string\n updatedAt?: string | null\n}\n\ntype SecretListResponse = {\n secrets?: SecretBindingResponse[]\n}\n\ntype SecretDeleteResponse = {\n deleted?: string\n}\n\nexport class Secret {\n private static readonly base = '/secrets'\n\n static async create(\n params: SecretWriteParams,\n opts?: ConnectionOpts\n ): Promise<SecretBinding> {\n validateSecretName(params.name)\n if (!params.value) {\n throw new InvalidArgumentError('value is required')\n }\n const body: Record<string, unknown> = {\n name: params.name,\n value: params.value,\n hosts: normalizeSecretHosts(params.hosts),\n }\n if (params.description !== undefined) {\n body.description = params.description\n }\n\n return bindingFromJson(\n await request<SecretBindingResponse>(\n 'POST',\n Secret.base,\n 'Secret.create',\n opts,\n body\n )\n )\n }\n\n static async list(opts?: ConnectionOpts): Promise<SecretBinding[]> {\n const data = await request<SecretListResponse>(\n 'GET',\n Secret.base,\n 'Secret.list',\n opts\n )\n return (data.secrets ?? []).map(bindingFromJson)\n }\n\n static async get(\n name: string,\n opts?: ConnectionOpts\n ): Promise<SecretBinding> {\n validateSecretName(name)\n return bindingFromJson(\n await request<SecretBindingResponse>(\n 'GET',\n `${Secret.base}/${encodeURIComponent(name)}`,\n 'Secret.get',\n opts\n )\n )\n }\n\n static async update(\n params: SecretWriteParams,\n opts?: ConnectionOpts\n ): Promise<SecretBinding> {\n validateSecretName(params.name)\n if (!params.value) {\n throw new InvalidArgumentError('value is required')\n }\n const body: Record<string, unknown> = {\n value: params.value,\n hosts: normalizeSecretHosts(params.hosts),\n }\n if (params.description !== undefined) {\n body.description = params.description\n }\n\n return bindingFromJson(\n await request<SecretBindingResponse>(\n 'PUT',\n `${Secret.base}/${encodeURIComponent(params.name)}`,\n 'Secret.update',\n opts,\n body\n )\n )\n }\n\n static async delete(name: string, opts?: ConnectionOpts): Promise<string> {\n validateSecretName(name)\n const data = await request<SecretDeleteResponse>(\n 'DELETE',\n `${Secret.base}/${encodeURIComponent(name)}`,\n 'Secret.delete',\n opts\n )\n return String(data.deleted ?? '')\n }\n}\n\nfunction validateSecretName(name: string) {\n if (typeof name !== 'string' || !SECRET_NAME_PATTERN.test(name)) {\n throw new InvalidArgumentError(\n `secret name ${JSON.stringify(name)} must be 1-128 characters and contain only letters, numbers, dots, underscores, and hyphens`\n )\n }\n}\n\nfunction normalizeSecretHosts(hosts: string[]): string[] {\n if (!hosts.length) {\n throw new InvalidArgumentError('hosts is required')\n }\n\n const seen = new Set<string>()\n const normalizedHosts: string[] = []\n for (const rawHost of hosts) {\n if (typeof rawHost !== 'string') {\n throw new InvalidArgumentError('host must be a string')\n }\n\n const host = rawHost.trim().toLowerCase()\n if (!host) {\n throw new InvalidArgumentError('host cannot be empty')\n }\n if (host.includes('://') || /[/?#@:]/.test(host)) {\n throw new InvalidArgumentError(\n `host ${JSON.stringify(host)} must be a hostname only`\n )\n }\n\n const wildcard = host.startsWith('*.')\n const lookupHost = wildcard ? host.slice(2) : host\n if (!lookupHost || lookupHost.includes('*')) {\n throw new InvalidArgumentError(`invalid host ${JSON.stringify(host)}`)\n }\n\n const normalized = wildcard ? `*.${lookupHost}` : lookupHost\n if (!HOST_PATTERN.test(normalized)) {\n throw new InvalidArgumentError(\n `host ${JSON.stringify(host)} must be a hostname or wildcard hostname`\n )\n }\n if (seen.has(normalized)) {\n continue\n }\n\n seen.add(normalized)\n normalizedHosts.push(normalized)\n }\n\n return normalizedHosts\n}\n\nasync function request<T>(\n method: string,\n path: string,\n feature: string,\n opts?: ConnectionOpts,\n body?: Record<string, unknown>\n): Promise<T> {\n const config = new ConnectionConfig(opts)\n raiseIfLegacy(config, feature, SecretError)\n\n const headers: Record<string, string> = {\n ...config.headers,\n ...(body ? { 'Content-Type': 'application/json' } : {}),\n ...(config.apiKey ? { 'X-API-KEY': config.apiKey } : {}),\n ...(config.accessToken\n ? { Authorization: `Bearer ${config.accessToken}` }\n : {}),\n }\n const response = await fetch(`${config.apiUrl}${path}`, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n signal: config.getSignal(),\n })\n\n const data = await parseJson(response)\n if (!response.ok) {\n const message =\n typeof data?.message === 'string' ? data.message : response.statusText\n throw new SecretError(`${response.status}: ${message}`)\n }\n\n return data as T\n}\n\nasync function parseJson(response: Response): Promise<any> {\n const text = await response.text()\n return text ? JSON.parse(text) : {}\n}\n\nfunction bindingFromJson(data: SecretBindingResponse): SecretBinding {\n return {\n name: data.name,\n hosts: data.hosts ?? [],\n placeholder: data.placeholder,\n description: data.description ?? null,\n hasSecret: data.hasSecret,\n status: data.status,\n updatedAt: data.updatedAt,\n }\n}\n","import { ApiClient, components, handleApiError } from '../api'\nimport {\n ConnectionConfig,\n ConnectionOpts,\n DEFAULT_SANDBOX_TIMEOUT_MS,\n isLegacyDomain,\n raiseIfLegacy,\n} from '../connectionConfig'\nimport { compareVersions } from 'compare-versions'\nimport { AuthenticationError, RateLimitError, SandboxError, SandboxNotFoundError, TemplateError } from '../errors'\nimport { timeoutToSeconds } from '../utils'\nimport type { BuildInfo } from '../template/types'\nimport type { Volume } from '../volume'\nimport type { McpServer as BaseMcpServer } from './mcp'\nimport { defaultHeaders } from '../api/metadata'\nimport { validateSecretEnvs } from '../secret'\n\n/**\n * Extended MCP server configuration that includes base servers\n * and allows dynamic GitHub-based MCP servers with custom run and install commands.\n */\nexport type McpServer = BaseMcpServer | GitHubMcpServer\n\nexport type GitHubMcpServer = {\n [key: `github/${string}`]: {\n /**\n * Command to run the MCP server. Must start a stdio-compatible server.\n */\n runCmd: string\n /**\n * Command to install dependencies for the MCP server. Working directory is the root of the github repository.\n */\n installCmd?: string\n /**\n * Environment variables to set in the MCP process.\n */\n envs?: Record<string, string>\n }\n}\n\nasync function createRawApiError(response: Response): Promise<Error> {\n let message = response.statusText\n\n try {\n const body = await response.json()\n message = body?.message ?? JSON.stringify(body)\n } catch {\n try {\n message = await response.text()\n } catch {\n // Use statusText.\n }\n }\n\n if (response.status === 401) {\n return new AuthenticationError(\n `Unauthorized, please check your credentials. - ${message}`\n )\n }\n\n if (response.status === 429) {\n return new RateLimitError(\n `Rate limit exceeded, please try again later - ${message}`\n )\n }\n\n return new SandboxError(`${response.status}: ${message}`)\n}\n\nfunction getRawApiHeaders(\n config: ConnectionConfig,\n headers?: Record<string, string>\n): Record<string, string> {\n return {\n ...defaultHeaders,\n ...(config.apiKey ? { 'X-API-KEY': config.apiKey } : {}),\n ...(config.accessToken ? { Authorization: `Bearer ${config.accessToken}` } : {}),\n ...config.headers,\n ...(headers ?? {}),\n }\n}\n\nexport type SandboxNetworkOpts = {\n /**\n * Allow outbound traffic from the sandbox to the specified addresses.\n * If `allowOut` is not specified, all outbound traffic is allowed.\n *\n * Examples:\n * - To allow traffic to a specific addresses: `[\"1.1.1.1\", \"8.8.8.0/24\"]`\n */\n allowOut?: string[]\n\n /**\n * Deny outbound traffic from the sandbox to the specified addresses.\n *\n * Examples:\n * - To deny traffic to a specific addresses: `[\"1.1.1.1\", \"8.8.8.0/24\"]`\n */\n denyOut?: string[]\n\n /**\n * Specify if the sandbox URLs should be accessible only with authentication.\n * @default true\n */\n allowPublicTraffic?: boolean\n\n /** Specify host mask which will be used for all sandbox requests in the header.\n * You can use the ${PORT} variable that will be replaced with the actual port number of the service.\n *\n * @default ${PORT}-sandboxid.sandbox.ppio.cn\n */\n maskRequestHost?: string\n}\n\nexport type SandboxNetworkUpdateOpts = SandboxApiOpts &\n Pick<SandboxNetworkOpts, 'allowOut' | 'denyOut'>\n\nexport type SandboxLifecycle = {\n /**\n * Action to take when sandbox timeout is reached.\n * @default \"kill\"\n */\n onTimeout: 'pause' | 'kill'\n\n /**\n * Auto-resume enabled flag.\n * @default false\n * Can be `true` only when `onTimeout` is `pause`.\n */\n autoResume?: boolean\n}\n\nexport type SandboxInfoLifecycle = {\n /**\n * Action to take when sandbox timeout is reached.\n */\n onTimeout: 'pause' | 'kill'\n\n /**\n * Whether the sandbox can auto-resume.\n */\n autoResume: boolean\n}\n\n/**\n * Options for request to the Sandbox API.\n */\nexport interface SandboxApiOpts\n extends Partial<\n Pick<\n ConnectionOpts,\n 'apiKey' | 'headers' | 'debug' | 'domain' | 'requestTimeoutMs' | 'sync'\n >\n > {}\n\n/**\n * Options for creating a new Sandbox.\n */\nexport interface SandboxOpts extends ConnectionOpts {\n /**\n * Sandbox template name or ID.\n *\n * @default 'base' (or 'mcp-gateway' when `mcp` option is set)\n */\n template?: string\n\n /**\n * Custom metadata for the sandbox.\n *\n * @default {}\n */\n metadata?: Record<string, string>\n\n /**\n * Custom environment variables for the sandbox.\n *\n * Used when executing commands and code in the sandbox.\n * Can be overridden with the `envs` argument when executing commands or code.\n *\n * @default {}\n */\n envs?: Record<string, string>\n\n /**\n * Timeout for the sandbox in **milliseconds**.\n * Maximum time a sandbox can be kept alive is 24 hours (86_400_000 milliseconds) for Pro users and 1 hour (3_600_000 milliseconds) for Hobby users.\n *\n * @default 300_000 // 5 minutes\n */\n timeoutMs?: number\n\n /**\n * Secure all traffic coming to the sandbox controller with auth token\n *\n * @default true\n */\n secure?: boolean\n\n /**\n * Allow sandbox to access the internet. If set to `False`, it works the same as setting network `denyOut` to `[0.0.0.0/0]`.\n *\n * @default true\n */\n allowInternetAccess?: boolean\n\n /**\n * MCP server to enable in the sandbox\n * @default undefined\n */\n mcp?: McpServer\n\n /**\n * Sandbox network configuration\n */\n network?: SandboxNetworkOpts\n\n /**\n * Volume mounts for the sandbox.\n *\n * The keys are mount paths inside the sandbox and the values are either\n * a `Volume` instance or a string representing the volume name.\n *\n * @default undefined\n */\n volumeMounts?: Record<string, Volume | string>\n\n /**\n * Sandbox URL. Used for local development\n */\n sandboxUrl?: string\n\n /**\n * Sandbox lifecycle configuration.\n */\n lifecycle?: SandboxLifecycle\n\n /**\n * Map of sandbox environment variable names to stored secret names.\n *\n * Each key is the environment variable name created inside the sandbox\n * (e.g. `OPENAI_API_KEY`). Each value is the name of a secret previously\n * created via the secrets API (e.g. `openai-prod`). The sandbox receives\n * a placeholder in the environment variable, not the real secret value.\n *\n * Keys must not duplicate `envs` keys.\n */\n secretEnvs?: Record<string, string>\n\n /**\n * Optional node ID to schedule the sandbox on.\n */\n nodeId?: string\n}\n\nexport type SandboxBetaCreateOpts = SandboxOpts & {\n /**\n * @deprecated Use `lifecycle.onTimeout = \"pause\"` instead.\n *\n * Automatically pause the sandbox after the timeout expires.\n * @default false\n */\n autoPause?: boolean\n}\n\n/**\n * Options for connecting to a Sandbox.\n */\nexport type SandboxConnectOpts = ConnectionOpts & {\n /**\n * Timeout for the sandbox in **milliseconds**.\n * For running sandboxes, the timeout will update only if the new timeout is longer than the existing one.\n * Maximum time a sandbox can be kept alive is 24 hours (86_400_000 milliseconds) for Pro users and 1 hour (3_600_000 milliseconds) for Hobby users.\n *\n * @default 300_000 // 5 minutes\n */\n timeoutMs?: number\n\n /**\n * Secure all traffic coming to the sandbox controller with auth token.\n */\n secure?: boolean\n allowPublicTraffic?: boolean\n\n /**\n * Sandbox network configuration.\n */\n network?: SandboxNetworkOpts\n}\n\n/**\n * State of the sandbox.\n */\nexport type SandboxState = 'running' | 'paused'\n\nexport interface SandboxListOpts extends SandboxApiOpts {\n /**\n * Filter the list of sandboxes, e.g. by metadata `metadata:{\"key\": \"value\"}`, if there are multiple filters they are combined with AND.\n *\n */\n query?: {\n metadata?: Record<string, string>\n /**\n * Filter the list of sandboxes by state.\n * @default ['running', 'paused']\n */\n state?: Array<SandboxState>\n }\n\n /**\n * Number of sandboxes to return per page.\n *\n * @default 100\n */\n limit?: number\n\n /**\n * Token to the next page.\n */\n nextToken?: string\n}\n\nexport interface SandboxMetricsOpts extends SandboxApiOpts {\n /**\n * Start time for the metrics, defaults to the start of the sandbox\n */\n start?: Date\n /**\n * End time for the metrics, defaults to the current time\n */\n end?: Date\n}\n\nexport interface SandboxCloneOpts extends SandboxApiOpts {\n /**\n * Number of sandboxes to clone.\n *\n * @default 1\n */\n count?: number\n\n /**\n * Optional node ID to schedule cloned sandboxes on.\n */\n nodeId?: string\n\n /**\n * If true, require the exact requested count or fail.\n *\n * @default false\n */\n strict?: boolean\n\n /**\n * Timeout for cloned sandboxes in milliseconds.\n */\n timeoutMs?: number\n}\n\nexport interface SandboxCloneResultInfo {\n sandboxId: string\n envdVersion: string\n envdAccessToken?: string\n trafficAccessToken?: string\n}\n\nexport interface SandboxCloneResult<SandboxInstance> {\n sandboxes: SandboxInstance[]\n count: number\n snapshotTemplateId?: string\n}\n\nexport interface SandboxResetOpts extends SandboxApiOpts {\n /**\n * Whether to resume the sandbox after reset.\n *\n * @default true\n */\n resume?: boolean\n\n /**\n * Timeout for the resumed sandbox in milliseconds.\n */\n timeoutMs?: number\n\n /**\n * Secure all traffic coming to the sandbox controller with auth token.\n */\n secure?: boolean\n allowPublicTraffic?: boolean\n\n /**\n * Sandbox network configuration.\n */\n network?: SandboxNetworkOpts\n}\n\nexport interface SandboxCommitOpts extends SandboxApiOpts {\n /**\n * Optional alias for the created snapshot template.\n */\n alias?: string\n}\n\nexport type SandboxCommitResult = BuildInfo & {\n aliases: string[]\n names: string[]\n templateType: 'snapshot_template'\n}\n\n/**\n * Options for listing snapshots.\n */\nexport interface SnapshotListOpts extends SandboxApiOpts {\n /**\n * Filter snapshots by source sandbox ID.\n */\n sandboxId?: string\n\n /**\n * Number of snapshots to return per page.\n *\n * @default 100\n */\n limit?: number\n\n /**\n * Token to the next page.\n */\n nextToken?: string\n}\n\n/**\n * Information about a snapshot.\n */\nexport interface SnapshotInfo {\n /**\n * Snapshot identifier — template ID with tag, or namespaced name with tag (e.g. my-snapshot:latest).\n * Can be used with Sandbox.create() to create a new sandbox from this snapshot.\n */\n snapshotId: string\n}\n\n/**\n * Information about a sandbox.\n */\nexport interface SandboxInfo {\n /**\n * Sandbox ID.\n */\n sandboxId: string\n\n /**\n * Template ID.\n */\n templateId: string\n\n /**\n * Template name.\n */\n name?: string\n\n /**\n * Saved sandbox metadata.\n */\n metadata: Record<string, string>\n\n /**\n * Sandbox start time.\n */\n startedAt: Date\n\n /**\n * Sandbox expiration date.\n */\n endAt: Date\n\n /**\n * Sandbox state.\n *\n * @string can be `running` or `paused`\n */\n state: SandboxState\n\n /**\n * Sandbox CPU count.\n */\n cpuCount: number\n\n /**\n * Sandbox Memory size in MiB.\n */\n memoryMB: number\n\n /**\n * Envd version.\n */\n envdVersion?: string\n\n /**\n * Whether internet access was explicitly enabled or disabled for the sandbox.\n */\n allowInternetAccess?: boolean | undefined\n\n /**\n * Sandbox network configuration.\n */\n network?: SandboxNetworkOpts\n\n /**\n * Sandbox lifecycle configuration.\n */\n lifecycle?: SandboxInfoLifecycle\n\n /**\n * Volume mounts for the sandbox.\n */\n volumeMounts?: Array<{ name: string; path: string }>\n}\n\n/**\n * Sandbox resource usage metrics.\n */\nexport interface SandboxMetrics {\n /**\n * Timestamp of the metrics.\n */\n timestamp: Date\n\n /**\n * CPU usage in percentage.\n */\n cpuUsedPct: number\n\n /**\n * Number of CPU cores.\n */\n cpuCount: number\n\n /**\n * Memory usage in bytes.\n */\n memUsed: number\n\n /**\n * Total memory available in bytes.\n */\n memTotal: number\n\n /**\n * Used disk space in bytes.\n */\n diskUsed: number\n\n /**\n * Total disk space available in bytes.\n */\n diskTotal: number\n}\n\nfunction getLifecycle(\n opts?: Pick<SandboxBetaCreateOpts, 'lifecycle' | 'autoPause'>\n): SandboxLifecycle {\n if (opts?.lifecycle) {\n return opts.lifecycle\n }\n\n if (opts?.autoPause) {\n return {\n onTimeout: 'pause',\n autoResume: false,\n }\n }\n\n return {\n onTimeout: 'kill',\n autoResume: false,\n }\n}\n\nexport class SandboxApi {\n protected constructor() {}\n\n /**\n * Kill the sandbox specified by sandbox ID.\n *\n * @param sandboxId sandbox ID.\n * @param opts connection options.\n *\n * @returns `true` if the sandbox was found and killed, `false` otherwise.\n */\n static async kill(\n sandboxId: string,\n opts?: SandboxApiOpts\n ): Promise<boolean> {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.DELETE('/sandboxes/{sandboxID}', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n return false\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n return true\n }\n\n /**\n * Get sandbox information like sandbox ID, template, metadata, started at/end at date.\n *\n * @param sandboxId sandbox ID.\n * @param opts connection options.\n *\n * @returns sandbox information.\n */\n static async getInfo(\n sandboxId: string,\n opts?: SandboxApiOpts\n ): Promise<SandboxInfo> {\n const fullInfo = await this.getFullInfo(sandboxId, opts)\n delete fullInfo.envdAccessToken\n delete fullInfo.sandboxDomain\n\n return fullInfo\n }\n\n /**\n * Get the metrics of the sandbox.\n *\n * @param sandboxId sandbox ID.\n * @param opts sandbox metrics options.\n *\n * @returns List of sandbox metrics containing CPU, memory and disk usage information.\n */\n static async getMetrics(\n sandboxId: string,\n opts?: SandboxMetricsOpts\n ): Promise<SandboxMetrics[]> {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n if (config.isLegacyDomain) {\n const res = await client.api.GET('/sandboxes/{sandboxID}/metrics', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n return (\n ((res.data ?? []) as Array<Record<string, any>>).map(metric => ({\n timestamp: new Date(metric.timestamp),\n cpuUsedPct: metric.cpuUsedPct,\n cpuCount: metric.cpuCount,\n memUsed: metric.memUsedMiB * 1024 * 1024,\n memTotal: metric.memTotalMiB * 1024 * 1024,\n diskUsed: -1,\n diskTotal: -1,\n })) ?? []\n )\n }\n\n // JS timestamp is in milliseconds, convert to unix (seconds)\n const start = opts?.start\n ? Math.round(opts.start.getTime() / 1000)\n : undefined\n const end = opts?.end ? Math.round(opts.end.getTime() / 1000) : undefined\n const res = await client.api.GET('/sandboxes/{sandboxID}/metrics', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n query: {\n start,\n end,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n return (\n res.data?.map((metric: components['schemas']['SandboxMetric']) => ({\n timestamp: new Date(metric.timestamp),\n cpuUsedPct: metric.cpuUsedPct,\n cpuCount: metric.cpuCount,\n memUsed: metric.memUsed,\n memTotal: metric.memTotal,\n diskUsed: metric.diskUsed,\n diskTotal: metric.diskTotal,\n })) ?? []\n )\n }\n\n /**\n * Set the timeout of the specified sandbox.\n * After the timeout expires the sandbox will be automatically killed.\n *\n * This method can extend or reduce the sandbox timeout set when creating the sandbox or from the last call to {@link Sandbox.setTimeout}.\n *\n * Maximum time a sandbox can be kept alive is 24 hours (86_400_000 milliseconds) for Pro users and 1 hour (3_600_000 milliseconds) for Hobby users.\n *\n * @param sandboxId sandbox ID.\n * @param timeoutMs timeout in **milliseconds**.\n * @param opts connection options.\n */\n static async setTimeout(\n sandboxId: string,\n timeoutMs: number,\n opts?: SandboxApiOpts\n ): Promise<void> {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.POST('/sandboxes/{sandboxID}/timeout', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n body: {\n timeout: timeoutToSeconds(timeoutMs),\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n }\n\n /**\n * @deprecated Only legacy domains support this method. Use {@link SandboxApi.createSnapshot} for modern domains.\n */\n static async commit(\n sandboxId: string,\n opts?: SandboxCommitOpts\n ): Promise<SandboxCommitResult> {\n const config = new ConnectionConfig(opts)\n if (!config.isLegacyDomain) {\n throw new SandboxError('Sandbox.commit is only supported for legacy domains')\n }\n\n const response = await fetch(\n `${config.apiUrl}/sandboxes/${encodeURIComponent(sandboxId)}/commit`,\n {\n method: 'POST',\n headers: getRawApiHeaders(config, {\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify(opts?.alias ? { alias: opts.alias } : {}),\n signal: config.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n if (response.status === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n const data = (await response.json()) as {\n templateID: string\n buildID: string\n aliases?: string[]\n names?: string[]\n }\n\n return {\n alias: data.aliases?.[0] ?? data.names?.[0] ?? '',\n name: data.names?.[0] ?? data.aliases?.[0] ?? '',\n tags: [],\n templateId: data.templateID,\n buildId: data.buildID,\n aliases: data.aliases ?? [],\n names: data.names ?? [],\n templateType: 'snapshot_template',\n }\n }\n\n static async hotplugMemory(\n sandboxId: string,\n requestedSizeMib: number,\n opts?: SandboxApiOpts\n ): Promise<void> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Sandbox.hotplugMemory', SandboxError)\n const response = await fetch(\n `${config.apiUrl}/sandboxes/${encodeURIComponent(sandboxId)}/hotplug-memory`,\n {\n method: 'POST',\n headers: getRawApiHeaders(config, {\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify({\n requested_size_mib: requestedSizeMib,\n }),\n signal: config.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n if (response.status === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n }\n\n static async reset(\n sandboxId: string,\n opts?: SandboxResetOpts\n ): Promise<boolean> {\n const config = new ConnectionConfig(opts)\n const body: Record<string, unknown> = {\n resume: opts?.resume ?? true,\n ...(opts?.timeoutMs !== undefined\n ? { timeout: timeoutToSeconds(opts.timeoutMs) }\n : {}),\n }\n if (opts?.secure !== undefined) {\n body.secure = opts.secure\n }\n if (opts?.allowPublicTraffic !== undefined) {\n body.allowPublicTraffic = opts.allowPublicTraffic\n }\n if (opts?.network) {\n body.network = opts.network\n }\n\n const response = await fetch(\n `${config.apiUrl}/sandboxes/${encodeURIComponent(sandboxId)}/reset`,\n {\n method: 'POST',\n headers: getRawApiHeaders(config, {\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify(body),\n signal: config.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n if (response.status === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (response.status === 409) {\n return false\n }\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n return true\n }\n\n static async mountVolume(\n sandboxId: string,\n name: string,\n path: string,\n opts?: SandboxApiOpts\n ): Promise<SandboxInfo> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Sandbox.mountVolume', SandboxError)\n const response = await fetch(\n `${config.apiUrl}/sandboxes/${encodeURIComponent(sandboxId)}/volume-mounts`,\n {\n method: 'POST',\n headers: getRawApiHeaders(config, {\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify({ name, path }),\n signal: config.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n if (response.status === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n const data = await response.json()\n return {\n sandboxId: data.sandboxID,\n templateId: data.templateID,\n name: data.name,\n metadata: data.metadata ?? {},\n startedAt: new Date(data.startedAt),\n endAt: new Date(data.endAt),\n state: data.state,\n cpuCount: data.cpuCount,\n memoryMB: data.memoryMB,\n envdVersion: data.envdVersion,\n volumeMounts: data.volumeMounts ?? [],\n }\n }\n\n static async unmountVolume(\n sandboxId: string,\n path: string,\n opts?: SandboxApiOpts & { force?: boolean }\n ): Promise<SandboxInfo> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Sandbox.unmountVolume', SandboxError)\n const url = new URL(\n `${config.apiUrl}/sandboxes/${encodeURIComponent(sandboxId)}/volume-mounts`\n )\n url.searchParams.set('path', path)\n if (opts?.force) {\n url.searchParams.set('force', 'true')\n }\n\n const response = await fetch(url, {\n method: 'DELETE',\n headers: getRawApiHeaders(config),\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (response.status === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n const data = await response.json()\n return {\n sandboxId: data.sandboxID,\n templateId: data.templateID,\n name: data.name,\n metadata: data.metadata ?? {},\n startedAt: new Date(data.startedAt),\n endAt: new Date(data.endAt),\n state: data.state,\n cpuCount: data.cpuCount,\n memoryMB: data.memoryMB,\n envdVersion: data.envdVersion,\n volumeMounts: data.volumeMounts ?? [],\n }\n }\n\n static async setNetwork(\n sandboxId: string,\n opts?: SandboxNetworkUpdateOpts\n ): Promise<void> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Sandbox.setNetwork', SandboxError)\n const response = await fetch(\n `${config.apiUrl}/sandboxes/${encodeURIComponent(sandboxId)}/network`,\n {\n method: 'PUT',\n headers: getRawApiHeaders(config, {\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify({\n ...(opts?.allowOut ? { allowOut: opts.allowOut } : {}),\n ...(opts?.denyOut ? { denyOut: opts.denyOut } : {}),\n }),\n signal: config.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n if (response.status === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n }\n\n protected static async cloneSandboxes(\n sandboxId: string,\n opts?: SandboxCloneOpts\n ): Promise<{\n sandboxes: SandboxCloneResultInfo[]\n snapshotTemplateId?: string\n }> {\n const config = new ConnectionConfig(opts)\n const response = await fetch(\n `${config.apiUrl}/sandboxes/${encodeURIComponent(sandboxId)}/clone`,\n {\n method: 'POST',\n headers: getRawApiHeaders(config, {\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify({\n count: opts?.count ?? 1,\n strict: opts?.strict ?? false,\n ...(opts?.nodeId ? { nodeID: opts.nodeId } : {}),\n ...(opts?.timeoutMs !== undefined\n ? { timeout: timeoutToSeconds(opts.timeoutMs) }\n : {}),\n }),\n signal: config.getSignal(opts?.requestTimeoutMs ?? 300_000),\n }\n )\n\n if (response.status === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n const data = (await response.json()) as {\n sandboxes?: Array<{\n sandboxID?: string\n clientID?: string\n envdVersion?: string\n envdAccessToken?: string\n trafficAccessToken?: string\n }>\n snapshotTemplateId?: string\n }\n\n return {\n sandboxes: (data.sandboxes ?? []).map(sandbox => {\n const baseSandboxId = sandbox.sandboxID ?? ''\n const sandboxId = sandbox.clientID\n ? `${baseSandboxId}-${sandbox.clientID}`\n : baseSandboxId\n\n return {\n sandboxId,\n envdVersion: sandbox.envdVersion ?? '0.0.0',\n envdAccessToken: sandbox.envdAccessToken,\n trafficAccessToken: sandbox.trafficAccessToken,\n }\n }),\n snapshotTemplateId: data.snapshotTemplateId,\n }\n }\n\n static async getFullInfo(sandboxId: string, opts?: SandboxApiOpts) {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.GET('/sandboxes/{sandboxID}', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n if (!res.data) {\n throw new Error('Sandbox not found')\n }\n\n if (config.isLegacyDomain) {\n const data = res.data as Record<string, any>\n return {\n sandboxId:\n data.clientID != null\n ? `${data.sandboxID}-${data.clientID}`\n : data.sandboxID,\n templateId: data.templateID,\n ...(data.alias && { name: data.alias }),\n metadata: data.metadata ?? {},\n envdVersion: data.envdVersion ?? '0.0.0',\n envdAccessToken: data.envdAccessToken,\n startedAt: new Date(data.startedAt),\n endAt: new Date(data.endAt),\n state: data.state,\n cpuCount: data.cpuCount,\n memoryMB: data.memoryMB,\n sandboxDomain: data.domain || undefined,\n }\n }\n\n return {\n sandboxId: res.data.sandboxID,\n templateId: res.data.templateID,\n ...(res.data.alias && { name: res.data.alias }),\n metadata: res.data.metadata ?? {},\n allowInternetAccess: res.data.allowInternetAccess ?? undefined,\n envdVersion: res.data.envdVersion,\n envdAccessToken: res.data.envdAccessToken,\n startedAt: new Date(res.data.startedAt),\n endAt: new Date(res.data.endAt),\n state: res.data.state,\n cpuCount: res.data.cpuCount,\n memoryMB: res.data.memoryMB,\n network: res.data.network\n ? {\n allowOut: res.data.network.allowOut,\n denyOut: res.data.network.denyOut,\n allowPublicTraffic: res.data.network.allowPublicTraffic,\n maskRequestHost: res.data.network.maskRequestHost,\n }\n : undefined,\n lifecycle: res.data.lifecycle\n ? {\n onTimeout: res.data.lifecycle.onTimeout,\n autoResume: res.data.lifecycle.autoResume,\n }\n : undefined,\n sandboxDomain: res.data.domain || undefined,\n volumeMounts: res.data.volumeMounts ?? [],\n }\n }\n\n /**\n * Pause the sandbox specified by sandbox ID.\n *\n * @param sandboxId sandbox ID.\n * @param opts connection options.\n *\n * @returns `true` if the sandbox got paused, `false` if the sandbox was already paused.\n */\n static async pause(\n sandboxId: string,\n opts?: SandboxApiOpts\n ): Promise<boolean> {\n const config = new ConnectionConfig(opts)\n\n if (config.isLegacyDomain) {\n const response = await fetch(\n `${config.apiUrl}/sandboxes/${encodeURIComponent(sandboxId)}/pause`,\n {\n method: 'POST',\n headers: getRawApiHeaders(config, {\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify({ sync: opts?.sync ?? false }),\n signal: config.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n if (response.status === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (response.status === 409) {\n return false\n }\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n return true\n }\n\n const client = new ApiClient(config)\n\n const res = await client.api.POST('/sandboxes/{sandboxID}/pause', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (res.error?.code === 409) {\n // Sandbox is already paused\n return false\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n return true\n }\n\n /**\n * @deprecated Use {@link SandboxApi.pause} instead.\n */\n static async betaPause(\n sandboxId: string,\n opts?: SandboxApiOpts\n ): Promise<boolean> {\n return this.pause(sandboxId, opts)\n }\n\n /**\n * Create a snapshot from a sandbox.\n *\n * The sandbox will be paused while the snapshot is being created.\n * The snapshot can be used to create new sandboxes with the same state.\n * The snapshot is a persistent image that survives sandbox deletion.\n *\n * @param sandboxId sandbox ID to create snapshot from.\n * @param opts connection options.\n *\n * @returns snapshot information including the snapshot name that can be used with Sandbox.create().\n */\n static async createSnapshot(\n sandboxId: string,\n opts?: SandboxApiOpts\n ): Promise<SnapshotInfo> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Sandbox.createSnapshot', SandboxError)\n const client = new ApiClient(config)\n\n const res = await client.api.POST('/sandboxes/{sandboxID}/snapshots', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n body: {},\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n return {\n snapshotId: res.data!.snapshotID,\n }\n }\n\n /**\n * List all snapshots.\n *\n * @param opts list options including filters and pagination.\n *\n * @returns paginator for listing snapshots.\n */\n static listSnapshots(opts?: SnapshotListOpts): SnapshotPaginator {\n return new SnapshotPaginator(opts)\n }\n\n /**\n * Delete a snapshot.\n *\n * @param snapshotId snapshot ID.\n * @param opts connection options.\n *\n * @returns `true` if the snapshot was deleted, `false` if it was not found.\n */\n static async deleteSnapshot(\n snapshotId: string,\n opts?: SandboxApiOpts\n ): Promise<boolean> {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.DELETE('/templates/{templateID}', {\n params: {\n path: {\n templateID: snapshotId,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n return false\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n return true\n }\n\n protected static async createSandbox(\n template: string,\n timeoutMs: number,\n opts?: SandboxBetaCreateOpts\n ) {\n const config = new ConnectionConfig(opts)\n const lifecycle = getLifecycle(opts)\n const autoPause = lifecycle.onTimeout === 'pause'\n const autoResumeEnabled =\n lifecycle.onTimeout === 'pause'\n ? (lifecycle.autoResume ?? false)\n : undefined\n\n if (config.isLegacyDomain) {\n if (opts?.mcp) {\n raiseIfLegacy(config, 'Sandbox.create mcp', SandboxError)\n }\n if (opts?.network) {\n raiseIfLegacy(config, 'Sandbox.create network', SandboxError)\n }\n if (opts?.volumeMounts) {\n raiseIfLegacy(config, 'Sandbox.create volumeMounts', SandboxError)\n }\n if (opts?.secretEnvs) {\n raiseIfLegacy(config, 'Sandbox.create secretEnvs', SandboxError)\n }\n const body: Record<string, unknown> = {\n templateID: template,\n timeout: timeoutToSeconds(timeoutMs),\n metadata: opts?.metadata ?? {},\n envVars: opts?.envs ?? {},\n secure: opts?.secure ?? false,\n autoPause: autoPause ?? false,\n ...(opts?.nodeId ? { nodeID: opts.nodeId } : {}),\n }\n\n const response = await fetch(`${config.apiUrl}/sandboxes`, {\n method: 'POST',\n headers: getRawApiHeaders(config, {\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify(body),\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n const data = await response.json()\n if (compareVersions(data.envdVersion, '0.1.0') < 0) {\n await this.kill(data.sandboxID, opts)\n throw new TemplateError(\n 'You need to update the template to use the new SDK. ' +\n 'You can do this by running `ppio-sandbox template build` in the directory with the template.'\n )\n }\n\n return {\n sandboxId: data.clientID\n ? `${data.sandboxID}-${data.clientID}`\n : data.sandboxID,\n sandboxDomain: data.domain || undefined,\n envdVersion: data.envdVersion,\n envdAccessToken: data.envdAccessToken,\n trafficAccessToken: undefined,\n }\n }\n\n const client = new ApiClient(config)\n\n const body: components['schemas']['NewSandbox'] = {\n templateID: template,\n metadata: opts?.metadata,\n mcp: opts?.mcp as Record<string, unknown> | undefined,\n envVars: opts?.envs,\n timeout: timeoutToSeconds(timeoutMs),\n secure: opts?.secure ?? true,\n allow_internet_access: opts?.allowInternetAccess ?? true,\n network: opts?.network,\n ...(opts?.nodeId ? { nodeID: opts.nodeId } : {}),\n ...(autoPause !== undefined ? { autoPause } : {}),\n ...(autoResumeEnabled !== undefined\n ? { autoResume: { enabled: autoResumeEnabled } }\n : {}),\n }\n\n if (opts?.volumeMounts) {\n body.volumeMounts = Object.entries(opts.volumeMounts).map(\n ([mountPath, vol]) => ({\n name: typeof vol === 'string' ? vol : vol.name,\n path: mountPath,\n })\n )\n }\n\n const validatedSecretEnvs = validateSecretEnvs(\n opts?.secretEnvs,\n opts?.envs\n )\n if (Object.keys(validatedSecretEnvs).length > 0) {\n ;(body as Record<string, unknown>).secrets = validatedSecretEnvs\n }\n\n const res = await client.api.POST('/sandboxes', {\n body,\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n if (compareVersions(res.data!.envdVersion, '0.1.0') < 0) {\n await this.kill(res.data!.sandboxID, opts)\n throw new TemplateError(\n 'You need to update the template to use the new SDK. ' +\n 'You can do this by running `ppio template build` in the directory with the template.'\n )\n }\n\n return {\n sandboxId: res.data!.sandboxID,\n sandboxDomain: res.data!.domain || undefined,\n envdVersion: res.data!.envdVersion,\n envdAccessToken: res.data!.envdAccessToken,\n trafficAccessToken: res.data!.trafficAccessToken || undefined,\n }\n }\n\n protected static async connectSandbox(\n sandboxId: string,\n opts?: SandboxConnectOpts\n ) {\n const timeoutMs = opts?.timeoutMs ?? DEFAULT_SANDBOX_TIMEOUT_MS\n\n const config = new ConnectionConfig(opts)\n\n if (config.isLegacyDomain) {\n const response = await fetch(\n `${config.apiUrl}/sandboxes/${encodeURIComponent(sandboxId)}/connect`,\n {\n method: 'POST',\n headers: getRawApiHeaders(config, {\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify({ timeout: timeoutToSeconds(timeoutMs) }),\n signal: config.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n if (response.status === 404) {\n throw new SandboxNotFoundError(`Paused sandbox ${sandboxId} not found`)\n }\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n const data = await response.json()\n return {\n sandboxId: data.clientID\n ? `${data.sandboxID}-${data.clientID}`\n : data.sandboxID,\n sandboxDomain: data.domain || undefined,\n envdVersion: data.envdVersion || '0.0.0',\n envdAccessToken: data.envdAccessToken,\n trafficAccessToken: undefined,\n }\n }\n\n const client = new ApiClient(config)\n\n const res = await client.api.POST('/sandboxes/{sandboxID}/connect', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n body: {\n timeout: timeoutToSeconds(timeoutMs),\n ...(opts?.secure !== undefined ? { secure: opts.secure } : {}),\n ...(opts?.allowPublicTraffic !== undefined\n ? { allowPublicTraffic: opts.allowPublicTraffic }\n : {}),\n ...(opts?.network ? { network: opts.network } : {}),\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n throw new SandboxNotFoundError(`Paused sandbox ${sandboxId} not found`)\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n return {\n sandboxId: res.data!.sandboxID,\n sandboxDomain: res.data!.domain || undefined,\n envdVersion: res.data!.envdVersion,\n envdAccessToken: res.data!.envdAccessToken,\n trafficAccessToken: res.data!.trafficAccessToken || undefined,\n }\n }\n\n static async getQuota(\n opts?: SandboxQuotaOpts\n ): Promise<SandboxQuota> {\n const config = new ConnectionConfig(opts)\n raiseIfLegacy(config, 'Sandbox.getQuota', SandboxError)\n const url = new URL(`${config.apiUrl}/sandboxes/quota`)\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n ...config.headers,\n ...(config.apiKey ? { 'X-API-KEY': config.apiKey } : {}),\n ...(config.accessToken\n ? { Authorization: `Bearer ${config.accessToken}` }\n : {}),\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n const data = (await response.json()) as {\n limit?: Record<string, number>\n usage?: Record<string, number>\n }\n\n return {\n limit: {\n concurrentInstances: data.limit?.concurrentInstances ?? 0,\n concurrentVcpu: data.limit?.concurrentVcpu ?? 0,\n concurrentRamMb: data.limit?.concurrentRamMb ?? 0,\n maxLengthHours: data.limit?.maxLengthHours ?? 0,\n diskMb: data.limit?.diskMb ?? 0,\n maxVcpu: data.limit?.maxVcpu ?? 0,\n maxRamMb: data.limit?.maxRamMb ?? 0,\n },\n usage: {\n concurrentInstances: data.usage?.concurrentInstances ?? 0,\n concurrentVcpu: data.usage?.concurrentVcpu ?? 0,\n concurrentRamMb: data.usage?.concurrentRamMb ?? 0,\n },\n }\n }\n\n static async getEvents(\n opts?: SandboxEventsOpts\n ): Promise<SandboxEventsResult> {\n const config = new ConnectionConfig(opts)\n const url = new URL(`${config.apiUrl}/sandboxes/events`)\n if (opts?.startTime !== undefined)\n url.searchParams.set('startTime', String(opts.startTime))\n if (opts?.endTime !== undefined)\n url.searchParams.set('endTime', String(opts.endTime))\n if (opts?.sandboxID) url.searchParams.set('sandboxID', opts.sandboxID)\n if (opts?.templateID) url.searchParams.set('templateID', opts.templateID)\n if (opts?.events) url.searchParams.set('events', opts.events)\n if (opts?.state) url.searchParams.set('state', opts.state)\n if (opts?.orderAsc !== undefined)\n url.searchParams.set('orderAsc', String(opts.orderAsc))\n if (opts?.offset !== undefined)\n url.searchParams.set('offset', String(opts.offset))\n if (opts?.limit !== undefined)\n url.searchParams.set('limit', String(opts.limit))\n\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n ...config.headers,\n ...(config.apiKey ? { 'X-API-KEY': config.apiKey } : {}),\n ...(config.accessToken\n ? { Authorization: `Bearer ${config.accessToken}` }\n : {}),\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n const data = (await response.json()) as {\n items?: Array<{\n eventID: string\n recordAt: number\n templateID: string\n templateName: string\n sandboxID: string\n eventName: string\n state: string\n errorMsg: string\n statusCode: number\n }>\n total?: number\n hasMore?: boolean\n }\n\n return {\n items: data.items ?? [],\n total: data.total ?? 0,\n hasMore: data.hasMore ?? false,\n }\n }\n}\n\nabstract class BasePaginator<T> {\n protected readonly config: ConnectionConfig\n protected client: ApiClient\n protected readonly limit?: number\n\n private _hasNext: boolean\n private _nextToken?: string\n\n constructor(config: ConnectionConfig, limit?: number, nextToken?: string) {\n this.config = config\n this.client = new ApiClient(this.config)\n\n this._hasNext = true\n this._nextToken = nextToken\n\n this.limit = limit\n }\n\n /**\n * Returns true if there are more items to fetch.\n */\n get hasNext(): boolean {\n return this._hasNext\n }\n\n /**\n * Returns the next token to use for pagination.\n */\n get nextToken(): string | undefined {\n return this._nextToken\n }\n\n protected updatePagination(response: Response) {\n this._nextToken = response.headers.get('x-next-token') || undefined\n this._hasNext = !!this._nextToken\n }\n\n /**\n * Get the next page of items.\n *\n * @throws Error if there are no more items to fetch. Call this method only if `hasNext` is `true`.\n *\n * @returns List of items\n */\n abstract nextItems(): Promise<T[]>\n}\n\n/**\n * Paginator for listing sandboxes.\n *\n * @example\n * ```ts\n * const paginator = Sandbox.list()\n * while (paginator.hasNext) {\n * const sandboxes = await paginator.nextItems()\n * console.log(sandboxes)\n * }\n * ```\n */\nexport class SandboxPaginator extends BasePaginator<SandboxInfo> {\n private query: SandboxListOpts['query']\n\n constructor(opts?: SandboxListOpts) {\n super(new ConnectionConfig(opts), opts?.limit, opts?.nextToken)\n\n this.query = opts?.query\n }\n\n async nextItems(): Promise<SandboxInfo[]> {\n if (!this.hasNext) {\n throw new Error('No more items to fetch')\n }\n\n let metadata = undefined\n if (this.query?.metadata) {\n const encodedPairs: Record<string, string> = Object.fromEntries(\n Object.entries(this.query.metadata).map(([key, value]) => [\n encodeURIComponent(key),\n encodeURIComponent(value),\n ])\n )\n\n metadata = new URLSearchParams(encodedPairs).toString()\n }\n\n if (this.config.isLegacyDomain) {\n const params = new URLSearchParams()\n if (metadata) {\n params.set('metadata', metadata)\n }\n if (this.query?.state?.length) {\n params.set('state', this.query.state.join(','))\n }\n if (this.limit) {\n params.set('limit', String(this.limit))\n }\n if (this.nextToken) {\n params.set('nextToken', this.nextToken)\n }\n\n const query = params.toString()\n const response = await fetch(\n `${this.config.apiUrl}/v2/sandboxes${query ? `?${query}` : ''}`,\n {\n headers: getRawApiHeaders(this.config),\n signal: this.config.getSignal(),\n }\n )\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n this.updatePagination(response)\n\n const data = (await response.json()) as components['schemas']['ListedSandbox'][] | null\n return (data ?? []).map(sandbox => ({\n sandboxId:\n sandbox.clientID != null\n ? `${sandbox.sandboxID}-${sandbox.clientID}`\n : sandbox.sandboxID,\n templateId: sandbox.templateID,\n ...(sandbox.alias && { name: sandbox.alias }),\n metadata: sandbox.metadata ?? {},\n startedAt: new Date(sandbox.startedAt),\n endAt: new Date(sandbox.endAt),\n state: sandbox.state,\n cpuCount: sandbox.cpuCount,\n memoryMB: sandbox.memoryMB,\n envdVersion: sandbox.envdVersion,\n volumeMounts: sandbox.volumeMounts ?? [],\n }))\n }\n\n const res = await this.client.api.GET('/v2/sandboxes', {\n params: {\n query: {\n metadata,\n state: this.query?.state,\n limit: this.limit,\n nextToken: this.nextToken,\n },\n },\n // requestTimeoutMs is already passed here via the connectionConfig.\n signal: this.config.getSignal(),\n })\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n this.updatePagination(res.response)\n\n return (res.data ?? []).map(\n (sandbox: components['schemas']['ListedSandbox']) => ({\n sandboxId:\n this.config.isLegacyDomain && sandbox.clientID != null\n ? `${sandbox.sandboxID}-${sandbox.clientID}`\n : sandbox.sandboxID,\n templateId: sandbox.templateID,\n ...(sandbox.alias && { name: sandbox.alias }),\n metadata: sandbox.metadata ?? {},\n startedAt: new Date(sandbox.startedAt),\n endAt: new Date(sandbox.endAt),\n state: sandbox.state,\n cpuCount: sandbox.cpuCount,\n memoryMB: sandbox.memoryMB,\n envdVersion: sandbox.envdVersion,\n volumeMounts: sandbox.volumeMounts ?? [],\n })\n )\n }\n}\n\n/**\n * Paginator for listing snapshots.\n *\n * @example\n * ```ts\n * const paginator = Sandbox.listSnapshots()\n * while (paginator.hasNext) {\n * const snapshots = await paginator.nextItems()\n * console.log(snapshots)\n * }\n * ```\n */\nexport class SnapshotPaginator extends BasePaginator<SnapshotInfo> {\n private readonly sandboxId?: string\n\n constructor(opts?: SnapshotListOpts) {\n super(new ConnectionConfig(opts), opts?.limit, opts?.nextToken)\n\n raiseIfLegacy(this.config, 'Sandbox.listSnapshots', SandboxError)\n\n this.sandboxId = opts?.sandboxId\n }\n\n async nextItems(): Promise<SnapshotInfo[]> {\n if (!this.hasNext) {\n throw new Error('No more items to fetch')\n }\n\n const res = await this.client.api.GET('/snapshots', {\n params: {\n query: {\n sandboxID: this.sandboxId,\n limit: this.limit,\n nextToken: this.nextToken,\n },\n },\n signal: this.config.getSignal(),\n })\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n this.updatePagination(res.response)\n\n return (res.data ?? []).map(\n (snapshot: components['schemas']['SnapshotInfo']) => ({\n snapshotId: snapshot.snapshotID,\n })\n )\n }\n}\n\nexport interface SandboxQuotaLimit {\n concurrentInstances: number\n concurrentVcpu: number\n concurrentRamMb: number\n maxLengthHours: number\n diskMb: number\n maxVcpu: number\n maxRamMb: number\n}\n\nexport interface SandboxQuotaUsage {\n concurrentInstances: number\n concurrentVcpu: number\n concurrentRamMb: number\n}\n\nexport interface SandboxQuota {\n limit: SandboxQuotaLimit\n usage: SandboxQuotaUsage\n}\n\nexport interface SandboxQuotaOpts extends SandboxApiOpts {}\n\nexport interface SandboxEventsOpts extends SandboxApiOpts {\n startTime?: number\n endTime?: number\n sandboxID?: string\n templateID?: string\n events?: string\n state?: string\n orderAsc?: boolean\n offset?: number\n limit?: number\n}\n\nexport interface SandboxEventItem {\n eventID: string\n recordAt: number\n templateID: string\n templateName: string\n sandboxID: string\n eventName: string\n state: string\n errorMsg: string\n statusCode: number\n}\n\nexport interface SandboxEventsResult {\n items: SandboxEventItem[]\n total: number\n hasMore: boolean\n}\n","import { sha256 } from '../utils'\n\n/**\n * Get the URL signature for the specified path, operation and user.\n *\n * @param path Path to the file in the sandbox.\n *\n * @param operation File system operation. Can be either `read` or `write`.\n *\n * @param user Sandbox user.\n *\n * @param expirationInSeconds Optional signature expiration time in seconds.\n */\n\ninterface SignatureOpts {\n path: string\n operation: 'read' | 'write'\n user: string | undefined\n expirationInSeconds?: number\n envdAccessToken?: string\n}\n\nexport async function getSignature({\n path,\n operation,\n user,\n expirationInSeconds,\n envdAccessToken,\n}: SignatureOpts): Promise<{ signature: string; expiration: number | null }> {\n if (!envdAccessToken) {\n throw new Error(\n 'Access token is not set and signature cannot be generated!'\n )\n }\n\n // expiration is unix timestamp\n const signatureExpiration = expirationInSeconds\n ? Math.floor(Date.now() / 1000) + expirationInSeconds\n : null\n let signatureRaw: string\n\n // if user is undefined, set it to empty string to handle default user\n if (user == undefined) {\n user = ''\n }\n\n if (signatureExpiration === null) {\n signatureRaw = `${path}:${operation}:${user}:${envdAccessToken}`\n } else {\n signatureRaw = `${path}:${operation}:${user}:${envdAccessToken}:${signatureExpiration.toString()}`\n }\n\n const hashBase64 = await sha256(signatureRaw)\n const signature = 'v1_' + hashBase64.replace(/=+$/, '')\n\n return {\n signature: signature,\n expiration: signatureExpiration,\n }\n}\n","import { createConnectTransport } from '@connectrpc/connect-web'\n\nimport {\n ConnectionConfig,\n ConnectionOpts,\n DEFAULT_SANDBOX_TIMEOUT_MS,\n defaultUsername,\n raiseIfLegacy,\n isLegacyDomain,\n Username,\n} from '../connectionConfig'\nimport { EnvdApiClient, handleEnvdApiError } from '../envd/api'\nimport { createRpcLogger } from '../logs'\nimport { Commands, Pty } from './commands'\nimport { Filesystem } from './filesystem'\nimport { Git } from './git'\nimport {\n SandboxOpts,\n SandboxConnectOpts,\n SandboxMetricsOpts,\n SandboxApi,\n SandboxListOpts,\n SandboxPaginator,\n SandboxBetaCreateOpts,\n SandboxApiOpts,\n SandboxCloneOpts,\n SandboxCloneResult,\n SandboxCommitOpts,\n SandboxCommitResult,\n SandboxEventsOpts,\n SandboxEventsResult,\n SandboxInfo,\n SandboxNetworkUpdateOpts,\n SandboxQuota,\n SandboxQuotaOpts,\n SandboxResetOpts,\n SnapshotListOpts,\n SnapshotInfo,\n SnapshotPaginator,\n} from './sandboxApi'\nimport { getSignature } from './signature'\nimport { compareVersions } from 'compare-versions'\nimport { SandboxError } from '../errors'\nimport { ENVD_DEBUG_FALLBACK, ENVD_DEFAULT_USER } from '../envd/versions'\nimport { shellQuote } from '../utils'\n\n/**\n * Options for sandbox upload/download URL generation.\n */\nexport interface SandboxUrlOpts {\n /**\n * Use signature expiration for the URL.\n * Optional parameter to set the expiration time for the signature in seconds.\n */\n useSignatureExpiration?: number\n\n /**\n * User that will be used to access the file.\n */\n user?: Username\n}\n\n/**\n * PPIO sandbox cloud sandbox is a secure and isolated cloud environment.\n *\n * The sandbox allows you to:\n * - Access Linux OS\n * - Create, list, and delete files and directories\n * - Run commands\n * - Run git operations\n * - Run isolated code\n * - Access the internet\n *\n * Check docs [here](https://ppio.com/docs/sandbox/overview).\n *\n * Use {@link Sandbox.create} to create a new sandbox.\n *\n * @example\n * ```ts\n * import { Sandbox } from 'ppio-sandbox'\n *\n * const sandbox = await Sandbox.create()\n * ```\n */\nexport class Sandbox extends SandboxApi {\n protected static readonly defaultTemplate: string = 'base'\n protected static readonly defaultMcpTemplate: string = 'mcp-gateway'\n protected static readonly defaultSandboxTimeoutMs = DEFAULT_SANDBOX_TIMEOUT_MS\n\n /**\n * Module for interacting with the sandbox filesystem\n */\n readonly files: Filesystem\n /**\n * Module for running commands in the sandbox\n */\n readonly commands: Commands\n /**\n * Module for interacting with the sandbox pseudo-terminals\n */\n readonly pty: Pty\n /**\n * Module for running git operations in the sandbox\n */\n readonly git: Git\n\n /**\n * Unique identifier of the sandbox.\n */\n readonly sandboxId: string\n\n /**\n * Domain where the sandbox is hosted.\n */\n readonly sandboxDomain: string\n\n /**\n * Traffic access token for accessing sandbox services with restricted public traffic.\n */\n readonly trafficAccessToken?: string\n\n protected readonly envdPort = 49983\n protected readonly mcpPort = 50005\n\n protected readonly connectionConfig: ConnectionConfig\n protected readonly envdAccessToken?: string\n private readonly envdApiUrl: string\n private readonly envdApi: EnvdApiClient\n private mcpToken?: string\n\n /**\n * Use {@link Sandbox.create} to create a new Sandbox instead.\n *\n * @hidden\n * @hide\n * @internal\n * @access protected\n */\n constructor(\n opts: SandboxConnectOpts & {\n sandboxId: string\n sandboxDomain?: string\n envdVersion: string\n envdAccessToken?: string\n trafficAccessToken?: string\n }\n ) {\n super()\n\n this.connectionConfig = new ConnectionConfig(opts)\n\n this.sandboxId = opts.sandboxId\n this.sandboxDomain = opts.sandboxDomain ?? this.connectionConfig.domain\n\n this.envdAccessToken = opts.envdAccessToken\n this.trafficAccessToken = opts.trafficAccessToken\n this.envdApiUrl = this.connectionConfig.getSandboxUrl(this.sandboxId, {\n sandboxDomain: this.sandboxDomain,\n envdPort: this.envdPort,\n })\n\n const sandboxHeaders = {\n 'E2b-Sandbox-Id': this.sandboxId,\n 'E2b-Sandbox-Port': this.envdPort.toString(),\n }\n\n const rpcTransport = createConnectTransport({\n baseUrl: this.envdApiUrl,\n useBinaryFormat: false,\n interceptors: opts?.logger ? [createRpcLogger(opts.logger)] : undefined,\n fetch: (url, options) => {\n // Patch fetch to always use redirect: \"follow\"\n // connect-web doesn't allow to configure redirect option - https://github.com/connectrpc/connect-es/pull/1082\n // connect-web package uses redirect: \"error\" which is not supported in edge runtimes\n // PPIO sandbox endpoints should be safe to use with redirect: \"follow\" https://github.com/ppio-dev/PPIO sandbox/issues/531#issuecomment-2779492867\n\n const headers = new Headers(this.connectionConfig.headers)\n new Headers(options?.headers).forEach((value, key) =>\n headers.append(key, value)\n )\n new Headers(sandboxHeaders).forEach((value, key) =>\n headers.append(key, value)\n )\n\n if (this.envdAccessToken) {\n headers.append('X-Access-Token', this.envdAccessToken)\n }\n\n options = {\n ...(options ?? {}),\n headers: headers,\n redirect: 'follow',\n }\n\n return fetch(url, options)\n },\n })\n\n this.envdApi = new EnvdApiClient(\n {\n apiUrl: this.envdApiUrl,\n logger: opts?.logger,\n accessToken: this.envdAccessToken,\n headers: {\n 'User-Agent': this.connectionConfig.headers?.['User-Agent'] ?? '',\n ...sandboxHeaders,\n ...(this.envdAccessToken\n ? { 'X-Access-Token': this.envdAccessToken }\n : {}),\n },\n },\n {\n version: opts.envdVersion,\n }\n )\n this.files = new Filesystem(\n rpcTransport,\n this.envdApi,\n this.connectionConfig\n )\n this.commands = new Commands(rpcTransport, this.connectionConfig, {\n version: opts.envdVersion,\n })\n this.pty = new Pty(rpcTransport, this.connectionConfig, {\n version: opts.envdVersion,\n })\n this.git = new Git(this.commands)\n }\n\n /**\n * List all sandboxes.\n *\n * @param opts connection options.\n *\n * @returns paginator for listing sandboxes.\n */\n static list(opts?: SandboxListOpts): SandboxPaginator {\n return new SandboxPaginator(opts)\n }\n\n /**\n * Create a new sandbox from the default `base` sandbox template.\n *\n * @param opts connection options.\n *\n * @returns sandbox instance for the new sandbox.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * ```\n * @constructs {@link Sandbox}\n */\n static async create<S extends typeof Sandbox>(\n this: S,\n opts?: SandboxOpts\n ): Promise<InstanceType<S>>\n\n /**\n * Create a new sandbox from the specified sandbox template.\n *\n * @param template sandbox template name or ID.\n * @param opts connection options.\n *\n * @returns sandbox instance for the new sandbox.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create('<template-name-or-id>')\n * ```\n * @constructs {@link Sandbox}\n */\n static async create<S extends typeof Sandbox>(\n this: S,\n template: string,\n opts?: SandboxOpts\n ): Promise<InstanceType<S>>\n static async create<S extends typeof Sandbox>(\n this: S,\n templateOrOpts?: SandboxOpts | string,\n opts?: SandboxOpts\n ): Promise<InstanceType<S>> {\n const { template, sandboxOpts } =\n typeof templateOrOpts === 'string'\n ? {\n template: templateOrOpts,\n sandboxOpts: opts,\n }\n : {\n template:\n templateOrOpts?.template ??\n (templateOrOpts?.mcp\n ? this.defaultMcpTemplate\n : this.defaultTemplate),\n sandboxOpts: templateOrOpts,\n }\n\n const config = new ConnectionConfig(sandboxOpts)\n if (config.debug) {\n return new this({\n sandboxId: 'debug_sandbox_id',\n envdVersion: ENVD_DEBUG_FALLBACK,\n ...config,\n }) as InstanceType<S>\n }\n\n const sandboxInfo = await SandboxApi.createSandbox(\n template,\n sandboxOpts?.timeoutMs ?? this.defaultSandboxTimeoutMs,\n sandboxOpts\n )\n\n const sandbox = new this({ ...sandboxInfo, ...config }) as InstanceType<S>\n\n if (sandboxOpts?.mcp && !config.isLegacyDomain) {\n sandbox.mcpToken = crypto.randomUUID()\n const res = await sandbox.commands.run(\n `mcp-gateway --config ${shellQuote(JSON.stringify(sandboxOpts.mcp))}`,\n {\n user: 'root',\n envs: {\n GATEWAY_ACCESS_TOKEN: sandbox.mcpToken ?? '',\n },\n }\n )\n if (res.exitCode !== 0) {\n throw new Error(`Failed to start MCP gateway: ${res.stderr}`)\n }\n }\n\n return sandbox\n }\n\n /**\n * Clone a sandbox to create one or more identical sandboxes.\n *\n * @param sandboxId source sandbox ID.\n * @param opts clone options.\n *\n * @returns cloned sandbox instances plus snapshot template ID.\n */\n static async clone<S extends typeof Sandbox>(\n this: S,\n sandboxId: string,\n opts?: SandboxCloneOpts\n ): Promise<SandboxCloneResult<InstanceType<S>>> {\n const cloneResult = await SandboxApi.cloneSandboxes(sandboxId, opts)\n const config = new ConnectionConfig(opts)\n\n const sandboxes = cloneResult.sandboxes.map(\n sandbox =>\n new this({\n sandboxId: sandbox.sandboxId,\n envdVersion: sandbox.envdVersion,\n envdAccessToken: sandbox.envdAccessToken,\n trafficAccessToken: sandbox.trafficAccessToken,\n ...config,\n }) as InstanceType<S>\n )\n\n return {\n sandboxes,\n count: sandboxes.length,\n snapshotTemplateId: cloneResult.snapshotTemplateId,\n }\n }\n\n /**\n * Dynamically adjust the hotplugged memory on a running sandbox.\n *\n * The value represents the new *total* plugged size in MiB, not a delta.\n * Use `0` to unplug all hotplugged memory.\n */\n static async hotplugMemory(\n sandboxId: string,\n requestedSizeMib: number,\n opts?: SandboxApiOpts\n ): Promise<void> {\n return await SandboxApi.hotplugMemory(\n sandboxId,\n requestedSizeMib,\n opts\n )\n }\n\n /**\n * Mount a volume to a sandbox.\n *\n * @param sandboxId sandbox ID.\n * @param name volume name.\n * @param path mount path inside the sandbox.\n * @param opts connection options.\n *\n * @returns updated sandbox information.\n */\n static async mountVolume(\n sandboxId: string,\n name: string,\n path: string,\n opts?: SandboxApiOpts\n ): Promise<SandboxInfo> {\n return await SandboxApi.mountVolume(sandboxId, name, path, opts)\n }\n\n /**\n * Unmount a volume from a sandbox.\n *\n * @param sandboxId sandbox ID.\n * @param path mount path to unmount.\n * @param opts connection options.\n * @param [opts.force] force unmount.\n *\n * @returns updated sandbox information.\n */\n static async unmountVolume(\n sandboxId: string,\n path: string,\n opts?: SandboxApiOpts & { force?: boolean }\n ) {\n return await SandboxApi.unmountVolume(sandboxId, path, opts)\n }\n\n /**\n * Commit a sandbox to create a snapshot template.\n *\n * @deprecated Use snapshot APIs instead. This method is only supported for modern domains.\n *\n * @param sandboxId source sandbox ID.\n * @param opts commit options.\n *\n * @returns created snapshot template.\n */\n static async commit(\n sandboxId: string,\n opts?: SandboxCommitOpts\n ): Promise<SandboxCommitResult> {\n return await SandboxApi.commit(sandboxId, opts)\n }\n\n /**\n * Reset sandbox memory and optionally resume the sandbox.\n *\n * @param sandboxId sandbox ID.\n * @param opts reset options.\n *\n * @returns `true` if reset succeeded, `false` if the sandbox is in a conflicting state.\n */\n static async reset(\n sandboxId: string,\n opts?: SandboxResetOpts\n ): Promise<boolean> {\n return await SandboxApi.reset(sandboxId, opts)\n }\n\n /**\n * Update network egress rules for a running sandbox.\n * Omitting both `allowOut` and `denyOut` clears all egress rules.\n */\n static async setNetwork(\n sandboxId: string,\n opts?: SandboxNetworkUpdateOpts\n ): Promise<void> {\n await SandboxApi.setNetwork(sandboxId, opts)\n }\n\n /**\n * @beta This feature is in beta and may change in the future.\n *\n * Create a new sandbox from the default `base` sandbox template.\n *\n * @param opts connection options.\n *\n * @returns sandbox instance for the new sandbox.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.betaCreate()\n * ```\n * @constructs {@link Sandbox}\n */\n static async betaCreate<S extends typeof Sandbox>(\n this: S,\n opts?: SandboxBetaCreateOpts\n ): Promise<InstanceType<S>>\n\n /**\n * @beta This feature is in beta and may change in the future.\n *\n * Create a new sandbox from the specified sandbox template.\n *\n * @param template sandbox template name or ID.\n * @param opts connection options.\n *\n * @returns sandbox instance for the new sandbox.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.betaCreate('<template-name-or-id>')\n * ```\n * @constructs {@link Sandbox}\n */\n static async betaCreate<S extends typeof Sandbox>(\n this: S,\n template: string,\n opts?: SandboxBetaCreateOpts\n ): Promise<InstanceType<S>>\n static async betaCreate<S extends typeof Sandbox>(\n this: S,\n templateOrOpts?: SandboxBetaCreateOpts | string,\n opts?: SandboxBetaCreateOpts\n ): Promise<InstanceType<S>> {\n const { template, sandboxOpts } =\n typeof templateOrOpts === 'string'\n ? {\n template: templateOrOpts,\n sandboxOpts: opts,\n }\n : {\n template:\n templateOrOpts?.template ??\n (templateOrOpts?.mcp\n ? this.defaultMcpTemplate\n : this.defaultTemplate),\n sandboxOpts: templateOrOpts,\n }\n\n const config = new ConnectionConfig(sandboxOpts)\n if (config.debug) {\n return new this({\n sandboxId: 'debug_sandbox_id',\n envdVersion: ENVD_DEBUG_FALLBACK,\n ...config,\n }) as InstanceType<S>\n }\n\n const sandboxInfo = await SandboxApi.createSandbox(\n template,\n sandboxOpts?.timeoutMs ?? this.defaultSandboxTimeoutMs,\n sandboxOpts\n )\n\n const sandbox = new this({ ...sandboxInfo, ...config }) as InstanceType<S>\n\n if (sandboxOpts?.mcp && !config.isLegacyDomain) {\n sandbox.mcpToken = crypto.randomUUID()\n const res = await sandbox.commands.run(\n `mcp-gateway --config ${shellQuote(JSON.stringify(sandboxOpts.mcp))}`,\n {\n user: 'root',\n envs: {\n GATEWAY_ACCESS_TOKEN: sandbox.mcpToken ?? '',\n },\n }\n )\n if (res.exitCode !== 0) {\n throw new Error(`Failed to start MCP gateway: ${res.stderr}`)\n }\n }\n\n return sandbox\n }\n\n /**\n * Connect to a sandbox. If the sandbox is paused, it will be automatically resumed.\n * Sandbox must be either running or be paused.\n *\n * With sandbox ID you can connect to the same sandbox from different places or environments (serverless functions, etc).\n *\n * @param sandboxId sandbox ID.\n * @param opts connection options.\n *\n * @returns A running sandbox instance\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * const sandboxId = sandbox.sandboxId\n *\n * // Connect to the same sandbox.\n * const sameSandbox = await Sandbox.connect(sandboxId)\n * ```\n */\n static async connect<S extends typeof Sandbox>(\n this: S,\n sandboxId: string,\n opts?: SandboxConnectOpts\n ): Promise<InstanceType<S>> {\n const sandbox = await SandboxApi.connectSandbox(sandboxId, opts)\n const config = new ConnectionConfig(opts)\n\n return new this({\n sandboxId,\n sandboxDomain: sandbox.sandboxDomain,\n envdAccessToken: sandbox.envdAccessToken,\n trafficAccessToken: sandbox.trafficAccessToken,\n envdVersion: sandbox.envdVersion,\n ...config,\n }) as InstanceType<S>\n }\n\n /**\n * Connect to a sandbox. If the sandbox is paused, it will be automatically resumed.\n * Sandbox must be either running or be paused.\n *\n * With sandbox ID you can connect to the same sandbox from different places or environments (serverless functions, etc).\n *\n * @param opts connection options.\n *\n * @returns A running sandbox instance\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * await sandbox.betaPause()\n *\n * // Connect to the same sandbox.\n * const sameSandbox = await sandbox.connect()\n * ```\n */\n async connect(opts?: SandboxConnectOpts): Promise<this> {\n await SandboxApi.connectSandbox(this.sandboxId, this.resolveApiOpts(opts))\n\n return this\n }\n\n /**\n * Get the host address for the specified sandbox port.\n * You can then use this address to connect to the sandbox port from outside the sandbox via HTTP or WebSocket.\n *\n * @param port number of the port in the sandbox.\n *\n * @returns host address of the sandbox port.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * // Start an HTTP server\n * await sandbox.commands.exec('python3 -m http.server 3000')\n * // Get the hostname of the HTTP server\n * const serverURL = sandbox.getHost(3000)\n * ```\n */\n getHost(port: number) {\n return this.connectionConfig.getHost(\n this.sandboxId,\n port,\n this.sandboxDomain\n )\n }\n\n /**\n * Check if the sandbox is running.\n *\n * @returns `true` if the sandbox is running, `false` otherwise.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * await sandbox.isRunning() // Returns true\n *\n * await sandbox.kill()\n * await sandbox.isRunning() // Returns false\n * ```\n */\n async isRunning(\n opts?: Pick<ConnectionOpts, 'requestTimeoutMs'>\n ): Promise<boolean> {\n const signal = this.connectionConfig.getSignal(opts?.requestTimeoutMs)\n\n const res = await this.envdApi.api.GET('/health', {\n signal,\n })\n\n if (res.response.status == 502) {\n return false\n }\n\n const err = await handleEnvdApiError(res)\n if (err) {\n throw err\n }\n\n return true\n }\n\n /**\n * Set the timeout of the sandbox.\n *\n * This method can extend or reduce the sandbox timeout set when creating the sandbox or from the last call to `.setTimeout`.\n * Maximum time a sandbox can be kept alive is 24 hours (86_400_000 milliseconds) for Pro users and 1 hour (3_600_000 milliseconds) for Hobby users.\n *\n * @param timeoutMs timeout in **milliseconds**.\n * @param opts connection options.\n */\n async setTimeout(\n timeoutMs: number,\n opts?: Pick<SandboxOpts, 'requestTimeoutMs'>\n ) {\n if (this.connectionConfig.debug) {\n // Skip timeout in debug mode\n return\n }\n\n await SandboxApi.setTimeout(\n this.sandboxId,\n timeoutMs,\n this.resolveApiOpts(opts)\n )\n }\n\n /**\n * Reset sandbox memory and optionally resume the sandbox.\n *\n * @param opts reset options.\n *\n * @returns `true` if reset succeeded, `false` if the sandbox is in a conflicting state.\n */\n async reset(opts?: SandboxResetOpts): Promise<boolean> {\n return await SandboxApi.reset(this.sandboxId, this.resolveApiOpts(opts))\n }\n\n /**\n * Update network egress rules for this running sandbox.\n * Omitting both `allowOut` and `denyOut` clears all egress rules.\n */\n async setNetwork(opts?: SandboxNetworkUpdateOpts): Promise<void> {\n await SandboxApi.setNetwork(this.sandboxId, this.resolveApiOpts(opts))\n }\n\n /**\n * Commit this sandbox to create a snapshot template.\n *\n * @deprecated Use snapshot APIs instead. This method is only supported for modern domains.\n *\n * @param opts commit options.\n *\n * @returns created snapshot template.\n */\n async commit(opts?: SandboxCommitOpts): Promise<SandboxCommitResult> {\n return await SandboxApi.commit(this.sandboxId, this.resolveApiOpts(opts))\n }\n\n /**\n * Mount a volume to this sandbox.\n *\n * @param name volume name.\n * @param path mount path inside the sandbox.\n * @param opts connection options.\n *\n * @returns updated sandbox information.\n */\n async mountVolume(\n name: string, \n path: string, \n opts?: SandboxApiOpts\n ) {\n return await SandboxApi.mountVolume(\n this.sandboxId,\n name,\n path,\n this.resolveApiOpts(opts)\n )\n }\n\n /**\n * Unmount a volume from this sandbox.\n *\n * @param path mount path to unmount.\n * @param opts connection options.\n * @param [opts.force] force unmount.\n *\n * @returns updated sandbox information.\n */\n async unmountVolume(\n path: string,\n opts?: SandboxApiOpts & { force?: boolean }\n ) {\n return await SandboxApi.unmountVolume(\n this.sandboxId,\n path,\n this.resolveApiOpts(opts)\n )\n }\n\n /**\n * Kill the sandbox.\n *\n * @param opts connection options.\n */\n async kill(opts?: Pick<SandboxOpts, 'requestTimeoutMs'>) {\n if (this.connectionConfig.debug) {\n // Skip killing in debug mode\n return\n }\n\n await SandboxApi.kill(this.sandboxId, this.resolveApiOpts(opts))\n }\n\n /**\n * Dynamically adjust the hotplugged memory on a running sandbox.\n *\n * The value represents the new *total* plugged size in MiB, not a delta.\n * Use `0` to unplug all hotplugged memory.\n *\n * @param requestedSizeMib new total plugged memory size in MiB.\n * @param opts connection options.\n */\n async hotplugMemory(\n requestedSizeMib: number,\n opts?: SandboxApiOpts\n ): Promise<void> {\n await SandboxApi.hotplugMemory(\n this.sandboxId,\n requestedSizeMib,\n this.resolveApiOpts(opts)\n )\n }\n\n /**\n * Pause a sandbox by its ID.\n *\n * @param opts connection options.\n *\n * @returns sandbox ID that can be used to resume the sandbox.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * await sandbox.pause()\n * ```\n */\n async pause(opts?: ConnectionOpts): Promise<boolean> {\n return await SandboxApi.pause(this.sandboxId, this.resolveApiOpts(opts))\n }\n\n /**\n * @deprecated Use {@link Sandbox.pause} instead.\n */\n async betaPause(opts?: ConnectionOpts): Promise<boolean> {\n return await SandboxApi.betaPause(\n this.sandboxId,\n this.resolveApiOpts(opts)\n )\n }\n\n /**\n * Create a snapshot of the sandbox's current state.\n *\n * The sandbox will be paused while the snapshot is being created.\n * The snapshot can be used to create new sandboxes with the same filesystem and state.\n * Snapshots are persistent and survive sandbox deletion.\n *\n * Use the returned `snapshotId` with `Sandbox.create(snapshotId)` to create a new sandbox from the snapshot.\n *\n * @param opts connection options.\n *\n * @returns snapshot information including the snapshot ID.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * await sandbox.files.write('/app/state.json', '{\"step\": 1}')\n *\n * // Create a snapshot\n * const snapshot = await sandbox.createSnapshot()\n *\n * // Create a new sandbox from the snapshot\n * const newSandbox = await Sandbox.create(snapshot.snapshotId)\n * ```\n */\n async createSnapshot(opts?: SandboxApiOpts): Promise<SnapshotInfo> {\n return await SandboxApi.createSnapshot(\n this.sandboxId,\n this.resolveApiOpts(opts)\n )\n }\n\n /**\n * List all snapshots created from this sandbox.\n *\n * @param opts list options.\n *\n * @returns paginator for listing snapshots from this sandbox.\n */\n listSnapshots(opts?: Omit<SnapshotListOpts, 'sandboxId'>): SnapshotPaginator {\n return SandboxApi.listSnapshots({\n ...this.resolveApiOpts(opts),\n sandboxId: this.sandboxId,\n })\n }\n\n /**\n *\n * Get the MCP URL for the sandbox.\n *\n * @returns MCP URL for the sandbox.\n */\n getMcpUrl(): string {\n raiseIfLegacy(this.connectionConfig, 'Sandbox.getMcpUrl', SandboxError)\n\n return `https://${this.getHost(this.mcpPort)}/mcp`\n }\n\n /**\n * Get the MCP token for the sandbox.\n *\n * @returns MCP token for the sandbox, or undefined if MCP is not enabled.\n */\n async getMcpToken(): Promise<string | undefined> {\n raiseIfLegacy(this.connectionConfig, 'Sandbox.getMcpToken', SandboxError)\n\n if (!this.mcpToken) {\n this.mcpToken = await this.files.read('/etc/mcp-gateway/.token', {\n user: 'root',\n })\n }\n\n return this.mcpToken\n }\n\n /**\n * Get the URL to upload a file to the sandbox.\n *\n * You have to send a POST request to this URL with the file as multipart/form-data.\n *\n * @param path path to the file in the sandbox.\n *\n * @param opts download url options.\n *\n * @returns URL for uploading file.\n */\n async uploadUrl(path?: string, opts?: SandboxUrlOpts) {\n opts = opts ?? {}\n\n const useSignature = !!this.envdAccessToken\n\n if (!useSignature && opts.useSignatureExpiration != undefined) {\n throw new Error(\n 'Signature expiration can be used only when sandbox is created as secured.'\n )\n }\n\n let username = opts.user\n if (\n username == undefined &&\n compareVersions(this.envdApi.version, ENVD_DEFAULT_USER) < 0\n ) {\n username = defaultUsername\n }\n\n const filePath = path ?? ''\n const fileUrl = this.fileUrl(filePath, username)\n\n if (useSignature) {\n const url = new URL(fileUrl)\n const sig = await getSignature({\n path: filePath,\n operation: 'write',\n user: username,\n expirationInSeconds: opts.useSignatureExpiration,\n envdAccessToken: this.envdAccessToken,\n })\n\n url.searchParams.set('signature', sig.signature)\n if (sig.expiration) {\n url.searchParams.set('signature_expiration', sig.expiration.toString())\n }\n\n return url.toString()\n }\n\n return fileUrl\n }\n\n /**\n * Get the URL to download a file from the sandbox.\n *\n * @param path path to the file in the sandbox.\n *\n * @param opts download url options.\n *\n * @returns URL for downloading file.\n */\n async downloadUrl(path: string, opts?: SandboxUrlOpts) {\n opts = opts ?? {}\n\n const useSignature = !!this.envdAccessToken\n\n if (!useSignature && opts.useSignatureExpiration != undefined) {\n throw new Error(\n 'Signature expiration can be used only when sandbox is created as secured.'\n )\n }\n\n let username = opts.user\n if (\n username == undefined &&\n compareVersions(this.envdApi.version, ENVD_DEFAULT_USER) < 0\n ) {\n username = defaultUsername\n }\n\n const fileUrl = this.fileUrl(path, username)\n\n if (useSignature) {\n const url = new URL(fileUrl)\n const sig = await getSignature({\n path,\n operation: 'read',\n user: username,\n expirationInSeconds: opts.useSignatureExpiration,\n envdAccessToken: this.envdAccessToken,\n })\n\n url.searchParams.set('signature', sig.signature)\n if (sig.expiration) {\n url.searchParams.set('signature_expiration', sig.expiration.toString())\n }\n\n return url.toString()\n }\n\n return fileUrl\n }\n\n /**\n * Get sandbox information like sandbox ID, template, metadata, started at/end at date.\n *\n * @param opts connection options.\n *\n * @returns information about the sandbox\n */\n async getInfo(opts?: Pick<SandboxOpts, 'requestTimeoutMs'>) {\n return await SandboxApi.getInfo(this.sandboxId, this.resolveApiOpts(opts))\n }\n\n /**\n * Get the metrics of the sandbox.\n *\n * @param opts connection options.\n *\n * @returns List of sandbox metrics containing CPU, memory and disk usage information.\n */\n async getMetrics(opts?: SandboxMetricsOpts) {\n if (this.envdApi.version) {\n if (compareVersions(this.envdApi.version, '0.1.5') < 0) {\n throw new SandboxError(\n 'You need to update the template to use the new SDK. ' +\n 'You can do this by running `ppio template build` in the directory with the template.'\n )\n }\n\n if (compareVersions(this.envdApi.version, '0.2.4') < 0) {\n this.connectionConfig.logger?.warn?.(\n 'Disk metrics are not supported in this version of the sandbox, please rebuild the template to get disk metrics.'\n )\n }\n }\n\n return await SandboxApi.getMetrics(\n this.sandboxId,\n this.resolveApiOpts(opts)\n )\n }\n\n private resolveApiOpts<T extends ConnectionOpts>(\n opts?: T\n ): ConnectionOpts & T {\n return {\n ...this.connectionConfig,\n ...(opts ?? {}),\n } as unknown as ConnectionOpts & T\n }\n\n private fileUrl(path: string | undefined, username: string | undefined) {\n const url = new URL('/files', this.envdApiUrl)\n\n if (username) {\n url.searchParams.set('username', username)\n }\n if (path) {\n url.searchParams.set('path', path)\n }\n\n return url.toString()\n }\n}\n","import chalk from 'chalk'\nimport { stripAnsi } from '../utils'\n\n/**\n * Log entry severity levels.\n */\nexport type LogEntryLevel = 'debug' | 'info' | 'warn' | 'error'\n\n/**\n * Represents a single log entry from the template build process.\n */\nexport class LogEntry {\n constructor(\n public readonly timestamp: Date,\n public readonly level: LogEntryLevel,\n public readonly message: string\n ) {}\n\n toString() {\n return `[${this.timestamp.toISOString()}] [${this.level}] ${stripAnsi(\n this.message\n )}`\n }\n}\n\n/**\n * Special log entry indicating the start of a build process.\n */\nexport class LogEntryStart extends LogEntry {\n constructor(timestamp: Date, message: string) {\n super(timestamp, 'debug', message)\n }\n}\n\n/**\n * Special log entry indicating the end of a build process.\n */\nexport class LogEntryEnd extends LogEntry {\n constructor(timestamp: Date, message: string) {\n super(timestamp, 'debug', message)\n }\n}\n\n/**\n * Interval in milliseconds for updating the build timer display.\n * @internal\n */\nconst TIMER_UPDATE_INTERVAL_MS = 150\n\n/**\n * Default minimum log level to display.\n * @internal\n */\nconst DEFAULT_LEVEL: LogEntryLevel = 'info'\n\n/**\n * Colored labels for each log level.\n * @internal\n */\nconst levels: Record<LogEntryLevel, string> = {\n error: chalk.red('ERROR'),\n warn: chalk.hex('#FF4400')('WARN '),\n info: chalk.hex('#FF8800')('INFO '),\n debug: chalk.gray('DEBUG'),\n}\n\n/**\n * Numeric ordering of log levels for comparison (lower = less severe).\n * @internal\n */\nconst level_order: Record<LogEntryLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n}\n\ninterface DefaultBuildLoggerState {\n startTime: number\n animationFrame: number\n timerInterval: NodeJS.Timeout | undefined\n}\n\nclass DefaultBuildLogger {\n private minLevel: LogEntryLevel\n private state: DefaultBuildLoggerState\n\n constructor(minLevel?: LogEntryLevel) {\n this.minLevel = minLevel ?? DEFAULT_LEVEL\n this.state = this.getInitialState()\n }\n\n logger(logEntry: LogEntry) {\n if (logEntry instanceof LogEntryStart) {\n this.startTimer()\n return\n }\n\n if (logEntry instanceof LogEntryEnd) {\n clearInterval(this.state.timerInterval)\n return\n }\n\n // Filter by minimum level\n if (level_order[logEntry.level] < level_order[this.minLevel]) {\n return\n }\n\n const formattedLine = this.formatLogLine(logEntry)\n process.stdout.write(`${formattedLine}\\n`)\n\n // Redraw the timer line\n this.updateTimer()\n }\n\n private getInitialState(\n timerInterval?: NodeJS.Timeout\n ): DefaultBuildLoggerState {\n return {\n startTime: Date.now(),\n animationFrame: 0,\n timerInterval: timerInterval,\n }\n }\n\n private formatTimerLine() {\n const elapsedSeconds = ((Date.now() - this.state.startTime) / 1000).toFixed(\n 1\n )\n return `${elapsedSeconds}s`\n }\n\n private animateStatus() {\n const frames = ['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷']\n const idx = this.state.animationFrame % frames.length\n return `${frames[idx]}`\n }\n\n private formatLogLine(line: LogEntry) {\n const timer = this.formatTimerLine().padEnd(5)\n\n const timestamp = chalk.dim(\n line.timestamp.toLocaleTimeString(undefined, {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n })\n )\n\n const level = levels[line.level] || levels[DEFAULT_LEVEL]\n\n const msg = line.message\n\n return `${timer} | ${timestamp} ${level} ${msg}`\n }\n\n private startTimer() {\n if (!process.stdout.isTTY) {\n return\n }\n\n // Start the timer interval\n const timerInterval = setInterval(\n this.updateTimer.bind(this),\n TIMER_UPDATE_INTERVAL_MS\n )\n\n this.state = this.getInitialState(timerInterval)\n\n // Initial timer display\n this.updateTimer()\n }\n\n private updateTimer() {\n if (!process.stdout.isTTY) {\n return\n }\n\n this.state.animationFrame++\n const jumpingSquares = this.animateStatus()\n process.stdout.write(\n `${jumpingSquares} Building ${this.formatTimerLine()}\\r`\n )\n }\n}\n\n/**\n * Create a default build logger with animated timer display.\n *\n * @param options Logger configuration options\n * @param options.minLevel Minimum log level to display (default: 'info')\n * @returns Logger function that accepts LogEntry instances\n *\n * @example\n * ```ts\n * import { Template, defaultBuildLogger } from 'ppio-sandbox'\n *\n * const template = Template().fromPythonImage()\n *\n * await Template.build(template, {\n * alias: 'my-template',\n * onBuildLogs: defaultBuildLogger({ minLevel: 'debug' })\n * })\n * ```\n */\nexport function defaultBuildLogger(options?: {\n minLevel?: LogEntryLevel\n}): (logEntry: LogEntry) => void {\n const buildLogger = new DefaultBuildLogger(options?.minLevel)\n\n return buildLogger.logger.bind(buildLogger)\n}\n","/**\n * Special step name for the finalization phase of template building.\n * This is the last step that runs after all user-defined instructions.\n * @internal\n */\nexport const FINALIZE_STEP_NAME = 'finalize'\n\n/**\n * Special step name for the base image phase of template building.\n * This is the first step that sets up the base image.\n * @internal\n */\nexport const BASE_STEP_NAME = 'base'\n\n/**\n * Stack trace depth for capturing caller information.\n *\n * Depth levels:\n * 1. Template function\n * 2. TemplateBase class\n * 3. Caller method (e.g., copy(), fromImage(), etc.)\n *\n * This depth is used to determine the original caller's location\n * for stack traces.\n * @internal\n */\nexport const STACK_TRACE_DEPTH = 3\n\n/**\n * Default setting for whether to resolve symbolic links when copying files.\n * When false, symlinks are copied as symlinks rather than following them.\n * @internal\n */\nexport const RESOLVE_SYMLINKS = false\n","import crypto from 'node:crypto'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { dynamicImport, dynamicRequire } from '../utils'\nimport { TemplateError } from '../errors'\nimport { BASE_STEP_NAME, FINALIZE_STEP_NAME } from './consts'\nimport type { Path } from 'glob'\nimport type { BuildOptions } from './types'\n\n/**\n * Validate that a source path for copy operations is a relative path that stays\n * within the context directory. This prevents path traversal attacks and ensures\n * files are copied from within the expected directory.\n *\n * @param src The source path to validate\n * @param stackTrace Optional stack trace for error reporting\n * @throws TemplateError if the path is absolute or escapes the context directory\n *\n * Invalid paths:\n * - Absolute paths: /absolute/path, C:\\Windows\\path\n * - Parent directory escapes: ../foo, foo/../../bar, ./foo/../../../bar\n *\n * Valid paths:\n * - Simple relative: foo, foo/bar\n * - Current directory prefix: ./foo, ./foo/bar\n * - Internal parent refs that don't escape: foo/../bar (stays within context)\n */\nexport function validateRelativePath(\n src: string,\n stackTrace: string | undefined\n): void {\n // Check for absolute paths using Node's cross-platform implementation\n if (path.isAbsolute(src)) {\n const error = new TemplateError(\n `Invalid source path \"${src}\": absolute paths are not allowed. Use a relative path within the context directory.`,\n stackTrace\n )\n throw error\n }\n\n // Normalize the path and check if it escapes the context directory\n const normalized = path.normalize(src)\n\n // After normalization, a path that escapes would be '..' or start with '../'\n // We check for '..' followed by path separator to avoid false positives on filenames like '..myconfig'\n // Examples:\n // - '../foo' -> '../foo' (escapes)\n // - 'foo/../../bar' -> '../bar' (escapes)\n // - './foo/../../../bar' -> '../../bar' (escapes)\n // - 'foo/../bar' -> 'bar' (doesn't escape)\n // - './foo/bar' -> 'foo/bar' (doesn't escape)\n // - '..myconfig' -> '..myconfig' (valid filename, doesn't escape)\n const escapes = normalized === '..' || normalized.startsWith('..' + path.sep)\n\n if (escapes) {\n const error = new TemplateError(\n `Invalid source path \"${src}\": path escapes the context directory. The path must stay within the context directory.`,\n stackTrace\n )\n throw error\n }\n}\n\n/**\n * Normalize build arguments from different overload signatures.\n * Handles string name or legacy options object with alias.\n *\n * @param nameOrOptions Name or legacy options with alias\n * @param options Optional build options (when first arg is name)\n * @returns Object with normalized name, tags, and build options\n * @throws TemplateError if no template name is provided\n */\nexport function normalizeBuildArguments(\n nameOrOptions: string | BuildOptions,\n options?: Omit<BuildOptions, 'alias'>\n): {\n name: string\n buildOptions: Omit<BuildOptions, 'alias'>\n} {\n let name: string\n let buildOptions: Omit<BuildOptions, 'alias'>\n\n if (typeof nameOrOptions === 'string') {\n name = nameOrOptions\n buildOptions = options ?? {}\n } else {\n // Legacy: options object with alias\n const { alias, ...restOpts } = nameOrOptions\n name = alias\n buildOptions = restOpts\n }\n\n if (!name || name.length === 0) {\n throw new TemplateError('Name must be provided')\n }\n\n return { name, buildOptions }\n}\n\n/**\n * Read and parse a .dockerignore file.\n *\n * @param contextPath Directory path containing the .dockerignore file\n * @returns Array of ignore patterns (empty lines and comments are filtered out)\n */\nexport function readDockerignore(contextPath: string): string[] {\n const dockerignorePath = path.join(contextPath, '.dockerignore')\n if (!fs.existsSync(dockerignorePath)) {\n return []\n }\n\n const content = fs.readFileSync(dockerignorePath, 'utf-8')\n return content\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line && !line.startsWith('#'))\n}\n\n/**\n * Normalize path separators to forward slashes for glob patterns (glob expects / even on Windows)\n * @param path - The path to normalize\n * @returns The normalized path\n */\nfunction normalizePath(path: string): string {\n return path.replace(/\\\\/g, '/')\n}\n\n/**\n * Get all files for a given path and ignore patterns.\n *\n * @param src Path to the source directory\n * @param contextPath Base directory for resolving relative paths\n * @param ignorePatterns Ignore patterns\n * @returns Array of files\n */\nexport async function getAllFilesInPath(\n src: string,\n contextPath: string,\n ignorePatterns: string[],\n includeDirectories: boolean = true\n) {\n const { glob } = await dynamicImport<typeof import('glob')>('glob')\n const files = new Map<string, Path>()\n\n const globFiles = await glob(src, {\n ignore: ignorePatterns,\n withFileTypes: true,\n dot: true,\n // this is required so that the ignore pattern is relative to the file path\n cwd: contextPath,\n })\n\n for (const file of globFiles) {\n if (file.isDirectory()) {\n // For directories, add the directory itself and all files inside it\n if (includeDirectories) {\n files.set(file.fullpath(), file)\n }\n const dirPattern = normalizePath(\n // When the matched directory is '.', `file.relative()` can be an empty string.\n // In that case, we want to match all files under the current directory instead of\n // creating an absolute glob like '/**/*' which would traverse the entire filesystem.\n path.join(file.relative() || '.', '**/*')\n )\n const dirFiles = await glob(dirPattern, {\n ignore: ignorePatterns,\n withFileTypes: true,\n dot: true,\n cwd: contextPath,\n })\n dirFiles.forEach((f) => files.set(f.fullpath(), f))\n } else {\n // For files, just add the file\n files.set(file.fullpath(), file)\n }\n }\n\n return Array.from(files.values()).sort()\n}\n\n/**\n * Calculate a hash of files being copied to detect changes for cache invalidation.\n * The hash includes file content, metadata (mode, size), and relative paths.\n * Note: uid, gid, and mtime are excluded to ensure stable hashes across environments.\n *\n * @param src Source path pattern for files to copy\n * @param dest Destination path where files will be copied\n * @param contextPath Base directory for resolving relative paths\n * @param ignorePatterns Glob patterns to ignore\n * @param resolveSymlinks Whether to resolve symbolic links when hashing\n * @param stackTrace Optional stack trace for error reporting\n * @returns Hex string hash of all files\n * @throws Error if no files match the source pattern\n */\nexport async function calculateFilesHash(\n src: string,\n dest: string,\n contextPath: string,\n ignorePatterns: string[],\n resolveSymlinks: boolean,\n stackTrace: string | undefined\n): Promise<string> {\n const srcPath = path.join(contextPath, src)\n const hash = crypto.createHash('sha256')\n const content = `COPY ${src} ${dest}`\n\n hash.update(content)\n\n const files = await getAllFilesInPath(src, contextPath, ignorePatterns, true)\n\n if (files.length === 0) {\n const error = new Error(`No files found in ${srcPath}`)\n if (stackTrace) {\n error.stack = stackTrace\n }\n throw error\n }\n\n // Hash stats - only include stable metadata (mode, size)\n // Exclude uid, gid, and mtime to ensure consistent hashes across environments\n const hashStats = (stats: fs.Stats) => {\n hash.update(stats.mode.toString())\n hash.update(stats.size.toString())\n }\n\n // Process files recursively\n for (const file of files) {\n // Add a relative path to hash calculation\n const relativePath = file.relativePosix()\n hash.update(relativePath)\n\n // Add stat information to hash calculation\n if (file.isSymbolicLink()) {\n // If the symlink is broken, it will return undefined, otherwise it will return a stats object of the target\n const stats = fs.statSync(file.fullpath(), { throwIfNoEntry: false })\n const shouldFollow =\n resolveSymlinks && (stats?.isFile() || stats?.isDirectory())\n\n if (!shouldFollow) {\n const stats = fs.lstatSync(file.fullpath())\n\n hashStats(stats)\n\n const content = fs.readlinkSync(file.fullpath())\n hash.update(content)\n\n continue\n }\n }\n\n const stats = fs.statSync(file.fullpath())\n hashStats(stats)\n\n // Add file content to hash calculation\n if (stats.isFile()) {\n const content = fs.readFileSync(file.fullpath())\n hash.update(new Uint8Array(content))\n }\n }\n\n return hash.digest('hex')\n}\n\n/**\n * Get the caller's stack trace frame at a specific depth.\n *\n * @param depth The depth of the stack trace to retrieve\n * - Levels: caller (e.g., TemplateBase.fromImage) > original caller (e.g., user's template file)\n * @returns The caller frame as a string, or undefined if not available\n */\nexport function getCallerFrame(depth: number): string | undefined {\n const stackTrace = new Error().stack\n if (!stackTrace) {\n return\n }\n\n const lines = stackTrace.split('\\n').slice(1) // Skip the this function (getCallerFrame)\n if (lines.length < depth + 1) {\n return\n }\n\n return lines.slice(depth).join('\\n')\n}\n\n// adopted from https://github.com/sindresorhus/callsites\nexport function callsites(depth: number): NodeJS.CallSite[] {\n const _originalPrepareStackTrace = Error.prepareStackTrace\n try {\n let result: NodeJS.CallSite[] = []\n Error.prepareStackTrace = (_, callSites) => {\n const callSitesWithoutCurrent = callSites.slice(depth)\n result = callSitesWithoutCurrent\n return callSitesWithoutCurrent\n }\n\n new Error().stack\n return result\n } finally {\n Error.prepareStackTrace = _originalPrepareStackTrace\n }\n}\n\n/**\n * Get the directory of the caller at a specific stack depth.\n *\n * @param depth The depth of the stack trace\n * @returns The caller's directory path, or undefined if not available\n */\nexport function getCallerDirectory(depth: number): string | undefined {\n // +1 depth to skip this function (getCallerDirectory)\n const callSites = callsites(depth + 1)\n if (callSites.length === 0) {\n return undefined\n }\n\n let fileName = callSites[0].getFileName()\n if (!fileName) {\n return undefined\n }\n\n // Handle file:// URLs returned by getFileName() in ESM modules\n if (fileName.startsWith('file:')) {\n // we use the dynamic import to avoid bundling node:url for browser compatibility\n // getCallerDirectory method is not called in the browser\n const { fileURLToPath } =\n dynamicRequire<typeof import('node:url')>('node:url')\n fileName = fileURLToPath(fileName)\n }\n\n return path.dirname(fileName)\n}\n\n/**\n * Convert a numeric file mode to a zero-padded octal string.\n *\n * @param mode File mode as a number (e.g., 493 for 0o755)\n * @returns Zero-padded 4-digit octal string (e.g., \"0755\")\n *\n * @example\n * ```ts\n * padOctal(0o755) // Returns \"0755\"\n * padOctal(0o644) // Returns \"0644\"\n * ```\n */\nexport function padOctal(mode: number): string {\n return mode.toString(8).padStart(4, '0')\n}\n\n/**\n * Create a compressed tar stream of files matching a pattern.\n *\n * @param fileName Glob pattern for files to include\n * @param fileContextPath Base directory for resolving file paths\n * @param ignorePatterns Ignore patterns to exclude from the archive\n * @param resolveSymlinks Whether to follow symbolic links\n * @returns A readable stream of the gzipped tar archive\n */\nexport async function tarFileStream(\n fileName: string,\n fileContextPath: string,\n ignorePatterns: string[],\n resolveSymlinks: boolean\n) {\n const { create } = await dynamicImport<typeof import('tar')>('tar')\n\n const allFiles = await getAllFilesInPath(\n fileName,\n fileContextPath,\n ignorePatterns,\n true\n )\n\n const filePaths = allFiles.map((file) => file.relativePosix())\n\n // gzip.portable ensures deterministic gzip header without affecting file modes\n return create(\n {\n gzip: true,\n cwd: fileContextPath,\n follow: resolveSymlinks,\n noDirRecurse: true,\n },\n filePaths\n )\n}\n\n/**\n * Create a tar stream for upload using chunked transfer encoding.\n *\n * @param fileName Glob pattern for files to include\n * @param fileContextPath Base directory for resolving file paths\n * @param resolveSymlinks Whether to follow symbolic links\n * @returns A readable stream of the gzipped tar archive\n */\nexport async function tarFileStreamUpload(\n fileName: string,\n fileContextPath: string,\n ignorePatterns: string[],\n resolveSymlinks: boolean\n) {\n return tarFileStream(\n fileName,\n fileContextPath,\n ignorePatterns,\n resolveSymlinks\n )\n}\n\n/**\n * Get the array index for a build step based on its name.\n *\n * Special steps:\n * - BASE_STEP_NAME: Returns 0 (first step)\n * - FINALIZE_STEP_NAME: Returns the last index\n * - Numeric strings: Converted to number\n *\n * @param step Build step name or number as string\n * @param stackTracesLength Total number of stack traces (used for FINALIZE_STEP_NAME)\n * @returns Index for the build step\n */\nexport function getBuildStepIndex(\n step: string,\n stackTracesLength: number\n): number {\n if (step === BASE_STEP_NAME) {\n return 0\n }\n\n if (step === FINALIZE_STEP_NAME) {\n return stackTracesLength - 1\n }\n\n return Number(step)\n}\n\n/**\n * Read GCP service account JSON from a file or object.\n *\n * @param contextPath Base directory for resolving relative file paths\n * @param pathOrContent Either a path to a JSON file or a service account object\n * @returns Service account JSON as a string\n */\nexport function readGCPServiceAccountJSON(\n contextPath: string,\n pathOrContent: string | object\n): string {\n if (typeof pathOrContent === 'string') {\n return fs.readFileSync(path.join(contextPath, pathOrContent), 'utf-8')\n }\n return JSON.stringify(pathOrContent)\n}\n","import { ApiClient, handleApiError, paths, components } from '../api'\nimport { dynamicImport, stripAnsi } from '../utils'\nimport { BuildError, FileUploadError, TemplateError } from '../errors'\nimport { LogEntry } from './logger'\nimport { getBuildStepIndex, tarFileStreamUpload } from './utils'\nimport {\n BuildStatusReason,\n RegistryConfig,\n TemplateBuildStatus,\n TemplateBuildStatusResponse,\n TemplateTag,\n TemplateTagInfo,\n} from './types'\n\ntype RequestBuildInput = {\n name: string\n tags?: string[]\n cpuCount: number\n memoryMB: number\n}\n\ntype GetFileUploadLinkInput = {\n templateID: string\n filesHash: string\n}\n\ntype TriggerBuildInput = {\n templateID: string\n buildID: string\n template: TriggerBuildTemplate\n}\n\ntype GetBuildStatusInput = {\n templateID: string\n buildID: string\n logsOffset?: number\n}\n\ntype CheckAliasExistsInput = {\n alias: string\n}\n\ntype ApiBuildStatusResponse =\n paths['/templates/{templateID}/builds/{buildID}/status']['get']['responses']['200']['content']['application/json']\n\nexport type TriggerBuildTemplate =\n Omit<\n paths['/v2/templates/{templateID}/builds/{buildID}']['post']['requestBody']['content']['application/json'],\n 'fromImageRegistry'\n > & {\n fromImageRegistry?: RegistryConfig\n preBootScript?: string\n }\n\nexport async function requestBuild(\n client: ApiClient,\n { name, tags, cpuCount, memoryMB }: RequestBuildInput\n) {\n const requestBuildRes = await client.api.POST('/v3/templates', {\n body: {\n name,\n tags,\n cpuCount,\n memoryMB,\n },\n })\n\n const error = handleApiError(requestBuildRes, BuildError)\n if (error) {\n throw error\n }\n\n if (!requestBuildRes.data) {\n throw new BuildError('Failed to request build')\n }\n\n return requestBuildRes.data\n}\n\nexport async function getFileUploadLink(\n client: ApiClient,\n { templateID, filesHash }: GetFileUploadLinkInput,\n stackTrace?: string\n) {\n const fileUploadLinkRes = await client.api.GET(\n '/templates/{templateID}/files/{hash}',\n {\n params: {\n path: {\n templateID,\n hash: filesHash,\n },\n },\n }\n )\n\n const error = handleApiError(fileUploadLinkRes, FileUploadError, stackTrace)\n if (error) {\n throw error\n }\n\n if (!fileUploadLinkRes.data) {\n throw new FileUploadError('Failed to get file upload link', stackTrace)\n }\n\n return fileUploadLinkRes.data\n}\n\nexport async function uploadFile(\n options: {\n fileName: string\n fileContextPath: string\n url: string\n ignorePatterns: string[]\n resolveSymlinks: boolean\n },\n stackTrace: string | undefined\n) {\n const { fileName, url, fileContextPath, ignorePatterns, resolveSymlinks } =\n options\n try {\n const uploadStream = await tarFileStreamUpload(\n fileName,\n fileContextPath,\n ignorePatterns,\n resolveSymlinks\n )\n\n // Buffer the archive before uploading so fetch sets Content-Length.\n // S3 presigned PUT URLs reject Transfer-Encoding: chunked with 501\n // NotImplemented, which is what Node's fetch falls back to when the\n // body is a Readable without a known length. See ppio-dev/ppio#1243.\n // The Python SDK takes the same approach (build_api.py:upload_file).\n // Dynamically import so the browser bundle doesn't pull in node:stream.\n // tar's Pack extends Minipass and is iterable as AsyncIterable<Buffer> at\n // runtime, but the cli's tsconfig (preserveSymlinks) doesn't surface that\n // through the type chain — cast via unknown.\n const { buffer } = await dynamicImport<\n typeof import('node:stream/consumers')\n >('node:stream/consumers')\n const uploadBody = await buffer(\n uploadStream as unknown as AsyncIterable<Buffer>\n )\n\n const res = await fetch(url, {\n method: 'PUT',\n body: uploadBody as unknown as BodyInit,\n })\n\n if (!res.ok) {\n throw new FileUploadError(\n `Failed to upload file: ${res.statusText}`,\n stackTrace\n )\n }\n } catch (error) {\n if (error instanceof FileUploadError) {\n throw error\n }\n throw new FileUploadError(`Failed to upload file: ${error}`, stackTrace)\n }\n}\n\nexport async function triggerBuild(\n client: ApiClient,\n { templateID, buildID, template }: TriggerBuildInput\n) {\n const triggerBuildRes = await client.api.POST(\n '/v2/templates/{templateID}/builds/{buildID}',\n {\n params: {\n path: {\n templateID,\n buildID,\n },\n },\n body: template as paths['/v2/templates/{templateID}/builds/{buildID}']['post']['requestBody']['content']['application/json'],\n }\n )\n\n const error = handleApiError(triggerBuildRes, BuildError)\n if (error) {\n throw error\n }\n}\n\nfunction mapLogEntry(\n entry: ApiBuildStatusResponse['logEntries'][number]\n): LogEntry {\n return new LogEntry(new Date(entry.timestamp), entry.level, entry.message)\n}\n\nfunction mapBuildStatusReason(\n reason: ApiBuildStatusResponse['reason']\n): BuildStatusReason | undefined {\n if (!reason) {\n return undefined\n }\n return {\n message: reason.message,\n step: reason.step,\n logEntries: (reason.logEntries ?? []).map(mapLogEntry),\n }\n}\n\nexport async function getBuildStatus(\n client: ApiClient,\n { templateID, buildID, logsOffset }: GetBuildStatusInput\n): Promise<TemplateBuildStatusResponse> {\n const buildStatusRes = await client.api.GET(\n '/templates/{templateID}/builds/{buildID}/status',\n {\n params: {\n path: {\n templateID,\n buildID,\n },\n query: {\n logsOffset,\n },\n },\n }\n )\n\n const error = handleApiError(buildStatusRes, BuildError)\n if (error) {\n throw error\n }\n\n if (!buildStatusRes.data) {\n throw new BuildError('Failed to get build status')\n }\n\n return {\n buildID: buildStatusRes.data.buildID,\n templateID: buildStatusRes.data.templateID,\n status: buildStatusRes.data.status,\n logEntries: buildStatusRes.data.logEntries.map(mapLogEntry),\n logs: buildStatusRes.data.logs,\n reason: mapBuildStatusReason(buildStatusRes.data.reason),\n }\n}\n\nexport async function checkAliasExists(\n client: ApiClient,\n { alias }: CheckAliasExistsInput\n): Promise<boolean> {\n const aliasRes = await client.api.GET('/templates/aliases/{alias}', {\n params: {\n path: {\n alias,\n },\n },\n })\n\n // If we get a NotFound, the alias doesn't exist\n if (aliasRes.response.status === 404) {\n return false\n }\n\n // If we get a Forbidden, alias exists, but you are not owner\n if (aliasRes.response.status === 403) {\n return true\n }\n\n // Handle other errors\n const error = handleApiError(aliasRes, TemplateError)\n if (error) {\n throw error\n }\n\n // If we get Ok with data, you are owner and the alias exists\n return aliasRes.data !== undefined\n}\n\nexport async function waitForBuildFinish(\n client: ApiClient,\n {\n templateID,\n buildID,\n onBuildLogs,\n logsRefreshFrequency,\n stackTraces,\n }: {\n templateID: string\n buildID: string\n onBuildLogs?: (logEntry: LogEntry) => void\n logsRefreshFrequency: number\n stackTraces: (string | undefined)[]\n }\n): Promise<void> {\n let logsOffset = 0\n let status: TemplateBuildStatus = 'building'\n\n while (status === 'building' || status === 'waiting') {\n const buildStatus = await getBuildStatus(client, {\n templateID,\n buildID,\n logsOffset,\n })\n\n logsOffset += buildStatus.logEntries.length\n\n buildStatus.logEntries.forEach((logEntry) =>\n onBuildLogs?.(\n new LogEntry(\n logEntry.timestamp,\n logEntry.level,\n stripAnsi(logEntry.message)\n )\n )\n )\n\n status = buildStatus.status\n switch (status) {\n case 'ready': {\n return\n }\n case 'waiting': {\n break\n }\n case 'error': {\n let stackError: string | undefined\n if (buildStatus.reason?.step !== undefined) {\n const step = getBuildStepIndex(\n buildStatus.reason.step,\n stackTraces.length\n )\n stackError = stackTraces[step]\n }\n\n throw new BuildError(\n buildStatus?.reason?.message ?? 'Unknown error',\n stackError\n )\n }\n }\n\n // Wait for a short period before checking the status again\n await new Promise((resolve) => setTimeout(resolve, logsRefreshFrequency))\n }\n\n throw new BuildError('Unknown build error occurred.')\n}\n\nexport async function assignTags(\n client: ApiClient,\n { targetName, tags }: { targetName: string; tags: string[] }\n): Promise<TemplateTagInfo> {\n const res = await client.api.POST('/templates/tags', {\n body: { target: targetName, tags },\n })\n\n const error = handleApiError(res, TemplateError)\n if (error) {\n throw error\n }\n\n if (!res.data) {\n throw new TemplateError('Failed to assign tags')\n }\n\n return {\n buildId: res.data.buildID,\n tags: res.data.tags,\n }\n}\n\nexport async function removeTags(\n client: ApiClient,\n { name, tags }: { name: string; tags: string[] }\n): Promise<void> {\n const res = await client.api.DELETE('/templates/tags', {\n body: { name, tags },\n })\n\n const error = handleApiError(res, TemplateError)\n if (error) {\n throw error\n }\n}\n\nexport async function getTemplateTags(\n client: ApiClient,\n { templateID }: { templateID: string }\n): Promise<TemplateTag[]> {\n const res = await client.api.GET('/templates/{templateID}/tags', {\n params: {\n path: {\n templateID,\n },\n },\n })\n\n const error = handleApiError(res, TemplateError)\n if (error) {\n throw error\n }\n\n if (!res.data) {\n throw new TemplateError('Failed to get template tags')\n }\n\n return res.data.map((item: components['schemas']['TemplateTag']) => ({\n tag: item.tag,\n buildId: item.buildID,\n createdAt: new Date(item.createdAt),\n }))\n}\n","/**\n * Class for ready check commands.\n */\nexport class ReadyCmd {\n private cmd: string\n\n constructor(cmd: string) {\n this.cmd = cmd\n }\n\n getCmd(): string {\n return this.cmd\n }\n}\n\n/**\n * Wait for a port to be listening.\n * Uses `ss` command to check if a port is open and listening.\n *\n * @param port Port number to wait for\n * @returns ReadyCmd that checks for the port\n *\n * @example\n * ```ts\n * import { Template, waitForPort } from 'ppio-sandbox'\n *\n * const template = Template()\n * .fromPythonImage()\n * .setStartCmd('python -m http.server 8000', waitForPort(8000))\n * ```\n */\nexport function waitForPort(port: number): ReadyCmd {\n const cmd = `ss -tuln | grep :${port}`\n return new ReadyCmd(cmd)\n}\n\n/**\n * Wait for a URL to return a specific HTTP status code.\n * Uses `curl` to make HTTP requests and check the response status.\n *\n * @param url URL to check (e.g., 'http://localhost:3000/health')\n * @param statusCode Expected HTTP status code (default: 200)\n * @returns ReadyCmd that checks the URL\n *\n * @example\n * ```ts\n * import { Template, waitForURL } from 'ppio-sandbox'\n *\n * const template = Template()\n * .fromNodeImage()\n * .setStartCmd('npm start', waitForURL('http://localhost:3000/health'))\n * ```\n */\nexport function waitForURL(url: string, statusCode: number = 200): ReadyCmd {\n const cmd = `curl -s -o /dev/null -w \"%{http_code}\" ${url} | grep -q \"${statusCode}\"`\n return new ReadyCmd(cmd)\n}\n\n/**\n * Wait for a process with a specific name to be running.\n * Uses `pgrep` to check if a process exists.\n *\n * @param processName Name of the process to wait for\n * @returns ReadyCmd that checks for the process\n *\n * @example\n * ```ts\n * import { Template, waitForProcess } from 'ppio-sandbox'\n *\n * const template = Template()\n * .fromBaseImage()\n * .setStartCmd('./my-daemon', waitForProcess('my-daemon'))\n * ```\n */\nexport function waitForProcess(processName: string): ReadyCmd {\n const cmd = `pgrep ${processName} > /dev/null`\n return new ReadyCmd(cmd)\n}\n\n/**\n * Wait for a file to exist.\n * Uses shell test command to check file existence.\n *\n * @param filename Path to the file to wait for\n * @returns ReadyCmd that checks for the file\n *\n * @example\n * ```ts\n * import { Template, waitForFile } from 'ppio-sandbox'\n *\n * const template = Template()\n * .fromBaseImage()\n * .setStartCmd('./init.sh', waitForFile('/tmp/ready'))\n * ```\n */\nexport function waitForFile(filename: string): ReadyCmd {\n const cmd = `[ -f ${filename} ]`\n return new ReadyCmd(cmd)\n}\n\n/**\n * Wait for a specified timeout before considering the sandbox ready.\n * Uses `sleep` command to wait for a fixed duration.\n *\n * @param timeout Time to wait in milliseconds (minimum: 1000ms / 1 second)\n * @returns ReadyCmd that waits for the specified duration\n *\n * @example\n * ```ts\n * import { Template, waitForTimeout } from 'ppio-sandbox'\n *\n * const template = Template()\n * .fromNodeImage()\n * .setStartCmd('npm start', waitForTimeout(5000)) // Wait 5 seconds\n * ```\n */\nexport function waitForTimeout(timeout: number): ReadyCmd {\n // convert to seconds, but ensure minimum of 1 second\n const seconds = Math.max(1, Math.floor(timeout / 1000))\n const cmd = `sleep ${seconds}`\n return new ReadyCmd(cmd)\n}\n","import { CopyItem } from './types'\nimport {\n Argument,\n DockerfileParser,\n Instruction as DockerfileInstruction,\n ModifiableInstruction,\n} from 'dockerfile-ast'\nimport fs from 'node:fs'\nimport { ReadyCmd, waitForTimeout } from './readycmd'\n\nexport interface DockerfileParseResult {\n baseImage: string\n}\n\ninterface DockerfileFinalParserInterface {}\n\nexport interface DockerfileParserInterface {\n setWorkdir(workdir: string): DockerfileParserInterface\n setUser(user: string): DockerfileParserInterface\n setEnvs(envs: Record<string, string>): DockerfileParserInterface\n runCmd(\n commandOrCommands: string | string[],\n options?: { user?: string }\n ): DockerfileParserInterface\n copy(\n src: string,\n dest: string,\n options?: { forceUpload?: true; user?: string; mode?: number }\n ): DockerfileParserInterface\n copyItems(\n items: CopyItem[],\n options?: { forceUpload?: true; user?: string; mode?: number }\n ): DockerfileParserInterface\n setStartCmd(\n startCommand: string,\n readyCommand: string | ReadyCmd\n ): DockerfileFinalParserInterface\n}\n\n/**\n * Parse a Dockerfile and convert it to Template SDK format\n *\n * @param dockerfileContentOrPath Either the Dockerfile content as a string,\n * or a path to a Dockerfile file\n * @param templateBuilder Interface providing template builder methods\n * @returns Parsed Dockerfile result with base image and instructions\n */\nexport function parseDockerfile(\n dockerfileContentOrPath: string,\n templateBuilder: DockerfileParserInterface\n): DockerfileParseResult {\n // Check if input is a file path that exists\n let dockerfileContent: string\n try {\n if (\n fs.existsSync(dockerfileContentOrPath) &&\n fs.statSync(dockerfileContentOrPath).isFile()\n ) {\n // Read the file content\n dockerfileContent = fs.readFileSync(dockerfileContentOrPath, 'utf-8')\n } else {\n // Treat as content directly\n dockerfileContent = dockerfileContentOrPath\n }\n } catch {\n // If there's any error checking the file, treat as content\n dockerfileContent = dockerfileContentOrPath\n }\n\n const dockerfile = DockerfileParser.parse(dockerfileContent)\n const instructions = dockerfile.getInstructions()\n\n // Check for multi-stage builds\n const fromInstructions = instructions.filter(\n (instruction) => instruction.getKeyword() === 'FROM'\n )\n\n if (fromInstructions.length > 1) {\n throw new Error('Multi-stage Dockerfiles are not supported')\n }\n\n if (fromInstructions.length === 0) {\n throw new Error('Dockerfile must contain a FROM instruction')\n }\n\n // Set the base image from the first FROM instruction\n const fromInstruction = fromInstructions[0]\n const argumentsData = fromInstruction.getArguments()\n let baseImage = 'ppio-sandbox/base' // default fallback\n let userChanged = false\n let workdirChanged = false\n if (argumentsData && argumentsData.length > 0) {\n baseImage = argumentsData[0].getValue()\n }\n\n // Set the user and workdir to the Docker defaults\n templateBuilder.setUser('root')\n templateBuilder.setWorkdir('/')\n\n // Process all other instructions\n for (const instruction of instructions) {\n const keyword = instruction.getKeyword()\n\n switch (keyword) {\n case 'FROM':\n // Already handled above\n break\n\n case 'RUN':\n handleRunInstruction(instruction, templateBuilder)\n break\n\n case 'COPY':\n case 'ADD':\n handleCopyInstruction(\n instruction as ModifiableInstruction,\n templateBuilder\n )\n break\n\n case 'WORKDIR':\n handleWorkdirInstruction(instruction, templateBuilder)\n workdirChanged = true\n break\n\n case 'USER':\n handleUserInstruction(instruction, templateBuilder)\n userChanged = true\n break\n\n case 'ENV':\n case 'ARG':\n handleEnvInstruction(instruction, templateBuilder)\n break\n\n case 'EXPOSE':\n // EXPOSE is not directly supported in our SDK, so we'll skip it\n break\n\n case 'VOLUME':\n // VOLUME is not directly supported in our SDK, so we'll skip it\n break\n\n case 'CMD':\n case 'ENTRYPOINT':\n handleCmdEntrypointInstruction(instruction, templateBuilder)\n break\n\n default:\n console.warn(`Unsupported instruction: ${keyword}`)\n break\n }\n }\n\n // Set the user and workdir to the PPIO sandbox defaults\n if (!userChanged) {\n templateBuilder.setUser('user')\n }\n if (!workdirChanged) {\n templateBuilder.setWorkdir('/home/user')\n }\n\n return {\n baseImage,\n }\n}\n\nfunction handleRunInstruction(\n instruction: DockerfileInstruction,\n templateBuilder: DockerfileParserInterface\n): void {\n const argumentsData = instruction.getArguments()\n if (argumentsData && argumentsData.length > 0) {\n const command = argumentsData\n .map((arg: Argument) => arg.getValue())\n .join(' ')\n templateBuilder.runCmd(command)\n }\n}\n\nfunction handleCopyInstruction(\n instruction: ModifiableInstruction,\n templateBuilder: DockerfileParserInterface\n): void {\n const argumentsData = instruction.getArguments()\n if (argumentsData && argumentsData.length >= 2) {\n const src = argumentsData[0].getValue()\n const dest = argumentsData[argumentsData.length - 1].getValue()\n\n let user: string | undefined\n const flags = instruction.getFlags()\n const chownFlag = flags.find((flag) => flag.getName() === 'chown')\n if (chownFlag) {\n user = chownFlag.getValue() ?? undefined\n }\n\n templateBuilder.copy(src, dest, { user })\n }\n}\n\nfunction handleWorkdirInstruction(\n instruction: DockerfileInstruction,\n templateBuilder: DockerfileParserInterface\n): void {\n const argumentsData = instruction.getArguments()\n if (argumentsData && argumentsData.length > 0) {\n const workdir = argumentsData[0].getValue()\n templateBuilder.setWorkdir(workdir)\n }\n}\n\nfunction handleUserInstruction(\n instruction: DockerfileInstruction,\n templateBuilder: DockerfileParserInterface\n): void {\n const argumentsData = instruction.getArguments()\n if (argumentsData && argumentsData.length > 0) {\n const user = argumentsData[0].getValue()\n templateBuilder.setUser(user)\n }\n}\n\nfunction handleEnvInstruction(\n instruction: DockerfileInstruction,\n templateBuilder: DockerfileParserInterface\n): void {\n const argumentsData = instruction.getArguments()\n const keyword = instruction.getKeyword()\n\n if (argumentsData && argumentsData.length >= 1) {\n const envVars: Record<string, string> = {}\n\n if (argumentsData.length === 2) {\n // ENV key value format OR multiple key=value pairs (from line continuation)\n const firstArg = argumentsData[0].getValue()\n const secondArg = argumentsData[1].getValue()\n\n // Check if both arguments contain '=' (multiple key=value pairs)\n if (firstArg.includes('=') && secondArg.includes('=')) {\n // Both are key=value pairs (line continuation)\n for (const arg of argumentsData) {\n const envString = arg.getValue()\n const equalIndex = envString.indexOf('=')\n if (equalIndex > 0) {\n const key = envString.substring(0, equalIndex)\n const value = envString.substring(equalIndex + 1)\n envVars[key] = value\n }\n }\n } else {\n // Traditional ENV key value format\n envVars[firstArg] = secondArg\n }\n } else if (argumentsData.length === 1) {\n // ENV/ARG key=value format (single argument) or ARG key (without default)\n const envString = argumentsData[0].getValue()\n\n // Check if it's a simple key=value or just a key (for ARG without default)\n const equalIndex = envString.indexOf('=')\n if (equalIndex > 0) {\n const key = envString.substring(0, equalIndex)\n const value = envString.substring(equalIndex + 1)\n envVars[key] = value\n } else if (keyword === 'ARG' && envString.trim()) {\n // ARG without default value - set as empty ENV\n const key = envString.trim()\n envVars[key] = ''\n }\n } else {\n // Multiple arguments (from line continuation with backslashes)\n for (const arg of argumentsData) {\n const envString = arg.getValue()\n const equalIndex = envString.indexOf('=')\n if (equalIndex > 0) {\n const key = envString.substring(0, equalIndex)\n const value = envString.substring(equalIndex + 1)\n envVars[key] = value\n } else if (keyword === 'ARG') {\n // ARG without default value\n const key = envString\n envVars[key] = ''\n }\n }\n }\n\n // Call setEnvs once with all environment variables from this instruction\n if (Object.keys(envVars).length > 0) {\n templateBuilder.setEnvs(envVars)\n }\n }\n}\n\nfunction handleCmdEntrypointInstruction(\n instruction: DockerfileInstruction,\n templateBuilder: DockerfileParserInterface\n): void {\n const argumentsData = instruction.getArguments()\n if (argumentsData && argumentsData.length > 0) {\n let command = argumentsData.map((arg: Argument) => arg.getValue()).join(' ')\n\n try {\n const parsedCommand = JSON.parse(command)\n if (Array.isArray(parsedCommand)) {\n command = parsedCommand.join(' ')\n }\n } catch {\n // Do nothing\n }\n\n templateBuilder.setStartCmd(command, waitForTimeout(20_000))\n }\n}\n","/**\n * Make a template's environment variables visible at *runtime*, not just at\n * build time.\n *\n * `setEnvs` records an ENV instruction. Two things were measured about it, and\n * neither reports an error:\n *\n * **The build's ENV does not reach the sandbox.** Template\n * `wu9ol3m99x5h2d9y63rc`, built from a Dockerfile declaring\n * `ENV PATH=/opt/venv/bin:$PATH`:\n *\n * build log [builder 4/8] ENV PATH /opt/venv/bin:$PATH (layer created)\n * sandbox PATH=/usr/local/bin:/usr/bin:/bin:... (venv absent)\n * which python3 /usr/local/bin/python3 (not the venv)\n * import requests -> exit 1 (installed, unreachable)\n *\n * A login shell and `sh -c` saw the same thing, and `/etc/environment` was empty.\n * So the environment is written to the filesystem, where the sandbox's own shell\n * startup reads it back — twice, because neither file covers both cases:\n *\n * /etc/profile.d/99-image-env.sh sourced by login shells\n * /etc/environment read by pam_env, covers non-login execution\n *\n * **The platform silently ignores an ENV instruction for PATH.** Template\n * `s9kk2s1dhfgcqmf94785` set `PATH=/opt/venv/bin:$PATH` and `PROBE_LITERAL=x` in\n * one instruction; the next build step reported\n *\n * SEEN_PATH=[/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin]\n * SEEN_LITERAL=[x]\n *\n * — PATH untouched, not even holding a literal `$PATH`, while the other variable\n * took effect. So the value cannot simply be read back out of the build\n * environment: for PATH, that reads the platform's own value, and PATH is where a\n * venv or conda prefix lives — the case this exists to fix.\n *\n * The declared string is therefore carried into the build and its variable\n * references are expanded *there*, against the build's live environment. Writing\n * the declared string verbatim instead breaks the build outright:\n *\n * [builder 9/9] RUN ... export PATH='/opt/venv/bin:$PATH' ... (step ok)\n * [finalize] Build failed: configuration script failed: exit status 127\n *\n * PATH held a literal `$PATH`, so the next command was not found.\n */\n\n/** Where the login-shell copy is written. */\nexport const PROFILE_PATH = '/etc/profile.d/99-image-env.sh'\n\n/** Where the pam_env copy is written. */\nexport const ENVIRONMENT_PATH = '/etc/environment'\n\n/** Where the generated script is staged during the build. */\nexport const SCRIPT_PATH = '/tmp/.ppio-image-env.sh'\n\n/**\n * True when no shell can set this name, so it cannot be restored at runtime.\n *\n * `export A B='v'` is two statements, so carrying over a name with a space in it\n * would set something other than what was asked for. Reported rather than\n * written, so a caller is not told a variable survived when it did not.\n */\nexport function unsettableEnvName(name: string): boolean {\n return !/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)\n}\n\n/**\n * Split names into the ones that can be restored and the ones that cannot.\n * `skipped` is sorted, so callers report a stable order.\n */\nexport function partitionEnvNames(names: string[]): {\n usable: string[]\n skipped: string[]\n} {\n const usable: string[] = []\n const skipped: string[] = []\n for (const name of names) {\n if (unsettableEnvName(name)) {\n skipped.push(name)\n } else {\n usable.push(name)\n }\n }\n return { usable, skipped: skipped.sort() }\n}\n\n/**\n * Quote a declared value for the generated script, leaving `$VAR` live.\n *\n * The value is emitted inside a double-quoted shell word, so `$VAR` and `${VAR}`\n * expand against the build's environment — which is the whole point, since\n * `/opt/venv/bin:$PATH` only means anything there.\n *\n * Backticks, `$(`, `\"` and `\\` are escaped, so a value cannot run a command or\n * end the word. Command substitution is deliberately *not* honoured: a value is\n * data, and `PATH=$(curl …)` executing during someone else's build is not a\n * feature. Docker expands only variable references here too.\n */\nexport function expandableDoubleQuote(value: string): string {\n const escaped = value\n // Backslash first, so the escapes added below are not re-escaped.\n .split('\\\\')\n .join('\\\\\\\\')\n .split('\"')\n .join('\\\\\"')\n .split('`')\n .join('\\\\`')\n // `$(` would be command substitution; `$NAME` and `${NAME}` stay live.\n .replace(/\\$\\(/g, '\\\\$(')\n return `\"${escaped}\"`\n}\n\n/**\n * The shell script that writes both files.\n *\n * Runs during the build. For each variable it expands the declared value against\n * the build's live environment, then writes the result to both files — quoted\n * *differently*, which is why this is not one write:\n *\n * - profile.d is sourced by a shell, so the expanded value is single-quoted with\n * `'` rewritten as `'\\''`. Single quotes are the only shell quoting with no\n * escapes inside them, so this is exact for any byte — including `$`, backticks\n * and backslashes, all of which `\"…\"` would interpret. Writing `KEY=\"value\"`\n * here is a green that hides a wrong value: the build succeeds, the sandbox\n * boots, and `JAVA_OPTS=-Xmx2g -Dname=\"my app\"` holds something else.\n * - /etc/environment is read by pam_env, which has no escape syntax at all. It\n * strips one leading and one trailing quote without scanning the interior, so\n * the value is written bare; and it is line-based with no continuation, so a\n * value containing a newline cannot be represented there and is left to the\n * profile.d copy rather than written as a corrupt second entry.\n *\n * @param envs Settable names mapped to their declared values — see\n * {@link partitionEnvNames}.\n */\nexport function envFilesScript(envs: Record<string, string>): string {\n const lines = [\n 'set -e',\n `: > ${PROFILE_PATH}`,\n `: > ${ENVIRONMENT_PATH}`,\n ]\n\n for (const [name, declared] of Object.entries(envs)) {\n lines.push(\n // Expand the declared value here, against the build's own environment.\n `v=${expandableDoubleQuote(declared)}`,\n // Export it before moving on, so a later value can reference this one --\n // `ENV VIRTUAL_ENV=/opt/venv PYTHONPATH=$VIRTUAL_ENV/lib` is ordinary, and\n // the platform's own ENV handling cannot be relied on for it (it ignores\n // PATH entirely). Without this the reference expanded to empty.\n `export ${name}=\"$v\"`,\n // profile.d: single-quoted, with any embedded quote closed and reopened.\n `printf \"export ${name}='%s'\\\\n\" \"$(printf '%s' \"$v\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\")\" >> ${PROFILE_PATH}`,\n // pam_env: bare, and only when it can represent the value at all.\n 'case \"$v\" in',\n ' *\\'\"\\'*) v= ;;',\n 'esac',\n `[ -n \"$v\" ] && [ \"$(printf '%s' \"$v\" | wc -l)\" -eq 0 ] && printf '${name}=%s\\\\n' \"$v\" >> ${ENVIRONMENT_PATH}`,\n // `[ ... ] &&` above exits non-zero when the value is skipped, which would\n // abort the script under `set -e`.\n 'true'\n )\n }\n\n lines.push(`chmod 0644 ${PROFILE_PATH} ${ENVIRONMENT_PATH}`)\n return lines.join('\\n')\n}\n\n/**\n * The single build command that stages and runs {@link envFilesScript}.\n *\n * base64 rather than passing the script inline: it travels through the build's\n * own shell before anything reads it, and base64 is the only form that survives\n * that leg intact regardless of what it contains.\n *\n * Must run as root: the Dockerfile parser leaves the build as `user` (measured:\n * `[builder 7/8] USER user`), which cannot write to `/etc`.\n *\n * `command` is null when no name can be carried over, so the caller adds no\n * layer at all.\n */\nexport function envFilesCommand(envs: Record<string, string>): {\n command: string | null\n skipped: string[]\n} {\n const { usable, skipped } = partitionEnvNames(Object.keys(envs))\n if (usable.length === 0) {\n return { command: null, skipped }\n }\n\n const script = envFilesScript(\n Object.fromEntries(usable.map(name => [name, envs[name]]))\n )\n const b64 = Buffer.from(script, 'utf8').toString('base64')\n\n return {\n command: [\n `echo ${b64} | base64 -d > ${SCRIPT_PATH}`,\n `sh ${SCRIPT_PATH}`,\n `rm -f ${SCRIPT_PATH}`,\n ].join(' && '),\n skipped,\n }\n}\n","/**\n * Read a Docker image's declared ENV, WORKDIR, ENTRYPOINT and CMD from its\n * registry config blob.\n *\n * Why this exists: `docker run <image>` inherits everything the image declares in\n * its config — PATH, LANG, VIRTUAL_ENV, CONDA_PREFIX, JAVA_HOME, and whatever the\n * language ecosystem stores there. A sandbox started from a template built with\n * `fromImage` does not, because nothing ever read the image's config: `fromImage`\n * records the reference and the platform pulls the image server-side. So an image\n * that \"works in Docker\" can land in a sandbox where the preinstalled toolchain\n * is not on PATH at all, with no error that points at the cause.\n *\n * Anonymous registry v2 pulls, falling back to Docker Hub for bare names. Results\n * are cached per process. Every failure is reported as data rather than thrown —\n * a template without the restored config still builds, and one unreachable\n * registry must not abort a batch conversion.\n */\n\n/**\n * The host `parseImageRef` normalises every Docker Hub spelling to, and the\n * prefix it gives a bare name.\n */\nconst HUB_HOST = 'registry-1.docker.io'\nconst HUB_OFFICIAL = 'library/'\n\nconst MANIFEST_TYPES = [\n 'application/vnd.docker.distribution.manifest.v2+json',\n 'application/vnd.oci.image.manifest.v1+json',\n 'application/vnd.docker.distribution.manifest.list.v2+json',\n 'application/vnd.oci.image.index.v1+json',\n].join(', ')\n\n/**\n * ENV vars describing the *build* machine, or that would fight the sandbox's own\n * runtime setup. Carrying these over can actively break a sandbox, so they never\n * do — even when the image declares them.\n */\nconst SKIP_ENV = new Set([\n 'HOSTNAME',\n 'HOME',\n 'PWD',\n 'OLDPWD',\n 'SHLVL',\n '_',\n 'TERM',\n])\n\n/**\n * Registry failures worth another attempt. 429 is the one that matters: Docker\n * Hub's anonymous pull limit is per-IP, so converting a hundred images hits it\n * routinely — and the consequence is not a failed conversion but a template built\n * with no restored ENV, which is the one thing this exists to prevent.\n */\nconst RETRY_STATUS = new Set([429, 500, 502, 503, 504])\nexport const READ_ATTEMPTS = 3\n\n/**\n * Backoff base, in milliseconds. Overridable only so a unit test can assert the\n * retry behaviour without spending the real three seconds waiting for it.\n */\nlet backoffBaseMs = 1000\n\n/** Set the backoff base; returns a function restoring the previous value. */\nexport function setRetryBackoffForTests(ms: number): () => void {\n const previous = backoffBaseMs\n backoffBaseMs = ms\n return () => {\n backoffBaseMs = previous\n }\n}\n\n/**\n * Whether the platform can provision a sandbox from this image's base OS.\n *\n * Measured, one template per image:\n *\n * debian:12, ubuntu:22.04, python:3.11-slim, redis:7 ready\n * alpine:3.20, nginx:alpine, node:20-alpine provisioning exit 1\n * busybox:1.36, fedora:40, rockylinux:9 provisioning exit 1\n *\n * So the line is not \"Debian\": Ubuntu builds. It is apt and glibc -- the platform\n * installs systemd during provisioning, which needs both.\n *\n * The check is deliberately one-directional. `ubuntu:22.04` builds and its config\n * blob carries *no* signal at all (one `ADD`, no labels, no distro-specific ENV),\n * while `rockylinux:9`'s blob is shaped identically and does not build. Absence of\n * evidence therefore cannot mean \"unsupported\" without rejecting images that\n * work, so this reports only what it can positively identify and says nothing\n * about the rest. The build is the backstop for those.\n *\n * apt evidence wins over everything: an image assembled from an Alpine stage but\n * based on Debian has both, and the apt one is what provisioning needs.\n *\n * @returns the unsupported family, or null when the image looks fine or unknown.\n */\nexport function unsupportedBase(blob: {\n history?: { created_by?: string }[]\n config?: { Labels?: Record<string, string>; Env?: string[] }\n}): string | null {\n const history = (blob.history ?? []).map(h => h.created_by ?? '').join('\\n')\n const labels = Object.keys(blob.config?.Labels ?? {}).join(' ')\n const env = (blob.config?.Env ?? []).join(' ')\n\n // `debian.sh` is how the official Debian rootfs is built; `debuerreotype` is\n // its older name. A bare mention of \"debian\" is not evidence: busybox:1.36\n // reports \"BusyBox 1.36.1 (glibc), Debian 13\" and cannot be provisioned.\n if (/debian\\.sh|debuerreotype|apt-get|apt install|dpkg/i.test(history)) {\n return null\n }\n\n const families: [RegExp, string][] = [\n [/alpine-minirootfs|etc\\/alpine-release|apk add|apk --no-cache/i, 'Alpine (musl)'],\n [/^BusyBox /im, 'BusyBox'],\n [/microdnf|dnf install|yum install|rpm -i/i, 'RPM-based (Fedora/RHEL/Rocky)'],\n [/pacman -S/i, 'Arch'],\n [/zypper|KIWI /i, 'SUSE'],\n ]\n for (const [pattern, family] of families) {\n if (pattern.test(history)) {\n return family\n }\n }\n\n // Signals outside the history: openSUSE stamps its own label namespace, and\n // Fedora sets DISTTAG in ENV. Both images build nothing here.\n if (/org\\.opensuse\\./.test(labels)) {\n return 'SUSE'\n }\n if (/DISTTAG=f\\d+container/.test(env)) {\n return 'RPM-based (Fedora/RHEL/Rocky)'\n }\n\n return null\n}\n\n/** What the image declares, plus why the read failed when it did. */\nexport type ImageConfig = {\n env: Record<string, string>\n workdir: string | null\n entrypoint: string[]\n cmd: string[]\n /** Set when the config could not be read at all. */\n error?: string\n /**\n * Set when the image's base OS cannot be provisioned -- see\n * {@link unsupportedBase}. Kept apart from `unusable`: the reference is fine\n * and the image exists, it is the base the platform cannot boot.\n */\n unsupportedBase?: string\n /**\n * Set when the image was read fine and still cannot be used here — no\n * linux/amd64 variant, or the reference names nothing. Distinct from `error`\n * because a retry cannot change it and the build would fail for the same\n * reason after minutes of pulling.\n */\n unusable?: string\n}\n\nexport type RegistryCredentials = { username: string; password: string }\n\nconst CACHE = new Map<string, ImageConfig>()\n\n/** A caller-owned copy, so one caller's edit cannot reach the next. */\nfunction copyConfig(config: ImageConfig): ImageConfig {\n return {\n ...config,\n env: { ...config.env },\n entrypoint: [...config.entrypoint],\n cmd: [...config.cmd],\n }\n}\n\nfunction emptyConfig(): ImageConfig {\n return { env: {}, workdir: null, entrypoint: [], cmd: [] }\n}\n\n/**\n * Split an image reference into its registry host, repository and tag or digest.\n *\n * 'nginx' -> registry-1.docker.io, library/nginx, latest\n * 'org/app:1.2' -> registry-1.docker.io, org/app, 1.2\n * 'ghcr.io/org/app:dev' -> ghcr.io, org/app, dev\n * 'reg:5000/app@sha256:ab…' -> reg:5000, app, sha256:ab…\n */\nexport function parseImageRef(image: string): {\n host: string\n repository: string\n reference: string\n} {\n let ref = image.startsWith('docker.io/')\n ? image.slice('docker.io/'.length)\n : image\n\n let host = HUB_HOST\n const slash = ref.indexOf('/')\n if (slash !== -1) {\n const head = ref.slice(0, slash)\n // A first segment is a registry host only if it looks like one: it contains a\n // dot or a port, or is literally localhost. Otherwise it is a Hub org.\n if (head.includes('.') || head.includes(':') || head === 'localhost') {\n host = head\n ref = ref.slice(slash + 1)\n }\n }\n\n let repository: string\n let reference: string\n const at = ref.indexOf('@')\n if (at !== -1) {\n // Digest pins take precedence: '@' can only introduce a digest.\n repository = ref.slice(0, at)\n reference = ref.slice(at + 1)\n } else {\n const colon = ref.lastIndexOf(':')\n // A ':' inside the final path segment is a tag; one before a '/' is a port.\n if (colon !== -1 && !ref.slice(colon + 1).includes('/')) {\n repository = ref.slice(0, colon)\n reference = ref.slice(colon + 1)\n } else {\n repository = ref\n reference = 'latest'\n }\n }\n\n if (host === HUB_HOST && !repository.includes('/')) {\n repository = `${HUB_OFFICIAL}${repository}`\n }\n\n return { host, repository, reference }\n}\n\n/** An HTTP status carried alongside the failure, so callers can act on it. */\nclass RegistryHttpError extends Error {\n constructor(\n readonly status: number,\n readonly retryAfter: string | null,\n message: string\n ) {\n super(message)\n this.name = 'RegistryHttpError'\n }\n}\n\n/** The image was read successfully and cannot be used here. */\nclass UnusableImageError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'UnusableImageError'\n }\n}\n\n/** Seconds to wait, from the response's Retry-After when it is usable. */\nfunction retryDelayMs(error: unknown, fallbackMs: number): number {\n const raw = error instanceof RegistryHttpError ? error.retryAfter : null\n const seconds = raw === null ? NaN : Number(raw)\n // Retry-After may be an HTTP-date rather than seconds; not worth parsing.\n if (!Number.isFinite(seconds)) {\n return fallbackMs\n }\n return Math.min(seconds * backoffBaseMs, 10_000)\n}\n\n/**\n * GET with a short retry on the statuses a registry uses for \"later\".\n *\n * Deliberately not a general retry: 401/403/404 are answers, not hiccups, and\n * retrying them spends a batch run's time to reach the same conclusion.\n */\nasync function registryGet(\n url: string,\n headers: Record<string, string>,\n options?: { attempts?: number; timeoutMs?: number }\n): Promise<unknown> {\n const attempts = options?.attempts ?? READ_ATTEMPTS\n const timeoutMs = options?.timeoutMs ?? 30_000\n let last: unknown\n\n for (let attempt = 0; attempt < attempts; attempt++) {\n if (attempt > 0) {\n await new Promise(resolve =>\n setTimeout(resolve, retryDelayMs(last, 2 ** (attempt - 1) * backoffBaseMs))\n )\n }\n\n try {\n const response = await fetch(url, {\n headers,\n signal: AbortSignal.timeout(timeoutMs),\n })\n\n if (!response.ok) {\n const error = new RegistryHttpError(\n response.status,\n response.headers.get('retry-after'),\n `HTTP ${response.status} ${response.statusText}`\n )\n if (!RETRY_STATUS.has(response.status)) {\n throw error\n }\n last = error\n continue\n }\n\n return await response.json()\n } catch (error) {\n if (error instanceof RegistryHttpError && !RETRY_STATUS.has(error.status)) {\n throw error\n }\n // Network-level flakiness has no status to inspect; same treatment.\n last = error\n }\n }\n\n throw last\n}\n\n/**\n * Best-effort registry token.\n *\n * Public Docker Hub and GHCR both hand out anonymous pull tokens; private\n * registries take the basic auth through unchanged.\n */\nasync function authHeaders(\n host: string,\n repository: string,\n credentials?: RegistryCredentials\n): Promise<Record<string, string>> {\n const headers: Record<string, string> = { Accept: MANIFEST_TYPES }\n\n if (credentials) {\n const basic = Buffer.from(\n `${credentials.username}:${credentials.password}`,\n 'utf8'\n ).toString('base64')\n headers.Authorization = `Basic ${basic}`\n }\n\n const services: Record<string, [string, string]> = {\n 'registry-1.docker.io': ['auth.docker.io', 'registry.docker.io'],\n 'ghcr.io': ['ghcr.io', 'ghcr.io'],\n }\n const service = services[host]\n if (!service) {\n return headers\n }\n\n const [authHost, serviceName] = service\n const url =\n `https://${authHost}/token?service=${serviceName}` +\n `&scope=repository:${repository}:pull`\n\n try {\n const tokenHeaders: Record<string, string> = headers.Authorization\n ? { Authorization: headers.Authorization }\n : {}\n // One attempt: a failure here falls back to anonymous or basic auth, and the\n // read below has its own retries. Retrying both turned one offline registry\n // into six requests and six seconds of backoff.\n const body = (await registryGet(url, tokenHeaders, {\n attempts: 1,\n })) as { token?: string }\n if (body.token) {\n headers.Authorization = `Bearer ${body.token}`\n }\n } catch {\n // Anonymous or basic auth may already suffice; the read below decides.\n }\n\n return headers\n}\n\nfunction platformName(entry: {\n platform?: { os?: string; architecture?: string; variant?: string }\n}): string {\n const p = entry.platform ?? {}\n const base = `${p.os ?? '?'}/${p.architecture ?? '?'}`\n return p.variant ? `${base}/${p.variant}` : base\n}\n\ntype ManifestIndex = {\n manifests?: {\n digest: string\n platform?: { os?: string; architecture?: string; variant?: string }\n }[]\n}\n\n/**\n * The linux/amd64 digest from a multi-arch index.\n *\n * Throws naming the platforms the image *does* offer. No amd64 variant means the\n * build will fail too, so this is worth catching before a build is spent.\n */\nfunction pickAmd64(index: ManifestIndex, image: string): string {\n for (const entry of index.manifests ?? []) {\n if (\n entry.platform?.architecture === 'amd64' &&\n entry.platform?.os === 'linux'\n ) {\n return entry.digest\n }\n }\n\n // 'unknown/unknown' entries are attestation manifests, not usable images;\n // listing them would suggest a platform that could be selected.\n const offered = [\n ...new Set(\n (index.manifests ?? [])\n .filter(e => e.platform?.os !== 'unknown')\n .map(platformName)\n ),\n ].sort()\n\n throw new UnusableImageError(\n `${image} has no linux/amd64 variant` +\n (offered.length > 0 ? ` (offers ${offered.join(', ')})` : '') +\n '; sandboxes are amd64, so this image cannot be used'\n )\n}\n\n/**\n * Turn a registry failure into the config's `error` / `unusable` fields.\n *\n * The two Docker Hub cases below are measured, and the codes are the opposite way\n * round from the obvious guess:\n *\n * library/redis 200\n * library/REDIS, library/nGiNx 404 (case-folds onto a real repo)\n * library/nginx:no-such-tag 404 (repo exists, tag does not)\n * library/nginxx, library/nginx-typo 401 (no such repo at all)\n *\n * So 404 means \"the repository resolved, the thing you named did not\", and a\n * plain typo — much the commoner mistake — answers 401.\n */\nfunction describeFailure(\n error: unknown,\n image: string,\n host: string,\n repository: string,\n authenticated: boolean\n): ImageConfig {\n const empty = emptyConfig()\n\n if (error instanceof UnusableImageError) {\n return { ...empty, error: error.message, unusable: error.message }\n }\n\n if (error instanceof RegistryHttpError) {\n if (error.status === 404) {\n const reason =\n `no such image: the registry has no '${image}' (HTTP 404). ` +\n 'Check spelling and case — repository names are case-sensitive'\n return { ...empty, error: reason, unusable: reason }\n }\n\n // 401 is normally ambiguous: an absent repository and a private one answer\n // byte-identically. Docker Hub's official `library/` namespace is the\n // exception — it has no private repositories, so nothing there can 401 for a\n // reason other than not existing.\n //\n // Unless credentials were supplied. Then the rejected credential is itself a\n // reason for a 401, and the ambiguity is back: measured, `redis:7` with a wrong\n // password and `rediss:7` with a right one answer identically. So neither cause\n // can be named alone -- blaming the spelling of a correct name, or the\n // credentials behind a correct one, each sends the reader to the wrong place --\n // and this is not marked `unusable`: a corrected password makes the very same\n // reference work, which is the one thing `unusable` promises it will not.\n if (\n error.status === 401 &&\n host === HUB_HOST &&\n repository.startsWith(HUB_OFFICIAL)\n ) {\n if (authenticated) {\n return {\n ...empty,\n error:\n `cannot read '${image}' (HTTP 401): either the credentials were ` +\n 'rejected or there is no such image. Both answer alike here, so ' +\n 'check the spelling and the case of the name, then the credentials',\n }\n }\n const reason =\n `no such image: Docker Hub has no official image '${image}' ` +\n '(HTTP 401). The `library/` namespace has no private repositories, so ' +\n 'this is a typo rather than a permissions problem'\n return { ...empty, error: reason, unusable: reason }\n }\n\n return { ...empty, error: `${error.name}: ${error.message}` }\n }\n\n const message = error instanceof Error ? error.message : String(error)\n return { ...empty, error: message }\n}\n\n/**\n * Read what an image declares.\n *\n * Every field is present even on failure, so a caller never has to distinguish\n * \"no config\" from \"read failed\" structurally — `error` says which it was.\n * Nothing is thrown: restoring an image's config is best-effort, and a batch\n * conversion must not stop because one registry was unreachable.\n */\nexport async function fetchImageConfig(\n image: string,\n credentials?: RegistryCredentials\n): Promise<ImageConfig> {\n // Keyed on the credentials too. An anonymous and an authenticated read of the\n // same private repository are different questions with different answers, so\n // caching only the reference would hand a caller who supplied credentials the\n // anonymous 401 from an earlier call.\n const key = JSON.stringify([\n image,\n credentials?.username ?? null,\n credentials?.password ?? null,\n ])\n const cached = CACHE.get(key)\n if (cached) {\n return copyConfig(cached)\n }\n\n const { host, repository, reference } = parseImageRef(image)\n let result: ImageConfig\n\n try {\n const auth = await authHeaders(host, repository, credentials)\n const base = `https://${host}/v2/${repository}`\n\n let manifest = (await registryGet(\n `${base}/manifests/${reference}`,\n auth\n )) as ManifestIndex & { config?: { digest: string } }\n\n if (manifest.manifests) {\n // Multi-arch index: resolve to the linux/amd64 manifest.\n const digest = pickAmd64(manifest, image)\n manifest = (await registryGet(`${base}/manifests/${digest}`, auth)) as {\n config?: { digest: string }\n }\n }\n\n if (!manifest.config?.digest) {\n throw new Error(`${image}: manifest names no config blob`)\n }\n\n const blob = (await registryGet(\n `${base}/blobs/${manifest.config.digest}`,\n auth\n )) as {\n history?: { created_by?: string }[]\n config?: {\n Env?: string[]\n WorkingDir?: string\n Entrypoint?: string[]\n Cmd?: string[]\n Labels?: Record<string, string>\n }\n }\n\n const declared = blob.config ?? {}\n const env: Record<string, string> = {}\n for (const entry of declared.Env ?? []) {\n const eq = entry.indexOf('=')\n if (eq === -1) {\n continue\n }\n const name = entry.slice(0, eq)\n if (!SKIP_ENV.has(name)) {\n env[name] = entry.slice(eq + 1)\n }\n }\n\n const badBase = unsupportedBase(blob)\n result = {\n env,\n workdir: declared.WorkingDir || null,\n entrypoint: declared.Entrypoint ?? [],\n cmd: declared.Cmd ?? [],\n ...(badBase ? { unsupportedBase: badBase } : {}),\n }\n } catch (error) {\n result = describeFailure(\n error,\n image,\n host,\n repository,\n credentials !== undefined\n )\n }\n\n CACHE.set(key, result)\n return copyConfig(result)\n}\n\n/**\n * Docker's effective command: ENTRYPOINT followed by CMD, joined with spaces.\n *\n * This matches what the SDK's own Dockerfile parser does with the array form, so\n * `docker-entrypoint.sh redis-server` is reproduced exactly. The naive join loses\n * shell quoting for an argument that itself contains spaces (`['sh','-c','echo a\n * b']` becomes `sh -c echo a b`), which is the parser's limitation too; matching\n * it keeps the two build paths in agreement rather than inventing a third\n * behaviour.\n *\n * Returns null when the image declares neither, so the sandbox is left as a bare\n * shell rather than handed an empty command.\n */\nexport function effectiveStartCmd(\n entrypoint: string[],\n cmd: string[]\n): string | null {\n const parts = [...entrypoint, ...cmd]\n return parts.length > 0 ? parts.map(shellQuoteArg).join(' ') : null\n}\n\n/** Quote one exec-form argument for the shell string used by the build API. */\nfunction shellQuoteArg(value: string): string {\n return /^[A-Za-z0-9_./:@%+=,-]+$/.test(value)\n ? value\n : `'${value.replace(/'/g, `'\\\\''`)}'`\n}\n\n/** Drop the process-wide read cache. Exposed for tests. */\nexport function clearImageConfigCache(): void {\n CACHE.clear()\n}\n","import { ReadyCmd } from './readycmd'\nimport type { PathLike } from 'node:fs'\nimport type { LogEntry } from './logger'\nimport type { McpServer } from '../sandbox/mcp'\nimport { ConnectionOpts } from '../connectionConfig'\n\n/**\n * Options for creating a new template.\n */\nexport type TemplateOptions = {\n /**\n * Path to the directory containing files to be copied into the template.\n * @default Current directory from template location\n */\n fileContextPath?: PathLike\n /**\n * Array of glob patterns to ignore when copying files.\n */\n fileIgnorePatterns?: string[]\n}\n\n/**\n * Basic options for building a template.\n */\nexport type BasicBuildOptions = {\n /**\n * Alias name for the template.\n * @deprecated Use the `name` parameter of `Template.build()` instead.\n */\n alias: string\n /**\n * Tags to assign to the template build.\n */\n tags?: string[]\n /**\n * Number of CPUs allocated to the sandbox.\n * @default 2\n */\n cpuCount?: number\n /**\n * Amount of memory in MB allocated to the sandbox.\n * @default 1024\n */\n memoryMB?: number\n /**\n * If true, skips cache and forces a complete rebuild.\n * @default false\n */\n skipCache?: boolean\n /**\n * Callback function to receive build logs during the build process.\n */\n onBuildLogs?: (logEntry: LogEntry) => void\n}\n\n/**\n * Options for building a template with authentication.\n */\nexport type BuildOptions = ConnectionOpts & BasicBuildOptions\n\n/**\n * Information about a built template.\n */\nexport type BuildInfo = {\n /**\n * First alias from the build (for backward compatibility).\n * @deprecated Use `name` instead.\n */\n alias: string\n /**\n * Name of the template.\n */\n name: string\n /**\n * Tags assigned to this build.\n */\n tags: string[]\n /**\n * Template identifier.\n */\n templateId: string\n /**\n * Build identifier.\n */\n buildId: string\n}\n\n/**\n * Options for getting build status.\n */\nexport type GetBuildStatusOptions = ConnectionOpts & { logsOffset?: number }\n\n/**\n * Status of a template build.\n */\nexport type TemplateBuildStatus = 'building' | 'waiting' | 'ready' | 'error'\n\n/**\n * Reason for the current build status (typically for errors).\n */\nexport type BuildStatusReason = {\n /**\n * Message with the status reason.\n */\n message: string\n /**\n * Step that failed.\n */\n step?: string\n /**\n * Log entries related to the status reason.\n */\n logEntries: LogEntry[]\n}\n\n/**\n * Response from getting build status.\n */\nexport type TemplateBuildStatusResponse = {\n /**\n * Build identifier.\n */\n buildID: string\n /**\n * Template identifier.\n */\n templateID: string\n /**\n * Current status of the build.\n */\n status: TemplateBuildStatus\n /**\n * Build log entries.\n */\n logEntries: LogEntry[]\n /**\n * Build logs (raw strings).\n * @deprecated Use `logEntries` instead.\n */\n logs: string[]\n /**\n * Reason for the current status (typically for errors).\n */\n reason?: BuildStatusReason\n}\n\n/**\n * Information about assigned template tags.\n */\nexport type TemplateTagInfo = {\n /**\n * Build identifier associated with this tag.\n */\n buildId: string\n /**\n * Assigned tags of the template.\n */\n tags: string[]\n}\n\n/**\n * Detailed information about a single template tag.\n */\nexport type TemplateTag = {\n /**\n * Name of the tag.\n */\n tag: string\n /**\n * Build identifier associated with this tag.\n */\n buildId: string\n /**\n * When this tag was assigned.\n */\n createdAt: Date\n}\n\nexport type TemplateType = 'template_build' | 'snapshot_template'\n\nexport type TemplateListOpts = ConnectionOpts & {\n teamID?: string\n templateType?: TemplateType\n page?: number\n limit?: number\n}\n\nexport type TemplateListOptions = TemplateListOpts\n\nexport type TemplateInfo = {\n templateId: string\n buildId: string\n aliases?: string[]\n templateType?: TemplateType\n buildCount: number\n cpuCount: number\n memoryMB: number\n diskSizeMB: number\n spawnCount: number\n envdVersion: string\n public: boolean\n metadata?: Record<string, string>\n createdAt: Date\n updatedAt: Date\n lastSpawnedAt: Date | null\n createdBy?: unknown\n originSandboxID?: string | null\n}\n\nexport type TemplateListResponse = {\n templates: TemplateInfo[]\n total: number\n page: number\n limit: number\n totalPages: number\n}\n\nexport type TemplateDeleteOpts = ConnectionOpts\n\n/**\n * Types of instructions that can be used in a template.\n */\nexport enum InstructionType {\n COPY = 'COPY',\n ENV = 'ENV',\n RUN = 'RUN',\n WORKDIR = 'WORKDIR',\n USER = 'USER',\n}\n\n/**\n * Represents a single instruction in the template build process.\n */\nexport type Instruction = {\n type: InstructionType\n args: string[]\n force: boolean\n forceUpload?: true\n filesHash?: string\n resolveSymlinks?: boolean\n}\n\n/**\n * Configuration for a single file/directory copy operation.\n */\nexport type CopyItem = {\n src: PathLike | PathLike[]\n dest: PathLike\n forceUpload?: true\n user?: string\n mode?: number\n resolveSymlinks?: boolean\n}\n\n/**\n * MCP server names that can be installed.\n */\nexport type McpServerName = keyof McpServer\n\n/**\n * Initial state of a template builder.\n * Use one of these methods to specify the base image or template to start from.\n */\nexport interface TemplateFromImage {\n /**\n * Start from a Debian-based Docker image.\n * @param variant Debian variant (default: 'stable')\n *\n * @example\n * ```ts\n * Template().fromDebianImage('bookworm')\n * ```\n */\n fromDebianImage(variant?: string): TemplateBuilder\n\n /**\n * Start from an Ubuntu-based Docker image.\n * @param variant Ubuntu variant (default: 'latest')\n *\n * @example\n * ```ts\n * Template().fromUbuntuImage('24.04')\n * ```\n */\n fromUbuntuImage(variant?: string): TemplateBuilder\n\n /**\n * Start from a Python-based Docker image.\n * @param version Python version (default: '3')\n *\n * @example\n * ```ts\n * Template().fromPythonImage('3')\n * ```\n */\n fromPythonImage(version?: string): TemplateBuilder\n\n /**\n * Start from a Node.js-based Docker image.\n * @param variant Node.js variant (default: 'lts')\n *\n * @example\n * ```ts\n * Template().fromNodeImage('24')\n * ```\n */\n fromNodeImage(variant?: string): TemplateBuilder\n\n /**\n * Start from a Bun-based Docker image.\n * @param variant Bun variant (default: 'latest')\n *\n * @example\n * ```ts\n * Template().fromBunImage('1.3')\n * ```\n */\n fromBunImage(variant?: string): TemplateBuilder\n\n /**\n * Start from PPIO sandbox's default base image (ppio-sandbox/base:latest).\n *\n * @example\n * ```ts\n * Template().fromBaseImage()\n * ```\n */\n fromBaseImage(): TemplateBuilder\n\n /**\n * Start from a custom Docker image.\n * @param baseImage Docker image name\n * @param credentials Optional credentials for private registries\n *\n * @example\n * ```ts\n * Template().fromImage('python:3')\n *\n * // With credentials (optional)\n * Template().fromImage('myregistry.com/myimage:latest', {\n * username: 'user',\n * password: 'pass'\n * })\n * ```\n */\n fromImage(\n baseImage: string,\n credentials?: { username: string; password: string },\n options?: {\n /**\n * Restore what the image declares — its ENV, WORKDIR and effective command\n * (ENTRYPOINT + CMD) — so the sandbox behaves like `docker run <image>`.\n * Defaults to true.\n *\n * Without it, none of the three reach the sandbox: the platform pulls the\n * image server-side and nothing reads its config, so an image whose\n * toolchain lives behind its own `PATH` (a virtualenv, a conda prefix)\n * starts fine and then behaves as though the toolchain were never\n * installed.\n *\n * Anything you set on the builder wins over what the image declared. Pass\n * false to take the image as a bare base — for instance to get an\n * interactive environment rather than the image's own process.\n */\n inheritConfig?: boolean\n }\n ): TemplateBuilder\n\n /**\n * Start from an existing PPIO sandbox template.\n * @param template PPIO sandbox template ID or alias\n *\n * @example\n * ```ts\n * Template().fromTemplate('my-base-template')\n * ```\n */\n fromTemplate(template: string): TemplateBuilder\n\n /**\n * Parse a Dockerfile and convert it to Template SDK format.\n * @param dockerfileContentOrPath Dockerfile content or path\n *\n * @example\n * ```ts\n * Template().fromDockerfile('Dockerfile')\n * Template().fromDockerfile('FROM python:3\\nRUN pip install numpy')\n * ```\n */\n fromDockerfile(dockerfileContentOrPath: string): TemplateBuilder\n\n /**\n * Start from a Docker image in AWS ECR.\n * @param image Full ECR image path\n * @param credentials AWS credentials\n *\n * @example\n * ```ts\n * Template().fromAWSRegistry(\n * '123456789.dkr.ecr.us-west-2.amazonaws.com/myimage:latest',\n * {\n * accessKeyId: 'AKIA...',\n * secretAccessKey: '...',\n * region: 'us-west-2'\n * }\n * )\n * ```\n */\n fromAWSRegistry(\n image: string,\n credentials: {\n accessKeyId: string\n secretAccessKey: string\n region: string\n }\n ): TemplateBuilder\n\n /**\n * Start from a Docker image in Google Container Registry.\n * @param image Full GCR/GAR image path\n * @param credentials GCP service account credentials\n *\n * @example\n * ```ts\n * Template().fromGCPRegistry(\n * 'gcr.io/myproject/myimage:latest',\n * { serviceAccountJSON: 'path/to/service-account.json' }\n * )\n * ```\n */\n fromGCPRegistry(\n image: string,\n credentials: {\n serviceAccountJSON: object | string\n }\n ): TemplateBuilder\n\n /**\n * Start from a Docker image in Oracle Cloud Infrastructure Registry.\n * @param image Full OCI registry image path\n * @param credentials OCI credentials\n *\n * @example\n * ```ts\n * Template().fromOCIRegistry(\n * 'iad.ocir.io/mytenancy/myimage:latest',\n * {\n * tenancyOcid: 'ocid1.tenancy...',\n * userOcid: 'ocid1.user...',\n * fingerprint: '...',\n * privateKey: '-----BEGIN PRIVATE KEY-----...',\n * region: 'us-ashburn-1'\n * }\n * )\n * ```\n */\n fromOCIRegistry(\n image: string,\n credentials: {\n tenancyOcid: string\n userOcid: string\n fingerprint: string\n privateKey: string\n region: string\n }\n ): TemplateBuilder\n\n /**\n * Start from a Docker image in Huawei Cloud SWR.\n * @param image Full Huawei Cloud SWR image path\n * @param credentials Huawei Cloud access key credentials\n *\n * @example\n * ```ts\n * Template().fromHuaweiCloudRegistry(\n * 'swr.cn-north-4.myhuaweicloud.com/myorg/myimage:latest',\n * {\n * accessKeyId: '...',\n * secretAccessKey: '...',\n * region: 'cn-north-4'\n * }\n * )\n * ```\n */\n fromHuaweiCloudRegistry(\n image: string,\n credentials: {\n accessKeyId: string\n secretAccessKey: string\n region: string\n }\n ): TemplateBuilder\n\n /**\n * Skip cache for all subsequent build instructions from this point.\n *\n * @example\n * ```ts\n * Template().skipCache().fromPythonImage('3')\n * ```\n */\n skipCache(): this\n}\n\n/**\n * Main builder state for constructing templates.\n * Provides methods for customizing the template environment.\n */\nexport interface TemplateBuilder {\n /**\n * Copy files or directories into the template.\n * @param src Source path(s)\n * @param dest Destination path\n * @param options Copy options\n *\n * @example\n * ```ts\n * template.copy('requirements.txt', '/home/user/')\n * template.copy(['app.ts', 'config.ts'], '/app/', { mode: 0o755 })\n * ```\n */\n copy(\n src: PathLike | PathLike[],\n dest: PathLike,\n options?: {\n forceUpload?: true\n user?: string\n mode?: number\n resolveSymlinks?: boolean\n }\n ): TemplateBuilder\n\n /**\n * Copy multiple items with individual options.\n * @param items Array of copy items\n *\n * @example\n * ```ts\n * template.copyItems([\n * { src: 'app.ts', dest: '/app/' },\n * { src: 'config.ts', dest: '/app/', mode: 0o644 }\n * ])\n * ```\n */\n copyItems(items: CopyItem[]): TemplateBuilder\n\n /**\n * Remove files or directories.\n * @param path Path(s) to remove\n * @param options Remove options\n *\n * @example\n * ```ts\n * template.remove('/tmp/cache', { recursive: true, force: true })\n * template.remove('/tmp/cache', { recursive: true, force: true, user: 'root' })\n * ```\n */\n remove(\n path: PathLike | PathLike[],\n options?: { force?: boolean; recursive?: boolean; user?: string }\n ): TemplateBuilder\n\n /**\n * Rename or move a file or directory.\n * @param src Source path\n * @param dest Destination path\n * @param options Rename options\n *\n * @example\n * ```ts\n * template.rename('/tmp/old.txt', '/tmp/new.txt')\n * template.rename('/tmp/old.txt', '/tmp/new.txt', { user: 'root' })\n * ```\n */\n rename(\n src: PathLike,\n dest: PathLike,\n options?: { force?: boolean; user?: string }\n ): TemplateBuilder\n\n /**\n * Create directories.\n * @param path Directory path(s)\n * @param options Directory options\n *\n * @example\n * ```ts\n * template.makeDir('/app/data', { mode: 0o755 })\n * template.makeDir(['/app/logs', '/app/cache'])\n * template.makeDir('/app/data', { mode: 0o755, user: 'root' })\n * ```\n */\n makeDir(\n path: PathLike | PathLike[],\n options?: { mode?: number; user?: string }\n ): TemplateBuilder\n\n /**\n * Create a symbolic link.\n * @param src Source path (target)\n * @param dest Destination path (symlink location)\n * @param options Symlink options\n *\n * @example\n * ```ts\n * template.makeSymlink('/usr/bin/python3', '/usr/bin/python')\n * template.makeSymlink('/usr/bin/python3', '/usr/bin/python', { user: 'root' })\n * template.makeSymlink('/usr/bin/python3', '/usr/bin/python', { force: true })\n * ```\n */\n makeSymlink(\n src: PathLike,\n dest: PathLike,\n options?: { user?: string; force?: boolean }\n ): TemplateBuilder\n\n /**\n * Run a shell command.\n * @param command Command string\n * @param options Command options\n *\n * @example\n * ```ts\n * template.runCmd('apt-get update')\n * template.runCmd(['pip install numpy', 'pip install pandas'])\n * template.runCmd('apt-get install vim', { user: 'root' })\n * ```\n */\n runCmd(command: string, options?: { user?: string }): TemplateBuilder\n\n /**\n * Run multiple shell commands.\n * @param commands Array of command strings\n * @param options Command options\n */\n runCmd(commands: string[], options?: { user?: string }): TemplateBuilder\n\n /**\n * Run command(s).\n * @param commandOrCommands Command or commands\n * @param options Command options\n */\n runCmd(\n commandOrCommands: string | string[],\n options?: { user?: string }\n ): TemplateBuilder\n\n /**\n * Set the working directory.\n * @param workdir Working directory path\n *\n * @example\n * ```ts\n * template.setWorkdir('/app')\n * ```\n */\n setWorkdir(workdir: PathLike): TemplateBuilder\n\n /**\n * Set the user for subsequent commands.\n * @param user Username\n *\n * @example\n * ```ts\n * template.setUser('root')\n * ```\n */\n setUser(user: string): TemplateBuilder\n\n /**\n * Install Python packages using pip.\n * @param packages Package name(s) or undefined for current directory\n * @param options Install options\n * @param options.g Install globally as root (default: true). Set to false for user-only installation with --user flag\n *\n * @example\n * ```ts\n * template.pipInstall('numpy') // Installs globally (default)\n * template.pipInstall(['pandas', 'scikit-learn'])\n * template.pipInstall('numpy', { g: false }) // Install for user only\n * template.pipInstall() // Installs from current directory\n * ```\n */\n pipInstall(\n packages?: string | string[],\n options?: { g?: boolean }\n ): TemplateBuilder\n\n /**\n * Install Node.js packages using npm.\n * @param packages Package name(s) or undefined for package.json\n * @param options Install options\n *\n * @example\n * ```ts\n * template.npmInstall('express')\n * template.npmInstall(['lodash', 'axios'])\n * template.npmInstall('tsx', { g: true })\n * template.npmInstall('typescript', { dev: true })\n * template.npmInstall() // Installs from package.json\n * ```\n */\n npmInstall(\n packages?: string | string[],\n options?: { g?: boolean; dev?: boolean }\n ): TemplateBuilder\n /**\n * Install Bun packages using bun.\n * @param packages Package name(s) or undefined for package.json\n * @param options Install options\n *\n * @example\n * ```ts\n * template.bunInstall('express')\n * template.bunInstall(['lodash', 'axios'])\n * template.bunInstall('tsx', { g: true })\n * template.bunInstall('typescript', { dev: true })\n * template.bunInstall() // Installs from package.json\n * ```\n */\n bunInstall(\n packages?: string | string[],\n options?: { g?: boolean; dev?: boolean }\n ): TemplateBuilder\n\n /**\n * Install Debian/Ubuntu packages using apt-get.\n * @param packages Package name(s)\n *\n * @example\n * ```ts\n * template.aptInstall('vim')\n * template.aptInstall(['git', 'curl', 'wget'])\n * template.aptInstall(['vim'], { noInstallRecommends: true })\n * template.aptInstall(['vim'], { fixMissing: true })\n * ```\n */\n aptInstall(\n packages: string | string[],\n options?: { noInstallRecommends?: boolean; fixMissing?: boolean }\n ): TemplateBuilder\n\n /**\n * Install MCP servers using mcp-gateway.\n * Note: Requires a base image with mcp-gateway pre-installed (e.g., mcp-gateway).\n * @param servers MCP server name(s)\n *\n * @throws {Error} If the base template is not mcp-gateway\n * @example\n * ```ts\n * template.addMcpServer('exa')\n * template.addMcpServer(['brave', 'firecrawl', 'duckduckgo'])\n * ```\n */\n addMcpServer(servers: McpServerName | McpServerName[]): TemplateBuilder\n\n /**\n * Clone a Git repository.\n * @param url Repository URL\n * @param path Optional destination path\n * @param options Clone options\n *\n * @example\n * ```ts\n * template.gitClone('https://github.com/user/repo.git', '/app/repo')\n * template.gitClone('https://github.com/user/repo.git', undefined, {\n * branch: 'main',\n * depth: 1\n * })\n * template.gitClone('https://github.com/user/repo.git', '/app/repo', {\n * user: 'root'\n * })\n * ```\n */\n gitClone(\n url: string,\n path?: PathLike,\n options?: { branch?: string; depth?: number; user?: string }\n ): TemplateBuilder\n\n /**\n * Set environment variables.\n * Note: Environment variables defined here are available only during template build.\n * @param envs Environment variables\n *\n * @example\n * ```ts\n * template.setEnvs({ NODE_ENV: 'production', PORT: '8080' })\n * ```\n */\n setEnvs(envs: Record<string, string>): TemplateBuilder\n\n /**\n * Skip cache for all subsequent build instructions from this point.\n *\n * @example\n * ```ts\n * template.skipCache().runCmd('apt-get update')\n * ```\n */\n skipCache(): this\n\n /**\n * Set the start command and ready check.\n * @param startCommand Command to run on startup\n * @param readyCommand Command to check readiness\n *\n * @example\n * ```ts\n * // Using a string command\n * template.setStartCmd(\n * 'node app.js',\n * 'curl http://localhost:8000/health'\n * )\n *\n * // Using ReadyCmd helpers\n * import { waitForPort, waitForURL } from 'ppio-sandbox'\n *\n * template.setStartCmd(\n * 'python -m http.server 8000',\n * waitForPort(8000)\n * )\n *\n * template.setStartCmd(\n * 'npm start',\n * waitForURL('http://localhost:3000/health', 200)\n * )\n * ```\n */\n setStartCmd(\n startCommand: string,\n readyCommand: string | ReadyCmd\n ): TemplateFinal\n\n /**\n * Set or update the ready check command.\n * @param readyCommand Command to check readiness\n *\n * @example\n * ```ts\n * // Using a string command\n * template.setReadyCmd('curl http://localhost:8000/health')\n *\n * // Using ReadyCmd helpers\n * import { waitForPort, waitForFile, waitForProcess } from 'ppio-sandbox'\n *\n * template.setReadyCmd(waitForPort(3000))\n *\n * template.setReadyCmd(waitForFile('/tmp/ready'))\n *\n * template.setReadyCmd(waitForProcess('nginx'))\n * ```\n */\n setReadyCmd(readyCommand: string | ReadyCmd): TemplateFinal\n\n /**\n * Set a patch command that runs during base image provisioning.\n *\n * The command runs at the end of base-image provisioning, before the first\n * systemd boot.\n *\n * @param cmd Shell command to run during base image provisioning.\n */\n setPatchCmd(cmd: string): TemplateBuilder\n\n /**\n * Prebuild a devcontainer from the specified directory.\n * @param devcontainerDirectory Path to the devcontainer directory\n *\n * @example\n * ```ts\n * template\n * .gitClone('https://myrepo.com/project.git', '/my-devcontainer')\n * .betaDevContainerPrebuild('/my-devcontainer')\n * ```\n */\n betaDevContainerPrebuild(devcontainerDirectory: string): TemplateBuilder\n\n /**\n * Start a devcontainer from the specified directory.\n * @param devcontainerDirectory Path to the devcontainer directory\n *\n * @example\n * ```ts\n * template\n * .gitClone('https://myrepo.com/project.git', '/my-devcontainer')\n * .startDevcontainer('/my-devcontainer')\n *\n * // Prebuild and start\n * template\n * .gitClone('https://myrepo.com/project.git', '/my-devcontainer')\n * .betaDevContainerPrebuild('/my-devcontainer')\n * // Other instructions...\n * .betaSetDevContainerStart('/my-devcontainer')\n * ```\n */\n betaSetDevContainerStart(devcontainerDirectory: string): TemplateFinal\n}\n\n/**\n * Final state of a template after start/ready commands are set.\n * The template can only be built in this state.\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface TemplateFinal {}\n\n/**\n * Configuration for a generic Docker registry with basic authentication.\n */\nexport type GenericDockerRegistry = {\n /** Registry type identifier */\n type: 'registry'\n /** Registry username */\n username: string\n /** Registry password */\n password: string\n}\n\n/**\n * Configuration for AWS Elastic Container Registry (ECR).\n */\nexport type AWSRegistry = {\n /** Registry type identifier */\n type: 'aws'\n /** AWS access key ID */\n awsAccessKeyId: string\n /** AWS secret access key */\n awsSecretAccessKey: string\n /** AWS region */\n awsRegion: string\n}\n\n/**\n * Configuration for Google Container Registry (GCR) or Artifact Registry.\n */\nexport type GCPRegistry = {\n /** Registry type identifier */\n type: 'gcp'\n /** Service account JSON as string */\n serviceAccountJson: string\n}\n\n/**\n * Configuration for Oracle Cloud Infrastructure Registry.\n */\nexport type OCIRegistry = {\n /** Registry type identifier */\n type: 'oci'\n /** OCI tenancy OCID */\n tenancyOcid: string\n /** OCI user OCID */\n userOcid: string\n /** API key fingerprint */\n fingerprint: string\n /** API private key PEM */\n privateKey: string\n /** OCI region */\n region: string\n}\n\n/**\n * Configuration for Huawei Cloud Software Repository for Container.\n */\nexport type HuaweiCloudRegistry = {\n /** Registry type identifier */\n type: 'huawei'\n /** Huawei Cloud access key ID */\n accessKeyId: string\n /** Huawei Cloud secret access key */\n secretAccessKey: string\n /** Huawei Cloud region */\n region: string\n}\n\n/**\n * Union type for all supported container registry configurations.\n */\nexport type RegistryConfig =\n | GenericDockerRegistry\n | AWSRegistry\n | GCPRegistry\n | OCIRegistry\n | HuaweiCloudRegistry\n\n/**\n * Type representing a template in any state (builder or final).\n */\nexport type TemplateClass = TemplateBuilder | TemplateFinal\n","import type { PathLike } from 'node:fs'\nimport { ApiClient, handleApiError } from '../api'\nimport type { components } from '../api/schema.gen'\nimport { ConnectionConfig, ConnectionOpts, raiseIfLegacy } from '../connectionConfig'\nimport { BuildError } from '../errors'\nimport { runtime } from '../utils'\nimport {\n assignTags,\n checkAliasExists,\n getTemplateTags,\n removeTags,\n getBuildStatus,\n getFileUploadLink,\n requestBuild,\n triggerBuild,\n TriggerBuildTemplate,\n uploadFile,\n waitForBuildFinish,\n} from './buildApi'\nimport { RESOLVE_SYMLINKS, STACK_TRACE_DEPTH } from './consts'\nimport { parseDockerfile } from './dockerfileParser'\nimport { envFilesCommand } from './envFiles'\nimport { effectiveStartCmd, fetchImageConfig } from './imageConfig'\nimport { LogEntry, LogEntryEnd, LogEntryStart } from './logger'\nimport { ReadyCmd, waitForFile, waitForTimeout } from './readycmd'\nimport {\n BuildInfo,\n BuildOptions,\n CopyItem,\n GetBuildStatusOptions,\n Instruction,\n InstructionType,\n McpServerName,\n RegistryConfig,\n TemplateDeleteOpts,\n TemplateInfo,\n TemplateListOpts,\n TemplateListResponse,\n TemplateBuilder,\n TemplateBuildStatusResponse,\n TemplateClass,\n TemplateFinal,\n TemplateFromImage,\n TemplateOptions,\n TemplateTag,\n TemplateTagInfo,\n} from './types'\nimport {\n calculateFilesHash,\n getCallerDirectory,\n getCallerFrame,\n normalizeBuildArguments,\n padOctal,\n readDockerignore,\n readGCPServiceAccountJSON,\n validateRelativePath,\n} from './utils'\n\nexport class TemplateApi {\n static async getTemplate(\n templateId: string,\n options?: ConnectionOpts\n ): Promise<components['schemas']['TemplateWithBuilds']> {\n const config = new ConnectionConfig(options)\n raiseIfLegacy(config, 'Template.get', BuildError)\n const client = new ApiClient(config)\n const response = await client.api.GET('/templates/{templateID}', {\n params: { path: { templateID: templateId } },\n signal: config.getSignal(options?.requestTimeoutMs),\n })\n const error = handleApiError(response)\n if (error) throw error\n if (!response.data) {\n throw new BuildError('Template details response data is missing')\n }\n return response.data\n }\n\n static async listTemplates(\n options?: TemplateListOpts\n ): Promise<TemplateListResponse> {\n const templateType = options?.templateType ?? 'template_build'\n const page = options?.page ?? 1\n const limit = options?.limit ?? 20\n\n if (!['template_build', 'snapshot_template'].includes(templateType)) {\n throw new Error(\n 'templateType must be either \"template_build\" or \"snapshot_template\"'\n )\n }\n if (page < 1) {\n throw new Error('page must be >= 1')\n }\n if (limit < 1 || limit > 100) {\n throw new Error('limit must be between 1 and 100')\n }\n\n const config = new ConnectionConfig(options)\n const url = new URL(`${config.apiUrl}/v2/templates`)\n if (options?.teamID) {\n url.searchParams.set('teamID', options.teamID)\n }\n url.searchParams.set('template_type', templateType)\n url.searchParams.set('page', String(page))\n url.searchParams.set('limit', String(limit))\n\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n ...config.headers,\n ...(config.apiKey ? { 'X-API-KEY': config.apiKey } : {}),\n ...(config.accessToken\n ? { Authorization: `Bearer ${config.accessToken}` }\n : {}),\n },\n signal: config.getSignal(options?.requestTimeoutMs),\n })\n\n if (!response.ok) {\n throw new Error(`${response.status}: ${await response.text()}`)\n }\n\n const data = await response.json()\n if (!data) {\n throw new Error('Template list response data is missing')\n }\n\n return {\n templates: (data.templates ?? []).map(\n (template: Record<string, any>) => ({\n templateId: template.templateID,\n aliases: template.aliases,\n buildCount: template.buildCount,\n buildId: template.buildID,\n cpuCount: template.cpuCount,\n createdAt: new Date(template.createdAt),\n createdBy: template.createdBy,\n diskSizeMB: template.diskSizeMB,\n envdVersion: template.envdVersion,\n lastSpawnedAt: template.lastSpawnedAt\n ? new Date(template.lastSpawnedAt)\n : null,\n memoryMB: template.memoryMB,\n metadata: template.metadata,\n public: template.public,\n spawnCount: template.spawnCount,\n templateType: template.templateType,\n originSandboxID: template.originSandboxID,\n updatedAt: new Date(template.updatedAt),\n })\n ),\n page: data.page ?? page,\n limit: data.limit ?? limit,\n total: data.total ?? 0,\n totalPages: data.totalPages ?? 0,\n }\n }\n\n static async deleteTemplate(\n templateId: string,\n options?: TemplateDeleteOpts\n ): Promise<boolean> {\n if (!templateId) {\n throw new Error('templateId cannot be empty')\n }\n\n const config = new ConnectionConfig(options)\n const client = new ApiClient(config)\n\n const res = await client.api.DELETE('/templates/{templateID}', {\n params: {\n path: {\n templateID: templateId,\n },\n },\n signal: config.getSignal(options?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404 || res.response.status === 404) {\n return false\n }\n\n const err = handleApiError(res, BuildError)\n if (err) {\n throw err\n }\n\n return true\n }\n}\n\nexport class TemplatePaginator {\n private readonly options?: TemplateListOpts\n private nextPageNumber: number\n private hasNextPage = true\n\n constructor(options?: TemplateListOpts) {\n this.options = options\n this.nextPageNumber = options?.page ?? 1\n }\n\n get hasNext(): boolean {\n return this.hasNextPage\n }\n\n get currentPage(): number {\n return this.nextPageNumber\n }\n\n async nextPage(): Promise<TemplateListResponse> {\n if (!this.hasNextPage) {\n throw new Error('No more pages to fetch')\n }\n\n const response = await TemplateApi.listTemplates({\n ...this.options,\n page: this.nextPageNumber,\n })\n this.hasNextPage = response.page < response.totalPages\n this.nextPageNumber = response.page + 1\n return response\n }\n\n reset(): void {\n this.nextPageNumber = this.options?.page ?? 1\n this.hasNextPage = true\n }\n}\n\n/**\n * Base class for building PPIO sandbox sandbox templates.\n */\nexport class TemplateBase\n implements TemplateFromImage, TemplateBuilder, TemplateFinal\n{\n private defaultBaseImage: string = 'ppio-sandbox/base'\n private baseImage: string | undefined = this.defaultBaseImage\n private baseTemplate: string | undefined = undefined\n private registryConfig: RegistryConfig | undefined = undefined\n private startCmd: string | undefined = undefined\n private readyCmd: string | undefined = undefined\n private patchCmd: string | undefined = undefined\n // Force the whole template to be rebuilt\n private force: boolean = false\n // Force the next layer to be rebuilt\n private forceNextLayer: boolean = false\n private instructions: Instruction[] = []\n // Everything passed to setEnvs, accumulated across calls. The declared value is\n // kept, not the resolved one: `/opt/venv/bin:$PATH` is expanded during the\n // build, since the platform ignores an ENV instruction for PATH and the build's\n // own PATH is therefore not the declared one (see envFiles.ts). Accumulated\n // rather than written per call because the file is written once from the full\n // set -- a per-call write would clobber the previous call's file.\n private envs: Record<string, string> = {}\n // Whether to restore what the base image declares -- see fromImage() and\n // resolveInheritedConfig(). Only meaningful for an image base; a Dockerfile\n // states its own ENV/WORKDIR/CMD, and a template base already carries them.\n private inheritImageConfig: boolean = false\n private imageCredentials: { username: string; password: string } | undefined =\n undefined\n // Why the image's config is missing, when it is. Recorded rather than only\n // logged: build() has a log channel and toJSON() does not, so a dry run or a\n // CLI conversion would otherwise show a clean template that silently lacks the\n // image's PATH -- the exact failure this reading exists to prevent.\n private imageConfigError: string | undefined = undefined\n private imageUnusable: string | undefined = undefined\n private fileContextPath: PathLike =\n runtime === 'browser' ? '.' : (getCallerDirectory(STACK_TRACE_DEPTH) ?? '.')\n private fileIgnorePatterns: string[] = []\n private logsRefreshFrequency: number = 200\n private stackTraces: (string | undefined)[] = []\n private stackTracesEnabled: boolean = true\n private stackTracesOverride: string | undefined = undefined\n\n constructor(options?: TemplateOptions) {\n this.fileContextPath = options?.fileContextPath ?? this.fileContextPath\n this.fileIgnorePatterns =\n options?.fileIgnorePatterns ?? this.fileIgnorePatterns\n }\n\n static list(options?: TemplateListOpts): TemplatePaginator {\n return new TemplatePaginator(options)\n }\n\n /**\n * Convert a template to JSON representation.\n *\n * @param template The template to convert\n * @param computeHashes Whether to compute file hashes for cache invalidation\n * @returns JSON string representation of the template\n */\n static toJSON(\n template: TemplateClass,\n computeHashes: boolean = true\n ): Promise<string> {\n return (template as TemplateBase).toJSON(computeHashes)\n }\n\n /**\n * Convert a template to Dockerfile format.\n * Note: Templates based on other PPIO sandbox templates cannot be converted to Dockerfile.\n *\n * @param template The template to convert\n * @returns Dockerfile string representation\n * @throws Error if the template is based on another PPIO sandbox template\n */\n static toDockerfile(template: TemplateClass): string {\n return (template as TemplateBase).toDockerfile()\n }\n\n /**\n * Build and deploy a template to PPIO sandbox infrastructure.\n *\n * @param template The template to build\n * @param name Template name in 'name' or 'name:tag' format\n * @param options Optional build configuration options\n *\n * @example\n * ```ts\n * const template = Template().fromPythonImage('3')\n *\n * // Build with single tag in name\n * await Template.build(template, 'my-python-env:v1.0')\n *\n * // Build with multiple tags\n * await Template.build(template, 'my-python-env', { tags: ['v1.0', 'stable'] })\n * ```\n */\n static async build(\n template: TemplateClass,\n name: string,\n options?: Omit<BuildOptions, 'alias'>\n ): Promise<BuildInfo>\n /**\n * Build and deploy a template to PPIO sandbox infrastructure.\n *\n * @param template The template to build\n * @param options Build configuration options with alias (deprecated)\n *\n * @deprecated Use the overload with `name` parameter instead.\n * @example\n * ```ts\n * // Deprecated:\n * await Template.build(template, { alias: 'my-python-env' })\n *\n * // Use instead:\n * await Template.build(template, 'my-python-env:v1.0')\n * ```\n */\n static async build(\n template: TemplateClass,\n options: BuildOptions\n ): Promise<BuildInfo>\n static async build(\n template: TemplateClass,\n nameOrOptions: string | BuildOptions,\n options?: Omit<BuildOptions, 'alias'>\n ): Promise<BuildInfo> {\n const { name, buildOptions } = normalizeBuildArguments(\n nameOrOptions,\n options\n )\n\n try {\n buildOptions.onBuildLogs?.(new LogEntryStart(new Date(), 'Build started'))\n const baseTemplate = template as TemplateBase\n\n const config = new ConnectionConfig(buildOptions)\n const client = new ApiClient(config)\n\n const data = await baseTemplate.build(client, name, buildOptions)\n\n buildOptions.onBuildLogs?.(\n new LogEntry(new Date(), 'info', 'Waiting for logs...')\n )\n\n await waitForBuildFinish(client, {\n templateID: data.templateId,\n buildID: data.buildId,\n onBuildLogs: buildOptions.onBuildLogs,\n logsRefreshFrequency: baseTemplate.logsRefreshFrequency,\n stackTraces: baseTemplate.stackTraces,\n })\n\n return data\n } finally {\n buildOptions.onBuildLogs?.(new LogEntryEnd(new Date(), 'Build finished'))\n }\n }\n\n /**\n * Build and deploy a template to PPIO sandbox infrastructure without waiting for completion.\n *\n * @param template The template to build\n * @param name Template name in 'name' or 'name:tag' format\n * @param options Optional build configuration options\n *\n * @example\n * ```ts\n * const template = Template().fromPythonImage('3')\n *\n * // Build with single tag in name\n * const data = await Template.buildInBackground(template, 'my-python-env:v1.0')\n *\n * // Build with multiple tags\n * const data = await Template.buildInBackground(template, 'my-python-env', { tags: ['v1.0', 'stable'] })\n * ```\n */\n static async buildInBackground(\n template: TemplateClass,\n name: string,\n options?: Omit<BuildOptions, 'alias'>\n ): Promise<BuildInfo>\n /**\n * Build and deploy a template to PPIO sandbox infrastructure without waiting for completion.\n *\n * @param template The template to build\n * @param options Build configuration options with alias (deprecated)\n *\n * @deprecated Use the overload with `name` parameter instead.\n * @example\n * ```ts\n * // Deprecated:\n * await Template.buildInBackground(template, { alias: 'my-python-env' })\n *\n * // Use instead:\n * await Template.buildInBackground(template, 'my-python-env:v1.0')\n * ```\n */\n static async buildInBackground(\n template: TemplateClass,\n options: BuildOptions\n ): Promise<BuildInfo>\n static async buildInBackground(\n template: TemplateClass,\n nameOrOptions: string | BuildOptions,\n options?: Omit<BuildOptions, 'alias'>\n ): Promise<BuildInfo> {\n const { name, buildOptions } = normalizeBuildArguments(\n nameOrOptions,\n options\n )\n\n const config = new ConnectionConfig(buildOptions)\n const client = new ApiClient(config)\n\n return (template as TemplateBase).build(client, name, buildOptions)\n }\n\n /**\n * Get the status of a build.\n *\n * @param data Build identifiers\n * @param options Authentication options\n *\n * @example\n * ```ts\n * const status = await Template.getBuildStatus(data, { logsOffset: 0 })\n * ```\n */\n static async getBuildStatus(\n data: Pick<BuildInfo, 'templateId' | 'buildId'>,\n options?: GetBuildStatusOptions\n ): Promise<TemplateBuildStatusResponse> {\n const config = new ConnectionConfig(options)\n raiseIfLegacy(config, 'Template.getBuildStatus', BuildError)\n const client = new ApiClient(config)\n\n return await getBuildStatus(client, {\n templateID: data.templateId,\n buildID: data.buildId,\n logsOffset: options?.logsOffset,\n })\n }\n\n static async listTemplates(\n options?: TemplateListOpts\n ): Promise<TemplateListResponse> {\n return TemplateApi.listTemplates(options)\n }\n\n static async get(\n templateId: string,\n options?: ConnectionOpts\n ): Promise<components['schemas']['TemplateWithBuilds']> {\n return TemplateApi.getTemplate(templateId, options)\n }\n\n static async delete(templateId: string, options?: ConnectionOpts) {\n await TemplateApi.deleteTemplate(templateId, options)\n }\n\n static async deleteTemplate(\n templateId: string,\n options?: TemplateDeleteOpts\n ): Promise<boolean> {\n return TemplateApi.deleteTemplate(templateId, options)\n }\n\n /**\n * Check if a template with the given name exists.\n *\n * @param name Template name to check\n * @param options Authentication options\n * @returns True if the name exists, false otherwise\n *\n * @example\n * ```ts\n * const exists = await Template.exists('my-python-env')\n * if (exists) {\n * console.log('Template exists!')\n * }\n * ```\n */\n static async exists(\n name: string,\n options?: ConnectionOpts\n ): Promise<boolean> {\n return TemplateBase.aliasExists(name, options)\n }\n\n /**\n * Check if a template with the given alias exists.\n *\n * @param alias Template alias to check\n * @param options Authentication options\n * @returns True if the alias exists, false otherwise\n *\n * @deprecated Use `exists` instead.\n * @example\n * ```ts\n * const exists = await Template.aliasExists('my-python-env')\n * if (exists) {\n * console.log('Template exists!')\n * }\n * ```\n */\n static async aliasExists(\n alias: string,\n options?: ConnectionOpts\n ): Promise<boolean> {\n const config = new ConnectionConfig(options)\n const client = new ApiClient(config)\n\n return checkAliasExists(client, { alias })\n }\n\n /**\n * Assign tag(s) to an existing template build.\n *\n * @param targetName Template name in 'name:tag' format (the source build to tag from)\n * @param tags Tag or tags to assign\n * @param options Authentication options\n * @returns Tag info with buildId and assigned tags\n *\n * @example\n * ```ts\n * // Assign a single tag\n * await Template.assignTags('my-template:v1.0', 'production')\n *\n * // Assign multiple tags\n * await Template.assignTags('my-template:v1.0', ['production', 'stable'])\n * ```\n */\n static async assignTags(\n targetName: string,\n tags: string | string[],\n options?: ConnectionOpts\n ): Promise<TemplateTagInfo> {\n const config = new ConnectionConfig(options)\n const client = new ApiClient(config)\n const normalizedTags = Array.isArray(tags) ? tags : [tags]\n return assignTags(client, { targetName, tags: normalizedTags })\n }\n\n /**\n * Remove tag(s) from a template.\n *\n * @param name Template name\n * @param tags Tag or tags to remove\n * @param options Authentication options\n *\n * @example\n * ```ts\n * // Remove a single tag\n * await Template.removeTags('my-template', 'production')\n *\n * // Remove multiple tags from a template\n * await Template.removeTags('my-template', ['production', 'staging'])\n * ```\n */\n static async removeTags(\n name: string,\n tags: string | string[],\n options?: ConnectionOpts\n ): Promise<void> {\n const config = new ConnectionConfig(options)\n const client = new ApiClient(config)\n const normalizedTags = Array.isArray(tags) ? tags : [tags]\n return removeTags(client, { name, tags: normalizedTags })\n }\n\n /**\n * Get all tags for a template.\n *\n * @param templateId Template ID or name\n * @param options Authentication options\n * @returns Array of tag details including tag name, buildId, and creation date\n *\n * @example\n * ```ts\n * const tags = await Template.getTags('my-template')\n * for (const tag of tags) {\n * console.log(`Tag: ${tag.tag}, Build: ${tag.buildId}, Created: ${tag.createdAt}`)\n * }\n * ```\n */\n static async getTags(\n templateId: string,\n options?: ConnectionOpts\n ): Promise<TemplateTag[]> {\n const config = new ConnectionConfig(options)\n const client = new ApiClient(config)\n return getTemplateTags(client, { templateID: templateId })\n }\n\n fromDebianImage(variant: string = 'stable'): TemplateBuilder {\n return this.fromImage(`debian:${variant}`)\n }\n\n fromUbuntuImage(variant: string = 'latest'): TemplateBuilder {\n return this.fromImage(`ubuntu:${variant}`)\n }\n\n fromPythonImage(version: string = '3'): TemplateBuilder {\n return this.fromImage(`python:${version}`)\n }\n\n fromNodeImage(variant: string = 'lts'): TemplateBuilder {\n return this.fromImage(`node:${variant}`)\n }\n\n fromBunImage(variant: string = 'latest'): TemplateBuilder {\n return this.fromImage(`oven/bun:${variant}`)\n }\n\n fromBaseImage(): TemplateBuilder {\n return this.fromImage(this.defaultBaseImage)\n }\n\n fromImage(\n baseImage: string,\n credentials?: { username: string; password: string },\n options?: { inheritConfig?: boolean }\n ): TemplateBuilder {\n this.baseImage = baseImage\n this.baseTemplate = undefined\n // Read at build time, not here: this method is synchronous so it can be\n // chained, and reading a registry is not. See resolveInheritedConfig().\n this.inheritImageConfig = options?.inheritConfig ?? true\n this.imageCredentials = credentials\n\n // Set the registry config if provided\n if (credentials) {\n this.registryConfig = {\n type: 'registry',\n username: credentials.username,\n password: credentials.password,\n }\n }\n\n // If we should force the next layer and it's a FROM command, invalidate whole template\n if (this.forceNextLayer) {\n this.force = true\n }\n\n this.collectStackTrace()\n return this\n }\n\n fromTemplate(template: string): TemplateBuilder {\n this.baseTemplate = template\n this.baseImage = undefined\n\n // If we should force the next layer and it's a FROM command, invalidate whole template\n if (this.forceNextLayer) {\n this.force = true\n }\n\n this.collectStackTrace()\n return this\n }\n\n fromDockerfile(dockerfileContentOrPath: string): TemplateBuilder {\n const { baseImage } = this.runInStackTraceOverrideContext(\n () => parseDockerfile(dockerfileContentOrPath, this),\n // -1 as we're going up the call stack from the parseDockerfile function\n getCallerFrame(STACK_TRACE_DEPTH - 1)\n )\n this.baseImage = baseImage\n this.baseTemplate = undefined\n\n // If we should force the next layer and it's a FROM command, invalidate whole template\n if (this.forceNextLayer) {\n this.force = true\n }\n\n this.collectStackTrace()\n return this\n }\n\n fromAWSRegistry(\n image: string,\n credentials: {\n accessKeyId: string\n secretAccessKey: string\n region: string\n }\n ): TemplateBuilder {\n this.baseImage = image\n this.baseTemplate = undefined\n\n // Set the registry config if provided\n this.registryConfig = {\n type: 'aws',\n awsAccessKeyId: credentials.accessKeyId,\n awsSecretAccessKey: credentials.secretAccessKey,\n awsRegion: credentials.region,\n }\n\n // If we should force the next layer and it's a FROM command, invalidate whole template\n if (this.forceNextLayer) {\n this.force = true\n }\n\n this.collectStackTrace()\n return this\n }\n\n fromGCPRegistry(\n image: string,\n credentials: {\n serviceAccountJSON: string | object\n }\n ): TemplateBuilder {\n this.baseImage = image\n this.baseTemplate = undefined\n\n // Set the registry config if provided\n this.registryConfig = {\n type: 'gcp',\n serviceAccountJson: readGCPServiceAccountJSON(\n this.fileContextPath.toString(),\n credentials.serviceAccountJSON\n ),\n }\n\n // If we should force the next layer and it's a FROM command, invalidate whole template\n if (this.forceNextLayer) {\n this.force = true\n }\n\n this.collectStackTrace()\n return this\n }\n\n fromOCIRegistry(\n image: string,\n credentials: {\n tenancyOcid: string\n userOcid: string\n fingerprint: string\n privateKey: string\n region: string\n }\n ): TemplateBuilder {\n this.baseImage = image\n this.baseTemplate = undefined\n\n this.registryConfig = {\n type: 'oci',\n tenancyOcid: credentials.tenancyOcid,\n userOcid: credentials.userOcid,\n fingerprint: credentials.fingerprint,\n privateKey: credentials.privateKey,\n region: credentials.region,\n }\n\n if (this.forceNextLayer) {\n this.force = true\n }\n\n this.collectStackTrace()\n return this\n }\n\n fromHuaweiCloudRegistry(\n image: string,\n credentials: {\n accessKeyId: string\n secretAccessKey: string\n region: string\n }\n ): TemplateBuilder {\n this.baseImage = image\n this.baseTemplate = undefined\n\n this.registryConfig = {\n type: 'huawei',\n accessKeyId: credentials.accessKeyId,\n secretAccessKey: credentials.secretAccessKey,\n region: credentials.region,\n }\n\n if (this.forceNextLayer) {\n this.force = true\n }\n\n this.collectStackTrace()\n return this\n }\n\n copy(\n src: PathLike | PathLike[],\n dest: PathLike,\n options?: {\n forceUpload?: true\n user?: string\n mode?: number\n resolveSymlinks?: boolean\n }\n ): TemplateBuilder {\n if (runtime === 'browser') {\n throw new Error('Browser runtime is not supported for copy')\n }\n\n const srcs = Array.isArray(src) ? src : [src]\n const stackTrace = getCallerFrame(STACK_TRACE_DEPTH - 1)\n\n for (const src of srcs) {\n const srcString = src.toString()\n\n // Validate that the source path is a relative path within the context directory\n validateRelativePath(srcString, stackTrace)\n\n const args = [\n srcString,\n dest.toString(),\n options?.user ?? '',\n options?.mode ? padOctal(options.mode) : '',\n ]\n\n this.instructions.push({\n type: InstructionType.COPY,\n args,\n force: options?.forceUpload || this.forceNextLayer,\n forceUpload: options?.forceUpload,\n resolveSymlinks: options?.resolveSymlinks,\n })\n }\n\n this.collectStackTrace()\n return this\n }\n\n copyItems(items: CopyItem[]): TemplateBuilder {\n if (runtime === 'browser') {\n throw new Error('Browser runtime is not supported for copyItems')\n }\n\n // Stack trace that will be used to re-throw the error with\n const stackTrace = getCallerFrame(STACK_TRACE_DEPTH - 1)\n\n this.runInNewStackTraceContext(() => {\n for (const item of items) {\n try {\n this.copy(item.src, item.dest, {\n forceUpload: item.forceUpload,\n user: item.user,\n mode: item.mode,\n resolveSymlinks: item.resolveSymlinks,\n })\n } catch (error) {\n const copyError = error as Error\n copyError.stack = stackTrace\n throw copyError\n }\n }\n })\n\n return this\n }\n\n remove(\n path: PathLike | PathLike[],\n options?: { force?: boolean; recursive?: boolean; user?: string }\n ): TemplateBuilder {\n const paths = Array.isArray(path) ? path : [path]\n const args = ['rm']\n if (options?.recursive) {\n args.push('-r')\n }\n if (options?.force) {\n args.push('-f')\n }\n args.push(...paths.map((p) => p.toString()))\n return this.runInNewStackTraceContext(() =>\n this.runCmd(args.join(' '), { user: options?.user })\n )\n }\n\n rename(\n src: PathLike,\n dest: PathLike,\n options?: { force?: boolean; user?: string }\n ): TemplateBuilder {\n const args = ['mv', src.toString(), dest.toString()]\n if (options?.force) {\n args.push('-f')\n }\n return this.runInNewStackTraceContext(() =>\n this.runCmd(args.join(' '), { user: options?.user })\n )\n }\n\n makeDir(\n path: PathLike | PathLike[],\n options?: { mode?: number; user?: string }\n ): TemplateBuilder {\n const paths = Array.isArray(path) ? path : [path]\n const args = ['mkdir', '-p']\n if (options?.mode) {\n args.push(`-m ${padOctal(options.mode)}`)\n }\n args.push(...paths.map((p) => p.toString()))\n return this.runInNewStackTraceContext(() =>\n this.runCmd(args.join(' '), { user: options?.user })\n )\n }\n\n makeSymlink(\n src: PathLike,\n dest: PathLike,\n options?: { user?: string; force?: boolean }\n ): TemplateBuilder {\n const args = ['ln', '-s']\n if (options?.force) {\n args.push('-f')\n }\n args.push(src.toString(), dest.toString())\n return this.runInNewStackTraceContext(() =>\n this.runCmd(args.join(' '), { user: options?.user })\n )\n }\n\n runCmd(command: string, options?: { user?: string }): TemplateBuilder\n runCmd(commands: string[], options?: { user?: string }): TemplateBuilder\n runCmd(\n commandOrCommands: string | string[],\n options?: { user?: string }\n ): TemplateBuilder {\n const cmds = Array.isArray(commandOrCommands)\n ? commandOrCommands\n : [commandOrCommands]\n\n const args = [cmds.join(' && ')]\n if (options?.user) {\n args.push(options.user)\n }\n\n this.instructions.push({\n type: InstructionType.RUN,\n args,\n force: this.forceNextLayer,\n })\n\n this.collectStackTrace()\n return this\n }\n\n setWorkdir(workdir: PathLike): TemplateBuilder {\n this.instructions.push({\n type: InstructionType.WORKDIR,\n args: [workdir.toString()],\n force: this.forceNextLayer,\n })\n\n this.collectStackTrace()\n return this\n }\n\n setUser(user: string): TemplateBuilder {\n this.instructions.push({\n type: InstructionType.USER,\n args: [user],\n force: this.forceNextLayer,\n })\n\n this.collectStackTrace()\n return this\n }\n\n pipInstall(\n packages?: string | string[],\n options?: { g?: boolean }\n ): TemplateBuilder {\n const g = options?.g ?? true\n\n const args = ['pip', 'install']\n const packageList = packages\n ? Array.isArray(packages)\n ? packages\n : [packages]\n : undefined\n if (g === false) {\n args.push('--user')\n }\n if (packageList) {\n args.push(...packageList)\n } else {\n args.push('.')\n }\n\n return this.runInNewStackTraceContext(() =>\n this.runCmd(args.join(' '), {\n user: g ? 'root' : undefined,\n })\n )\n }\n\n npmInstall(\n packages?: string | string[],\n options?: { g?: boolean; dev?: boolean }\n ): TemplateBuilder {\n const args = ['npm', 'install']\n const packageList = packages\n ? Array.isArray(packages)\n ? packages\n : [packages]\n : undefined\n if (options?.g) {\n args.push('-g')\n }\n if (options?.dev) {\n args.push('--save-dev')\n }\n if (packageList) {\n args.push(...packageList)\n }\n\n return this.runInNewStackTraceContext(() =>\n this.runCmd(args.join(' '), {\n user: options?.g ? 'root' : undefined,\n })\n )\n }\n\n bunInstall(\n packages?: string | string[],\n options?: { g?: boolean; dev?: boolean }\n ): TemplateBuilder {\n const args = ['bun', 'install']\n const packageList = packages\n ? Array.isArray(packages)\n ? packages\n : [packages]\n : undefined\n if (options?.g) {\n args.push('-g')\n }\n if (options?.dev) {\n args.push('--dev')\n }\n if (packageList) {\n args.push(...packageList)\n }\n\n return this.runInNewStackTraceContext(() =>\n this.runCmd(args.join(' '), {\n user: options?.g ? 'root' : undefined,\n })\n )\n }\n\n aptInstall(\n packages: string | string[],\n options?: { noInstallRecommends?: boolean; fixMissing?: boolean }\n ): TemplateBuilder {\n const packageList = Array.isArray(packages) ? packages : [packages]\n return this.runInNewStackTraceContext(() =>\n this.runCmd(\n [\n 'apt-get update',\n `DEBIAN_FRONTEND=noninteractive DEBCONF_NOWARNINGS=yes apt-get install -y ${options?.noInstallRecommends ? '--no-install-recommends ' : ''}${options?.fixMissing ? '--fix-missing ' : ''}${packageList.join(\n ' '\n )}`,\n ],\n { user: 'root' }\n )\n )\n }\n\n addMcpServer(servers: McpServerName | McpServerName[]): TemplateBuilder {\n if (this.baseTemplate !== 'mcp-gateway') {\n throw new BuildError(\n 'MCP servers can only be added to mcp-gateway template',\n getCallerFrame(STACK_TRACE_DEPTH - 1)\n )\n }\n\n const serverList = Array.isArray(servers) ? servers : [servers]\n return this.runInNewStackTraceContext(() =>\n this.runCmd(`mcp-gateway pull ${serverList.join(' ')}`, {\n user: 'root',\n })\n )\n }\n\n gitClone(\n url: string,\n path?: PathLike,\n options?: { branch?: string; depth?: number; user?: string }\n ): TemplateBuilder {\n const args = ['git', 'clone', url]\n if (options?.branch) {\n args.push(`--branch ${options.branch}`)\n args.push('--single-branch')\n }\n if (options?.depth) {\n args.push(`--depth ${options.depth}`)\n }\n if (path) {\n args.push(path.toString())\n }\n\n return this.runInNewStackTraceContext(() =>\n this.runCmd(args.join(' '), { user: options?.user })\n )\n }\n\n setStartCmd(\n startCommand: string,\n readyCommand: string | ReadyCmd\n ): TemplateFinal {\n this.startCmd = startCommand\n\n if (readyCommand instanceof ReadyCmd) {\n this.readyCmd = readyCommand.getCmd()\n } else {\n this.readyCmd = readyCommand\n }\n\n this.collectStackTrace()\n return this\n }\n\n setReadyCmd(readyCommand: string | ReadyCmd): TemplateFinal {\n if (readyCommand instanceof ReadyCmd) {\n this.readyCmd = readyCommand.getCmd()\n } else {\n this.readyCmd = readyCommand\n }\n\n this.collectStackTrace()\n return this\n }\n\n setPatchCmd(cmd: string): TemplateBuilder {\n this.patchCmd = cmd\n this.collectStackTrace()\n return this\n }\n\n setEnvs(envs: Record<string, string>): TemplateBuilder {\n if (Object.keys(envs).length === 0) {\n return this\n }\n\n this.instructions.push({\n type: InstructionType.ENV,\n args: Object.entries(envs).flatMap(([key, value]) => [key, value]),\n force: this.forceNextLayer,\n })\n // The ENV instruction above only reaches the *build*. A sandbox started from\n // the finished template does not inherit it, so the names are also written to\n // the filesystem at the end of the build -- see runtimeEnvInstruction() and\n // envFiles.ts for the measurement that established this.\n this.envs = { ...this.envs, ...envs }\n this.collectStackTrace()\n return this\n }\n\n /**\n * The instruction that makes {@link setEnvs} visible at runtime, or null when\n * no environment was set.\n *\n * Appended at build time rather than inside `setEnvs`, for two reasons: the\n * file is written once from the complete set (a per-call write would clobber\n * the previous call's file), and it must land after any USER instruction the\n * caller added, since the write needs root.\n *\n * Not run through `runCmd` -- that would mutate `this.instructions` and make a\n * second build of the same template append a duplicate layer.\n */\n private runtimeEnvInstruction(): Instruction | null {\n const { command } = envFilesCommand(this.envs)\n if (command === null) {\n return null\n }\n\n return {\n type: InstructionType.RUN,\n args: [command, 'root'],\n force: this.forceNextLayer,\n }\n }\n\n /**\n * `instructions` with the runtime-env write appended, if there is one.\n *\n * Returns a new array rather than pushing: `toJSON` and `build` both call this,\n * and a template that is serialized and then built must not end up with the\n * layer twice.\n */\n private withRuntimeEnv(instructions: Instruction[]): Instruction[] {\n const runtimeEnv = this.runtimeEnvInstruction()\n return runtimeEnv ? [...instructions, runtimeEnv] : instructions\n }\n\n /**\n * Restore what the base image declares: ENV, WORKDIR and its effective command.\n *\n * `fromImage` records only the reference — the platform pulls the image\n * server-side, and nothing ever read its config. So the image's own ENV is as\n * absent at runtime as a template's own: measured, `python:3.11-slim` declares\n * `PATH=/usr/local/bin:…` and a sandbox built from it reported a different PATH\n * entirely. Same for WORKDIR, and for ENTRYPOINT/CMD, which is what `docker run`\n * would have launched.\n *\n * Runs at build time because reading a registry is asynchronous and `fromImage`\n * has to stay chainable. **The caller always wins**: anything set explicitly on\n * the builder overrides what the image declared, which is the same precedence a\n * Dockerfile has over its own base image.\n *\n * A failed read is not fatal — the template still builds, just without the\n * restored config — but it is reported, since an image whose toolchain lives\n * behind its ENV will otherwise look installed and behave as though it is not.\n */\n private async resolveInheritedConfig(\n onBuildLogs?: (logEntry: LogEntry) => void\n ): Promise<void> {\n if (!this.inheritImageConfig || this.baseImage === undefined) {\n return\n }\n // Only once: build() and toJSON() both call this, and a second read would\n // re-apply the image's values over any the caller set in between. Belt and\n // braces -- the two places it would matter defend themselves anyway (the env\n // merge puts the caller last, and the WORKDIR push checks for an existing\n // one), so removing this alone does not currently change any outcome.\n this.inheritImageConfig = false\n\n const config = await fetchImageConfig(this.baseImage, this.imageCredentials)\n\n if (config.error) {\n // Reported rather than thrown. The build can still succeed, and one\n // unreachable registry must not fail a batch conversion -- but a template\n // silently missing the image's PATH is the failure this exists to prevent,\n // so it must not pass unmentioned.\n this.imageConfigError = config.error\n this.imageUnusable = config.unusable\n onBuildLogs?.(\n new LogEntry(\n new Date(),\n 'warn',\n `Could not read ${this.baseImage}: ${config.error}. ` +\n 'The template will build without the environment, working directory ' +\n 'and start command the image declares.'\n )\n )\n return\n }\n\n // The image is the base, the caller's own calls override it -- so the\n // inherited names go under what setEnvs already recorded.\n this.envs = { ...config.env, ...this.envs }\n\n if (\n config.workdir &&\n !this.instructions.some(i => i.type === InstructionType.WORKDIR)\n ) {\n this.instructions.push({\n type: InstructionType.WORKDIR,\n args: [config.workdir],\n force: false,\n })\n }\n\n const startCmd = effectiveStartCmd(config.entrypoint, config.cmd)\n if (startCmd && this.startCmd === undefined) {\n this.startCmd = startCmd\n // setStartCmd requires a readiness check, and without one the SDK's own\n // Dockerfile parser pairs the command with waitForTimeout(20_000). Kept\n // byte-identical so an image built through fromImage behaves the same as\n // one built from its Dockerfile -- note this is a timer, not a health\n // check: pass setReadyCmd for a real one.\n this.readyCmd = this.readyCmd ?? waitForTimeout(20_000).getCmd()\n }\n }\n\n /**\n * Why the base image's declared config is missing, or undefined when nothing\n * was missing. Populated once the template has been serialized or built.\n *\n * `unusable` means the read succeeded and the image still cannot be used here\n * -- no linux/amd64 variant, or the reference names nothing. A retry cannot\n * change it, and the build would fail for the same reason minutes later, so a\n * caller converting images in bulk should skip rather than build.\n *\n * `error` alone means the read itself failed. The template builds without the\n * image's environment, working directory and start command.\n */\n static imageConfigFailure(\n template: TemplateClass\n ): { error: string; unusable?: string } | undefined {\n const base = template as TemplateBase\n if (base.imageConfigError === undefined) {\n return undefined\n }\n return base.imageUnusable === undefined\n ? { error: base.imageConfigError }\n : { error: base.imageConfigError, unusable: base.imageUnusable }\n }\n\n skipCache(): this {\n this.forceNextLayer = true\n return this\n }\n\n betaDevContainerPrebuild(devcontainerDirectory: string): TemplateBuilder {\n if (this.baseTemplate !== 'devcontainer') {\n throw new BuildError(\n 'Devcontainers can only used in the devcontainer template',\n getCallerFrame(STACK_TRACE_DEPTH - 1)\n )\n }\n\n return this.runInNewStackTraceContext(() => {\n return this.runCmd(\n `devcontainer build --workspace-folder ${devcontainerDirectory}`,\n { user: 'root' }\n )\n })\n }\n\n betaSetDevContainerStart(devcontainerDirectory: string): TemplateFinal {\n if (this.baseTemplate !== 'devcontainer') {\n throw new BuildError(\n 'Devcontainers can only used in the devcontainer template',\n getCallerFrame(STACK_TRACE_DEPTH - 1)\n )\n }\n\n return this.runInNewStackTraceContext(() => {\n return this.setStartCmd(\n `sudo devcontainer up --workspace-folder ${devcontainerDirectory} && sudo /prepare-exec.sh ${devcontainerDirectory} | sudo tee /devcontainer.sh > /dev/null && sudo chmod +x /devcontainer.sh && sudo touch /devcontainer.up`,\n waitForFile('/devcontainer.up')\n )\n })\n }\n\n /**\n * Collect the current stack trace for debugging purposes.\n *\n * @param stackTracesDepth Depth to traverse in the call stack\n * @returns this for method chaining\n */\n private collectStackTrace(stackTracesDepth: number = STACK_TRACE_DEPTH) {\n if (!this.stackTracesEnabled) {\n return this\n }\n\n if (this.stackTracesOverride) {\n this.stackTraces.push(this.stackTracesOverride)\n return this\n }\n\n this.stackTraces.push(getCallerFrame(stackTracesDepth))\n return this\n }\n\n /**\n * Temporarily disable stack trace collection.\n *\n * @returns this for method chaining\n */\n private disableStackTrace() {\n this.stackTracesEnabled = false\n return this\n }\n\n /**\n * Re-enable stack trace collection.\n *\n * @returns this for method chaining\n */\n private enableStackTrace() {\n this.stackTracesEnabled = true\n return this\n }\n\n /**\n * Execute a function in a clean stack trace context.\n *\n * @param fn Function to execute\n * @returns The result of the function\n */\n private runInNewStackTraceContext<T>(fn: () => T): T {\n this.disableStackTrace()\n const result = fn()\n this.enableStackTrace()\n this.collectStackTrace(STACK_TRACE_DEPTH + 1)\n return result\n }\n\n private runInStackTraceOverrideContext<T>(\n fn: () => T,\n stackTraceOverride: string | undefined\n ): T {\n this.stackTracesOverride = stackTraceOverride\n const result = fn()\n this.stackTracesOverride = undefined\n return result\n }\n\n /**\n * Convert the template to JSON representation.\n *\n * @param computeHashes Whether to compute file hashes for COPY instructions\n * @returns JSON string representation of the template\n */\n private async toJSON(computeHashes: boolean): Promise<string> {\n await this.resolveInheritedConfig()\n\n let instructions = this.instructions\n if (computeHashes) {\n instructions = await this.instructionsWithHashes()\n }\n\n return JSON.stringify(\n this.serialize(this.withRuntimeEnv(instructions)),\n undefined,\n 2\n )\n }\n\n /**\n * Convert the template to Dockerfile format.\n *\n * Note: Only templates based on Docker images can be converted to Dockerfile.\n * Templates based on other PPIO sandbox templates cannot be converted because they\n * may use features not available in standard Dockerfiles.\n *\n * @returns Dockerfile string representation\n * @throws Error if template is based on another PPIO sandbox template or has no base image\n */\n private toDockerfile(): string {\n if (this.baseTemplate !== undefined) {\n throw new Error(\n 'Cannot convert template built from another template to Dockerfile. ' +\n 'Templates based on other templates can only be built using the PPIO sandbox API.'\n )\n }\n\n if (this.baseImage === undefined) {\n throw new Error('No base image specified for template')\n }\n\n let dockerfile = `FROM ${this.baseImage}\\n`\n for (const instruction of this.instructions) {\n if (instruction.type === InstructionType.RUN) {\n dockerfile += `RUN ${instruction.args[0]}\\n`\n continue\n }\n if (instruction.type === InstructionType.COPY) {\n dockerfile += `COPY ${instruction.args[0]} ${instruction.args[1]}\\n`\n continue\n }\n if (instruction.type === InstructionType.ENV) {\n const values: string[] = []\n for (let i = 0; i < instruction.args.length; i += 2) {\n values.push(`${instruction.args[i]}=${instruction.args[i + 1]}`)\n }\n dockerfile += `ENV ${values.join(' ')}\\n`\n continue\n }\n dockerfile += `${instruction.type} ${instruction.args.join(' ')}\\n`\n }\n if (this.startCmd) {\n dockerfile += `ENTRYPOINT ${this.startCmd}\\n`\n }\n return dockerfile\n }\n\n /**\n * Internal implementation of the template build process.\n *\n * @param client API client for communicating with PPIO sandbox backend\n * @param name Template name in 'name' or 'name:tag' format\n * @param tags Additional tags to assign to the build\n * @param options Build configuration options\n * @throws BuildError if the build fails\n */\n private async build(\n client: ApiClient,\n name: string,\n options: Omit<BuildOptions, 'alias'>\n ): Promise<BuildInfo> {\n if (options.skipCache) {\n this.force = true\n }\n\n // Create template\n options.onBuildLogs?.(\n new LogEntry(\n new Date(),\n 'info',\n `Requesting build for template: ${name}${options.tags && options.tags.length > 0 ? ` with tags ${options.tags.join(', ')}` : ''}`\n )\n )\n\n const {\n templateID,\n buildID,\n tags: responseTags,\n } = await requestBuild(client, {\n name,\n tags: options.tags,\n cpuCount: options.cpuCount ?? 2,\n memoryMB: options.memoryMB ?? 1024,\n })\n\n options.onBuildLogs?.(\n new LogEntry(\n new Date(),\n 'info',\n `Template created with ID: ${templateID}, Build ID: ${buildID}`\n )\n )\n\n // Before the instructions are assembled: this can add a WORKDIR step and set\n // the start command, both of which have to be in the payload below.\n await this.resolveInheritedConfig(options.onBuildLogs)\n\n const instructionsWithHashes = await this.instructionsWithHashes()\n\n // Upload files in parallel\n const uploadPromises = instructionsWithHashes.map(\n async (instruction, index) => {\n if (instruction.type !== InstructionType.COPY) {\n return\n }\n\n const src = instruction.args.length > 0 ? instruction.args[0] : null\n const filesHash = instruction.filesHash ?? null\n if (src === null || filesHash === null) {\n throw new Error('Source path and files hash are required')\n }\n\n const forceUpload = instruction.forceUpload\n let stackTrace = undefined\n if (index + 1 >= 0 && index + 1 < this.stackTraces.length) {\n stackTrace = this.stackTraces[index + 1]\n }\n\n const { present, url } = await getFileUploadLink(\n client,\n {\n templateID,\n filesHash,\n },\n stackTrace\n )\n\n if (\n (forceUpload && url != null) ||\n (present === false && url != null)\n ) {\n await uploadFile(\n {\n fileName: src,\n fileContextPath: this.fileContextPath.toString(),\n url,\n ignorePatterns: [\n ...this.fileIgnorePatterns,\n ...readDockerignore(this.fileContextPath.toString()),\n ],\n resolveSymlinks: instruction.resolveSymlinks ?? RESOLVE_SYMLINKS,\n },\n stackTrace\n )\n options.onBuildLogs?.(\n new LogEntry(new Date(), 'info', `Uploaded '${src}'`)\n )\n } else {\n options.onBuildLogs?.(\n new LogEntry(\n new Date(),\n 'info',\n `Skipping upload of '${src}', already cached`\n )\n )\n }\n }\n )\n\n await Promise.all(uploadPromises)\n\n options.onBuildLogs?.(\n new LogEntry(new Date(), 'info', 'All file uploads completed')\n )\n\n // Start build\n options.onBuildLogs?.(\n new LogEntry(new Date(), 'info', 'Starting building...')\n )\n\n await triggerBuild(client, {\n templateID,\n buildID,\n template: this.serialize(this.withRuntimeEnv(instructionsWithHashes)),\n })\n\n return {\n alias: name,\n name: name,\n tags: responseTags,\n templateId: templateID,\n buildId: buildID,\n }\n }\n\n /**\n * Add file hashes to COPY instructions for cache invalidation.\n *\n * @returns Copy of instructions array with filesHash added to COPY instructions\n */\n private async instructionsWithHashes(): Promise<Instruction[]> {\n return Promise.all(\n this.instructions.map(async (instruction, index) => {\n if (instruction.type !== InstructionType.COPY) {\n return instruction\n }\n\n const src = instruction.args.length > 0 ? instruction.args[0] : null\n const dest = instruction.args.length > 1 ? instruction.args[1] : null\n if (src === null || dest === null) {\n throw new Error('Source path and destination path are required')\n }\n\n let stackTrace = undefined\n if (index + 1 >= 0 && index + 1 < this.stackTraces.length) {\n stackTrace = this.stackTraces[index + 1]\n }\n\n return {\n ...instruction,\n filesHash: await calculateFilesHash(\n src,\n dest,\n this.fileContextPath.toString(),\n [\n ...this.fileIgnorePatterns,\n ...(runtime === 'browser'\n ? []\n : readDockerignore(this.fileContextPath.toString())),\n ],\n instruction.resolveSymlinks ?? RESOLVE_SYMLINKS,\n stackTrace\n ),\n }\n })\n )\n }\n\n /**\n * Serialize the template to the API request format.\n *\n * @param steps Array of build instructions with file hashes\n * @returns Template data formatted for the API\n */\n private serialize(steps: Instruction[]): TriggerBuildTemplate {\n const templateData: TriggerBuildTemplate = {\n startCmd: this.startCmd,\n readyCmd: this.readyCmd,\n preBootScript: this.patchCmd,\n steps,\n force: this.force,\n }\n\n if (this.baseImage !== undefined) {\n templateData.fromImage = this.baseImage\n }\n\n if (this.baseTemplate !== undefined) {\n templateData.fromTemplate = this.baseTemplate\n }\n\n if (this.registryConfig !== undefined) {\n templateData.fromImageRegistry = this.registryConfig\n }\n\n return templateData\n }\n}\n\n/**\n * Create a new PPIO sandbox template builder instance.\n *\n * @param options Optional configuration for the template builder\n * @returns A new template builder instance\n *\n * @example\n * ```ts\n * import { Template } from 'ppio-sandbox'\n *\n * const template = Template()\n * .fromPythonImage('3')\n * .copy('requirements.txt', '/app/')\n * .pipInstall()\n *\n * await Template.build(template, 'my-python-app:v1.0')\n * ```\n */\nexport function Template(options?: TemplateOptions): TemplateFromImage {\n return new TemplateBase(options)\n}\n\nTemplate.build = TemplateBase.build\nTemplate.buildInBackground = TemplateBase.buildInBackground\nTemplate.getBuildStatus = TemplateBase.getBuildStatus\nTemplate.get = TemplateBase.get\nTemplate.exists = TemplateBase.exists\nTemplate.aliasExists = TemplateBase.aliasExists\nTemplate.assignTags = TemplateBase.assignTags\nTemplate.removeTags = TemplateBase.removeTags\nTemplate.getTags = TemplateBase.getTags\nTemplate.list = TemplateBase.list\nTemplate.delete = TemplateBase.delete\nTemplate.toJSON = TemplateBase.toJSON\nTemplate.toDockerfile = TemplateBase.toDockerfile\n\nexport type {\n BuildInfo,\n BuildOptions,\n BuildStatusReason,\n CopyItem,\n GetBuildStatusOptions,\n McpServerName,\n TemplateBuilder,\n TemplateBuildStatus,\n TemplateBuildStatusResponse,\n TemplateClass,\n TemplateDeleteOpts,\n TemplateInfo,\n TemplateListOpts,\n TemplateListOptions,\n TemplateListResponse,\n TemplateTag,\n TemplateTagInfo,\n TemplateType,\n} from './types'\n","import { ApiClient, handleApiError } from '../api'\nimport {\n ConnectionConfig,\n ConnectionOpts,\n raiseIfLegacy,\n validateDomain,\n} from '../connectionConfig'\nimport { NotFoundError, VolumeError } from '../errors'\nimport type {\n VolumeAndToken,\n VolumeInfo,\n} from './types'\n\nfunction quotaInodesForSize(quotaSizeGiB: number) {\n return quotaSizeGiB * 1000\n}\n\n/**\n * Module for interacting with PPIO sandbox volumes.\n *\n * Use the static methods to manage volumes or create a `Volume` instance\n * to pass volume references to sandbox operations.\n */\nexport class Volume {\n /**\n * Volume ID.\n */\n readonly volumeId: string\n\n /**\n * Volume name.\n */\n readonly name: string\n\n /**\n * Volume auth token.\n */\n readonly token: string\n\n /**\n * Domain used for constructing the volume API URL.\n */\n readonly domain?: string\n\n /**\n * Whether to use debug mode (connects to local volume API server).\n */\n readonly debug?: boolean\n\n /**\n * Create a local Volume instance with no API call.\n *\n * @param volumeId volume ID.\n * @param name volume name.\n * @param token volume auth token.\n * @param domain domain for the volume API.\n * @param debug whether to use debug mode.\n */\n constructor(\n volumeId: string,\n name: string,\n token: string,\n domain?: string,\n debug?: boolean\n ) {\n if (domain) {\n validateDomain(domain)\n }\n this.volumeId = volumeId\n this.name = name\n this.token = token\n this.domain = domain\n this.debug = debug\n }\n\n /**\n * Create a new volume.\n *\n * @param name name of the volume.\n * @param opts connection options.\n * @param [opts.quotaSizeGiB] capacity quota in GiB.\n *\n * @returns new Volume instance.\n */\n static async create(name: string, opts?: ConnectionOpts & {\n quotaSizeGiB?: number\n }): Promise<Volume> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Volume.create', VolumeError)\n\n const client = new ApiClient(config)\n const body: {\n name: string\n quotaSizeGiB?: number\n quotaInodes?: number\n } = { name }\n\n if (opts?.quotaSizeGiB !== undefined) {\n body.quotaSizeGiB = opts.quotaSizeGiB\n body.quotaInodes = quotaInodesForSize(opts.quotaSizeGiB)\n }\n\n const res = await client.api.POST('/volumes', {\n body,\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n const err = handleApiError(res, VolumeError)\n if (err) {\n throw err\n }\n\n if (!res.data) {\n throw new Error('Response data is missing')\n }\n\n return new Volume(\n res.data.volumeID,\n res.data.name,\n res.data.token,\n config.domain,\n config.debug\n )\n }\n\n /**\n * Connect to an existing volume by ID.\n *\n * @param volumeId volume ID.\n * @param opts connection options.\n *\n * @returns Volume instance.\n */\n static async connect(\n volumeId: string,\n opts?: ConnectionOpts\n ): Promise<Volume> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Volume.connect', VolumeError)\n const { name, token } = await Volume.getInfo(volumeId, opts)\n return new Volume(volumeId, name, token, config.domain, config.debug)\n }\n\n /**\n * Get volume information.\n *\n * @param volumeId volume ID.\n * @param opts connection options.\n *\n * @returns volume information.\n */\n static async getInfo(\n volumeId: string,\n opts?: ConnectionOpts\n ): Promise<VolumeAndToken> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Volume.getInfo', VolumeError)\n\n const client = new ApiClient(config)\n\n const res = await client.api.GET('/volumes/{volumeID}', {\n params: {\n path: {\n volumeID: volumeId,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.response.status === 404) {\n throw new NotFoundError(`Volume ${volumeId} not found`)\n }\n\n const err = handleApiError(res, VolumeError)\n if (err) {\n throw err\n }\n\n const data = res.data as any\n\n return {\n volumeId: data.volumeID,\n name: data.name,\n token: data.token,\n quotaSizeGiB: data.quotaSizeGiB ?? 0,\n usedSizeBytes: data.usedSizeBytes ?? 0,\n }\n }\n\n /**\n * List all volumes.\n *\n * @param opts connection options.\n *\n * @returns list of volume information.\n */\n static async list(opts?: ConnectionOpts): Promise<VolumeInfo[]> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Volume.list', VolumeError)\n\n const client = new ApiClient(config)\n\n const res = await client.api.GET('/volumes', {\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n const err = handleApiError(res, VolumeError)\n if (err) {\n throw err\n }\n\n return ((res.data ?? []) as any[]).map((vol: any) => ({\n volumeId: vol.volumeID,\n name: vol.name,\n quotaSizeGiB: vol.quotaSizeGiB ?? 0,\n usedSizeBytes: vol.usedSizeBytes ?? 0,\n }))\n }\n\n /**\n * Update volume quota.\n *\n * @param volumeId volume ID.\n * @param params quota parameters.\n * @param opts connection options.\n *\n * @returns updated volume information.\n */\n static async updateQuota(\n volumeId: string,\n params: { quotaSizeGiB?: number },\n opts?: ConnectionOpts\n ): Promise<VolumeAndToken> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Volume.updateQuota', VolumeError)\n const body: {\n quotaSizeGiB?: number\n quotaInodes?: number\n } = {}\n\n if (params.quotaSizeGiB !== undefined) {\n body.quotaSizeGiB = params.quotaSizeGiB\n body.quotaInodes = quotaInodesForSize(params.quotaSizeGiB)\n }\n\n const res = await fetch(\n `${config.apiUrl}/volumes/${encodeURIComponent(volumeId)}`,\n {\n method: 'PATCH',\n headers: {\n ...config.headers,\n 'Content-Type': 'application/json',\n ...(config.apiKey ? { 'X-API-KEY': config.apiKey } : {}),\n ...(config.accessToken\n ? { Authorization: `Bearer ${config.accessToken}` }\n : {}),\n },\n body: JSON.stringify(body),\n signal: config.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n if (res.status === 404) {\n throw new NotFoundError(`Volume ${volumeId} not found`)\n }\n\n if (!res.ok) {\n throw new VolumeError(`${res.status}: ${res.statusText}`)\n }\n\n const data = await res.json()\n return {\n volumeId: data.volumeID,\n name: data.name,\n token: data.token,\n quotaSizeGiB: data.quotaSizeGiB ?? 0,\n usedSizeBytes: data.usedSizeBytes ?? 0,\n }\n }\n\n /**\n * Destroy a volume.\n *\n * @param volumeId volume ID.\n * @param opts connection options.\n */\n static async destroy(\n volumeId: string,\n opts?: ConnectionOpts\n ): Promise<boolean> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Volume.destroy', VolumeError)\n\n const client = new ApiClient(config)\n\n const res = await client.api.DELETE('/volumes/{volumeID}', {\n params: {\n path: {\n volumeID: volumeId,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.response.status === 404) {\n return false\n }\n\n const err = handleApiError(res, VolumeError)\n if (err) {\n throw err\n }\n\n return true\n }\n}\n\nexport type {\n VolumeInfo,\n VolumeAndToken,\n} from './types'\n","import { NotFoundError, SandboxError, TimeoutError } from '../core'\nimport { ChartTypes } from './charts'\n\nexport async function extractError(res: Response) {\n if (res.ok) {\n return\n }\n\n switch (res.status) {\n case 502:\n return new TimeoutError(\n `${await res.text()}: This error is likely due to sandbox timeout. You can modify the sandbox timeout by passing 'timeoutMs' when starting the sandbox or calling '.setTimeout' on the sandbox with the desired timeout.`\n )\n case 404:\n return new NotFoundError(await res.text())\n default:\n return new SandboxError(`${res.status} ${res.statusText}`)\n }\n}\n\n/**\n * Represents an output message from the sandbox code execution.\n */\nexport class OutputMessage {\n constructor(\n /**\n * The output line.\n */\n public readonly line: string,\n /**\n * Unix epoch in nanoseconds.\n */\n public readonly timestamp: number,\n /**\n * Whether the output is an error.\n */\n public readonly error: boolean\n ) { }\n\n public toString() {\n return this.line\n }\n}\n\n/**\n * Represents an error that occurred during the execution of a cell.\n * The error contains the name of the error, the value of the error, and the traceback.\n */\nexport class ExecutionError {\n constructor(\n /**\n * Name of the error.\n **/\n public name: string,\n /**\n * Value of the error.\n **/\n public value: string,\n /**\n * The raw traceback of the error.\n **/\n public traceback: string\n ) { }\n}\n\n/**\n * Represents a MIME type.\n */\nexport type MIMEType = string\n\n\ntype PPIOSandboxData = {\n data: Record<string, unknown>\n chart: ChartTypes\n}\n\n/**\n * Dictionary that maps MIME types to their corresponding representations of the data.\n */\nexport type RawData = {\n [key: MIMEType]: string\n} & PPIOSandboxData\n\n/**\n * Represents the data to be displayed as a result of executing a cell in a Jupyter notebook.\n * The result is similar to the structure returned by ipython kernel: https://ipython.readthedocs.io/en/stable/development/execution.html#execution-semantics\n *\n *\n * The result can contain multiple types of data, such as text, images, plots, etc. Each type of data is represented\n * as a string, and the result can contain multiple types of data. The display calls don't have to have text representation,\n * for the actual result the representation is always present for the result, the other representations are always optional.\n */\nexport class Result {\n /**\n * Text representation of the result.\n */\n readonly text?: string\n /**\n * HTML representation of the data.\n */\n readonly html?: string\n /**\n * Markdown representation of the data.\n */\n readonly markdown?: string\n /**\n * SVG representation of the data.\n */\n readonly svg?: string\n /**\n * PNG representation of the data.\n */\n readonly png?: string\n /**\n * JPEG representation of the data.\n */\n readonly jpeg?: string\n /**\n * PDF representation of the data.\n */\n readonly pdf?: string\n /**\n * LaTeX representation of the data.\n */\n readonly latex?: string\n /**\n * JSON representation of the data.\n */\n readonly json?: string\n /**\n * JavaScript representation of the data.\n */\n readonly javascript?: string\n /**\n * Contains the data from DataFrame.\n */\n readonly data?: Record<string, unknown>\n /**\n * Contains the chart data.\n */\n readonly chart?: ChartTypes\n /**\n * Extra data that can be included. Not part of the standard types.\n */\n readonly extra?: any\n\n readonly raw: RawData\n\n constructor(rawData: RawData, public readonly isMainResult: boolean) {\n const data = { ...rawData }\n delete data['type']\n delete data['is_main_result']\n\n this.text = data['text']\n this.html = data['html']\n this.markdown = data['markdown']\n this.svg = data['svg']\n this.png = data['png']\n this.jpeg = data['jpeg']\n this.pdf = data['pdf']\n this.latex = data['latex']\n this.json = data['json']\n this.javascript = data['javascript']\n this.isMainResult = isMainResult\n this.raw = data\n\n this.data = data['data']\n this.chart = data['chart']\n\n this.extra = {}\n\n for (const key of Object.keys(data)) {\n if (\n ![\n 'plain',\n 'html',\n 'markdown',\n 'svg',\n 'png',\n 'jpeg',\n 'pdf',\n 'latex',\n 'json',\n 'javascript',\n 'data',\n 'chart',\n 'extra',\n \"text\"\n ].includes(key)\n ) {\n this.extra[key] = data[key]\n }\n }\n }\n\n /**\n * Returns all the formats available for the result.\n *\n * @returns Array of strings representing the formats available for the result.\n */\n formats(): string[] {\n const formats = []\n if (this.html) {\n formats.push('html')\n }\n if (this.markdown) {\n formats.push('markdown')\n }\n if (this.svg) {\n formats.push('svg')\n }\n if (this.png) {\n formats.push('png')\n }\n if (this.jpeg) {\n formats.push('jpeg')\n }\n if (this.pdf) {\n formats.push('pdf')\n }\n if (this.latex) {\n formats.push('latex')\n }\n if (this.json) {\n formats.push('json')\n }\n if (this.javascript) {\n formats.push('javascript')\n }\n if (this.data) {\n formats.push('data')\n }\n\n for (const key of Object.keys(this.extra)) {\n formats.push(key)\n }\n\n return formats\n }\n\n /**\n * Returns the serializable representation of the result.\n */\n toJSON() {\n return {\n text: this.text,\n html: this.html,\n markdown: this.markdown,\n svg: this.svg,\n png: this.png,\n jpeg: this.jpeg,\n pdf: this.pdf,\n latex: this.latex,\n json: this.json,\n javascript: this.javascript,\n ...(Object.keys(this.extra).length > 0 ? { extra: this.extra } : {}),\n }\n }\n}\n\n/**\n * Data printed to stdout and stderr during execution, usually by print statements, logs, warnings, subprocesses, etc.\n */\nexport type Logs = {\n /**\n * List of strings printed to stdout by prints, subprocesses, etc.\n */\n stdout: string[]\n /**\n * List of strings printed to stderr by prints, subprocesses, etc.\n */\n stderr: string[]\n}\n\n/**\n * Represents the result of a cell execution.\n */\nexport class Execution {\n constructor(\n /**\n * List of result of the cell (interactively interpreted last line), display calls (e.g. matplotlib plots).\n */\n public results: Result[] = [],\n /**\n * Logs printed to stdout and stderr during execution.\n */\n public logs: Logs = { stdout: [], stderr: [] },\n /**\n * An Error object if an error occurred, null otherwise.\n */\n public error?: ExecutionError,\n /**\n * Execution count of the cell.\n */\n public executionCount?: number\n ) { }\n\n /**\n * Returns the text representation of the main result of the cell.\n */\n get text(): string | undefined {\n for (const data of this.results) {\n if (data.isMainResult) {\n return data.text\n }\n }\n }\n\n /**\n * Returns the serializable representation of the execution result.\n */\n toJSON() {\n return {\n results: this.results,\n logs: this.logs,\n error: this.error,\n }\n }\n}\n\nexport async function parseOutput(\n execution: Execution,\n line: string,\n onStdout?: (output: OutputMessage) => Promise<any> | any,\n onStderr?: (output: OutputMessage) => Promise<any> | any,\n onResult?: (data: Result) => Promise<any> | any,\n onError?: (error: ExecutionError) => Promise<any> | any\n) {\n const msg = JSON.parse(line)\n\n switch (msg.type) {\n case 'result':\n const result = new Result(\n { ...msg, type: undefined, is_main_result: undefined },\n msg.is_main_result\n )\n execution.results.push(result)\n if (onResult) {\n await onResult(result)\n }\n break\n case 'stdout':\n execution.logs.stdout.push(msg.text)\n if (onStdout) {\n await onStdout({\n error: false,\n line: msg.text,\n timestamp: new Date().getTime() * 1000,\n })\n }\n break\n case 'stderr':\n execution.logs.stderr.push(msg.text)\n if (onStderr) {\n await onStderr({\n error: true,\n line: msg.text,\n timestamp: new Date().getTime() * 1000,\n })\n }\n break\n case 'error':\n execution.error = new ExecutionError(msg.name, msg.value, msg.traceback)\n if (onError) {\n await onError(execution.error)\n }\n break\n case 'number_of_executions':\n execution.executionCount = msg.execution_count\n break\n }\n}\n","import { TimeoutError } from '../core'\n\nexport function formatRequestTimeoutError(error: unknown) {\n if (error instanceof Error && error.name === 'AbortError') {\n return new TimeoutError('Request timed out — the \\'requestTimeoutMs\\' option can be used to increase this timeout')\n }\n\n return error\n}\n\nexport function formatExecutionTimeoutError(error: unknown) {\n if (error instanceof Error && error.name === 'AbortError') {\n return new TimeoutError('Execution timed out — the \\'timeoutMs\\' option can be used to increase this timeout')\n }\n\n return error\n}\n\nexport async function* readLines(stream: ReadableStream<Uint8Array>) {\n const reader = stream.getReader();\n let buffer = ''\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n\n if (value !== undefined) {\n buffer += new TextDecoder().decode(value)\n }\n\n if (done) {\n if (buffer.length > 0) {\n yield buffer\n }\n break\n }\n\n let newlineIdx = -1\n\n do {\n newlineIdx = buffer.indexOf('\\n')\n if (newlineIdx !== -1) {\n yield buffer.slice(0, newlineIdx)\n buffer = buffer.slice(newlineIdx + 1)\n }\n } while (newlineIdx !== -1)\n }\n } finally {\n reader.releaseLock()\n }\n}\n","export const DEFAULT_TIMEOUT_MS = 60_000 // 1 minute\nexport const JUPYTER_PORT = 49999\n","import { Sandbox as BaseSandbox, InvalidArgumentError } from '../core'\n\nimport {\n Result,\n Execution,\n OutputMessage,\n parseOutput,\n extractError,\n ExecutionError,\n} from './messaging'\nimport {\n formatExecutionTimeoutError,\n formatRequestTimeoutError,\n readLines,\n} from './utils'\nimport { JUPYTER_PORT, DEFAULT_TIMEOUT_MS } from './consts'\n\n/**\n * Represents a context for code execution.\n */\nexport type Context = {\n /**\n * The ID of the context.\n */\n id: string\n /**\n * The language of the context.\n */\n language: string\n /**\n * The working directory of the context.\n */\n cwd: string\n}\n\n/**\n * Options for running code.\n */\nexport interface RunCodeOpts {\n /**\n * Callback for handling stdout messages.\n */\n onStdout?: (output: OutputMessage) => Promise<any> | any\n /**\n * Callback for handling stderr messages.\n */\n onStderr?: (output: OutputMessage) => Promise<any> | any\n /**\n * Callback for handling the final execution result.\n */\n onResult?: (data: Result) => Promise<any> | any\n /**\n * Callback for handling the `ExecutionError` object.\n */\n onError?: (error: ExecutionError) => Promise<any> | any\n /**\n * Custom environment variables for code execution.\n *\n * @default {}\n */\n envs?: Record<string, string>\n /**\n * Timeout for the code execution in **milliseconds**.\n *\n * @default 60_000 // 60 seconds\n */\n timeoutMs?: number\n /**\n * Timeout for the request in **milliseconds**.\n *\n * @default 30_000 // 30 seconds\n */\n requestTimeoutMs?: number\n}\n\n/**\n * Options for creating a code context.\n */\nexport interface CreateCodeContextOpts {\n /**\n * Working directory for the context.\n *\n * @default /home/user\n */\n cwd?: string\n /**\n * Language for the context.\n *\n * @default python\n */\n language?: string\n /**\n * Timeout for the request in **milliseconds**.\n *\n * @default 30_000 // 30 seconds\n */\n requestTimeoutMs?: number\n}\n\n/**\n * Options for code context management requests.\n */\nexport interface CodeContextRequestOpts {\n /**\n * Timeout for the request in **milliseconds**.\n *\n * @default 30_000 // 30 seconds\n */\n requestTimeoutMs?: number\n}\n\n/**\n * PPIO agent sandbox is a secure and isolated cloud environment.\n *\n * The sandbox allows you to:\n * - Access Linux OS\n * - Create, list, and delete files and directories\n * - Run commands\n * - Run isolated code\n * - Access the internet\n *\n * Check docs [here](https://ppio.com/docs/sandbox/overview).\n *\n * Use {@link Sandbox.create} to create a new sandbox.\n *\n * @example\n * ```ts\n * import { Sandbox } from '@ppio-sandbox/code-interpreter'\n *\n * const sandbox = await Sandbox.create()\n * ```\n */\nexport class Sandbox extends BaseSandbox {\n protected static override readonly defaultTemplate: string =\n 'code-interpreter-v1'\n\n /**\n * Run the code as Python.\n *\n * Specify the `language` or `context` option to run the code as a different language or in a different `Context`.\n *\n * You can reference previously defined variables, imports, and functions in the code.\n *\n * @param code code to execute.\n * @param opts options for executing the code.\n *\n * @returns `Execution` result object.\n */\n async runCode(\n code: string,\n opts?: RunCodeOpts & {\n /**\n * Language to use for code execution.\n *\n * If not defined, the default Python context is used.\n */\n language?: 'python'\n }\n ): Promise<Execution>\n /**\n * Run the code for the specified language.\n *\n * Specify the `language` or `context` option to run the code as a different language or in a different `Context`.\n * If no language is specified, Python is used.\n *\n * You can reference previously defined variables, imports, and functions in the code.\n *\n * @param code code to execute.\n * @param opts options for executing the code.\n *\n * @returns `Execution` result object.\n */\n async runCode(\n code: string,\n opts?: RunCodeOpts & {\n /**\n * Language to use for code execution.\n *\n * If not defined, the default Python context is used.\n */\n language?: string\n }\n ): Promise<Execution>\n /**\n * Runs the code in the specified context, if not specified, the default context is used.\n *\n * Specify the `language` or `context` option to run the code as a different language or in a different `Context`.\n *\n * You can reference previously defined variables, imports, and functions in the code.\n *\n * @param code code to execute.\n * @param opts options for executing the code\n *\n * @returns `Execution` result object\n */\n async runCode(\n code: string,\n opts?: RunCodeOpts & {\n /**\n * Context to run the code in.\n */\n context?: Context\n }\n ): Promise<Execution>\n async runCode(\n code: string,\n opts?: RunCodeOpts & {\n language?: string\n context?: Context\n }\n ): Promise<Execution> {\n if (opts?.context && opts?.language) {\n throw new InvalidArgumentError(\n 'You can provide context or language, but not both at the same time.'\n )\n }\n\n const controller = new AbortController()\n\n const requestTimeout =\n opts?.requestTimeoutMs ?? this.connectionConfig.requestTimeoutMs\n\n const reqTimer = requestTimeout\n ? setTimeout(() => {\n controller.abort()\n }, requestTimeout)\n : undefined\n\n try {\n const res = await fetch(`${this.jupyterUrl}/execute`, {\n method: 'POST',\n headers: this.jupyterHeaders,\n body: JSON.stringify({\n code,\n context_id: opts?.context?.id,\n language: opts?.language,\n env_vars: opts?.envs,\n }),\n signal: controller.signal,\n keepalive: true,\n })\n\n const error = await extractError(res)\n if (error) {\n throw error\n }\n\n if (!res.body) {\n throw new Error(\n `Not response body: ${res.statusText} ${await res?.text()}`\n )\n }\n\n clearTimeout(reqTimer)\n\n const bodyTimeout = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS\n\n const bodyTimer = bodyTimeout\n ? setTimeout(() => {\n controller.abort()\n }, bodyTimeout)\n : undefined\n\n const execution = new Execution()\n\n try {\n for await (const chunk of readLines(res.body)) {\n await parseOutput(\n execution,\n chunk,\n opts?.onStdout,\n opts?.onStderr,\n opts?.onResult,\n opts?.onError\n )\n }\n } catch (error) {\n throw formatExecutionTimeoutError(error)\n } finally {\n clearTimeout(bodyTimer)\n }\n\n return execution\n } catch (error) {\n throw formatRequestTimeoutError(error)\n }\n }\n\n /**\n * Creates a new context to run code in.\n *\n * @param opts options for creating the context.\n *\n * @returns context object.\n */\n async createCodeContext(opts?: CreateCodeContextOpts): Promise<Context> {\n try {\n const res = await fetch(`${this.jupyterUrl}/contexts`, {\n method: 'POST',\n headers: this.jupyterHeaders,\n body: JSON.stringify({\n language: opts?.language,\n cwd: opts?.cwd,\n }),\n keepalive: true,\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n })\n\n const error = await extractError(res)\n if (error) {\n throw error\n }\n\n return (await res.json()) as Context\n } catch (error) {\n throw formatRequestTimeoutError(error)\n }\n }\n\n /**\n * Lists all code execution contexts in the sandbox.\n *\n * @param opts options for the request.\n *\n * @returns array of context objects.\n */\n async listCodeContexts(opts?: CodeContextRequestOpts): Promise<Context[]> {\n try {\n const res = await fetch(`${this.jupyterUrl}/contexts`, {\n method: 'GET',\n headers: this.jupyterHeaders,\n keepalive: true,\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n })\n\n const error = await extractError(res)\n if (error) {\n throw error\n }\n\n const data = await res.json()\n return Array.isArray(data) ? data : (data.contexts ?? [])\n } catch (error) {\n throw formatRequestTimeoutError(error)\n }\n }\n\n /**\n * Removes a code execution context from the sandbox.\n *\n * @param context context object or context ID to remove.\n * @param opts options for the request.\n */\n async removeCodeContext(\n context: Context | string,\n opts?: CodeContextRequestOpts\n ): Promise<void> {\n const contextID = typeof context === 'string' ? context : context.id\n\n try {\n const res = await fetch(\n `${this.jupyterUrl}/contexts/${encodeURIComponent(contextID)}`,\n {\n method: 'DELETE',\n headers: this.jupyterHeaders,\n keepalive: true,\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n const error = await extractError(res)\n if (error) {\n throw error\n }\n } catch (error) {\n throw formatRequestTimeoutError(error)\n }\n }\n\n /**\n * Restarts a code execution context in the sandbox.\n *\n * @param context context object or context ID to restart.\n * @param opts options for the request.\n */\n async restartCodeContext(\n context: Context | string,\n opts?: CodeContextRequestOpts\n ): Promise<void> {\n const contextID = typeof context === 'string' ? context : context.id\n\n try {\n const res = await fetch(\n `${this.jupyterUrl}/contexts/${encodeURIComponent(contextID)}/restart`,\n {\n method: 'POST',\n headers: this.jupyterHeaders,\n keepalive: true,\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n const error = await extractError(res)\n if (error) {\n throw error\n }\n } catch (error) {\n throw formatRequestTimeoutError(error)\n }\n }\n\n /**\n * Deletes a code execution context from the sandbox.\n *\n * Alias for {@link removeCodeContext}.\n *\n * @param context context object or context ID to delete.\n * @param opts options for the request.\n */\n async deleteCodeContext(\n context: Context | string,\n opts?: CodeContextRequestOpts\n ): Promise<void> {\n return this.removeCodeContext(context, opts)\n }\n\n private get jupyterHeaders(): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n ...this.connectionConfig.headers,\n ...(this.envdAccessToken\n ? { 'X-Access-Token': this.envdAccessToken }\n : {}),\n ...(this.trafficAccessToken\n ? { 'E2B-Traffic-Access-Token': this.trafficAccessToken }\n : {}),\n }\n }\n\n protected get jupyterUrl(): string {\n return `${this.connectionConfig.debug ? 'http' : 'https'}://${this.getHost(\n JUPYTER_PORT\n )}`\n }\n}\n","import { randomBytes } from 'crypto';\n\nexport function generateRandomString(length: number = 16): string {\n const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n const bytes = randomBytes(length);\n let result = '';\n\n for (let i = 0; i < length; i++) {\n result += characters[bytes[i] % characters.length];\n }\n\n return result;\n}","import {\n Sandbox as SandboxBase,\n SandboxOpts as SandboxOptsBase,\n CommandHandle,\n CommandResult,\n CommandExitError,\n ConnectionConfig,\n TimeoutError,\n} from '../core'\n\nimport { generateRandomString } from './utils'\n\ninterface CursorPosition {\n x: number\n y: number\n}\n\ninterface ScreenSize {\n width: number\n height: number\n}\n\nconst MOUSE_BUTTONS = {\n left: 1,\n right: 3,\n middle: 2,\n}\n\nconst KEYS = {\n alt: 'Alt_L',\n alt_left: 'Alt_L',\n alt_right: 'Alt_R',\n backspace: 'BackSpace',\n break: 'Pause',\n caps_lock: 'Caps_Lock',\n cmd: 'Super_L',\n command: 'Super_L',\n control: 'Control_L',\n control_left: 'Control_L',\n control_right: 'Control_R',\n ctrl: 'Control_L',\n del: 'Delete',\n delete: 'Delete',\n down: 'Down',\n end: 'End',\n enter: 'Return',\n esc: 'Escape',\n escape: 'Escape',\n f1: 'F1',\n f2: 'F2',\n f3: 'F3',\n f4: 'F4',\n f5: 'F5',\n f6: 'F6',\n f7: 'F7',\n f8: 'F8',\n f9: 'F9',\n f10: 'F10',\n f11: 'F11',\n f12: 'F12',\n home: 'Home',\n insert: 'Insert',\n left: 'Left',\n menu: 'Menu',\n meta: 'Meta_L',\n num_lock: 'Num_Lock',\n page_down: 'Page_Down',\n page_up: 'Page_Up',\n pause: 'Pause',\n print: 'Print',\n right: 'Right',\n scroll_lock: 'Scroll_Lock',\n shift: 'Shift_L',\n shift_left: 'Shift_L',\n shift_right: 'Shift_R',\n space: 'space',\n super: 'Super_L',\n super_left: 'Super_L',\n super_right: 'Super_R',\n tab: 'Tab',\n up: 'Up',\n win: 'Super_L',\n windows: 'Super_L',\n}\n\nfunction mapKey(key: string): string {\n const lowerKey = key.toLowerCase()\n if (lowerKey in KEYS) {\n return KEYS[lowerKey as keyof typeof KEYS]\n }\n return lowerKey\n}\n\n/**\n * Configuration options for the Sandbox environment.\n * @interface SandboxOpts\n * @extends {SandboxOptsBase}\n */\nexport interface SandboxOpts extends SandboxOptsBase {\n /**\n * The screen resolution in pixels, specified as [width, height].\n * @type {[number, number]}\n */\n resolution?: [number, number]\n\n /**\n * Dots per inch (DPI) setting for the display.\n * @type {number}\n */\n dpi?: number\n\n /**\n * Display identifier.\n * @type {string}\n */\n display?: string\n}\n\nexport class Sandbox extends SandboxBase {\n protected static override readonly defaultTemplate: string = 'desktop'\n private lastXfce4Pid: number | null = null\n public display: string = ':0'\n public stream: VNCServer = new VNCServer(this)\n\n /**\n * Use {@link Sandbox.create} to create a new Sandbox instead.\n *\n * @hidden\n * @hide\n * @internal\n * @access protected\n */\n constructor(\n opts: Omit<SandboxOpts, 'timeoutMs' | 'metadata'> & {\n sandboxId: string\n envdVersion?: string\n }\n ) {\n super({ ...opts, envdVersion: opts.envdVersion ?? '0.0.0' })\n }\n /**\n * Create a new sandbox from the default `desktop` sandbox template.\n *\n * @param opts connection options.\n *\n * @returns sandbox instance for the new sandbox.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * ```\n * @constructs Sandbox\n */\n static async create<S extends typeof Sandbox>(\n this: S,\n opts?: SandboxOpts\n ): Promise<InstanceType<S>>\n /**\n * Create a new sandbox from the specified sandbox template.\n *\n * @param template sandbox template name or ID.\n * @param opts connection options.\n *\n * @returns sandbox instance for the new sandbox.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create('<template-name-or-id>')\n * ```\n * @constructs Sandbox\n */\n static async create<S extends typeof Sandbox>(\n this: S,\n template: string,\n opts?: SandboxOpts\n ): Promise<InstanceType<S>>\n static async create<S extends typeof Sandbox>(\n this: S,\n templateOrOpts?: SandboxOpts | string,\n opts?: SandboxOpts\n ): Promise<InstanceType<S>> {\n const { template, sandboxOpts } =\n typeof templateOrOpts === 'string'\n ? { template: templateOrOpts, sandboxOpts: opts }\n : { template: this.defaultTemplate, sandboxOpts: templateOrOpts }\n\n const config = new ConnectionConfig(sandboxOpts)\n\n // Add DISPLAY environment variable if not already set\n const display = opts?.display || ':0'\n const sandboxOptsWithDisplay = {\n ...sandboxOpts,\n envs: {\n ...sandboxOpts?.envs,\n DISPLAY: display,\n },\n }\n\n let sbx\n if (config.debug) {\n sbx = new this({\n sandboxId: 'desktop',\n ...sandboxOptsWithDisplay,\n ...config,\n }) as InstanceType<S>\n } else {\n const sandbox = await this.createSandbox(\n template,\n sandboxOptsWithDisplay?.timeoutMs ?? this.defaultSandboxTimeoutMs,\n sandboxOptsWithDisplay\n )\n sbx = new this({\n ...sandbox,\n ...sandboxOptsWithDisplay,\n ...config,\n }) as InstanceType<S>\n }\n\n sbx.display = display\n sbx.lastXfce4Pid = null\n sbx.stream = new VNCServer(sbx)\n\n const [width, height] = sandboxOpts?.resolution ?? [1024, 768]\n await sbx.commands.run(\n `Xvfb ${sbx.display} -ac -screen 0 ${width}x${height}x24 ` +\n `-retro -dpi ${sandboxOpts?.dpi ?? 96} -nolisten tcp -nolisten unix`,\n { background: true, timeoutMs: 0 }\n )\n\n let hasStarted = await sbx.waitAndVerify(\n `xdpyinfo -display ${sbx.display}`,\n (r: CommandResult) => r.exitCode === 0\n )\n if (!hasStarted) {\n throw new TimeoutError('Could not start Xvfb')\n }\n\n await sbx.startXfce4()\n\n return sbx\n }\n\n /**\n * Wait for a command to return a specific result.\n * @param cmd - The command to run.\n * @param onResult - The function to check the result of the command.\n * @param timeout - The maximum time to wait for the command to return the result.\n * @param interval - The interval to wait between checks.\n * @returns `true` if the command returned the result within the timeout, otherwise `false`.\n */\n async waitAndVerify(\n cmd: string,\n onResult: (result: CommandResult) => boolean,\n timeout: number = 10,\n interval: number = 0.5\n ): Promise<boolean> {\n let elapsed = 0\n\n while (elapsed < timeout) {\n try {\n if (onResult(await this.commands.run(cmd))) {\n return true\n }\n } catch (e) {\n if (e instanceof CommandExitError) {\n continue\n }\n throw e\n }\n\n await new Promise((resolve) => setTimeout(resolve, interval * 1000))\n elapsed += interval\n }\n\n return false\n }\n\n /**\n * Start xfce4 session if logged out or not running.\n */\n private async startXfce4(): Promise<void> {\n if (\n this.lastXfce4Pid === null ||\n (\n await this.commands.run(\n `ps aux | grep ${this.lastXfce4Pid} | grep -v grep | head -n 1`\n )\n ).stdout\n .trim()\n .includes('[xfce4-session] <defunct>')\n ) {\n const result = await this.commands.run('startxfce4', {\n background: true,\n timeoutMs: 0,\n })\n this.lastXfce4Pid = result.pid\n }\n }\n\n /**\n * Take a screenshot and save it to the given name.\n * @param format - The format of the screenshot.\n * @returns A Uint8Array bytes representation of the screenshot.\n */\n async screenshot(): Promise<Uint8Array>\n /**\n * Take a screenshot and save it to the given name.\n * @param format - The format of the screenshot.\n * @returns A Uint8Array bytes representation of the screenshot.\n */\n async screenshot(format: 'bytes'): Promise<Uint8Array>\n /**\n * Take a screenshot and save it to the given name.\n * @returns A Blob representation of the screenshot.\n */\n async screenshot(format: 'blob'): Promise<Blob>\n /**\n * Take a screenshot and save it to the given name.\n * @returns A ReadableStream of bytes representation of the screenshot.\n */\n async screenshot(format: 'stream'): Promise<ReadableStream<Uint8Array>>\n async screenshot(format: 'bytes' | 'blob' | 'stream' = 'bytes') {\n const path = `/tmp/screenshot-${generateRandomString()}.png`\n await this.commands.run(`scrot --pointer ${path}`)\n\n // @ts-expect-error\n const file = await this.files.read(path, { format })\n this.files.remove(path)\n return file\n }\n\n /**\n * Left click on the mouse position.\n */\n async leftClick(x?: number, y?: number): Promise<void> {\n if (x && y) {\n await this.moveMouse(x, y)\n }\n\n await this.commands.run('xdotool click 1')\n }\n\n /**\n * Double left click on the mouse position.\n */\n async doubleClick(x?: number, y?: number): Promise<void> {\n if (x && y) {\n await this.moveMouse(x, y)\n }\n\n await this.commands.run('xdotool click --repeat 2 1')\n }\n\n /**\n * Right click on the mouse position.\n */\n async rightClick(x?: number, y?: number): Promise<void> {\n if (x && y) {\n await this.moveMouse(x, y)\n }\n\n await this.commands.run('xdotool click 3')\n }\n\n /**\n * Middle click on the mouse position.\n */\n async middleClick(x?: number, y?: number): Promise<void> {\n if (x && y) {\n await this.moveMouse(x, y)\n }\n\n await this.commands.run('xdotool click 2')\n }\n\n /**\n * Scroll the mouse wheel by the given amount.\n * @param direction - The direction to scroll. Can be \"up\" or \"down\".\n * @param amount - The amount to scroll.\n */\n async scroll(\n direction: 'up' | 'down' = 'down',\n amount: number = 1\n ): Promise<void> {\n const button = direction === 'up' ? '4' : '5'\n await this.commands.run(`xdotool click --repeat ${amount} ${button}`)\n }\n\n /**\n * Move the mouse to the given coordinates.\n * @param x - The x coordinate.\n * @param y - The y coordinate.\n */\n async moveMouse(x: number, y: number): Promise<void> {\n await this.commands.run(`xdotool mousemove --sync ${x} ${y}`)\n }\n\n /**\n * Press the mouse button.\n */\n async mousePress(\n button: 'left' | 'right' | 'middle' = 'left'\n ): Promise<void> {\n await this.commands.run(`xdotool mousedown ${MOUSE_BUTTONS[button]}`)\n }\n\n /**\n * Release the mouse button.\n */\n async mouseRelease(\n button: 'left' | 'right' | 'middle' = 'left'\n ): Promise<void> {\n await this.commands.run(`xdotool mouseup ${MOUSE_BUTTONS[button]}`)\n }\n\n /**\n * Get the current cursor position.\n * @returns A object with the x and y coordinates\n * @throws Error if cursor position cannot be determined\n */\n async getCursorPosition(): Promise<CursorPosition> {\n const result = await this.commands.run('xdotool getmouselocation')\n\n const match = result.stdout.match(/x:(\\d+)\\s+y:(\\d+)/)\n if (!match) {\n throw new Error(\n `Failed to parse cursor position from output: ${result.stdout}`\n )\n }\n\n const [, x, y] = match\n if (!x || !y) {\n throw new Error(`Invalid cursor position values: x=${x}, y=${y}`)\n }\n\n return { x: parseInt(x), y: parseInt(y) }\n }\n\n /**\n * Get the current screen size.\n * @returns An {@link ScreenSize} object\n * @throws Error if screen size cannot be determined\n */\n async getScreenSize(): Promise<ScreenSize> {\n const result = await this.commands.run('xrandr')\n\n const match = result.stdout.match(/(\\d+x\\d+)/)\n if (!match) {\n throw new Error(\n `Failed to parse screen size from output: ${result.stdout}`\n )\n }\n\n try {\n const [width, height] = match[1].split('x').map((val) => parseInt(val))\n return { width, height }\n } catch (error) {\n throw new Error(`Invalid screen size format: ${match[1]}`)\n }\n }\n\n private *breakIntoChunks(text: string, n: number): Generator<string> {\n for (let i = 0; i < text.length; i += n) {\n yield text.slice(i, i + n)\n }\n }\n\n private quoteString(s: string): string {\n if (!s) {\n return \"''\"\n }\n\n if (!/[^\\w@%+=:,./-]/.test(s)) {\n return s\n }\n\n // use single quotes, and put single quotes into double quotes\n // the string $'b is then quoted as '$'\"'\"'b'\n return \"'\" + s.replace(/'/g, \"'\\\"'\\\"'\") + \"'\"\n }\n\n /**\n * Write the given text at the current cursor position.\n * @param text - The text to write.\n * @param options - An object containing the chunk size and delay between each chunk of text.\n * @param options.chunkSize - The size of each chunk of text to write. Default is 25 characters.\n * @param options.delayInMs - The delay between each chunk of text. Default is 75 ms.\n */\n async write(\n text: string,\n options: { chunkSize: number; delayInMs: number } = {\n chunkSize: 25,\n delayInMs: 75,\n }\n ): Promise<void> {\n const chunks = this.breakIntoChunks(text, options.chunkSize)\n\n for (const chunk of chunks) {\n await this.commands.run(\n `xdotool type --delay ${options.delayInMs} ${this.quoteString(chunk)}`\n )\n }\n }\n\n /**\n * Press a key.\n * @param key - The key to press (e.g. \"enter\", \"space\", \"backspace\", etc.). Can be a single key or an array of keys.\n */\n async press(key: string | string[]): Promise<void> {\n if (Array.isArray(key)) {\n key = key.map(mapKey).join('+')\n } else {\n key = mapKey(key)\n }\n\n await this.commands.run(`xdotool key ${key}`)\n }\n\n /**\n * Drag the mouse from the given position to the given position.\n * @param from - The starting position.\n * @param to - The ending position.\n */\n async drag(\n [x1, y1]: [number, number],\n [x2, y2]: [number, number]\n ): Promise<void> {\n await this.moveMouse(x1, y1)\n await this.mousePress()\n await this.moveMouse(x2, y2)\n await this.mouseRelease()\n }\n\n /**\n * Wait for the given amount of time.\n * @param ms - The amount of time to wait in milliseconds.\n */\n async wait(ms: number): Promise<void> {\n await this.commands.run(`sleep ${ms / 1000}`)\n }\n\n /**\n * Open a file or a URL in the default application.\n * @param fileOrUrl - The file or URL to open.\n */\n async open(fileOrUrl: string): Promise<void> {\n await this.commands.run(`xdg-open ${fileOrUrl}`, {\n background: true,\n })\n }\n\n /**\n * Get the current window ID.\n * @returns The ID of the current window.\n */\n async getCurrentWindowId(): Promise<string> {\n const result = await this.commands.run('xdotool getwindowfocus')\n return result.stdout.trim()\n }\n\n /**\n * Get the window ID of the window with the given title.\n * @param title - The title of the window.\n * @returns The ID of the window.\n */\n async getApplicationWindows(application: string): Promise<string[]> {\n const result = await this.commands.run(\n `xdotool search --onlyvisible --class ${application}`\n )\n\n return result.stdout.trim().split('\\n')\n }\n\n /**\n * Get the title of the window with the given ID.\n * @param windowId - The ID of the window.\n * @returns The title of the window.\n */\n async getWindowTitle(windowId: string): Promise<string> {\n const result = await this.commands.run(`xdotool getwindowname ${windowId}`)\n\n return result.stdout.trim()\n }\n\n /**\n * Launch an application.\n * @param application - The application to launch.\n * @param uri - The URI to open in the application.\n */\n async launch(application: string, uri?: string): Promise<void> {\n await this.commands.run(`gtk-launch ${application} ${uri ?? ''}`, {\n background: true,\n timeoutMs: 0,\n })\n }\n}\n\ninterface VNCServerOptions {\n vncPort?: number\n port?: number\n requireAuth?: boolean\n windowId?: string\n}\n\ninterface UrlOptions {\n autoConnect?: boolean\n viewOnly?: boolean\n resize?: 'off' | 'scale' | 'remote'\n authKey?: string\n}\n\n// Modified VNCServer class\nclass VNCServer {\n private vncPort: number = 5900\n private port: number = 6080\n private novncAuthEnabled: boolean = false\n private url: URL | null = null\n private novncHandle: CommandHandle | null = null\n private password: string | undefined\n private readonly novncCommand: string\n private readonly desktop: Sandbox\n\n constructor(desktop: Sandbox) {\n this.desktop = desktop\n this.novncCommand =\n `cd /opt/noVNC/utils && ./novnc_proxy --vnc localhost:${this.vncPort} ` +\n `--listen ${this.port} --web /opt/noVNC > /tmp/novnc.log 2>&1`\n }\n\n public getAuthKey(): string {\n if (!this.password) {\n throw new Error(\n 'Unable to retrieve stream auth key, check if requireAuth is enabled'\n )\n }\n\n return this.password\n }\n\n /**\n * Set the VNC command to start the VNC server.\n */\n private async getVNCCommand(windowId?: string): Promise<string> {\n let pwdFlag = '-nopw'\n if (this.novncAuthEnabled) {\n // Create .vnc directory if it doesn't exist\n await this.desktop.commands.run('mkdir -p ~/.vnc')\n await this.desktop.commands.run(\n `x11vnc -storepasswd ${this.password} ~/.vnc/passwd`\n )\n pwdFlag = '-usepw'\n }\n\n return (\n `x11vnc -bg -display ${this.desktop.display} -forever -wait 50 -shared ` +\n `-rfbport ${this.vncPort} ${pwdFlag} 2>/tmp/x11vnc_stderr.log` +\n (windowId ? ` -id ${windowId}` : '')\n )\n }\n\n private async waitForPort(port: number): Promise<boolean> {\n return await this.desktop.waitAndVerify(\n `netstat -tuln | grep \":${port} \"`,\n (r: CommandResult) => r.stdout.trim() !== ''\n )\n }\n\n /**\n * Check if the VNC server is running.\n * @returns Whether the VNC server is running.\n */\n private async checkVNCRunning(): Promise<boolean> {\n try {\n const result = await this.desktop.commands.run('pgrep -x x11vnc')\n return result.stdout.trim() !== ''\n } catch (error) {\n return false\n }\n }\n\n /**\n * Get the URL to a web page with a stream of the desktop sandbox.\n * @param autoConnect - Whether to automatically connect to the server after opening the URL.\n * @param viewOnly - Whether to prevent user interaction through the client.\n * @param resize - Whether to resize the view when the window resizes.\n * @param authKey - The password to use to connect to the server.\n * @returns The URL to connect to the VNC server.\n */\n public getUrl({\n autoConnect = true,\n viewOnly = false,\n resize = 'scale',\n authKey,\n }: UrlOptions = {}): string {\n if (this.url === null) {\n throw new Error('Server is not running')\n }\n\n let url = new URL(this.url)\n if (autoConnect) {\n url.searchParams.set('autoconnect', 'true')\n }\n if (viewOnly) {\n url.searchParams.set('view_only', 'true')\n }\n if (resize) {\n url.searchParams.set('resize', resize)\n }\n if (authKey) {\n url.searchParams.set('password', authKey)\n }\n return url.toString()\n }\n\n /**\n * Start the VNC server.\n */\n public async start(opts: VNCServerOptions = {}): Promise<void> {\n // If stream is already running, throw an error.\n if (await this.checkVNCRunning()) {\n throw new Error('Stream is already running')\n }\n\n this.vncPort = opts.vncPort ?? this.vncPort\n this.port = opts.port ?? this.port\n this.novncAuthEnabled = opts.requireAuth ?? this.novncAuthEnabled\n this.password = this.novncAuthEnabled ? generateRandomString() : undefined\n this.url = new URL(`https://${this.desktop.getHost(this.port)}/vnc.html`)\n\n const vncCommand = await this.getVNCCommand(opts.windowId)\n await this.desktop.commands.run(vncCommand)\n\n this.novncHandle = await this.desktop.commands.run(this.novncCommand, {\n background: true,\n timeoutMs: 0,\n })\n if (!(await this.waitForPort(this.port))) {\n throw new Error('Could not start noVNC server')\n }\n }\n\n /**\n * Stop the VNC server.\n */\n public async stop(): Promise<void> {\n if (await this.checkVNCRunning()) {\n await this.desktop.commands.run('pkill x11vnc')\n }\n\n if (this.novncHandle) {\n await this.novncHandle.kill()\n this.novncHandle = null\n }\n }\n}\n","import { ConnectionOpts } from './connectionConfig';\nimport { Sandbox } from './sandbox';\nimport type { Sandbox as CodeInterpreterSandbox } from '../code-interpreter/sandbox';\nimport type {\n Sandbox as DesktopSandbox,\n SandboxOpts as DesktopSandboxOpts,\n} from '../desktop/sandbox';\nimport type {\n SandboxApiOpts,\n SandboxBetaCreateOpts,\n SandboxCloneOpts,\n SandboxCloneResult,\n SandboxCommitOpts,\n SandboxConnectOpts,\n SandboxEventsOpts,\n SandboxEventsResult,\n SandboxListOpts,\n SandboxMetrics,\n SandboxMetricsOpts,\n SandboxNetworkUpdateOpts,\n SandboxOpts,\n SandboxInfo,\n SandboxQuota,\n SandboxQuotaOpts,\n SandboxResetOpts,\n SandboxCommitResult,\n SnapshotInfo,\n SnapshotListOpts,\n SnapshotPaginator,\n} from './sandbox/sandboxApi';\nimport {\n Template,\n TemplateApi,\n type BuildInfo,\n type BuildOptions,\n type GetBuildStatusOptions,\n type TemplateClass,\n type TemplateDeleteOpts,\n type TemplateInfo,\n type TemplateListOpts,\n type TemplatePaginator,\n type TemplateTag,\n type TemplateTagInfo,\n type TemplateBuildStatusResponse,\n} from './template';\nimport type { TemplateOptions } from './template/types';\nimport { Volume, type VolumeAndToken, type VolumeInfo } from './volume';\nimport { Secret, type SecretBinding, type SecretWriteParams } from './secret';\n\ntype VolumeCreateOpts = ConnectionOpts & {\n quotaSizeGiB?: number;\n quotaInodes?: number;\n};\n\ntype RuntimeSandboxClass<TSandbox, TCreateOpts> = {\n create(opts?: TCreateOpts): Promise<TSandbox>;\n create(template: string, opts?: TCreateOpts): Promise<TSandbox>;\n betaCreate(opts?: SandboxBetaCreateOpts): Promise<TSandbox>;\n betaCreate(template: string, opts?: SandboxBetaCreateOpts): Promise<TSandbox>;\n connect(sandboxId: string, opts?: SandboxConnectOpts): Promise<TSandbox>;\n clone(\n sandboxId: string,\n opts?: SandboxCloneOpts\n ): Promise<SandboxCloneResult<TSandbox>>;\n};\n\ntype RuntimeSandboxLoader<TSandbox, TCreateOpts> = () => Promise<{\n Sandbox: RuntimeSandboxClass<TSandbox, TCreateOpts>;\n}>;\n\nfunction mergeConnectionOpts<T extends ConnectionOpts>(\n base: ConnectionOpts,\n next?: T\n): T {\n const baseHeaders = base.headers ?? {};\n const nextHeaders = next?.headers ?? {};\n\n return {\n ...base,\n ...(next ?? {}),\n headers: {\n ...baseHeaders,\n ...nextHeaders,\n },\n } as T;\n}\n\nclass RuntimeSandboxNamespace<TSandbox, TCreateOpts extends ConnectionOpts> {\n constructor(\n private readonly opts: ConnectionOpts,\n private readonly loadSandbox: RuntimeSandboxLoader<TSandbox, TCreateOpts>\n ) {}\n\n async create(opts?: TCreateOpts): Promise<TSandbox>;\n async create(template: string, opts?: TCreateOpts): Promise<TSandbox>;\n async create(\n templateOrOpts?: string | TCreateOpts,\n opts?: TCreateOpts\n ): Promise<TSandbox> {\n const { Sandbox: RuntimeSandbox } = await this.loadSandbox();\n\n if (typeof templateOrOpts === 'string') {\n return RuntimeSandbox.create(\n templateOrOpts,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n return RuntimeSandbox.create(\n mergeConnectionOpts(this.opts, templateOrOpts)\n );\n }\n\n async betaCreate(opts?: SandboxBetaCreateOpts): Promise<TSandbox>;\n async betaCreate(\n template: string,\n opts?: SandboxBetaCreateOpts\n ): Promise<TSandbox>;\n async betaCreate(\n templateOrOpts?: string | SandboxBetaCreateOpts,\n opts?: SandboxBetaCreateOpts\n ): Promise<TSandbox> {\n const { Sandbox: RuntimeSandbox } = await this.loadSandbox();\n\n if (typeof templateOrOpts === 'string') {\n return RuntimeSandbox.betaCreate(\n templateOrOpts,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n return RuntimeSandbox.betaCreate(\n mergeConnectionOpts(this.opts, templateOrOpts)\n );\n }\n\n async connect(\n sandboxId: string,\n opts?: SandboxConnectOpts\n ): Promise<TSandbox> {\n const { Sandbox: RuntimeSandbox } = await this.loadSandbox();\n\n return RuntimeSandbox.connect(\n sandboxId,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n get(sandboxId: string, opts?: SandboxConnectOpts): Promise<TSandbox> {\n return this.connect(sandboxId, opts);\n }\n\n list(opts?: SandboxListOpts) {\n return Sandbox.list(mergeConnectionOpts(this.opts, opts));\n }\n\n kill(sandboxId: string, opts?: SandboxApiOpts): Promise<boolean> {\n return Sandbox.kill(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n pause(sandboxId: string, opts?: SandboxApiOpts): Promise<boolean> {\n return Sandbox.pause(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n betaPause(sandboxId: string, opts?: SandboxApiOpts): Promise<boolean> {\n return Sandbox.betaPause(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n async clone(\n sandboxId: string,\n opts?: SandboxCloneOpts\n ): Promise<SandboxCloneResult<TSandbox>> {\n const { Sandbox: RuntimeSandbox } = await this.loadSandbox();\n\n return RuntimeSandbox.clone(\n sandboxId,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n reset(sandboxId: string, opts?: SandboxResetOpts): Promise<boolean> {\n return Sandbox.reset(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n commit(sandboxId: string, opts?: SandboxCommitOpts): Promise<SandboxCommitResult> {\n return Sandbox.commit(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n setNetwork(\n sandboxId: string,\n opts?: SandboxNetworkUpdateOpts\n ): Promise<void> {\n return Sandbox.setNetwork(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n createSnapshot(\n sandboxId: string,\n opts?: SandboxApiOpts\n ): Promise<SnapshotInfo> {\n return Sandbox.createSnapshot(\n sandboxId,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n listSnapshots(opts?: SnapshotListOpts): SnapshotPaginator {\n return Sandbox.listSnapshots(mergeConnectionOpts(this.opts, opts));\n }\n\n deleteSnapshot(snapshotId: string, opts?: SandboxApiOpts): Promise<boolean> {\n return Sandbox.deleteSnapshot(\n snapshotId,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n setTimeout(\n sandboxId: string,\n timeoutMs: number,\n opts?: SandboxApiOpts\n ): Promise<void> {\n return Sandbox.setTimeout(\n sandboxId,\n timeoutMs,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n getInfo(sandboxId: string, opts?: SandboxApiOpts): Promise<SandboxInfo> {\n return Sandbox.getInfo(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n getMetrics(\n sandboxId: string,\n opts?: SandboxMetricsOpts\n ): Promise<SandboxMetrics[]> {\n return Sandbox.getMetrics(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n getQuota(opts?: SandboxQuotaOpts): Promise<SandboxQuota> {\n return Sandbox.getQuota(mergeConnectionOpts(this.opts, opts));\n }\n\n getEvents(opts?: SandboxEventsOpts): Promise<SandboxEventsResult> {\n return Sandbox.getEvents(mergeConnectionOpts(this.opts, opts));\n }\n\n}\n\nclass SandboxNamespace {\n constructor(private readonly opts: ConnectionOpts) {}\n\n async create(opts?: SandboxOpts): Promise<Sandbox>;\n async create(template: string, opts?: SandboxOpts): Promise<Sandbox>;\n async create(\n templateOrOpts?: string | SandboxOpts,\n opts?: SandboxOpts\n ): Promise<Sandbox> {\n if (typeof templateOrOpts === 'string') {\n return Sandbox.create(\n templateOrOpts,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n return Sandbox.create(mergeConnectionOpts(this.opts, templateOrOpts));\n }\n\n async betaCreate(opts?: SandboxBetaCreateOpts): Promise<Sandbox>;\n async betaCreate(\n template: string,\n opts?: SandboxBetaCreateOpts\n ): Promise<Sandbox>;\n async betaCreate(\n templateOrOpts?: string | SandboxBetaCreateOpts,\n opts?: SandboxBetaCreateOpts\n ): Promise<Sandbox> {\n if (typeof templateOrOpts === 'string') {\n return Sandbox.betaCreate(\n templateOrOpts,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n return Sandbox.betaCreate(mergeConnectionOpts(this.opts, templateOrOpts));\n }\n\n async connect(\n sandboxId: string,\n opts?: SandboxConnectOpts\n ): Promise<Sandbox> {\n return Sandbox.connect(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n async get(sandboxId: string, opts?: SandboxConnectOpts): Promise<Sandbox> {\n return this.connect(sandboxId, opts);\n }\n\n list(opts?: SandboxListOpts) {\n return Sandbox.list(mergeConnectionOpts(this.opts, opts));\n }\n\n async kill(sandboxId: string, opts?: SandboxApiOpts): Promise<boolean> {\n return Sandbox.kill(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n setTimeout(\n sandboxId: string,\n timeoutMs: number,\n opts?: SandboxApiOpts\n ): Promise<void> {\n return Sandbox.setTimeout(\n sandboxId,\n timeoutMs,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n getInfo(sandboxId: string, opts?: SandboxApiOpts): Promise<SandboxInfo> {\n return Sandbox.getInfo(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n getMetrics(\n sandboxId: string,\n opts?: SandboxMetricsOpts\n ): Promise<SandboxMetrics[]> {\n return Sandbox.getMetrics(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n pause(sandboxId: string, opts?: SandboxApiOpts): Promise<boolean> {\n return Sandbox.pause(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n betaPause(sandboxId: string, opts?: SandboxApiOpts): Promise<boolean> {\n return Sandbox.betaPause(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n clone(\n sandboxId: string,\n opts?: SandboxCloneOpts\n ): Promise<SandboxCloneResult<Sandbox>> {\n return Sandbox.clone(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n reset(sandboxId: string, opts?: SandboxResetOpts): Promise<boolean> {\n return Sandbox.reset(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n commit(sandboxId: string, opts?: SandboxCommitOpts): Promise<SandboxCommitResult> {\n return Sandbox.commit(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n setNetwork(\n sandboxId: string,\n opts?: SandboxNetworkUpdateOpts\n ): Promise<void> {\n return Sandbox.setNetwork(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n createSnapshot(\n sandboxId: string,\n opts?: SandboxApiOpts\n ): Promise<SnapshotInfo> {\n return Sandbox.createSnapshot(\n sandboxId,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n listSnapshots(opts?: SnapshotListOpts): SnapshotPaginator {\n return Sandbox.listSnapshots(mergeConnectionOpts(this.opts, opts));\n }\n\n deleteSnapshot(snapshotId: string, opts?: SandboxApiOpts): Promise<boolean> {\n return Sandbox.deleteSnapshot(\n snapshotId,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n getQuota(opts?: SandboxQuotaOpts): Promise<SandboxQuota> {\n return Sandbox.getQuota(mergeConnectionOpts(this.opts, opts));\n }\n\n getEvents(opts?: SandboxEventsOpts): Promise<SandboxEventsResult> {\n return Sandbox.getEvents(mergeConnectionOpts(this.opts, opts));\n }\n\n}\n\nclass TemplateNamespace {\n constructor(private readonly opts: ConnectionOpts) {}\n\n new(options?: TemplateOptions) {\n return Template(options);\n }\n\n list(opts?: TemplateListOpts): TemplatePaginator {\n return Template.list(mergeConnectionOpts(this.opts, opts));\n }\n\n get(templateId: string, opts?: ConnectionOpts) {\n return Template.get(templateId, mergeConnectionOpts(this.opts, opts));\n }\n\n delete(templateId: string, opts?: TemplateDeleteOpts): Promise<boolean> {\n return TemplateApi.deleteTemplate(\n templateId,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n async build(\n template: TemplateClass,\n name: string,\n options?: Omit<BuildOptions, 'alias'>\n ): Promise<BuildInfo>;\n async build(\n template: TemplateClass,\n options: BuildOptions\n ): Promise<BuildInfo>;\n async build(\n template: TemplateClass,\n nameOrOptions: string | BuildOptions,\n options?: Omit<BuildOptions, 'alias'>\n ): Promise<BuildInfo> {\n if (typeof nameOrOptions === 'string') {\n return Template.build(\n template,\n nameOrOptions,\n mergeConnectionOpts(this.opts, options)\n );\n }\n\n return Template.build(\n template,\n mergeConnectionOpts(this.opts, nameOrOptions)\n );\n }\n\n async buildInBackground(\n template: TemplateClass,\n name: string,\n options?: Omit<BuildOptions, 'alias'>\n ): Promise<BuildInfo>;\n async buildInBackground(\n template: TemplateClass,\n options: BuildOptions\n ): Promise<BuildInfo>;\n async buildInBackground(\n template: TemplateClass,\n nameOrOptions: string | BuildOptions,\n options?: Omit<BuildOptions, 'alias'>\n ): Promise<BuildInfo> {\n if (typeof nameOrOptions === 'string') {\n return Template.buildInBackground(\n template,\n nameOrOptions,\n mergeConnectionOpts(this.opts, options)\n );\n }\n\n return Template.buildInBackground(\n template,\n mergeConnectionOpts(this.opts, nameOrOptions)\n );\n }\n\n getBuildStatus(\n data: Pick<BuildInfo, 'templateId' | 'buildId'>,\n options?: GetBuildStatusOptions\n ): Promise<TemplateBuildStatusResponse> {\n return Template.getBuildStatus(\n data,\n mergeConnectionOpts(this.opts, options)\n );\n }\n\n exists(name: string, options?: ConnectionOpts): Promise<boolean> {\n return Template.exists(name, mergeConnectionOpts(this.opts, options));\n }\n\n aliasExists(alias: string, options?: ConnectionOpts): Promise<boolean> {\n return Template.aliasExists(alias, mergeConnectionOpts(this.opts, options));\n }\n\n assignTags(\n targetName: string,\n tags: string | string[],\n options?: ConnectionOpts\n ): Promise<TemplateTagInfo> {\n return Template.assignTags(\n targetName,\n tags,\n mergeConnectionOpts(this.opts, options)\n );\n }\n\n removeTags(\n name: string,\n tags: string | string[],\n options?: ConnectionOpts\n ): Promise<void> {\n return Template.removeTags(\n name,\n tags,\n mergeConnectionOpts(this.opts, options)\n );\n }\n\n getTags(\n templateId: string,\n options?: ConnectionOpts\n ): Promise<TemplateTag[]> {\n return Template.getTags(\n templateId,\n mergeConnectionOpts(this.opts, options)\n );\n }\n\n toJSON = Template.toJSON;\n toDockerfile = Template.toDockerfile;\n}\n\nclass VolumeNamespace {\n constructor(private readonly opts: ConnectionOpts) {}\n\n create(name: string, opts?: VolumeCreateOpts): Promise<Volume> {\n return Volume.create(name, mergeConnectionOpts(this.opts, opts));\n }\n\n connect(volumeId: string, opts?: ConnectionOpts): Promise<Volume> {\n return Volume.connect(volumeId, mergeConnectionOpts(this.opts, opts));\n }\n\n getInfo(volumeId: string, opts?: ConnectionOpts): Promise<VolumeAndToken> {\n return Volume.getInfo(volumeId, mergeConnectionOpts(this.opts, opts));\n }\n\n list(opts?: ConnectionOpts): Promise<VolumeInfo[]> {\n return Volume.list(mergeConnectionOpts(this.opts, opts));\n }\n\n updateQuota(\n volumeId: string,\n params: { quotaSizeGiB?: number; quotaInodes?: number },\n opts?: ConnectionOpts\n ): Promise<VolumeAndToken> {\n return Volume.updateQuota(\n volumeId,\n params,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n destroy(volumeId: string, opts?: ConnectionOpts): Promise<boolean> {\n return Volume.destroy(volumeId, mergeConnectionOpts(this.opts, opts));\n }\n}\n\nclass SecretNamespace {\n constructor(private readonly opts: ConnectionOpts) {}\n\n create(\n params: SecretWriteParams,\n opts?: ConnectionOpts\n ): Promise<SecretBinding> {\n return Secret.create(params, mergeConnectionOpts(this.opts, opts));\n }\n\n list(opts?: ConnectionOpts): Promise<SecretBinding[]> {\n return Secret.list(mergeConnectionOpts(this.opts, opts));\n }\n\n get(name: string, opts?: ConnectionOpts): Promise<SecretBinding> {\n return Secret.get(name, mergeConnectionOpts(this.opts, opts));\n }\n\n update(\n params: SecretWriteParams,\n opts?: ConnectionOpts\n ): Promise<SecretBinding> {\n return Secret.update(params, mergeConnectionOpts(this.opts, opts));\n }\n\n delete(name: string, opts?: ConnectionOpts): Promise<string> {\n return Secret.delete(name, mergeConnectionOpts(this.opts, opts));\n }\n}\n\n/**\n * High-level PPIO client for accessing core SDK resources.\n */\nexport class PPIO {\n readonly sandbox: SandboxNamespace;\n readonly template: TemplateNamespace;\n readonly volume: VolumeNamespace;\n readonly secret: SecretNamespace;\n readonly codeInterpreter: RuntimeSandboxNamespace<\n CodeInterpreterSandbox,\n SandboxOpts\n >;\n readonly code_interpreter: RuntimeSandboxNamespace<\n CodeInterpreterSandbox,\n SandboxOpts\n >;\n readonly desktop: RuntimeSandboxNamespace<DesktopSandbox, DesktopSandboxOpts>;\n\n constructor(private readonly opts: ConnectionOpts = {}) {\n this.sandbox = new SandboxNamespace(opts);\n this.template = new TemplateNamespace(opts);\n this.volume = new VolumeNamespace(opts);\n this.secret = new SecretNamespace(opts);\n this.codeInterpreter = new RuntimeSandboxNamespace<\n CodeInterpreterSandbox,\n SandboxOpts\n >(\n opts,\n () =>\n import('../code-interpreter/sandbox') as Promise<{\n Sandbox: RuntimeSandboxClass<CodeInterpreterSandbox, SandboxOpts>;\n }>\n );\n this.code_interpreter = this.codeInterpreter;\n this.desktop = new RuntimeSandboxNamespace<\n DesktopSandbox,\n DesktopSandboxOpts\n >(\n opts,\n () =>\n import('../desktop/sandbox') as Promise<{\n Sandbox: RuntimeSandboxClass<DesktopSandbox, DesktopSandboxOpts>;\n }>\n );\n }\n\n async create(opts?: SandboxOpts): Promise<Sandbox>;\n async create(template: string, opts?: SandboxOpts): Promise<Sandbox>;\n async create(\n templateOrOpts?: string | SandboxOpts,\n opts?: SandboxOpts\n ): Promise<Sandbox> {\n if (typeof templateOrOpts === 'string') {\n return this.sandbox.create(templateOrOpts, opts);\n }\n\n return this.sandbox.create(templateOrOpts);\n }\n\n connect(sandboxId: string, opts?: SandboxConnectOpts): Promise<Sandbox> {\n return this.sandbox.connect(sandboxId, opts);\n }\n\n get(sandboxId: string, opts?: SandboxConnectOpts): Promise<Sandbox> {\n return this.sandbox.get(sandboxId, opts);\n }\n}\n","/**\n * CIDR range that represents all traffic.\n */\nexport const ALL_TRAFFIC = '0.0.0.0/0'\n","export { ApiClient } from './api'\nexport type { components, paths } from './api'\n\nexport { PPIO } from './client'\n\nexport { ConnectionConfig } from './connectionConfig'\nexport type { ConnectionOpts, Username } from './connectionConfig'\nexport {\n AuthenticationError,\n FileNotFoundError,\n GitAuthError,\n GitUpstreamError,\n InvalidArgumentError,\n NotEnoughSpaceError,\n NotFoundError,\n SandboxError,\n SandboxNotFoundError,\n TemplateError,\n TimeoutError,\n RateLimitError,\n BuildError,\n FileUploadError,\n SecretError,\n VolumeError,\n} from './errors'\nexport type { Logger } from './logs'\n\nexport { getSignature } from './sandbox/signature'\n\nexport { FileType } from './sandbox/filesystem'\nexport type {\n WriteInfo,\n EntryInfo,\n Filesystem,\n FilesystemWriteOpts,\n FilesystemReadOpts,\n} from './sandbox/filesystem'\nexport { FilesystemEventType } from './sandbox/filesystem/watchHandle'\nexport type {\n FilesystemEvent,\n WatchHandle,\n} from './sandbox/filesystem/watchHandle'\n\nexport { CommandExitError } from './sandbox/commands/commandHandle'\nexport type {\n CommandResult,\n Stdout,\n Stderr,\n PtyOutput,\n CommandHandle,\n} from './sandbox/commands/commandHandle'\nexport type {\n SandboxInfo,\n SandboxMetrics,\n SandboxOpts,\n SandboxApiOpts,\n SandboxConnectOpts,\n SandboxBetaCreateOpts,\n SandboxMetricsOpts,\n SandboxCloneOpts,\n SandboxCloneResult,\n SandboxCommitOpts,\n SandboxCommitResult,\n SandboxResetOpts,\n SandboxState,\n SandboxListOpts,\n SandboxPaginator,\n SandboxNetworkOpts,\n SandboxNetworkUpdateOpts,\n SandboxLifecycle,\n SandboxInfoLifecycle,\n SnapshotInfo,\n SnapshotListOpts,\n SnapshotPaginator,\n SandboxQuota,\n SandboxQuotaLimit,\n SandboxQuotaUsage,\n SandboxQuotaOpts,\n SandboxEventItem,\n SandboxEventsOpts,\n SandboxEventsResult,\n} from './sandbox/sandboxApi'\n\nexport type { McpServer } from './sandbox/mcp'\n\nexport { ALL_TRAFFIC } from './sandbox/network'\n\nexport type {\n ProcessInfo,\n CommandRequestOpts,\n CommandConnectOpts,\n CommandStartOpts,\n Commands,\n Pty,\n} from './sandbox/commands'\n\nexport { Git } from './sandbox/git'\nexport type {\n GitRequestOpts,\n GitCloneOpts,\n GitInitOpts,\n GitRemoteAddOpts,\n GitCommitOpts,\n GitAddOpts,\n GitDeleteBranchOpts,\n GitPushOpts,\n GitPullOpts,\n GitDangerouslyAuthenticateOpts,\n GitConfigOpts,\n GitConfigScope,\n GitBranches,\n GitFileStatus,\n GitStatus,\n} from './sandbox/git'\n\nexport { Volume } from './volume'\nexport type { VolumeInfo, VolumeAndToken } from './volume'\n\nexport { Secret } from './secret'\nexport type { SecretBinding, SecretWriteParams } from './secret'\n\nexport { Sandbox }\nimport { Sandbox } from './sandbox'\n\nexport default Sandbox\n\nexport * from './template'\n\nexport {\n ReadyCmd,\n waitForPort,\n waitForURL,\n waitForProcess,\n waitForFile,\n waitForTimeout,\n} from './template/readycmd'\n\nexport {\n LogEntry,\n LogEntryStart,\n LogEntryEnd,\n type LogEntryLevel,\n defaultBuildLogger,\n} from './template/logger'\n\nexport {\n type ImageConfig,\n type RegistryCredentials,\n clearImageConfigCache,\n effectiveStartCmd,\n fetchImageConfig,\n parseImageRef,\n unsupportedBase,\n} from './template/imageConfig'\n","export * from '../core'\n\nexport { Sandbox } from './sandbox'\nexport type {\n Context,\n RunCodeOpts,\n CreateCodeContextOpts,\n CodeContextRequestOpts,\n} from './sandbox'\nexport type {\n Logs,\n ExecutionError,\n Result,\n Execution,\n MIMEType,\n RawData,\n OutputMessage,\n} from './messaging'\nexport type {\n ScaleType,\n ChartType,\n ChartTypes,\n Chart,\n BarChart,\n BarData,\n LineChart,\n ScatterChart,\n BoxAndWhiskerChart,\n BoxAndWhiskerData,\n PieChart,\n PieData,\n SuperChart,\n PointData,\n} from './charts'\nimport { Sandbox } from './sandbox'\n\nexport default Sandbox\n"],"mappings":"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","names":["_a","platform","module","import_platform","platform","_a","request","_a","message","createClient","_a","_a","import_openapi_fetch","init_api","createClient","DEFAULT_ERROR_MAP","import_connect","_a","import_connect","init_api","_a","pid","import_connect","import_compare_versions","init_api","_a","pid","import_codegenv2","FilesystemEventType","_a","import_connect","import_compare_versions","FileType","Filesystem","init_api","path","_a","name","path","init_utils","init_utils","_a","path","fetch","paths","path","_a","_a","e","import_compare_versions","res","err","path","_b","sandboxId","body","path","import_compare_versions","init_api","_a","Filesystem","path","chalk","path","_a","fs","crypto","stats","content","init_utils","_a","init_utils","fs","_a","import_node_fs","_a","_a","init_utils","version","src","path","paths","_b","_c","_d","_a","init_utils","init_consts","Sandbox","init_sandbox","init_utils","init_consts","_a","error","init_utils","sandbox_exports","Sandbox","init_sandbox","init_utils","_a","path","_a","FileType","Sandbox","init_sandbox"]}
|
|
1
|
+
{"version":3,"sources":["../package.json","../src/core/utils.ts","../src/core/api/metadata.ts","../src/core/errors.ts","../src/core/logs.ts","../src/core/api/index.ts","../src/core/connectionConfig.ts","../src/core/envd/api.ts","../src/core/envd/process/process_pb.ts","../src/core/envd/versions.ts","../src/core/envd/rpc.ts","../src/core/sandbox/commands/commandHandle.ts","../src/core/sandbox/commands/pty.ts","../src/core/sandbox/commands/index.ts","../src/core/envd/filesystem/filesystem_pb.ts","../src/core/sandbox/filesystem/watchHandle.ts","../src/core/sandbox/filesystem/index.ts","../src/core/sandbox/git/utils.ts","../src/core/sandbox/git/index.ts","../src/core/secret/index.ts","../src/core/sandbox/sandboxApi.ts","../src/core/sandbox/signature.ts","../src/core/sandbox/index.ts","../src/core/template/logger.ts","../src/core/template/consts.ts","../src/core/template/utils.ts","../src/core/template/buildApi.ts","../src/core/template/readycmd.ts","../src/core/template/dockerfileParser.ts","../src/core/template/envFiles.ts","../src/core/template/imageConfig.ts","../src/core/template/types.ts","../src/core/template/index.ts","../src/core/volume/index.ts","../src/code-interpreter/messaging.ts","../src/code-interpreter/utils.ts","../src/code-interpreter/consts.ts","../src/code-interpreter/sandbox.ts","../src/desktop/utils.ts","../src/desktop/sandbox.ts","../src/core/client.ts","../src/core/sandbox/network.ts","../src/core/index.ts","../src/code-interpreter/index.ts"],"sourcesContent":["{\n \"name\": \"ppio-sandbox\",\n \"version\": \"2.1.1\",\n \"description\": \"PPIO Sandbox SDK for JavaScript/TypeScript - A comprehensive SDK for code execution, desktop automation, and cloud computing environments\",\n \"main\": \"dist/index.js\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.js\"\n },\n \"./code-interpreter\": {\n \"types\": \"./dist/code-interpreter.d.ts\",\n \"import\": \"./dist/code-interpreter.mjs\",\n \"require\": \"./dist/code-interpreter.js\"\n },\n \"./desktop\": {\n \"types\": \"./dist/desktop.d.ts\",\n \"import\": \"./dist/desktop.mjs\",\n \"require\": \"./dist/desktop.js\"\n }\n },\n \"files\": [\n \"dist/**/*\",\n \"README.md\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"check-deps\": \"knip\",\n \"update-deps\": \"ncu -u && pnpm i\",\n \"build\": \"tsc --noEmit && tsup\",\n \"dev\": \"tsup --watch\",\n \"lint:fix\": \"eslint src/**/*.ts --fix\",\n \"lint\": \"eslint src/**/*.ts tests/**/*.ts\",\n \"format\": \"prettier --write src/**/*.ts\",\n \"clean\": \"rimraf dist\",\n \"prepublishOnly\": \"pnpm build\",\n \"test:core\": \"vitest run ./src/core/ --reporter verbose --run\",\n \"test:code-interpreter\": \"vitest run ./src/code-interpreter/ --reporter verbose --run\",\n \"test:desktop\": \"vitest run ./src/desktop/ --reporter verbose --run\",\n \"generate:api\": \"python ./spec/remove_extra_tags.py sandboxes templates auth && openapi-typescript ./spec/openapi_generated.yml -x api_key --array-length --alphabetize --output src/core/api/schema.gen.ts\",\n \"generate:envd-api\": \"openapi-typescript ./spec/envd/envd.yaml -x api_key --array-length --alphabetize --output src/core/envd/schema.gen.ts\"\n },\n \"keywords\": [\n \"ppio\",\n \"ai-agent\",\n \"sandbox\",\n \"sdk\",\n \"typescript\",\n \"javascript\",\n \"code-interpreter\",\n \"desktop-automation\",\n \"cloud-computing\",\n \"remote-execution\",\n \"api-client\"\n ],\n \"author\": {\n \"name\": \"PPIO\",\n \"url\": \"https://ppio.com\"\n },\n \"engines\": {\n \"node\": \">=20\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^20.0.0\",\n \"@types/platform\": \"^1.3.6\",\n \"@types/react\": \"^19.1.12\",\n \"@typescript-eslint/eslint-plugin\": \"^6.0.0\",\n \"@typescript-eslint/parser\": \"^6.0.0\",\n \"eslint\": \"^8.0.0\",\n \"eslint-config-prettier\": \"^9.0.0\",\n \"eslint-plugin-prettier\": \"^5.0.0\",\n \"knip\": \"^5.43.6\",\n \"prettier\": \"^3.0.0\",\n \"react\": \"^18.3.1\",\n \"rimraf\": \"^5.0.0\",\n \"ts-jest\": \"^29.1.0\",\n \"ts-node\": \"^10.9.0\",\n \"typescript\": \"^5.0.0\",\n \"vitest\": \"^3.1.1\",\n \"tsup\": \"^8.4.0\",\n \"openapi-typescript\": \"^7.6.1\"\n },\n \"dependencies\": {\n \"@bufbuild/protobuf\": \"^2.6.2\",\n \"@connectrpc/connect\": \"2.0.0-rc.3\",\n \"@connectrpc/connect-web\": \"2.0.0-rc.3\",\n \"chalk\": \"^5.3.0\",\n \"compare-versions\": \"^6.1.0\",\n \"dockerfile-ast\": \"^0.7.1\",\n \"glob\": \"^11.1.0\",\n \"openapi-fetch\": \"^0.14.1\",\n \"platform\": \"^1.3.6\",\n \"tar\": \"^7.5.11\"\n },\n \"bugs\": {\n \"url\": \"https://ppio.com/about?index=2\"\n },\n \"homepage\": \"https://ppio.com/ai-computing/sandbox\",\n \"packageManager\": \"pnpm@10.17.0+sha512.fce8a3dd29a4ed2ec566fb53efbb04d8c44a0f05bc6f24a73046910fb9c3ce7afa35a0980500668fa3573345bd644644fa98338fa168235c80f4aa17aa17fbef\"\n}\n","import platform from 'platform'\n\ndeclare let window: any\n\ntype Runtime =\n | 'node'\n | 'browser'\n | 'deno'\n | 'bun'\n | 'vercel-edge'\n | 'cloudflare-worker'\n | 'unknown'\n\nfunction getRuntime(): { runtime: Runtime; version: string } {\n // @ts-ignore\n if ((globalThis as any).Bun) {\n // @ts-ignore\n return { runtime: 'bun', version: globalThis.Bun.version }\n }\n\n // @ts-ignore\n if ((globalThis as any).Deno) {\n // @ts-ignore\n return { runtime: 'deno', version: globalThis.Deno.version.deno }\n }\n\n if ((globalThis as any).process?.release?.name === 'node') {\n return { runtime: 'node', version: platform.version || 'unknown' }\n }\n\n // @ts-ignore\n if (typeof EdgeRuntime === 'string') {\n return { runtime: 'vercel-edge', version: 'unknown' }\n }\n\n if ((globalThis as any).navigator?.userAgent === 'Cloudflare-Workers') {\n return { runtime: 'cloudflare-worker', version: 'unknown' }\n }\n\n if (typeof window !== 'undefined') {\n return { runtime: 'browser', version: platform.version || 'unknown' }\n }\n\n return { runtime: 'unknown', version: 'unknown' }\n}\n\nexport const { runtime, version: runtimeVersion } = getRuntime()\n\nexport async function sha256(data: string): Promise<string> {\n // Use WebCrypto API if available\n if (typeof crypto !== 'undefined') {\n const encoder = new TextEncoder()\n const dataBuffer = encoder.encode(data)\n const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer)\n const hashArray = new Uint8Array(hashBuffer)\n return btoa(String.fromCharCode(...hashArray))\n }\n\n // Use Node.js crypto if WebCrypto is not available\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const { createHash } = require('node:crypto')\n const hash = createHash('sha256').update(data, 'utf8').digest()\n return hash.toString('base64')\n}\n\nexport function timeoutToSeconds(timeout: number): number {\n return Math.ceil(timeout / 1000)\n}\n\nexport function dynamicRequire<T>(module: string): T {\n if (runtime === 'browser') {\n throw new Error('Browser runtime is not supported for require')\n }\n\n return require(module)\n}\n\nexport async function dynamicImport<T>(module: string): Promise<T> {\n if (runtime === 'browser') {\n throw new Error('Browser runtime is not supported for dynamic import')\n }\n\n // @ts-ignore\n return await import(module)\n}\n\n// Source: https://github.com/chalk/ansi-regex/blob/main/index.js\nfunction ansiRegex({ onlyFirst = false } = {}) {\n // Valid string terminator sequences are BEL, ESC\\, and 0x9c\n const ST = '(?:\\\\u0007|\\\\u001B\\\\u005C|\\\\u009C)'\n // OSC sequences only: ESC ] ... ST (non-greedy until the first ST)\n const osc = `(?:\\\\u001B\\\\][\\\\s\\\\S]*?${ST})`\n // CSI and related: ESC/C1, optional intermediates, optional params (supports ; and :) then final byte\n const csi =\n '[\\\\u001B\\\\u009B][[\\\\]()#;?]*(?:\\\\d{1,4}(?:[;:]\\\\d{0,4})*)?[\\\\dA-PR-TZcf-nq-uy=><~]'\n\n const pattern = `${osc}|${csi}`\n\n return new RegExp(pattern, onlyFirst ? undefined : 'g')\n}\n\nexport function stripAnsi(text: string): string {\n return text.replace(ansiRegex(), '')\n}\n\nexport async function wait(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n/**\n * Convert data to a Blob, avoiding unnecessary conversions when possible.\n */\nexport function toBlob(\n data: string | ArrayBuffer | Blob | ReadableStream\n): Blob | Promise<Blob> {\n // Already a Blob - use directly\n if (data instanceof Blob) {\n return data\n }\n // String or ArrayBuffer - create Blob\n if (typeof data === 'string' || data instanceof ArrayBuffer) {\n return new Blob([data])\n }\n // ReadableStream - must consume to get Blob\n return new Response(data).blob()\n}\n\n/**\n * Escape a string for safe inclusion in a single-quoted shell argument.\n * Equivalent to Python's shlex.quote().\n */\nexport function shellQuote(s: string): string {\n return \"'\" + s.replace(/'/g, \"'\\\\''\") + \"'\"\n}\n\n/**\n * Prepare data for upload as a BodyInit, optionally gzip-compressed.\n * When gzip is enabled, compresses the data and returns a Blob.\n */\nexport async function toUploadBody(\n data: string | ArrayBuffer | Blob | ReadableStream,\n gzip?: boolean\n): Promise<BodyInit> {\n if (gzip) {\n const stream =\n data instanceof ReadableStream\n ? data\n : data instanceof Blob\n ? data.stream()\n : new Blob([data]).stream()\n const compressed = stream.pipeThrough(new CompressionStream('gzip'))\n return new Response(compressed).blob()\n }\n\n return toBlob(data)\n}\n","import platform from 'platform'\n\nimport { version } from '../../../package.json'\nimport { runtime, runtimeVersion } from '../utils'\n\nexport { version }\n\nexport const defaultHeaders = {\n browser: (typeof window !== 'undefined' && platform.name) || 'unknown',\n lang: 'js',\n lang_version: runtimeVersion,\n package_version: version,\n publisher: 'ppio',\n sdk_runtime: runtime,\n system: platform.os?.family || 'unknown',\n}\n\nexport function getEnvVar(name: string) {\n if (runtime === 'deno') {\n // @ts-ignore\n return Deno.env.get(name)\n }\n\n if (typeof process === 'undefined') {\n return ''\n }\n\n return process.env[name]\n}\n","// This is the message for the sandbox timeout error when the response code is 502/Unavailable\nexport function formatSandboxTimeoutError(message: string) {\n return new TimeoutError(\n `${message}: This error is likely due to sandbox timeout. You can modify the sandbox timeout by passing 'timeoutMs' when starting the sandbox or calling '.setTimeout' on the sandbox with the desired timeout.`\n )\n}\n\n/**\n * Base class for all sandbox errors.\n *\n * Thrown when general sandbox errors occur.\n */\nexport class SandboxError extends Error {\n constructor(message?: string, stackTrace?: string) {\n super(message)\n this.name = 'SandboxError'\n if (stackTrace) {\n this.stack = stackTrace\n }\n }\n}\n\n/**\n * Thrown when a timeout error occurs.\n *\n * The [unavailable] error type is caused by sandbox timeout.\n *\n * The [canceled] error type is caused by exceeding request timeout.\n *\n * The [deadline_exceeded] error type is caused by exceeding the timeout for command execution, watch, etc.\n *\n * The [unknown] error type is sometimes caused by the sandbox timeout when the request is not processed correctly.\n */\nexport class TimeoutError extends SandboxError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'TimeoutError'\n }\n}\n\n/**\n * Thrown when an invalid argument is provided.\n */\nexport class InvalidArgumentError extends SandboxError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'InvalidArgumentError'\n }\n}\n\n/**\n * Thrown when there is not enough disk space.\n */\nexport class NotEnoughSpaceError extends SandboxError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'NotEnoughSpaceError'\n }\n}\n\n/**\n * Thrown when a resource is not found.\n *\n * @deprecated Use {@link FileNotFoundError} or {@link SandboxNotFoundError} instead. This class will be removed in the next major version.\n */\nexport class NotFoundError extends SandboxError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'NotFoundError'\n }\n}\n\n/**\n * Thrown when a file or directory is not found inside a sandbox.\n */\nexport class FileNotFoundError extends NotFoundError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'FileNotFoundError'\n }\n}\n\n/**\n * Thrown when a sandbox is not found (e.g. it doesn't exist or is no longer running).\n */\nexport class SandboxNotFoundError extends NotFoundError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'SandboxNotFoundError'\n }\n}\n\n/**\n * Thrown when authentication fails.\n */\nexport class AuthenticationError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'AuthenticationError'\n }\n}\n\n/**\n * Thrown when git authentication fails.\n */\nexport class GitAuthError extends AuthenticationError {\n constructor(message: string) {\n super(message)\n this.name = 'GitAuthError'\n }\n}\n\n/**\n * Thrown when git upstream tracking is missing.\n */\nexport class GitUpstreamError extends SandboxError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'GitUpstreamError'\n }\n}\n\n/**\n * Thrown when the template uses old envd version. It isn't compatible with the new SDK.\n */\nexport class TemplateError extends SandboxError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'TemplateError'\n }\n}\n\n/**\n * Thrown when the API rate limit is exceeded.\n */\nexport class RateLimitError extends SandboxError {\n constructor(message: string) {\n super(message)\n this.name = 'RateLimitError'\n }\n}\n\n/**\n * Thrown when the build fails.\n */\nexport class BuildError extends Error {\n constructor(message: string, stackTrace?: string) {\n super(message)\n this.name = 'BuildError'\n if (stackTrace) {\n this.stack = stackTrace\n }\n }\n}\n\n/**\n * Thrown when the file upload fails.\n */\nexport class FileUploadError extends BuildError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'FileUploadError'\n }\n}\n\n/**\n * Base class for all volume errors.\n *\n * Thrown when general volume errors occur.\n */\nexport class VolumeError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'VolumeError'\n }\n}\n\n/**\n * Thrown when secret-related operations fail.\n */\nexport class SecretError extends SandboxError {\n constructor(message: string, stackTrace?: string) {\n super(message, stackTrace)\n this.name = 'SecretError'\n }\n}\n","import type { Interceptor } from '@connectrpc/connect'\nimport type { Middleware } from 'openapi-fetch'\n\n/**\n * Logger interface compatible with {@link console} used for logging Sandbox messages.\n */\nexport interface Logger {\n /**\n * Debug level logging method.\n */\n debug?: (...args: any[]) => void\n /**\n * Info level logging method.\n */\n info?: (...args: any[]) => void\n /**\n * Warn level logging method.\n */\n warn?: (...args: any[]) => void\n /**\n * Error level logging method.\n */\n error?: (...args: any[]) => void\n}\n\nfunction formatLog(log: any) {\n return JSON.parse(JSON.stringify(log))\n}\n\nexport function createRpcLogger(logger: Logger): Interceptor {\n async function* logEach(stream: AsyncIterable<any>) {\n for await (const m of stream) {\n logger.debug?.('Response stream:', formatLog(m))\n yield m\n }\n }\n\n return (next) => async (req) => {\n logger.info?.(`Request: POST ${req.url}`)\n\n const res = await next(req)\n if (res.stream) {\n return {\n ...res,\n message: logEach(res.message),\n }\n } else {\n logger.info?.('Response:', formatLog(res.message))\n }\n\n return res\n }\n}\n\nexport function createApiLogger(logger: Logger): Middleware {\n return {\n async onRequest({ request }) {\n logger.info?.(`Request ${request.method} ${request.url}`)\n return request\n },\n async onResponse({ response }) {\n if (response.status >= 400) {\n logger.error?.('Response:', response.status, response.statusText)\n } else {\n logger.info?.('Response:', response.status, response.statusText)\n }\n\n return response\n },\n }\n}\n","import createClient, { FetchResponse } from 'openapi-fetch'\n\nimport type { components, paths } from './schema.gen'\nimport { defaultHeaders } from './metadata'\nimport { ConnectionConfig } from '../connectionConfig'\nimport { AuthenticationError, RateLimitError, SandboxError } from '../errors'\nimport { createApiLogger } from '../logs'\n\nexport function handleApiError(\n response: FetchResponse<any, any, any>,\n errorClass: new (\n message: string,\n stackTrace?: string\n ) => Error = SandboxError,\n stackTrace?: string\n): Error | undefined {\n // openapi-fetch returns empty string for error when response body is empty,\n // so we check !== undefined instead of truthiness\n if (response.error === undefined) {\n return\n }\n\n if (response.response.status === 401) {\n const message = 'Unauthorized, please check your credentials.'\n const content = response.error?.message ?? response.error\n\n if (content) {\n return new AuthenticationError(`${message} - ${content}`)\n }\n return new AuthenticationError(message)\n }\n\n if (response.response.status === 429) {\n const message = 'Rate limit exceeded, please try again later'\n const content = response.error?.message ?? response.error\n\n if (content) {\n return new RateLimitError(`${message} - ${content}`)\n }\n return new RateLimitError(message)\n }\n\n const message = response.error?.message ?? response.error\n return new errorClass(`${response.response.status}: ${message}`, stackTrace)\n}\n\n/**\n * Client for interacting with the PPIO sandbox API.\n */\nclass ApiClient {\n readonly api: ReturnType<typeof createClient<paths>>\n\n constructor(\n config: ConnectionConfig,\n opts: {\n requireAccessToken?: boolean\n requireApiKey?: boolean\n } = { requireAccessToken: false, requireApiKey: false }\n ) {\n if (opts?.requireApiKey && !config.apiKey) {\n throw new AuthenticationError(\n 'API key is required, please visit the Team tab at https://ppio.com/settings/key-management to get your API key. ' +\n 'You can either set the environment variable `PPIO_API_KEY` ' +\n \"or you can pass it directly to the sandbox like Sandbox.create({ apiKey: 'ppio_...' })\"\n )\n }\n\n if (opts?.requireAccessToken && !config.accessToken) {\n throw new AuthenticationError(\n 'Access token is required, please visit the Personal tab at https://ppio.com/settings/key-management to get your access token. ' +\n 'You can set the environment variable `PPIO_ACCESS_TOKEN` or pass the `accessToken` in options.'\n )\n }\n\n this.api = createClient<paths>({\n baseUrl: config.apiUrl,\n // In HTTP 1.1, all connections are considered persistent unless declared otherwise\n // keepalive: true,\n headers: {\n ...defaultHeaders,\n ...(config.apiKey && { 'X-API-KEY': config.apiKey }),\n ...(config.accessToken && {\n Authorization: `Bearer ${config.accessToken}`,\n }),\n ...config.headers,\n },\n querySerializer: {\n array: {\n style: 'form',\n explode: false,\n },\n },\n })\n\n if (config.logger) {\n this.api.use(createApiLogger(config.logger))\n }\n }\n}\n\nexport type { components, paths }\nexport { ApiClient }\n","import { Logger } from './logs'\nimport { getEnvVar, version } from './api/metadata'\n\nexport const REQUEST_TIMEOUT_MS = 60_000 // 60 seconds\nexport const LEGACY_REQUEST_TIMEOUT_MS = 1_800_000 // 30 minutes\nexport const DEFAULT_SANDBOX_TIMEOUT_MS = 300_000 // 300 seconds\nexport const KEEPALIVE_PING_INTERVAL_SEC = 50 // 50 seconds\n\nexport const KEEPALIVE_PING_HEADER = 'Keepalive-Ping-Interval'\n\nconst LEGACY_DOMAINS = [\n 'sandbox.ppio.cn',\n 'sandbox-test.ppio.cn',\n]\nconst DEFAULT_PPIO_API_URLS: Record<string, string> = {\n 'cn-beijing-1.sandbox.ppio.com':\n 'https://api.cn-beijing-1.sandbox.ppio.com',\n}\n\nexport function isLegacyDomain(domain?: string) {\n return domain ? LEGACY_DOMAINS.includes(domain) : true // use legacy domain by default\n}\n\ntype ErrorConstructor = new (message: string) => Error\n\nexport function raiseIfLegacy(\n config: ConnectionConfig,\n feature: string,\n ErrorType: ErrorConstructor = Error\n) {\n if (config.isLegacyDomain) {\n throw new ErrorType(`${feature} is not supported on legacy domains`)\n }\n}\n\nexport function validateDomain(domain: string) {\n if (!domain) {\n throw new Error('Domain cannot be empty')\n }\n}\n\nexport function normalizeApiUrl(apiUrl?: string): string | undefined {\n if (!apiUrl) return apiUrl\n return /^[a-z][a-z\\d+.-]*:\\/\\//i.test(apiUrl) ? apiUrl : `https://${apiUrl}`\n}\n\nexport function getDefaultApiUrl(domain: string, debug: boolean) {\n if (debug) {\n return 'http://localhost:3000'\n }\n return DEFAULT_PPIO_API_URLS[domain] ?? `https://api.${domain}`\n}\n\n/**\n * Connection options for requests to the API.\n */\nexport interface ConnectionOpts {\n secure?: boolean\n allowPublicTraffic?: boolean\n /**\n * PPIO sandbox API key to use for authentication.\n *\n * @default PPIO_API_KEY // environment variable\n */\n apiKey?: string\n /**\n * PPIO sandbox access token to use for authentication.\n *\n * @default PPIO_ACCESS_TOKEN // environment variable\n */\n accessToken?: string\n /**\n * Domain to use for the API.\n *\n * @default PPIO_DOMAIN // environment variable or `sandbox.ppio.cn`\n */\n domain?: string\n /**\n * API Url to use for the API.\n * @internal\n * @default PPIO_API_URL // environment variable or the default API URL for the selected domain\n */\n apiUrl?: string\n /**\n * Sandbox Url to use for the API.\n * @internal\n * @default PPIO_SANDBOX_URL // environment variable or `https://${port}-${sandboxID}.${domain}`\n */\n sandboxUrl?: string\n /**\n * If true the SDK starts in the debug mode and connects to the local envd API server.\n * @internal\n * @default PPIO_DEBUG // environment variable or `false`\n */\n debug?: boolean\n /**\n * Timeout for requests to the API in **milliseconds**.\n *\n * @default 60_000 // 60 seconds\n */\n requestTimeoutMs?: number\n /**\n * Logger to use for logging messages. It can accept any object that implements `Logger` interface—for example, {@link console}.\n */\n logger?: Logger\n\n /**\n * Additional headers to send with the request.\n */\n headers?: Record<string, string>\n\n /**\n * If true, the legacy pause endpoint waits until sandbox pause succeeds.\n * Ignored by modern domains, only used for legacy domains\n *\n * @deprecated Only used for legacy domains; ignored by modern domains.\n */\n sync?: boolean\n}\n\n/**\n * Configuration for connecting to the API.\n */\nexport class ConnectionConfig {\n public static envdPort = 49983\n\n readonly debug: boolean\n readonly domain: string\n readonly isLegacyDomain: boolean\n readonly apiUrl: string\n readonly sandboxUrl?: string\n readonly logger?: Logger\n\n readonly requestTimeoutMs: number\n\n readonly apiKey?: string\n readonly accessToken?: string\n\n readonly headers?: Record<string, string>\n\n constructor(opts?: ConnectionOpts) {\n this.apiKey = opts?.apiKey || ConnectionConfig.apiKey\n this.debug = opts?.debug || ConnectionConfig.debug\n this.domain = opts?.domain || ConnectionConfig.domain\n this.isLegacyDomain = isLegacyDomain(this.domain)\n this.accessToken = opts?.accessToken || ConnectionConfig.accessToken\n this.requestTimeoutMs =\n opts?.requestTimeoutMs ??\n (this.isLegacyDomain ? LEGACY_REQUEST_TIMEOUT_MS : REQUEST_TIMEOUT_MS)\n this.logger = opts?.logger\n this.headers = opts?.headers || {}\n this.headers['User-Agent'] = `ppio-sandbox-sdk-js/${version}`\n\n this.apiUrl =\n normalizeApiUrl(opts?.apiUrl) ||\n normalizeApiUrl(ConnectionConfig.apiUrl) ||\n getDefaultApiUrl(this.domain, this.debug)\n\n this.sandboxUrl = opts?.sandboxUrl || ConnectionConfig.sandboxUrl\n }\n\n private static get domain() {\n return getEnvVar('PPIO_DOMAIN') || 'sandbox.ppio.cn'\n }\n\n private static get apiUrl() {\n return getEnvVar('PPIO_API_URL')\n }\n\n private static get sandboxUrl() {\n return getEnvVar('PPIO_SANDBOX_URL')\n }\n\n private static get debug() {\n return (getEnvVar('PPIO_DEBUG') || 'false').toLowerCase() === 'true'\n }\n\n private static get apiKey() {\n return getEnvVar('PPIO_API_KEY')\n }\n\n private static get accessToken() {\n return getEnvVar('PPIO_ACCESS_TOKEN')\n }\n\n getSignal(requestTimeoutMs?: number) {\n const timeout = requestTimeoutMs ?? this.requestTimeoutMs\n\n return timeout ? AbortSignal.timeout(timeout) : undefined\n }\n\n getSandboxUrl(\n sandboxId: string,\n opts: { sandboxDomain: string; envdPort: number }\n ) {\n if (this.sandboxUrl) {\n return this.sandboxUrl\n }\n\n return `${this.debug ? 'http' : 'https'}://${this.getHost(sandboxId, opts.envdPort, opts.sandboxDomain)}`\n }\n\n getHost(sandboxId: string, port: number, sandboxDomain: string) {\n if (this.debug) {\n return `localhost:${port}`\n }\n\n return `${port}-${sandboxId}.${sandboxDomain ?? this.domain}`\n }\n}\n\n/**\n * User used for the operation in the sandbox.\n */\n\nexport const defaultUsername: Username = 'user'\nexport type Username = string\n","import createClient from 'openapi-fetch'\n\nimport type { components, paths } from './schema.gen'\nimport { ConnectionConfig } from '../connectionConfig'\nimport { createApiLogger } from '../logs'\nimport {\n SandboxError,\n InvalidArgumentError,\n NotFoundError,\n NotEnoughSpaceError,\n SandboxNotFoundError,\n formatSandboxTimeoutError,\n AuthenticationError,\n} from '../errors'\nimport { StartResponse, ConnectResponse } from './process/process_pb'\nimport { Code, ConnectError } from '@connectrpc/connect'\nimport { WatchDirResponse } from './filesystem/filesystem_pb'\n\ntype ApiError = { message?: string } | string\n\nconst DEFAULT_ERROR_MAP: Record<number, (message: string) => Error> = {\n 400: (message) => new InvalidArgumentError(message),\n 401: (message) => new AuthenticationError(message),\n 404: (message) => new NotFoundError(message),\n 429: (message) =>\n new SandboxError(`${message}: The requests are being rate limited.`),\n 502: formatSandboxTimeoutError,\n 507: (message) => new NotEnoughSpaceError(message),\n}\n\n/**\n * Handles errors from envd API responses by mapping HTTP status codes to specific error types.\n *\n * @param res - The API response object containing an optional error and the raw `Response`.\n * @param errorMap - Optional map of HTTP status codes to error factory functions that override the defaults.\n * @returns The corresponding `Error` instance if an error is present, or `undefined` if the response is successful.\n */\nexport async function handleEnvdApiError(\n res: {\n error?: ApiError\n response: Response\n },\n errorMap?: Record<number, (message: string) => Error>\n) {\n if (!res.error) {\n return\n }\n\n const message: string =\n typeof res.error == 'string'\n ? res.error\n : res.error?.message || (await res.response.text())\n\n // Check if a custom error mapping is provided for this error code\n if (errorMap && res.response.status in errorMap) {\n return errorMap[res.response.status]?.(message)\n }\n\n // Check if there is a default error mapping for this error code\n if (res.response.status in DEFAULT_ERROR_MAP) {\n return DEFAULT_ERROR_MAP[res.response.status]?.(message)\n }\n\n // Fallback to a generic SandboxError if no specific mapping is found\n return new SandboxError(`${res.response.status}: ${message}`)\n}\n\nexport async function handleProcessStartEvent(\n events: AsyncIterable<StartResponse | ConnectResponse>\n) {\n let startEvent: StartResponse | ConnectResponse\n\n try {\n startEvent = (await events[Symbol.asyncIterator]().next()).value\n } catch (err) {\n if (err instanceof ConnectError) {\n if (err.code === Code.Unavailable) {\n throw new SandboxNotFoundError(\n 'Sandbox is probably not running anymore'\n )\n }\n }\n\n throw err\n }\n if (startEvent.event?.event.case !== 'start') {\n throw new Error('Expected start event')\n }\n\n return startEvent.event.event.value.pid\n}\n\nexport async function handleWatchDirStartEvent(\n events: AsyncIterable<WatchDirResponse>\n) {\n let startEvent: WatchDirResponse\n\n try {\n startEvent = (await events[Symbol.asyncIterator]().next()).value\n } catch (err) {\n if (err instanceof ConnectError) {\n if (err.code === Code.Unavailable) {\n throw new SandboxNotFoundError(\n 'Sandbox is probably not running anymore'\n )\n }\n }\n\n throw err\n }\n if (startEvent.event?.case !== 'start') {\n throw new Error('Expected start event')\n }\n\n return startEvent.event.value\n}\n\nclass EnvdApiClient {\n readonly api: ReturnType<typeof createClient<paths>>\n readonly version: string\n\n constructor(\n config: Pick<ConnectionConfig, 'apiUrl' | 'logger' | 'accessToken'> & {\n fetch?: (request: Request) => ReturnType<typeof fetch>\n headers?: Record<string, string>\n },\n metadata: {\n version: string\n }\n ) {\n this.api = createClient({\n baseUrl: config.apiUrl,\n fetch: config?.fetch,\n headers: config?.headers,\n // In HTTP 1.1, all connections are considered persistent unless declared otherwise\n // keepalive: true,\n })\n this.version = metadata.version\n\n if (config.logger) {\n this.api.use(createApiLogger(config.logger))\n }\n }\n}\n\nexport type { components, paths }\nexport { EnvdApiClient }\n","// @generated by protoc-gen-es v2.6.2 with parameter \"target=ts\"\n// @generated from file process/process.proto (package process, syntax proto3)\n/* eslint-disable */\n\nimport type {\n GenEnum,\n GenFile,\n GenMessage,\n GenService,\n} from '@bufbuild/protobuf/codegenv2'\nimport {\n enumDesc,\n fileDesc,\n messageDesc,\n serviceDesc,\n} from '@bufbuild/protobuf/codegenv2'\nimport type { Message } from '@bufbuild/protobuf'\n\n/**\n * Describes the file process/process.proto.\n */\nexport const file_process_process: GenFile =\n /*@__PURE__*/\n fileDesc(\n 'ChVwcm9jZXNzL3Byb2Nlc3MucHJvdG8SB3Byb2Nlc3MiSgoDUFRZEh8KBHNpemUYASABKAsyES5wcm9jZXNzLlBUWS5TaXplGiIKBFNpemUSDAoEY29scxgBIAEoDRIMCgRyb3dzGAIgASgNIqEBCg1Qcm9jZXNzQ29uZmlnEgsKA2NtZBgBIAEoCRIMCgRhcmdzGAIgAygJEi4KBGVudnMYAyADKAsyIC5wcm9jZXNzLlByb2Nlc3NDb25maWcuRW52c0VudHJ5EhAKA2N3ZBgEIAEoCUgAiAEBGisKCUVudnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBQgYKBF9jd2QiDQoLTGlzdFJlcXVlc3QiXAoLUHJvY2Vzc0luZm8SJgoGY29uZmlnGAEgASgLMhYucHJvY2Vzcy5Qcm9jZXNzQ29uZmlnEgsKA3BpZBgCIAEoDRIQCgN0YWcYAyABKAlIAIgBAUIGCgRfdGFnIjcKDExpc3RSZXNwb25zZRInCglwcm9jZXNzZXMYASADKAsyFC5wcm9jZXNzLlByb2Nlc3NJbmZvIpcBCgxTdGFydFJlcXVlc3QSJwoHcHJvY2VzcxgBIAEoCzIWLnByb2Nlc3MuUHJvY2Vzc0NvbmZpZxIeCgNwdHkYAiABKAsyDC5wcm9jZXNzLlBUWUgAiAEBEhAKA3RhZxgDIAEoCUgBiAEBEhIKBXN0ZGluGAQgASgISAKIAQFCBgoEX3B0eUIGCgRfdGFnQggKBl9zdGRpbiJiCg1VcGRhdGVSZXF1ZXN0EikKB3Byb2Nlc3MYASABKAsyGC5wcm9jZXNzLlByb2Nlc3NTZWxlY3RvchIeCgNwdHkYAiABKAsyDC5wcm9jZXNzLlBUWUgAiAEBQgYKBF9wdHkiEAoOVXBkYXRlUmVzcG9uc2UirwMKDFByb2Nlc3NFdmVudBIxCgVzdGFydBgBIAEoCzIgLnByb2Nlc3MuUHJvY2Vzc0V2ZW50LlN0YXJ0RXZlbnRIABIvCgRkYXRhGAIgASgLMh8ucHJvY2Vzcy5Qcm9jZXNzRXZlbnQuRGF0YUV2ZW50SAASLQoDZW5kGAMgASgLMh4ucHJvY2Vzcy5Qcm9jZXNzRXZlbnQuRW5kRXZlbnRIABI0CglrZWVwYWxpdmUYBCABKAsyHy5wcm9jZXNzLlByb2Nlc3NFdmVudC5LZWVwQWxpdmVIABoZCgpTdGFydEV2ZW50EgsKA3BpZBgBIAEoDRpICglEYXRhRXZlbnQSEAoGc3Rkb3V0GAEgASgMSAASEAoGc3RkZXJyGAIgASgMSAASDQoDcHR5GAMgASgMSABCCAoGb3V0cHV0GlsKCEVuZEV2ZW50EhEKCWV4aXRfY29kZRgBIAEoERIOCgZleGl0ZWQYAiABKAgSDgoGc3RhdHVzGAMgASgJEhIKBWVycm9yGAQgASgJSACIAQFCCAoGX2Vycm9yGgsKCUtlZXBBbGl2ZUIHCgVldmVudCI1Cg1TdGFydFJlc3BvbnNlEiQKBWV2ZW50GAEgASgLMhUucHJvY2Vzcy5Qcm9jZXNzRXZlbnQiNwoPQ29ubmVjdFJlc3BvbnNlEiQKBWV2ZW50GAEgASgLMhUucHJvY2Vzcy5Qcm9jZXNzRXZlbnQiYwoQU2VuZElucHV0UmVxdWVzdBIpCgdwcm9jZXNzGAEgASgLMhgucHJvY2Vzcy5Qcm9jZXNzU2VsZWN0b3ISJAoFaW5wdXQYAiABKAsyFS5wcm9jZXNzLlByb2Nlc3NJbnB1dCITChFTZW5kSW5wdXRSZXNwb25zZSI3CgxQcm9jZXNzSW5wdXQSDwoFc3RkaW4YASABKAxIABINCgNwdHkYAiABKAxIAEIHCgVpbnB1dCLCAgoSU3RyZWFtSW5wdXRSZXF1ZXN0EjcKBXN0YXJ0GAEgASgLMiYucHJvY2Vzcy5TdHJlYW1JbnB1dFJlcXVlc3QuU3RhcnRFdmVudEgAEjUKBGRhdGEYAiABKAsyJS5wcm9jZXNzLlN0cmVhbUlucHV0UmVxdWVzdC5EYXRhRXZlbnRIABI6CglrZWVwYWxpdmUYAyABKAsyJS5wcm9jZXNzLlN0cmVhbUlucHV0UmVxdWVzdC5LZWVwQWxpdmVIABo3CgpTdGFydEV2ZW50EikKB3Byb2Nlc3MYASABKAsyGC5wcm9jZXNzLlByb2Nlc3NTZWxlY3RvchoxCglEYXRhRXZlbnQSJAoFaW5wdXQYAiABKAsyFS5wcm9jZXNzLlByb2Nlc3NJbnB1dBoLCglLZWVwQWxpdmVCBwoFZXZlbnQiFQoTU3RyZWFtSW5wdXRSZXNwb25zZSJfChFTZW5kU2lnbmFsUmVxdWVzdBIpCgdwcm9jZXNzGAEgASgLMhgucHJvY2Vzcy5Qcm9jZXNzU2VsZWN0b3ISHwoGc2lnbmFsGAIgASgOMg8ucHJvY2Vzcy5TaWduYWwiFAoSU2VuZFNpZ25hbFJlc3BvbnNlIj4KEUNsb3NlU3RkaW5SZXF1ZXN0EikKB3Byb2Nlc3MYASABKAsyGC5wcm9jZXNzLlByb2Nlc3NTZWxlY3RvciIUChJDbG9zZVN0ZGluUmVzcG9uc2UiOwoOQ29ubmVjdFJlcXVlc3QSKQoHcHJvY2VzcxgBIAEoCzIYLnByb2Nlc3MuUHJvY2Vzc1NlbGVjdG9yIjsKD1Byb2Nlc3NTZWxlY3RvchINCgNwaWQYASABKA1IABINCgN0YWcYAiABKAlIAEIKCghzZWxlY3RvcipICgZTaWduYWwSFgoSU0lHTkFMX1VOU1BFQ0lGSUVEEAASEgoOU0lHTkFMX1NJR1RFUk0QDxISCg5TSUdOQUxfU0lHS0lMTBAJMpEECgdQcm9jZXNzEjMKBExpc3QSFC5wcm9jZXNzLkxpc3RSZXF1ZXN0GhUucHJvY2Vzcy5MaXN0UmVzcG9uc2USPgoHQ29ubmVjdBIXLnByb2Nlc3MuQ29ubmVjdFJlcXVlc3QaGC5wcm9jZXNzLkNvbm5lY3RSZXNwb25zZTABEjgKBVN0YXJ0EhUucHJvY2Vzcy5TdGFydFJlcXVlc3QaFi5wcm9jZXNzLlN0YXJ0UmVzcG9uc2UwARI5CgZVcGRhdGUSFi5wcm9jZXNzLlVwZGF0ZVJlcXVlc3QaFy5wcm9jZXNzLlVwZGF0ZVJlc3BvbnNlEkoKC1N0cmVhbUlucHV0EhsucHJvY2Vzcy5TdHJlYW1JbnB1dFJlcXVlc3QaHC5wcm9jZXNzLlN0cmVhbUlucHV0UmVzcG9uc2UoARJCCglTZW5kSW5wdXQSGS5wcm9jZXNzLlNlbmRJbnB1dFJlcXVlc3QaGi5wcm9jZXNzLlNlbmRJbnB1dFJlc3BvbnNlEkUKClNlbmRTaWduYWwSGi5wcm9jZXNzLlNlbmRTaWduYWxSZXF1ZXN0GhsucHJvY2Vzcy5TZW5kU2lnbmFsUmVzcG9uc2USRQoKQ2xvc2VTdGRpbhIaLnByb2Nlc3MuQ2xvc2VTdGRpblJlcXVlc3QaGy5wcm9jZXNzLkNsb3NlU3RkaW5SZXNwb25zZUJXCgtjb20ucHJvY2Vzc0IMUHJvY2Vzc1Byb3RvUAGiAgNQWFiqAgdQcm9jZXNzygIHUHJvY2Vzc+ICE1Byb2Nlc3NcR1BCTWV0YWRhdGHqAgdQcm9jZXNzYgZwcm90bzM'\n )\n\n/**\n * @generated from message process.PTY\n */\nexport type PTY = Message<'process.PTY'> & {\n /**\n * @generated from field: process.PTY.Size size = 1;\n */\n size?: PTY_Size\n}\n\n/**\n * Describes the message process.PTY.\n * Use `create(PTYSchema)` to create a new message.\n */\nexport const PTYSchema: GenMessage<PTY> =\n /*@__PURE__*/\n messageDesc(file_process_process, 0)\n\n/**\n * @generated from message process.PTY.Size\n */\nexport type PTY_Size = Message<'process.PTY.Size'> & {\n /**\n * @generated from field: uint32 cols = 1;\n */\n cols: number\n\n /**\n * @generated from field: uint32 rows = 2;\n */\n rows: number\n}\n\n/**\n * Describes the message process.PTY.Size.\n * Use `create(PTY_SizeSchema)` to create a new message.\n */\nexport const PTY_SizeSchema: GenMessage<PTY_Size> =\n /*@__PURE__*/\n messageDesc(file_process_process, 0, 0)\n\n/**\n * @generated from message process.ProcessConfig\n */\nexport type ProcessConfig = Message<'process.ProcessConfig'> & {\n /**\n * @generated from field: string cmd = 1;\n */\n cmd: string\n\n /**\n * @generated from field: repeated string args = 2;\n */\n args: string[]\n\n /**\n * @generated from field: map<string, string> envs = 3;\n */\n envs: { [key: string]: string }\n\n /**\n * @generated from field: optional string cwd = 4;\n */\n cwd?: string\n}\n\n/**\n * Describes the message process.ProcessConfig.\n * Use `create(ProcessConfigSchema)` to create a new message.\n */\nexport const ProcessConfigSchema: GenMessage<ProcessConfig> =\n /*@__PURE__*/\n messageDesc(file_process_process, 1)\n\n/**\n * @generated from message process.ListRequest\n */\nexport type ListRequest = Message<'process.ListRequest'> & {}\n\n/**\n * Describes the message process.ListRequest.\n * Use `create(ListRequestSchema)` to create a new message.\n */\nexport const ListRequestSchema: GenMessage<ListRequest> =\n /*@__PURE__*/\n messageDesc(file_process_process, 2)\n\n/**\n * @generated from message process.ProcessInfo\n */\nexport type ProcessInfo = Message<'process.ProcessInfo'> & {\n /**\n * @generated from field: process.ProcessConfig config = 1;\n */\n config?: ProcessConfig\n\n /**\n * @generated from field: uint32 pid = 2;\n */\n pid: number\n\n /**\n * @generated from field: optional string tag = 3;\n */\n tag?: string\n}\n\n/**\n * Describes the message process.ProcessInfo.\n * Use `create(ProcessInfoSchema)` to create a new message.\n */\nexport const ProcessInfoSchema: GenMessage<ProcessInfo> =\n /*@__PURE__*/\n messageDesc(file_process_process, 3)\n\n/**\n * @generated from message process.ListResponse\n */\nexport type ListResponse = Message<'process.ListResponse'> & {\n /**\n * @generated from field: repeated process.ProcessInfo processes = 1;\n */\n processes: ProcessInfo[]\n}\n\n/**\n * Describes the message process.ListResponse.\n * Use `create(ListResponseSchema)` to create a new message.\n */\nexport const ListResponseSchema: GenMessage<ListResponse> =\n /*@__PURE__*/\n messageDesc(file_process_process, 4)\n\n/**\n * @generated from message process.StartRequest\n */\nexport type StartRequest = Message<'process.StartRequest'> & {\n /**\n * @generated from field: process.ProcessConfig process = 1;\n */\n process?: ProcessConfig\n\n /**\n * @generated from field: optional process.PTY pty = 2;\n */\n pty?: PTY\n\n /**\n * @generated from field: optional string tag = 3;\n */\n tag?: string\n\n /**\n * @generated from field: optional bool stdin = 4;\n */\n stdin?: boolean\n}\n\n/**\n * Describes the message process.StartRequest.\n * Use `create(StartRequestSchema)` to create a new message.\n */\nexport const StartRequestSchema: GenMessage<StartRequest> =\n /*@__PURE__*/\n messageDesc(file_process_process, 5)\n\n/**\n * @generated from message process.UpdateRequest\n */\nexport type UpdateRequest = Message<'process.UpdateRequest'> & {\n /**\n * @generated from field: process.ProcessSelector process = 1;\n */\n process?: ProcessSelector\n\n /**\n * @generated from field: optional process.PTY pty = 2;\n */\n pty?: PTY\n}\n\n/**\n * Describes the message process.UpdateRequest.\n * Use `create(UpdateRequestSchema)` to create a new message.\n */\nexport const UpdateRequestSchema: GenMessage<UpdateRequest> =\n /*@__PURE__*/\n messageDesc(file_process_process, 6)\n\n/**\n * @generated from message process.UpdateResponse\n */\nexport type UpdateResponse = Message<'process.UpdateResponse'> & {}\n\n/**\n * Describes the message process.UpdateResponse.\n * Use `create(UpdateResponseSchema)` to create a new message.\n */\nexport const UpdateResponseSchema: GenMessage<UpdateResponse> =\n /*@__PURE__*/\n messageDesc(file_process_process, 7)\n\n/**\n * @generated from message process.ProcessEvent\n */\nexport type ProcessEvent = Message<'process.ProcessEvent'> & {\n /**\n * @generated from oneof process.ProcessEvent.event\n */\n event:\n | {\n /**\n * @generated from field: process.ProcessEvent.StartEvent start = 1;\n */\n value: ProcessEvent_StartEvent\n case: 'start'\n }\n | {\n /**\n * @generated from field: process.ProcessEvent.DataEvent data = 2;\n */\n value: ProcessEvent_DataEvent\n case: 'data'\n }\n | {\n /**\n * @generated from field: process.ProcessEvent.EndEvent end = 3;\n */\n value: ProcessEvent_EndEvent\n case: 'end'\n }\n | {\n /**\n * @generated from field: process.ProcessEvent.KeepAlive keepalive = 4;\n */\n value: ProcessEvent_KeepAlive\n case: 'keepalive'\n }\n | { case: undefined; value?: undefined }\n}\n\n/**\n * Describes the message process.ProcessEvent.\n * Use `create(ProcessEventSchema)` to create a new message.\n */\nexport const ProcessEventSchema: GenMessage<ProcessEvent> =\n /*@__PURE__*/\n messageDesc(file_process_process, 8)\n\n/**\n * @generated from message process.ProcessEvent.StartEvent\n */\nexport type ProcessEvent_StartEvent =\n Message<'process.ProcessEvent.StartEvent'> & {\n /**\n * @generated from field: uint32 pid = 1;\n */\n pid: number\n }\n\n/**\n * Describes the message process.ProcessEvent.StartEvent.\n * Use `create(ProcessEvent_StartEventSchema)` to create a new message.\n */\nexport const ProcessEvent_StartEventSchema: GenMessage<ProcessEvent_StartEvent> =\n /*@__PURE__*/\n messageDesc(file_process_process, 8, 0)\n\n/**\n * @generated from message process.ProcessEvent.DataEvent\n */\nexport type ProcessEvent_DataEvent =\n Message<'process.ProcessEvent.DataEvent'> & {\n /**\n * @generated from oneof process.ProcessEvent.DataEvent.output\n */\n output:\n | {\n /**\n * @generated from field: bytes stdout = 1;\n */\n value: Uint8Array\n case: 'stdout'\n }\n | {\n /**\n * @generated from field: bytes stderr = 2;\n */\n value: Uint8Array\n case: 'stderr'\n }\n | {\n /**\n * @generated from field: bytes pty = 3;\n */\n value: Uint8Array\n case: 'pty'\n }\n | { case: undefined; value?: undefined }\n }\n\n/**\n * Describes the message process.ProcessEvent.DataEvent.\n * Use `create(ProcessEvent_DataEventSchema)` to create a new message.\n */\nexport const ProcessEvent_DataEventSchema: GenMessage<ProcessEvent_DataEvent> =\n /*@__PURE__*/\n messageDesc(file_process_process, 8, 1)\n\n/**\n * @generated from message process.ProcessEvent.EndEvent\n */\nexport type ProcessEvent_EndEvent = Message<'process.ProcessEvent.EndEvent'> & {\n /**\n * @generated from field: sint32 exit_code = 1;\n */\n exitCode: number\n\n /**\n * @generated from field: bool exited = 2;\n */\n exited: boolean\n\n /**\n * @generated from field: string status = 3;\n */\n status: string\n\n /**\n * @generated from field: optional string error = 4;\n */\n error?: string\n}\n\n/**\n * Describes the message process.ProcessEvent.EndEvent.\n * Use `create(ProcessEvent_EndEventSchema)` to create a new message.\n */\nexport const ProcessEvent_EndEventSchema: GenMessage<ProcessEvent_EndEvent> =\n /*@__PURE__*/\n messageDesc(file_process_process, 8, 2)\n\n/**\n * @generated from message process.ProcessEvent.KeepAlive\n */\nexport type ProcessEvent_KeepAlive =\n Message<'process.ProcessEvent.KeepAlive'> & {}\n\n/**\n * Describes the message process.ProcessEvent.KeepAlive.\n * Use `create(ProcessEvent_KeepAliveSchema)` to create a new message.\n */\nexport const ProcessEvent_KeepAliveSchema: GenMessage<ProcessEvent_KeepAlive> =\n /*@__PURE__*/\n messageDesc(file_process_process, 8, 3)\n\n/**\n * @generated from message process.StartResponse\n */\nexport type StartResponse = Message<'process.StartResponse'> & {\n /**\n * @generated from field: process.ProcessEvent event = 1;\n */\n event?: ProcessEvent\n}\n\n/**\n * Describes the message process.StartResponse.\n * Use `create(StartResponseSchema)` to create a new message.\n */\nexport const StartResponseSchema: GenMessage<StartResponse> =\n /*@__PURE__*/\n messageDesc(file_process_process, 9)\n\n/**\n * @generated from message process.ConnectResponse\n */\nexport type ConnectResponse = Message<'process.ConnectResponse'> & {\n /**\n * @generated from field: process.ProcessEvent event = 1;\n */\n event?: ProcessEvent\n}\n\n/**\n * Describes the message process.ConnectResponse.\n * Use `create(ConnectResponseSchema)` to create a new message.\n */\nexport const ConnectResponseSchema: GenMessage<ConnectResponse> =\n /*@__PURE__*/\n messageDesc(file_process_process, 10)\n\n/**\n * @generated from message process.SendInputRequest\n */\nexport type SendInputRequest = Message<'process.SendInputRequest'> & {\n /**\n * @generated from field: process.ProcessSelector process = 1;\n */\n process?: ProcessSelector\n\n /**\n * @generated from field: process.ProcessInput input = 2;\n */\n input?: ProcessInput\n}\n\n/**\n * Describes the message process.SendInputRequest.\n * Use `create(SendInputRequestSchema)` to create a new message.\n */\nexport const SendInputRequestSchema: GenMessage<SendInputRequest> =\n /*@__PURE__*/\n messageDesc(file_process_process, 11)\n\n/**\n * @generated from message process.SendInputResponse\n */\nexport type SendInputResponse = Message<'process.SendInputResponse'> & {}\n\n/**\n * Describes the message process.SendInputResponse.\n * Use `create(SendInputResponseSchema)` to create a new message.\n */\nexport const SendInputResponseSchema: GenMessage<SendInputResponse> =\n /*@__PURE__*/\n messageDesc(file_process_process, 12)\n\n/**\n * @generated from message process.ProcessInput\n */\nexport type ProcessInput = Message<'process.ProcessInput'> & {\n /**\n * @generated from oneof process.ProcessInput.input\n */\n input:\n | {\n /**\n * @generated from field: bytes stdin = 1;\n */\n value: Uint8Array\n case: 'stdin'\n }\n | {\n /**\n * @generated from field: bytes pty = 2;\n */\n value: Uint8Array\n case: 'pty'\n }\n | { case: undefined; value?: undefined }\n}\n\n/**\n * Describes the message process.ProcessInput.\n * Use `create(ProcessInputSchema)` to create a new message.\n */\nexport const ProcessInputSchema: GenMessage<ProcessInput> =\n /*@__PURE__*/\n messageDesc(file_process_process, 13)\n\n/**\n * @generated from message process.StreamInputRequest\n */\nexport type StreamInputRequest = Message<'process.StreamInputRequest'> & {\n /**\n * @generated from oneof process.StreamInputRequest.event\n */\n event:\n | {\n /**\n * @generated from field: process.StreamInputRequest.StartEvent start = 1;\n */\n value: StreamInputRequest_StartEvent\n case: 'start'\n }\n | {\n /**\n * @generated from field: process.StreamInputRequest.DataEvent data = 2;\n */\n value: StreamInputRequest_DataEvent\n case: 'data'\n }\n | {\n /**\n * @generated from field: process.StreamInputRequest.KeepAlive keepalive = 3;\n */\n value: StreamInputRequest_KeepAlive\n case: 'keepalive'\n }\n | { case: undefined; value?: undefined }\n}\n\n/**\n * Describes the message process.StreamInputRequest.\n * Use `create(StreamInputRequestSchema)` to create a new message.\n */\nexport const StreamInputRequestSchema: GenMessage<StreamInputRequest> =\n /*@__PURE__*/\n messageDesc(file_process_process, 14)\n\n/**\n * @generated from message process.StreamInputRequest.StartEvent\n */\nexport type StreamInputRequest_StartEvent =\n Message<'process.StreamInputRequest.StartEvent'> & {\n /**\n * @generated from field: process.ProcessSelector process = 1;\n */\n process?: ProcessSelector\n }\n\n/**\n * Describes the message process.StreamInputRequest.StartEvent.\n * Use `create(StreamInputRequest_StartEventSchema)` to create a new message.\n */\nexport const StreamInputRequest_StartEventSchema: GenMessage<StreamInputRequest_StartEvent> =\n /*@__PURE__*/\n messageDesc(file_process_process, 14, 0)\n\n/**\n * @generated from message process.StreamInputRequest.DataEvent\n */\nexport type StreamInputRequest_DataEvent =\n Message<'process.StreamInputRequest.DataEvent'> & {\n /**\n * @generated from field: process.ProcessInput input = 2;\n */\n input?: ProcessInput\n }\n\n/**\n * Describes the message process.StreamInputRequest.DataEvent.\n * Use `create(StreamInputRequest_DataEventSchema)` to create a new message.\n */\nexport const StreamInputRequest_DataEventSchema: GenMessage<StreamInputRequest_DataEvent> =\n /*@__PURE__*/\n messageDesc(file_process_process, 14, 1)\n\n/**\n * @generated from message process.StreamInputRequest.KeepAlive\n */\nexport type StreamInputRequest_KeepAlive =\n Message<'process.StreamInputRequest.KeepAlive'> & {}\n\n/**\n * Describes the message process.StreamInputRequest.KeepAlive.\n * Use `create(StreamInputRequest_KeepAliveSchema)` to create a new message.\n */\nexport const StreamInputRequest_KeepAliveSchema: GenMessage<StreamInputRequest_KeepAlive> =\n /*@__PURE__*/\n messageDesc(file_process_process, 14, 2)\n\n/**\n * @generated from message process.StreamInputResponse\n */\nexport type StreamInputResponse = Message<'process.StreamInputResponse'> & {}\n\n/**\n * Describes the message process.StreamInputResponse.\n * Use `create(StreamInputResponseSchema)` to create a new message.\n */\nexport const StreamInputResponseSchema: GenMessage<StreamInputResponse> =\n /*@__PURE__*/\n messageDesc(file_process_process, 15)\n\n/**\n * @generated from message process.SendSignalRequest\n */\nexport type SendSignalRequest = Message<'process.SendSignalRequest'> & {\n /**\n * @generated from field: process.ProcessSelector process = 1;\n */\n process?: ProcessSelector\n\n /**\n * @generated from field: process.Signal signal = 2;\n */\n signal: Signal\n}\n\n/**\n * Describes the message process.SendSignalRequest.\n * Use `create(SendSignalRequestSchema)` to create a new message.\n */\nexport const SendSignalRequestSchema: GenMessage<SendSignalRequest> =\n /*@__PURE__*/\n messageDesc(file_process_process, 16)\n\n/**\n * @generated from message process.SendSignalResponse\n */\nexport type SendSignalResponse = Message<'process.SendSignalResponse'> & {}\n\n/**\n * Describes the message process.SendSignalResponse.\n * Use `create(SendSignalResponseSchema)` to create a new message.\n */\nexport const SendSignalResponseSchema: GenMessage<SendSignalResponse> =\n /*@__PURE__*/\n messageDesc(file_process_process, 17)\n\n/**\n * @generated from message process.CloseStdinRequest\n */\nexport type CloseStdinRequest = Message<'process.CloseStdinRequest'> & {\n /**\n * @generated from field: process.ProcessSelector process = 1;\n */\n process?: ProcessSelector\n}\n\n/**\n * Describes the message process.CloseStdinRequest.\n * Use `create(CloseStdinRequestSchema)` to create a new message.\n */\nexport const CloseStdinRequestSchema: GenMessage<CloseStdinRequest> =\n /*@__PURE__*/\n messageDesc(file_process_process, 18)\n\n/**\n * @generated from message process.CloseStdinResponse\n */\nexport type CloseStdinResponse = Message<'process.CloseStdinResponse'> & {}\n\n/**\n * Describes the message process.CloseStdinResponse.\n * Use `create(CloseStdinResponseSchema)` to create a new message.\n */\nexport const CloseStdinResponseSchema: GenMessage<CloseStdinResponse> =\n /*@__PURE__*/\n messageDesc(file_process_process, 19)\n\n/**\n * @generated from message process.ConnectRequest\n */\nexport type ConnectRequest = Message<'process.ConnectRequest'> & {\n /**\n * @generated from field: process.ProcessSelector process = 1;\n */\n process?: ProcessSelector\n}\n\n/**\n * Describes the message process.ConnectRequest.\n * Use `create(ConnectRequestSchema)` to create a new message.\n */\nexport const ConnectRequestSchema: GenMessage<ConnectRequest> =\n /*@__PURE__*/\n messageDesc(file_process_process, 20)\n\n/**\n * @generated from message process.ProcessSelector\n */\nexport type ProcessSelector = Message<'process.ProcessSelector'> & {\n /**\n * @generated from oneof process.ProcessSelector.selector\n */\n selector:\n | {\n /**\n * @generated from field: uint32 pid = 1;\n */\n value: number\n case: 'pid'\n }\n | {\n /**\n * @generated from field: string tag = 2;\n */\n value: string\n case: 'tag'\n }\n | { case: undefined; value?: undefined }\n}\n\n/**\n * Describes the message process.ProcessSelector.\n * Use `create(ProcessSelectorSchema)` to create a new message.\n */\nexport const ProcessSelectorSchema: GenMessage<ProcessSelector> =\n /*@__PURE__*/\n messageDesc(file_process_process, 21)\n\n/**\n * @generated from enum process.Signal\n */\nexport enum Signal {\n /**\n * @generated from enum value: SIGNAL_UNSPECIFIED = 0;\n */\n UNSPECIFIED = 0,\n\n /**\n * @generated from enum value: SIGNAL_SIGTERM = 15;\n */\n SIGTERM = 15,\n\n /**\n * @generated from enum value: SIGNAL_SIGKILL = 9;\n */\n SIGKILL = 9,\n}\n\n/**\n * Describes the enum process.Signal.\n */\nexport const SignalSchema: GenEnum<Signal> =\n /*@__PURE__*/\n enumDesc(file_process_process, 0)\n\n/**\n * @generated from service process.Process\n */\nexport const Process: GenService<{\n /**\n * @generated from rpc process.Process.List\n */\n list: {\n methodKind: 'unary'\n input: typeof ListRequestSchema\n output: typeof ListResponseSchema\n }\n /**\n * @generated from rpc process.Process.Connect\n */\n connect: {\n methodKind: 'server_streaming'\n input: typeof ConnectRequestSchema\n output: typeof ConnectResponseSchema\n }\n /**\n * @generated from rpc process.Process.Start\n */\n start: {\n methodKind: 'server_streaming'\n input: typeof StartRequestSchema\n output: typeof StartResponseSchema\n }\n /**\n * @generated from rpc process.Process.Update\n */\n update: {\n methodKind: 'unary'\n input: typeof UpdateRequestSchema\n output: typeof UpdateResponseSchema\n }\n /**\n * Client input stream ensures ordering of messages\n *\n * @generated from rpc process.Process.StreamInput\n */\n streamInput: {\n methodKind: 'client_streaming'\n input: typeof StreamInputRequestSchema\n output: typeof StreamInputResponseSchema\n }\n /**\n * @generated from rpc process.Process.SendInput\n */\n sendInput: {\n methodKind: 'unary'\n input: typeof SendInputRequestSchema\n output: typeof SendInputResponseSchema\n }\n /**\n * @generated from rpc process.Process.SendSignal\n */\n sendSignal: {\n methodKind: 'unary'\n input: typeof SendSignalRequestSchema\n output: typeof SendSignalResponseSchema\n }\n /**\n * Close stdin to signal EOF to the process.\n * Only works for non-PTY processes. For PTY, send Ctrl+D (0x04) instead.\n *\n * @generated from rpc process.Process.CloseStdin\n */\n closeStdin: {\n methodKind: 'unary'\n input: typeof CloseStdinRequestSchema\n output: typeof CloseStdinResponseSchema\n }\n}> = /*@__PURE__*/ serviceDesc(file_process_process, 0)\n","export const ENVD_VERSION_RECURSIVE_WATCH = '0.1.4'\nexport const ENVD_DEBUG_FALLBACK = '99.99.99'\nexport const ENVD_COMMANDS_STDIN = '0.3.0'\nexport const ENVD_DEFAULT_USER = '0.4.0'\nexport const ENVD_ENVD_CLOSE = '0.5.2'\nexport const ENVD_OCTET_STREAM_UPLOAD = '0.5.7'\n","import { Code, ConnectError } from '@connectrpc/connect'\nimport { runtime } from '../utils'\n\nimport { compareVersions } from 'compare-versions'\nimport { defaultUsername } from '../connectionConfig'\nimport {\n AuthenticationError,\n formatSandboxTimeoutError,\n InvalidArgumentError,\n NotFoundError,\n SandboxError,\n TimeoutError,\n} from '../errors'\nimport { ENVD_DEFAULT_USER } from './versions'\n\nconst DEFAULT_ERROR_MAP: Partial<Record<Code, (message: string) => Error>> = {\n [Code.InvalidArgument]: (message) => new InvalidArgumentError(message),\n [Code.Unauthenticated]: (message) => new AuthenticationError(message),\n [Code.NotFound]: (message) => new NotFoundError(message),\n [Code.Unavailable]: formatSandboxTimeoutError,\n [Code.Canceled]: (message) =>\n new TimeoutError(\n `${message}: This error is likely due to exceeding 'requestTimeoutMs'. You can pass the request timeout value as an option when making the request.`\n ),\n [Code.DeadlineExceeded]: (message) =>\n new TimeoutError(\n `${message}: This error is likely due to exceeding 'timeoutMs' — the total time a long running request (like command execution or directory watch) can be active. It can be modified by passing 'timeoutMs' when making the request. Use '0' to disable the timeout.`\n ),\n}\n\n/**\n * Handles errors from envd RPC calls by mapping gRPC status codes to specific error types.\n *\n * @param err - The caught error, expected to be a `ConnectError` from the gRPC transport.\n * @param errorMap - Optional map of gRPC `Code` values to error factory functions that override the defaults.\n * @returns The corresponding `Error` instance mapped from the gRPC status code, or the original error if it is not a `ConnectError`.\n */\nexport function handleRpcError(\n err: unknown,\n errorMap?: Partial<Record<Code, (message: string) => Error>>\n): Error {\n if (err instanceof ConnectError) {\n // Check if a custom error mapping is provided for this error code\n if (errorMap && err.code in errorMap) {\n return errorMap[err.code]!(err.message)\n }\n\n // Check if there is a default error mapping for this error code\n if (err.code in DEFAULT_ERROR_MAP) {\n return DEFAULT_ERROR_MAP[err.code]!(err.message)\n }\n\n // Fallback to a generic SandboxError if no specific mapping is found\n return new SandboxError(`${err.code}: ${err.message}`)\n }\n\n return err as Error\n}\n\nfunction encode64(value: string): string {\n switch (runtime) {\n case 'deno':\n return btoa(value)\n case 'node':\n return Buffer.from(value).toString('base64')\n case 'bun':\n return Buffer.from(value).toString('base64')\n default:\n return btoa(value)\n }\n}\n\nexport function authenticationHeader(\n envdVersion: string,\n username: string | undefined\n): Record<string, string> {\n if (\n username == undefined &&\n compareVersions(envdVersion, ENVD_DEFAULT_USER) < 0\n ) {\n username = defaultUsername\n }\n\n if (!username) {\n return {}\n }\n\n const value = `${username}:`\n\n const encoded = encode64(value)\n\n return { Authorization: `Basic ${encoded}` }\n}\n","import { handleRpcError } from '../../envd/rpc'\nimport { SandboxError } from '../../errors'\nimport { ConnectResponse, StartResponse } from '../../envd/process/process_pb'\n\ndeclare const __brand: unique symbol\ntype Brand<B> = { [__brand]: B }\nexport type Branded<T, B> = T & Brand<B>\n\nexport type Stdout = Branded<string, 'stdout'>\nexport type Stderr = Branded<string, 'stderr'>\nexport type PtyOutput = Branded<Uint8Array, 'pty'>\n\n/**\n * Command execution result.\n */\nexport interface CommandResult {\n /**\n * Command execution exit code.\n * `0` if the command finished successfully.\n */\n exitCode: number\n /**\n * Error message from command execution if it failed.\n */\n error?: string\n /**\n * Command stdout output.\n */\n stdout: string\n /**\n * Command stderr output.\n */\n stderr: string\n}\n\n/**\n * Error thrown when a command exits with a non-zero exit code.\n */\nexport class CommandExitError extends SandboxError implements CommandResult {\n constructor(private readonly result: CommandResult) {\n super(result.error)\n this.name = 'CommandExitError'\n }\n\n /**\n * Command execution exit code.\n * `0` if the command finished successfully.\n */\n get exitCode() {\n return this.result.exitCode\n }\n\n /**\n * Error message from command execution.\n */\n get error() {\n return this.result.error\n }\n\n /**\n * Command execution stdout output.\n */\n get stdout() {\n return this.result.stdout\n }\n\n /**\n * Command execution stderr output.\n */\n get stderr() {\n return this.result.stderr\n }\n}\n\n/**\n * Command execution handle.\n *\n * It provides methods for waiting for the command to finish, retrieving stdout/stderr, and killing the command.\n *\n * @property {number} pid process ID of the command.\n */\nexport class CommandHandle\n implements\n Omit<CommandResult, 'exitCode' | 'error'>,\n Partial<Pick<CommandResult, 'exitCode' | 'error'>>\n{\n private _stdout = ''\n private _stderr = ''\n\n private result?: CommandResult\n private iterationError?: Error\n\n private readonly _wait: Promise<void>\n\n /**\n * @hidden\n * @internal\n * @access protected\n */\n constructor(\n readonly pid: number,\n private readonly handleDisconnect: () => void,\n private readonly handleKill: () => Promise<boolean>,\n private readonly events: AsyncIterable<ConnectResponse | StartResponse>,\n private readonly onStdout?: (stdout: string) => void | Promise<void>,\n private readonly onStderr?: (stderr: string) => void | Promise<void>,\n private readonly onPty?: (pty: Uint8Array) => void | Promise<void>\n ) {\n this._wait = this.handleEvents()\n }\n\n /**\n * Command execution exit code.\n * `0` if the command finished successfully.\n *\n * It is `undefined` if the command is still running.\n */\n get exitCode() {\n return this.result?.exitCode\n }\n\n /**\n * Error message from command execution.\n */\n get error() {\n return this.result?.error\n }\n\n /**\n * Command execution stderr output.\n */\n get stderr() {\n return this._stderr\n }\n\n /**\n * Command execution stdout output.\n */\n get stdout() {\n return this._stdout\n }\n\n /**\n * Wait for the command to finish and return the result.\n * If the command exits with a non-zero exit code, it throws a `CommandExitError`.\n *\n * @returns `CommandResult` result of command execution.\n */\n async wait() {\n await this._wait\n\n if (this.iterationError) {\n throw this.iterationError\n }\n\n if (!this.result) {\n throw new SandboxError('Process exited without a result')\n }\n\n if (this.result.exitCode !== 0) {\n throw new CommandExitError(this.result)\n }\n\n return this.result\n }\n\n /**\n * Disconnect from the command.\n *\n * The command is not killed, but SDK stops receiving events from the command.\n * You can reconnect to the command using {@link Commands.connect}.\n */\n async disconnect() {\n this.handleDisconnect()\n }\n\n /**\n * Kill the command.\n * It uses `SIGKILL` signal to kill the command.\n *\n * @returns `true` if the command was killed successfully, `false` if the command was not found.\n */\n async kill() {\n return await this.handleKill()\n }\n\n private async *iterateEvents(): AsyncGenerator<\n [Stdout, null, null] | [null, Stderr, null] | [null, null, PtyOutput]\n > {\n for await (const event of this.events) {\n const e = event?.event?.event\n let out: string | undefined\n\n switch (e?.case) {\n case 'data':\n switch (e.value.output.case) {\n case 'stdout':\n out = new TextDecoder().decode(e.value.output.value)\n this._stdout += out\n yield [out as Stdout, null, null]\n break\n case 'stderr':\n out = new TextDecoder().decode(e.value.output.value)\n this._stderr += out\n yield [null, out as Stderr, null]\n break\n case 'pty':\n yield [null, null, e.value.output.value as PtyOutput]\n break\n }\n break\n case 'end':\n this.result = {\n exitCode: e.value.exitCode,\n error: e.value.error,\n stdout: this.stdout,\n stderr: this.stderr,\n }\n break\n }\n // TODO: Handle empty events like in python SDK\n }\n }\n\n private async handleEvents() {\n try {\n for await (const [stdout, stderr, pty] of this.iterateEvents()) {\n if (stdout !== null) {\n this.onStdout?.(stdout)\n } else if (stderr !== null) {\n this.onStderr?.(stderr)\n } else if (pty) {\n this.onPty?.(pty)\n }\n }\n } catch (e) {\n this.iterationError = handleRpcError(e)\n }\n }\n}\n","import {\n Code,\n ConnectError,\n createClient,\n Client,\n Transport,\n} from '@connectrpc/connect'\n\nimport {\n Signal,\n Process as ProcessService,\n} from '../../envd/process/process_pb'\nimport {\n ConnectionConfig,\n ConnectionOpts,\n Username,\n KEEPALIVE_PING_HEADER,\n KEEPALIVE_PING_INTERVAL_SEC,\n} from '../../connectionConfig'\nimport { CommandHandle } from './commandHandle'\nimport { authenticationHeader, handleRpcError } from '../../envd/rpc'\nimport { handleProcessStartEvent } from '../../envd/api'\n\nexport interface PtyCreateOpts\n extends Pick<ConnectionOpts, 'requestTimeoutMs'> {\n /**\n * Number of columns for the PTY.\n */\n cols: number\n /**\n * Number of rows for the PTY.\n */\n rows: number\n /**\n * Callback to handle PTY data.\n */\n onData: (data: Uint8Array) => void | Promise<void>\n /**\n * Timeout for the PTY in **milliseconds**.\n *\n * @default 60_000 // 60 seconds\n */\n timeoutMs?: number\n /**\n * User to use for the PTY.\n *\n * @default `default Sandbox user (as specified in the template)`\n */\n user?: Username\n /**\n * Environment variables for the PTY.\n *\n * @default {}\n */\n envs?: Record<string, string>\n /**\n * Working directory for the PTY.\n *\n * @default // home directory of the user used to start the PTY\n */\n cwd?: string\n}\n\n/**\n * Options for connecting to a command.\n */\nexport type PtyConnectOpts = Pick<PtyCreateOpts, 'onData' | 'timeoutMs'> &\n Pick<ConnectionOpts, 'requestTimeoutMs'>\n\n/**\n * Module for interacting with PTYs (pseudo-terminals) in the sandbox.\n */\nexport class Pty {\n private readonly rpc: Client<typeof ProcessService>\n private readonly envdVersion: string\n\n private readonly defaultPtyConnectionTimeout = 60_000 // 60 seconds\n\n constructor(\n private readonly transport: Transport,\n private readonly connectionConfig: ConnectionConfig,\n metadata: {\n version: string\n }\n ) {\n this.rpc = createClient(ProcessService, this.transport)\n this.envdVersion = metadata.version\n }\n\n /**\n * Create a new PTY (pseudo-terminal).\n *\n * @param opts options for creating the PTY.\n *\n * @returns handle to interact with the PTY.\n */\n async create(opts: PtyCreateOpts) {\n const requestTimeoutMs =\n opts?.requestTimeoutMs ?? this.connectionConfig.requestTimeoutMs\n const envs = opts?.envs ?? {}\n envs.TERM = envs.TERM ?? 'xterm-256color'\n envs.LANG = envs.LANG ?? 'C.UTF-8'\n envs.LC_ALL = envs.LC_ALL ?? 'C.UTF-8'\n const controller = new AbortController()\n\n const reqTimeout = setTimeout(() => {\n controller.abort()\n }, requestTimeoutMs)\n\n const events = this.rpc.start(\n {\n process: {\n cmd: '/bin/bash',\n args: ['-i', '-l'],\n envs: envs,\n cwd: opts?.cwd,\n },\n pty: {\n size: {\n cols: opts.cols,\n rows: opts.rows,\n },\n },\n },\n {\n headers: {\n ...authenticationHeader(this.envdVersion, opts?.user),\n [KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString(),\n },\n signal: controller.signal,\n timeoutMs: opts?.timeoutMs ?? this.defaultPtyConnectionTimeout,\n }\n )\n\n try {\n const pid = await handleProcessStartEvent(events)\n\n clearTimeout(reqTimeout)\n\n return new CommandHandle(\n pid,\n () => controller.abort(),\n () => this.kill(pid),\n events,\n undefined,\n undefined,\n opts.onData\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Connect to a running PTY.\n *\n * @param pid process ID of the PTY to connect to. You can get the list of running PTYs using {@link Commands.list}.\n * @param opts connection options.\n *\n * @returns handle to interact with the PTY.\n */\n async connect(pid: number, opts?: PtyConnectOpts): Promise<CommandHandle> {\n const requestTimeoutMs =\n opts?.requestTimeoutMs ?? this.connectionConfig.requestTimeoutMs\n\n const controller = new AbortController()\n\n const reqTimeout = requestTimeoutMs\n ? setTimeout(() => {\n controller.abort()\n }, requestTimeoutMs)\n : undefined\n\n const events = this.rpc.connect(\n {\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n },\n {\n signal: controller.signal,\n headers: {\n [KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString(),\n },\n timeoutMs: opts?.timeoutMs ?? this.defaultPtyConnectionTimeout,\n }\n )\n\n try {\n const pid = await handleProcessStartEvent(events)\n\n clearTimeout(reqTimeout)\n\n return new CommandHandle(\n pid,\n () => controller.abort(),\n () => this.kill(pid),\n events,\n undefined,\n undefined,\n opts?.onData\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Send input to a PTY.\n *\n * @param pid process ID of the PTY.\n * @param data input data to send to the PTY.\n * @param opts connection options.\n */\n async sendInput(\n pid: number,\n data: Uint8Array,\n opts?: Pick<ConnectionOpts, 'requestTimeoutMs'>\n ): Promise<void> {\n try {\n await this.rpc.sendInput(\n {\n input: {\n input: {\n case: 'pty',\n value: data,\n },\n },\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n },\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Resize PTY.\n * Call this when the terminal window is resized and the number of columns and rows has changed.\n *\n * @param pid process ID of the PTY.\n * @param size new size of the PTY.\n * @param opts connection options.\n */\n async resize(\n pid: number,\n size: {\n cols: number\n rows: number\n },\n opts?: Pick<ConnectionOpts, 'requestTimeoutMs'>\n ): Promise<void> {\n try {\n await this.rpc.update(\n {\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n pty: {\n size,\n },\n },\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Kill a running PTY specified by process ID.\n * It uses `SIGKILL` signal to kill the PTY.\n *\n * @param pid process ID of the PTY.\n * @param opts connection options.\n *\n * @returns `true` if the PTY was killed, `false` if the PTY was not found.\n */\n async kill(\n pid: number,\n opts?: Pick<ConnectionOpts, 'requestTimeoutMs'>\n ): Promise<boolean> {\n try {\n await this.rpc.sendSignal(\n {\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n signal: Signal.SIGKILL,\n },\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n return true\n } catch (err) {\n if (err instanceof ConnectError) {\n if (err.code === Code.NotFound) {\n return false\n }\n }\n\n throw handleRpcError(err)\n }\n }\n}\n","import {\n Client,\n Code,\n ConnectError,\n Transport,\n createClient,\n} from '@connectrpc/connect'\n\nimport { compareVersions } from 'compare-versions'\nimport {\n ConnectionConfig,\n ConnectionOpts,\n KEEPALIVE_PING_HEADER,\n KEEPALIVE_PING_INTERVAL_SEC,\n Username,\n} from '../../connectionConfig'\nimport { handleProcessStartEvent } from '../../envd/api'\nimport {\n Process as ProcessService,\n Signal,\n} from '../../envd/process/process_pb'\nimport { authenticationHeader, handleRpcError } from '../../envd/rpc'\nimport { ENVD_COMMANDS_STDIN, ENVD_ENVD_CLOSE } from '../../envd/versions'\nimport { SandboxError } from '../../errors'\nimport { CommandHandle, CommandResult } from './commandHandle'\nexport { Pty } from './pty'\n\n/**\n * Options for sending a command request.\n */\nexport interface CommandRequestOpts\n extends Partial<Pick<ConnectionOpts, 'requestTimeoutMs'>> {}\n\n/**\n * Options for starting a new command.\n */\nexport interface CommandStartOpts extends CommandRequestOpts {\n /**\n * If true, starts command in the background and the method returns immediately.\n * You can use {@link CommandHandle.wait} to wait for the command to finish.\n */\n background?: boolean\n /**\n * Working directory for the command.\n *\n * @default // home directory of the user used to start the command\n */\n cwd?: string\n /**\n * User to run the command as.\n *\n * @default `default Sandbox user (as specified in the template)`\n */\n user?: Username\n /**\n * Environment variables used for the command.\n *\n * This overrides the default environment variables from `Sandbox` constructor.\n *\n * @default `{}`\n */\n envs?: Record<string, string>\n /**\n * Callback for command stdout output.\n */\n onStdout?: (data: string) => void | Promise<void>\n /**\n * Callback for command stderr output.\n */\n onStderr?: (data: string) => void | Promise<void>\n /**\n * If true, command stdin is kept open and you can send data to it using {@link Commands.sendStdin} or {@link CommandHandle.sendStdin}.\n * @default false\n */\n stdin?: boolean\n /**\n * Timeout for the command in **milliseconds**.\n *\n * @default 60_000 // 60 seconds\n */\n timeoutMs?: number\n}\n\n/**\n * Options for connecting to a command.\n */\nexport type CommandConnectOpts = Pick<\n CommandStartOpts,\n 'onStderr' | 'onStdout' | 'timeoutMs'\n> &\n CommandRequestOpts\n\n/**\n * Information about a command, PTY session or start command running in the sandbox as process.\n */\nexport interface ProcessInfo {\n /**\n * Process ID.\n */\n pid: number\n /**\n * Custom tag used for identifying special commands like start command in the custom template.\n */\n tag?: string\n /**\n * Command that was executed.\n */\n cmd: string\n /**\n * Command arguments.\n */\n args: string[]\n /**\n * Environment variables used for the command.\n */\n envs: Record<string, string>\n /**\n * Executed command working directory.\n */\n cwd?: string\n}\n\n/**\n * Module for starting and interacting with commands in the sandbox.\n */\nexport class Commands {\n protected readonly rpc: Client<typeof ProcessService>\n\n private readonly defaultProcessConnectionTimeout = 60_000 // 60 seconds\n private readonly envdVersion: string\n\n constructor(\n transport: Transport,\n private readonly connectionConfig: ConnectionConfig,\n metadata: {\n version: string\n }\n ) {\n this.rpc = createClient(ProcessService, transport)\n this.envdVersion = metadata.version\n }\n\n /**\n * @hidden\n * @internal\n */\n get supportsStdinClose(): boolean {\n return compareVersions(this.envdVersion, ENVD_ENVD_CLOSE) >= 0\n }\n\n /**\n * List all running commands and PTY sessions.\n *\n * @param opts connection options.\n *\n * @returns list of running commands and PTY sessions.\n */\n async list(opts?: CommandRequestOpts): Promise<ProcessInfo[]> {\n try {\n const res = await this.rpc.list(\n {},\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n return res.processes.map((p) => ({\n pid: p.pid,\n ...(p.tag && { tag: p.tag }),\n args: p.config!.args,\n envs: p.config!.envs,\n cmd: p.config!.cmd,\n ...(p.config!.cwd && { cwd: p.config!.cwd }),\n }))\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Send data to command stdin.\n *\n * @param pid process ID of the command. You can get the list of running commands using {@link Commands.list}.\n * @param data data to send to the command.\n * @param opts connection options.\n */\n async sendStdin(\n pid: number,\n data: string | Uint8Array,\n opts?: CommandRequestOpts\n ): Promise<void> {\n try {\n const payload =\n typeof data === 'string' ? new TextEncoder().encode(data) : data\n\n await this.rpc.sendInput(\n {\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n input: {\n input: {\n case: 'stdin',\n value: payload,\n },\n },\n },\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * @hidden\n * @internal\n */\n async closeStdin(pid: number, opts?: CommandRequestOpts): Promise<void> {\n if (!this.supportsStdinClose) {\n throw new SandboxError(\n `Sandbox envd version ${this.envdVersion} doesn't support closeStdin. Please rebuild your template to pick up the latest sandbox version.`\n )\n }\n\n try {\n await this.rpc.closeStdin(\n {\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n },\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Kill a running command specified by its process ID.\n * It uses `SIGKILL` signal to kill the command.\n *\n * @param pid process ID of the command. You can get the list of running commands using {@link Commands.list}.\n * @param opts connection options.\n *\n * @returns `true` if the command was killed, `false` if the command was not found.\n */\n async kill(pid: number, opts?: CommandRequestOpts): Promise<boolean> {\n try {\n await this.rpc.sendSignal(\n {\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n signal: Signal.SIGKILL,\n },\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n return true\n } catch (err) {\n if (err instanceof ConnectError) {\n if (err.code === Code.NotFound) {\n return false\n }\n }\n\n throw handleRpcError(err)\n }\n }\n\n /**\n * Connect to a running command.\n * You can use {@link CommandHandle.wait} to wait for the command to finish and get execution results.\n *\n * @param pid process ID of the command to connect to. You can get the list of running commands using {@link Commands.list}.\n * @param opts connection options.\n *\n * @returns `CommandHandle` handle to interact with the running command.\n */\n async connect(\n pid: number,\n opts?: CommandConnectOpts\n ): Promise<CommandHandle> {\n const requestTimeoutMs =\n opts?.requestTimeoutMs ?? this.connectionConfig.requestTimeoutMs\n\n const controller = new AbortController()\n\n const reqTimeout = requestTimeoutMs\n ? setTimeout(() => {\n controller.abort()\n }, requestTimeoutMs)\n : undefined\n\n const events = this.rpc.connect(\n {\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n },\n {\n signal: controller.signal,\n headers: {\n [KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString(),\n },\n timeoutMs: opts?.timeoutMs ?? this.defaultProcessConnectionTimeout,\n }\n )\n\n try {\n const pid = await handleProcessStartEvent(events)\n\n clearTimeout(reqTimeout)\n\n return new CommandHandle(\n pid,\n () => controller.abort(),\n () => this.kill(pid),\n events,\n opts?.onStdout,\n opts?.onStderr,\n undefined\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Start a new command and wait until it finishes executing.\n *\n * @param cmd command to execute.\n * @param opts options for starting the command.\n *\n * @returns `CommandResult` result of the command execution.\n */\n async run(\n cmd: string,\n opts?: CommandStartOpts & { background?: false }\n ): Promise<CommandResult>\n\n /**\n * Start a new command in the background.\n * You can use {@link CommandHandle.wait} to wait for the command to finish and get its result.\n *\n * @param cmd command to execute.\n * @param opts options for starting the command\n *\n * @returns `CommandHandle` handle to interact with the running command.\n */\n async run(\n cmd: string,\n opts: CommandStartOpts & { background: true }\n ): Promise<CommandHandle>\n\n // NOTE - The following overload seems redundant, but it's required to make the type inference work correctly.\n\n /**\n * Start a new command.\n *\n * @param cmd command to execute.\n * @param opts options for starting the command.\n * - `opts.background: true` - runs in background, returns `CommandHandle`\n * - `opts.background: false | undefined` - waits for completion, returns `CommandResult`\n *\n * @returns Either a `CommandHandle` or a `CommandResult` (depending on `opts.background`).\n */\n async run(\n cmd: string,\n opts?: CommandStartOpts & { background?: boolean }\n ): Promise<CommandHandle | CommandResult>\n async run(\n cmd: string,\n opts?: CommandStartOpts & { background?: boolean }\n ): Promise<CommandHandle | CommandResult> {\n const proc = await this.start(cmd, opts)\n\n return opts?.background ? proc : proc.wait()\n }\n\n private async start(\n cmd: string,\n opts?: CommandStartOpts\n ): Promise<CommandHandle> {\n const requestTimeoutMs =\n opts?.requestTimeoutMs ?? this.connectionConfig.requestTimeoutMs\n\n const controller = new AbortController()\n\n const reqTimeout = requestTimeoutMs\n ? setTimeout(() => {\n controller.abort()\n }, requestTimeoutMs)\n : undefined\n\n if (\n opts?.stdin === false &&\n compareVersions(this.envdVersion, ENVD_COMMANDS_STDIN) < 0\n ) {\n throw new SandboxError(\n `Sandbox envd version ${this.envdVersion} can't specify stdin, it's always turned on. Please rebuild your template if you need this feature.`\n )\n }\n\n const events = this.rpc.start(\n {\n process: {\n cmd: '/bin/bash',\n cwd: opts?.cwd,\n envs: opts?.envs,\n args: ['-l', '-c', cmd],\n },\n stdin: opts?.stdin || false,\n },\n {\n headers: {\n ...authenticationHeader(this.envdVersion, opts?.user),\n [KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString(),\n },\n signal: controller.signal,\n timeoutMs: opts?.timeoutMs ?? this.defaultProcessConnectionTimeout,\n }\n )\n\n try {\n const pid = await handleProcessStartEvent(events)\n\n clearTimeout(reqTimeout)\n\n return new CommandHandle(\n pid,\n () => controller.abort(),\n () => this.kill(pid),\n events,\n opts?.onStdout,\n opts?.onStderr,\n undefined\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n}\n","// @generated by protoc-gen-es v2.6.2 with parameter \"target=ts\"\n// @generated from file filesystem/filesystem.proto (package filesystem, syntax proto3)\n/* eslint-disable */\n\nimport type {\n GenEnum,\n GenFile,\n GenMessage,\n GenService,\n} from '@bufbuild/protobuf/codegenv2'\nimport {\n enumDesc,\n fileDesc,\n messageDesc,\n serviceDesc,\n} from '@bufbuild/protobuf/codegenv2'\nimport type { Timestamp } from '@bufbuild/protobuf/wkt'\nimport { file_google_protobuf_timestamp } from '@bufbuild/protobuf/wkt'\nimport type { Message } from '@bufbuild/protobuf'\n\n/**\n * Describes the file filesystem/filesystem.proto.\n */\nexport const file_filesystem_filesystem: GenFile =\n /*@__PURE__*/\n fileDesc(\n 'ChtmaWxlc3lzdGVtL2ZpbGVzeXN0ZW0ucHJvdG8SCmZpbGVzeXN0ZW0iMgoLTW92ZVJlcXVlc3QSDgoGc291cmNlGAEgASgJEhMKC2Rlc3RpbmF0aW9uGAIgASgJIjQKDE1vdmVSZXNwb25zZRIkCgVlbnRyeRgBIAEoCzIVLmZpbGVzeXN0ZW0uRW50cnlJbmZvIh4KDk1ha2VEaXJSZXF1ZXN0EgwKBHBhdGgYASABKAkiNwoPTWFrZURpclJlc3BvbnNlEiQKBWVudHJ5GAEgASgLMhUuZmlsZXN5c3RlbS5FbnRyeUluZm8iHQoNUmVtb3ZlUmVxdWVzdBIMCgRwYXRoGAEgASgJIhAKDlJlbW92ZVJlc3BvbnNlIhsKC1N0YXRSZXF1ZXN0EgwKBHBhdGgYASABKAkiNAoMU3RhdFJlc3BvbnNlEiQKBWVudHJ5GAEgASgLMhUuZmlsZXN5c3RlbS5FbnRyeUluZm8i/QEKCUVudHJ5SW5mbxIMCgRuYW1lGAEgASgJEiIKBHR5cGUYAiABKA4yFC5maWxlc3lzdGVtLkZpbGVUeXBlEgwKBHBhdGgYAyABKAkSDAoEc2l6ZRgEIAEoAxIMCgRtb2RlGAUgASgNEhMKC3Blcm1pc3Npb25zGAYgASgJEg0KBW93bmVyGAcgASgJEg0KBWdyb3VwGAggASgJEjEKDW1vZGlmaWVkX3RpbWUYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhsKDnN5bWxpbmtfdGFyZ2V0GAogASgJSACIAQFCEQoPX3N5bWxpbmtfdGFyZ2V0Ii0KDkxpc3REaXJSZXF1ZXN0EgwKBHBhdGgYASABKAkSDQoFZGVwdGgYAiABKA0iOQoPTGlzdERpclJlc3BvbnNlEiYKB2VudHJpZXMYASADKAsyFS5maWxlc3lzdGVtLkVudHJ5SW5mbyIyCg9XYXRjaERpclJlcXVlc3QSDAoEcGF0aBgBIAEoCRIRCglyZWN1cnNpdmUYAiABKAgiRAoPRmlsZXN5c3RlbUV2ZW50EgwKBG5hbWUYASABKAkSIwoEdHlwZRgCIAEoDjIVLmZpbGVzeXN0ZW0uRXZlbnRUeXBlIuABChBXYXRjaERpclJlc3BvbnNlEjgKBXN0YXJ0GAEgASgLMicuZmlsZXN5c3RlbS5XYXRjaERpclJlc3BvbnNlLlN0YXJ0RXZlbnRIABIxCgpmaWxlc3lzdGVtGAIgASgLMhsuZmlsZXN5c3RlbS5GaWxlc3lzdGVtRXZlbnRIABI7CglrZWVwYWxpdmUYAyABKAsyJi5maWxlc3lzdGVtLldhdGNoRGlyUmVzcG9uc2UuS2VlcEFsaXZlSAAaDAoKU3RhcnRFdmVudBoLCglLZWVwQWxpdmVCBwoFZXZlbnQiNwoUQ3JlYXRlV2F0Y2hlclJlcXVlc3QSDAoEcGF0aBgBIAEoCRIRCglyZWN1cnNpdmUYAiABKAgiKwoVQ3JlYXRlV2F0Y2hlclJlc3BvbnNlEhIKCndhdGNoZXJfaWQYASABKAkiLQoXR2V0V2F0Y2hlckV2ZW50c1JlcXVlc3QSEgoKd2F0Y2hlcl9pZBgBIAEoCSJHChhHZXRXYXRjaGVyRXZlbnRzUmVzcG9uc2USKwoGZXZlbnRzGAEgAygLMhsuZmlsZXN5c3RlbS5GaWxlc3lzdGVtRXZlbnQiKgoUUmVtb3ZlV2F0Y2hlclJlcXVlc3QSEgoKd2F0Y2hlcl9pZBgBIAEoCSIXChVSZW1vdmVXYXRjaGVyUmVzcG9uc2UqUgoIRmlsZVR5cGUSGQoVRklMRV9UWVBFX1VOU1BFQ0lGSUVEEAASEgoORklMRV9UWVBFX0ZJTEUQARIXChNGSUxFX1RZUEVfRElSRUNUT1JZEAIqmAEKCUV2ZW50VHlwZRIaChZFVkVOVF9UWVBFX1VOU1BFQ0lGSUVEEAASFQoRRVZFTlRfVFlQRV9DUkVBVEUQARIUChBFVkVOVF9UWVBFX1dSSVRFEAISFQoRRVZFTlRfVFlQRV9SRU1PVkUQAxIVChFFVkVOVF9UWVBFX1JFTkFNRRAEEhQKEEVWRU5UX1RZUEVfQ0hNT0QQBTKfBQoKRmlsZXN5c3RlbRI5CgRTdGF0EhcuZmlsZXN5c3RlbS5TdGF0UmVxdWVzdBoYLmZpbGVzeXN0ZW0uU3RhdFJlc3BvbnNlEkIKB01ha2VEaXISGi5maWxlc3lzdGVtLk1ha2VEaXJSZXF1ZXN0GhsuZmlsZXN5c3RlbS5NYWtlRGlyUmVzcG9uc2USOQoETW92ZRIXLmZpbGVzeXN0ZW0uTW92ZVJlcXVlc3QaGC5maWxlc3lzdGVtLk1vdmVSZXNwb25zZRJCCgdMaXN0RGlyEhouZmlsZXN5c3RlbS5MaXN0RGlyUmVxdWVzdBobLmZpbGVzeXN0ZW0uTGlzdERpclJlc3BvbnNlEj8KBlJlbW92ZRIZLmZpbGVzeXN0ZW0uUmVtb3ZlUmVxdWVzdBoaLmZpbGVzeXN0ZW0uUmVtb3ZlUmVzcG9uc2USRwoIV2F0Y2hEaXISGy5maWxlc3lzdGVtLldhdGNoRGlyUmVxdWVzdBocLmZpbGVzeXN0ZW0uV2F0Y2hEaXJSZXNwb25zZTABElQKDUNyZWF0ZVdhdGNoZXISIC5maWxlc3lzdGVtLkNyZWF0ZVdhdGNoZXJSZXF1ZXN0GiEuZmlsZXN5c3RlbS5DcmVhdGVXYXRjaGVyUmVzcG9uc2USXQoQR2V0V2F0Y2hlckV2ZW50cxIjLmZpbGVzeXN0ZW0uR2V0V2F0Y2hlckV2ZW50c1JlcXVlc3QaJC5maWxlc3lzdGVtLkdldFdhdGNoZXJFdmVudHNSZXNwb25zZRJUCg1SZW1vdmVXYXRjaGVyEiAuZmlsZXN5c3RlbS5SZW1vdmVXYXRjaGVyUmVxdWVzdBohLmZpbGVzeXN0ZW0uUmVtb3ZlV2F0Y2hlclJlc3BvbnNlQmkKDmNvbS5maWxlc3lzdGVtQg9GaWxlc3lzdGVtUHJvdG9QAaICA0ZYWKoCCkZpbGVzeXN0ZW3KAgpGaWxlc3lzdGVt4gIWRmlsZXN5c3RlbVxHUEJNZXRhZGF0YeoCCkZpbGVzeXN0ZW1iBnByb3RvMw',\n [file_google_protobuf_timestamp]\n )\n\n/**\n * @generated from message filesystem.MoveRequest\n */\nexport type MoveRequest = Message<'filesystem.MoveRequest'> & {\n /**\n * @generated from field: string source = 1;\n */\n source: string\n\n /**\n * @generated from field: string destination = 2;\n */\n destination: string\n}\n\n/**\n * Describes the message filesystem.MoveRequest.\n * Use `create(MoveRequestSchema)` to create a new message.\n */\nexport const MoveRequestSchema: GenMessage<MoveRequest> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 0)\n\n/**\n * @generated from message filesystem.MoveResponse\n */\nexport type MoveResponse = Message<'filesystem.MoveResponse'> & {\n /**\n * @generated from field: filesystem.EntryInfo entry = 1;\n */\n entry?: EntryInfo\n}\n\n/**\n * Describes the message filesystem.MoveResponse.\n * Use `create(MoveResponseSchema)` to create a new message.\n */\nexport const MoveResponseSchema: GenMessage<MoveResponse> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 1)\n\n/**\n * @generated from message filesystem.MakeDirRequest\n */\nexport type MakeDirRequest = Message<'filesystem.MakeDirRequest'> & {\n /**\n * @generated from field: string path = 1;\n */\n path: string\n}\n\n/**\n * Describes the message filesystem.MakeDirRequest.\n * Use `create(MakeDirRequestSchema)` to create a new message.\n */\nexport const MakeDirRequestSchema: GenMessage<MakeDirRequest> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 2)\n\n/**\n * @generated from message filesystem.MakeDirResponse\n */\nexport type MakeDirResponse = Message<'filesystem.MakeDirResponse'> & {\n /**\n * @generated from field: filesystem.EntryInfo entry = 1;\n */\n entry?: EntryInfo\n}\n\n/**\n * Describes the message filesystem.MakeDirResponse.\n * Use `create(MakeDirResponseSchema)` to create a new message.\n */\nexport const MakeDirResponseSchema: GenMessage<MakeDirResponse> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 3)\n\n/**\n * @generated from message filesystem.RemoveRequest\n */\nexport type RemoveRequest = Message<'filesystem.RemoveRequest'> & {\n /**\n * @generated from field: string path = 1;\n */\n path: string\n}\n\n/**\n * Describes the message filesystem.RemoveRequest.\n * Use `create(RemoveRequestSchema)` to create a new message.\n */\nexport const RemoveRequestSchema: GenMessage<RemoveRequest> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 4)\n\n/**\n * @generated from message filesystem.RemoveResponse\n */\nexport type RemoveResponse = Message<'filesystem.RemoveResponse'> & {}\n\n/**\n * Describes the message filesystem.RemoveResponse.\n * Use `create(RemoveResponseSchema)` to create a new message.\n */\nexport const RemoveResponseSchema: GenMessage<RemoveResponse> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 5)\n\n/**\n * @generated from message filesystem.StatRequest\n */\nexport type StatRequest = Message<'filesystem.StatRequest'> & {\n /**\n * @generated from field: string path = 1;\n */\n path: string\n}\n\n/**\n * Describes the message filesystem.StatRequest.\n * Use `create(StatRequestSchema)` to create a new message.\n */\nexport const StatRequestSchema: GenMessage<StatRequest> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 6)\n\n/**\n * @generated from message filesystem.StatResponse\n */\nexport type StatResponse = Message<'filesystem.StatResponse'> & {\n /**\n * @generated from field: filesystem.EntryInfo entry = 1;\n */\n entry?: EntryInfo\n}\n\n/**\n * Describes the message filesystem.StatResponse.\n * Use `create(StatResponseSchema)` to create a new message.\n */\nexport const StatResponseSchema: GenMessage<StatResponse> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 7)\n\n/**\n * @generated from message filesystem.EntryInfo\n */\nexport type EntryInfo = Message<'filesystem.EntryInfo'> & {\n /**\n * @generated from field: string name = 1;\n */\n name: string\n\n /**\n * @generated from field: filesystem.FileType type = 2;\n */\n type: FileType\n\n /**\n * @generated from field: string path = 3;\n */\n path: string\n\n /**\n * @generated from field: int64 size = 4;\n */\n size: bigint\n\n /**\n * @generated from field: uint32 mode = 5;\n */\n mode: number\n\n /**\n * @generated from field: string permissions = 6;\n */\n permissions: string\n\n /**\n * @generated from field: string owner = 7;\n */\n owner: string\n\n /**\n * @generated from field: string group = 8;\n */\n group: string\n\n /**\n * @generated from field: google.protobuf.Timestamp modified_time = 9;\n */\n modifiedTime?: Timestamp\n\n /**\n * If the entry is a symlink, this field contains the target of the symlink.\n *\n * @generated from field: optional string symlink_target = 10;\n */\n symlinkTarget?: string\n}\n\n/**\n * Describes the message filesystem.EntryInfo.\n * Use `create(EntryInfoSchema)` to create a new message.\n */\nexport const EntryInfoSchema: GenMessage<EntryInfo> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 8)\n\n/**\n * @generated from message filesystem.ListDirRequest\n */\nexport type ListDirRequest = Message<'filesystem.ListDirRequest'> & {\n /**\n * @generated from field: string path = 1;\n */\n path: string\n\n /**\n * @generated from field: uint32 depth = 2;\n */\n depth: number\n}\n\n/**\n * Describes the message filesystem.ListDirRequest.\n * Use `create(ListDirRequestSchema)` to create a new message.\n */\nexport const ListDirRequestSchema: GenMessage<ListDirRequest> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 9)\n\n/**\n * @generated from message filesystem.ListDirResponse\n */\nexport type ListDirResponse = Message<'filesystem.ListDirResponse'> & {\n /**\n * @generated from field: repeated filesystem.EntryInfo entries = 1;\n */\n entries: EntryInfo[]\n}\n\n/**\n * Describes the message filesystem.ListDirResponse.\n * Use `create(ListDirResponseSchema)` to create a new message.\n */\nexport const ListDirResponseSchema: GenMessage<ListDirResponse> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 10)\n\n/**\n * @generated from message filesystem.WatchDirRequest\n */\nexport type WatchDirRequest = Message<'filesystem.WatchDirRequest'> & {\n /**\n * @generated from field: string path = 1;\n */\n path: string\n\n /**\n * @generated from field: bool recursive = 2;\n */\n recursive: boolean\n}\n\n/**\n * Describes the message filesystem.WatchDirRequest.\n * Use `create(WatchDirRequestSchema)` to create a new message.\n */\nexport const WatchDirRequestSchema: GenMessage<WatchDirRequest> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 11)\n\n/**\n * @generated from message filesystem.FilesystemEvent\n */\nexport type FilesystemEvent = Message<'filesystem.FilesystemEvent'> & {\n /**\n * @generated from field: string name = 1;\n */\n name: string\n\n /**\n * @generated from field: filesystem.EventType type = 2;\n */\n type: EventType\n}\n\n/**\n * Describes the message filesystem.FilesystemEvent.\n * Use `create(FilesystemEventSchema)` to create a new message.\n */\nexport const FilesystemEventSchema: GenMessage<FilesystemEvent> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 12)\n\n/**\n * @generated from message filesystem.WatchDirResponse\n */\nexport type WatchDirResponse = Message<'filesystem.WatchDirResponse'> & {\n /**\n * @generated from oneof filesystem.WatchDirResponse.event\n */\n event:\n | {\n /**\n * @generated from field: filesystem.WatchDirResponse.StartEvent start = 1;\n */\n value: WatchDirResponse_StartEvent\n case: 'start'\n }\n | {\n /**\n * @generated from field: filesystem.FilesystemEvent filesystem = 2;\n */\n value: FilesystemEvent\n case: 'filesystem'\n }\n | {\n /**\n * @generated from field: filesystem.WatchDirResponse.KeepAlive keepalive = 3;\n */\n value: WatchDirResponse_KeepAlive\n case: 'keepalive'\n }\n | { case: undefined; value?: undefined }\n}\n\n/**\n * Describes the message filesystem.WatchDirResponse.\n * Use `create(WatchDirResponseSchema)` to create a new message.\n */\nexport const WatchDirResponseSchema: GenMessage<WatchDirResponse> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 13)\n\n/**\n * @generated from message filesystem.WatchDirResponse.StartEvent\n */\nexport type WatchDirResponse_StartEvent =\n Message<'filesystem.WatchDirResponse.StartEvent'> & {}\n\n/**\n * Describes the message filesystem.WatchDirResponse.StartEvent.\n * Use `create(WatchDirResponse_StartEventSchema)` to create a new message.\n */\nexport const WatchDirResponse_StartEventSchema: GenMessage<WatchDirResponse_StartEvent> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 13, 0)\n\n/**\n * @generated from message filesystem.WatchDirResponse.KeepAlive\n */\nexport type WatchDirResponse_KeepAlive =\n Message<'filesystem.WatchDirResponse.KeepAlive'> & {}\n\n/**\n * Describes the message filesystem.WatchDirResponse.KeepAlive.\n * Use `create(WatchDirResponse_KeepAliveSchema)` to create a new message.\n */\nexport const WatchDirResponse_KeepAliveSchema: GenMessage<WatchDirResponse_KeepAlive> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 13, 1)\n\n/**\n * @generated from message filesystem.CreateWatcherRequest\n */\nexport type CreateWatcherRequest =\n Message<'filesystem.CreateWatcherRequest'> & {\n /**\n * @generated from field: string path = 1;\n */\n path: string\n\n /**\n * @generated from field: bool recursive = 2;\n */\n recursive: boolean\n }\n\n/**\n * Describes the message filesystem.CreateWatcherRequest.\n * Use `create(CreateWatcherRequestSchema)` to create a new message.\n */\nexport const CreateWatcherRequestSchema: GenMessage<CreateWatcherRequest> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 14)\n\n/**\n * @generated from message filesystem.CreateWatcherResponse\n */\nexport type CreateWatcherResponse =\n Message<'filesystem.CreateWatcherResponse'> & {\n /**\n * @generated from field: string watcher_id = 1;\n */\n watcherId: string\n }\n\n/**\n * Describes the message filesystem.CreateWatcherResponse.\n * Use `create(CreateWatcherResponseSchema)` to create a new message.\n */\nexport const CreateWatcherResponseSchema: GenMessage<CreateWatcherResponse> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 15)\n\n/**\n * @generated from message filesystem.GetWatcherEventsRequest\n */\nexport type GetWatcherEventsRequest =\n Message<'filesystem.GetWatcherEventsRequest'> & {\n /**\n * @generated from field: string watcher_id = 1;\n */\n watcherId: string\n }\n\n/**\n * Describes the message filesystem.GetWatcherEventsRequest.\n * Use `create(GetWatcherEventsRequestSchema)` to create a new message.\n */\nexport const GetWatcherEventsRequestSchema: GenMessage<GetWatcherEventsRequest> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 16)\n\n/**\n * @generated from message filesystem.GetWatcherEventsResponse\n */\nexport type GetWatcherEventsResponse =\n Message<'filesystem.GetWatcherEventsResponse'> & {\n /**\n * @generated from field: repeated filesystem.FilesystemEvent events = 1;\n */\n events: FilesystemEvent[]\n }\n\n/**\n * Describes the message filesystem.GetWatcherEventsResponse.\n * Use `create(GetWatcherEventsResponseSchema)` to create a new message.\n */\nexport const GetWatcherEventsResponseSchema: GenMessage<GetWatcherEventsResponse> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 17)\n\n/**\n * @generated from message filesystem.RemoveWatcherRequest\n */\nexport type RemoveWatcherRequest =\n Message<'filesystem.RemoveWatcherRequest'> & {\n /**\n * @generated from field: string watcher_id = 1;\n */\n watcherId: string\n }\n\n/**\n * Describes the message filesystem.RemoveWatcherRequest.\n * Use `create(RemoveWatcherRequestSchema)` to create a new message.\n */\nexport const RemoveWatcherRequestSchema: GenMessage<RemoveWatcherRequest> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 18)\n\n/**\n * @generated from message filesystem.RemoveWatcherResponse\n */\nexport type RemoveWatcherResponse =\n Message<'filesystem.RemoveWatcherResponse'> & {}\n\n/**\n * Describes the message filesystem.RemoveWatcherResponse.\n * Use `create(RemoveWatcherResponseSchema)` to create a new message.\n */\nexport const RemoveWatcherResponseSchema: GenMessage<RemoveWatcherResponse> =\n /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 19)\n\n/**\n * @generated from enum filesystem.FileType\n */\nexport enum FileType {\n /**\n * @generated from enum value: FILE_TYPE_UNSPECIFIED = 0;\n */\n UNSPECIFIED = 0,\n\n /**\n * @generated from enum value: FILE_TYPE_FILE = 1;\n */\n FILE = 1,\n\n /**\n * @generated from enum value: FILE_TYPE_DIRECTORY = 2;\n */\n DIRECTORY = 2,\n}\n\n/**\n * Describes the enum filesystem.FileType.\n */\nexport const FileTypeSchema: GenEnum<FileType> =\n /*@__PURE__*/\n enumDesc(file_filesystem_filesystem, 0)\n\n/**\n * @generated from enum filesystem.EventType\n */\nexport enum EventType {\n /**\n * @generated from enum value: EVENT_TYPE_UNSPECIFIED = 0;\n */\n UNSPECIFIED = 0,\n\n /**\n * @generated from enum value: EVENT_TYPE_CREATE = 1;\n */\n CREATE = 1,\n\n /**\n * @generated from enum value: EVENT_TYPE_WRITE = 2;\n */\n WRITE = 2,\n\n /**\n * @generated from enum value: EVENT_TYPE_REMOVE = 3;\n */\n REMOVE = 3,\n\n /**\n * @generated from enum value: EVENT_TYPE_RENAME = 4;\n */\n RENAME = 4,\n\n /**\n * @generated from enum value: EVENT_TYPE_CHMOD = 5;\n */\n CHMOD = 5,\n}\n\n/**\n * Describes the enum filesystem.EventType.\n */\nexport const EventTypeSchema: GenEnum<EventType> =\n /*@__PURE__*/\n enumDesc(file_filesystem_filesystem, 1)\n\n/**\n * @generated from service filesystem.Filesystem\n */\nexport const Filesystem: GenService<{\n /**\n * @generated from rpc filesystem.Filesystem.Stat\n */\n stat: {\n methodKind: 'unary'\n input: typeof StatRequestSchema\n output: typeof StatResponseSchema\n }\n /**\n * @generated from rpc filesystem.Filesystem.MakeDir\n */\n makeDir: {\n methodKind: 'unary'\n input: typeof MakeDirRequestSchema\n output: typeof MakeDirResponseSchema\n }\n /**\n * @generated from rpc filesystem.Filesystem.Move\n */\n move: {\n methodKind: 'unary'\n input: typeof MoveRequestSchema\n output: typeof MoveResponseSchema\n }\n /**\n * @generated from rpc filesystem.Filesystem.ListDir\n */\n listDir: {\n methodKind: 'unary'\n input: typeof ListDirRequestSchema\n output: typeof ListDirResponseSchema\n }\n /**\n * @generated from rpc filesystem.Filesystem.Remove\n */\n remove: {\n methodKind: 'unary'\n input: typeof RemoveRequestSchema\n output: typeof RemoveResponseSchema\n }\n /**\n * @generated from rpc filesystem.Filesystem.WatchDir\n */\n watchDir: {\n methodKind: 'server_streaming'\n input: typeof WatchDirRequestSchema\n output: typeof WatchDirResponseSchema\n }\n /**\n * Non-streaming versions of WatchDir\n *\n * @generated from rpc filesystem.Filesystem.CreateWatcher\n */\n createWatcher: {\n methodKind: 'unary'\n input: typeof CreateWatcherRequestSchema\n output: typeof CreateWatcherResponseSchema\n }\n /**\n * @generated from rpc filesystem.Filesystem.GetWatcherEvents\n */\n getWatcherEvents: {\n methodKind: 'unary'\n input: typeof GetWatcherEventsRequestSchema\n output: typeof GetWatcherEventsResponseSchema\n }\n /**\n * @generated from rpc filesystem.Filesystem.RemoveWatcher\n */\n removeWatcher: {\n methodKind: 'unary'\n input: typeof RemoveWatcherRequestSchema\n output: typeof RemoveWatcherResponseSchema\n }\n}> = /*@__PURE__*/ serviceDesc(file_filesystem_filesystem, 0)\n","import { handleRpcError } from '../../envd/rpc'\nimport {\n EventType,\n WatchDirResponse,\n} from '../../envd/filesystem/filesystem_pb'\n\n/**\n * Sandbox filesystem event types.\n */\nexport enum FilesystemEventType {\n /**\n * Filesystem object permissions were changed.\n */\n CHMOD = 'chmod',\n /**\n * Filesystem object was created.\n */\n CREATE = 'create',\n /**\n * Filesystem object was removed.\n */\n REMOVE = 'remove',\n /**\n * Filesystem object was renamed.\n */\n RENAME = 'rename',\n /**\n * Filesystem object was written to.\n */\n WRITE = 'write',\n}\n\nfunction mapEventType(type: EventType) {\n switch (type) {\n case EventType.CHMOD:\n return FilesystemEventType.CHMOD\n case EventType.CREATE:\n return FilesystemEventType.CREATE\n case EventType.REMOVE:\n return FilesystemEventType.REMOVE\n case EventType.RENAME:\n return FilesystemEventType.RENAME\n case EventType.WRITE:\n return FilesystemEventType.WRITE\n }\n}\n\n/**\n * Information about a filesystem event.\n */\nexport interface FilesystemEvent {\n /**\n * Relative path to the filesystem object.\n */\n name: string\n /**\n * Filesystem operation event type.\n */\n type: FilesystemEventType\n}\n\n/**\n * Handle for watching a directory in the sandbox filesystem.\n *\n * Use {@link WatchHandle.stop} to stop watching the directory.\n */\nexport class WatchHandle {\n constructor(\n private readonly handleStop: () => void,\n private readonly events: AsyncIterable<WatchDirResponse>,\n private readonly onEvent?: (event: FilesystemEvent) => void | Promise<void>,\n private readonly onExit?: (err?: Error) => void | Promise<void>\n ) {\n this.handleEvents()\n }\n\n /**\n * Stop watching the directory.\n */\n async stop() {\n this.handleStop()\n }\n\n private async *iterateEvents() {\n try {\n for await (const event of this.events) {\n switch (event.event.case) {\n case 'filesystem':\n yield event.event\n break\n }\n }\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n private async handleEvents() {\n try {\n for await (const event of this.iterateEvents()) {\n const eventType = mapEventType(event.value.type)\n if (eventType === undefined) {\n continue\n }\n\n this.onEvent?.({\n name: event.value.name,\n type: eventType,\n })\n }\n this.onExit?.()\n } catch (err) {\n this.onExit?.(err as Error)\n }\n }\n}\n","import {\n Client,\n Code,\n ConnectError,\n createClient,\n Transport,\n} from '@connectrpc/connect'\nimport {\n ConnectionConfig,\n ConnectionOpts,\n defaultUsername,\n KEEPALIVE_PING_HEADER,\n KEEPALIVE_PING_INTERVAL_SEC,\n Username,\n} from '../../connectionConfig'\n\nimport { handleEnvdApiError, handleWatchDirStartEvent } from '../../envd/api'\nimport { authenticationHeader, handleRpcError } from '../../envd/rpc'\n\nimport { EnvdApiClient } from '../../envd/api'\nimport {\n Filesystem as FilesystemService,\n FileType as FsFileType,\n} from '../../envd/filesystem/filesystem_pb'\n\nimport { FilesystemEvent, WatchHandle } from './watchHandle'\n\nimport type { Timestamp } from '@bufbuild/protobuf/wkt'\nimport { compareVersions } from 'compare-versions'\nimport {\n ENVD_DEFAULT_USER,\n ENVD_OCTET_STREAM_UPLOAD,\n ENVD_VERSION_RECURSIVE_WATCH,\n} from '../../envd/versions'\nimport {\n FileNotFoundError,\n InvalidArgumentError,\n TemplateError,\n} from '../../errors'\nimport { toBlob, toUploadBody } from '../../utils'\n\nconst FILESYSTEM_HTTP_ERROR_MAP: Record<number, (message: string) => Error> = {\n 404: (message: string) => new FileNotFoundError(message),\n}\n\nconst FILESYSTEM_RPC_ERROR_MAP: Partial<\n Record<Code, (message: string) => Error>\n> = {\n [Code.NotFound]: (message: string) => new FileNotFoundError(message),\n}\n\nfunction handleFilesystemRpcError(err: unknown): Error {\n return handleRpcError(err, FILESYSTEM_RPC_ERROR_MAP)\n}\n\nfunction handleFilesystemEnvdApiError(res: {\n error?: { message?: string } | string\n response: Response\n}) {\n return handleEnvdApiError(res, FILESYSTEM_HTTP_ERROR_MAP)\n}\n\n/**\n * Sandbox filesystem object information.\n */\nexport interface WriteInfo {\n /**\n * Name of the filesystem object.\n */\n name: string\n /**\n * Type of the filesystem object.\n */\n type?: FileType\n /**\n * Path to the filesystem object.\n */\n path: string\n}\n\nexport interface EntryInfo extends WriteInfo {\n /**\n * Size of the filesystem object in bytes.\n */\n size: number\n\n /**\n * File mode and permission bits.\n */\n mode: number\n\n /**\n * String representation of file permissions (e.g. 'rwxr-xr-x').\n */\n permissions: string\n\n /**\n * Owner of the filesystem object.\n */\n owner: string\n\n /**\n * Group owner of the filesystem object.\n */\n group: string\n\n /**\n * Last modification time of the filesystem object.\n */\n modifiedTime?: Date\n\n /**\n * If the filesystem object is a symlink, this is the target of the symlink.\n */\n symlinkTarget?: string\n}\n\n/**\n * Sandbox filesystem object type.\n */\nexport enum FileType {\n /**\n * Filesystem object is a file.\n */\n FILE = 'file',\n /**\n * Filesystem object is a directory.\n */\n DIR = 'dir',\n}\n\nexport type WriteEntry = {\n path: string\n data: string | ArrayBuffer | Blob | ReadableStream\n}\n\nfunction mapFileType(fileType: FsFileType) {\n switch (fileType) {\n case FsFileType.DIRECTORY:\n return FileType.DIR\n case FsFileType.FILE:\n return FileType.FILE\n }\n}\n\nfunction mapModifiedTime(modifiedTime: Timestamp | undefined) {\n if (!modifiedTime) return undefined\n\n return new Date(\n Number(modifiedTime.seconds) * 1000 +\n Math.floor(modifiedTime.nanos / 1_000_000)\n )\n}\n\n/**\n * Options for the sandbox filesystem operations.\n */\nexport interface FilesystemRequestOpts\n extends Partial<Pick<ConnectionOpts, 'requestTimeoutMs'>> {\n /**\n * User to use for the operation in the sandbox.\n * This affects the resolution of relative paths and ownership of the created filesystem objects.\n */\n user?: Username\n}\n\n/**\n * Options for writing files to the sandbox filesystem.\n */\nexport interface FilesystemWriteOpts extends FilesystemRequestOpts {\n /**\n * When true, the upload will be gzip-compressed.\n */\n gzip?: boolean\n}\n\n/**\n * Options for reading files from the sandbox filesystem.\n */\nexport interface FilesystemReadOpts extends FilesystemRequestOpts {\n /**\n * When true, the download will request gzip-encoded responses.\n */\n gzip?: boolean\n}\n\nexport interface FilesystemListOpts extends FilesystemRequestOpts {\n /**\n * Depth of the directory to list.\n */\n depth?: number\n}\n\n/**\n * Options for watching a directory.\n */\nexport interface WatchOpts extends FilesystemRequestOpts {\n /**\n * Timeout for the watch operation in **milliseconds**.\n * You can pass `0` to disable the timeout.\n *\n * @default 60_000 // 60 seconds\n */\n timeoutMs?: number\n /**\n * Callback to call when the watch operation stops.\n */\n onExit?: (err?: Error) => void | Promise<void>\n /**\n * Watch the directory recursively\n */\n recursive?: boolean\n}\n\n/**\n * Module for interacting with the sandbox filesystem.\n */\nexport class Filesystem {\n private readonly rpc: Client<typeof FilesystemService>\n\n private readonly defaultWatchTimeout = 60_000 // 60 seconds\n private readonly defaultWatchRecursive = false\n\n constructor(\n transport: Transport,\n private readonly envdApi: EnvdApiClient,\n private readonly connectionConfig: ConnectionConfig\n ) {\n this.rpc = createClient(FilesystemService, transport)\n }\n\n /**\n * Read file content as a `string`.\n *\n * You can pass `text`, `bytes`, `blob`, or `stream` to `opts.format` to change the return type.\n *\n * @param path path to the file.\n * @param opts connection options.\n * @param [opts.format] format of the file content—`text` by default.\n *\n * @returns file content as string\n */\n async read(\n path: string,\n opts?: FilesystemReadOpts & { format?: 'text' }\n ): Promise<string>\n /**\n * Read file content as a `Uint8Array`.\n *\n * You can pass `text`, `bytes`, `blob`, or `stream` to `opts.format` to change the return type.\n *\n * @param path path to the file.\n * @param opts connection options.\n * @param [opts.format] format of the file content—`bytes`.\n *\n * @returns file content as `Uint8Array`\n */\n async read(\n path: string,\n opts?: FilesystemReadOpts & { format: 'bytes' }\n ): Promise<Uint8Array>\n /**\n * Read file content as a `Blob`.\n *\n * You can pass `text`, `bytes`, `blob`, or `stream` to `opts.format` to change the return type.\n *\n * @param path path to the file.\n * @param opts connection options.\n * @param [opts.format] format of the file content—`blob`.\n *\n * @returns file content as `Blob`\n */\n async read(\n path: string,\n opts?: FilesystemReadOpts & { format: 'blob' }\n ): Promise<Blob>\n /**\n * Read file content as a `ReadableStream`.\n *\n * You can pass `text`, `bytes`, `blob`, or `stream` to `opts.format` to change the return type.\n *\n * @param path path to the file.\n * @param opts connection options.\n * @param [opts.format] format of the file content—`stream`.\n *\n * @returns file content as `ReadableStream`\n */\n async read(\n path: string,\n opts?: FilesystemReadOpts & { format: 'stream' }\n ): Promise<ReadableStream<Uint8Array>>\n async read(\n path: string,\n opts?: FilesystemReadOpts & {\n format?: 'text' | 'bytes' | 'blob' | 'stream'\n }\n ): Promise<unknown> {\n const format = opts?.format ?? 'text'\n\n let user = opts?.user\n if (\n user == undefined &&\n compareVersions(this.envdApi.version, ENVD_DEFAULT_USER) < 0\n ) {\n user = defaultUsername\n }\n\n const headers: Record<string, string> = {}\n if (opts?.gzip) {\n headers['Accept-Encoding'] = 'gzip'\n }\n\n const res = await this.envdApi.api.GET('/files', {\n params: {\n query: {\n path,\n username: user,\n },\n },\n parseAs: format === 'bytes' ? 'arrayBuffer' : format,\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n headers,\n })\n\n const err = await handleFilesystemEnvdApiError(res)\n if (err) {\n throw err\n }\n\n if (format === 'bytes') {\n return new Uint8Array(res.data as ArrayBuffer)\n }\n\n // When the file is empty, res.data is parsed as `{}`. This is a workaround to return an empty string.\n if (res.response.headers.get('content-length') === '0') {\n if (format === 'blob') {\n return new Blob([])\n }\n\n return ''\n }\n\n return res.data\n }\n\n /**\n * Write content to a file.\n *\n *\n * Writing to a file that doesn't exist creates the file.\n *\n * Writing to a file that already exists overwrites the file.\n *\n * Writing to a file at path that doesn't exist creates the necessary directories.\n *\n * @param path path to file.\n * @param data data to write to the file. Data can be a string, `ArrayBuffer`, `Blob`, or `ReadableStream`.\n * @param opts connection options.\n *\n * @returns information about the written file\n */\n async write(\n path: string,\n data: string | ArrayBuffer | Blob | ReadableStream,\n opts?: FilesystemWriteOpts\n ): Promise<WriteInfo>\n async write(\n files: WriteEntry[],\n opts?: FilesystemWriteOpts\n ): Promise<WriteInfo[]>\n async write(\n pathOrFiles: string | WriteEntry[],\n dataOrOpts?:\n | string\n | ArrayBuffer\n | Blob\n | ReadableStream\n | FilesystemWriteOpts,\n opts?: FilesystemWriteOpts\n ): Promise<WriteInfo | WriteInfo[]> {\n if (typeof pathOrFiles !== 'string' && !Array.isArray(pathOrFiles)) {\n throw new Error('Path or files are required')\n }\n\n if (typeof pathOrFiles === 'string' && Array.isArray(dataOrOpts)) {\n throw new Error(\n 'Cannot specify both path and array of files. You have to specify either path and data for a single file or an array for multiple files.'\n )\n }\n\n const { path, writeOpts, writeFiles } =\n typeof pathOrFiles === 'string'\n ? {\n path: pathOrFiles,\n writeOpts: opts as FilesystemWriteOpts,\n writeFiles: [\n {\n data: dataOrOpts as\n | string\n | ArrayBuffer\n | Blob\n | ReadableStream,\n },\n ],\n }\n : {\n path: undefined,\n writeOpts: dataOrOpts as FilesystemWriteOpts,\n writeFiles: pathOrFiles as WriteEntry[],\n }\n\n if (writeFiles.length === 0) return [] as WriteInfo[]\n\n let user = writeOpts?.user\n if (\n user == undefined &&\n compareVersions(this.envdApi.version, ENVD_DEFAULT_USER) < 0\n ) {\n user = defaultUsername\n }\n\n const useOctetStream =\n compareVersions(this.envdApi.version, ENVD_OCTET_STREAM_UPLOAD) >= 0\n\n const results: WriteInfo[] = []\n\n const useGzip = writeOpts?.gzip === true\n\n if (useOctetStream) {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/octet-stream',\n }\n if (useGzip) {\n headers['Content-Encoding'] = 'gzip'\n }\n\n const uploadResults = await Promise.all(\n writeFiles.map(async (file) => {\n const filePath = path ?? (file as WriteEntry).path\n const body = await toUploadBody(file.data, useGzip)\n\n const res = await this.envdApi.api.POST('/files', {\n params: {\n query: {\n path: filePath,\n username: user,\n },\n },\n bodySerializer: () => body,\n headers,\n signal: this.connectionConfig.getSignal(\n writeOpts?.requestTimeoutMs\n ),\n body: {},\n })\n\n const err = await handleFilesystemEnvdApiError(res)\n if (err) {\n throw err\n }\n\n const files = res.data as WriteInfo[]\n if (!files || files.length === 0) {\n throw new Error(\n 'Expected to receive information about written file'\n )\n }\n\n return files\n })\n )\n\n for (const files of uploadResults) {\n results.push(...files)\n }\n } else {\n const formData = new FormData()\n for (const file of writeFiles) {\n formData.append(\n 'file',\n await toBlob(file.data),\n (file as WriteEntry).path ?? path!\n )\n }\n\n const res = await this.envdApi.api.POST('/files', {\n params: {\n query: {\n path,\n username: user,\n },\n },\n bodySerializer: () => formData,\n signal: this.connectionConfig.getSignal(writeOpts?.requestTimeoutMs),\n body: {},\n })\n\n const err = await handleFilesystemEnvdApiError(res)\n if (err) {\n throw err\n }\n\n const files = res.data as WriteInfo[]\n if (!files || files.length === 0) {\n throw new Error('Expected to receive information about written file')\n }\n\n results.push(...files)\n }\n\n return results.length === 1 && path ? results[0] : results\n }\n\n /**\n * Write multiple files.\n *\n *\n * Writing to a file that doesn't exist creates the file.\n *\n * Writing to a file that already exists overwrites the file.\n *\n * Writing to a file at path that doesn't exist creates the necessary directories.\n *\n * @param files list of files to write as `WriteEntry` objects, each containing `path` and `data`.\n * @param opts connection options.\n *\n * @returns information about the written files\n */\n async writeFiles(\n files: WriteEntry[],\n opts?: FilesystemWriteOpts\n ): Promise<WriteInfo[]> {\n return this.write(files, opts) as Promise<WriteInfo[]>\n }\n\n /**\n * List entries in a directory.\n *\n * @param path path to the directory.\n * @param opts connection options.\n *\n * @returns list of entries in the sandbox filesystem directory.\n */\n async list(path: string, opts?: FilesystemListOpts): Promise<EntryInfo[]> {\n if (typeof opts?.depth === 'number' && opts.depth < 1) {\n throw new InvalidArgumentError('depth should be at least one')\n }\n\n try {\n const res = await this.rpc.listDir(\n {\n path,\n depth: opts?.depth ?? 1,\n },\n {\n headers: authenticationHeader(this.envdApi.version, opts?.user),\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n const entries: EntryInfo[] = []\n\n for (const e of res.entries) {\n const type = mapFileType(e.type)\n\n if (type) {\n entries.push({\n name: e.name,\n type,\n path: e.path,\n size: Number(e.size),\n mode: e.mode,\n permissions: e.permissions,\n owner: e.owner,\n group: e.group,\n modifiedTime: mapModifiedTime(e.modifiedTime),\n symlinkTarget: e.symlinkTarget,\n })\n }\n }\n\n return entries\n } catch (err) {\n throw handleFilesystemRpcError(err)\n }\n }\n\n /**\n * Create a new directory and all directories along the way if needed on the specified path.\n *\n * @param path path to a new directory. For example '/dirA/dirB' when creating 'dirB'.\n * @param opts connection options.\n *\n * @returns `true` if the directory was created, `false` if it already exists.\n */\n async makeDir(path: string, opts?: FilesystemRequestOpts): Promise<boolean> {\n try {\n await this.rpc.makeDir(\n { path },\n {\n headers: authenticationHeader(this.envdApi.version, opts?.user),\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n return true\n } catch (err) {\n if (err instanceof ConnectError) {\n if (err.code === Code.AlreadyExists) {\n return false\n }\n }\n\n throw handleFilesystemRpcError(err)\n }\n }\n\n /**\n * Rename a file or directory.\n *\n * @param oldPath path to the file or directory to rename.\n * @param newPath new path for the file or directory.\n * @param opts connection options.\n *\n * @returns information about renamed file or directory.\n */\n async rename(\n oldPath: string,\n newPath: string,\n opts?: FilesystemRequestOpts\n ): Promise<EntryInfo> {\n try {\n const res = await this.rpc.move(\n {\n source: oldPath,\n destination: newPath,\n },\n {\n headers: authenticationHeader(this.envdApi.version, opts?.user),\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n const entry = res.entry\n if (!entry) {\n throw new Error('Expected to receive information about moved object')\n }\n\n return {\n name: entry.name,\n type: mapFileType(entry.type),\n path: entry.path,\n size: Number(entry.size),\n mode: entry.mode,\n permissions: entry.permissions,\n owner: entry.owner,\n group: entry.group,\n modifiedTime: mapModifiedTime(entry.modifiedTime),\n symlinkTarget: entry.symlinkTarget,\n }\n } catch (err) {\n throw handleFilesystemRpcError(err)\n }\n }\n\n /**\n * Remove a file or directory.\n *\n * @param path path to a file or directory.\n * @param opts connection options.\n */\n async remove(path: string, opts?: FilesystemRequestOpts): Promise<void> {\n try {\n await this.rpc.remove(\n { path },\n {\n headers: authenticationHeader(this.envdApi.version, opts?.user),\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n } catch (err) {\n throw handleFilesystemRpcError(err)\n }\n }\n\n /**\n * Check if a file or a directory exists.\n *\n * @param path path to a file or a directory\n * @param opts connection options.\n *\n * @returns `true` if the file or directory exists, `false` otherwise\n */\n async exists(path: string, opts?: FilesystemRequestOpts): Promise<boolean> {\n try {\n await this.rpc.stat(\n { path },\n {\n headers: authenticationHeader(this.envdApi.version, opts?.user),\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n return true\n } catch (err) {\n if (err instanceof ConnectError) {\n if (err.code === Code.NotFound) {\n return false\n }\n }\n\n throw handleFilesystemRpcError(err)\n }\n }\n\n /**\n * Get information about a file or directory.\n *\n * @param path path to a file or directory.\n * @param opts connection options.\n *\n * @returns information about the file or directory like name, type, and path.\n */\n async getInfo(\n path: string,\n opts?: FilesystemRequestOpts\n ): Promise<EntryInfo> {\n try {\n const res = await this.rpc.stat(\n { path },\n {\n headers: authenticationHeader(this.envdApi.version, opts?.user),\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n if (!res.entry) {\n throw new Error(\n 'Expected to receive information about the file or directory'\n )\n }\n\n return {\n name: res.entry.name,\n type: mapFileType(res.entry.type),\n path: res.entry.path,\n size: Number(res.entry.size),\n mode: res.entry.mode,\n permissions: res.entry.permissions,\n owner: res.entry.owner,\n group: res.entry.group,\n modifiedTime: mapModifiedTime(res.entry.modifiedTime),\n symlinkTarget: res.entry.symlinkTarget,\n }\n } catch (err) {\n throw handleFilesystemRpcError(err)\n }\n }\n\n /**\n * Start watching a directory for filesystem events.\n *\n * @param path path to directory to watch.\n * @param onEvent callback to call when an event in the directory occurs.\n * @param opts connection options.\n *\n * @returns `WatchHandle` object for stopping watching directory.\n */\n async watchDir(\n path: string,\n onEvent: (event: FilesystemEvent) => void | Promise<void>,\n opts?: WatchOpts & {\n onExit?: (err?: Error) => void | Promise<void>\n }\n ): Promise<WatchHandle> {\n if (\n opts?.recursive &&\n this.envdApi.version &&\n compareVersions(this.envdApi.version, ENVD_VERSION_RECURSIVE_WATCH) < 0\n ) {\n throw new TemplateError(\n 'You need to update the template to use recursive watching. ' +\n 'You can do this by running `ppio template build` in the directory with the template.'\n )\n }\n\n const requestTimeoutMs =\n opts?.requestTimeoutMs ?? this.connectionConfig.requestTimeoutMs\n\n const controller = new AbortController()\n\n const reqTimeout = requestTimeoutMs\n ? setTimeout(() => {\n controller.abort()\n }, requestTimeoutMs)\n : undefined\n\n const events = this.rpc.watchDir(\n {\n path,\n recursive: opts?.recursive ?? this.defaultWatchRecursive,\n },\n {\n headers: {\n ...authenticationHeader(this.envdApi.version, opts?.user),\n [KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString(),\n },\n signal: controller.signal,\n timeoutMs: opts?.timeoutMs ?? this.defaultWatchTimeout,\n }\n )\n\n try {\n await handleWatchDirStartEvent(events)\n\n clearTimeout(reqTimeout)\n\n return new WatchHandle(\n () => controller.abort(),\n events,\n onEvent,\n opts?.onExit\n )\n } catch (err) {\n throw handleFilesystemRpcError(err)\n }\n }\n}\n","import { InvalidArgumentError } from '../../errors'\nimport { CommandExitError } from '../commands/commandHandle'\n\n/**\n * Parsed git status entry for a file.\n */\nexport interface GitFileStatus {\n /**\n * Path relative to the repository root.\n */\n name: string\n /**\n * Normalized status string (for example, `\"modified\"` or `\"added\"`).\n */\n status: GitStatusLabel\n /**\n * Index status character from porcelain output.\n */\n indexStatus: string\n /**\n * Working tree status character from porcelain output.\n */\n workingTreeStatus: string\n /**\n * Whether the change is staged.\n */\n staged: boolean\n /**\n * Original path when the file was renamed.\n */\n renamedFrom?: string\n}\n\n/**\n * Supported normalized git status labels.\n */\nexport type GitStatusLabel =\n | 'conflict'\n | 'renamed'\n | 'copied'\n | 'deleted'\n | 'added'\n | 'modified'\n | 'typechange'\n | 'untracked'\n | 'unknown'\n\n/**\n * Scope for git config operations.\n */\nexport type GitConfigScope = 'global' | 'local' | 'system'\n\n/**\n * Parsed git repository status.\n */\nexport interface GitStatus {\n /**\n * Current branch name, if available.\n */\n currentBranch?: string\n /**\n * Upstream branch name, if available.\n */\n upstream?: string\n /**\n * Number of commits the branch is ahead of upstream.\n */\n ahead: number\n /**\n * Number of commits the branch is behind upstream.\n */\n behind: number\n /**\n * Whether HEAD is detached.\n */\n detached: boolean\n /**\n * List of file status entries.\n */\n fileStatus: GitFileStatus[]\n /**\n * Whether the repository has no tracked or untracked file changes.\n */\n isClean: boolean\n /**\n * Whether the repository has any tracked or untracked file changes.\n */\n hasChanges: boolean\n /**\n * Whether there are staged changes.\n */\n hasStaged: boolean\n /**\n * Whether there are untracked files.\n */\n hasUntracked: boolean\n /**\n * Whether there are merge conflicts.\n */\n hasConflicts: boolean\n /**\n * Total number of changed files.\n */\n totalCount: number\n /**\n * Number of files with staged changes.\n */\n stagedCount: number\n /**\n * Number of files with unstaged changes.\n */\n unstagedCount: number\n /**\n * Number of untracked files.\n */\n untrackedCount: number\n /**\n * Number of files with merge conflicts.\n */\n conflictCount: number\n}\n\n/**\n * Parsed git branch list.\n */\nexport interface GitBranches {\n /**\n * List of branch names.\n */\n branches: string[]\n /**\n * Current branch name, if available.\n */\n currentBranch?: string\n}\n\n/**\n * Escape a string for safe use in a shell command.\n *\n * This uses single-quoted shell escaping and safely handles embedded single quotes.\n */\nexport function shellEscape(value: string): string {\n return `'${value.replace(/'/g, \"'\\\"'\\\"'\")}'`\n}\n\n/**\n * Add HTTP(S) credentials to a Git URL.\n *\n * @param url Git repository URL.\n * @param username Username for HTTP(S) authentication.\n * @param password Password or token for HTTP(S) authentication.\n * @returns URL with embedded credentials.\n */\nexport function withCredentials(\n url: string,\n username?: string,\n password?: string\n): string {\n if (!username && !password) {\n return url\n }\n\n if (!username || !password) {\n throw new InvalidArgumentError(\n 'Both username and password are required when using Git credentials.'\n )\n }\n\n let parsed: URL\n try {\n parsed = new URL(url)\n } catch {\n throw new InvalidArgumentError(`Invalid Git URL: ${url}`)\n }\n\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw new InvalidArgumentError(\n 'Only http(s) Git URLs support username/password credentials.'\n )\n }\n\n parsed.username = username\n parsed.password = password\n\n return parsed.toString()\n}\n\n/**\n * Strip HTTP(S) credentials from a Git URL.\n *\n * @param url Git repository URL.\n * @returns URL without embedded credentials.\n */\nexport function stripCredentials(url: string): string {\n let parsed: URL\n try {\n parsed = new URL(url)\n } catch {\n return url\n }\n\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n return url\n }\n\n if (!parsed.username && !parsed.password) {\n return url\n }\n\n parsed.username = ''\n parsed.password = ''\n return parsed.toString()\n}\n\n/**\n * Derive the default repository directory name from a Git URL.\n *\n * @param url Git repository URL.\n * @returns Repository directory name, if it can be determined.\n */\nexport function deriveRepoDirFromUrl(url: string): string | undefined {\n let parsed: URL\n try {\n parsed = new URL(url)\n } catch {\n return undefined\n }\n\n const trimmedPath = parsed.pathname.replace(/\\/+$/, '')\n const lastSegment = trimmedPath.split('/').pop()\n if (!lastSegment) {\n return undefined\n }\n\n return lastSegment.endsWith('.git') ? lastSegment.slice(0, -4) : lastSegment\n}\n\n/**\n * Build a shell-safe git command string.\n *\n * @param args Git command arguments.\n * @param repoPath Repository path for `git -C`, if provided.\n * @returns Shell-safe git command.\n */\nexport function buildGitCommand(args: string[], repoPath?: string): string {\n const parts = ['git']\n if (repoPath) {\n parts.push('-C', repoPath)\n }\n parts.push(...args)\n\n return parts.map((part) => shellEscape(part)).join(' ')\n}\n\ntype GitPushArgsOptions = {\n remote?: string\n branch?: string\n setUpstream: boolean\n}\n\nexport function buildPushArgs(\n remoteName: string | undefined,\n opts: GitPushArgsOptions\n): string[] {\n const { remote, branch, setUpstream } = opts\n const args = ['push']\n const targetRemote = remoteName ?? remote\n if (setUpstream && targetRemote) {\n args.push('--set-upstream')\n }\n if (targetRemote) {\n args.push(targetRemote)\n }\n if (branch) {\n args.push(branch)\n }\n return args\n}\n\nfunction parseAheadBehind(segment?: string): { ahead: number; behind: number } {\n if (!segment) {\n return { ahead: 0, behind: 0 }\n }\n\n let ahead = 0\n let behind = 0\n\n if (segment.includes('ahead')) {\n try {\n ahead = Number.parseInt(\n segment.split('ahead')[1].split(',')[0].trim(),\n 10\n )\n } catch {\n ahead = 0\n }\n }\n\n if (segment.includes('behind')) {\n try {\n behind = Number.parseInt(\n segment.split('behind')[1].split(',')[0].trim(),\n 10\n )\n } catch {\n behind = 0\n }\n }\n\n return { ahead, behind }\n}\n\nfunction normalizeBranchName(name: string): string {\n if (name.startsWith('HEAD (detached at ')) {\n return name.replace('HEAD (detached at ', '').replace(/\\)$/, '')\n }\n\n return name\n .replace('HEAD (no branch)', 'HEAD')\n .replace('No commits yet on ', '')\n .replace('Initial commit on ', '')\n}\n\nfunction deriveStatus(\n indexStatus: string,\n workingStatus: string\n): GitStatusLabel {\n const statuses = new Set([indexStatus, workingStatus])\n\n if (statuses.has('U')) return 'conflict'\n if (statuses.has('R')) return 'renamed'\n if (statuses.has('C')) return 'copied'\n if (statuses.has('D')) return 'deleted'\n if (statuses.has('A')) return 'added'\n if (statuses.has('M')) return 'modified'\n if (statuses.has('T')) return 'typechange'\n if (statuses.has('?')) return 'untracked'\n\n return 'unknown'\n}\n\n/**\n * Parse `git status --porcelain=1 -b` output into a structured object.\n *\n * @param output Git status output.\n * @returns Parsed {@link GitStatus}.\n */\nexport function parseGitStatus(output: string): GitStatus {\n const lines = output\n .split('\\n')\n .map((line) => line.replace(/\\r$/, ''))\n .filter((line) => line.trim().length > 0)\n\n let currentBranch: string | undefined\n let upstream: string | undefined\n let ahead = 0\n let behind = 0\n let detached = false\n const fileStatus: GitFileStatus[] = []\n\n if (lines.length === 0) {\n return {\n currentBranch,\n upstream,\n ahead,\n behind,\n detached,\n fileStatus,\n isClean: true,\n hasChanges: false,\n hasStaged: false,\n hasUntracked: false,\n hasConflicts: false,\n totalCount: 0,\n stagedCount: 0,\n unstagedCount: 0,\n untrackedCount: 0,\n conflictCount: 0,\n }\n }\n\n const branchLine = lines[0]\n if (branchLine.startsWith('## ')) {\n const branchInfo = branchLine.slice(3)\n const aheadStart = branchInfo.indexOf(' [')\n const branchPart =\n aheadStart === -1 ? branchInfo : branchInfo.slice(0, aheadStart)\n const aheadPart =\n aheadStart === -1 ? undefined : branchInfo.slice(aheadStart + 2, -1)\n const normalizedBranch = normalizeBranchName(branchPart)\n const rawBranch = branchPart\n const isDetached =\n rawBranch.startsWith('HEAD (detached at ') ||\n rawBranch.includes('detached')\n\n if (isDetached || normalizedBranch.startsWith('HEAD')) {\n detached = true\n } else if (normalizedBranch.includes('...')) {\n const [branch, upstreamBranch] = normalizedBranch.split('...')\n currentBranch = branch || undefined\n upstream = upstreamBranch || undefined\n } else {\n currentBranch = normalizedBranch || undefined\n }\n\n const aheadBehind = parseAheadBehind(aheadPart)\n ahead = aheadBehind.ahead\n behind = aheadBehind.behind\n }\n\n for (const line of lines.slice(1)) {\n if (line.startsWith('?? ')) {\n const name = line.slice(3)\n fileStatus.push({\n name,\n status: 'untracked',\n indexStatus: '?',\n workingTreeStatus: '?',\n staged: false,\n })\n continue\n }\n\n if (line.length < 3) {\n continue\n }\n\n const indexStatus = line[0]\n const workingTreeStatus = line[1]\n const path = line.slice(3)\n\n let renamedFrom: string | undefined\n let name = path\n\n if (path.includes(' -> ')) {\n const parts = path.split(' -> ')\n renamedFrom = parts[0]\n name = parts.slice(1).join(' -> ')\n }\n\n fileStatus.push({\n name,\n status: deriveStatus(indexStatus, workingTreeStatus),\n indexStatus,\n workingTreeStatus,\n staged: indexStatus !== ' ' && indexStatus !== '?',\n ...(renamedFrom ? { renamedFrom } : {}),\n })\n }\n\n const totalCount = fileStatus.length\n const stagedCount = fileStatus.filter((item) => item.staged).length\n const untrackedCount = fileStatus.filter(\n (item) => item.status === 'untracked'\n ).length\n const conflictCount = fileStatus.filter(\n (item) => item.status === 'conflict'\n ).length\n const unstagedCount = totalCount - stagedCount\n\n return {\n currentBranch,\n upstream,\n ahead,\n behind,\n detached,\n fileStatus,\n isClean: totalCount === 0,\n hasChanges: totalCount > 0,\n hasStaged: stagedCount > 0,\n hasUntracked: untrackedCount > 0,\n hasConflicts: conflictCount > 0,\n totalCount,\n stagedCount,\n unstagedCount,\n untrackedCount,\n conflictCount,\n }\n}\n\n/**\n * Parse `git branch --format=%(refname:short)\\t%(HEAD)` output.\n *\n * @param output Git branch output.\n * @returns Parsed {@link GitBranches}.\n */\nexport function parseGitBranches(output: string): GitBranches {\n const branches: string[] = []\n let currentBranch: string | undefined\n\n const lines = output\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n\n for (const line of lines) {\n const parts = line.split('\\t')\n const name = parts[0]\n branches.push(name)\n if (parts.length > 1 && parts[1] === '*') {\n currentBranch = name\n }\n }\n\n return { branches, currentBranch }\n}\n\nexport function isAuthFailure(err: unknown): boolean {\n if (!(err instanceof CommandExitError)) {\n return false\n }\n\n const message = `${err.stderr}\\n${err.stdout}`.toLowerCase()\n const authSnippets = [\n 'authentication failed',\n 'terminal prompts disabled',\n 'could not read username',\n 'invalid username or password',\n 'access denied',\n 'permission denied',\n 'not authorized',\n ]\n\n return authSnippets.some((snippet) => message.includes(snippet))\n}\n\nexport function getScopeFlag(scope: GitConfigScope): `--${GitConfigScope}` {\n if (scope !== 'global' && scope !== 'local' && scope !== 'system') {\n throw new InvalidArgumentError(\n 'Git config scope must be one of: global, local, system.'\n )\n }\n return `--${scope}`\n}\n\nexport function isMissingUpstream(err: unknown): boolean {\n if (!(err instanceof CommandExitError)) {\n return false\n }\n\n const message = `${err.stderr}\\n${err.stdout}`.toLowerCase()\n const upstreamSnippets = [\n 'has no upstream branch',\n 'no upstream branch',\n 'no upstream configured',\n 'no tracking information for the current branch',\n 'no tracking information',\n 'set the remote as upstream',\n 'set the upstream branch',\n 'please specify which branch you want to merge with',\n ]\n\n return upstreamSnippets.some((snippet) => message.includes(snippet))\n}\n\nexport function buildAuthErrorMessage(\n action: 'clone' | 'push' | 'pull',\n missingPassword: boolean\n): string {\n if (missingPassword) {\n return `Git ${action} requires a password/token for private repositories.`\n }\n return `Git ${action} requires credentials for private repositories.`\n}\n\nexport function buildUpstreamErrorMessage(action: 'push' | 'pull'): string {\n if (action === 'push') {\n return (\n 'Git push failed because no upstream branch is configured. ' +\n 'Set upstream once with { setUpstream: true } (and optional remote/branch), ' +\n 'or pass remote and branch explicitly.'\n )\n }\n\n return (\n 'Git pull failed because no upstream branch is configured. ' +\n 'Pass remote and branch explicitly, or set upstream once (push with { setUpstream: true } ' +\n 'or run: git branch --set-upstream-to=origin/<branch> <branch>).'\n )\n}\n\nexport function getRepoPathForScope(\n scope: GitConfigScope,\n path?: string\n): string | undefined {\n if (scope !== 'local') {\n return undefined\n }\n if (!path) {\n throw new InvalidArgumentError(\n 'A repository path is required when using scope \"local\".'\n )\n }\n return path\n}\n","import {\n GitAuthError,\n GitUpstreamError,\n InvalidArgumentError,\n} from '../../errors'\nimport type { CommandStartOpts } from '../commands'\nimport type { CommandResult } from '../commands/commandHandle'\nimport { Commands } from '../commands'\nimport {\n buildAuthErrorMessage,\n buildGitCommand,\n buildPushArgs,\n buildUpstreamErrorMessage,\n GitBranches,\n GitConfigScope,\n GitStatus,\n getRepoPathForScope,\n getScopeFlag,\n isAuthFailure,\n isMissingUpstream,\n parseGitBranches,\n parseGitStatus,\n shellEscape,\n stripCredentials,\n deriveRepoDirFromUrl,\n withCredentials,\n} from './utils'\n\nconst DEFAULT_GIT_ENV: Record<string, string> = {\n GIT_TERMINAL_PROMPT: '0',\n}\n\n/**\n * Options for git operations in the sandbox.\n */\nexport interface GitRequestOpts\n extends Partial<\n Pick<\n CommandStartOpts,\n 'envs' | 'user' | 'cwd' | 'timeoutMs' | 'requestTimeoutMs'\n >\n > {}\n\n/**\n * Options for cloning a repository.\n */\nexport interface GitCloneOpts extends GitRequestOpts {\n /**\n * Destination path for the clone.\n */\n path?: string\n /**\n * Branch to check out.\n */\n branch?: string\n /**\n * If set, perform a shallow clone with this depth.\n */\n depth?: number\n /**\n * Username for HTTP(S) authentication.\n */\n username?: string\n /**\n * Password or token for HTTP(S) authentication.\n */\n password?: string\n /**\n * Store credentials in the cloned repository when `true`.\n *\n * @default false\n */\n dangerouslyStoreCredentials?: boolean\n}\n\n/**\n * Options for initializing a repository.\n */\nexport interface GitInitOpts extends GitRequestOpts {\n /**\n * Create a bare repository when `true`.\n */\n bare?: boolean\n /**\n * Initial branch name (for example, `\"main\"`).\n */\n initialBranch?: string\n}\n\n/**\n * Options for adding a git remote.\n */\nexport interface GitRemoteAddOpts extends GitRequestOpts {\n /**\n * Fetch the remote after adding it when `true`.\n */\n fetch?: boolean\n /**\n * Overwrite the remote URL if the remote already exists when `true`.\n */\n overwrite?: boolean\n}\n\n/**\n * Options for creating a commit.\n */\nexport interface GitCommitOpts extends GitRequestOpts {\n /**\n * Commit author name.\n */\n authorName?: string\n /**\n * Commit author email.\n */\n authorEmail?: string\n /**\n * Allow empty commits when `true`.\n */\n allowEmpty?: boolean\n}\n\n/**\n * Options for staging files.\n */\nexport interface GitAddOpts extends GitRequestOpts {\n /**\n * Files to add; when omitted, adds the current directory.\n */\n files?: string[]\n /**\n * When `true` and `files` is omitted, stage all changes.\n */\n all?: boolean\n}\n\n/**\n * Supported reset modes.\n */\nexport type GitResetMode = 'soft' | 'mixed' | 'hard' | 'merge' | 'keep'\n\n/**\n * Options for resetting a repository.\n */\nexport interface GitResetOpts extends GitRequestOpts {\n /**\n * Reset mode to use.\n */\n mode?: GitResetMode\n /**\n * Commit, branch, or ref to reset to (defaults to HEAD).\n */\n target?: string\n /**\n * Paths to reset.\n */\n paths?: string[]\n}\n\n/**\n * Options for restoring files or unstaging changes.\n */\nexport interface GitRestoreOpts extends GitRequestOpts {\n /**\n * Paths to restore (use `['.']` for all).\n */\n paths: string[]\n /**\n * Restore the index (unstage).\n */\n staged?: boolean\n /**\n * Restore working tree files.\n */\n worktree?: boolean\n /**\n * Restore from the given source (commit, branch, or ref).\n */\n source?: string\n}\n/**\n * Options for deleting a branch.\n */\nexport interface GitDeleteBranchOpts extends GitRequestOpts {\n /**\n * Force deletion with `-D` when `true`.\n */\n force?: boolean\n}\n\n/**\n * Options for pushing commits.\n */\nexport interface GitPushOpts extends GitRequestOpts {\n /**\n * Remote name (for example, `\"origin\"`).\n */\n remote?: string\n /**\n * Branch name to push.\n */\n branch?: string\n /**\n * Set upstream tracking when `true`.\n */\n setUpstream?: boolean\n /**\n * Username for HTTP(S) authentication.\n */\n username?: string\n /**\n * Password or token for HTTP(S) authentication.\n */\n password?: string\n}\n\n/**\n * Options for pulling commits.\n */\nexport interface GitPullOpts extends GitRequestOpts {\n /**\n * Remote name (for example, `\"origin\"`).\n */\n remote?: string\n /**\n * Branch name to pull.\n */\n branch?: string\n /**\n * Username for HTTP(S) authentication.\n */\n username?: string\n /**\n * Password or token for HTTP(S) authentication.\n */\n password?: string\n}\n\n/**\n * Supported scopes for git config operations.\n */\n/**\n * Options for git config operations.\n */\nexport interface GitConfigOpts extends GitRequestOpts {\n /**\n * Scope for the git config command.\n *\n * @default \"global\"\n */\n scope?: GitConfigScope\n /**\n * Repository path required when `scope` is `\"local\"`.\n */\n path?: string\n}\n\n/**\n * Options for dangerously authenticating git globally via the credential helper.\n */\nexport interface GitDangerouslyAuthenticateOpts extends GitRequestOpts {\n /**\n * Username for HTTP(S) authentication.\n */\n username: string\n /**\n * Password or token for HTTP(S) authentication.\n */\n password: string\n /**\n * Host to authenticate for.\n *\n * @default \"github.com\"\n */\n host?: string\n /**\n * Protocol to authenticate for.\n *\n * @default \"https\"\n */\n protocol?: string\n}\n\n/**\n * Module for running git operations in the sandbox.\n */\nexport class Git {\n constructor(private readonly commands: Commands) {}\n\n /**\n * Clone a git repository into the sandbox.\n *\n * @param url Git repository URL.\n * @param opts Clone options.\n * @returns Command result from the command runner.\n */\n async clone(url: string, opts?: GitCloneOpts): Promise<CommandResult> {\n const {\n username,\n password,\n branch,\n depth,\n path,\n dangerouslyStoreCredentials,\n ...rest\n } = opts ?? {}\n\n if (password && !username) {\n throw new InvalidArgumentError(\n 'Username is required when using a password or token for git clone.'\n )\n }\n\n const attemptClone = async (\n authUsername?: string,\n authPassword?: string\n ): Promise<CommandResult> => {\n const urlWithCreds =\n authUsername && authPassword\n ? withCredentials(url, authUsername, authPassword)\n : url\n\n const sanitizedUrl = stripCredentials(urlWithCreds)\n const stripInlineCreds =\n !dangerouslyStoreCredentials && sanitizedUrl !== urlWithCreds\n\n const repoPath = stripInlineCreds\n ? (path ?? deriveRepoDirFromUrl(url))\n : path\n\n if (stripInlineCreds && !repoPath) {\n throw new InvalidArgumentError(\n 'A destination path is required when using credentials without storing them.'\n )\n }\n\n const args = ['clone', urlWithCreds]\n\n if (branch) args.push('--branch', branch, '--single-branch')\n if (depth) args.push('--depth', depth.toString())\n if (repoPath) args.push(repoPath)\n\n const result = await this.runGit(args, undefined, rest)\n\n if (stripInlineCreds) {\n await this.runGit(\n ['remote', 'set-url', 'origin', sanitizedUrl],\n repoPath,\n rest\n )\n }\n\n return result\n }\n\n try {\n return await attemptClone(username, password)\n } catch (err) {\n if (isAuthFailure(err)) {\n throw new GitAuthError(\n buildAuthErrorMessage('clone', Boolean(username) && !password)\n )\n }\n throw err\n }\n }\n\n /**\n * Initialize a new git repository.\n *\n * @param path Destination path for the repository.\n * @param opts Init options.\n * @returns Command result from the command runner.\n */\n async init(path: string, opts?: GitInitOpts): Promise<CommandResult> {\n const { bare, initialBranch, ...rest } = opts ?? {}\n const args = ['init']\n\n if (initialBranch) {\n args.push('--initial-branch', initialBranch)\n }\n if (bare) {\n args.push('--bare')\n }\n\n args.push(path)\n return this.runGit(args, undefined, rest)\n }\n\n /**\n * Add (or update) a remote for a repository.\n *\n * @param path Repository path.\n * @param name Remote name (for example, `\"origin\"`).\n * @param url Remote URL.\n * @param opts Remote add options.\n * @returns Command result from the command runner.\n */\n async remoteAdd(\n path: string,\n name: string,\n url: string,\n opts?: GitRemoteAddOpts\n ): Promise<CommandResult> {\n if (!name || !url) {\n throw new InvalidArgumentError(\n 'Both remote name and URL are required to add a git remote.'\n )\n }\n\n const { fetch, overwrite, ...rest } = opts ?? {}\n const addArgs = ['remote', 'add']\n\n if (fetch) {\n addArgs.push('-f')\n }\n\n addArgs.push(name, url)\n\n if (!overwrite) {\n return this.runGit(addArgs, path, rest)\n }\n\n const addCmd = buildGitCommand(addArgs, path)\n const setUrlCmd = buildGitCommand(['remote', 'set-url', name, url], path)\n let cmd = `${addCmd} || ${setUrlCmd}`\n if (fetch) {\n const fetchCmd = buildGitCommand(['fetch', name], path)\n cmd = `(${cmd}) && ${fetchCmd}`\n }\n return this.runShell(cmd, rest)\n }\n\n /**\n * Get the URL for a git remote.\n *\n * Returns `undefined` when the remote does not exist.\n *\n * @param path Repository path.\n * @param name Remote name (for example, `\"origin\"`).\n * @param opts Command execution options.\n * @returns Remote URL if present.\n */\n async remoteGet(\n path: string,\n name: string,\n opts?: GitRequestOpts\n ): Promise<string | undefined> {\n if (!name) {\n throw new InvalidArgumentError('Remote name is required.')\n }\n\n const cmd = `${buildGitCommand(['remote', 'get-url', name], path)} || true`\n const result = await this.runShell(cmd, opts)\n const trimmed = result.stdout.trim()\n return trimmed.length > 0 ? trimmed : undefined\n }\n\n /**\n * Get repository status information.\n *\n * @param path Repository path.\n * @param opts Command execution options.\n * @returns Parsed git status.\n */\n async status(path: string, opts?: GitRequestOpts): Promise<GitStatus> {\n const result = await this.runGit(\n ['status', '--porcelain=1', '-b'],\n path,\n opts\n )\n return parseGitStatus(result.stdout)\n }\n\n /**\n * List branches in a repository.\n *\n * @param path Repository path.\n * @param opts Command execution options.\n * @returns Parsed branch list.\n */\n async branches(path: string, opts?: GitRequestOpts): Promise<GitBranches> {\n const result = await this.runGit(\n ['branch', '--format=%(refname:short)\\t%(HEAD)'],\n path,\n opts\n )\n return parseGitBranches(result.stdout)\n }\n\n /**\n * Create and check out a new branch.\n *\n * @param path Repository path.\n * @param branch Branch name to create.\n * @param opts Command execution options.\n * @returns Command result from the command runner.\n */\n async createBranch(\n path: string,\n branch: string,\n opts?: GitRequestOpts\n ): Promise<CommandResult> {\n return this.runGit(['checkout', '-b', branch], path, opts)\n }\n\n /**\n * Check out an existing branch.\n *\n * @param path Repository path.\n * @param branch Branch name to check out.\n * @param opts Command execution options.\n * @returns Command result from the command runner.\n */\n async checkoutBranch(\n path: string,\n branch: string,\n opts?: GitRequestOpts\n ): Promise<CommandResult> {\n return this.runGit(['checkout', branch], path, opts)\n }\n\n /**\n * Delete a branch.\n *\n * @param path Repository path.\n * @param branch Branch name to delete.\n * @param opts Delete options.\n * @returns Command result from the command runner.\n */\n async deleteBranch(\n path: string,\n branch: string,\n opts?: GitDeleteBranchOpts\n ): Promise<CommandResult> {\n const { force, ...rest } = opts ?? {}\n const args = ['branch', force ? '-D' : '-d', branch]\n return this.runGit(args, path, rest)\n }\n\n /**\n * Stage files for commit.\n *\n * @param path Repository path.\n * @param opts Add options.\n * @returns Command result from the command runner.\n */\n async add(path: string, opts?: GitAddOpts): Promise<CommandResult> {\n const { files, all = true, ...rest } = opts ?? {}\n const args = ['add']\n\n if (!files || files.length === 0) {\n args.push(all ? '-A' : '.')\n } else {\n args.push('--', ...files)\n }\n\n return this.runGit(args, path, rest)\n }\n\n /**\n * Create a commit in the repository.\n *\n * @param path Repository path.\n * @param message Commit message.\n * @param opts Commit options.\n * @returns Command result from the command runner.\n */\n async commit(\n path: string,\n message: string,\n opts?: GitCommitOpts\n ): Promise<CommandResult> {\n const { authorName, authorEmail, allowEmpty, ...rest } = opts ?? {}\n const args = ['commit', '-m', message]\n\n if (allowEmpty) {\n args.push('--allow-empty')\n }\n\n const authorArgs: string[] = []\n if (authorName) {\n authorArgs.push('-c', `user.name=${authorName}`)\n }\n if (authorEmail) {\n authorArgs.push('-c', `user.email=${authorEmail}`)\n }\n\n return this.runGit([...authorArgs, ...args], path, rest)\n }\n\n /**\n * Reset the current HEAD to a specified state.\n *\n * @param path Repository path.\n * @param opts Reset options.\n * @returns Command result from the command runner.\n */\n async reset(path: string, opts?: GitResetOpts): Promise<CommandResult> {\n const { mode, target, paths, ...rest } = opts ?? {}\n const allowedModes: GitResetMode[] = [\n 'soft',\n 'mixed',\n 'hard',\n 'merge',\n 'keep',\n ]\n\n if (mode && !allowedModes.includes(mode)) {\n throw new InvalidArgumentError(\n `Reset mode must be one of ${allowedModes.join(', ')}.`\n )\n }\n\n const args = ['reset']\n if (mode) {\n args.push(`--${mode}`)\n }\n if (target) {\n args.push(target)\n }\n if (paths && paths.length > 0) {\n args.push('--', ...paths)\n }\n\n return this.runGit(args, path, rest)\n }\n\n /**\n * Restore working tree files or unstage changes.\n *\n * @param path Repository path.\n * @param opts Restore options.\n * @returns Command result from the command runner.\n */\n async restore(path: string, opts: GitRestoreOpts): Promise<CommandResult> {\n const { paths, staged, worktree, source, ...rest } = opts\n\n if (!paths || paths.length === 0) {\n throw new InvalidArgumentError('At least one path is required.')\n }\n\n let resolvedStaged = staged\n let resolvedWorktree = worktree\n\n if (staged === undefined && worktree === undefined) {\n resolvedWorktree = true\n } else if (staged === true && worktree === undefined) {\n resolvedWorktree = false\n } else if (staged === undefined && worktree !== undefined) {\n resolvedStaged = false\n }\n\n if (resolvedStaged === false && resolvedWorktree === false) {\n throw new InvalidArgumentError(\n 'At least one of staged or worktree must be true.'\n )\n }\n\n const args = ['restore']\n if (resolvedWorktree) {\n args.push('--worktree')\n }\n if (resolvedStaged) {\n args.push('--staged')\n }\n if (source) {\n args.push('--source', source)\n }\n args.push('--', ...paths)\n\n return this.runGit(args, path, rest)\n }\n\n /**\n * Push commits to a remote.\n *\n * @param path Repository path.\n * @param opts Push options.\n * @returns Command result from the command runner.\n */\n async push(path: string, opts?: GitPushOpts): Promise<CommandResult> {\n const {\n remote,\n branch,\n setUpstream = true,\n username,\n password,\n ...rest\n } = opts ?? {}\n\n if (password && !username) {\n throw new InvalidArgumentError(\n 'Username is required when using a password or token for git push.'\n )\n }\n\n if (username && password) {\n const remoteName = await this.resolveRemoteName(path, remote, rest)\n return this.withRemoteCredentials(\n path,\n remoteName,\n username,\n password,\n rest,\n () =>\n this.runGit(\n buildPushArgs(remoteName, { remote, branch, setUpstream }),\n path,\n rest\n )\n )\n }\n\n try {\n return await this.runGit(\n buildPushArgs(undefined, { remote, branch, setUpstream }),\n path,\n rest\n )\n } catch (err) {\n if (isAuthFailure(err)) {\n throw new GitAuthError(\n buildAuthErrorMessage('push', Boolean(username) && !password)\n )\n }\n if (isMissingUpstream(err)) {\n throw new GitUpstreamError(buildUpstreamErrorMessage('push'))\n }\n throw err\n }\n }\n\n /**\n * Pull changes from a remote.\n *\n * @param path Repository path.\n * @param opts Pull options.\n * @returns Command result from the command runner.\n */\n async pull(path: string, opts?: GitPullOpts): Promise<CommandResult> {\n const { remote, branch, username, password, ...rest } = opts ?? {}\n if (password && !username) {\n throw new InvalidArgumentError(\n 'Username is required when using a password or token for git pull.'\n )\n }\n\n if (!remote && !branch) {\n const hasUpstream = await this.hasUpstream(path, rest)\n if (!hasUpstream) {\n throw new GitUpstreamError(buildUpstreamErrorMessage('pull'))\n }\n }\n\n const buildArgs = (remoteName?: string) => {\n const args = ['pull']\n const targetRemote = remoteName ?? remote\n if (targetRemote) {\n args.push(targetRemote)\n }\n if (branch) {\n args.push(branch)\n }\n return args\n }\n\n if (username && password) {\n const remoteName = await this.resolveRemoteName(path, remote, rest)\n return this.withRemoteCredentials(\n path,\n remoteName,\n username,\n password,\n rest,\n () => this.runGit(buildArgs(remoteName), path, rest)\n )\n }\n\n try {\n return await this.runGit(buildArgs(), path, rest)\n } catch (err) {\n if (isAuthFailure(err)) {\n throw new GitAuthError(\n buildAuthErrorMessage('pull', Boolean(username) && !password)\n )\n }\n if (isMissingUpstream(err)) {\n throw new GitUpstreamError(buildUpstreamErrorMessage('pull'))\n }\n throw err\n }\n }\n\n /**\n * Set a git config value.\n *\n * Use `scope: \"local\"` together with `path` to configure a specific repository.\n *\n * @param key Git config key (for example, `\"pull.rebase\"`).\n * @param value Git config value.\n * @param opts Config options.\n * @returns Command result from the command runner.\n */\n async setConfig(\n key: string,\n value: string,\n opts?: GitConfigOpts\n ): Promise<CommandResult> {\n if (!key) {\n throw new InvalidArgumentError('Git config key is required.')\n }\n\n const scope = opts?.scope ?? 'global'\n const scopeFlag = getScopeFlag(scope)\n const repoPath = getRepoPathForScope(scope, opts?.path)\n\n return this.runGit(['config', scopeFlag, key, value], repoPath, opts)\n }\n\n /**\n * Get a git config value.\n *\n * Returns `undefined` when the key is not set in the requested scope.\n *\n * @param key Git config key (for example, `\"pull.rebase\"`).\n * @param opts Config options.\n * @returns The config value if present.\n */\n async getConfig(\n key: string,\n opts?: GitConfigOpts\n ): Promise<string | undefined> {\n if (!key) {\n throw new InvalidArgumentError('Git config key is required.')\n }\n\n const scope = opts?.scope ?? 'global'\n const scopeFlag = getScopeFlag(scope)\n const repoPath = getRepoPathForScope(scope, opts?.path)\n const cmd = `${buildGitCommand(['config', scopeFlag, '--get', key], repoPath)} || true`\n const result = await this.runShell(cmd, opts)\n const trimmed = result.stdout.trim()\n return trimmed.length > 0 ? trimmed : undefined\n }\n\n /**\n * Dangerously authenticate git globally via the credential helper.\n *\n * This persists credentials in the credential store.\n * Prefer short-lived credentials when possible.\n *\n * @param opts Authentication options.\n * @returns Command result from the command runner.\n */\n async dangerouslyAuthenticate(\n opts: GitDangerouslyAuthenticateOpts\n ): Promise<CommandResult> {\n const { username, password, host, protocol, ...rest } = opts\n\n if (!username || !password) {\n throw new InvalidArgumentError(\n 'Both username and password are required to authenticate git.'\n )\n }\n\n const targetHost = (host ?? 'github.com').trim()\n const targetProtocol = (protocol ?? 'https').trim()\n const credentialInput = [\n `protocol=${targetProtocol}`,\n `host=${targetHost}`,\n `username=${username}`,\n `password=${password}`,\n '',\n '',\n ].join('\\n')\n\n await this.runGit(\n ['config', '--global', 'credential.helper', 'store'],\n undefined,\n rest\n )\n\n const approveCmd = `printf %s ${shellEscape(credentialInput)} | ${buildGitCommand(\n ['credential', 'approve']\n )}`\n\n return this.runShell(approveCmd, rest)\n }\n\n /**\n * Configure git user name and email.\n *\n * @param name Git user name.\n * @param email Git user email.\n * @param opts Config options.\n * @returns Command result from the command runner.\n */\n async configureUser(\n name: string,\n email: string,\n opts?: GitConfigOpts\n ): Promise<CommandResult> {\n if (!name || !email) {\n throw new InvalidArgumentError('Both name and email are required.')\n }\n\n const scope = opts?.scope ?? 'global'\n const configOpts = { ...opts, scope }\n\n await this.setConfig('user.name', name, configOpts)\n return this.setConfig('user.email', email, configOpts)\n }\n\n /**\n * Build and execute a git command inside the sandbox.\n *\n * @param args Git arguments to pass to the git binary.\n * @param repoPath Repository path used with `git -C`, if provided.\n * @param opts Command execution options.\n * @returns Command result from the command runner.\n */\n private async runGit(\n args: string[],\n repoPath?: string,\n opts?: GitRequestOpts\n ): Promise<CommandResult> {\n const { envs, ...rest } = opts ?? {}\n const cmd = buildGitCommand(args, repoPath)\n const mergedEnvs = { ...DEFAULT_GIT_ENV, ...(envs ?? {}) }\n\n return this.commands.run(cmd, {\n ...rest,\n envs: mergedEnvs,\n })\n }\n\n /**\n * Execute a raw shell command while applying default git environment variables.\n *\n Note: We can likely just modify runGit later to allow appending commands to the git but for now it's separate.\n */\n private async runShell(\n cmd: string,\n opts?: GitRequestOpts\n ): Promise<CommandResult> {\n const { envs, ...rest } = opts ?? {}\n const mergedEnvs = { ...DEFAULT_GIT_ENV, ...(envs ?? {}) }\n\n return this.commands.run(cmd, {\n ...rest,\n envs: mergedEnvs,\n })\n }\n\n private async getRemoteUrl(\n path: string,\n remote: string,\n opts?: GitRequestOpts\n ): Promise<string> {\n const result = await this.runGit(['remote', 'get-url', remote], path, opts)\n const url = result.stdout.trim()\n if (!url) {\n throw new InvalidArgumentError(\n `Remote \"${remote}\" URL not found in repository.`\n )\n }\n return url\n }\n\n private async resolveRemoteName(\n path: string,\n remote: string | undefined,\n opts?: GitRequestOpts\n ): Promise<string> {\n if (remote) {\n return remote\n }\n\n const result = await this.runGit(['remote'], path, opts)\n const remotes = result.stdout\n .split('\\n')\n .map((line) => line.trim())\n .filter(Boolean)\n\n if (remotes.length === 1) {\n return remotes[0]\n }\n\n throw new InvalidArgumentError(\n 'Remote is required when using username/password and the repository has multiple remotes.'\n )\n }\n\n private async withRemoteCredentials<T>(\n path: string,\n remote: string,\n username: string,\n password: string,\n opts: GitRequestOpts | undefined,\n operation: () => Promise<T>\n ): Promise<T> {\n const originalUrl = await this.getRemoteUrl(path, remote, opts)\n const credentialUrl = withCredentials(originalUrl, username, password)\n\n await this.runGit(['remote', 'set-url', remote, credentialUrl], path, opts)\n\n let result: T | undefined\n let operationError: unknown\n try {\n result = await operation()\n } catch (err) {\n operationError = err\n }\n\n let restoreError: unknown\n try {\n await this.runGit(['remote', 'set-url', remote, originalUrl], path, opts)\n } catch (err) {\n restoreError = err\n }\n\n if (operationError) {\n throw operationError\n }\n if (restoreError) {\n throw restoreError\n }\n\n return result as T\n }\n\n private async hasUpstream(\n path: string,\n opts?: GitRequestOpts\n ): Promise<boolean> {\n try {\n const result = await this.runGit(\n ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'],\n path,\n opts\n )\n return result.stdout.trim().length > 0\n } catch {\n return false\n }\n }\n}\n\nexport type {\n GitBranches,\n GitConfigScope,\n GitFileStatus,\n GitStatus,\n} from './utils'\n","import {\n ConnectionConfig,\n ConnectionOpts,\n raiseIfLegacy,\n} from '../connectionConfig'\nimport { InvalidArgumentError, SecretError } from '../errors'\n\nconst SECRET_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/\nconst ENV_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/\nconst HOST_PATTERN =\n /^(\\*\\.)?[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?(?:\\.[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/\n\nexport function validateSecretEnvs(\n secretEnvs?: Record<string, string>,\n envs?: Record<string, string>\n): Record<string, string> {\n if (!secretEnvs) {\n return {}\n }\n\n if (typeof secretEnvs !== 'object' || Array.isArray(secretEnvs)) {\n throw new InvalidArgumentError('secretEnvs must be a mapping')\n }\n\n const envNames = new Set(Object.keys(envs ?? {}))\n const validated: Record<string, string> = {}\n\n for (const [envName, secretName] of Object.entries(secretEnvs)) {\n if (!ENV_NAME_PATTERN.test(envName)) {\n throw new InvalidArgumentError(\n `secretEnvs key ${JSON.stringify(envName)} must be a valid sandbox environment variable name`\n )\n }\n if (envNames.has(envName)) {\n throw new InvalidArgumentError(\n `envs and secretEnvs both define ${JSON.stringify(envName)}`\n )\n }\n validateSecretName(secretName)\n validated[envName] = secretName\n }\n\n return validated\n}\n\nexport type SecretBinding = {\n name: string\n hosts: string[]\n placeholder: string\n description: string | null\n hasSecret: boolean\n status: string\n updatedAt?: string | null\n}\n\nexport type SecretWriteParams = {\n name: string\n value: string\n hosts: string[]\n description?: string | null\n}\n\ntype SecretBindingResponse = {\n name: string\n hosts?: string[]\n placeholder: string\n description?: string | null\n hasSecret: boolean\n status: string\n updatedAt?: string | null\n}\n\ntype SecretListResponse = {\n secrets?: SecretBindingResponse[]\n}\n\ntype SecretDeleteResponse = {\n deleted?: string\n}\n\nexport class Secret {\n private static readonly base = '/secrets'\n\n static async create(\n params: SecretWriteParams,\n opts?: ConnectionOpts\n ): Promise<SecretBinding> {\n validateSecretName(params.name)\n if (!params.value) {\n throw new InvalidArgumentError('value is required')\n }\n const body: Record<string, unknown> = {\n name: params.name,\n value: params.value,\n hosts: normalizeSecretHosts(params.hosts),\n }\n if (params.description !== undefined) {\n body.description = params.description\n }\n\n return bindingFromJson(\n await request<SecretBindingResponse>(\n 'POST',\n Secret.base,\n 'Secret.create',\n opts,\n body\n )\n )\n }\n\n static async list(opts?: ConnectionOpts): Promise<SecretBinding[]> {\n const data = await request<SecretListResponse>(\n 'GET',\n Secret.base,\n 'Secret.list',\n opts\n )\n return (data.secrets ?? []).map(bindingFromJson)\n }\n\n static async get(\n name: string,\n opts?: ConnectionOpts\n ): Promise<SecretBinding> {\n validateSecretName(name)\n return bindingFromJson(\n await request<SecretBindingResponse>(\n 'GET',\n `${Secret.base}/${encodeURIComponent(name)}`,\n 'Secret.get',\n opts\n )\n )\n }\n\n static async update(\n params: SecretWriteParams,\n opts?: ConnectionOpts\n ): Promise<SecretBinding> {\n validateSecretName(params.name)\n if (!params.value) {\n throw new InvalidArgumentError('value is required')\n }\n const body: Record<string, unknown> = {\n value: params.value,\n hosts: normalizeSecretHosts(params.hosts),\n }\n if (params.description !== undefined) {\n body.description = params.description\n }\n\n return bindingFromJson(\n await request<SecretBindingResponse>(\n 'PUT',\n `${Secret.base}/${encodeURIComponent(params.name)}`,\n 'Secret.update',\n opts,\n body\n )\n )\n }\n\n static async delete(name: string, opts?: ConnectionOpts): Promise<string> {\n validateSecretName(name)\n const data = await request<SecretDeleteResponse>(\n 'DELETE',\n `${Secret.base}/${encodeURIComponent(name)}`,\n 'Secret.delete',\n opts\n )\n return String(data.deleted ?? '')\n }\n}\n\nfunction validateSecretName(name: string) {\n if (typeof name !== 'string' || !SECRET_NAME_PATTERN.test(name)) {\n throw new InvalidArgumentError(\n `secret name ${JSON.stringify(name)} must be 1-128 characters and contain only letters, numbers, dots, underscores, and hyphens`\n )\n }\n}\n\nfunction normalizeSecretHosts(hosts: string[]): string[] {\n if (!hosts.length) {\n throw new InvalidArgumentError('hosts is required')\n }\n\n const seen = new Set<string>()\n const normalizedHosts: string[] = []\n for (const rawHost of hosts) {\n if (typeof rawHost !== 'string') {\n throw new InvalidArgumentError('host must be a string')\n }\n\n const host = rawHost.trim().toLowerCase()\n if (!host) {\n throw new InvalidArgumentError('host cannot be empty')\n }\n if (host.includes('://') || /[/?#@:]/.test(host)) {\n throw new InvalidArgumentError(\n `host ${JSON.stringify(host)} must be a hostname only`\n )\n }\n\n const wildcard = host.startsWith('*.')\n const lookupHost = wildcard ? host.slice(2) : host\n if (!lookupHost || lookupHost.includes('*')) {\n throw new InvalidArgumentError(`invalid host ${JSON.stringify(host)}`)\n }\n\n const normalized = wildcard ? `*.${lookupHost}` : lookupHost\n if (!HOST_PATTERN.test(normalized)) {\n throw new InvalidArgumentError(\n `host ${JSON.stringify(host)} must be a hostname or wildcard hostname`\n )\n }\n if (seen.has(normalized)) {\n continue\n }\n\n seen.add(normalized)\n normalizedHosts.push(normalized)\n }\n\n return normalizedHosts\n}\n\nasync function request<T>(\n method: string,\n path: string,\n feature: string,\n opts?: ConnectionOpts,\n body?: Record<string, unknown>\n): Promise<T> {\n const config = new ConnectionConfig(opts)\n raiseIfLegacy(config, feature, SecretError)\n\n const headers: Record<string, string> = {\n ...config.headers,\n ...(body ? { 'Content-Type': 'application/json' } : {}),\n ...(config.apiKey ? { 'X-API-KEY': config.apiKey } : {}),\n ...(config.accessToken\n ? { Authorization: `Bearer ${config.accessToken}` }\n : {}),\n }\n const response = await fetch(`${config.apiUrl}${path}`, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n signal: config.getSignal(),\n })\n\n const data = await parseJson(response)\n if (!response.ok) {\n const message =\n typeof data?.message === 'string' ? data.message : response.statusText\n throw new SecretError(`${response.status}: ${message}`)\n }\n\n return data as T\n}\n\nasync function parseJson(response: Response): Promise<any> {\n const text = await response.text()\n return text ? JSON.parse(text) : {}\n}\n\nfunction bindingFromJson(data: SecretBindingResponse): SecretBinding {\n return {\n name: data.name,\n hosts: data.hosts ?? [],\n placeholder: data.placeholder,\n description: data.description ?? null,\n hasSecret: data.hasSecret,\n status: data.status,\n updatedAt: data.updatedAt,\n }\n}\n","import { ApiClient, components, handleApiError } from '../api'\nimport {\n ConnectionConfig,\n ConnectionOpts,\n DEFAULT_SANDBOX_TIMEOUT_MS,\n isLegacyDomain,\n raiseIfLegacy,\n} from '../connectionConfig'\nimport { compareVersions } from 'compare-versions'\nimport { AuthenticationError, RateLimitError, SandboxError, SandboxNotFoundError, TemplateError } from '../errors'\nimport { timeoutToSeconds } from '../utils'\nimport type { BuildInfo } from '../template/types'\nimport type { Volume } from '../volume'\nimport type { McpServer as BaseMcpServer } from './mcp'\nimport { defaultHeaders } from '../api/metadata'\nimport { validateSecretEnvs } from '../secret'\n\n/**\n * Extended MCP server configuration that includes base servers\n * and allows dynamic GitHub-based MCP servers with custom run and install commands.\n */\nexport type McpServer = BaseMcpServer | GitHubMcpServer\n\nexport type GitHubMcpServer = {\n [key: `github/${string}`]: {\n /**\n * Command to run the MCP server. Must start a stdio-compatible server.\n */\n runCmd: string\n /**\n * Command to install dependencies for the MCP server. Working directory is the root of the github repository.\n */\n installCmd?: string\n /**\n * Environment variables to set in the MCP process.\n */\n envs?: Record<string, string>\n }\n}\n\nasync function createRawApiError(response: Response): Promise<Error> {\n let message = response.statusText\n\n try {\n const body = await response.json()\n message = body?.message ?? JSON.stringify(body)\n } catch {\n try {\n message = await response.text()\n } catch {\n // Use statusText.\n }\n }\n\n if (response.status === 401) {\n return new AuthenticationError(\n `Unauthorized, please check your credentials. - ${message}`\n )\n }\n\n if (response.status === 429) {\n return new RateLimitError(\n `Rate limit exceeded, please try again later - ${message}`\n )\n }\n\n return new SandboxError(`${response.status}: ${message}`)\n}\n\nfunction getRawApiHeaders(\n config: ConnectionConfig,\n headers?: Record<string, string>\n): Record<string, string> {\n return {\n ...defaultHeaders,\n ...(config.apiKey ? { 'X-API-KEY': config.apiKey } : {}),\n ...(config.accessToken ? { Authorization: `Bearer ${config.accessToken}` } : {}),\n ...config.headers,\n ...(headers ?? {}),\n }\n}\n\nexport type SandboxNetworkOpts = {\n /**\n * Allow outbound traffic from the sandbox to the specified addresses.\n * If `allowOut` is not specified, all outbound traffic is allowed.\n *\n * Examples:\n * - To allow traffic to a specific addresses: `[\"1.1.1.1\", \"8.8.8.0/24\"]`\n */\n allowOut?: string[]\n\n /**\n * Deny outbound traffic from the sandbox to the specified addresses.\n *\n * Examples:\n * - To deny traffic to a specific addresses: `[\"1.1.1.1\", \"8.8.8.0/24\"]`\n */\n denyOut?: string[]\n\n /**\n * Specify if the sandbox URLs should be accessible only with authentication.\n * @default true\n */\n allowPublicTraffic?: boolean\n\n /** Specify host mask which will be used for all sandbox requests in the header.\n * You can use the ${PORT} variable that will be replaced with the actual port number of the service.\n *\n * @default ${PORT}-sandboxid.sandbox.ppio.cn\n */\n maskRequestHost?: string\n}\n\nexport type SandboxNetworkUpdateOpts = SandboxApiOpts &\n Pick<SandboxNetworkOpts, 'allowOut' | 'denyOut'>\n\nexport type SandboxLifecycle = {\n /**\n * Action to take when sandbox timeout is reached.\n * @default \"kill\"\n */\n onTimeout: 'pause' | 'kill'\n\n /**\n * Auto-resume enabled flag.\n * @default false\n * Can be `true` only when `onTimeout` is `pause`.\n */\n autoResume?: boolean\n}\n\nexport type SandboxInfoLifecycle = {\n /**\n * Action to take when sandbox timeout is reached.\n */\n onTimeout: 'pause' | 'kill'\n\n /**\n * Whether the sandbox can auto-resume.\n */\n autoResume: boolean\n}\n\n/**\n * Options for request to the Sandbox API.\n */\nexport interface SandboxApiOpts\n extends Partial<\n Pick<\n ConnectionOpts,\n 'apiKey' | 'headers' | 'debug' | 'domain' | 'requestTimeoutMs' | 'sync'\n >\n > {}\n\n/**\n * Options for creating a new Sandbox.\n */\nexport interface SandboxOpts extends ConnectionOpts {\n /**\n * Sandbox template name or ID.\n *\n * @default 'base' (or 'mcp-gateway' when `mcp` option is set)\n */\n template?: string\n\n /**\n * Custom metadata for the sandbox.\n *\n * @default {}\n */\n metadata?: Record<string, string>\n\n /**\n * Custom environment variables for the sandbox.\n *\n * Used when executing commands and code in the sandbox.\n * Can be overridden with the `envs` argument when executing commands or code.\n *\n * @default {}\n */\n envs?: Record<string, string>\n\n /**\n * Timeout for the sandbox in **milliseconds**.\n * Maximum time a sandbox can be kept alive is 24 hours (86_400_000 milliseconds) for Pro users and 1 hour (3_600_000 milliseconds) for Hobby users.\n *\n * @default 300_000 // 5 minutes\n */\n timeoutMs?: number\n\n /**\n * Secure all traffic coming to the sandbox controller with auth token\n *\n * @default true\n */\n secure?: boolean\n\n /**\n * Allow sandbox to access the internet. If set to `False`, it works the same as setting network `denyOut` to `[0.0.0.0/0]`.\n *\n * @default true\n */\n allowInternetAccess?: boolean\n\n /**\n * MCP server to enable in the sandbox\n * @default undefined\n */\n mcp?: McpServer\n\n /**\n * Sandbox network configuration\n */\n network?: SandboxNetworkOpts\n\n /**\n * Volume mounts for the sandbox.\n *\n * The keys are mount paths inside the sandbox and the values are either\n * a `Volume` instance or a string representing the volume name.\n *\n * @default undefined\n */\n volumeMounts?: Record<string, Volume | string>\n\n /**\n * Sandbox URL. Used for local development\n */\n sandboxUrl?: string\n\n /**\n * Sandbox lifecycle configuration.\n */\n lifecycle?: SandboxLifecycle\n\n /**\n * Map of sandbox environment variable names to stored secret names.\n *\n * Each key is the environment variable name created inside the sandbox\n * (e.g. `OPENAI_API_KEY`). Each value is the name of a secret previously\n * created via the secrets API (e.g. `openai-prod`). The sandbox receives\n * a placeholder in the environment variable, not the real secret value.\n *\n * Keys must not duplicate `envs` keys.\n */\n secretEnvs?: Record<string, string>\n\n /**\n * Optional node ID to schedule the sandbox on.\n */\n nodeId?: string\n}\n\nexport type SandboxBetaCreateOpts = SandboxOpts & {\n /**\n * @deprecated Use `lifecycle.onTimeout = \"pause\"` instead.\n *\n * Automatically pause the sandbox after the timeout expires.\n * @default false\n */\n autoPause?: boolean\n}\n\n/**\n * Options for connecting to a Sandbox.\n */\nexport type SandboxConnectOpts = ConnectionOpts & {\n /**\n * Timeout for the sandbox in **milliseconds**.\n * For running sandboxes, the timeout will update only if the new timeout is longer than the existing one.\n * Maximum time a sandbox can be kept alive is 24 hours (86_400_000 milliseconds) for Pro users and 1 hour (3_600_000 milliseconds) for Hobby users.\n *\n * @default 300_000 // 5 minutes\n */\n timeoutMs?: number\n\n /**\n * Secure all traffic coming to the sandbox controller with auth token.\n */\n secure?: boolean\n allowPublicTraffic?: boolean\n\n /**\n * Sandbox network configuration.\n */\n network?: SandboxNetworkOpts\n}\n\n/**\n * State of the sandbox.\n */\nexport type SandboxState = 'running' | 'paused'\n\nexport interface SandboxListOpts extends SandboxApiOpts {\n /**\n * Filter the list of sandboxes, e.g. by metadata `metadata:{\"key\": \"value\"}`, if there are multiple filters they are combined with AND.\n *\n */\n query?: {\n metadata?: Record<string, string>\n /**\n * Filter the list of sandboxes by state.\n * @default ['running', 'paused']\n */\n state?: Array<SandboxState>\n }\n\n /**\n * Number of sandboxes to return per page.\n *\n * @default 100\n */\n limit?: number\n\n /**\n * Token to the next page.\n */\n nextToken?: string\n}\n\nexport interface SandboxMetricsOpts extends SandboxApiOpts {\n /**\n * Start time for the metrics, defaults to the start of the sandbox\n */\n start?: Date\n /**\n * End time for the metrics, defaults to the current time\n */\n end?: Date\n}\n\nexport interface SandboxCloneOpts extends SandboxApiOpts {\n /**\n * Number of sandboxes to clone.\n *\n * @default 1\n */\n count?: number\n\n /**\n * Optional node ID to schedule cloned sandboxes on.\n */\n nodeId?: string\n\n /**\n * If true, require the exact requested count or fail.\n *\n * @default false\n */\n strict?: boolean\n\n /**\n * Timeout for cloned sandboxes in milliseconds.\n */\n timeoutMs?: number\n}\n\nexport interface SandboxCloneResultInfo {\n sandboxId: string\n envdVersion: string\n envdAccessToken?: string\n trafficAccessToken?: string\n}\n\nexport interface SandboxCloneResult<SandboxInstance> {\n sandboxes: SandboxInstance[]\n count: number\n snapshotTemplateId?: string\n}\n\nexport interface SandboxResetOpts extends SandboxApiOpts {\n /**\n * Whether to resume the sandbox after reset.\n *\n * @default true\n */\n resume?: boolean\n\n /**\n * Timeout for the resumed sandbox in milliseconds.\n */\n timeoutMs?: number\n\n /**\n * Secure all traffic coming to the sandbox controller with auth token.\n */\n secure?: boolean\n allowPublicTraffic?: boolean\n\n /**\n * Sandbox network configuration.\n */\n network?: SandboxNetworkOpts\n}\n\nexport interface SandboxCommitOpts extends SandboxApiOpts {\n /**\n * Optional alias for the created snapshot template.\n */\n alias?: string\n}\n\nexport type SandboxCommitResult = BuildInfo & {\n aliases: string[]\n names: string[]\n templateType: 'snapshot_template'\n}\n\n/**\n * Options for listing snapshots.\n */\nexport interface SnapshotListOpts extends SandboxApiOpts {\n /**\n * Filter snapshots by source sandbox ID.\n */\n sandboxId?: string\n\n /**\n * Number of snapshots to return per page.\n *\n * @default 100\n */\n limit?: number\n\n /**\n * Token to the next page.\n */\n nextToken?: string\n}\n\n/**\n * Information about a snapshot.\n */\nexport interface SnapshotInfo {\n /**\n * Snapshot identifier — template ID with tag, or namespaced name with tag (e.g. my-snapshot:latest).\n * Can be used with Sandbox.create() to create a new sandbox from this snapshot.\n */\n snapshotId: string\n}\n\n/**\n * Information about a sandbox.\n */\nexport interface SandboxInfo {\n /**\n * Sandbox ID.\n */\n sandboxId: string\n\n /**\n * Template ID.\n */\n templateId: string\n\n /**\n * Template name.\n */\n name?: string\n\n /**\n * Saved sandbox metadata.\n */\n metadata: Record<string, string>\n\n /**\n * Sandbox start time.\n */\n startedAt: Date\n\n /**\n * Sandbox expiration date.\n */\n endAt: Date\n\n /**\n * Sandbox state.\n *\n * @string can be `running` or `paused`\n */\n state: SandboxState\n\n /**\n * Sandbox CPU count.\n */\n cpuCount: number\n\n /**\n * Sandbox Memory size in MiB.\n */\n memoryMB: number\n\n /**\n * Envd version.\n */\n envdVersion?: string\n\n /**\n * Whether internet access was explicitly enabled or disabled for the sandbox.\n */\n allowInternetAccess?: boolean | undefined\n\n /**\n * Sandbox network configuration.\n */\n network?: SandboxNetworkOpts\n\n /**\n * Sandbox lifecycle configuration.\n */\n lifecycle?: SandboxInfoLifecycle\n\n /**\n * Volume mounts for the sandbox.\n */\n volumeMounts?: Array<{ name: string; path: string }>\n}\n\n/**\n * Sandbox resource usage metrics.\n */\nexport interface SandboxMetrics {\n /**\n * Timestamp of the metrics.\n */\n timestamp: Date\n\n /**\n * CPU usage in percentage.\n */\n cpuUsedPct: number\n\n /**\n * Number of CPU cores.\n */\n cpuCount: number\n\n /**\n * Memory usage in bytes.\n */\n memUsed: number\n\n /**\n * Total memory available in bytes.\n */\n memTotal: number\n\n /**\n * Used disk space in bytes.\n */\n diskUsed: number\n\n /**\n * Total disk space available in bytes.\n */\n diskTotal: number\n}\n\nfunction getLifecycle(\n opts?: Pick<SandboxBetaCreateOpts, 'lifecycle' | 'autoPause'>\n): SandboxLifecycle {\n if (opts?.lifecycle) {\n return opts.lifecycle\n }\n\n if (opts?.autoPause) {\n return {\n onTimeout: 'pause',\n autoResume: false,\n }\n }\n\n return {\n onTimeout: 'kill',\n autoResume: false,\n }\n}\n\nexport class SandboxApi {\n protected constructor() {}\n\n /**\n * Kill the sandbox specified by sandbox ID.\n *\n * @param sandboxId sandbox ID.\n * @param opts connection options.\n *\n * @returns `true` if the sandbox was found and killed, `false` otherwise.\n */\n static async kill(\n sandboxId: string,\n opts?: SandboxApiOpts\n ): Promise<boolean> {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.DELETE('/sandboxes/{sandboxID}', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n return false\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n return true\n }\n\n /**\n * Get sandbox information like sandbox ID, template, metadata, started at/end at date.\n *\n * @param sandboxId sandbox ID.\n * @param opts connection options.\n *\n * @returns sandbox information.\n */\n static async getInfo(\n sandboxId: string,\n opts?: SandboxApiOpts\n ): Promise<SandboxInfo> {\n const fullInfo = await this.getFullInfo(sandboxId, opts)\n delete fullInfo.envdAccessToken\n delete fullInfo.sandboxDomain\n\n return fullInfo\n }\n\n /**\n * Get the metrics of the sandbox.\n *\n * @param sandboxId sandbox ID.\n * @param opts sandbox metrics options.\n *\n * @returns List of sandbox metrics containing CPU, memory and disk usage information.\n */\n static async getMetrics(\n sandboxId: string,\n opts?: SandboxMetricsOpts\n ): Promise<SandboxMetrics[]> {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n if (config.isLegacyDomain) {\n const res = await client.api.GET('/sandboxes/{sandboxID}/metrics', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n return (\n ((res.data ?? []) as Array<Record<string, any>>).map(metric => ({\n timestamp: new Date(metric.timestamp),\n cpuUsedPct: metric.cpuUsedPct,\n cpuCount: metric.cpuCount,\n memUsed: metric.memUsedMiB * 1024 * 1024,\n memTotal: metric.memTotalMiB * 1024 * 1024,\n diskUsed: -1,\n diskTotal: -1,\n })) ?? []\n )\n }\n\n // JS timestamp is in milliseconds, convert to unix (seconds)\n const start = opts?.start\n ? Math.round(opts.start.getTime() / 1000)\n : undefined\n const end = opts?.end ? Math.round(opts.end.getTime() / 1000) : undefined\n const res = await client.api.GET('/sandboxes/{sandboxID}/metrics', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n query: {\n start,\n end,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n return (\n res.data?.map((metric: components['schemas']['SandboxMetric']) => ({\n timestamp: new Date(metric.timestamp),\n cpuUsedPct: metric.cpuUsedPct,\n cpuCount: metric.cpuCount,\n memUsed: metric.memUsed,\n memTotal: metric.memTotal,\n diskUsed: metric.diskUsed,\n diskTotal: metric.diskTotal,\n })) ?? []\n )\n }\n\n /**\n * Set the timeout of the specified sandbox.\n * After the timeout expires the sandbox will be automatically killed.\n *\n * This method can extend or reduce the sandbox timeout set when creating the sandbox or from the last call to {@link Sandbox.setTimeout}.\n *\n * Maximum time a sandbox can be kept alive is 24 hours (86_400_000 milliseconds) for Pro users and 1 hour (3_600_000 milliseconds) for Hobby users.\n *\n * @param sandboxId sandbox ID.\n * @param timeoutMs timeout in **milliseconds**.\n * @param opts connection options.\n */\n static async setTimeout(\n sandboxId: string,\n timeoutMs: number,\n opts?: SandboxApiOpts\n ): Promise<void> {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.POST('/sandboxes/{sandboxID}/timeout', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n body: {\n timeout: timeoutToSeconds(timeoutMs),\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n }\n\n /**\n * @deprecated Only legacy domains support this method. Use {@link SandboxApi.createSnapshot} for modern domains.\n */\n static async commit(\n sandboxId: string,\n opts?: SandboxCommitOpts\n ): Promise<SandboxCommitResult> {\n const config = new ConnectionConfig(opts)\n if (!config.isLegacyDomain) {\n throw new SandboxError('Sandbox.commit is only supported for legacy domains')\n }\n\n const response = await fetch(\n `${config.apiUrl}/sandboxes/${encodeURIComponent(sandboxId)}/commit`,\n {\n method: 'POST',\n headers: getRawApiHeaders(config, {\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify(opts?.alias ? { alias: opts.alias } : {}),\n signal: config.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n if (response.status === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n const data = (await response.json()) as {\n templateID: string\n buildID: string\n aliases?: string[]\n names?: string[]\n }\n\n return {\n alias: data.aliases?.[0] ?? data.names?.[0] ?? '',\n name: data.names?.[0] ?? data.aliases?.[0] ?? '',\n tags: [],\n templateId: data.templateID,\n buildId: data.buildID,\n aliases: data.aliases ?? [],\n names: data.names ?? [],\n templateType: 'snapshot_template',\n }\n }\n\n static async hotplugMemory(\n sandboxId: string,\n requestedSizeMib: number,\n opts?: SandboxApiOpts\n ): Promise<void> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Sandbox.hotplugMemory', SandboxError)\n const response = await fetch(\n `${config.apiUrl}/sandboxes/${encodeURIComponent(sandboxId)}/hotplug-memory`,\n {\n method: 'POST',\n headers: getRawApiHeaders(config, {\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify({\n requested_size_mib: requestedSizeMib,\n }),\n signal: config.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n if (response.status === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n }\n\n static async reset(\n sandboxId: string,\n opts?: SandboxResetOpts\n ): Promise<boolean> {\n const config = new ConnectionConfig(opts)\n const body: Record<string, unknown> = {\n resume: opts?.resume ?? true,\n ...(opts?.timeoutMs !== undefined\n ? { timeout: timeoutToSeconds(opts.timeoutMs) }\n : {}),\n }\n if (opts?.secure !== undefined) {\n body.secure = opts.secure\n }\n if (opts?.allowPublicTraffic !== undefined) {\n body.allowPublicTraffic = opts.allowPublicTraffic\n }\n if (opts?.network) {\n body.network = opts.network\n }\n\n const response = await fetch(\n `${config.apiUrl}/sandboxes/${encodeURIComponent(sandboxId)}/reset`,\n {\n method: 'POST',\n headers: getRawApiHeaders(config, {\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify(body),\n signal: config.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n if (response.status === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (response.status === 409) {\n return false\n }\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n return true\n }\n\n static async mountVolume(\n sandboxId: string,\n name: string,\n path: string,\n opts?: SandboxApiOpts\n ): Promise<SandboxInfo> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Sandbox.mountVolume', SandboxError)\n const response = await fetch(\n `${config.apiUrl}/sandboxes/${encodeURIComponent(sandboxId)}/volume-mounts`,\n {\n method: 'POST',\n headers: getRawApiHeaders(config, {\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify({ name, path }),\n signal: config.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n if (response.status === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n const data = await response.json()\n return {\n sandboxId: data.sandboxID,\n templateId: data.templateID,\n name: data.name,\n metadata: data.metadata ?? {},\n startedAt: new Date(data.startedAt),\n endAt: new Date(data.endAt),\n state: data.state,\n cpuCount: data.cpuCount,\n memoryMB: data.memoryMB,\n envdVersion: data.envdVersion,\n volumeMounts: data.volumeMounts ?? [],\n }\n }\n\n static async unmountVolume(\n sandboxId: string,\n path: string,\n opts?: SandboxApiOpts & { force?: boolean }\n ): Promise<SandboxInfo> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Sandbox.unmountVolume', SandboxError)\n const url = new URL(\n `${config.apiUrl}/sandboxes/${encodeURIComponent(sandboxId)}/volume-mounts`\n )\n url.searchParams.set('path', path)\n if (opts?.force) {\n url.searchParams.set('force', 'true')\n }\n\n const response = await fetch(url, {\n method: 'DELETE',\n headers: getRawApiHeaders(config),\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (response.status === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n const data = await response.json()\n return {\n sandboxId: data.sandboxID,\n templateId: data.templateID,\n name: data.name,\n metadata: data.metadata ?? {},\n startedAt: new Date(data.startedAt),\n endAt: new Date(data.endAt),\n state: data.state,\n cpuCount: data.cpuCount,\n memoryMB: data.memoryMB,\n envdVersion: data.envdVersion,\n volumeMounts: data.volumeMounts ?? [],\n }\n }\n\n static async setNetwork(\n sandboxId: string,\n opts?: SandboxNetworkUpdateOpts\n ): Promise<void> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Sandbox.setNetwork', SandboxError)\n const response = await fetch(\n `${config.apiUrl}/sandboxes/${encodeURIComponent(sandboxId)}/network`,\n {\n method: 'PUT',\n headers: getRawApiHeaders(config, {\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify({\n ...(opts?.allowOut ? { allowOut: opts.allowOut } : {}),\n ...(opts?.denyOut ? { denyOut: opts.denyOut } : {}),\n }),\n signal: config.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n if (response.status === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n }\n\n protected static async cloneSandboxes(\n sandboxId: string,\n opts?: SandboxCloneOpts\n ): Promise<{\n sandboxes: SandboxCloneResultInfo[]\n snapshotTemplateId?: string\n }> {\n const config = new ConnectionConfig(opts)\n const response = await fetch(\n `${config.apiUrl}/sandboxes/${encodeURIComponent(sandboxId)}/clone`,\n {\n method: 'POST',\n headers: getRawApiHeaders(config, {\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify({\n count: opts?.count ?? 1,\n strict: opts?.strict ?? false,\n ...(opts?.nodeId ? { nodeID: opts.nodeId } : {}),\n ...(opts?.timeoutMs !== undefined\n ? { timeout: timeoutToSeconds(opts.timeoutMs) }\n : {}),\n }),\n signal: config.getSignal(opts?.requestTimeoutMs ?? 300_000),\n }\n )\n\n if (response.status === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n const data = (await response.json()) as {\n sandboxes?: Array<{\n sandboxID?: string\n clientID?: string\n envdVersion?: string\n envdAccessToken?: string\n trafficAccessToken?: string\n }>\n snapshotTemplateId?: string\n }\n\n return {\n sandboxes: (data.sandboxes ?? []).map(sandbox => {\n const baseSandboxId = sandbox.sandboxID ?? ''\n const sandboxId = sandbox.clientID\n ? `${baseSandboxId}-${sandbox.clientID}`\n : baseSandboxId\n\n return {\n sandboxId,\n envdVersion: sandbox.envdVersion ?? '0.0.0',\n envdAccessToken: sandbox.envdAccessToken,\n trafficAccessToken: sandbox.trafficAccessToken,\n }\n }),\n snapshotTemplateId: data.snapshotTemplateId,\n }\n }\n\n static async getFullInfo(sandboxId: string, opts?: SandboxApiOpts) {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.GET('/sandboxes/{sandboxID}', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n if (!res.data) {\n throw new Error('Sandbox not found')\n }\n\n if (config.isLegacyDomain) {\n const data = res.data as Record<string, any>\n return {\n sandboxId:\n data.clientID != null\n ? `${data.sandboxID}-${data.clientID}`\n : data.sandboxID,\n templateId: data.templateID,\n ...(data.alias && { name: data.alias }),\n metadata: data.metadata ?? {},\n envdVersion: data.envdVersion ?? '0.0.0',\n envdAccessToken: data.envdAccessToken,\n startedAt: new Date(data.startedAt),\n endAt: new Date(data.endAt),\n state: data.state,\n cpuCount: data.cpuCount,\n memoryMB: data.memoryMB,\n sandboxDomain: data.domain || undefined,\n }\n }\n\n return {\n sandboxId: res.data.sandboxID,\n templateId: res.data.templateID,\n ...(res.data.alias && { name: res.data.alias }),\n metadata: res.data.metadata ?? {},\n allowInternetAccess: res.data.allowInternetAccess ?? undefined,\n envdVersion: res.data.envdVersion,\n envdAccessToken: res.data.envdAccessToken,\n startedAt: new Date(res.data.startedAt),\n endAt: new Date(res.data.endAt),\n state: res.data.state,\n cpuCount: res.data.cpuCount,\n memoryMB: res.data.memoryMB,\n network: res.data.network\n ? {\n allowOut: res.data.network.allowOut,\n denyOut: res.data.network.denyOut,\n allowPublicTraffic: res.data.network.allowPublicTraffic,\n maskRequestHost: res.data.network.maskRequestHost,\n }\n : undefined,\n lifecycle: res.data.lifecycle\n ? {\n onTimeout: res.data.lifecycle.onTimeout,\n autoResume: res.data.lifecycle.autoResume,\n }\n : undefined,\n sandboxDomain: res.data.domain || undefined,\n volumeMounts: res.data.volumeMounts ?? [],\n }\n }\n\n /**\n * Pause the sandbox specified by sandbox ID.\n *\n * @param sandboxId sandbox ID.\n * @param opts connection options.\n *\n * @returns `true` if the sandbox got paused, `false` if the sandbox was already paused.\n */\n static async pause(\n sandboxId: string,\n opts?: SandboxApiOpts\n ): Promise<boolean> {\n const config = new ConnectionConfig(opts)\n\n if (config.isLegacyDomain) {\n const response = await fetch(\n `${config.apiUrl}/sandboxes/${encodeURIComponent(sandboxId)}/pause`,\n {\n method: 'POST',\n headers: getRawApiHeaders(config, {\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify({ sync: opts?.sync ?? false }),\n signal: config.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n if (response.status === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (response.status === 409) {\n return false\n }\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n return true\n }\n\n const client = new ApiClient(config)\n\n const res = await client.api.POST('/sandboxes/{sandboxID}/pause', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (res.error?.code === 409) {\n // Sandbox is already paused\n return false\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n return true\n }\n\n /**\n * @deprecated Use {@link SandboxApi.pause} instead.\n */\n static async betaPause(\n sandboxId: string,\n opts?: SandboxApiOpts\n ): Promise<boolean> {\n return this.pause(sandboxId, opts)\n }\n\n /**\n * Create a snapshot from a sandbox.\n *\n * The sandbox will be paused while the snapshot is being created.\n * The snapshot can be used to create new sandboxes with the same state.\n * The snapshot is a persistent image that survives sandbox deletion.\n *\n * @param sandboxId sandbox ID to create snapshot from.\n * @param opts connection options.\n *\n * @returns snapshot information including the snapshot name that can be used with Sandbox.create().\n */\n static async createSnapshot(\n sandboxId: string,\n opts?: SandboxApiOpts\n ): Promise<SnapshotInfo> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Sandbox.createSnapshot', SandboxError)\n const client = new ApiClient(config)\n\n const res = await client.api.POST('/sandboxes/{sandboxID}/snapshots', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n body: {},\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n return {\n snapshotId: res.data!.snapshotID,\n }\n }\n\n /**\n * List all snapshots.\n *\n * @param opts list options including filters and pagination.\n *\n * @returns paginator for listing snapshots.\n */\n static listSnapshots(opts?: SnapshotListOpts): SnapshotPaginator {\n return new SnapshotPaginator(opts)\n }\n\n /**\n * Delete a snapshot.\n *\n * @param snapshotId snapshot ID.\n * @param opts connection options.\n *\n * @returns `true` if the snapshot was deleted, `false` if it was not found.\n */\n static async deleteSnapshot(\n snapshotId: string,\n opts?: SandboxApiOpts\n ): Promise<boolean> {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.DELETE('/templates/{templateID}', {\n params: {\n path: {\n templateID: snapshotId,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n return false\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n return true\n }\n\n protected static async createSandbox(\n template: string,\n timeoutMs: number,\n opts?: SandboxBetaCreateOpts\n ) {\n const config = new ConnectionConfig(opts)\n const lifecycle = getLifecycle(opts)\n const autoPause = lifecycle.onTimeout === 'pause'\n const autoResumeEnabled =\n lifecycle.onTimeout === 'pause'\n ? (lifecycle.autoResume ?? false)\n : undefined\n\n if (config.isLegacyDomain) {\n if (opts?.mcp) {\n raiseIfLegacy(config, 'Sandbox.create mcp', SandboxError)\n }\n if (opts?.network) {\n raiseIfLegacy(config, 'Sandbox.create network', SandboxError)\n }\n if (opts?.volumeMounts) {\n raiseIfLegacy(config, 'Sandbox.create volumeMounts', SandboxError)\n }\n if (opts?.secretEnvs) {\n raiseIfLegacy(config, 'Sandbox.create secretEnvs', SandboxError)\n }\n const body: Record<string, unknown> = {\n templateID: template,\n timeout: timeoutToSeconds(timeoutMs),\n metadata: opts?.metadata ?? {},\n envVars: opts?.envs ?? {},\n secure: opts?.secure ?? false,\n autoPause: autoPause ?? false,\n ...(opts?.nodeId ? { nodeID: opts.nodeId } : {}),\n }\n\n const response = await fetch(`${config.apiUrl}/sandboxes`, {\n method: 'POST',\n headers: getRawApiHeaders(config, {\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify(body),\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n const data = await response.json()\n if (compareVersions(data.envdVersion, '0.1.0') < 0) {\n await this.kill(data.sandboxID, opts)\n throw new TemplateError(\n 'You need to update the template to use the new SDK. ' +\n 'You can do this by running `ppio-sandbox template build` in the directory with the template.'\n )\n }\n\n return {\n sandboxId: data.clientID\n ? `${data.sandboxID}-${data.clientID}`\n : data.sandboxID,\n sandboxDomain: data.domain || undefined,\n envdVersion: data.envdVersion,\n envdAccessToken: data.envdAccessToken,\n trafficAccessToken: undefined,\n }\n }\n\n const client = new ApiClient(config)\n\n const body: components['schemas']['NewSandbox'] = {\n templateID: template,\n metadata: opts?.metadata,\n mcp: opts?.mcp as Record<string, unknown> | undefined,\n envVars: opts?.envs,\n timeout: timeoutToSeconds(timeoutMs),\n secure: opts?.secure ?? true,\n allow_internet_access: opts?.allowInternetAccess ?? true,\n network: opts?.network,\n ...(opts?.nodeId ? { nodeID: opts.nodeId } : {}),\n ...(autoPause !== undefined ? { autoPause } : {}),\n ...(autoResumeEnabled !== undefined\n ? { autoResume: { enabled: autoResumeEnabled } }\n : {}),\n }\n\n if (opts?.volumeMounts) {\n body.volumeMounts = Object.entries(opts.volumeMounts).map(\n ([mountPath, vol]) => ({\n name: typeof vol === 'string' ? vol : vol.name,\n path: mountPath,\n })\n )\n }\n\n const validatedSecretEnvs = validateSecretEnvs(\n opts?.secretEnvs,\n opts?.envs\n )\n if (Object.keys(validatedSecretEnvs).length > 0) {\n ;(body as Record<string, unknown>).secrets = validatedSecretEnvs\n }\n\n const res = await client.api.POST('/sandboxes', {\n body,\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n if (compareVersions(res.data!.envdVersion, '0.1.0') < 0) {\n await this.kill(res.data!.sandboxID, opts)\n throw new TemplateError(\n 'You need to update the template to use the new SDK. ' +\n 'You can do this by running `ppio template build` in the directory with the template.'\n )\n }\n\n return {\n sandboxId: res.data!.sandboxID,\n sandboxDomain: res.data!.domain || undefined,\n envdVersion: res.data!.envdVersion,\n envdAccessToken: res.data!.envdAccessToken,\n trafficAccessToken: res.data!.trafficAccessToken || undefined,\n }\n }\n\n protected static async connectSandbox(\n sandboxId: string,\n opts?: SandboxConnectOpts\n ) {\n const timeoutMs = opts?.timeoutMs ?? DEFAULT_SANDBOX_TIMEOUT_MS\n\n const config = new ConnectionConfig(opts)\n\n if (config.isLegacyDomain) {\n const response = await fetch(\n `${config.apiUrl}/sandboxes/${encodeURIComponent(sandboxId)}/connect`,\n {\n method: 'POST',\n headers: getRawApiHeaders(config, {\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify({ timeout: timeoutToSeconds(timeoutMs) }),\n signal: config.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n if (response.status === 404) {\n throw new SandboxNotFoundError(`Paused sandbox ${sandboxId} not found`)\n }\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n const data = await response.json()\n return {\n sandboxId: data.clientID\n ? `${data.sandboxID}-${data.clientID}`\n : data.sandboxID,\n sandboxDomain: data.domain || undefined,\n envdVersion: data.envdVersion || '0.0.0',\n envdAccessToken: data.envdAccessToken,\n trafficAccessToken: undefined,\n }\n }\n\n const client = new ApiClient(config)\n\n const res = await client.api.POST('/sandboxes/{sandboxID}/connect', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n body: {\n timeout: timeoutToSeconds(timeoutMs),\n ...(opts?.secure !== undefined ? { secure: opts.secure } : {}),\n ...(opts?.allowPublicTraffic !== undefined\n ? { allowPublicTraffic: opts.allowPublicTraffic }\n : {}),\n ...(opts?.network ? { network: opts.network } : {}),\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n throw new SandboxNotFoundError(`Paused sandbox ${sandboxId} not found`)\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n return {\n sandboxId: res.data!.sandboxID,\n sandboxDomain: res.data!.domain || undefined,\n envdVersion: res.data!.envdVersion,\n envdAccessToken: res.data!.envdAccessToken,\n trafficAccessToken: res.data!.trafficAccessToken || undefined,\n }\n }\n\n static async getQuota(\n opts?: SandboxQuotaOpts\n ): Promise<SandboxQuota> {\n const config = new ConnectionConfig(opts)\n raiseIfLegacy(config, 'Sandbox.getQuota', SandboxError)\n const url = new URL(`${config.apiUrl}/sandboxes/quota`)\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n ...config.headers,\n ...(config.apiKey ? { 'X-API-KEY': config.apiKey } : {}),\n ...(config.accessToken\n ? { Authorization: `Bearer ${config.accessToken}` }\n : {}),\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n const data = (await response.json()) as {\n limit?: Record<string, number>\n usage?: Record<string, number>\n }\n\n return {\n limit: {\n concurrentInstances: data.limit?.concurrentInstances ?? 0,\n concurrentVcpu: data.limit?.concurrentVcpu ?? 0,\n concurrentRamMb: data.limit?.concurrentRamMb ?? 0,\n maxLengthHours: data.limit?.maxLengthHours ?? 0,\n diskMb: data.limit?.diskMb ?? 0,\n maxVcpu: data.limit?.maxVcpu ?? 0,\n maxRamMb: data.limit?.maxRamMb ?? 0,\n },\n usage: {\n concurrentInstances: data.usage?.concurrentInstances ?? 0,\n concurrentVcpu: data.usage?.concurrentVcpu ?? 0,\n concurrentRamMb: data.usage?.concurrentRamMb ?? 0,\n },\n }\n }\n\n static async getEvents(\n opts?: SandboxEventsOpts\n ): Promise<SandboxEventsResult> {\n const config = new ConnectionConfig(opts)\n const url = new URL(`${config.apiUrl}/sandboxes/events`)\n if (opts?.startTime !== undefined)\n url.searchParams.set('startTime', String(opts.startTime))\n if (opts?.endTime !== undefined)\n url.searchParams.set('endTime', String(opts.endTime))\n if (opts?.sandboxID) url.searchParams.set('sandboxID', opts.sandboxID)\n if (opts?.templateID) url.searchParams.set('templateID', opts.templateID)\n if (opts?.events) url.searchParams.set('events', opts.events)\n if (opts?.state) url.searchParams.set('state', opts.state)\n if (opts?.orderAsc !== undefined)\n url.searchParams.set('orderAsc', String(opts.orderAsc))\n if (opts?.offset !== undefined)\n url.searchParams.set('offset', String(opts.offset))\n if (opts?.limit !== undefined)\n url.searchParams.set('limit', String(opts.limit))\n\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n ...config.headers,\n ...(config.apiKey ? { 'X-API-KEY': config.apiKey } : {}),\n ...(config.accessToken\n ? { Authorization: `Bearer ${config.accessToken}` }\n : {}),\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n const data = (await response.json()) as {\n items?: Array<{\n eventID: string\n recordAt: number\n templateID: string\n templateName: string\n sandboxID: string\n eventName: string\n state: string\n errorMsg: string\n statusCode: number\n }>\n total?: number\n hasMore?: boolean\n }\n\n return {\n items: data.items ?? [],\n total: data.total ?? 0,\n hasMore: data.hasMore ?? false,\n }\n }\n}\n\nabstract class BasePaginator<T> {\n protected readonly config: ConnectionConfig\n protected client: ApiClient\n protected readonly limit?: number\n\n private _hasNext: boolean\n private _nextToken?: string\n\n constructor(config: ConnectionConfig, limit?: number, nextToken?: string) {\n this.config = config\n this.client = new ApiClient(this.config)\n\n this._hasNext = true\n this._nextToken = nextToken\n\n this.limit = limit\n }\n\n /**\n * Returns true if there are more items to fetch.\n */\n get hasNext(): boolean {\n return this._hasNext\n }\n\n /**\n * Returns the next token to use for pagination.\n */\n get nextToken(): string | undefined {\n return this._nextToken\n }\n\n protected updatePagination(response: Response) {\n this._nextToken = response.headers.get('x-next-token') || undefined\n this._hasNext = !!this._nextToken\n }\n\n /**\n * Get the next page of items.\n *\n * @throws Error if there are no more items to fetch. Call this method only if `hasNext` is `true`.\n *\n * @returns List of items\n */\n abstract nextItems(): Promise<T[]>\n}\n\n/**\n * Paginator for listing sandboxes.\n *\n * @example\n * ```ts\n * const paginator = Sandbox.list()\n * while (paginator.hasNext) {\n * const sandboxes = await paginator.nextItems()\n * console.log(sandboxes)\n * }\n * ```\n */\nexport class SandboxPaginator extends BasePaginator<SandboxInfo> {\n private query: SandboxListOpts['query']\n\n constructor(opts?: SandboxListOpts) {\n super(new ConnectionConfig(opts), opts?.limit, opts?.nextToken)\n\n this.query = opts?.query\n }\n\n async nextItems(): Promise<SandboxInfo[]> {\n if (!this.hasNext) {\n throw new Error('No more items to fetch')\n }\n\n let metadata = undefined\n if (this.query?.metadata) {\n const encodedPairs: Record<string, string> = Object.fromEntries(\n Object.entries(this.query.metadata).map(([key, value]) => [\n encodeURIComponent(key),\n encodeURIComponent(value),\n ])\n )\n\n metadata = new URLSearchParams(encodedPairs).toString()\n }\n\n if (this.config.isLegacyDomain) {\n const params = new URLSearchParams()\n if (metadata) {\n params.set('metadata', metadata)\n }\n if (this.query?.state?.length) {\n params.set('state', this.query.state.join(','))\n }\n if (this.limit) {\n params.set('limit', String(this.limit))\n }\n if (this.nextToken) {\n params.set('nextToken', this.nextToken)\n }\n\n const query = params.toString()\n const response = await fetch(\n `${this.config.apiUrl}/v2/sandboxes${query ? `?${query}` : ''}`,\n {\n headers: getRawApiHeaders(this.config),\n signal: this.config.getSignal(),\n }\n )\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n this.updatePagination(response)\n\n const data = (await response.json()) as components['schemas']['ListedSandbox'][] | null\n return (data ?? []).map(sandbox => ({\n sandboxId:\n sandbox.clientID != null\n ? `${sandbox.sandboxID}-${sandbox.clientID}`\n : sandbox.sandboxID,\n templateId: sandbox.templateID,\n ...(sandbox.alias && { name: sandbox.alias }),\n metadata: sandbox.metadata ?? {},\n startedAt: new Date(sandbox.startedAt),\n endAt: new Date(sandbox.endAt),\n state: sandbox.state,\n cpuCount: sandbox.cpuCount,\n memoryMB: sandbox.memoryMB,\n envdVersion: sandbox.envdVersion,\n volumeMounts: sandbox.volumeMounts ?? [],\n }))\n }\n\n const res = await this.client.api.GET('/v2/sandboxes', {\n params: {\n query: {\n metadata,\n state: this.query?.state,\n limit: this.limit,\n nextToken: this.nextToken,\n },\n },\n // requestTimeoutMs is already passed here via the connectionConfig.\n signal: this.config.getSignal(),\n })\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n this.updatePagination(res.response)\n\n return (res.data ?? []).map(\n (sandbox: components['schemas']['ListedSandbox']) => ({\n sandboxId:\n this.config.isLegacyDomain && sandbox.clientID != null\n ? `${sandbox.sandboxID}-${sandbox.clientID}`\n : sandbox.sandboxID,\n templateId: sandbox.templateID,\n ...(sandbox.alias && { name: sandbox.alias }),\n metadata: sandbox.metadata ?? {},\n startedAt: new Date(sandbox.startedAt),\n endAt: new Date(sandbox.endAt),\n state: sandbox.state,\n cpuCount: sandbox.cpuCount,\n memoryMB: sandbox.memoryMB,\n envdVersion: sandbox.envdVersion,\n volumeMounts: sandbox.volumeMounts ?? [],\n })\n )\n }\n}\n\n/**\n * Paginator for listing snapshots.\n *\n * @example\n * ```ts\n * const paginator = Sandbox.listSnapshots()\n * while (paginator.hasNext) {\n * const snapshots = await paginator.nextItems()\n * console.log(snapshots)\n * }\n * ```\n */\nexport class SnapshotPaginator extends BasePaginator<SnapshotInfo> {\n private readonly sandboxId?: string\n\n constructor(opts?: SnapshotListOpts) {\n super(new ConnectionConfig(opts), opts?.limit, opts?.nextToken)\n\n raiseIfLegacy(this.config, 'Sandbox.listSnapshots', SandboxError)\n\n this.sandboxId = opts?.sandboxId\n }\n\n async nextItems(): Promise<SnapshotInfo[]> {\n if (!this.hasNext) {\n throw new Error('No more items to fetch')\n }\n\n const res = await this.client.api.GET('/snapshots', {\n params: {\n query: {\n sandboxID: this.sandboxId,\n limit: this.limit,\n nextToken: this.nextToken,\n },\n },\n signal: this.config.getSignal(),\n })\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n this.updatePagination(res.response)\n\n return (res.data ?? []).map(\n (snapshot: components['schemas']['SnapshotInfo']) => ({\n snapshotId: snapshot.snapshotID,\n })\n )\n }\n}\n\nexport interface SandboxQuotaLimit {\n concurrentInstances: number\n concurrentVcpu: number\n concurrentRamMb: number\n maxLengthHours: number\n diskMb: number\n maxVcpu: number\n maxRamMb: number\n}\n\nexport interface SandboxQuotaUsage {\n concurrentInstances: number\n concurrentVcpu: number\n concurrentRamMb: number\n}\n\nexport interface SandboxQuota {\n limit: SandboxQuotaLimit\n usage: SandboxQuotaUsage\n}\n\nexport interface SandboxQuotaOpts extends SandboxApiOpts {}\n\nexport interface SandboxEventsOpts extends SandboxApiOpts {\n startTime?: number\n endTime?: number\n sandboxID?: string\n templateID?: string\n events?: string\n state?: string\n orderAsc?: boolean\n offset?: number\n limit?: number\n}\n\nexport interface SandboxEventItem {\n eventID: string\n recordAt: number\n templateID: string\n templateName: string\n sandboxID: string\n eventName: string\n state: string\n errorMsg: string\n statusCode: number\n}\n\nexport interface SandboxEventsResult {\n items: SandboxEventItem[]\n total: number\n hasMore: boolean\n}\n","import { sha256 } from '../utils'\n\n/**\n * Get the URL signature for the specified path, operation and user.\n *\n * @param path Path to the file in the sandbox.\n *\n * @param operation File system operation. Can be either `read` or `write`.\n *\n * @param user Sandbox user.\n *\n * @param expirationInSeconds Optional signature expiration time in seconds.\n */\n\ninterface SignatureOpts {\n path: string\n operation: 'read' | 'write'\n user: string | undefined\n expirationInSeconds?: number\n envdAccessToken?: string\n}\n\nexport async function getSignature({\n path,\n operation,\n user,\n expirationInSeconds,\n envdAccessToken,\n}: SignatureOpts): Promise<{ signature: string; expiration: number | null }> {\n if (!envdAccessToken) {\n throw new Error(\n 'Access token is not set and signature cannot be generated!'\n )\n }\n\n // expiration is unix timestamp\n const signatureExpiration = expirationInSeconds\n ? Math.floor(Date.now() / 1000) + expirationInSeconds\n : null\n let signatureRaw: string\n\n // if user is undefined, set it to empty string to handle default user\n if (user == undefined) {\n user = ''\n }\n\n if (signatureExpiration === null) {\n signatureRaw = `${path}:${operation}:${user}:${envdAccessToken}`\n } else {\n signatureRaw = `${path}:${operation}:${user}:${envdAccessToken}:${signatureExpiration.toString()}`\n }\n\n const hashBase64 = await sha256(signatureRaw)\n const signature = 'v1_' + hashBase64.replace(/=+$/, '')\n\n return {\n signature: signature,\n expiration: signatureExpiration,\n }\n}\n","import { createConnectTransport } from '@connectrpc/connect-web'\n\nimport {\n ConnectionConfig,\n ConnectionOpts,\n DEFAULT_SANDBOX_TIMEOUT_MS,\n defaultUsername,\n raiseIfLegacy,\n isLegacyDomain,\n Username,\n} from '../connectionConfig'\nimport { EnvdApiClient, handleEnvdApiError } from '../envd/api'\nimport { createRpcLogger } from '../logs'\nimport { Commands, Pty } from './commands'\nimport { Filesystem } from './filesystem'\nimport { Git } from './git'\nimport {\n SandboxOpts,\n SandboxConnectOpts,\n SandboxMetricsOpts,\n SandboxApi,\n SandboxListOpts,\n SandboxPaginator,\n SandboxBetaCreateOpts,\n SandboxApiOpts,\n SandboxCloneOpts,\n SandboxCloneResult,\n SandboxCommitOpts,\n SandboxCommitResult,\n SandboxEventsOpts,\n SandboxEventsResult,\n SandboxInfo,\n SandboxNetworkUpdateOpts,\n SandboxQuota,\n SandboxQuotaOpts,\n SandboxResetOpts,\n SnapshotListOpts,\n SnapshotInfo,\n SnapshotPaginator,\n} from './sandboxApi'\nimport { getSignature } from './signature'\nimport { compareVersions } from 'compare-versions'\nimport { SandboxError } from '../errors'\nimport { ENVD_DEBUG_FALLBACK, ENVD_DEFAULT_USER } from '../envd/versions'\nimport { shellQuote } from '../utils'\n\n/**\n * Options for sandbox upload/download URL generation.\n */\nexport interface SandboxUrlOpts {\n /**\n * Use signature expiration for the URL.\n * Optional parameter to set the expiration time for the signature in seconds.\n */\n useSignatureExpiration?: number\n\n /**\n * User that will be used to access the file.\n */\n user?: Username\n}\n\n/**\n * PPIO sandbox cloud sandbox is a secure and isolated cloud environment.\n *\n * The sandbox allows you to:\n * - Access Linux OS\n * - Create, list, and delete files and directories\n * - Run commands\n * - Run git operations\n * - Run isolated code\n * - Access the internet\n *\n * Check docs [here](https://ppio.com/docs/sandbox/overview).\n *\n * Use {@link Sandbox.create} to create a new sandbox.\n *\n * @example\n * ```ts\n * import { Sandbox } from 'ppio-sandbox'\n *\n * const sandbox = await Sandbox.create()\n * ```\n */\nexport class Sandbox extends SandboxApi {\n protected static readonly defaultTemplate: string = 'base'\n protected static readonly defaultMcpTemplate: string = 'mcp-gateway'\n protected static readonly defaultSandboxTimeoutMs = DEFAULT_SANDBOX_TIMEOUT_MS\n\n /**\n * Module for interacting with the sandbox filesystem\n */\n readonly files: Filesystem\n /**\n * Module for running commands in the sandbox\n */\n readonly commands: Commands\n /**\n * Module for interacting with the sandbox pseudo-terminals\n */\n readonly pty: Pty\n /**\n * Module for running git operations in the sandbox\n */\n readonly git: Git\n\n /**\n * Unique identifier of the sandbox.\n */\n readonly sandboxId: string\n\n /**\n * Domain where the sandbox is hosted.\n */\n readonly sandboxDomain: string\n\n /**\n * Traffic access token for accessing sandbox services with restricted public traffic.\n */\n readonly trafficAccessToken?: string\n\n protected readonly envdPort = 49983\n protected readonly mcpPort = 50005\n\n protected readonly connectionConfig: ConnectionConfig\n protected readonly envdAccessToken?: string\n private readonly envdApiUrl: string\n private readonly envdApi: EnvdApiClient\n private mcpToken?: string\n\n /**\n * Use {@link Sandbox.create} to create a new Sandbox instead.\n *\n * @hidden\n * @hide\n * @internal\n * @access protected\n */\n constructor(\n opts: SandboxConnectOpts & {\n sandboxId: string\n sandboxDomain?: string\n envdVersion: string\n envdAccessToken?: string\n trafficAccessToken?: string\n }\n ) {\n super()\n\n this.connectionConfig = new ConnectionConfig(opts)\n\n this.sandboxId = opts.sandboxId\n this.sandboxDomain = opts.sandboxDomain ?? this.connectionConfig.domain\n\n this.envdAccessToken = opts.envdAccessToken\n this.trafficAccessToken = opts.trafficAccessToken\n this.envdApiUrl = this.connectionConfig.getSandboxUrl(this.sandboxId, {\n sandboxDomain: this.sandboxDomain,\n envdPort: this.envdPort,\n })\n\n const sandboxHeaders = {\n 'E2b-Sandbox-Id': this.sandboxId,\n 'E2b-Sandbox-Port': this.envdPort.toString(),\n }\n\n const rpcTransport = createConnectTransport({\n baseUrl: this.envdApiUrl,\n useBinaryFormat: false,\n interceptors: opts?.logger ? [createRpcLogger(opts.logger)] : undefined,\n fetch: (url, options) => {\n // Patch fetch to always use redirect: \"follow\"\n // connect-web doesn't allow to configure redirect option - https://github.com/connectrpc/connect-es/pull/1082\n // connect-web package uses redirect: \"error\" which is not supported in edge runtimes\n // PPIO sandbox endpoints should be safe to use with redirect: \"follow\" https://github.com/ppio-dev/PPIO sandbox/issues/531#issuecomment-2779492867\n\n const headers = new Headers(this.connectionConfig.headers)\n new Headers(options?.headers).forEach((value, key) =>\n headers.append(key, value)\n )\n new Headers(sandboxHeaders).forEach((value, key) =>\n headers.append(key, value)\n )\n\n if (this.envdAccessToken) {\n headers.append('X-Access-Token', this.envdAccessToken)\n }\n\n options = {\n ...(options ?? {}),\n headers: headers,\n redirect: 'follow',\n }\n\n return fetch(url, options)\n },\n })\n\n this.envdApi = new EnvdApiClient(\n {\n apiUrl: this.envdApiUrl,\n logger: opts?.logger,\n accessToken: this.envdAccessToken,\n headers: {\n 'User-Agent': this.connectionConfig.headers?.['User-Agent'] ?? '',\n ...sandboxHeaders,\n ...(this.envdAccessToken\n ? { 'X-Access-Token': this.envdAccessToken }\n : {}),\n },\n },\n {\n version: opts.envdVersion,\n }\n )\n this.files = new Filesystem(\n rpcTransport,\n this.envdApi,\n this.connectionConfig\n )\n this.commands = new Commands(rpcTransport, this.connectionConfig, {\n version: opts.envdVersion,\n })\n this.pty = new Pty(rpcTransport, this.connectionConfig, {\n version: opts.envdVersion,\n })\n this.git = new Git(this.commands)\n }\n\n /**\n * List all sandboxes.\n *\n * @param opts connection options.\n *\n * @returns paginator for listing sandboxes.\n */\n static list(opts?: SandboxListOpts): SandboxPaginator {\n return new SandboxPaginator(opts)\n }\n\n /**\n * Create a new sandbox from the default `base` sandbox template.\n *\n * @param opts connection options.\n *\n * @returns sandbox instance for the new sandbox.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * ```\n * @constructs {@link Sandbox}\n */\n static async create<S extends typeof Sandbox>(\n this: S,\n opts?: SandboxOpts\n ): Promise<InstanceType<S>>\n\n /**\n * Create a new sandbox from the specified sandbox template.\n *\n * @param template sandbox template name or ID.\n * @param opts connection options.\n *\n * @returns sandbox instance for the new sandbox.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create('<template-name-or-id>')\n * ```\n * @constructs {@link Sandbox}\n */\n static async create<S extends typeof Sandbox>(\n this: S,\n template: string,\n opts?: SandboxOpts\n ): Promise<InstanceType<S>>\n static async create<S extends typeof Sandbox>(\n this: S,\n templateOrOpts?: SandboxOpts | string,\n opts?: SandboxOpts\n ): Promise<InstanceType<S>> {\n const { template, sandboxOpts } =\n typeof templateOrOpts === 'string'\n ? {\n template: templateOrOpts,\n sandboxOpts: opts,\n }\n : {\n template:\n templateOrOpts?.template ??\n (templateOrOpts?.mcp\n ? this.defaultMcpTemplate\n : this.defaultTemplate),\n sandboxOpts: templateOrOpts,\n }\n\n const config = new ConnectionConfig(sandboxOpts)\n if (config.debug) {\n return new this({\n sandboxId: 'debug_sandbox_id',\n envdVersion: ENVD_DEBUG_FALLBACK,\n ...config,\n }) as InstanceType<S>\n }\n\n const sandboxInfo = await SandboxApi.createSandbox(\n template,\n sandboxOpts?.timeoutMs ?? this.defaultSandboxTimeoutMs,\n sandboxOpts\n )\n\n const sandbox = new this({ ...sandboxInfo, ...config }) as InstanceType<S>\n\n if (sandboxOpts?.mcp && !config.isLegacyDomain) {\n sandbox.mcpToken = crypto.randomUUID()\n const res = await sandbox.commands.run(\n `mcp-gateway --config ${shellQuote(JSON.stringify(sandboxOpts.mcp))}`,\n {\n user: 'root',\n envs: {\n GATEWAY_ACCESS_TOKEN: sandbox.mcpToken ?? '',\n },\n }\n )\n if (res.exitCode !== 0) {\n throw new Error(`Failed to start MCP gateway: ${res.stderr}`)\n }\n }\n\n return sandbox\n }\n\n /**\n * Clone a sandbox to create one or more identical sandboxes.\n *\n * @param sandboxId source sandbox ID.\n * @param opts clone options.\n *\n * @returns cloned sandbox instances plus snapshot template ID.\n */\n static async clone<S extends typeof Sandbox>(\n this: S,\n sandboxId: string,\n opts?: SandboxCloneOpts\n ): Promise<SandboxCloneResult<InstanceType<S>>> {\n const cloneResult = await SandboxApi.cloneSandboxes(sandboxId, opts)\n const config = new ConnectionConfig(opts)\n\n const sandboxes = cloneResult.sandboxes.map(\n sandbox =>\n new this({\n sandboxId: sandbox.sandboxId,\n envdVersion: sandbox.envdVersion,\n envdAccessToken: sandbox.envdAccessToken,\n trafficAccessToken: sandbox.trafficAccessToken,\n ...config,\n }) as InstanceType<S>\n )\n\n return {\n sandboxes,\n count: sandboxes.length,\n snapshotTemplateId: cloneResult.snapshotTemplateId,\n }\n }\n\n /**\n * Dynamically adjust the hotplugged memory on a running sandbox.\n *\n * The value represents the new *total* plugged size in MiB, not a delta.\n * Use `0` to unplug all hotplugged memory.\n */\n static async hotplugMemory(\n sandboxId: string,\n requestedSizeMib: number,\n opts?: SandboxApiOpts\n ): Promise<void> {\n return await SandboxApi.hotplugMemory(\n sandboxId,\n requestedSizeMib,\n opts\n )\n }\n\n /**\n * Mount a volume to a sandbox.\n *\n * @param sandboxId sandbox ID.\n * @param name volume name.\n * @param path mount path inside the sandbox.\n * @param opts connection options.\n *\n * @returns updated sandbox information.\n */\n static async mountVolume(\n sandboxId: string,\n name: string,\n path: string,\n opts?: SandboxApiOpts\n ): Promise<SandboxInfo> {\n return await SandboxApi.mountVolume(sandboxId, name, path, opts)\n }\n\n /**\n * Unmount a volume from a sandbox.\n *\n * @param sandboxId sandbox ID.\n * @param path mount path to unmount.\n * @param opts connection options.\n * @param [opts.force] force unmount.\n *\n * @returns updated sandbox information.\n */\n static async unmountVolume(\n sandboxId: string,\n path: string,\n opts?: SandboxApiOpts & { force?: boolean }\n ) {\n return await SandboxApi.unmountVolume(sandboxId, path, opts)\n }\n\n /**\n * Commit a sandbox to create a snapshot template.\n *\n * @deprecated Use snapshot APIs instead. This method is only supported for modern domains.\n *\n * @param sandboxId source sandbox ID.\n * @param opts commit options.\n *\n * @returns created snapshot template.\n */\n static async commit(\n sandboxId: string,\n opts?: SandboxCommitOpts\n ): Promise<SandboxCommitResult> {\n return await SandboxApi.commit(sandboxId, opts)\n }\n\n /**\n * Reset sandbox memory and optionally resume the sandbox.\n *\n * @param sandboxId sandbox ID.\n * @param opts reset options.\n *\n * @returns `true` if reset succeeded, `false` if the sandbox is in a conflicting state.\n */\n static async reset(\n sandboxId: string,\n opts?: SandboxResetOpts\n ): Promise<boolean> {\n return await SandboxApi.reset(sandboxId, opts)\n }\n\n /**\n * Update network egress rules for a running sandbox.\n * Omitting both `allowOut` and `denyOut` clears all egress rules.\n */\n static async setNetwork(\n sandboxId: string,\n opts?: SandboxNetworkUpdateOpts\n ): Promise<void> {\n await SandboxApi.setNetwork(sandboxId, opts)\n }\n\n /**\n * @beta This feature is in beta and may change in the future.\n *\n * Create a new sandbox from the default `base` sandbox template.\n *\n * @param opts connection options.\n *\n * @returns sandbox instance for the new sandbox.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.betaCreate()\n * ```\n * @constructs {@link Sandbox}\n */\n static async betaCreate<S extends typeof Sandbox>(\n this: S,\n opts?: SandboxBetaCreateOpts\n ): Promise<InstanceType<S>>\n\n /**\n * @beta This feature is in beta and may change in the future.\n *\n * Create a new sandbox from the specified sandbox template.\n *\n * @param template sandbox template name or ID.\n * @param opts connection options.\n *\n * @returns sandbox instance for the new sandbox.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.betaCreate('<template-name-or-id>')\n * ```\n * @constructs {@link Sandbox}\n */\n static async betaCreate<S extends typeof Sandbox>(\n this: S,\n template: string,\n opts?: SandboxBetaCreateOpts\n ): Promise<InstanceType<S>>\n static async betaCreate<S extends typeof Sandbox>(\n this: S,\n templateOrOpts?: SandboxBetaCreateOpts | string,\n opts?: SandboxBetaCreateOpts\n ): Promise<InstanceType<S>> {\n const { template, sandboxOpts } =\n typeof templateOrOpts === 'string'\n ? {\n template: templateOrOpts,\n sandboxOpts: opts,\n }\n : {\n template:\n templateOrOpts?.template ??\n (templateOrOpts?.mcp\n ? this.defaultMcpTemplate\n : this.defaultTemplate),\n sandboxOpts: templateOrOpts,\n }\n\n const config = new ConnectionConfig(sandboxOpts)\n if (config.debug) {\n return new this({\n sandboxId: 'debug_sandbox_id',\n envdVersion: ENVD_DEBUG_FALLBACK,\n ...config,\n }) as InstanceType<S>\n }\n\n const sandboxInfo = await SandboxApi.createSandbox(\n template,\n sandboxOpts?.timeoutMs ?? this.defaultSandboxTimeoutMs,\n sandboxOpts\n )\n\n const sandbox = new this({ ...sandboxInfo, ...config }) as InstanceType<S>\n\n if (sandboxOpts?.mcp && !config.isLegacyDomain) {\n sandbox.mcpToken = crypto.randomUUID()\n const res = await sandbox.commands.run(\n `mcp-gateway --config ${shellQuote(JSON.stringify(sandboxOpts.mcp))}`,\n {\n user: 'root',\n envs: {\n GATEWAY_ACCESS_TOKEN: sandbox.mcpToken ?? '',\n },\n }\n )\n if (res.exitCode !== 0) {\n throw new Error(`Failed to start MCP gateway: ${res.stderr}`)\n }\n }\n\n return sandbox\n }\n\n /**\n * Connect to a sandbox. If the sandbox is paused, it will be automatically resumed.\n * Sandbox must be either running or be paused.\n *\n * With sandbox ID you can connect to the same sandbox from different places or environments (serverless functions, etc).\n *\n * @param sandboxId sandbox ID.\n * @param opts connection options.\n *\n * @returns A running sandbox instance\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * const sandboxId = sandbox.sandboxId\n *\n * // Connect to the same sandbox.\n * const sameSandbox = await Sandbox.connect(sandboxId)\n * ```\n */\n static async connect<S extends typeof Sandbox>(\n this: S,\n sandboxId: string,\n opts?: SandboxConnectOpts\n ): Promise<InstanceType<S>> {\n const sandbox = await SandboxApi.connectSandbox(sandboxId, opts)\n const config = new ConnectionConfig(opts)\n\n return new this({\n sandboxId,\n sandboxDomain: sandbox.sandboxDomain,\n envdAccessToken: sandbox.envdAccessToken,\n trafficAccessToken: sandbox.trafficAccessToken,\n envdVersion: sandbox.envdVersion,\n ...config,\n }) as InstanceType<S>\n }\n\n /**\n * Connect to a sandbox. If the sandbox is paused, it will be automatically resumed.\n * Sandbox must be either running or be paused.\n *\n * With sandbox ID you can connect to the same sandbox from different places or environments (serverless functions, etc).\n *\n * @param opts connection options.\n *\n * @returns A running sandbox instance\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * await sandbox.betaPause()\n *\n * // Connect to the same sandbox.\n * const sameSandbox = await sandbox.connect()\n * ```\n */\n async connect(opts?: SandboxConnectOpts): Promise<this> {\n await SandboxApi.connectSandbox(this.sandboxId, this.resolveApiOpts(opts))\n\n return this\n }\n\n /**\n * Get the host address for the specified sandbox port.\n * You can then use this address to connect to the sandbox port from outside the sandbox via HTTP or WebSocket.\n *\n * @param port number of the port in the sandbox.\n *\n * @returns host address of the sandbox port.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * // Start an HTTP server\n * await sandbox.commands.exec('python3 -m http.server 3000')\n * // Get the hostname of the HTTP server\n * const serverURL = sandbox.getHost(3000)\n * ```\n */\n getHost(port: number) {\n return this.connectionConfig.getHost(\n this.sandboxId,\n port,\n this.sandboxDomain\n )\n }\n\n /**\n * Check if the sandbox is running.\n *\n * @returns `true` if the sandbox is running, `false` otherwise.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * await sandbox.isRunning() // Returns true\n *\n * await sandbox.kill()\n * await sandbox.isRunning() // Returns false\n * ```\n */\n async isRunning(\n opts?: Pick<ConnectionOpts, 'requestTimeoutMs'>\n ): Promise<boolean> {\n const signal = this.connectionConfig.getSignal(opts?.requestTimeoutMs)\n\n const res = await this.envdApi.api.GET('/health', {\n signal,\n })\n\n if (res.response.status == 502) {\n return false\n }\n\n const err = await handleEnvdApiError(res)\n if (err) {\n throw err\n }\n\n return true\n }\n\n /**\n * Set the timeout of the sandbox.\n *\n * This method can extend or reduce the sandbox timeout set when creating the sandbox or from the last call to `.setTimeout`.\n * Maximum time a sandbox can be kept alive is 24 hours (86_400_000 milliseconds) for Pro users and 1 hour (3_600_000 milliseconds) for Hobby users.\n *\n * @param timeoutMs timeout in **milliseconds**.\n * @param opts connection options.\n */\n async setTimeout(\n timeoutMs: number,\n opts?: Pick<SandboxOpts, 'requestTimeoutMs'>\n ) {\n if (this.connectionConfig.debug) {\n // Skip timeout in debug mode\n return\n }\n\n await SandboxApi.setTimeout(\n this.sandboxId,\n timeoutMs,\n this.resolveApiOpts(opts)\n )\n }\n\n /**\n * Reset sandbox memory and optionally resume the sandbox.\n *\n * @param opts reset options.\n *\n * @returns `true` if reset succeeded, `false` if the sandbox is in a conflicting state.\n */\n async reset(opts?: SandboxResetOpts): Promise<boolean> {\n return await SandboxApi.reset(this.sandboxId, this.resolveApiOpts(opts))\n }\n\n /**\n * Update network egress rules for this running sandbox.\n * Omitting both `allowOut` and `denyOut` clears all egress rules.\n */\n async setNetwork(opts?: SandboxNetworkUpdateOpts): Promise<void> {\n await SandboxApi.setNetwork(this.sandboxId, this.resolveApiOpts(opts))\n }\n\n /**\n * Commit this sandbox to create a snapshot template.\n *\n * @deprecated Use snapshot APIs instead. This method is only supported for modern domains.\n *\n * @param opts commit options.\n *\n * @returns created snapshot template.\n */\n async commit(opts?: SandboxCommitOpts): Promise<SandboxCommitResult> {\n return await SandboxApi.commit(this.sandboxId, this.resolveApiOpts(opts))\n }\n\n /**\n * Mount a volume to this sandbox.\n *\n * @param name volume name.\n * @param path mount path inside the sandbox.\n * @param opts connection options.\n *\n * @returns updated sandbox information.\n */\n async mountVolume(\n name: string, \n path: string, \n opts?: SandboxApiOpts\n ) {\n return await SandboxApi.mountVolume(\n this.sandboxId,\n name,\n path,\n this.resolveApiOpts(opts)\n )\n }\n\n /**\n * Unmount a volume from this sandbox.\n *\n * @param path mount path to unmount.\n * @param opts connection options.\n * @param [opts.force] force unmount.\n *\n * @returns updated sandbox information.\n */\n async unmountVolume(\n path: string,\n opts?: SandboxApiOpts & { force?: boolean }\n ) {\n return await SandboxApi.unmountVolume(\n this.sandboxId,\n path,\n this.resolveApiOpts(opts)\n )\n }\n\n /**\n * Kill the sandbox.\n *\n * @param opts connection options.\n */\n async kill(opts?: Pick<SandboxOpts, 'requestTimeoutMs'>) {\n if (this.connectionConfig.debug) {\n // Skip killing in debug mode\n return\n }\n\n await SandboxApi.kill(this.sandboxId, this.resolveApiOpts(opts))\n }\n\n /**\n * Dynamically adjust the hotplugged memory on a running sandbox.\n *\n * The value represents the new *total* plugged size in MiB, not a delta.\n * Use `0` to unplug all hotplugged memory.\n *\n * @param requestedSizeMib new total plugged memory size in MiB.\n * @param opts connection options.\n */\n async hotplugMemory(\n requestedSizeMib: number,\n opts?: SandboxApiOpts\n ): Promise<void> {\n await SandboxApi.hotplugMemory(\n this.sandboxId,\n requestedSizeMib,\n this.resolveApiOpts(opts)\n )\n }\n\n /**\n * Pause a sandbox by its ID.\n *\n * @param opts connection options.\n *\n * @returns sandbox ID that can be used to resume the sandbox.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * await sandbox.pause()\n * ```\n */\n async pause(opts?: ConnectionOpts): Promise<boolean> {\n return await SandboxApi.pause(this.sandboxId, this.resolveApiOpts(opts))\n }\n\n /**\n * @deprecated Use {@link Sandbox.pause} instead.\n */\n async betaPause(opts?: ConnectionOpts): Promise<boolean> {\n return await SandboxApi.betaPause(\n this.sandboxId,\n this.resolveApiOpts(opts)\n )\n }\n\n /**\n * Create a snapshot of the sandbox's current state.\n *\n * The sandbox will be paused while the snapshot is being created.\n * The snapshot can be used to create new sandboxes with the same filesystem and state.\n * Snapshots are persistent and survive sandbox deletion.\n *\n * Use the returned `snapshotId` with `Sandbox.create(snapshotId)` to create a new sandbox from the snapshot.\n *\n * @param opts connection options.\n *\n * @returns snapshot information including the snapshot ID.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * await sandbox.files.write('/app/state.json', '{\"step\": 1}')\n *\n * // Create a snapshot\n * const snapshot = await sandbox.createSnapshot()\n *\n * // Create a new sandbox from the snapshot\n * const newSandbox = await Sandbox.create(snapshot.snapshotId)\n * ```\n */\n async createSnapshot(opts?: SandboxApiOpts): Promise<SnapshotInfo> {\n return await SandboxApi.createSnapshot(\n this.sandboxId,\n this.resolveApiOpts(opts)\n )\n }\n\n /**\n * List all snapshots created from this sandbox.\n *\n * @param opts list options.\n *\n * @returns paginator for listing snapshots from this sandbox.\n */\n listSnapshots(opts?: Omit<SnapshotListOpts, 'sandboxId'>): SnapshotPaginator {\n return SandboxApi.listSnapshots({\n ...this.resolveApiOpts(opts),\n sandboxId: this.sandboxId,\n })\n }\n\n /**\n *\n * Get the MCP URL for the sandbox.\n *\n * @returns MCP URL for the sandbox.\n */\n getMcpUrl(): string {\n raiseIfLegacy(this.connectionConfig, 'Sandbox.getMcpUrl', SandboxError)\n\n return `https://${this.getHost(this.mcpPort)}/mcp`\n }\n\n /**\n * Get the MCP token for the sandbox.\n *\n * @returns MCP token for the sandbox, or undefined if MCP is not enabled.\n */\n async getMcpToken(): Promise<string | undefined> {\n raiseIfLegacy(this.connectionConfig, 'Sandbox.getMcpToken', SandboxError)\n\n if (!this.mcpToken) {\n this.mcpToken = await this.files.read('/etc/mcp-gateway/.token', {\n user: 'root',\n })\n }\n\n return this.mcpToken\n }\n\n /**\n * Get the URL to upload a file to the sandbox.\n *\n * You have to send a POST request to this URL with the file as multipart/form-data.\n *\n * @param path path to the file in the sandbox.\n *\n * @param opts download url options.\n *\n * @returns URL for uploading file.\n */\n async uploadUrl(path?: string, opts?: SandboxUrlOpts) {\n opts = opts ?? {}\n\n const useSignature = !!this.envdAccessToken\n\n if (!useSignature && opts.useSignatureExpiration != undefined) {\n throw new Error(\n 'Signature expiration can be used only when sandbox is created as secured.'\n )\n }\n\n let username = opts.user\n if (\n username == undefined &&\n compareVersions(this.envdApi.version, ENVD_DEFAULT_USER) < 0\n ) {\n username = defaultUsername\n }\n\n const filePath = path ?? ''\n const fileUrl = this.fileUrl(filePath, username)\n\n if (useSignature) {\n const url = new URL(fileUrl)\n const sig = await getSignature({\n path: filePath,\n operation: 'write',\n user: username,\n expirationInSeconds: opts.useSignatureExpiration,\n envdAccessToken: this.envdAccessToken,\n })\n\n url.searchParams.set('signature', sig.signature)\n if (sig.expiration) {\n url.searchParams.set('signature_expiration', sig.expiration.toString())\n }\n\n return url.toString()\n }\n\n return fileUrl\n }\n\n /**\n * Get the URL to download a file from the sandbox.\n *\n * @param path path to the file in the sandbox.\n *\n * @param opts download url options.\n *\n * @returns URL for downloading file.\n */\n async downloadUrl(path: string, opts?: SandboxUrlOpts) {\n opts = opts ?? {}\n\n const useSignature = !!this.envdAccessToken\n\n if (!useSignature && opts.useSignatureExpiration != undefined) {\n throw new Error(\n 'Signature expiration can be used only when sandbox is created as secured.'\n )\n }\n\n let username = opts.user\n if (\n username == undefined &&\n compareVersions(this.envdApi.version, ENVD_DEFAULT_USER) < 0\n ) {\n username = defaultUsername\n }\n\n const fileUrl = this.fileUrl(path, username)\n\n if (useSignature) {\n const url = new URL(fileUrl)\n const sig = await getSignature({\n path,\n operation: 'read',\n user: username,\n expirationInSeconds: opts.useSignatureExpiration,\n envdAccessToken: this.envdAccessToken,\n })\n\n url.searchParams.set('signature', sig.signature)\n if (sig.expiration) {\n url.searchParams.set('signature_expiration', sig.expiration.toString())\n }\n\n return url.toString()\n }\n\n return fileUrl\n }\n\n /**\n * Get sandbox information like sandbox ID, template, metadata, started at/end at date.\n *\n * @param opts connection options.\n *\n * @returns information about the sandbox\n */\n async getInfo(opts?: Pick<SandboxOpts, 'requestTimeoutMs'>) {\n return await SandboxApi.getInfo(this.sandboxId, this.resolveApiOpts(opts))\n }\n\n /**\n * Get the metrics of the sandbox.\n *\n * @param opts connection options.\n *\n * @returns List of sandbox metrics containing CPU, memory and disk usage information.\n */\n async getMetrics(opts?: SandboxMetricsOpts) {\n if (this.envdApi.version) {\n if (compareVersions(this.envdApi.version, '0.1.5') < 0) {\n throw new SandboxError(\n 'You need to update the template to use the new SDK. ' +\n 'You can do this by running `ppio template build` in the directory with the template.'\n )\n }\n\n if (compareVersions(this.envdApi.version, '0.2.4') < 0) {\n this.connectionConfig.logger?.warn?.(\n 'Disk metrics are not supported in this version of the sandbox, please rebuild the template to get disk metrics.'\n )\n }\n }\n\n return await SandboxApi.getMetrics(\n this.sandboxId,\n this.resolveApiOpts(opts)\n )\n }\n\n private resolveApiOpts<T extends ConnectionOpts>(\n opts?: T\n ): ConnectionOpts & T {\n return {\n ...this.connectionConfig,\n ...(opts ?? {}),\n } as unknown as ConnectionOpts & T\n }\n\n private fileUrl(path: string | undefined, username: string | undefined) {\n const url = new URL('/files', this.envdApiUrl)\n\n if (username) {\n url.searchParams.set('username', username)\n }\n if (path) {\n url.searchParams.set('path', path)\n }\n\n return url.toString()\n }\n}\n","import chalk from 'chalk'\nimport { stripAnsi } from '../utils'\n\n/**\n * Log entry severity levels.\n */\nexport type LogEntryLevel = 'debug' | 'info' | 'warn' | 'error'\n\n/**\n * Represents a single log entry from the template build process.\n */\nexport class LogEntry {\n constructor(\n public readonly timestamp: Date,\n public readonly level: LogEntryLevel,\n public readonly message: string\n ) {}\n\n toString() {\n return `[${this.timestamp.toISOString()}] [${this.level}] ${stripAnsi(\n this.message\n )}`\n }\n}\n\n/**\n * Special log entry indicating the start of a build process.\n */\nexport class LogEntryStart extends LogEntry {\n constructor(timestamp: Date, message: string) {\n super(timestamp, 'debug', message)\n }\n}\n\n/**\n * Special log entry indicating the end of a build process.\n */\nexport class LogEntryEnd extends LogEntry {\n constructor(timestamp: Date, message: string) {\n super(timestamp, 'debug', message)\n }\n}\n\n/**\n * Interval in milliseconds for updating the build timer display.\n * @internal\n */\nconst TIMER_UPDATE_INTERVAL_MS = 150\n\n/**\n * Default minimum log level to display.\n * @internal\n */\nconst DEFAULT_LEVEL: LogEntryLevel = 'info'\n\n/**\n * Colored labels for each log level.\n * @internal\n */\nconst levels: Record<LogEntryLevel, string> = {\n error: chalk.red('ERROR'),\n warn: chalk.hex('#FF4400')('WARN '),\n info: chalk.hex('#FF8800')('INFO '),\n debug: chalk.gray('DEBUG'),\n}\n\n/**\n * Numeric ordering of log levels for comparison (lower = less severe).\n * @internal\n */\nconst level_order: Record<LogEntryLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n}\n\ninterface DefaultBuildLoggerState {\n startTime: number\n animationFrame: number\n timerInterval: NodeJS.Timeout | undefined\n}\n\nclass DefaultBuildLogger {\n private minLevel: LogEntryLevel\n private state: DefaultBuildLoggerState\n\n constructor(minLevel?: LogEntryLevel) {\n this.minLevel = minLevel ?? DEFAULT_LEVEL\n this.state = this.getInitialState()\n }\n\n logger(logEntry: LogEntry) {\n if (logEntry instanceof LogEntryStart) {\n this.startTimer()\n return\n }\n\n if (logEntry instanceof LogEntryEnd) {\n clearInterval(this.state.timerInterval)\n return\n }\n\n // Filter by minimum level\n if (level_order[logEntry.level] < level_order[this.minLevel]) {\n return\n }\n\n const formattedLine = this.formatLogLine(logEntry)\n process.stdout.write(`${formattedLine}\\n`)\n\n // Redraw the timer line\n this.updateTimer()\n }\n\n private getInitialState(\n timerInterval?: NodeJS.Timeout\n ): DefaultBuildLoggerState {\n return {\n startTime: Date.now(),\n animationFrame: 0,\n timerInterval: timerInterval,\n }\n }\n\n private formatTimerLine() {\n const elapsedSeconds = ((Date.now() - this.state.startTime) / 1000).toFixed(\n 1\n )\n return `${elapsedSeconds}s`\n }\n\n private animateStatus() {\n const frames = ['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷']\n const idx = this.state.animationFrame % frames.length\n return `${frames[idx]}`\n }\n\n private formatLogLine(line: LogEntry) {\n const timer = this.formatTimerLine().padEnd(5)\n\n const timestamp = chalk.dim(\n line.timestamp.toLocaleTimeString(undefined, {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n })\n )\n\n const level = levels[line.level] || levels[DEFAULT_LEVEL]\n\n const msg = line.message\n\n return `${timer} | ${timestamp} ${level} ${msg}`\n }\n\n private startTimer() {\n if (!process.stdout.isTTY) {\n return\n }\n\n // Start the timer interval\n const timerInterval = setInterval(\n this.updateTimer.bind(this),\n TIMER_UPDATE_INTERVAL_MS\n )\n\n this.state = this.getInitialState(timerInterval)\n\n // Initial timer display\n this.updateTimer()\n }\n\n private updateTimer() {\n if (!process.stdout.isTTY) {\n return\n }\n\n this.state.animationFrame++\n const jumpingSquares = this.animateStatus()\n process.stdout.write(\n `${jumpingSquares} Building ${this.formatTimerLine()}\\r`\n )\n }\n}\n\n/**\n * Create a default build logger with animated timer display.\n *\n * @param options Logger configuration options\n * @param options.minLevel Minimum log level to display (default: 'info')\n * @returns Logger function that accepts LogEntry instances\n *\n * @example\n * ```ts\n * import { Template, defaultBuildLogger } from 'ppio-sandbox'\n *\n * const template = Template().fromPythonImage()\n *\n * await Template.build(template, {\n * alias: 'my-template',\n * onBuildLogs: defaultBuildLogger({ minLevel: 'debug' })\n * })\n * ```\n */\nexport function defaultBuildLogger(options?: {\n minLevel?: LogEntryLevel\n}): (logEntry: LogEntry) => void {\n const buildLogger = new DefaultBuildLogger(options?.minLevel)\n\n return buildLogger.logger.bind(buildLogger)\n}\n","/**\n * Special step name for the finalization phase of template building.\n * This is the last step that runs after all user-defined instructions.\n * @internal\n */\nexport const FINALIZE_STEP_NAME = 'finalize'\n\n/**\n * Special step name for the base image phase of template building.\n * This is the first step that sets up the base image.\n * @internal\n */\nexport const BASE_STEP_NAME = 'base'\n\n/**\n * Stack trace depth for capturing caller information.\n *\n * Depth levels:\n * 1. Template function\n * 2. TemplateBase class\n * 3. Caller method (e.g., copy(), fromImage(), etc.)\n *\n * This depth is used to determine the original caller's location\n * for stack traces.\n * @internal\n */\nexport const STACK_TRACE_DEPTH = 3\n\n/**\n * Default setting for whether to resolve symbolic links when copying files.\n * When false, symlinks are copied as symlinks rather than following them.\n * @internal\n */\nexport const RESOLVE_SYMLINKS = false\n","import crypto from 'node:crypto'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { dynamicImport, dynamicRequire } from '../utils'\nimport { TemplateError } from '../errors'\nimport { BASE_STEP_NAME, FINALIZE_STEP_NAME } from './consts'\nimport type { Path } from 'glob'\nimport type { BuildOptions } from './types'\n\n/**\n * Validate that a source path for copy operations is a relative path that stays\n * within the context directory. This prevents path traversal attacks and ensures\n * files are copied from within the expected directory.\n *\n * @param src The source path to validate\n * @param stackTrace Optional stack trace for error reporting\n * @throws TemplateError if the path is absolute or escapes the context directory\n *\n * Invalid paths:\n * - Absolute paths: /absolute/path, C:\\Windows\\path\n * - Parent directory escapes: ../foo, foo/../../bar, ./foo/../../../bar\n *\n * Valid paths:\n * - Simple relative: foo, foo/bar\n * - Current directory prefix: ./foo, ./foo/bar\n * - Internal parent refs that don't escape: foo/../bar (stays within context)\n */\nexport function validateRelativePath(\n src: string,\n stackTrace: string | undefined\n): void {\n // Check for absolute paths using Node's cross-platform implementation\n if (path.isAbsolute(src)) {\n const error = new TemplateError(\n `Invalid source path \"${src}\": absolute paths are not allowed. Use a relative path within the context directory.`,\n stackTrace\n )\n throw error\n }\n\n // Normalize the path and check if it escapes the context directory\n const normalized = path.normalize(src)\n\n // After normalization, a path that escapes would be '..' or start with '../'\n // We check for '..' followed by path separator to avoid false positives on filenames like '..myconfig'\n // Examples:\n // - '../foo' -> '../foo' (escapes)\n // - 'foo/../../bar' -> '../bar' (escapes)\n // - './foo/../../../bar' -> '../../bar' (escapes)\n // - 'foo/../bar' -> 'bar' (doesn't escape)\n // - './foo/bar' -> 'foo/bar' (doesn't escape)\n // - '..myconfig' -> '..myconfig' (valid filename, doesn't escape)\n const escapes = normalized === '..' || normalized.startsWith('..' + path.sep)\n\n if (escapes) {\n const error = new TemplateError(\n `Invalid source path \"${src}\": path escapes the context directory. The path must stay within the context directory.`,\n stackTrace\n )\n throw error\n }\n}\n\n/**\n * Normalize build arguments from different overload signatures.\n * Handles string name or legacy options object with alias.\n *\n * @param nameOrOptions Name or legacy options with alias\n * @param options Optional build options (when first arg is name)\n * @returns Object with normalized name, tags, and build options\n * @throws TemplateError if no template name is provided\n */\nexport function normalizeBuildArguments(\n nameOrOptions: string | BuildOptions,\n options?: Omit<BuildOptions, 'alias'>\n): {\n name: string\n buildOptions: Omit<BuildOptions, 'alias'>\n} {\n let name: string\n let buildOptions: Omit<BuildOptions, 'alias'>\n\n if (typeof nameOrOptions === 'string') {\n name = nameOrOptions\n buildOptions = options ?? {}\n } else {\n // Legacy: options object with alias\n const { alias, ...restOpts } = nameOrOptions\n name = alias\n buildOptions = restOpts\n }\n\n if (!name || name.length === 0) {\n throw new TemplateError('Name must be provided')\n }\n\n return { name, buildOptions }\n}\n\n/**\n * Read and parse a .dockerignore file.\n *\n * @param contextPath Directory path containing the .dockerignore file\n * @returns Array of ignore patterns (empty lines and comments are filtered out)\n */\nexport function readDockerignore(contextPath: string): string[] {\n const dockerignorePath = path.join(contextPath, '.dockerignore')\n if (!fs.existsSync(dockerignorePath)) {\n return []\n }\n\n const content = fs.readFileSync(dockerignorePath, 'utf-8')\n return content\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line && !line.startsWith('#'))\n}\n\n/**\n * Normalize path separators to forward slashes for glob patterns (glob expects / even on Windows)\n * @param path - The path to normalize\n * @returns The normalized path\n */\nfunction normalizePath(path: string): string {\n return path.replace(/\\\\/g, '/')\n}\n\n/**\n * Get all files for a given path and ignore patterns.\n *\n * @param src Path to the source directory\n * @param contextPath Base directory for resolving relative paths\n * @param ignorePatterns Ignore patterns\n * @returns Array of files\n */\nexport async function getAllFilesInPath(\n src: string,\n contextPath: string,\n ignorePatterns: string[],\n includeDirectories: boolean = true\n) {\n const { glob } = await dynamicImport<typeof import('glob')>('glob')\n const files = new Map<string, Path>()\n\n const globFiles = await glob(src, {\n ignore: ignorePatterns,\n withFileTypes: true,\n dot: true,\n // this is required so that the ignore pattern is relative to the file path\n cwd: contextPath,\n })\n\n for (const file of globFiles) {\n if (file.isDirectory()) {\n // For directories, add the directory itself and all files inside it\n if (includeDirectories) {\n files.set(file.fullpath(), file)\n }\n const dirPattern = normalizePath(\n // When the matched directory is '.', `file.relative()` can be an empty string.\n // In that case, we want to match all files under the current directory instead of\n // creating an absolute glob like '/**/*' which would traverse the entire filesystem.\n path.join(file.relative() || '.', '**/*')\n )\n const dirFiles = await glob(dirPattern, {\n ignore: ignorePatterns,\n withFileTypes: true,\n dot: true,\n cwd: contextPath,\n })\n dirFiles.forEach((f) => files.set(f.fullpath(), f))\n } else {\n // For files, just add the file\n files.set(file.fullpath(), file)\n }\n }\n\n return Array.from(files.values()).sort()\n}\n\n/**\n * Calculate a hash of files being copied to detect changes for cache invalidation.\n * The hash includes file content, metadata (mode, size), and relative paths.\n * Note: uid, gid, and mtime are excluded to ensure stable hashes across environments.\n *\n * @param src Source path pattern for files to copy\n * @param dest Destination path where files will be copied\n * @param contextPath Base directory for resolving relative paths\n * @param ignorePatterns Glob patterns to ignore\n * @param resolveSymlinks Whether to resolve symbolic links when hashing\n * @param stackTrace Optional stack trace for error reporting\n * @returns Hex string hash of all files\n * @throws Error if no files match the source pattern\n */\nexport async function calculateFilesHash(\n src: string,\n dest: string,\n contextPath: string,\n ignorePatterns: string[],\n resolveSymlinks: boolean,\n stackTrace: string | undefined\n): Promise<string> {\n const srcPath = path.join(contextPath, src)\n const hash = crypto.createHash('sha256')\n const content = `COPY ${src} ${dest}`\n\n hash.update(content)\n\n const files = await getAllFilesInPath(src, contextPath, ignorePatterns, true)\n\n if (files.length === 0) {\n const error = new Error(`No files found in ${srcPath}`)\n if (stackTrace) {\n error.stack = stackTrace\n }\n throw error\n }\n\n // Hash stats - only include stable metadata (mode, size)\n // Exclude uid, gid, and mtime to ensure consistent hashes across environments\n const hashStats = (stats: fs.Stats) => {\n hash.update(stats.mode.toString())\n hash.update(stats.size.toString())\n }\n\n // Process files recursively\n for (const file of files) {\n // Add a relative path to hash calculation\n const relativePath = file.relativePosix()\n hash.update(relativePath)\n\n // Add stat information to hash calculation\n if (file.isSymbolicLink()) {\n // If the symlink is broken, it will return undefined, otherwise it will return a stats object of the target\n const stats = fs.statSync(file.fullpath(), { throwIfNoEntry: false })\n const shouldFollow =\n resolveSymlinks && (stats?.isFile() || stats?.isDirectory())\n\n if (!shouldFollow) {\n const stats = fs.lstatSync(file.fullpath())\n\n hashStats(stats)\n\n const content = fs.readlinkSync(file.fullpath())\n hash.update(content)\n\n continue\n }\n }\n\n const stats = fs.statSync(file.fullpath())\n hashStats(stats)\n\n // Add file content to hash calculation\n if (stats.isFile()) {\n const content = fs.readFileSync(file.fullpath())\n hash.update(new Uint8Array(content))\n }\n }\n\n return hash.digest('hex')\n}\n\n/**\n * Get the caller's stack trace frame at a specific depth.\n *\n * @param depth The depth of the stack trace to retrieve\n * - Levels: caller (e.g., TemplateBase.fromImage) > original caller (e.g., user's template file)\n * @returns The caller frame as a string, or undefined if not available\n */\nexport function getCallerFrame(depth: number): string | undefined {\n const stackTrace = new Error().stack\n if (!stackTrace) {\n return\n }\n\n const lines = stackTrace.split('\\n').slice(1) // Skip the this function (getCallerFrame)\n if (lines.length < depth + 1) {\n return\n }\n\n return lines.slice(depth).join('\\n')\n}\n\n// adopted from https://github.com/sindresorhus/callsites\nexport function callsites(depth: number): NodeJS.CallSite[] {\n const _originalPrepareStackTrace = Error.prepareStackTrace\n try {\n let result: NodeJS.CallSite[] = []\n Error.prepareStackTrace = (_, callSites) => {\n const callSitesWithoutCurrent = callSites.slice(depth)\n result = callSitesWithoutCurrent\n return callSitesWithoutCurrent\n }\n\n new Error().stack\n return result\n } finally {\n Error.prepareStackTrace = _originalPrepareStackTrace\n }\n}\n\n/**\n * Get the directory of the caller at a specific stack depth.\n *\n * @param depth The depth of the stack trace\n * @returns The caller's directory path, or undefined if not available\n */\nexport function getCallerDirectory(depth: number): string | undefined {\n // +1 depth to skip this function (getCallerDirectory)\n const callSites = callsites(depth + 1)\n if (callSites.length === 0) {\n return undefined\n }\n\n let fileName = callSites[0].getFileName()\n if (!fileName) {\n return undefined\n }\n\n // Handle file:// URLs returned by getFileName() in ESM modules\n if (fileName.startsWith('file:')) {\n // we use the dynamic import to avoid bundling node:url for browser compatibility\n // getCallerDirectory method is not called in the browser\n const { fileURLToPath } =\n dynamicRequire<typeof import('node:url')>('node:url')\n fileName = fileURLToPath(fileName)\n }\n\n return path.dirname(fileName)\n}\n\n/**\n * Convert a numeric file mode to a zero-padded octal string.\n *\n * @param mode File mode as a number (e.g., 493 for 0o755)\n * @returns Zero-padded 4-digit octal string (e.g., \"0755\")\n *\n * @example\n * ```ts\n * padOctal(0o755) // Returns \"0755\"\n * padOctal(0o644) // Returns \"0644\"\n * ```\n */\nexport function padOctal(mode: number): string {\n return mode.toString(8).padStart(4, '0')\n}\n\n/**\n * Create a compressed tar stream of files matching a pattern.\n *\n * @param fileName Glob pattern for files to include\n * @param fileContextPath Base directory for resolving file paths\n * @param ignorePatterns Ignore patterns to exclude from the archive\n * @param resolveSymlinks Whether to follow symbolic links\n * @returns A readable stream of the gzipped tar archive\n */\nexport async function tarFileStream(\n fileName: string,\n fileContextPath: string,\n ignorePatterns: string[],\n resolveSymlinks: boolean\n) {\n const { create } = await dynamicImport<typeof import('tar')>('tar')\n\n const allFiles = await getAllFilesInPath(\n fileName,\n fileContextPath,\n ignorePatterns,\n true\n )\n\n const filePaths = allFiles.map((file) => file.relativePosix())\n\n // gzip.portable ensures deterministic gzip header without affecting file modes\n return create(\n {\n gzip: true,\n cwd: fileContextPath,\n follow: resolveSymlinks,\n noDirRecurse: true,\n },\n filePaths\n )\n}\n\n/**\n * Create a tar stream for upload using chunked transfer encoding.\n *\n * @param fileName Glob pattern for files to include\n * @param fileContextPath Base directory for resolving file paths\n * @param resolveSymlinks Whether to follow symbolic links\n * @returns A readable stream of the gzipped tar archive\n */\nexport async function tarFileStreamUpload(\n fileName: string,\n fileContextPath: string,\n ignorePatterns: string[],\n resolveSymlinks: boolean\n) {\n return tarFileStream(\n fileName,\n fileContextPath,\n ignorePatterns,\n resolveSymlinks\n )\n}\n\n/**\n * Get the array index for a build step based on its name.\n *\n * Special steps:\n * - BASE_STEP_NAME: Returns 0 (first step)\n * - FINALIZE_STEP_NAME: Returns the last index\n * - Numeric strings: Converted to number\n *\n * @param step Build step name or number as string\n * @param stackTracesLength Total number of stack traces (used for FINALIZE_STEP_NAME)\n * @returns Index for the build step\n */\nexport function getBuildStepIndex(\n step: string,\n stackTracesLength: number\n): number {\n if (step === BASE_STEP_NAME) {\n return 0\n }\n\n if (step === FINALIZE_STEP_NAME) {\n return stackTracesLength - 1\n }\n\n return Number(step)\n}\n\n/**\n * Read GCP service account JSON from a file or object.\n *\n * @param contextPath Base directory for resolving relative file paths\n * @param pathOrContent Either a path to a JSON file or a service account object\n * @returns Service account JSON as a string\n */\nexport function readGCPServiceAccountJSON(\n contextPath: string,\n pathOrContent: string | object\n): string {\n if (typeof pathOrContent === 'string') {\n return fs.readFileSync(path.join(contextPath, pathOrContent), 'utf-8')\n }\n return JSON.stringify(pathOrContent)\n}\n","import { ApiClient, handleApiError, paths, components } from '../api'\nimport { dynamicImport, stripAnsi } from '../utils'\nimport { BuildError, FileUploadError, TemplateError } from '../errors'\nimport { LogEntry } from './logger'\nimport { getBuildStepIndex, tarFileStreamUpload } from './utils'\nimport {\n BuildStatusReason,\n RegistryConfig,\n TemplateBuildStatus,\n TemplateBuildStatusResponse,\n TemplateTag,\n TemplateTagInfo,\n} from './types'\n\ntype RequestBuildInput = {\n name: string\n tags?: string[]\n cpuCount: number\n memoryMB: number\n}\n\ntype GetFileUploadLinkInput = {\n templateID: string\n filesHash: string\n}\n\ntype TriggerBuildInput = {\n templateID: string\n buildID: string\n template: TriggerBuildTemplate\n}\n\ntype GetBuildStatusInput = {\n templateID: string\n buildID: string\n logsOffset?: number\n}\n\ntype CheckAliasExistsInput = {\n alias: string\n}\n\ntype ApiBuildStatusResponse =\n paths['/templates/{templateID}/builds/{buildID}/status']['get']['responses']['200']['content']['application/json']\n\nexport type TriggerBuildTemplate =\n Omit<\n paths['/v2/templates/{templateID}/builds/{buildID}']['post']['requestBody']['content']['application/json'],\n 'fromImageRegistry'\n > & {\n fromImageRegistry?: RegistryConfig\n preBootScript?: string\n }\n\nexport async function requestBuild(\n client: ApiClient,\n { name, tags, cpuCount, memoryMB }: RequestBuildInput\n) {\n const requestBuildRes = await client.api.POST('/v3/templates', {\n body: {\n name,\n tags,\n cpuCount,\n memoryMB,\n },\n })\n\n const error = handleApiError(requestBuildRes, BuildError)\n if (error) {\n throw error\n }\n\n if (!requestBuildRes.data) {\n throw new BuildError('Failed to request build')\n }\n\n return requestBuildRes.data\n}\n\nexport async function getFileUploadLink(\n client: ApiClient,\n { templateID, filesHash }: GetFileUploadLinkInput,\n stackTrace?: string\n) {\n const fileUploadLinkRes = await client.api.GET(\n '/templates/{templateID}/files/{hash}',\n {\n params: {\n path: {\n templateID,\n hash: filesHash,\n },\n },\n }\n )\n\n const error = handleApiError(fileUploadLinkRes, FileUploadError, stackTrace)\n if (error) {\n throw error\n }\n\n if (!fileUploadLinkRes.data) {\n throw new FileUploadError('Failed to get file upload link', stackTrace)\n }\n\n return fileUploadLinkRes.data\n}\n\nexport async function uploadFile(\n options: {\n fileName: string\n fileContextPath: string\n url: string\n ignorePatterns: string[]\n resolveSymlinks: boolean\n },\n stackTrace: string | undefined\n) {\n const { fileName, url, fileContextPath, ignorePatterns, resolveSymlinks } =\n options\n try {\n const uploadStream = await tarFileStreamUpload(\n fileName,\n fileContextPath,\n ignorePatterns,\n resolveSymlinks\n )\n\n // Buffer the archive before uploading so fetch sets Content-Length.\n // S3 presigned PUT URLs reject Transfer-Encoding: chunked with 501\n // NotImplemented, which is what Node's fetch falls back to when the\n // body is a Readable without a known length. See ppio-dev/ppio#1243.\n // The Python SDK takes the same approach (build_api.py:upload_file).\n // Dynamically import so the browser bundle doesn't pull in node:stream.\n // tar's Pack extends Minipass and is iterable as AsyncIterable<Buffer> at\n // runtime, but the cli's tsconfig (preserveSymlinks) doesn't surface that\n // through the type chain — cast via unknown.\n const { buffer } = await dynamicImport<\n typeof import('node:stream/consumers')\n >('node:stream/consumers')\n const uploadBody = await buffer(\n uploadStream as unknown as AsyncIterable<Buffer>\n )\n\n const res = await fetch(url, {\n method: 'PUT',\n body: uploadBody as unknown as BodyInit,\n })\n\n if (!res.ok) {\n throw new FileUploadError(\n `Failed to upload file: ${res.statusText}`,\n stackTrace\n )\n }\n } catch (error) {\n if (error instanceof FileUploadError) {\n throw error\n }\n throw new FileUploadError(`Failed to upload file: ${error}`, stackTrace)\n }\n}\n\nexport async function triggerBuild(\n client: ApiClient,\n { templateID, buildID, template }: TriggerBuildInput\n) {\n const triggerBuildRes = await client.api.POST(\n '/v2/templates/{templateID}/builds/{buildID}',\n {\n params: {\n path: {\n templateID,\n buildID,\n },\n },\n body: template as paths['/v2/templates/{templateID}/builds/{buildID}']['post']['requestBody']['content']['application/json'],\n }\n )\n\n const error = handleApiError(triggerBuildRes, BuildError)\n if (error) {\n throw error\n }\n}\n\nfunction mapLogEntry(\n entry: ApiBuildStatusResponse['logEntries'][number]\n): LogEntry {\n return new LogEntry(new Date(entry.timestamp), entry.level, entry.message)\n}\n\nfunction mapBuildStatusReason(\n reason: ApiBuildStatusResponse['reason']\n): BuildStatusReason | undefined {\n if (!reason) {\n return undefined\n }\n return {\n message: reason.message,\n step: reason.step,\n logEntries: (reason.logEntries ?? []).map(mapLogEntry),\n }\n}\n\nexport async function getBuildStatus(\n client: ApiClient,\n { templateID, buildID, logsOffset }: GetBuildStatusInput\n): Promise<TemplateBuildStatusResponse> {\n const buildStatusRes = await client.api.GET(\n '/templates/{templateID}/builds/{buildID}/status',\n {\n params: {\n path: {\n templateID,\n buildID,\n },\n query: {\n logsOffset,\n },\n },\n }\n )\n\n const error = handleApiError(buildStatusRes, BuildError)\n if (error) {\n throw error\n }\n\n if (!buildStatusRes.data) {\n throw new BuildError('Failed to get build status')\n }\n\n return {\n buildID: buildStatusRes.data.buildID,\n templateID: buildStatusRes.data.templateID,\n status: buildStatusRes.data.status,\n logEntries: buildStatusRes.data.logEntries.map(mapLogEntry),\n logs: buildStatusRes.data.logs,\n reason: mapBuildStatusReason(buildStatusRes.data.reason),\n }\n}\n\nexport async function checkAliasExists(\n client: ApiClient,\n { alias }: CheckAliasExistsInput\n): Promise<boolean> {\n const aliasRes = await client.api.GET('/templates/aliases/{alias}', {\n params: {\n path: {\n alias,\n },\n },\n })\n\n // If we get a NotFound, the alias doesn't exist\n if (aliasRes.response.status === 404) {\n return false\n }\n\n // If we get a Forbidden, alias exists, but you are not owner\n if (aliasRes.response.status === 403) {\n return true\n }\n\n // Handle other errors\n const error = handleApiError(aliasRes, TemplateError)\n if (error) {\n throw error\n }\n\n // If we get Ok with data, you are owner and the alias exists\n return aliasRes.data !== undefined\n}\n\nexport async function waitForBuildFinish(\n client: ApiClient,\n {\n templateID,\n buildID,\n onBuildLogs,\n logsRefreshFrequency,\n stackTraces,\n }: {\n templateID: string\n buildID: string\n onBuildLogs?: (logEntry: LogEntry) => void\n logsRefreshFrequency: number\n stackTraces: (string | undefined)[]\n }\n): Promise<void> {\n let logsOffset = 0\n let status: TemplateBuildStatus = 'building'\n\n while (status === 'building' || status === 'waiting') {\n const buildStatus = await getBuildStatus(client, {\n templateID,\n buildID,\n logsOffset,\n })\n\n logsOffset += buildStatus.logEntries.length\n\n buildStatus.logEntries.forEach((logEntry) =>\n onBuildLogs?.(\n new LogEntry(\n logEntry.timestamp,\n logEntry.level,\n stripAnsi(logEntry.message)\n )\n )\n )\n\n status = buildStatus.status\n switch (status) {\n case 'ready': {\n return\n }\n case 'waiting': {\n break\n }\n case 'error': {\n let stackError: string | undefined\n if (buildStatus.reason?.step !== undefined) {\n const step = getBuildStepIndex(\n buildStatus.reason.step,\n stackTraces.length\n )\n stackError = stackTraces[step]\n }\n\n throw new BuildError(\n buildStatus?.reason?.message ?? 'Unknown error',\n stackError\n )\n }\n }\n\n // Wait for a short period before checking the status again\n await new Promise((resolve) => setTimeout(resolve, logsRefreshFrequency))\n }\n\n throw new BuildError('Unknown build error occurred.')\n}\n\nexport async function assignTags(\n client: ApiClient,\n { targetName, tags }: { targetName: string; tags: string[] }\n): Promise<TemplateTagInfo> {\n const res = await client.api.POST('/templates/tags', {\n body: { target: targetName, tags },\n })\n\n const error = handleApiError(res, TemplateError)\n if (error) {\n throw error\n }\n\n if (!res.data) {\n throw new TemplateError('Failed to assign tags')\n }\n\n return {\n buildId: res.data.buildID,\n tags: res.data.tags,\n }\n}\n\nexport async function removeTags(\n client: ApiClient,\n { name, tags }: { name: string; tags: string[] }\n): Promise<void> {\n const res = await client.api.DELETE('/templates/tags', {\n body: { name, tags },\n })\n\n const error = handleApiError(res, TemplateError)\n if (error) {\n throw error\n }\n}\n\nexport async function getTemplateTags(\n client: ApiClient,\n { templateID }: { templateID: string }\n): Promise<TemplateTag[]> {\n const res = await client.api.GET('/templates/{templateID}/tags', {\n params: {\n path: {\n templateID,\n },\n },\n })\n\n const error = handleApiError(res, TemplateError)\n if (error) {\n throw error\n }\n\n if (!res.data) {\n throw new TemplateError('Failed to get template tags')\n }\n\n return res.data.map((item: components['schemas']['TemplateTag']) => ({\n tag: item.tag,\n buildId: item.buildID,\n createdAt: new Date(item.createdAt),\n }))\n}\n","/**\n * Class for ready check commands.\n */\nexport class ReadyCmd {\n private cmd: string\n\n constructor(cmd: string) {\n this.cmd = cmd\n }\n\n getCmd(): string {\n return this.cmd\n }\n}\n\n/**\n * Wait for a port to be listening.\n * Uses `ss` command to check if a port is open and listening.\n *\n * @param port Port number to wait for\n * @returns ReadyCmd that checks for the port\n *\n * @example\n * ```ts\n * import { Template, waitForPort } from 'ppio-sandbox'\n *\n * const template = Template()\n * .fromPythonImage()\n * .setStartCmd('python -m http.server 8000', waitForPort(8000))\n * ```\n */\nexport function waitForPort(port: number): ReadyCmd {\n const cmd = `ss -tuln | grep :${port}`\n return new ReadyCmd(cmd)\n}\n\n/**\n * Wait for a URL to return a specific HTTP status code.\n * Uses `curl` to make HTTP requests and check the response status.\n *\n * @param url URL to check (e.g., 'http://localhost:3000/health')\n * @param statusCode Expected HTTP status code (default: 200)\n * @returns ReadyCmd that checks the URL\n *\n * @example\n * ```ts\n * import { Template, waitForURL } from 'ppio-sandbox'\n *\n * const template = Template()\n * .fromNodeImage()\n * .setStartCmd('npm start', waitForURL('http://localhost:3000/health'))\n * ```\n */\nexport function waitForURL(url: string, statusCode: number = 200): ReadyCmd {\n const cmd = `curl -s -o /dev/null -w \"%{http_code}\" ${url} | grep -q \"${statusCode}\"`\n return new ReadyCmd(cmd)\n}\n\n/**\n * Wait for a process with a specific name to be running.\n * Uses `pgrep` to check if a process exists.\n *\n * @param processName Name of the process to wait for\n * @returns ReadyCmd that checks for the process\n *\n * @example\n * ```ts\n * import { Template, waitForProcess } from 'ppio-sandbox'\n *\n * const template = Template()\n * .fromBaseImage()\n * .setStartCmd('./my-daemon', waitForProcess('my-daemon'))\n * ```\n */\nexport function waitForProcess(processName: string): ReadyCmd {\n const cmd = `pgrep ${processName} > /dev/null`\n return new ReadyCmd(cmd)\n}\n\n/**\n * Wait for a file to exist.\n * Uses shell test command to check file existence.\n *\n * @param filename Path to the file to wait for\n * @returns ReadyCmd that checks for the file\n *\n * @example\n * ```ts\n * import { Template, waitForFile } from 'ppio-sandbox'\n *\n * const template = Template()\n * .fromBaseImage()\n * .setStartCmd('./init.sh', waitForFile('/tmp/ready'))\n * ```\n */\nexport function waitForFile(filename: string): ReadyCmd {\n const cmd = `[ -f ${filename} ]`\n return new ReadyCmd(cmd)\n}\n\n/**\n * Wait for a specified timeout before considering the sandbox ready.\n * Uses `sleep` command to wait for a fixed duration.\n *\n * @param timeout Time to wait in milliseconds (minimum: 1000ms / 1 second)\n * @returns ReadyCmd that waits for the specified duration\n *\n * @example\n * ```ts\n * import { Template, waitForTimeout } from 'ppio-sandbox'\n *\n * const template = Template()\n * .fromNodeImage()\n * .setStartCmd('npm start', waitForTimeout(5000)) // Wait 5 seconds\n * ```\n */\nexport function waitForTimeout(timeout: number): ReadyCmd {\n // convert to seconds, but ensure minimum of 1 second\n const seconds = Math.max(1, Math.floor(timeout / 1000))\n const cmd = `sleep ${seconds}`\n return new ReadyCmd(cmd)\n}\n","import { CopyItem } from './types'\nimport {\n Argument,\n DockerfileParser,\n Instruction as DockerfileInstruction,\n ModifiableInstruction,\n} from 'dockerfile-ast'\nimport fs from 'node:fs'\nimport { ReadyCmd, waitForTimeout } from './readycmd'\n\nexport interface DockerfileParseResult {\n baseImage: string\n}\n\ninterface DockerfileFinalParserInterface {}\n\nexport interface DockerfileParserInterface {\n setWorkdir(workdir: string): DockerfileParserInterface\n setUser(user: string): DockerfileParserInterface\n setEnvs(envs: Record<string, string>): DockerfileParserInterface\n runCmd(\n commandOrCommands: string | string[],\n options?: { user?: string }\n ): DockerfileParserInterface\n copy(\n src: string,\n dest: string,\n options?: { forceUpload?: true; user?: string; mode?: number }\n ): DockerfileParserInterface\n copyItems(\n items: CopyItem[],\n options?: { forceUpload?: true; user?: string; mode?: number }\n ): DockerfileParserInterface\n setStartCmd(\n startCommand: string,\n readyCommand: string | ReadyCmd\n ): DockerfileFinalParserInterface\n}\n\n/**\n * Parse a Dockerfile and convert it to Template SDK format\n *\n * @param dockerfileContentOrPath Either the Dockerfile content as a string,\n * or a path to a Dockerfile file\n * @param templateBuilder Interface providing template builder methods\n * @returns Parsed Dockerfile result with base image and instructions\n */\nexport function parseDockerfile(\n dockerfileContentOrPath: string,\n templateBuilder: DockerfileParserInterface\n): DockerfileParseResult {\n // Check if input is a file path that exists\n let dockerfileContent: string\n try {\n if (\n fs.existsSync(dockerfileContentOrPath) &&\n fs.statSync(dockerfileContentOrPath).isFile()\n ) {\n // Read the file content\n dockerfileContent = fs.readFileSync(dockerfileContentOrPath, 'utf-8')\n } else {\n // Treat as content directly\n dockerfileContent = dockerfileContentOrPath\n }\n } catch {\n // If there's any error checking the file, treat as content\n dockerfileContent = dockerfileContentOrPath\n }\n\n const dockerfile = DockerfileParser.parse(dockerfileContent)\n const instructions = dockerfile.getInstructions()\n\n // Check for multi-stage builds\n const fromInstructions = instructions.filter(\n (instruction) => instruction.getKeyword() === 'FROM'\n )\n\n if (fromInstructions.length > 1) {\n throw new Error('Multi-stage Dockerfiles are not supported')\n }\n\n if (fromInstructions.length === 0) {\n throw new Error('Dockerfile must contain a FROM instruction')\n }\n\n // Set the base image from the first FROM instruction\n const fromInstruction = fromInstructions[0]\n const argumentsData = fromInstruction.getArguments()\n let baseImage = 'ppio-sandbox/base' // default fallback\n let userChanged = false\n let workdirChanged = false\n if (argumentsData && argumentsData.length > 0) {\n baseImage = argumentsData[0].getValue()\n }\n\n // Set the user and workdir to the Docker defaults\n templateBuilder.setUser('root')\n templateBuilder.setWorkdir('/')\n\n // Process all other instructions\n for (const instruction of instructions) {\n const keyword = instruction.getKeyword()\n\n switch (keyword) {\n case 'FROM':\n // Already handled above\n break\n\n case 'RUN':\n handleRunInstruction(instruction, templateBuilder)\n break\n\n case 'COPY':\n case 'ADD':\n handleCopyInstruction(\n instruction as ModifiableInstruction,\n templateBuilder\n )\n break\n\n case 'WORKDIR':\n handleWorkdirInstruction(instruction, templateBuilder)\n workdirChanged = true\n break\n\n case 'USER':\n handleUserInstruction(instruction, templateBuilder)\n userChanged = true\n break\n\n case 'ENV':\n case 'ARG':\n handleEnvInstruction(instruction, templateBuilder)\n break\n\n case 'EXPOSE':\n // EXPOSE is not directly supported in our SDK, so we'll skip it\n break\n\n case 'VOLUME':\n // VOLUME is not directly supported in our SDK, so we'll skip it\n break\n\n case 'CMD':\n case 'ENTRYPOINT':\n handleCmdEntrypointInstruction(instruction, templateBuilder)\n break\n\n default:\n console.warn(`Unsupported instruction: ${keyword}`)\n break\n }\n }\n\n // Set the user and workdir to the PPIO sandbox defaults\n if (!userChanged) {\n templateBuilder.setUser('user')\n }\n if (!workdirChanged) {\n templateBuilder.setWorkdir('/home/user')\n }\n\n return {\n baseImage,\n }\n}\n\nfunction handleRunInstruction(\n instruction: DockerfileInstruction,\n templateBuilder: DockerfileParserInterface\n): void {\n const argumentsData = instruction.getArguments()\n if (argumentsData && argumentsData.length > 0) {\n const command = argumentsData\n .map((arg: Argument) => arg.getValue())\n .join(' ')\n templateBuilder.runCmd(command)\n }\n}\n\nfunction handleCopyInstruction(\n instruction: ModifiableInstruction,\n templateBuilder: DockerfileParserInterface\n): void {\n const argumentsData = instruction.getArguments()\n if (argumentsData && argumentsData.length >= 2) {\n const src = argumentsData[0].getValue()\n const dest = argumentsData[argumentsData.length - 1].getValue()\n\n let user: string | undefined\n const flags = instruction.getFlags()\n const chownFlag = flags.find((flag) => flag.getName() === 'chown')\n if (chownFlag) {\n user = chownFlag.getValue() ?? undefined\n }\n\n templateBuilder.copy(src, dest, { user })\n }\n}\n\nfunction handleWorkdirInstruction(\n instruction: DockerfileInstruction,\n templateBuilder: DockerfileParserInterface\n): void {\n const argumentsData = instruction.getArguments()\n if (argumentsData && argumentsData.length > 0) {\n const workdir = argumentsData[0].getValue()\n templateBuilder.setWorkdir(workdir)\n }\n}\n\nfunction handleUserInstruction(\n instruction: DockerfileInstruction,\n templateBuilder: DockerfileParserInterface\n): void {\n const argumentsData = instruction.getArguments()\n if (argumentsData && argumentsData.length > 0) {\n const user = argumentsData[0].getValue()\n templateBuilder.setUser(user)\n }\n}\n\nfunction handleEnvInstruction(\n instruction: DockerfileInstruction,\n templateBuilder: DockerfileParserInterface\n): void {\n const argumentsData = instruction.getArguments()\n const keyword = instruction.getKeyword()\n\n if (argumentsData && argumentsData.length >= 1) {\n const envVars: Record<string, string> = {}\n\n if (argumentsData.length === 2) {\n // ENV key value format OR multiple key=value pairs (from line continuation)\n const firstArg = argumentsData[0].getValue()\n const secondArg = argumentsData[1].getValue()\n\n // Check if both arguments contain '=' (multiple key=value pairs)\n if (firstArg.includes('=') && secondArg.includes('=')) {\n // Both are key=value pairs (line continuation)\n for (const arg of argumentsData) {\n const envString = arg.getValue()\n const equalIndex = envString.indexOf('=')\n if (equalIndex > 0) {\n const key = envString.substring(0, equalIndex)\n const value = envString.substring(equalIndex + 1)\n envVars[key] = value\n }\n }\n } else {\n // Traditional ENV key value format\n envVars[firstArg] = secondArg\n }\n } else if (argumentsData.length === 1) {\n // ENV/ARG key=value format (single argument) or ARG key (without default)\n const envString = argumentsData[0].getValue()\n\n // Check if it's a simple key=value or just a key (for ARG without default)\n const equalIndex = envString.indexOf('=')\n if (equalIndex > 0) {\n const key = envString.substring(0, equalIndex)\n const value = envString.substring(equalIndex + 1)\n envVars[key] = value\n } else if (keyword === 'ARG' && envString.trim()) {\n // ARG without default value - set as empty ENV\n const key = envString.trim()\n envVars[key] = ''\n }\n } else {\n // Multiple arguments (from line continuation with backslashes)\n for (const arg of argumentsData) {\n const envString = arg.getValue()\n const equalIndex = envString.indexOf('=')\n if (equalIndex > 0) {\n const key = envString.substring(0, equalIndex)\n const value = envString.substring(equalIndex + 1)\n envVars[key] = value\n } else if (keyword === 'ARG') {\n // ARG without default value\n const key = envString\n envVars[key] = ''\n }\n }\n }\n\n // Call setEnvs once with all environment variables from this instruction\n if (Object.keys(envVars).length > 0) {\n templateBuilder.setEnvs(envVars)\n }\n }\n}\n\nfunction handleCmdEntrypointInstruction(\n instruction: DockerfileInstruction,\n templateBuilder: DockerfileParserInterface\n): void {\n const argumentsData = instruction.getArguments()\n if (argumentsData && argumentsData.length > 0) {\n let command = argumentsData.map((arg: Argument) => arg.getValue()).join(' ')\n\n try {\n const parsedCommand = JSON.parse(command)\n if (Array.isArray(parsedCommand)) {\n command = parsedCommand.join(' ')\n }\n } catch {\n // Do nothing\n }\n\n templateBuilder.setStartCmd(command, waitForTimeout(20_000))\n }\n}\n","/**\n * Make a template's environment variables visible at *runtime*, not just at\n * build time.\n *\n * `setEnvs` records an ENV instruction. Two things were measured about it, and\n * neither reports an error:\n *\n * **The build's ENV does not reach the sandbox.** Template\n * `wu9ol3m99x5h2d9y63rc`, built from a Dockerfile declaring\n * `ENV PATH=/opt/venv/bin:$PATH`:\n *\n * build log [builder 4/8] ENV PATH /opt/venv/bin:$PATH (layer created)\n * sandbox PATH=/usr/local/bin:/usr/bin:/bin:... (venv absent)\n * which python3 /usr/local/bin/python3 (not the venv)\n * import requests -> exit 1 (installed, unreachable)\n *\n * A login shell and `sh -c` saw the same thing, and `/etc/environment` was empty.\n * So the environment is written to the filesystem, where the sandbox's own shell\n * startup reads it back — twice, because neither file covers both cases:\n *\n * /etc/profile.d/99-image-env.sh sourced by login shells\n * /etc/environment read by pam_env, covers non-login execution\n *\n * **The platform silently ignores an ENV instruction for PATH.** Template\n * `s9kk2s1dhfgcqmf94785` set `PATH=/opt/venv/bin:$PATH` and `PROBE_LITERAL=x` in\n * one instruction; the next build step reported\n *\n * SEEN_PATH=[/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin]\n * SEEN_LITERAL=[x]\n *\n * — PATH untouched, not even holding a literal `$PATH`, while the other variable\n * took effect. So the value cannot simply be read back out of the build\n * environment: for PATH, that reads the platform's own value, and PATH is where a\n * venv or conda prefix lives — the case this exists to fix.\n *\n * The declared string is therefore carried into the build and its variable\n * references are expanded *there*, against the build's live environment. Writing\n * the declared string verbatim instead breaks the build outright:\n *\n * [builder 9/9] RUN ... export PATH='/opt/venv/bin:$PATH' ... (step ok)\n * [finalize] Build failed: configuration script failed: exit status 127\n *\n * PATH held a literal `$PATH`, so the next command was not found.\n */\n\n/** Where the login-shell copy is written. */\nexport const PROFILE_PATH = '/etc/profile.d/99-image-env.sh'\n\n/** Where the pam_env copy is written. */\nexport const ENVIRONMENT_PATH = '/etc/environment'\n\n/** Where the generated script is staged during the build. */\nexport const SCRIPT_PATH = '/tmp/.ppio-image-env.sh'\n\n/**\n * True when no shell can set this name, so it cannot be restored at runtime.\n *\n * `export A B='v'` is two statements, so carrying over a name with a space in it\n * would set something other than what was asked for. Reported rather than\n * written, so a caller is not told a variable survived when it did not.\n */\nexport function unsettableEnvName(name: string): boolean {\n return !/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)\n}\n\n/**\n * Split names into the ones that can be restored and the ones that cannot.\n * `skipped` is sorted, so callers report a stable order.\n */\nexport function partitionEnvNames(names: string[]): {\n usable: string[]\n skipped: string[]\n} {\n const usable: string[] = []\n const skipped: string[] = []\n for (const name of names) {\n if (unsettableEnvName(name)) {\n skipped.push(name)\n } else {\n usable.push(name)\n }\n }\n return { usable, skipped: skipped.sort() }\n}\n\n/**\n * Quote a declared value for the generated script, leaving `$VAR` live.\n *\n * The value is emitted inside a double-quoted shell word, so `$VAR` and `${VAR}`\n * expand against the build's environment — which is the whole point, since\n * `/opt/venv/bin:$PATH` only means anything there.\n *\n * Backticks, `$(`, `\"` and `\\` are escaped, so a value cannot run a command or\n * end the word. Command substitution is deliberately *not* honoured: a value is\n * data, and `PATH=$(curl …)` executing during someone else's build is not a\n * feature. Docker expands only variable references here too.\n */\nexport function expandableDoubleQuote(value: string): string {\n const escaped = value\n // Backslash first, so the escapes added below are not re-escaped.\n .split('\\\\')\n .join('\\\\\\\\')\n .split('\"')\n .join('\\\\\"')\n .split('`')\n .join('\\\\`')\n // `$(` would be command substitution; `$NAME` and `${NAME}` stay live.\n .replace(/\\$\\(/g, '\\\\$(')\n return `\"${escaped}\"`\n}\n\n/**\n * The shell script that writes both files.\n *\n * Runs during the build. For each variable it expands the declared value against\n * the build's live environment, then writes the result to both files — quoted\n * *differently*, which is why this is not one write:\n *\n * - profile.d is sourced by a shell, so the expanded value is single-quoted with\n * `'` rewritten as `'\\''`. Single quotes are the only shell quoting with no\n * escapes inside them, so this is exact for any byte — including `$`, backticks\n * and backslashes, all of which `\"…\"` would interpret. Writing `KEY=\"value\"`\n * here is a green that hides a wrong value: the build succeeds, the sandbox\n * boots, and `JAVA_OPTS=-Xmx2g -Dname=\"my app\"` holds something else.\n * - /etc/environment is read by pam_env, which has no escape syntax at all. It\n * strips one leading and one trailing quote without scanning the interior, so\n * the value is written bare; and it is line-based with no continuation, so a\n * value containing a newline cannot be represented there and is left to the\n * profile.d copy rather than written as a corrupt second entry.\n *\n * @param envs Settable names mapped to their declared values — see\n * {@link partitionEnvNames}.\n */\nexport function envFilesScript(envs: Record<string, string>): string {\n const lines = [\n 'set -e',\n `: > ${PROFILE_PATH}`,\n `: > ${ENVIRONMENT_PATH}`,\n ]\n\n for (const [name, declared] of Object.entries(envs)) {\n lines.push(\n // Expand the declared value here, against the build's own environment.\n `v=${expandableDoubleQuote(declared)}`,\n // Export it before moving on, so a later value can reference this one --\n // `ENV VIRTUAL_ENV=/opt/venv PYTHONPATH=$VIRTUAL_ENV/lib` is ordinary, and\n // the platform's own ENV handling cannot be relied on for it (it ignores\n // PATH entirely). Without this the reference expanded to empty.\n `export ${name}=\"$v\"`,\n // profile.d: single-quoted, with any embedded quote closed and reopened.\n `printf \"export ${name}='%s'\\\\n\" \"$(printf '%s' \"$v\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\")\" >> ${PROFILE_PATH}`,\n // pam_env: bare, and only when it can represent the value at all.\n 'case \"$v\" in',\n ' *\\'\"\\'*) v= ;;',\n 'esac',\n `[ -n \"$v\" ] && [ \"$(printf '%s' \"$v\" | wc -l)\" -eq 0 ] && printf '${name}=%s\\\\n' \"$v\" >> ${ENVIRONMENT_PATH}`,\n // `[ ... ] &&` above exits non-zero when the value is skipped, which would\n // abort the script under `set -e`.\n 'true'\n )\n }\n\n lines.push(`chmod 0644 ${PROFILE_PATH} ${ENVIRONMENT_PATH}`)\n return lines.join('\\n')\n}\n\n/**\n * The single build command that stages and runs {@link envFilesScript}.\n *\n * base64 rather than passing the script inline: it travels through the build's\n * own shell before anything reads it, and base64 is the only form that survives\n * that leg intact regardless of what it contains.\n *\n * Must run as root: the Dockerfile parser leaves the build as `user` (measured:\n * `[builder 7/8] USER user`), which cannot write to `/etc`.\n *\n * `command` is null when no name can be carried over, so the caller adds no\n * layer at all.\n */\nexport function envFilesCommand(envs: Record<string, string>): {\n command: string | null\n skipped: string[]\n} {\n const { usable, skipped } = partitionEnvNames(Object.keys(envs))\n if (usable.length === 0) {\n return { command: null, skipped }\n }\n\n const script = envFilesScript(\n Object.fromEntries(usable.map(name => [name, envs[name]]))\n )\n const b64 = Buffer.from(script, 'utf8').toString('base64')\n\n return {\n command: [\n `echo ${b64} | base64 -d > ${SCRIPT_PATH}`,\n `sh ${SCRIPT_PATH}`,\n `rm -f ${SCRIPT_PATH}`,\n ].join(' && '),\n skipped,\n }\n}\n","/**\n * Read a Docker image's declared ENV, WORKDIR, ENTRYPOINT and CMD from its\n * registry config blob.\n *\n * Why this exists: `docker run <image>` inherits everything the image declares in\n * its config — PATH, LANG, VIRTUAL_ENV, CONDA_PREFIX, JAVA_HOME, and whatever the\n * language ecosystem stores there. A sandbox started from a template built with\n * `fromImage` does not, because nothing ever read the image's config: `fromImage`\n * records the reference and the platform pulls the image server-side. So an image\n * that \"works in Docker\" can land in a sandbox where the preinstalled toolchain\n * is not on PATH at all, with no error that points at the cause.\n *\n * Anonymous registry v2 pulls, falling back to Docker Hub for bare names. Results\n * are cached per process. Every failure is reported as data rather than thrown —\n * a template without the restored config still builds, and one unreachable\n * registry must not abort a batch conversion.\n */\n\n/**\n * The host `parseImageRef` normalises every Docker Hub spelling to, and the\n * prefix it gives a bare name.\n */\nconst HUB_HOST = 'registry-1.docker.io'\nconst HUB_OFFICIAL = 'library/'\n\nconst MANIFEST_TYPES = [\n 'application/vnd.docker.distribution.manifest.v2+json',\n 'application/vnd.oci.image.manifest.v1+json',\n 'application/vnd.docker.distribution.manifest.list.v2+json',\n 'application/vnd.oci.image.index.v1+json',\n].join(', ')\n\n/**\n * ENV vars describing the *build* machine, or that would fight the sandbox's own\n * runtime setup. Carrying these over can actively break a sandbox, so they never\n * do — even when the image declares them.\n */\nconst SKIP_ENV = new Set([\n 'HOSTNAME',\n 'HOME',\n 'PWD',\n 'OLDPWD',\n 'SHLVL',\n '_',\n 'TERM',\n])\n\n/**\n * Registry failures worth another attempt. 429 is the one that matters: Docker\n * Hub's anonymous pull limit is per-IP, so converting a hundred images hits it\n * routinely — and the consequence is not a failed conversion but a template built\n * with no restored ENV, which is the one thing this exists to prevent.\n */\nconst RETRY_STATUS = new Set([429, 500, 502, 503, 504])\nexport const READ_ATTEMPTS = 3\n\n/**\n * Backoff base, in milliseconds. Overridable only so a unit test can assert the\n * retry behaviour without spending the real three seconds waiting for it.\n */\nlet backoffBaseMs = 1000\n\n/** Set the backoff base; returns a function restoring the previous value. */\nexport function setRetryBackoffForTests(ms: number): () => void {\n const previous = backoffBaseMs\n backoffBaseMs = ms\n return () => {\n backoffBaseMs = previous\n }\n}\n\n/**\n * Whether the platform can provision a sandbox from this image's base OS.\n *\n * Measured, one template per image:\n *\n * debian:12, ubuntu:22.04, python:3.11-slim, redis:7 ready\n * alpine:3.20, nginx:alpine, node:20-alpine provisioning exit 1\n * busybox:1.36, fedora:40, rockylinux:9 provisioning exit 1\n *\n * So the line is not \"Debian\": Ubuntu builds. It is apt and glibc -- the platform\n * installs systemd during provisioning, which needs both.\n *\n * The check is deliberately one-directional. `ubuntu:22.04` builds and its config\n * blob carries *no* signal at all (one `ADD`, no labels, no distro-specific ENV),\n * while `rockylinux:9`'s blob is shaped identically and does not build. Absence of\n * evidence therefore cannot mean \"unsupported\" without rejecting images that\n * work, so this reports only what it can positively identify and says nothing\n * about the rest. The build is the backstop for those.\n *\n * apt evidence wins over everything: an image assembled from an Alpine stage but\n * based on Debian has both, and the apt one is what provisioning needs.\n *\n * @returns the unsupported family, or null when the image looks fine or unknown.\n */\nexport function unsupportedBase(blob: {\n history?: { created_by?: string }[]\n config?: { Labels?: Record<string, string>; Env?: string[] }\n}): string | null {\n const history = (blob.history ?? []).map(h => h.created_by ?? '').join('\\n')\n const labels = Object.keys(blob.config?.Labels ?? {}).join(' ')\n const env = (blob.config?.Env ?? []).join(' ')\n\n // `debian.sh` is how the official Debian rootfs is built; `debuerreotype` is\n // its older name. A bare mention of \"debian\" is not evidence: busybox:1.36\n // reports \"BusyBox 1.36.1 (glibc), Debian 13\" and cannot be provisioned.\n if (/debian\\.sh|debuerreotype|apt-get|apt install|dpkg/i.test(history)) {\n return null\n }\n\n const families: [RegExp, string][] = [\n [/alpine-minirootfs|etc\\/alpine-release|apk add|apk --no-cache/i, 'Alpine (musl)'],\n [/^BusyBox /im, 'BusyBox'],\n [/microdnf|dnf install|yum install|rpm -i/i, 'RPM-based (Fedora/RHEL/Rocky)'],\n [/pacman -S/i, 'Arch'],\n [/zypper|KIWI /i, 'SUSE'],\n ]\n for (const [pattern, family] of families) {\n if (pattern.test(history)) {\n return family\n }\n }\n\n // Signals outside the history: openSUSE stamps its own label namespace, and\n // Fedora sets DISTTAG in ENV. Both images build nothing here.\n if (/org\\.opensuse\\./.test(labels)) {\n return 'SUSE'\n }\n if (/DISTTAG=f\\d+container/.test(env)) {\n return 'RPM-based (Fedora/RHEL/Rocky)'\n }\n\n return null\n}\n\n/** What the image declares, plus why the read failed when it did. */\nexport type ImageConfig = {\n env: Record<string, string>\n workdir: string | null\n entrypoint: string[]\n cmd: string[]\n /** Set when the config could not be read at all. */\n error?: string\n /**\n * Set when the image's base OS cannot be provisioned -- see\n * {@link unsupportedBase}. Kept apart from `unusable`: the reference is fine\n * and the image exists, it is the base the platform cannot boot.\n */\n unsupportedBase?: string\n /**\n * Set when the image was read fine and still cannot be used here — no\n * linux/amd64 variant, or the reference names nothing. Distinct from `error`\n * because a retry cannot change it and the build would fail for the same\n * reason after minutes of pulling.\n */\n unusable?: string\n}\n\nexport type RegistryCredentials = { username: string; password: string }\n\nconst CACHE = new Map<string, ImageConfig>()\n\n/** A caller-owned copy, so one caller's edit cannot reach the next. */\nfunction copyConfig(config: ImageConfig): ImageConfig {\n return {\n ...config,\n env: { ...config.env },\n entrypoint: [...config.entrypoint],\n cmd: [...config.cmd],\n }\n}\n\nfunction emptyConfig(): ImageConfig {\n return { env: {}, workdir: null, entrypoint: [], cmd: [] }\n}\n\n/**\n * Split an image reference into its registry host, repository and tag or digest.\n *\n * 'nginx' -> registry-1.docker.io, library/nginx, latest\n * 'org/app:1.2' -> registry-1.docker.io, org/app, 1.2\n * 'ghcr.io/org/app:dev' -> ghcr.io, org/app, dev\n * 'reg:5000/app@sha256:ab…' -> reg:5000, app, sha256:ab…\n */\nexport function parseImageRef(image: string): {\n host: string\n repository: string\n reference: string\n} {\n let ref = image.startsWith('docker.io/')\n ? image.slice('docker.io/'.length)\n : image\n\n let host = HUB_HOST\n const slash = ref.indexOf('/')\n if (slash !== -1) {\n const head = ref.slice(0, slash)\n // A first segment is a registry host only if it looks like one: it contains a\n // dot or a port, or is literally localhost. Otherwise it is a Hub org.\n if (head.includes('.') || head.includes(':') || head === 'localhost') {\n host = head\n ref = ref.slice(slash + 1)\n }\n }\n\n let repository: string\n let reference: string\n const at = ref.indexOf('@')\n if (at !== -1) {\n // Digest pins take precedence: '@' can only introduce a digest.\n repository = ref.slice(0, at)\n reference = ref.slice(at + 1)\n } else {\n const colon = ref.lastIndexOf(':')\n // A ':' inside the final path segment is a tag; one before a '/' is a port.\n if (colon !== -1 && !ref.slice(colon + 1).includes('/')) {\n repository = ref.slice(0, colon)\n reference = ref.slice(colon + 1)\n } else {\n repository = ref\n reference = 'latest'\n }\n }\n\n if (host === HUB_HOST && !repository.includes('/')) {\n repository = `${HUB_OFFICIAL}${repository}`\n }\n\n return { host, repository, reference }\n}\n\n/** An HTTP status carried alongside the failure, so callers can act on it. */\nclass RegistryHttpError extends Error {\n constructor(\n readonly status: number,\n readonly retryAfter: string | null,\n message: string\n ) {\n super(message)\n this.name = 'RegistryHttpError'\n }\n}\n\n/** The image was read successfully and cannot be used here. */\nclass UnusableImageError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'UnusableImageError'\n }\n}\n\n/** Seconds to wait, from the response's Retry-After when it is usable. */\nfunction retryDelayMs(error: unknown, fallbackMs: number): number {\n const raw = error instanceof RegistryHttpError ? error.retryAfter : null\n const seconds = raw === null ? NaN : Number(raw)\n // Retry-After may be an HTTP-date rather than seconds; not worth parsing.\n if (!Number.isFinite(seconds)) {\n return fallbackMs\n }\n return Math.min(seconds * backoffBaseMs, 10_000)\n}\n\n/**\n * GET with a short retry on the statuses a registry uses for \"later\".\n *\n * Deliberately not a general retry: 401/403/404 are answers, not hiccups, and\n * retrying them spends a batch run's time to reach the same conclusion.\n */\nasync function registryGet(\n url: string,\n headers: Record<string, string>,\n options?: { attempts?: number; timeoutMs?: number }\n): Promise<unknown> {\n const attempts = options?.attempts ?? READ_ATTEMPTS\n const timeoutMs = options?.timeoutMs ?? 30_000\n let last: unknown\n\n for (let attempt = 0; attempt < attempts; attempt++) {\n if (attempt > 0) {\n await new Promise(resolve =>\n setTimeout(resolve, retryDelayMs(last, 2 ** (attempt - 1) * backoffBaseMs))\n )\n }\n\n try {\n const response = await fetch(url, {\n headers,\n signal: AbortSignal.timeout(timeoutMs),\n })\n\n if (!response.ok) {\n const error = new RegistryHttpError(\n response.status,\n response.headers.get('retry-after'),\n `HTTP ${response.status} ${response.statusText}`\n )\n if (!RETRY_STATUS.has(response.status)) {\n throw error\n }\n last = error\n continue\n }\n\n return await response.json()\n } catch (error) {\n if (error instanceof RegistryHttpError && !RETRY_STATUS.has(error.status)) {\n throw error\n }\n // Network-level flakiness has no status to inspect; same treatment.\n last = error\n }\n }\n\n throw last\n}\n\n/**\n * Best-effort registry token.\n *\n * Public Docker Hub and GHCR both hand out anonymous pull tokens; private\n * registries take the basic auth through unchanged.\n */\nasync function authHeaders(\n host: string,\n repository: string,\n credentials?: RegistryCredentials\n): Promise<Record<string, string>> {\n const headers: Record<string, string> = { Accept: MANIFEST_TYPES }\n\n if (credentials) {\n const basic = Buffer.from(\n `${credentials.username}:${credentials.password}`,\n 'utf8'\n ).toString('base64')\n headers.Authorization = `Basic ${basic}`\n }\n\n const services: Record<string, [string, string]> = {\n 'registry-1.docker.io': ['auth.docker.io', 'registry.docker.io'],\n 'ghcr.io': ['ghcr.io', 'ghcr.io'],\n }\n const service = services[host]\n if (!service) {\n return headers\n }\n\n const [authHost, serviceName] = service\n const url =\n `https://${authHost}/token?service=${serviceName}` +\n `&scope=repository:${repository}:pull`\n\n try {\n const tokenHeaders: Record<string, string> = headers.Authorization\n ? { Authorization: headers.Authorization }\n : {}\n // One attempt: a failure here falls back to anonymous or basic auth, and the\n // read below has its own retries. Retrying both turned one offline registry\n // into six requests and six seconds of backoff.\n const body = (await registryGet(url, tokenHeaders, {\n attempts: 1,\n })) as { token?: string }\n if (body.token) {\n headers.Authorization = `Bearer ${body.token}`\n }\n } catch {\n // Anonymous or basic auth may already suffice; the read below decides.\n }\n\n return headers\n}\n\nfunction platformName(entry: {\n platform?: { os?: string; architecture?: string; variant?: string }\n}): string {\n const p = entry.platform ?? {}\n const base = `${p.os ?? '?'}/${p.architecture ?? '?'}`\n return p.variant ? `${base}/${p.variant}` : base\n}\n\ntype ManifestIndex = {\n manifests?: {\n digest: string\n platform?: { os?: string; architecture?: string; variant?: string }\n }[]\n}\n\n/**\n * The linux/amd64 digest from a multi-arch index.\n *\n * Throws naming the platforms the image *does* offer. No amd64 variant means the\n * build will fail too, so this is worth catching before a build is spent.\n */\nfunction pickAmd64(index: ManifestIndex, image: string): string {\n for (const entry of index.manifests ?? []) {\n if (\n entry.platform?.architecture === 'amd64' &&\n entry.platform?.os === 'linux'\n ) {\n return entry.digest\n }\n }\n\n // 'unknown/unknown' entries are attestation manifests, not usable images;\n // listing them would suggest a platform that could be selected.\n const offered = [\n ...new Set(\n (index.manifests ?? [])\n .filter(e => e.platform?.os !== 'unknown')\n .map(platformName)\n ),\n ].sort()\n\n throw new UnusableImageError(\n `${image} has no linux/amd64 variant` +\n (offered.length > 0 ? ` (offers ${offered.join(', ')})` : '') +\n '; sandboxes are amd64, so this image cannot be used'\n )\n}\n\n/**\n * Turn a registry failure into the config's `error` / `unusable` fields.\n *\n * The two Docker Hub cases below are measured, and the codes are the opposite way\n * round from the obvious guess:\n *\n * library/redis 200\n * library/REDIS, library/nGiNx 404 (case-folds onto a real repo)\n * library/nginx:no-such-tag 404 (repo exists, tag does not)\n * library/nginxx, library/nginx-typo 401 (no such repo at all)\n *\n * So 404 means \"the repository resolved, the thing you named did not\", and a\n * plain typo — much the commoner mistake — answers 401.\n */\nfunction describeFailure(\n error: unknown,\n image: string,\n host: string,\n repository: string,\n authenticated: boolean\n): ImageConfig {\n const empty = emptyConfig()\n\n if (error instanceof UnusableImageError) {\n return { ...empty, error: error.message, unusable: error.message }\n }\n\n if (error instanceof RegistryHttpError) {\n if (error.status === 404) {\n const reason =\n `no such image: the registry has no '${image}' (HTTP 404). ` +\n 'Check spelling and case — repository names are case-sensitive'\n return { ...empty, error: reason, unusable: reason }\n }\n\n // 401 is normally ambiguous: an absent repository and a private one answer\n // byte-identically. Docker Hub's official `library/` namespace is the\n // exception — it has no private repositories, so nothing there can 401 for a\n // reason other than not existing.\n //\n // Unless credentials were supplied. Then the rejected credential is itself a\n // reason for a 401, and the ambiguity is back: measured, `redis:7` with a wrong\n // password and `rediss:7` with a right one answer identically. So neither cause\n // can be named alone -- blaming the spelling of a correct name, or the\n // credentials behind a correct one, each sends the reader to the wrong place --\n // and this is not marked `unusable`: a corrected password makes the very same\n // reference work, which is the one thing `unusable` promises it will not.\n if (\n error.status === 401 &&\n host === HUB_HOST &&\n repository.startsWith(HUB_OFFICIAL)\n ) {\n if (authenticated) {\n return {\n ...empty,\n error:\n `cannot read '${image}' (HTTP 401): either the credentials were ` +\n 'rejected or there is no such image. Both answer alike here, so ' +\n 'check the spelling and the case of the name, then the credentials',\n }\n }\n const reason =\n `no such image: Docker Hub has no official image '${image}' ` +\n '(HTTP 401). The `library/` namespace has no private repositories, so ' +\n 'this is a typo rather than a permissions problem'\n return { ...empty, error: reason, unusable: reason }\n }\n\n return { ...empty, error: `${error.name}: ${error.message}` }\n }\n\n const message = error instanceof Error ? error.message : String(error)\n return { ...empty, error: message }\n}\n\n/**\n * Read what an image declares.\n *\n * Every field is present even on failure, so a caller never has to distinguish\n * \"no config\" from \"read failed\" structurally — `error` says which it was.\n * Nothing is thrown: restoring an image's config is best-effort, and a batch\n * conversion must not stop because one registry was unreachable.\n */\nexport async function fetchImageConfig(\n image: string,\n credentials?: RegistryCredentials\n): Promise<ImageConfig> {\n // Keyed on the credentials too. An anonymous and an authenticated read of the\n // same private repository are different questions with different answers, so\n // caching only the reference would hand a caller who supplied credentials the\n // anonymous 401 from an earlier call.\n const key = JSON.stringify([\n image,\n credentials?.username ?? null,\n credentials?.password ?? null,\n ])\n const cached = CACHE.get(key)\n if (cached) {\n return copyConfig(cached)\n }\n\n const { host, repository, reference } = parseImageRef(image)\n let result: ImageConfig\n\n try {\n const auth = await authHeaders(host, repository, credentials)\n const base = `https://${host}/v2/${repository}`\n\n let manifest = (await registryGet(\n `${base}/manifests/${reference}`,\n auth\n )) as ManifestIndex & { config?: { digest: string } }\n\n if (manifest.manifests) {\n // Multi-arch index: resolve to the linux/amd64 manifest.\n const digest = pickAmd64(manifest, image)\n manifest = (await registryGet(`${base}/manifests/${digest}`, auth)) as {\n config?: { digest: string }\n }\n }\n\n if (!manifest.config?.digest) {\n throw new Error(`${image}: manifest names no config blob`)\n }\n\n const blob = (await registryGet(\n `${base}/blobs/${manifest.config.digest}`,\n auth\n )) as {\n history?: { created_by?: string }[]\n config?: {\n Env?: string[]\n WorkingDir?: string\n Entrypoint?: string[]\n Cmd?: string[]\n Labels?: Record<string, string>\n }\n }\n\n const declared = blob.config ?? {}\n const env: Record<string, string> = {}\n for (const entry of declared.Env ?? []) {\n const eq = entry.indexOf('=')\n if (eq === -1) {\n continue\n }\n const name = entry.slice(0, eq)\n if (!SKIP_ENV.has(name)) {\n env[name] = entry.slice(eq + 1)\n }\n }\n\n const badBase = unsupportedBase(blob)\n result = {\n env,\n workdir: declared.WorkingDir || null,\n entrypoint: declared.Entrypoint ?? [],\n cmd: declared.Cmd ?? [],\n ...(badBase ? { unsupportedBase: badBase } : {}),\n }\n } catch (error) {\n result = describeFailure(\n error,\n image,\n host,\n repository,\n credentials !== undefined\n )\n }\n\n CACHE.set(key, result)\n return copyConfig(result)\n}\n\n/**\n * Docker's effective command: ENTRYPOINT followed by CMD, joined with spaces.\n *\n * This matches what the SDK's own Dockerfile parser does with the array form, so\n * `docker-entrypoint.sh redis-server` is reproduced exactly. The naive join loses\n * shell quoting for an argument that itself contains spaces (`['sh','-c','echo a\n * b']` becomes `sh -c echo a b`), which is the parser's limitation too; matching\n * it keeps the two build paths in agreement rather than inventing a third\n * behaviour.\n *\n * Returns null when the image declares neither, so the sandbox is left as a bare\n * shell rather than handed an empty command.\n */\nexport function effectiveStartCmd(\n entrypoint: string[],\n cmd: string[]\n): string | null {\n const parts = [...entrypoint, ...cmd]\n return parts.length > 0 ? parts.map(shellQuoteArg).join(' ') : null\n}\n\n/** Quote one exec-form argument for the shell string used by the build API. */\nfunction shellQuoteArg(value: string): string {\n return /^[A-Za-z0-9_./:@%+=,-]+$/.test(value)\n ? value\n : `'${value.replace(/'/g, `'\\\\''`)}'`\n}\n\n/** Drop the process-wide read cache. Exposed for tests. */\nexport function clearImageConfigCache(): void {\n CACHE.clear()\n}\n","import { ReadyCmd } from './readycmd'\nimport type { PathLike } from 'node:fs'\nimport type { LogEntry } from './logger'\nimport type { McpServer } from '../sandbox/mcp'\nimport { ConnectionOpts } from '../connectionConfig'\n\n/**\n * Options for creating a new template.\n */\nexport type TemplateOptions = {\n /**\n * Path to the directory containing files to be copied into the template.\n * @default Current directory from template location\n */\n fileContextPath?: PathLike\n /**\n * Array of glob patterns to ignore when copying files.\n */\n fileIgnorePatterns?: string[]\n}\n\n/**\n * Basic options for building a template.\n */\nexport type BasicBuildOptions = {\n /**\n * Alias name for the template.\n * @deprecated Use the `name` parameter of `Template.build()` instead.\n */\n alias: string\n /**\n * Tags to assign to the template build.\n */\n tags?: string[]\n /**\n * Number of CPUs allocated to the sandbox.\n * @default 2\n */\n cpuCount?: number\n /**\n * Amount of memory in MB allocated to the sandbox.\n * @default 1024\n */\n memoryMB?: number\n /**\n * If true, skips cache and forces a complete rebuild.\n * @default false\n */\n skipCache?: boolean\n /**\n * Callback function to receive build logs during the build process.\n */\n onBuildLogs?: (logEntry: LogEntry) => void\n}\n\n/**\n * Options for building a template with authentication.\n */\nexport type BuildOptions = ConnectionOpts & BasicBuildOptions\n\n/**\n * Information about a built template.\n */\nexport type BuildInfo = {\n /**\n * First alias from the build (for backward compatibility).\n * @deprecated Use `name` instead.\n */\n alias: string\n /**\n * Name of the template.\n */\n name: string\n /**\n * Tags assigned to this build.\n */\n tags: string[]\n /**\n * Template identifier.\n */\n templateId: string\n /**\n * Build identifier.\n */\n buildId: string\n}\n\n/**\n * Options for getting build status.\n */\nexport type GetBuildStatusOptions = ConnectionOpts & { logsOffset?: number }\n\n/**\n * Status of a template build.\n */\nexport type TemplateBuildStatus = 'building' | 'waiting' | 'ready' | 'error'\n\n/**\n * Reason for the current build status (typically for errors).\n */\nexport type BuildStatusReason = {\n /**\n * Message with the status reason.\n */\n message: string\n /**\n * Step that failed.\n */\n step?: string\n /**\n * Log entries related to the status reason.\n */\n logEntries: LogEntry[]\n}\n\n/**\n * Response from getting build status.\n */\nexport type TemplateBuildStatusResponse = {\n /**\n * Build identifier.\n */\n buildID: string\n /**\n * Template identifier.\n */\n templateID: string\n /**\n * Current status of the build.\n */\n status: TemplateBuildStatus\n /**\n * Build log entries.\n */\n logEntries: LogEntry[]\n /**\n * Build logs (raw strings).\n * @deprecated Use `logEntries` instead.\n */\n logs: string[]\n /**\n * Reason for the current status (typically for errors).\n */\n reason?: BuildStatusReason\n}\n\n/**\n * Information about assigned template tags.\n */\nexport type TemplateTagInfo = {\n /**\n * Build identifier associated with this tag.\n */\n buildId: string\n /**\n * Assigned tags of the template.\n */\n tags: string[]\n}\n\n/**\n * Detailed information about a single template tag.\n */\nexport type TemplateTag = {\n /**\n * Name of the tag.\n */\n tag: string\n /**\n * Build identifier associated with this tag.\n */\n buildId: string\n /**\n * When this tag was assigned.\n */\n createdAt: Date\n}\n\nexport type TemplateType = 'template_build' | 'snapshot_template'\n\nexport type TemplateListOpts = ConnectionOpts & {\n teamID?: string\n templateType?: TemplateType\n page?: number\n limit?: number\n}\n\nexport type TemplateListOptions = TemplateListOpts\n\nexport type TemplateInfo = {\n templateId: string\n buildId: string\n aliases?: string[]\n templateType?: TemplateType\n buildCount: number\n cpuCount: number\n memoryMB: number\n diskSizeMB: number\n spawnCount: number\n envdVersion: string\n public: boolean\n metadata?: Record<string, string>\n createdAt: Date\n updatedAt: Date\n lastSpawnedAt: Date | null\n createdBy?: unknown\n originSandboxID?: string | null\n}\n\nexport type TemplateListResponse = {\n templates: TemplateInfo[]\n total: number\n page: number\n limit: number\n totalPages: number\n}\n\nexport type TemplateDeleteOpts = ConnectionOpts\n\n/**\n * Types of instructions that can be used in a template.\n */\nexport enum InstructionType {\n COPY = 'COPY',\n ENV = 'ENV',\n RUN = 'RUN',\n WORKDIR = 'WORKDIR',\n USER = 'USER',\n}\n\n/**\n * Represents a single instruction in the template build process.\n */\nexport type Instruction = {\n type: InstructionType\n args: string[]\n force: boolean\n forceUpload?: true\n filesHash?: string\n resolveSymlinks?: boolean\n}\n\n/**\n * Configuration for a single file/directory copy operation.\n */\nexport type CopyItem = {\n src: PathLike | PathLike[]\n dest: PathLike\n forceUpload?: true\n user?: string\n mode?: number\n resolveSymlinks?: boolean\n}\n\n/**\n * MCP server names that can be installed.\n */\nexport type McpServerName = keyof McpServer\n\n/**\n * Initial state of a template builder.\n * Use one of these methods to specify the base image or template to start from.\n */\nexport interface TemplateFromImage {\n /**\n * Start from a Debian-based Docker image.\n * @param variant Debian variant (default: 'stable')\n *\n * @example\n * ```ts\n * Template().fromDebianImage('bookworm')\n * ```\n */\n fromDebianImage(variant?: string): TemplateBuilder\n\n /**\n * Start from an Ubuntu-based Docker image.\n * @param variant Ubuntu variant (default: 'latest')\n *\n * @example\n * ```ts\n * Template().fromUbuntuImage('24.04')\n * ```\n */\n fromUbuntuImage(variant?: string): TemplateBuilder\n\n /**\n * Start from a Python-based Docker image.\n * @param version Python version (default: '3')\n *\n * @example\n * ```ts\n * Template().fromPythonImage('3')\n * ```\n */\n fromPythonImage(version?: string): TemplateBuilder\n\n /**\n * Start from a Node.js-based Docker image.\n * @param variant Node.js variant (default: 'lts')\n *\n * @example\n * ```ts\n * Template().fromNodeImage('24')\n * ```\n */\n fromNodeImage(variant?: string): TemplateBuilder\n\n /**\n * Start from a Bun-based Docker image.\n * @param variant Bun variant (default: 'latest')\n *\n * @example\n * ```ts\n * Template().fromBunImage('1.3')\n * ```\n */\n fromBunImage(variant?: string): TemplateBuilder\n\n /**\n * Start from PPIO sandbox's default base image (ppio-sandbox/base:latest).\n *\n * @example\n * ```ts\n * Template().fromBaseImage()\n * ```\n */\n fromBaseImage(): TemplateBuilder\n\n /**\n * Start from a custom Docker image.\n * @param baseImage Docker image name\n * @param credentials Optional credentials for private registries\n *\n * @example\n * ```ts\n * Template().fromImage('python:3')\n *\n * // With credentials (optional)\n * Template().fromImage('myregistry.com/myimage:latest', {\n * username: 'user',\n * password: 'pass'\n * })\n * ```\n */\n fromImage(\n baseImage: string,\n credentials?: { username: string; password: string },\n options?: {\n /**\n * Restore what the image declares — its ENV, WORKDIR and effective command\n * (ENTRYPOINT + CMD) — so the sandbox behaves like `docker run <image>`.\n * Defaults to true.\n *\n * Without it, none of the three reach the sandbox: the platform pulls the\n * image server-side and nothing reads its config, so an image whose\n * toolchain lives behind its own `PATH` (a virtualenv, a conda prefix)\n * starts fine and then behaves as though the toolchain were never\n * installed.\n *\n * Anything you set on the builder wins over what the image declared. Pass\n * false to take the image as a bare base — for instance to get an\n * interactive environment rather than the image's own process.\n */\n inheritConfig?: boolean\n }\n ): TemplateBuilder\n\n /**\n * Start from an existing PPIO sandbox template.\n * @param template PPIO sandbox template ID or alias\n *\n * @example\n * ```ts\n * Template().fromTemplate('my-base-template')\n * ```\n */\n fromTemplate(template: string): TemplateBuilder\n\n /**\n * Parse a Dockerfile and convert it to Template SDK format.\n * @param dockerfileContentOrPath Dockerfile content or path\n *\n * @example\n * ```ts\n * Template().fromDockerfile('Dockerfile')\n * Template().fromDockerfile('FROM python:3\\nRUN pip install numpy')\n * ```\n */\n fromDockerfile(dockerfileContentOrPath: string): TemplateBuilder\n\n /**\n * Start from a Docker image in AWS ECR.\n * @param image Full ECR image path\n * @param credentials AWS credentials\n *\n * @example\n * ```ts\n * Template().fromAWSRegistry(\n * '123456789.dkr.ecr.us-west-2.amazonaws.com/myimage:latest',\n * {\n * accessKeyId: 'AKIA...',\n * secretAccessKey: '...',\n * region: 'us-west-2'\n * }\n * )\n * ```\n */\n fromAWSRegistry(\n image: string,\n credentials: {\n accessKeyId: string\n secretAccessKey: string\n region: string\n }\n ): TemplateBuilder\n\n /**\n * Start from a Docker image in Google Container Registry.\n * @param image Full GCR/GAR image path\n * @param credentials GCP service account credentials\n *\n * @example\n * ```ts\n * Template().fromGCPRegistry(\n * 'gcr.io/myproject/myimage:latest',\n * { serviceAccountJSON: 'path/to/service-account.json' }\n * )\n * ```\n */\n fromGCPRegistry(\n image: string,\n credentials: {\n serviceAccountJSON: object | string\n }\n ): TemplateBuilder\n\n /**\n * Start from a Docker image in Oracle Cloud Infrastructure Registry.\n * @param image Full OCI registry image path\n * @param credentials OCI credentials\n *\n * @example\n * ```ts\n * Template().fromOCIRegistry(\n * 'iad.ocir.io/mytenancy/myimage:latest',\n * {\n * tenancyOcid: 'ocid1.tenancy...',\n * userOcid: 'ocid1.user...',\n * fingerprint: '...',\n * privateKey: '-----BEGIN PRIVATE KEY-----...',\n * region: 'us-ashburn-1'\n * }\n * )\n * ```\n */\n fromOCIRegistry(\n image: string,\n credentials: {\n tenancyOcid: string\n userOcid: string\n fingerprint: string\n privateKey: string\n region: string\n }\n ): TemplateBuilder\n\n /**\n * Start from a Docker image in Huawei Cloud SWR.\n * @param image Full Huawei Cloud SWR image path\n * @param credentials Huawei Cloud access key credentials\n *\n * @example\n * ```ts\n * Template().fromHuaweiCloudRegistry(\n * 'swr.cn-north-4.myhuaweicloud.com/myorg/myimage:latest',\n * {\n * accessKeyId: '...',\n * secretAccessKey: '...',\n * region: 'cn-north-4'\n * }\n * )\n * ```\n */\n fromHuaweiCloudRegistry(\n image: string,\n credentials: {\n accessKeyId: string\n secretAccessKey: string\n region: string\n }\n ): TemplateBuilder\n\n /**\n * Skip cache for all subsequent build instructions from this point.\n *\n * @example\n * ```ts\n * Template().skipCache().fromPythonImage('3')\n * ```\n */\n skipCache(): this\n}\n\n/**\n * Main builder state for constructing templates.\n * Provides methods for customizing the template environment.\n */\nexport interface TemplateBuilder {\n /**\n * Copy files or directories into the template.\n * @param src Source path(s)\n * @param dest Destination path\n * @param options Copy options\n *\n * @example\n * ```ts\n * template.copy('requirements.txt', '/home/user/')\n * template.copy(['app.ts', 'config.ts'], '/app/', { mode: 0o755 })\n * ```\n */\n copy(\n src: PathLike | PathLike[],\n dest: PathLike,\n options?: {\n forceUpload?: true\n user?: string\n mode?: number\n resolveSymlinks?: boolean\n }\n ): TemplateBuilder\n\n /**\n * Copy multiple items with individual options.\n * @param items Array of copy items\n *\n * @example\n * ```ts\n * template.copyItems([\n * { src: 'app.ts', dest: '/app/' },\n * { src: 'config.ts', dest: '/app/', mode: 0o644 }\n * ])\n * ```\n */\n copyItems(items: CopyItem[]): TemplateBuilder\n\n /**\n * Remove files or directories.\n * @param path Path(s) to remove\n * @param options Remove options\n *\n * @example\n * ```ts\n * template.remove('/tmp/cache', { recursive: true, force: true })\n * template.remove('/tmp/cache', { recursive: true, force: true, user: 'root' })\n * ```\n */\n remove(\n path: PathLike | PathLike[],\n options?: { force?: boolean; recursive?: boolean; user?: string }\n ): TemplateBuilder\n\n /**\n * Rename or move a file or directory.\n * @param src Source path\n * @param dest Destination path\n * @param options Rename options\n *\n * @example\n * ```ts\n * template.rename('/tmp/old.txt', '/tmp/new.txt')\n * template.rename('/tmp/old.txt', '/tmp/new.txt', { user: 'root' })\n * ```\n */\n rename(\n src: PathLike,\n dest: PathLike,\n options?: { force?: boolean; user?: string }\n ): TemplateBuilder\n\n /**\n * Create directories.\n * @param path Directory path(s)\n * @param options Directory options\n *\n * @example\n * ```ts\n * template.makeDir('/app/data', { mode: 0o755 })\n * template.makeDir(['/app/logs', '/app/cache'])\n * template.makeDir('/app/data', { mode: 0o755, user: 'root' })\n * ```\n */\n makeDir(\n path: PathLike | PathLike[],\n options?: { mode?: number; user?: string }\n ): TemplateBuilder\n\n /**\n * Create a symbolic link.\n * @param src Source path (target)\n * @param dest Destination path (symlink location)\n * @param options Symlink options\n *\n * @example\n * ```ts\n * template.makeSymlink('/usr/bin/python3', '/usr/bin/python')\n * template.makeSymlink('/usr/bin/python3', '/usr/bin/python', { user: 'root' })\n * template.makeSymlink('/usr/bin/python3', '/usr/bin/python', { force: true })\n * ```\n */\n makeSymlink(\n src: PathLike,\n dest: PathLike,\n options?: { user?: string; force?: boolean }\n ): TemplateBuilder\n\n /**\n * Run a shell command.\n * @param command Command string\n * @param options Command options\n *\n * @example\n * ```ts\n * template.runCmd('apt-get update')\n * template.runCmd(['pip install numpy', 'pip install pandas'])\n * template.runCmd('apt-get install vim', { user: 'root' })\n * ```\n */\n runCmd(command: string, options?: { user?: string }): TemplateBuilder\n\n /**\n * Run multiple shell commands.\n * @param commands Array of command strings\n * @param options Command options\n */\n runCmd(commands: string[], options?: { user?: string }): TemplateBuilder\n\n /**\n * Run command(s).\n * @param commandOrCommands Command or commands\n * @param options Command options\n */\n runCmd(\n commandOrCommands: string | string[],\n options?: { user?: string }\n ): TemplateBuilder\n\n /**\n * Set the working directory.\n * @param workdir Working directory path\n *\n * @example\n * ```ts\n * template.setWorkdir('/app')\n * ```\n */\n setWorkdir(workdir: PathLike): TemplateBuilder\n\n /**\n * Set the user for subsequent commands.\n * @param user Username\n *\n * @example\n * ```ts\n * template.setUser('root')\n * ```\n */\n setUser(user: string): TemplateBuilder\n\n /**\n * Install Python packages using pip.\n * @param packages Package name(s) or undefined for current directory\n * @param options Install options\n * @param options.g Install globally as root (default: true). Set to false for user-only installation with --user flag\n *\n * @example\n * ```ts\n * template.pipInstall('numpy') // Installs globally (default)\n * template.pipInstall(['pandas', 'scikit-learn'])\n * template.pipInstall('numpy', { g: false }) // Install for user only\n * template.pipInstall() // Installs from current directory\n * ```\n */\n pipInstall(\n packages?: string | string[],\n options?: { g?: boolean }\n ): TemplateBuilder\n\n /**\n * Install Node.js packages using npm.\n * @param packages Package name(s) or undefined for package.json\n * @param options Install options\n *\n * @example\n * ```ts\n * template.npmInstall('express')\n * template.npmInstall(['lodash', 'axios'])\n * template.npmInstall('tsx', { g: true })\n * template.npmInstall('typescript', { dev: true })\n * template.npmInstall() // Installs from package.json\n * ```\n */\n npmInstall(\n packages?: string | string[],\n options?: { g?: boolean; dev?: boolean }\n ): TemplateBuilder\n /**\n * Install Bun packages using bun.\n * @param packages Package name(s) or undefined for package.json\n * @param options Install options\n *\n * @example\n * ```ts\n * template.bunInstall('express')\n * template.bunInstall(['lodash', 'axios'])\n * template.bunInstall('tsx', { g: true })\n * template.bunInstall('typescript', { dev: true })\n * template.bunInstall() // Installs from package.json\n * ```\n */\n bunInstall(\n packages?: string | string[],\n options?: { g?: boolean; dev?: boolean }\n ): TemplateBuilder\n\n /**\n * Install Debian/Ubuntu packages using apt-get.\n * @param packages Package name(s)\n *\n * @example\n * ```ts\n * template.aptInstall('vim')\n * template.aptInstall(['git', 'curl', 'wget'])\n * template.aptInstall(['vim'], { noInstallRecommends: true })\n * template.aptInstall(['vim'], { fixMissing: true })\n * ```\n */\n aptInstall(\n packages: string | string[],\n options?: { noInstallRecommends?: boolean; fixMissing?: boolean }\n ): TemplateBuilder\n\n /**\n * Install MCP servers using mcp-gateway.\n * Note: Requires a base image with mcp-gateway pre-installed (e.g., mcp-gateway).\n * @param servers MCP server name(s)\n *\n * @throws {Error} If the base template is not mcp-gateway\n * @example\n * ```ts\n * template.addMcpServer('exa')\n * template.addMcpServer(['brave', 'firecrawl', 'duckduckgo'])\n * ```\n */\n addMcpServer(servers: McpServerName | McpServerName[]): TemplateBuilder\n\n /**\n * Clone a Git repository.\n * @param url Repository URL\n * @param path Optional destination path\n * @param options Clone options\n *\n * @example\n * ```ts\n * template.gitClone('https://github.com/user/repo.git', '/app/repo')\n * template.gitClone('https://github.com/user/repo.git', undefined, {\n * branch: 'main',\n * depth: 1\n * })\n * template.gitClone('https://github.com/user/repo.git', '/app/repo', {\n * user: 'root'\n * })\n * ```\n */\n gitClone(\n url: string,\n path?: PathLike,\n options?: { branch?: string; depth?: number; user?: string }\n ): TemplateBuilder\n\n /**\n * Set environment variables.\n * Note: Environment variables defined here are available only during template build.\n * @param envs Environment variables\n *\n * @example\n * ```ts\n * template.setEnvs({ NODE_ENV: 'production', PORT: '8080' })\n * ```\n */\n setEnvs(envs: Record<string, string>): TemplateBuilder\n\n /**\n * Skip cache for all subsequent build instructions from this point.\n *\n * @example\n * ```ts\n * template.skipCache().runCmd('apt-get update')\n * ```\n */\n skipCache(): this\n\n /**\n * Set the start command and ready check.\n * @param startCommand Command to run on startup\n * @param readyCommand Command to check readiness\n *\n * @example\n * ```ts\n * // Using a string command\n * template.setStartCmd(\n * 'node app.js',\n * 'curl http://localhost:8000/health'\n * )\n *\n * // Using ReadyCmd helpers\n * import { waitForPort, waitForURL } from 'ppio-sandbox'\n *\n * template.setStartCmd(\n * 'python -m http.server 8000',\n * waitForPort(8000)\n * )\n *\n * template.setStartCmd(\n * 'npm start',\n * waitForURL('http://localhost:3000/health', 200)\n * )\n * ```\n */\n setStartCmd(\n startCommand: string,\n readyCommand: string | ReadyCmd\n ): TemplateFinal\n\n /**\n * Set or update the ready check command.\n * @param readyCommand Command to check readiness\n *\n * @example\n * ```ts\n * // Using a string command\n * template.setReadyCmd('curl http://localhost:8000/health')\n *\n * // Using ReadyCmd helpers\n * import { waitForPort, waitForFile, waitForProcess } from 'ppio-sandbox'\n *\n * template.setReadyCmd(waitForPort(3000))\n *\n * template.setReadyCmd(waitForFile('/tmp/ready'))\n *\n * template.setReadyCmd(waitForProcess('nginx'))\n * ```\n */\n setReadyCmd(readyCommand: string | ReadyCmd): TemplateFinal\n\n /**\n * Set a patch command that runs during base image provisioning.\n *\n * The command runs at the end of base-image provisioning, before the first\n * systemd boot.\n *\n * @param cmd Shell command to run during base image provisioning.\n */\n setPatchCmd(cmd: string): TemplateBuilder\n\n /**\n * Prebuild a devcontainer from the specified directory.\n * @param devcontainerDirectory Path to the devcontainer directory\n *\n * @example\n * ```ts\n * template\n * .gitClone('https://myrepo.com/project.git', '/my-devcontainer')\n * .betaDevContainerPrebuild('/my-devcontainer')\n * ```\n */\n betaDevContainerPrebuild(devcontainerDirectory: string): TemplateBuilder\n\n /**\n * Start a devcontainer from the specified directory.\n * @param devcontainerDirectory Path to the devcontainer directory\n *\n * @example\n * ```ts\n * template\n * .gitClone('https://myrepo.com/project.git', '/my-devcontainer')\n * .startDevcontainer('/my-devcontainer')\n *\n * // Prebuild and start\n * template\n * .gitClone('https://myrepo.com/project.git', '/my-devcontainer')\n * .betaDevContainerPrebuild('/my-devcontainer')\n * // Other instructions...\n * .betaSetDevContainerStart('/my-devcontainer')\n * ```\n */\n betaSetDevContainerStart(devcontainerDirectory: string): TemplateFinal\n}\n\n/**\n * Final state of a template after start/ready commands are set.\n * The template can only be built in this state.\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface TemplateFinal {}\n\n/**\n * Configuration for a generic Docker registry with basic authentication.\n */\nexport type GenericDockerRegistry = {\n /** Registry type identifier */\n type: 'registry'\n /** Registry username */\n username: string\n /** Registry password */\n password: string\n}\n\n/**\n * Configuration for AWS Elastic Container Registry (ECR).\n */\nexport type AWSRegistry = {\n /** Registry type identifier */\n type: 'aws'\n /** AWS access key ID */\n awsAccessKeyId: string\n /** AWS secret access key */\n awsSecretAccessKey: string\n /** AWS region */\n awsRegion: string\n}\n\n/**\n * Configuration for Google Container Registry (GCR) or Artifact Registry.\n */\nexport type GCPRegistry = {\n /** Registry type identifier */\n type: 'gcp'\n /** Service account JSON as string */\n serviceAccountJson: string\n}\n\n/**\n * Configuration for Oracle Cloud Infrastructure Registry.\n */\nexport type OCIRegistry = {\n /** Registry type identifier */\n type: 'oci'\n /** OCI tenancy OCID */\n tenancyOcid: string\n /** OCI user OCID */\n userOcid: string\n /** API key fingerprint */\n fingerprint: string\n /** API private key PEM */\n privateKey: string\n /** OCI region */\n region: string\n}\n\n/**\n * Configuration for Huawei Cloud Software Repository for Container.\n */\nexport type HuaweiCloudRegistry = {\n /** Registry type identifier */\n type: 'huawei'\n /** Huawei Cloud access key ID */\n accessKeyId: string\n /** Huawei Cloud secret access key */\n secretAccessKey: string\n /** Huawei Cloud region */\n region: string\n}\n\n/**\n * Union type for all supported container registry configurations.\n */\nexport type RegistryConfig =\n | GenericDockerRegistry\n | AWSRegistry\n | GCPRegistry\n | OCIRegistry\n | HuaweiCloudRegistry\n\n/**\n * Type representing a template in any state (builder or final).\n */\nexport type TemplateClass = TemplateBuilder | TemplateFinal\n","import type { PathLike } from 'node:fs'\nimport { ApiClient, handleApiError } from '../api'\nimport type { components } from '../api/schema.gen'\nimport { ConnectionConfig, ConnectionOpts, raiseIfLegacy } from '../connectionConfig'\nimport { BuildError } from '../errors'\nimport { runtime } from '../utils'\nimport {\n assignTags,\n checkAliasExists,\n getTemplateTags,\n removeTags,\n getBuildStatus,\n getFileUploadLink,\n requestBuild,\n triggerBuild,\n TriggerBuildTemplate,\n uploadFile,\n waitForBuildFinish,\n} from './buildApi'\nimport { RESOLVE_SYMLINKS, STACK_TRACE_DEPTH } from './consts'\nimport { parseDockerfile } from './dockerfileParser'\nimport { envFilesCommand } from './envFiles'\nimport { effectiveStartCmd, fetchImageConfig } from './imageConfig'\nimport { LogEntry, LogEntryEnd, LogEntryStart } from './logger'\nimport { ReadyCmd, waitForFile, waitForTimeout } from './readycmd'\nimport {\n BuildInfo,\n BuildOptions,\n CopyItem,\n GetBuildStatusOptions,\n Instruction,\n InstructionType,\n McpServerName,\n RegistryConfig,\n TemplateDeleteOpts,\n TemplateInfo,\n TemplateListOpts,\n TemplateListResponse,\n TemplateBuilder,\n TemplateBuildStatusResponse,\n TemplateClass,\n TemplateFinal,\n TemplateFromImage,\n TemplateOptions,\n TemplateTag,\n TemplateTagInfo,\n} from './types'\nimport {\n calculateFilesHash,\n getCallerDirectory,\n getCallerFrame,\n normalizeBuildArguments,\n padOctal,\n readDockerignore,\n readGCPServiceAccountJSON,\n validateRelativePath,\n} from './utils'\n\nexport class TemplateApi {\n static async getTemplate(\n templateId: string,\n options?: ConnectionOpts\n ): Promise<components['schemas']['TemplateWithBuilds']> {\n const config = new ConnectionConfig(options)\n raiseIfLegacy(config, 'Template.get', BuildError)\n const client = new ApiClient(config)\n const response = await client.api.GET('/templates/{templateID}', {\n params: { path: { templateID: templateId } },\n signal: config.getSignal(options?.requestTimeoutMs),\n })\n const error = handleApiError(response)\n if (error) throw error\n if (!response.data) {\n throw new BuildError('Template details response data is missing')\n }\n return response.data\n }\n\n static async listTemplates(\n options?: TemplateListOpts\n ): Promise<TemplateListResponse> {\n const templateType = options?.templateType ?? 'template_build'\n const page = options?.page ?? 1\n const limit = options?.limit ?? 20\n\n if (!['template_build', 'snapshot_template'].includes(templateType)) {\n throw new Error(\n 'templateType must be either \"template_build\" or \"snapshot_template\"'\n )\n }\n if (page < 1) {\n throw new Error('page must be >= 1')\n }\n if (limit < 1 || limit > 100) {\n throw new Error('limit must be between 1 and 100')\n }\n\n const config = new ConnectionConfig(options)\n const url = new URL(`${config.apiUrl}/v2/templates`)\n if (options?.teamID) {\n url.searchParams.set('teamID', options.teamID)\n }\n url.searchParams.set('template_type', templateType)\n url.searchParams.set('page', String(page))\n url.searchParams.set('limit', String(limit))\n\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n ...config.headers,\n ...(config.apiKey ? { 'X-API-KEY': config.apiKey } : {}),\n ...(config.accessToken\n ? { Authorization: `Bearer ${config.accessToken}` }\n : {}),\n },\n signal: config.getSignal(options?.requestTimeoutMs),\n })\n\n if (!response.ok) {\n throw new Error(`${response.status}: ${await response.text()}`)\n }\n\n const data = await response.json()\n if (!data) {\n throw new Error('Template list response data is missing')\n }\n\n return {\n templates: (data.templates ?? []).map(\n (template: Record<string, any>) => ({\n templateId: template.templateID,\n aliases: template.aliases,\n buildCount: template.buildCount,\n buildId: template.buildID,\n cpuCount: template.cpuCount,\n createdAt: new Date(template.createdAt),\n createdBy: template.createdBy,\n diskSizeMB: template.diskSizeMB,\n envdVersion: template.envdVersion,\n lastSpawnedAt: template.lastSpawnedAt\n ? new Date(template.lastSpawnedAt)\n : null,\n memoryMB: template.memoryMB,\n metadata: template.metadata,\n public: template.public,\n spawnCount: template.spawnCount,\n templateType: template.templateType,\n originSandboxID: template.originSandboxID,\n updatedAt: new Date(template.updatedAt),\n })\n ),\n page: data.page ?? page,\n limit: data.limit ?? limit,\n total: data.total ?? 0,\n totalPages: data.totalPages ?? 0,\n }\n }\n\n static async deleteTemplate(\n templateId: string,\n options?: TemplateDeleteOpts\n ): Promise<boolean> {\n if (!templateId) {\n throw new Error('templateId cannot be empty')\n }\n\n const config = new ConnectionConfig(options)\n const client = new ApiClient(config)\n\n const res = await client.api.DELETE('/templates/{templateID}', {\n params: {\n path: {\n templateID: templateId,\n },\n },\n signal: config.getSignal(options?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404 || res.response.status === 404) {\n return false\n }\n\n const err = handleApiError(res, BuildError)\n if (err) {\n throw err\n }\n\n return true\n }\n}\n\nexport class TemplatePaginator {\n private readonly options?: TemplateListOpts\n private nextPageNumber: number\n private hasNextPage = true\n\n constructor(options?: TemplateListOpts) {\n this.options = options\n this.nextPageNumber = options?.page ?? 1\n }\n\n get hasNext(): boolean {\n return this.hasNextPage\n }\n\n get currentPage(): number {\n return this.nextPageNumber\n }\n\n async nextPage(): Promise<TemplateListResponse> {\n if (!this.hasNextPage) {\n throw new Error('No more pages to fetch')\n }\n\n const response = await TemplateApi.listTemplates({\n ...this.options,\n page: this.nextPageNumber,\n })\n this.hasNextPage = response.page < response.totalPages\n this.nextPageNumber = response.page + 1\n return response\n }\n\n reset(): void {\n this.nextPageNumber = this.options?.page ?? 1\n this.hasNextPage = true\n }\n}\n\n/**\n * Base class for building PPIO sandbox sandbox templates.\n */\nexport class TemplateBase\n implements TemplateFromImage, TemplateBuilder, TemplateFinal\n{\n private defaultBaseImage: string = 'ppio-sandbox/base'\n private baseImage: string | undefined = this.defaultBaseImage\n private baseTemplate: string | undefined = undefined\n private registryConfig: RegistryConfig | undefined = undefined\n private startCmd: string | undefined = undefined\n private readyCmd: string | undefined = undefined\n private patchCmd: string | undefined = undefined\n // Force the whole template to be rebuilt\n private force: boolean = false\n // Force the next layer to be rebuilt\n private forceNextLayer: boolean = false\n private instructions: Instruction[] = []\n // Everything passed to setEnvs, accumulated across calls. The declared value is\n // kept, not the resolved one: `/opt/venv/bin:$PATH` is expanded during the\n // build, since the platform ignores an ENV instruction for PATH and the build's\n // own PATH is therefore not the declared one (see envFiles.ts). Accumulated\n // rather than written per call because the file is written once from the full\n // set -- a per-call write would clobber the previous call's file.\n private envs: Record<string, string> = {}\n // Whether to restore what the base image declares -- see fromImage() and\n // resolveInheritedConfig(). Only meaningful for an image base; a Dockerfile\n // states its own ENV/WORKDIR/CMD, and a template base already carries them.\n private inheritImageConfig: boolean = false\n private imageCredentials: { username: string; password: string } | undefined =\n undefined\n // Why the image's config is missing, when it is. Recorded rather than only\n // logged: build() has a log channel and toJSON() does not, so a dry run or a\n // CLI conversion would otherwise show a clean template that silently lacks the\n // image's PATH -- the exact failure this reading exists to prevent.\n private imageConfigError: string | undefined = undefined\n private imageUnusable: string | undefined = undefined\n private fileContextPath: PathLike =\n runtime === 'browser' ? '.' : (getCallerDirectory(STACK_TRACE_DEPTH) ?? '.')\n private fileIgnorePatterns: string[] = []\n private logsRefreshFrequency: number = 200\n private stackTraces: (string | undefined)[] = []\n private stackTracesEnabled: boolean = true\n private stackTracesOverride: string | undefined = undefined\n\n constructor(options?: TemplateOptions) {\n this.fileContextPath = options?.fileContextPath ?? this.fileContextPath\n this.fileIgnorePatterns =\n options?.fileIgnorePatterns ?? this.fileIgnorePatterns\n }\n\n static list(options?: TemplateListOpts): TemplatePaginator {\n return new TemplatePaginator(options)\n }\n\n /**\n * Convert a template to JSON representation.\n *\n * @param template The template to convert\n * @param computeHashes Whether to compute file hashes for cache invalidation\n * @returns JSON string representation of the template\n */\n static toJSON(\n template: TemplateClass,\n computeHashes: boolean = true\n ): Promise<string> {\n return (template as TemplateBase).toJSON(computeHashes)\n }\n\n /**\n * Convert a template to Dockerfile format.\n * Note: Templates based on other PPIO sandbox templates cannot be converted to Dockerfile.\n *\n * @param template The template to convert\n * @returns Dockerfile string representation\n * @throws Error if the template is based on another PPIO sandbox template\n */\n static toDockerfile(template: TemplateClass): string {\n return (template as TemplateBase).toDockerfile()\n }\n\n /**\n * Build and deploy a template to PPIO sandbox infrastructure.\n *\n * @param template The template to build\n * @param name Template name in 'name' or 'name:tag' format\n * @param options Optional build configuration options\n *\n * @example\n * ```ts\n * const template = Template().fromPythonImage('3')\n *\n * // Build with single tag in name\n * await Template.build(template, 'my-python-env:v1.0')\n *\n * // Build with multiple tags\n * await Template.build(template, 'my-python-env', { tags: ['v1.0', 'stable'] })\n * ```\n */\n static async build(\n template: TemplateClass,\n name: string,\n options?: Omit<BuildOptions, 'alias'>\n ): Promise<BuildInfo>\n /**\n * Build and deploy a template to PPIO sandbox infrastructure.\n *\n * @param template The template to build\n * @param options Build configuration options with alias (deprecated)\n *\n * @deprecated Use the overload with `name` parameter instead.\n * @example\n * ```ts\n * // Deprecated:\n * await Template.build(template, { alias: 'my-python-env' })\n *\n * // Use instead:\n * await Template.build(template, 'my-python-env:v1.0')\n * ```\n */\n static async build(\n template: TemplateClass,\n options: BuildOptions\n ): Promise<BuildInfo>\n static async build(\n template: TemplateClass,\n nameOrOptions: string | BuildOptions,\n options?: Omit<BuildOptions, 'alias'>\n ): Promise<BuildInfo> {\n const { name, buildOptions } = normalizeBuildArguments(\n nameOrOptions,\n options\n )\n\n try {\n buildOptions.onBuildLogs?.(new LogEntryStart(new Date(), 'Build started'))\n const baseTemplate = template as TemplateBase\n\n const config = new ConnectionConfig(buildOptions)\n const client = new ApiClient(config)\n\n const data = await baseTemplate.build(client, name, buildOptions)\n\n buildOptions.onBuildLogs?.(\n new LogEntry(new Date(), 'info', 'Waiting for logs...')\n )\n\n await waitForBuildFinish(client, {\n templateID: data.templateId,\n buildID: data.buildId,\n onBuildLogs: buildOptions.onBuildLogs,\n logsRefreshFrequency: baseTemplate.logsRefreshFrequency,\n stackTraces: baseTemplate.stackTraces,\n })\n\n return data\n } finally {\n buildOptions.onBuildLogs?.(new LogEntryEnd(new Date(), 'Build finished'))\n }\n }\n\n /**\n * Build and deploy a template to PPIO sandbox infrastructure without waiting for completion.\n *\n * @param template The template to build\n * @param name Template name in 'name' or 'name:tag' format\n * @param options Optional build configuration options\n *\n * @example\n * ```ts\n * const template = Template().fromPythonImage('3')\n *\n * // Build with single tag in name\n * const data = await Template.buildInBackground(template, 'my-python-env:v1.0')\n *\n * // Build with multiple tags\n * const data = await Template.buildInBackground(template, 'my-python-env', { tags: ['v1.0', 'stable'] })\n * ```\n */\n static async buildInBackground(\n template: TemplateClass,\n name: string,\n options?: Omit<BuildOptions, 'alias'>\n ): Promise<BuildInfo>\n /**\n * Build and deploy a template to PPIO sandbox infrastructure without waiting for completion.\n *\n * @param template The template to build\n * @param options Build configuration options with alias (deprecated)\n *\n * @deprecated Use the overload with `name` parameter instead.\n * @example\n * ```ts\n * // Deprecated:\n * await Template.buildInBackground(template, { alias: 'my-python-env' })\n *\n * // Use instead:\n * await Template.buildInBackground(template, 'my-python-env:v1.0')\n * ```\n */\n static async buildInBackground(\n template: TemplateClass,\n options: BuildOptions\n ): Promise<BuildInfo>\n static async buildInBackground(\n template: TemplateClass,\n nameOrOptions: string | BuildOptions,\n options?: Omit<BuildOptions, 'alias'>\n ): Promise<BuildInfo> {\n const { name, buildOptions } = normalizeBuildArguments(\n nameOrOptions,\n options\n )\n\n const config = new ConnectionConfig(buildOptions)\n const client = new ApiClient(config)\n\n return (template as TemplateBase).build(client, name, buildOptions)\n }\n\n /**\n * Get the status of a build.\n *\n * @param data Build identifiers\n * @param options Authentication options\n *\n * @example\n * ```ts\n * const status = await Template.getBuildStatus(data, { logsOffset: 0 })\n * ```\n */\n static async getBuildStatus(\n data: Pick<BuildInfo, 'templateId' | 'buildId'>,\n options?: GetBuildStatusOptions\n ): Promise<TemplateBuildStatusResponse> {\n const config = new ConnectionConfig(options)\n raiseIfLegacy(config, 'Template.getBuildStatus', BuildError)\n const client = new ApiClient(config)\n\n return await getBuildStatus(client, {\n templateID: data.templateId,\n buildID: data.buildId,\n logsOffset: options?.logsOffset,\n })\n }\n\n static async listTemplates(\n options?: TemplateListOpts\n ): Promise<TemplateListResponse> {\n return TemplateApi.listTemplates(options)\n }\n\n static async get(\n templateId: string,\n options?: ConnectionOpts\n ): Promise<components['schemas']['TemplateWithBuilds']> {\n return TemplateApi.getTemplate(templateId, options)\n }\n\n static async delete(templateId: string, options?: ConnectionOpts) {\n await TemplateApi.deleteTemplate(templateId, options)\n }\n\n static async deleteTemplate(\n templateId: string,\n options?: TemplateDeleteOpts\n ): Promise<boolean> {\n return TemplateApi.deleteTemplate(templateId, options)\n }\n\n /**\n * Check if a template with the given name exists.\n *\n * @param name Template name to check\n * @param options Authentication options\n * @returns True if the name exists, false otherwise\n *\n * @example\n * ```ts\n * const exists = await Template.exists('my-python-env')\n * if (exists) {\n * console.log('Template exists!')\n * }\n * ```\n */\n static async exists(\n name: string,\n options?: ConnectionOpts\n ): Promise<boolean> {\n return TemplateBase.aliasExists(name, options)\n }\n\n /**\n * Check if a template with the given alias exists.\n *\n * @param alias Template alias to check\n * @param options Authentication options\n * @returns True if the alias exists, false otherwise\n *\n * @deprecated Use `exists` instead.\n * @example\n * ```ts\n * const exists = await Template.aliasExists('my-python-env')\n * if (exists) {\n * console.log('Template exists!')\n * }\n * ```\n */\n static async aliasExists(\n alias: string,\n options?: ConnectionOpts\n ): Promise<boolean> {\n const config = new ConnectionConfig(options)\n const client = new ApiClient(config)\n\n return checkAliasExists(client, { alias })\n }\n\n /**\n * Assign tag(s) to an existing template build.\n *\n * @param targetName Template name in 'name:tag' format (the source build to tag from)\n * @param tags Tag or tags to assign\n * @param options Authentication options\n * @returns Tag info with buildId and assigned tags\n *\n * @example\n * ```ts\n * // Assign a single tag\n * await Template.assignTags('my-template:v1.0', 'production')\n *\n * // Assign multiple tags\n * await Template.assignTags('my-template:v1.0', ['production', 'stable'])\n * ```\n */\n static async assignTags(\n targetName: string,\n tags: string | string[],\n options?: ConnectionOpts\n ): Promise<TemplateTagInfo> {\n const config = new ConnectionConfig(options)\n const client = new ApiClient(config)\n const normalizedTags = Array.isArray(tags) ? tags : [tags]\n return assignTags(client, { targetName, tags: normalizedTags })\n }\n\n /**\n * Remove tag(s) from a template.\n *\n * @param name Template name\n * @param tags Tag or tags to remove\n * @param options Authentication options\n *\n * @example\n * ```ts\n * // Remove a single tag\n * await Template.removeTags('my-template', 'production')\n *\n * // Remove multiple tags from a template\n * await Template.removeTags('my-template', ['production', 'staging'])\n * ```\n */\n static async removeTags(\n name: string,\n tags: string | string[],\n options?: ConnectionOpts\n ): Promise<void> {\n const config = new ConnectionConfig(options)\n const client = new ApiClient(config)\n const normalizedTags = Array.isArray(tags) ? tags : [tags]\n return removeTags(client, { name, tags: normalizedTags })\n }\n\n /**\n * Get all tags for a template.\n *\n * @param templateId Template ID or name\n * @param options Authentication options\n * @returns Array of tag details including tag name, buildId, and creation date\n *\n * @example\n * ```ts\n * const tags = await Template.getTags('my-template')\n * for (const tag of tags) {\n * console.log(`Tag: ${tag.tag}, Build: ${tag.buildId}, Created: ${tag.createdAt}`)\n * }\n * ```\n */\n static async getTags(\n templateId: string,\n options?: ConnectionOpts\n ): Promise<TemplateTag[]> {\n const config = new ConnectionConfig(options)\n const client = new ApiClient(config)\n return getTemplateTags(client, { templateID: templateId })\n }\n\n fromDebianImage(variant: string = 'stable'): TemplateBuilder {\n return this.fromImage(`debian:${variant}`)\n }\n\n fromUbuntuImage(variant: string = 'latest'): TemplateBuilder {\n return this.fromImage(`ubuntu:${variant}`)\n }\n\n fromPythonImage(version: string = '3'): TemplateBuilder {\n return this.fromImage(`python:${version}`)\n }\n\n fromNodeImage(variant: string = 'lts'): TemplateBuilder {\n return this.fromImage(`node:${variant}`)\n }\n\n fromBunImage(variant: string = 'latest'): TemplateBuilder {\n return this.fromImage(`oven/bun:${variant}`)\n }\n\n fromBaseImage(): TemplateBuilder {\n return this.fromImage(this.defaultBaseImage)\n }\n\n fromImage(\n baseImage: string,\n credentials?: { username: string; password: string },\n options?: { inheritConfig?: boolean }\n ): TemplateBuilder {\n this.baseImage = baseImage\n this.baseTemplate = undefined\n // Read at build time, not here: this method is synchronous so it can be\n // chained, and reading a registry is not. See resolveInheritedConfig().\n this.inheritImageConfig = options?.inheritConfig ?? true\n this.imageCredentials = credentials\n\n // Set the registry config if provided\n if (credentials) {\n this.registryConfig = {\n type: 'registry',\n username: credentials.username,\n password: credentials.password,\n }\n }\n\n // If we should force the next layer and it's a FROM command, invalidate whole template\n if (this.forceNextLayer) {\n this.force = true\n }\n\n this.collectStackTrace()\n return this\n }\n\n fromTemplate(template: string): TemplateBuilder {\n this.baseTemplate = template\n this.baseImage = undefined\n\n // If we should force the next layer and it's a FROM command, invalidate whole template\n if (this.forceNextLayer) {\n this.force = true\n }\n\n this.collectStackTrace()\n return this\n }\n\n fromDockerfile(dockerfileContentOrPath: string): TemplateBuilder {\n const { baseImage } = this.runInStackTraceOverrideContext(\n () => parseDockerfile(dockerfileContentOrPath, this),\n // -1 as we're going up the call stack from the parseDockerfile function\n getCallerFrame(STACK_TRACE_DEPTH - 1)\n )\n this.baseImage = baseImage\n this.baseTemplate = undefined\n\n // If we should force the next layer and it's a FROM command, invalidate whole template\n if (this.forceNextLayer) {\n this.force = true\n }\n\n this.collectStackTrace()\n return this\n }\n\n fromAWSRegistry(\n image: string,\n credentials: {\n accessKeyId: string\n secretAccessKey: string\n region: string\n }\n ): TemplateBuilder {\n this.baseImage = image\n this.baseTemplate = undefined\n\n // Set the registry config if provided\n this.registryConfig = {\n type: 'aws',\n awsAccessKeyId: credentials.accessKeyId,\n awsSecretAccessKey: credentials.secretAccessKey,\n awsRegion: credentials.region,\n }\n\n // If we should force the next layer and it's a FROM command, invalidate whole template\n if (this.forceNextLayer) {\n this.force = true\n }\n\n this.collectStackTrace()\n return this\n }\n\n fromGCPRegistry(\n image: string,\n credentials: {\n serviceAccountJSON: string | object\n }\n ): TemplateBuilder {\n this.baseImage = image\n this.baseTemplate = undefined\n\n // Set the registry config if provided\n this.registryConfig = {\n type: 'gcp',\n serviceAccountJson: readGCPServiceAccountJSON(\n this.fileContextPath.toString(),\n credentials.serviceAccountJSON\n ),\n }\n\n // If we should force the next layer and it's a FROM command, invalidate whole template\n if (this.forceNextLayer) {\n this.force = true\n }\n\n this.collectStackTrace()\n return this\n }\n\n fromOCIRegistry(\n image: string,\n credentials: {\n tenancyOcid: string\n userOcid: string\n fingerprint: string\n privateKey: string\n region: string\n }\n ): TemplateBuilder {\n this.baseImage = image\n this.baseTemplate = undefined\n\n this.registryConfig = {\n type: 'oci',\n tenancyOcid: credentials.tenancyOcid,\n userOcid: credentials.userOcid,\n fingerprint: credentials.fingerprint,\n privateKey: credentials.privateKey,\n region: credentials.region,\n }\n\n if (this.forceNextLayer) {\n this.force = true\n }\n\n this.collectStackTrace()\n return this\n }\n\n fromHuaweiCloudRegistry(\n image: string,\n credentials: {\n accessKeyId: string\n secretAccessKey: string\n region: string\n }\n ): TemplateBuilder {\n this.baseImage = image\n this.baseTemplate = undefined\n\n this.registryConfig = {\n type: 'huawei',\n accessKeyId: credentials.accessKeyId,\n secretAccessKey: credentials.secretAccessKey,\n region: credentials.region,\n }\n\n if (this.forceNextLayer) {\n this.force = true\n }\n\n this.collectStackTrace()\n return this\n }\n\n copy(\n src: PathLike | PathLike[],\n dest: PathLike,\n options?: {\n forceUpload?: true\n user?: string\n mode?: number\n resolveSymlinks?: boolean\n }\n ): TemplateBuilder {\n if (runtime === 'browser') {\n throw new Error('Browser runtime is not supported for copy')\n }\n\n const srcs = Array.isArray(src) ? src : [src]\n const stackTrace = getCallerFrame(STACK_TRACE_DEPTH - 1)\n\n for (const src of srcs) {\n const srcString = src.toString()\n\n // Validate that the source path is a relative path within the context directory\n validateRelativePath(srcString, stackTrace)\n\n const args = [\n srcString,\n dest.toString(),\n options?.user ?? '',\n options?.mode ? padOctal(options.mode) : '',\n ]\n\n this.instructions.push({\n type: InstructionType.COPY,\n args,\n force: options?.forceUpload || this.forceNextLayer,\n forceUpload: options?.forceUpload,\n resolveSymlinks: options?.resolveSymlinks,\n })\n }\n\n this.collectStackTrace()\n return this\n }\n\n copyItems(items: CopyItem[]): TemplateBuilder {\n if (runtime === 'browser') {\n throw new Error('Browser runtime is not supported for copyItems')\n }\n\n // Stack trace that will be used to re-throw the error with\n const stackTrace = getCallerFrame(STACK_TRACE_DEPTH - 1)\n\n this.runInNewStackTraceContext(() => {\n for (const item of items) {\n try {\n this.copy(item.src, item.dest, {\n forceUpload: item.forceUpload,\n user: item.user,\n mode: item.mode,\n resolveSymlinks: item.resolveSymlinks,\n })\n } catch (error) {\n const copyError = error as Error\n copyError.stack = stackTrace\n throw copyError\n }\n }\n })\n\n return this\n }\n\n remove(\n path: PathLike | PathLike[],\n options?: { force?: boolean; recursive?: boolean; user?: string }\n ): TemplateBuilder {\n const paths = Array.isArray(path) ? path : [path]\n const args = ['rm']\n if (options?.recursive) {\n args.push('-r')\n }\n if (options?.force) {\n args.push('-f')\n }\n args.push(...paths.map((p) => p.toString()))\n return this.runInNewStackTraceContext(() =>\n this.runCmd(args.join(' '), { user: options?.user })\n )\n }\n\n rename(\n src: PathLike,\n dest: PathLike,\n options?: { force?: boolean; user?: string }\n ): TemplateBuilder {\n const args = ['mv', src.toString(), dest.toString()]\n if (options?.force) {\n args.push('-f')\n }\n return this.runInNewStackTraceContext(() =>\n this.runCmd(args.join(' '), { user: options?.user })\n )\n }\n\n makeDir(\n path: PathLike | PathLike[],\n options?: { mode?: number; user?: string }\n ): TemplateBuilder {\n const paths = Array.isArray(path) ? path : [path]\n const args = ['mkdir', '-p']\n if (options?.mode) {\n args.push(`-m ${padOctal(options.mode)}`)\n }\n args.push(...paths.map((p) => p.toString()))\n return this.runInNewStackTraceContext(() =>\n this.runCmd(args.join(' '), { user: options?.user })\n )\n }\n\n makeSymlink(\n src: PathLike,\n dest: PathLike,\n options?: { user?: string; force?: boolean }\n ): TemplateBuilder {\n const args = ['ln', '-s']\n if (options?.force) {\n args.push('-f')\n }\n args.push(src.toString(), dest.toString())\n return this.runInNewStackTraceContext(() =>\n this.runCmd(args.join(' '), { user: options?.user })\n )\n }\n\n runCmd(command: string, options?: { user?: string }): TemplateBuilder\n runCmd(commands: string[], options?: { user?: string }): TemplateBuilder\n runCmd(\n commandOrCommands: string | string[],\n options?: { user?: string }\n ): TemplateBuilder {\n const cmds = Array.isArray(commandOrCommands)\n ? commandOrCommands\n : [commandOrCommands]\n\n const args = [cmds.join(' && ')]\n if (options?.user) {\n args.push(options.user)\n }\n\n this.instructions.push({\n type: InstructionType.RUN,\n args,\n force: this.forceNextLayer,\n })\n\n this.collectStackTrace()\n return this\n }\n\n setWorkdir(workdir: PathLike): TemplateBuilder {\n this.instructions.push({\n type: InstructionType.WORKDIR,\n args: [workdir.toString()],\n force: this.forceNextLayer,\n })\n\n this.collectStackTrace()\n return this\n }\n\n setUser(user: string): TemplateBuilder {\n this.instructions.push({\n type: InstructionType.USER,\n args: [user],\n force: this.forceNextLayer,\n })\n\n this.collectStackTrace()\n return this\n }\n\n pipInstall(\n packages?: string | string[],\n options?: { g?: boolean }\n ): TemplateBuilder {\n const g = options?.g ?? true\n\n const args = ['pip', 'install']\n const packageList = packages\n ? Array.isArray(packages)\n ? packages\n : [packages]\n : undefined\n if (g === false) {\n args.push('--user')\n }\n if (packageList) {\n args.push(...packageList)\n } else {\n args.push('.')\n }\n\n return this.runInNewStackTraceContext(() =>\n this.runCmd(args.join(' '), {\n user: g ? 'root' : undefined,\n })\n )\n }\n\n npmInstall(\n packages?: string | string[],\n options?: { g?: boolean; dev?: boolean }\n ): TemplateBuilder {\n const args = ['npm', 'install']\n const packageList = packages\n ? Array.isArray(packages)\n ? packages\n : [packages]\n : undefined\n if (options?.g) {\n args.push('-g')\n }\n if (options?.dev) {\n args.push('--save-dev')\n }\n if (packageList) {\n args.push(...packageList)\n }\n\n return this.runInNewStackTraceContext(() =>\n this.runCmd(args.join(' '), {\n user: options?.g ? 'root' : undefined,\n })\n )\n }\n\n bunInstall(\n packages?: string | string[],\n options?: { g?: boolean; dev?: boolean }\n ): TemplateBuilder {\n const args = ['bun', 'install']\n const packageList = packages\n ? Array.isArray(packages)\n ? packages\n : [packages]\n : undefined\n if (options?.g) {\n args.push('-g')\n }\n if (options?.dev) {\n args.push('--dev')\n }\n if (packageList) {\n args.push(...packageList)\n }\n\n return this.runInNewStackTraceContext(() =>\n this.runCmd(args.join(' '), {\n user: options?.g ? 'root' : undefined,\n })\n )\n }\n\n aptInstall(\n packages: string | string[],\n options?: { noInstallRecommends?: boolean; fixMissing?: boolean }\n ): TemplateBuilder {\n const packageList = Array.isArray(packages) ? packages : [packages]\n return this.runInNewStackTraceContext(() =>\n this.runCmd(\n [\n 'apt-get update',\n `DEBIAN_FRONTEND=noninteractive DEBCONF_NOWARNINGS=yes apt-get install -y ${options?.noInstallRecommends ? '--no-install-recommends ' : ''}${options?.fixMissing ? '--fix-missing ' : ''}${packageList.join(\n ' '\n )}`,\n ],\n { user: 'root' }\n )\n )\n }\n\n addMcpServer(servers: McpServerName | McpServerName[]): TemplateBuilder {\n if (this.baseTemplate !== 'mcp-gateway') {\n throw new BuildError(\n 'MCP servers can only be added to mcp-gateway template',\n getCallerFrame(STACK_TRACE_DEPTH - 1)\n )\n }\n\n const serverList = Array.isArray(servers) ? servers : [servers]\n return this.runInNewStackTraceContext(() =>\n this.runCmd(`mcp-gateway pull ${serverList.join(' ')}`, {\n user: 'root',\n })\n )\n }\n\n gitClone(\n url: string,\n path?: PathLike,\n options?: { branch?: string; depth?: number; user?: string }\n ): TemplateBuilder {\n const args = ['git', 'clone', url]\n if (options?.branch) {\n args.push(`--branch ${options.branch}`)\n args.push('--single-branch')\n }\n if (options?.depth) {\n args.push(`--depth ${options.depth}`)\n }\n if (path) {\n args.push(path.toString())\n }\n\n return this.runInNewStackTraceContext(() =>\n this.runCmd(args.join(' '), { user: options?.user })\n )\n }\n\n setStartCmd(\n startCommand: string,\n readyCommand: string | ReadyCmd\n ): TemplateFinal {\n this.startCmd = startCommand\n\n if (readyCommand instanceof ReadyCmd) {\n this.readyCmd = readyCommand.getCmd()\n } else {\n this.readyCmd = readyCommand\n }\n\n this.collectStackTrace()\n return this\n }\n\n setReadyCmd(readyCommand: string | ReadyCmd): TemplateFinal {\n if (readyCommand instanceof ReadyCmd) {\n this.readyCmd = readyCommand.getCmd()\n } else {\n this.readyCmd = readyCommand\n }\n\n this.collectStackTrace()\n return this\n }\n\n setPatchCmd(cmd: string): TemplateBuilder {\n this.patchCmd = cmd\n this.collectStackTrace()\n return this\n }\n\n setEnvs(envs: Record<string, string>): TemplateBuilder {\n if (Object.keys(envs).length === 0) {\n return this\n }\n\n this.instructions.push({\n type: InstructionType.ENV,\n args: Object.entries(envs).flatMap(([key, value]) => [key, value]),\n force: this.forceNextLayer,\n })\n // The ENV instruction above only reaches the *build*. A sandbox started from\n // the finished template does not inherit it, so the names are also written to\n // the filesystem at the end of the build -- see runtimeEnvInstruction() and\n // envFiles.ts for the measurement that established this.\n this.envs = { ...this.envs, ...envs }\n this.collectStackTrace()\n return this\n }\n\n /**\n * The instruction that makes {@link setEnvs} visible at runtime, or null when\n * no environment was set.\n *\n * Appended at build time rather than inside `setEnvs`, for two reasons: the\n * file is written once from the complete set (a per-call write would clobber\n * the previous call's file), and it must land after any USER instruction the\n * caller added, since the write needs root.\n *\n * Not run through `runCmd` -- that would mutate `this.instructions` and make a\n * second build of the same template append a duplicate layer.\n */\n private runtimeEnvInstruction(): Instruction | null {\n const { command } = envFilesCommand(this.envs)\n if (command === null) {\n return null\n }\n\n return {\n type: InstructionType.RUN,\n args: [command, 'root'],\n force: this.forceNextLayer,\n }\n }\n\n /**\n * `instructions` with the runtime-env write appended, if there is one.\n *\n * Returns a new array rather than pushing: `toJSON` and `build` both call this,\n * and a template that is serialized and then built must not end up with the\n * layer twice.\n */\n private withRuntimeEnv(instructions: Instruction[]): Instruction[] {\n const runtimeEnv = this.runtimeEnvInstruction()\n return runtimeEnv ? [...instructions, runtimeEnv] : instructions\n }\n\n /**\n * Restore what the base image declares: ENV, WORKDIR and its effective command.\n *\n * `fromImage` records only the reference — the platform pulls the image\n * server-side, and nothing ever read its config. So the image's own ENV is as\n * absent at runtime as a template's own: measured, `python:3.11-slim` declares\n * `PATH=/usr/local/bin:…` and a sandbox built from it reported a different PATH\n * entirely. Same for WORKDIR, and for ENTRYPOINT/CMD, which is what `docker run`\n * would have launched.\n *\n * Runs at build time because reading a registry is asynchronous and `fromImage`\n * has to stay chainable. **The caller always wins**: anything set explicitly on\n * the builder overrides what the image declared, which is the same precedence a\n * Dockerfile has over its own base image.\n *\n * A failed read is not fatal — the template still builds, just without the\n * restored config — but it is reported, since an image whose toolchain lives\n * behind its ENV will otherwise look installed and behave as though it is not.\n */\n private async resolveInheritedConfig(\n onBuildLogs?: (logEntry: LogEntry) => void\n ): Promise<void> {\n if (!this.inheritImageConfig || this.baseImage === undefined) {\n return\n }\n // Only once: build() and toJSON() both call this, and a second read would\n // re-apply the image's values over any the caller set in between. Belt and\n // braces -- the two places it would matter defend themselves anyway (the env\n // merge puts the caller last, and the WORKDIR push checks for an existing\n // one), so removing this alone does not currently change any outcome.\n this.inheritImageConfig = false\n\n const config = await fetchImageConfig(this.baseImage, this.imageCredentials)\n\n if (config.error) {\n // Reported rather than thrown. The build can still succeed, and one\n // unreachable registry must not fail a batch conversion -- but a template\n // silently missing the image's PATH is the failure this exists to prevent,\n // so it must not pass unmentioned.\n this.imageConfigError = config.error\n this.imageUnusable = config.unusable\n onBuildLogs?.(\n new LogEntry(\n new Date(),\n 'warn',\n `Could not read ${this.baseImage}: ${config.error}. ` +\n 'The template will build without the environment, working directory ' +\n 'and start command the image declares.'\n )\n )\n return\n }\n\n // The image is the base, the caller's own calls override it -- so the\n // inherited names go under what setEnvs already recorded.\n this.envs = { ...config.env, ...this.envs }\n\n if (\n config.workdir &&\n !this.instructions.some(i => i.type === InstructionType.WORKDIR)\n ) {\n this.instructions.push({\n type: InstructionType.WORKDIR,\n args: [config.workdir],\n force: false,\n })\n }\n\n const startCmd = effectiveStartCmd(config.entrypoint, config.cmd)\n if (startCmd && this.startCmd === undefined) {\n this.startCmd = startCmd\n // setStartCmd requires a readiness check, and without one the SDK's own\n // Dockerfile parser pairs the command with waitForTimeout(20_000). Kept\n // byte-identical so an image built through fromImage behaves the same as\n // one built from its Dockerfile -- note this is a timer, not a health\n // check: pass setReadyCmd for a real one.\n this.readyCmd = this.readyCmd ?? waitForTimeout(20_000).getCmd()\n }\n }\n\n /**\n * Why the base image's declared config is missing, or undefined when nothing\n * was missing. Populated once the template has been serialized or built.\n *\n * `unusable` means the read succeeded and the image still cannot be used here\n * -- no linux/amd64 variant, or the reference names nothing. A retry cannot\n * change it, and the build would fail for the same reason minutes later, so a\n * caller converting images in bulk should skip rather than build.\n *\n * `error` alone means the read itself failed. The template builds without the\n * image's environment, working directory and start command.\n */\n static imageConfigFailure(\n template: TemplateClass\n ): { error: string; unusable?: string } | undefined {\n const base = template as TemplateBase\n if (base.imageConfigError === undefined) {\n return undefined\n }\n return base.imageUnusable === undefined\n ? { error: base.imageConfigError }\n : { error: base.imageConfigError, unusable: base.imageUnusable }\n }\n\n skipCache(): this {\n this.forceNextLayer = true\n return this\n }\n\n betaDevContainerPrebuild(devcontainerDirectory: string): TemplateBuilder {\n if (this.baseTemplate !== 'devcontainer') {\n throw new BuildError(\n 'Devcontainers can only used in the devcontainer template',\n getCallerFrame(STACK_TRACE_DEPTH - 1)\n )\n }\n\n return this.runInNewStackTraceContext(() => {\n return this.runCmd(\n `devcontainer build --workspace-folder ${devcontainerDirectory}`,\n { user: 'root' }\n )\n })\n }\n\n betaSetDevContainerStart(devcontainerDirectory: string): TemplateFinal {\n if (this.baseTemplate !== 'devcontainer') {\n throw new BuildError(\n 'Devcontainers can only used in the devcontainer template',\n getCallerFrame(STACK_TRACE_DEPTH - 1)\n )\n }\n\n return this.runInNewStackTraceContext(() => {\n return this.setStartCmd(\n `sudo devcontainer up --workspace-folder ${devcontainerDirectory} && sudo /prepare-exec.sh ${devcontainerDirectory} | sudo tee /devcontainer.sh > /dev/null && sudo chmod +x /devcontainer.sh && sudo touch /devcontainer.up`,\n waitForFile('/devcontainer.up')\n )\n })\n }\n\n /**\n * Collect the current stack trace for debugging purposes.\n *\n * @param stackTracesDepth Depth to traverse in the call stack\n * @returns this for method chaining\n */\n private collectStackTrace(stackTracesDepth: number = STACK_TRACE_DEPTH) {\n if (!this.stackTracesEnabled) {\n return this\n }\n\n if (this.stackTracesOverride) {\n this.stackTraces.push(this.stackTracesOverride)\n return this\n }\n\n this.stackTraces.push(getCallerFrame(stackTracesDepth))\n return this\n }\n\n /**\n * Temporarily disable stack trace collection.\n *\n * @returns this for method chaining\n */\n private disableStackTrace() {\n this.stackTracesEnabled = false\n return this\n }\n\n /**\n * Re-enable stack trace collection.\n *\n * @returns this for method chaining\n */\n private enableStackTrace() {\n this.stackTracesEnabled = true\n return this\n }\n\n /**\n * Execute a function in a clean stack trace context.\n *\n * @param fn Function to execute\n * @returns The result of the function\n */\n private runInNewStackTraceContext<T>(fn: () => T): T {\n this.disableStackTrace()\n const result = fn()\n this.enableStackTrace()\n this.collectStackTrace(STACK_TRACE_DEPTH + 1)\n return result\n }\n\n private runInStackTraceOverrideContext<T>(\n fn: () => T,\n stackTraceOverride: string | undefined\n ): T {\n this.stackTracesOverride = stackTraceOverride\n const result = fn()\n this.stackTracesOverride = undefined\n return result\n }\n\n /**\n * Convert the template to JSON representation.\n *\n * @param computeHashes Whether to compute file hashes for COPY instructions\n * @returns JSON string representation of the template\n */\n private async toJSON(computeHashes: boolean): Promise<string> {\n await this.resolveInheritedConfig()\n\n let instructions = this.instructions\n if (computeHashes) {\n instructions = await this.instructionsWithHashes()\n }\n\n return JSON.stringify(\n this.serialize(this.withRuntimeEnv(instructions)),\n undefined,\n 2\n )\n }\n\n /**\n * Convert the template to Dockerfile format.\n *\n * Note: Only templates based on Docker images can be converted to Dockerfile.\n * Templates based on other PPIO sandbox templates cannot be converted because they\n * may use features not available in standard Dockerfiles.\n *\n * @returns Dockerfile string representation\n * @throws Error if template is based on another PPIO sandbox template or has no base image\n */\n private toDockerfile(): string {\n if (this.baseTemplate !== undefined) {\n throw new Error(\n 'Cannot convert template built from another template to Dockerfile. ' +\n 'Templates based on other templates can only be built using the PPIO sandbox API.'\n )\n }\n\n if (this.baseImage === undefined) {\n throw new Error('No base image specified for template')\n }\n\n let dockerfile = `FROM ${this.baseImage}\\n`\n for (const instruction of this.instructions) {\n if (instruction.type === InstructionType.RUN) {\n dockerfile += `RUN ${instruction.args[0]}\\n`\n continue\n }\n if (instruction.type === InstructionType.COPY) {\n dockerfile += `COPY ${instruction.args[0]} ${instruction.args[1]}\\n`\n continue\n }\n if (instruction.type === InstructionType.ENV) {\n const values: string[] = []\n for (let i = 0; i < instruction.args.length; i += 2) {\n values.push(`${instruction.args[i]}=${instruction.args[i + 1]}`)\n }\n dockerfile += `ENV ${values.join(' ')}\\n`\n continue\n }\n dockerfile += `${instruction.type} ${instruction.args.join(' ')}\\n`\n }\n if (this.startCmd) {\n dockerfile += `ENTRYPOINT ${this.startCmd}\\n`\n }\n return dockerfile\n }\n\n /**\n * Internal implementation of the template build process.\n *\n * @param client API client for communicating with PPIO sandbox backend\n * @param name Template name in 'name' or 'name:tag' format\n * @param tags Additional tags to assign to the build\n * @param options Build configuration options\n * @throws BuildError if the build fails\n */\n private async build(\n client: ApiClient,\n name: string,\n options: Omit<BuildOptions, 'alias'>\n ): Promise<BuildInfo> {\n if (options.skipCache) {\n this.force = true\n }\n\n // Create template\n options.onBuildLogs?.(\n new LogEntry(\n new Date(),\n 'info',\n `Requesting build for template: ${name}${options.tags && options.tags.length > 0 ? ` with tags ${options.tags.join(', ')}` : ''}`\n )\n )\n\n const {\n templateID,\n buildID,\n tags: responseTags,\n } = await requestBuild(client, {\n name,\n tags: options.tags,\n cpuCount: options.cpuCount ?? 2,\n memoryMB: options.memoryMB ?? 1024,\n })\n\n options.onBuildLogs?.(\n new LogEntry(\n new Date(),\n 'info',\n `Template created with ID: ${templateID}, Build ID: ${buildID}`\n )\n )\n\n // Before the instructions are assembled: this can add a WORKDIR step and set\n // the start command, both of which have to be in the payload below.\n await this.resolveInheritedConfig(options.onBuildLogs)\n\n const instructionsWithHashes = await this.instructionsWithHashes()\n\n // Upload files in parallel\n const uploadPromises = instructionsWithHashes.map(\n async (instruction, index) => {\n if (instruction.type !== InstructionType.COPY) {\n return\n }\n\n const src = instruction.args.length > 0 ? instruction.args[0] : null\n const filesHash = instruction.filesHash ?? null\n if (src === null || filesHash === null) {\n throw new Error('Source path and files hash are required')\n }\n\n const forceUpload = instruction.forceUpload\n let stackTrace = undefined\n if (index + 1 >= 0 && index + 1 < this.stackTraces.length) {\n stackTrace = this.stackTraces[index + 1]\n }\n\n const { present, url } = await getFileUploadLink(\n client,\n {\n templateID,\n filesHash,\n },\n stackTrace\n )\n\n if (\n (forceUpload && url != null) ||\n (present === false && url != null)\n ) {\n await uploadFile(\n {\n fileName: src,\n fileContextPath: this.fileContextPath.toString(),\n url,\n ignorePatterns: [\n ...this.fileIgnorePatterns,\n ...readDockerignore(this.fileContextPath.toString()),\n ],\n resolveSymlinks: instruction.resolveSymlinks ?? RESOLVE_SYMLINKS,\n },\n stackTrace\n )\n options.onBuildLogs?.(\n new LogEntry(new Date(), 'info', `Uploaded '${src}'`)\n )\n } else {\n options.onBuildLogs?.(\n new LogEntry(\n new Date(),\n 'info',\n `Skipping upload of '${src}', already cached`\n )\n )\n }\n }\n )\n\n await Promise.all(uploadPromises)\n\n options.onBuildLogs?.(\n new LogEntry(new Date(), 'info', 'All file uploads completed')\n )\n\n // Start build\n options.onBuildLogs?.(\n new LogEntry(new Date(), 'info', 'Starting building...')\n )\n\n await triggerBuild(client, {\n templateID,\n buildID,\n template: this.serialize(this.withRuntimeEnv(instructionsWithHashes)),\n })\n\n return {\n alias: name,\n name: name,\n tags: responseTags,\n templateId: templateID,\n buildId: buildID,\n }\n }\n\n /**\n * Add file hashes to COPY instructions for cache invalidation.\n *\n * @returns Copy of instructions array with filesHash added to COPY instructions\n */\n private async instructionsWithHashes(): Promise<Instruction[]> {\n return Promise.all(\n this.instructions.map(async (instruction, index) => {\n if (instruction.type !== InstructionType.COPY) {\n return instruction\n }\n\n const src = instruction.args.length > 0 ? instruction.args[0] : null\n const dest = instruction.args.length > 1 ? instruction.args[1] : null\n if (src === null || dest === null) {\n throw new Error('Source path and destination path are required')\n }\n\n let stackTrace = undefined\n if (index + 1 >= 0 && index + 1 < this.stackTraces.length) {\n stackTrace = this.stackTraces[index + 1]\n }\n\n return {\n ...instruction,\n filesHash: await calculateFilesHash(\n src,\n dest,\n this.fileContextPath.toString(),\n [\n ...this.fileIgnorePatterns,\n ...(runtime === 'browser'\n ? []\n : readDockerignore(this.fileContextPath.toString())),\n ],\n instruction.resolveSymlinks ?? RESOLVE_SYMLINKS,\n stackTrace\n ),\n }\n })\n )\n }\n\n /**\n * Serialize the template to the API request format.\n *\n * @param steps Array of build instructions with file hashes\n * @returns Template data formatted for the API\n */\n private serialize(steps: Instruction[]): TriggerBuildTemplate {\n const templateData: TriggerBuildTemplate = {\n startCmd: this.startCmd,\n readyCmd: this.readyCmd,\n preBootScript: this.patchCmd,\n steps,\n force: this.force,\n }\n\n if (this.baseImage !== undefined) {\n templateData.fromImage = this.baseImage\n }\n\n if (this.baseTemplate !== undefined) {\n templateData.fromTemplate = this.baseTemplate\n }\n\n if (this.registryConfig !== undefined) {\n templateData.fromImageRegistry = this.registryConfig\n }\n\n return templateData\n }\n}\n\n/**\n * Create a new PPIO sandbox template builder instance.\n *\n * @param options Optional configuration for the template builder\n * @returns A new template builder instance\n *\n * @example\n * ```ts\n * import { Template } from 'ppio-sandbox'\n *\n * const template = Template()\n * .fromPythonImage('3')\n * .copy('requirements.txt', '/app/')\n * .pipInstall()\n *\n * await Template.build(template, 'my-python-app:v1.0')\n * ```\n */\nexport function Template(options?: TemplateOptions): TemplateFromImage {\n return new TemplateBase(options)\n}\n\nTemplate.build = TemplateBase.build\nTemplate.buildInBackground = TemplateBase.buildInBackground\nTemplate.getBuildStatus = TemplateBase.getBuildStatus\nTemplate.get = TemplateBase.get\nTemplate.exists = TemplateBase.exists\nTemplate.aliasExists = TemplateBase.aliasExists\nTemplate.assignTags = TemplateBase.assignTags\nTemplate.removeTags = TemplateBase.removeTags\nTemplate.getTags = TemplateBase.getTags\nTemplate.list = TemplateBase.list\nTemplate.delete = TemplateBase.delete\nTemplate.toJSON = TemplateBase.toJSON\nTemplate.toDockerfile = TemplateBase.toDockerfile\n\nexport type {\n BuildInfo,\n BuildOptions,\n BuildStatusReason,\n CopyItem,\n GetBuildStatusOptions,\n McpServerName,\n TemplateBuilder,\n TemplateBuildStatus,\n TemplateBuildStatusResponse,\n TemplateClass,\n TemplateDeleteOpts,\n TemplateInfo,\n TemplateListOpts,\n TemplateListOptions,\n TemplateListResponse,\n TemplateTag,\n TemplateTagInfo,\n TemplateType,\n} from './types'\n","import { ApiClient, handleApiError } from '../api'\nimport {\n ConnectionConfig,\n ConnectionOpts,\n raiseIfLegacy,\n validateDomain,\n} from '../connectionConfig'\nimport { NotFoundError, VolumeError } from '../errors'\nimport type {\n VolumeAndToken,\n VolumeInfo,\n} from './types'\n\nfunction quotaInodesForSize(quotaSizeGiB: number) {\n return quotaSizeGiB * 1000\n}\n\n/**\n * Module for interacting with PPIO sandbox volumes.\n *\n * Use the static methods to manage volumes or create a `Volume` instance\n * to pass volume references to sandbox operations.\n */\nexport class Volume {\n /**\n * Volume ID.\n */\n readonly volumeId: string\n\n /**\n * Volume name.\n */\n readonly name: string\n\n /**\n * Volume auth token.\n */\n readonly token: string\n\n /**\n * Domain used for constructing the volume API URL.\n */\n readonly domain?: string\n\n /**\n * Whether to use debug mode (connects to local volume API server).\n */\n readonly debug?: boolean\n\n /**\n * Create a local Volume instance with no API call.\n *\n * @param volumeId volume ID.\n * @param name volume name.\n * @param token volume auth token.\n * @param domain domain for the volume API.\n * @param debug whether to use debug mode.\n */\n constructor(\n volumeId: string,\n name: string,\n token: string,\n domain?: string,\n debug?: boolean\n ) {\n if (domain) {\n validateDomain(domain)\n }\n this.volumeId = volumeId\n this.name = name\n this.token = token\n this.domain = domain\n this.debug = debug\n }\n\n /**\n * Create a new volume.\n *\n * @param name name of the volume.\n * @param opts connection options.\n * @param [opts.quotaSizeGiB] capacity quota in GiB.\n *\n * @returns new Volume instance.\n */\n static async create(name: string, opts?: ConnectionOpts & {\n quotaSizeGiB?: number\n }): Promise<Volume> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Volume.create', VolumeError)\n\n const client = new ApiClient(config)\n const body: {\n name: string\n quotaSizeGiB?: number\n quotaInodes?: number\n } = { name }\n\n if (opts?.quotaSizeGiB !== undefined) {\n body.quotaSizeGiB = opts.quotaSizeGiB\n body.quotaInodes = quotaInodesForSize(opts.quotaSizeGiB)\n }\n\n const res = await client.api.POST('/volumes', {\n body,\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n const err = handleApiError(res, VolumeError)\n if (err) {\n throw err\n }\n\n if (!res.data) {\n throw new Error('Response data is missing')\n }\n\n return new Volume(\n res.data.volumeID,\n res.data.name,\n res.data.token,\n config.domain,\n config.debug\n )\n }\n\n /**\n * Connect to an existing volume by ID.\n *\n * @param volumeId volume ID.\n * @param opts connection options.\n *\n * @returns Volume instance.\n */\n static async connect(\n volumeId: string,\n opts?: ConnectionOpts\n ): Promise<Volume> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Volume.connect', VolumeError)\n const { name, token } = await Volume.getInfo(volumeId, opts)\n return new Volume(volumeId, name, token, config.domain, config.debug)\n }\n\n /**\n * Get volume information.\n *\n * @param volumeId volume ID.\n * @param opts connection options.\n *\n * @returns volume information.\n */\n static async getInfo(\n volumeId: string,\n opts?: ConnectionOpts\n ): Promise<VolumeAndToken> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Volume.getInfo', VolumeError)\n\n const client = new ApiClient(config)\n\n const res = await client.api.GET('/volumes/{volumeID}', {\n params: {\n path: {\n volumeID: volumeId,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.response.status === 404) {\n throw new NotFoundError(`Volume ${volumeId} not found`)\n }\n\n const err = handleApiError(res, VolumeError)\n if (err) {\n throw err\n }\n\n const data = res.data as any\n\n return {\n volumeId: data.volumeID,\n name: data.name,\n token: data.token,\n quotaSizeGiB: data.quotaSizeGiB ?? 0,\n usedSizeBytes: data.usedSizeBytes ?? 0,\n }\n }\n\n /**\n * List all volumes.\n *\n * @param opts connection options.\n *\n * @returns list of volume information.\n */\n static async list(opts?: ConnectionOpts): Promise<VolumeInfo[]> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Volume.list', VolumeError)\n\n const client = new ApiClient(config)\n\n const res = await client.api.GET('/volumes', {\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n const err = handleApiError(res, VolumeError)\n if (err) {\n throw err\n }\n\n return ((res.data ?? []) as any[]).map((vol: any) => ({\n volumeId: vol.volumeID,\n name: vol.name,\n quotaSizeGiB: vol.quotaSizeGiB ?? 0,\n usedSizeBytes: vol.usedSizeBytes ?? 0,\n }))\n }\n\n /**\n * Update volume quota.\n *\n * @param volumeId volume ID.\n * @param params quota parameters.\n * @param opts connection options.\n *\n * @returns updated volume information.\n */\n static async updateQuota(\n volumeId: string,\n params: { quotaSizeGiB?: number },\n opts?: ConnectionOpts\n ): Promise<VolumeAndToken> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Volume.updateQuota', VolumeError)\n const body: {\n quotaSizeGiB?: number\n quotaInodes?: number\n } = {}\n\n if (params.quotaSizeGiB !== undefined) {\n body.quotaSizeGiB = params.quotaSizeGiB\n body.quotaInodes = quotaInodesForSize(params.quotaSizeGiB)\n }\n\n const res = await fetch(\n `${config.apiUrl}/volumes/${encodeURIComponent(volumeId)}`,\n {\n method: 'PATCH',\n headers: {\n ...config.headers,\n 'Content-Type': 'application/json',\n ...(config.apiKey ? { 'X-API-KEY': config.apiKey } : {}),\n ...(config.accessToken\n ? { Authorization: `Bearer ${config.accessToken}` }\n : {}),\n },\n body: JSON.stringify(body),\n signal: config.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n if (res.status === 404) {\n throw new NotFoundError(`Volume ${volumeId} not found`)\n }\n\n if (!res.ok) {\n throw new VolumeError(`${res.status}: ${res.statusText}`)\n }\n\n const data = await res.json()\n return {\n volumeId: data.volumeID,\n name: data.name,\n token: data.token,\n quotaSizeGiB: data.quotaSizeGiB ?? 0,\n usedSizeBytes: data.usedSizeBytes ?? 0,\n }\n }\n\n /**\n * Destroy a volume.\n *\n * @param volumeId volume ID.\n * @param opts connection options.\n */\n static async destroy(\n volumeId: string,\n opts?: ConnectionOpts\n ): Promise<boolean> {\n const config = new ConnectionConfig(opts)\n\n raiseIfLegacy(config, 'Volume.destroy', VolumeError)\n\n const client = new ApiClient(config)\n\n const res = await client.api.DELETE('/volumes/{volumeID}', {\n params: {\n path: {\n volumeID: volumeId,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.response.status === 404) {\n return false\n }\n\n const err = handleApiError(res, VolumeError)\n if (err) {\n throw err\n }\n\n return true\n }\n}\n\nexport type {\n VolumeInfo,\n VolumeAndToken,\n} from './types'\n","import { NotFoundError, SandboxError, TimeoutError } from '../core'\nimport { ChartTypes } from './charts'\n\nexport async function extractError(res: Response) {\n if (res.ok) {\n return\n }\n\n switch (res.status) {\n case 502:\n return new TimeoutError(\n `${await res.text()}: This error is likely due to sandbox timeout. You can modify the sandbox timeout by passing 'timeoutMs' when starting the sandbox or calling '.setTimeout' on the sandbox with the desired timeout.`\n )\n case 404:\n return new NotFoundError(await res.text())\n default:\n return new SandboxError(`${res.status} ${res.statusText}`)\n }\n}\n\n/**\n * Represents an output message from the sandbox code execution.\n */\nexport class OutputMessage {\n constructor(\n /**\n * The output line.\n */\n public readonly line: string,\n /**\n * Unix epoch in nanoseconds.\n */\n public readonly timestamp: number,\n /**\n * Whether the output is an error.\n */\n public readonly error: boolean\n ) { }\n\n public toString() {\n return this.line\n }\n}\n\n/**\n * Represents an error that occurred during the execution of a cell.\n * The error contains the name of the error, the value of the error, and the traceback.\n */\nexport class ExecutionError {\n constructor(\n /**\n * Name of the error.\n **/\n public name: string,\n /**\n * Value of the error.\n **/\n public value: string,\n /**\n * The raw traceback of the error.\n **/\n public traceback: string\n ) { }\n}\n\n/**\n * Represents a MIME type.\n */\nexport type MIMEType = string\n\n\ntype PPIOSandboxData = {\n data: Record<string, unknown>\n chart: ChartTypes\n}\n\n/**\n * Dictionary that maps MIME types to their corresponding representations of the data.\n */\nexport type RawData = {\n [key: MIMEType]: string\n} & PPIOSandboxData\n\n/**\n * Represents the data to be displayed as a result of executing a cell in a Jupyter notebook.\n * The result is similar to the structure returned by ipython kernel: https://ipython.readthedocs.io/en/stable/development/execution.html#execution-semantics\n *\n *\n * The result can contain multiple types of data, such as text, images, plots, etc. Each type of data is represented\n * as a string, and the result can contain multiple types of data. The display calls don't have to have text representation,\n * for the actual result the representation is always present for the result, the other representations are always optional.\n */\nexport class Result {\n /**\n * Text representation of the result.\n */\n readonly text?: string\n /**\n * HTML representation of the data.\n */\n readonly html?: string\n /**\n * Markdown representation of the data.\n */\n readonly markdown?: string\n /**\n * SVG representation of the data.\n */\n readonly svg?: string\n /**\n * PNG representation of the data.\n */\n readonly png?: string\n /**\n * JPEG representation of the data.\n */\n readonly jpeg?: string\n /**\n * PDF representation of the data.\n */\n readonly pdf?: string\n /**\n * LaTeX representation of the data.\n */\n readonly latex?: string\n /**\n * JSON representation of the data.\n */\n readonly json?: string\n /**\n * JavaScript representation of the data.\n */\n readonly javascript?: string\n /**\n * Contains the data from DataFrame.\n */\n readonly data?: Record<string, unknown>\n /**\n * Contains the chart data.\n */\n readonly chart?: ChartTypes\n /**\n * Extra data that can be included. Not part of the standard types.\n */\n readonly extra?: any\n\n readonly raw: RawData\n\n constructor(rawData: RawData, public readonly isMainResult: boolean) {\n const data = { ...rawData }\n delete data['type']\n delete data['is_main_result']\n\n this.text = data['text']\n this.html = data['html']\n this.markdown = data['markdown']\n this.svg = data['svg']\n this.png = data['png']\n this.jpeg = data['jpeg']\n this.pdf = data['pdf']\n this.latex = data['latex']\n this.json = data['json']\n this.javascript = data['javascript']\n this.isMainResult = isMainResult\n this.raw = data\n\n this.data = data['data']\n this.chart = data['chart']\n\n this.extra = {}\n\n for (const key of Object.keys(data)) {\n if (\n ![\n 'plain',\n 'html',\n 'markdown',\n 'svg',\n 'png',\n 'jpeg',\n 'pdf',\n 'latex',\n 'json',\n 'javascript',\n 'data',\n 'chart',\n 'extra',\n \"text\"\n ].includes(key)\n ) {\n this.extra[key] = data[key]\n }\n }\n }\n\n /**\n * Returns all the formats available for the result.\n *\n * @returns Array of strings representing the formats available for the result.\n */\n formats(): string[] {\n const formats = []\n if (this.html) {\n formats.push('html')\n }\n if (this.markdown) {\n formats.push('markdown')\n }\n if (this.svg) {\n formats.push('svg')\n }\n if (this.png) {\n formats.push('png')\n }\n if (this.jpeg) {\n formats.push('jpeg')\n }\n if (this.pdf) {\n formats.push('pdf')\n }\n if (this.latex) {\n formats.push('latex')\n }\n if (this.json) {\n formats.push('json')\n }\n if (this.javascript) {\n formats.push('javascript')\n }\n if (this.data) {\n formats.push('data')\n }\n\n for (const key of Object.keys(this.extra)) {\n formats.push(key)\n }\n\n return formats\n }\n\n /**\n * Returns the serializable representation of the result.\n */\n toJSON() {\n return {\n text: this.text,\n html: this.html,\n markdown: this.markdown,\n svg: this.svg,\n png: this.png,\n jpeg: this.jpeg,\n pdf: this.pdf,\n latex: this.latex,\n json: this.json,\n javascript: this.javascript,\n ...(Object.keys(this.extra).length > 0 ? { extra: this.extra } : {}),\n }\n }\n}\n\n/**\n * Data printed to stdout and stderr during execution, usually by print statements, logs, warnings, subprocesses, etc.\n */\nexport type Logs = {\n /**\n * List of strings printed to stdout by prints, subprocesses, etc.\n */\n stdout: string[]\n /**\n * List of strings printed to stderr by prints, subprocesses, etc.\n */\n stderr: string[]\n}\n\n/**\n * Represents the result of a cell execution.\n */\nexport class Execution {\n constructor(\n /**\n * List of result of the cell (interactively interpreted last line), display calls (e.g. matplotlib plots).\n */\n public results: Result[] = [],\n /**\n * Logs printed to stdout and stderr during execution.\n */\n public logs: Logs = { stdout: [], stderr: [] },\n /**\n * An Error object if an error occurred, null otherwise.\n */\n public error?: ExecutionError,\n /**\n * Execution count of the cell.\n */\n public executionCount?: number\n ) { }\n\n /**\n * Returns the text representation of the main result of the cell.\n */\n get text(): string | undefined {\n for (const data of this.results) {\n if (data.isMainResult) {\n return data.text\n }\n }\n }\n\n /**\n * Returns the serializable representation of the execution result.\n */\n toJSON() {\n return {\n results: this.results,\n logs: this.logs,\n error: this.error,\n }\n }\n}\n\nexport async function parseOutput(\n execution: Execution,\n line: string,\n onStdout?: (output: OutputMessage) => Promise<any> | any,\n onStderr?: (output: OutputMessage) => Promise<any> | any,\n onResult?: (data: Result) => Promise<any> | any,\n onError?: (error: ExecutionError) => Promise<any> | any\n) {\n const msg = JSON.parse(line)\n\n switch (msg.type) {\n case 'result':\n const result = new Result(\n { ...msg, type: undefined, is_main_result: undefined },\n msg.is_main_result\n )\n execution.results.push(result)\n if (onResult) {\n await onResult(result)\n }\n break\n case 'stdout':\n execution.logs.stdout.push(msg.text)\n if (onStdout) {\n await onStdout({\n error: false,\n line: msg.text,\n timestamp: new Date().getTime() * 1000,\n })\n }\n break\n case 'stderr':\n execution.logs.stderr.push(msg.text)\n if (onStderr) {\n await onStderr({\n error: true,\n line: msg.text,\n timestamp: new Date().getTime() * 1000,\n })\n }\n break\n case 'error':\n execution.error = new ExecutionError(msg.name, msg.value, msg.traceback)\n if (onError) {\n await onError(execution.error)\n }\n break\n case 'number_of_executions':\n execution.executionCount = msg.execution_count\n break\n }\n}\n","import { TimeoutError } from '../core'\n\nexport function formatRequestTimeoutError(error: unknown) {\n if (error instanceof Error && error.name === 'AbortError') {\n return new TimeoutError('Request timed out — the \\'requestTimeoutMs\\' option can be used to increase this timeout')\n }\n\n return error\n}\n\nexport function formatExecutionTimeoutError(error: unknown) {\n if (error instanceof Error && error.name === 'AbortError') {\n return new TimeoutError('Execution timed out — the \\'timeoutMs\\' option can be used to increase this timeout')\n }\n\n return error\n}\n\nexport async function* readLines(stream: ReadableStream<Uint8Array>) {\n const reader = stream.getReader();\n let buffer = ''\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n\n if (value !== undefined) {\n buffer += new TextDecoder().decode(value)\n }\n\n if (done) {\n if (buffer.length > 0) {\n yield buffer\n }\n break\n }\n\n let newlineIdx = -1\n\n do {\n newlineIdx = buffer.indexOf('\\n')\n if (newlineIdx !== -1) {\n yield buffer.slice(0, newlineIdx)\n buffer = buffer.slice(newlineIdx + 1)\n }\n } while (newlineIdx !== -1)\n }\n } finally {\n reader.releaseLock()\n }\n}\n","export const DEFAULT_TIMEOUT_MS = 60_000 // 1 minute\nexport const JUPYTER_PORT = 49999\n","import { Sandbox as BaseSandbox, InvalidArgumentError } from '../core'\n\nimport {\n Result,\n Execution,\n OutputMessage,\n parseOutput,\n extractError,\n ExecutionError,\n} from './messaging'\nimport {\n formatExecutionTimeoutError,\n formatRequestTimeoutError,\n readLines,\n} from './utils'\nimport { JUPYTER_PORT, DEFAULT_TIMEOUT_MS } from './consts'\n\n/**\n * Represents a context for code execution.\n */\nexport type Context = {\n /**\n * The ID of the context.\n */\n id: string\n /**\n * The language of the context.\n */\n language: string\n /**\n * The working directory of the context.\n */\n cwd: string\n}\n\n/**\n * Options for running code.\n */\nexport interface RunCodeOpts {\n /**\n * Callback for handling stdout messages.\n */\n onStdout?: (output: OutputMessage) => Promise<any> | any\n /**\n * Callback for handling stderr messages.\n */\n onStderr?: (output: OutputMessage) => Promise<any> | any\n /**\n * Callback for handling the final execution result.\n */\n onResult?: (data: Result) => Promise<any> | any\n /**\n * Callback for handling the `ExecutionError` object.\n */\n onError?: (error: ExecutionError) => Promise<any> | any\n /**\n * Custom environment variables for code execution.\n *\n * @default {}\n */\n envs?: Record<string, string>\n /**\n * Timeout for the code execution in **milliseconds**.\n *\n * @default 60_000 // 60 seconds\n */\n timeoutMs?: number\n /**\n * Timeout for the request in **milliseconds**.\n *\n * @default 30_000 // 30 seconds\n */\n requestTimeoutMs?: number\n}\n\n/**\n * Options for creating a code context.\n */\nexport interface CreateCodeContextOpts {\n /**\n * Working directory for the context.\n *\n * @default /home/user\n */\n cwd?: string\n /**\n * Language for the context.\n *\n * @default python\n */\n language?: string\n /**\n * Timeout for the request in **milliseconds**.\n *\n * @default 30_000 // 30 seconds\n */\n requestTimeoutMs?: number\n}\n\n/**\n * Options for code context management requests.\n */\nexport interface CodeContextRequestOpts {\n /**\n * Timeout for the request in **milliseconds**.\n *\n * @default 30_000 // 30 seconds\n */\n requestTimeoutMs?: number\n}\n\n/**\n * PPIO agent sandbox is a secure and isolated cloud environment.\n *\n * The sandbox allows you to:\n * - Access Linux OS\n * - Create, list, and delete files and directories\n * - Run commands\n * - Run isolated code\n * - Access the internet\n *\n * Check docs [here](https://ppio.com/docs/sandbox/overview).\n *\n * Use {@link Sandbox.create} to create a new sandbox.\n *\n * @example\n * ```ts\n * import { Sandbox } from '@ppio-sandbox/code-interpreter'\n *\n * const sandbox = await Sandbox.create()\n * ```\n */\nexport class Sandbox extends BaseSandbox {\n protected static override readonly defaultTemplate: string =\n 'code-interpreter-v1'\n\n /**\n * Run the code as Python.\n *\n * Specify the `language` or `context` option to run the code as a different language or in a different `Context`.\n *\n * You can reference previously defined variables, imports, and functions in the code.\n *\n * @param code code to execute.\n * @param opts options for executing the code.\n *\n * @returns `Execution` result object.\n */\n async runCode(\n code: string,\n opts?: RunCodeOpts & {\n /**\n * Language to use for code execution.\n *\n * If not defined, the default Python context is used.\n */\n language?: 'python'\n }\n ): Promise<Execution>\n /**\n * Run the code for the specified language.\n *\n * Specify the `language` or `context` option to run the code as a different language or in a different `Context`.\n * If no language is specified, Python is used.\n *\n * You can reference previously defined variables, imports, and functions in the code.\n *\n * @param code code to execute.\n * @param opts options for executing the code.\n *\n * @returns `Execution` result object.\n */\n async runCode(\n code: string,\n opts?: RunCodeOpts & {\n /**\n * Language to use for code execution.\n *\n * If not defined, the default Python context is used.\n */\n language?: string\n }\n ): Promise<Execution>\n /**\n * Runs the code in the specified context, if not specified, the default context is used.\n *\n * Specify the `language` or `context` option to run the code as a different language or in a different `Context`.\n *\n * You can reference previously defined variables, imports, and functions in the code.\n *\n * @param code code to execute.\n * @param opts options for executing the code\n *\n * @returns `Execution` result object\n */\n async runCode(\n code: string,\n opts?: RunCodeOpts & {\n /**\n * Context to run the code in.\n */\n context?: Context\n }\n ): Promise<Execution>\n async runCode(\n code: string,\n opts?: RunCodeOpts & {\n language?: string\n context?: Context\n }\n ): Promise<Execution> {\n if (opts?.context && opts?.language) {\n throw new InvalidArgumentError(\n 'You can provide context or language, but not both at the same time.'\n )\n }\n\n const controller = new AbortController()\n\n const requestTimeout =\n opts?.requestTimeoutMs ?? this.connectionConfig.requestTimeoutMs\n\n const reqTimer = requestTimeout\n ? setTimeout(() => {\n controller.abort()\n }, requestTimeout)\n : undefined\n\n try {\n const res = await fetch(`${this.jupyterUrl}/execute`, {\n method: 'POST',\n headers: this.jupyterHeaders,\n body: JSON.stringify({\n code,\n context_id: opts?.context?.id,\n language: opts?.language,\n env_vars: opts?.envs,\n }),\n signal: controller.signal,\n keepalive: true,\n })\n\n const error = await extractError(res)\n if (error) {\n throw error\n }\n\n if (!res.body) {\n throw new Error(\n `Not response body: ${res.statusText} ${await res?.text()}`\n )\n }\n\n clearTimeout(reqTimer)\n\n const bodyTimeout = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS\n\n const bodyTimer = bodyTimeout\n ? setTimeout(() => {\n controller.abort()\n }, bodyTimeout)\n : undefined\n\n const execution = new Execution()\n\n try {\n for await (const chunk of readLines(res.body)) {\n await parseOutput(\n execution,\n chunk,\n opts?.onStdout,\n opts?.onStderr,\n opts?.onResult,\n opts?.onError\n )\n }\n } catch (error) {\n throw formatExecutionTimeoutError(error)\n } finally {\n clearTimeout(bodyTimer)\n }\n\n return execution\n } catch (error) {\n throw formatRequestTimeoutError(error)\n }\n }\n\n /**\n * Creates a new context to run code in.\n *\n * @param opts options for creating the context.\n *\n * @returns context object.\n */\n async createCodeContext(opts?: CreateCodeContextOpts): Promise<Context> {\n try {\n const res = await fetch(`${this.jupyterUrl}/contexts`, {\n method: 'POST',\n headers: this.jupyterHeaders,\n body: JSON.stringify({\n language: opts?.language,\n cwd: opts?.cwd,\n }),\n keepalive: true,\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n })\n\n const error = await extractError(res)\n if (error) {\n throw error\n }\n\n return (await res.json()) as Context\n } catch (error) {\n throw formatRequestTimeoutError(error)\n }\n }\n\n /**\n * Lists all code execution contexts in the sandbox.\n *\n * @param opts options for the request.\n *\n * @returns array of context objects.\n */\n async listCodeContexts(opts?: CodeContextRequestOpts): Promise<Context[]> {\n try {\n const res = await fetch(`${this.jupyterUrl}/contexts`, {\n method: 'GET',\n headers: this.jupyterHeaders,\n keepalive: true,\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n })\n\n const error = await extractError(res)\n if (error) {\n throw error\n }\n\n const data = await res.json()\n return Array.isArray(data) ? data : (data.contexts ?? [])\n } catch (error) {\n throw formatRequestTimeoutError(error)\n }\n }\n\n /**\n * Removes a code execution context from the sandbox.\n *\n * @param context context object or context ID to remove.\n * @param opts options for the request.\n */\n async removeCodeContext(\n context: Context | string,\n opts?: CodeContextRequestOpts\n ): Promise<void> {\n const contextID = typeof context === 'string' ? context : context.id\n\n try {\n const res = await fetch(\n `${this.jupyterUrl}/contexts/${encodeURIComponent(contextID)}`,\n {\n method: 'DELETE',\n headers: this.jupyterHeaders,\n keepalive: true,\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n const error = await extractError(res)\n if (error) {\n throw error\n }\n } catch (error) {\n throw formatRequestTimeoutError(error)\n }\n }\n\n /**\n * Restarts a code execution context in the sandbox.\n *\n * @param context context object or context ID to restart.\n * @param opts options for the request.\n */\n async restartCodeContext(\n context: Context | string,\n opts?: CodeContextRequestOpts\n ): Promise<void> {\n const contextID = typeof context === 'string' ? context : context.id\n\n try {\n const res = await fetch(\n `${this.jupyterUrl}/contexts/${encodeURIComponent(contextID)}/restart`,\n {\n method: 'POST',\n headers: this.jupyterHeaders,\n keepalive: true,\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n const error = await extractError(res)\n if (error) {\n throw error\n }\n } catch (error) {\n throw formatRequestTimeoutError(error)\n }\n }\n\n /**\n * Deletes a code execution context from the sandbox.\n *\n * Alias for {@link removeCodeContext}.\n *\n * @param context context object or context ID to delete.\n * @param opts options for the request.\n */\n async deleteCodeContext(\n context: Context | string,\n opts?: CodeContextRequestOpts\n ): Promise<void> {\n return this.removeCodeContext(context, opts)\n }\n\n private get jupyterHeaders(): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n ...this.connectionConfig.headers,\n ...(this.envdAccessToken\n ? { 'X-Access-Token': this.envdAccessToken }\n : {}),\n ...(this.trafficAccessToken\n ? { 'E2B-Traffic-Access-Token': this.trafficAccessToken }\n : {}),\n }\n }\n\n protected get jupyterUrl(): string {\n return `${this.connectionConfig.debug ? 'http' : 'https'}://${this.getHost(\n JUPYTER_PORT\n )}`\n }\n}\n","import { randomBytes } from 'crypto';\n\nexport function generateRandomString(length: number = 16): string {\n const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n const bytes = randomBytes(length);\n let result = '';\n\n for (let i = 0; i < length; i++) {\n result += characters[bytes[i] % characters.length];\n }\n\n return result;\n}","import {\n Sandbox as SandboxBase,\n SandboxOpts as SandboxOptsBase,\n CommandHandle,\n CommandResult,\n CommandExitError,\n ConnectionConfig,\n TimeoutError,\n} from '../core'\n\nimport { generateRandomString } from './utils'\n\ninterface CursorPosition {\n x: number\n y: number\n}\n\ninterface ScreenSize {\n width: number\n height: number\n}\n\nconst MOUSE_BUTTONS = {\n left: 1,\n right: 3,\n middle: 2,\n}\n\nconst KEYS = {\n alt: 'Alt_L',\n alt_left: 'Alt_L',\n alt_right: 'Alt_R',\n backspace: 'BackSpace',\n break: 'Pause',\n caps_lock: 'Caps_Lock',\n cmd: 'Super_L',\n command: 'Super_L',\n control: 'Control_L',\n control_left: 'Control_L',\n control_right: 'Control_R',\n ctrl: 'Control_L',\n del: 'Delete',\n delete: 'Delete',\n down: 'Down',\n end: 'End',\n enter: 'Return',\n esc: 'Escape',\n escape: 'Escape',\n f1: 'F1',\n f2: 'F2',\n f3: 'F3',\n f4: 'F4',\n f5: 'F5',\n f6: 'F6',\n f7: 'F7',\n f8: 'F8',\n f9: 'F9',\n f10: 'F10',\n f11: 'F11',\n f12: 'F12',\n home: 'Home',\n insert: 'Insert',\n left: 'Left',\n menu: 'Menu',\n meta: 'Meta_L',\n num_lock: 'Num_Lock',\n page_down: 'Page_Down',\n page_up: 'Page_Up',\n pause: 'Pause',\n print: 'Print',\n right: 'Right',\n scroll_lock: 'Scroll_Lock',\n shift: 'Shift_L',\n shift_left: 'Shift_L',\n shift_right: 'Shift_R',\n space: 'space',\n super: 'Super_L',\n super_left: 'Super_L',\n super_right: 'Super_R',\n tab: 'Tab',\n up: 'Up',\n win: 'Super_L',\n windows: 'Super_L',\n}\n\nfunction mapKey(key: string): string {\n const lowerKey = key.toLowerCase()\n if (lowerKey in KEYS) {\n return KEYS[lowerKey as keyof typeof KEYS]\n }\n return lowerKey\n}\n\n/**\n * Configuration options for the Sandbox environment.\n * @interface SandboxOpts\n * @extends {SandboxOptsBase}\n */\nexport interface SandboxOpts extends SandboxOptsBase {\n /**\n * The screen resolution in pixels, specified as [width, height].\n * @type {[number, number]}\n */\n resolution?: [number, number]\n\n /**\n * Dots per inch (DPI) setting for the display.\n * @type {number}\n */\n dpi?: number\n\n /**\n * Display identifier.\n * @type {string}\n */\n display?: string\n}\n\nexport class Sandbox extends SandboxBase {\n protected static override readonly defaultTemplate: string = 'desktop'\n private lastXfce4Pid: number | null = null\n public display: string = ':0'\n public stream: VNCServer = new VNCServer(this)\n\n /**\n * Use {@link Sandbox.create} to create a new Sandbox instead.\n *\n * @hidden\n * @hide\n * @internal\n * @access protected\n */\n constructor(\n opts: Omit<SandboxOpts, 'timeoutMs' | 'metadata'> & {\n sandboxId: string\n envdVersion?: string\n }\n ) {\n super({ ...opts, envdVersion: opts.envdVersion ?? '0.0.0' })\n }\n /**\n * Create a new sandbox from the default `desktop` sandbox template.\n *\n * @param opts connection options.\n *\n * @returns sandbox instance for the new sandbox.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * ```\n * @constructs Sandbox\n */\n static async create<S extends typeof Sandbox>(\n this: S,\n opts?: SandboxOpts\n ): Promise<InstanceType<S>>\n /**\n * Create a new sandbox from the specified sandbox template.\n *\n * @param template sandbox template name or ID.\n * @param opts connection options.\n *\n * @returns sandbox instance for the new sandbox.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create('<template-name-or-id>')\n * ```\n * @constructs Sandbox\n */\n static async create<S extends typeof Sandbox>(\n this: S,\n template: string,\n opts?: SandboxOpts\n ): Promise<InstanceType<S>>\n static async create<S extends typeof Sandbox>(\n this: S,\n templateOrOpts?: SandboxOpts | string,\n opts?: SandboxOpts\n ): Promise<InstanceType<S>> {\n const { template, sandboxOpts } =\n typeof templateOrOpts === 'string'\n ? { template: templateOrOpts, sandboxOpts: opts }\n : { template: this.defaultTemplate, sandboxOpts: templateOrOpts }\n\n const config = new ConnectionConfig(sandboxOpts)\n\n // Add DISPLAY environment variable if not already set\n const display = opts?.display || ':0'\n const sandboxOptsWithDisplay = {\n ...sandboxOpts,\n envs: {\n ...sandboxOpts?.envs,\n DISPLAY: display,\n },\n }\n\n let sbx\n if (config.debug) {\n sbx = new this({\n sandboxId: 'desktop',\n ...sandboxOptsWithDisplay,\n ...config,\n }) as InstanceType<S>\n } else {\n const sandbox = await this.createSandbox(\n template,\n sandboxOptsWithDisplay?.timeoutMs ?? this.defaultSandboxTimeoutMs,\n sandboxOptsWithDisplay\n )\n sbx = new this({\n ...sandbox,\n ...sandboxOptsWithDisplay,\n ...config,\n }) as InstanceType<S>\n }\n\n sbx.display = display\n sbx.lastXfce4Pid = null\n sbx.stream = new VNCServer(sbx)\n\n const [width, height] = sandboxOpts?.resolution ?? [1024, 768]\n await sbx.commands.run(\n `Xvfb ${sbx.display} -ac -screen 0 ${width}x${height}x24 ` +\n `-retro -dpi ${sandboxOpts?.dpi ?? 96} -nolisten tcp -nolisten unix`,\n { background: true, timeoutMs: 0 }\n )\n\n let hasStarted = await sbx.waitAndVerify(\n `xdpyinfo -display ${sbx.display}`,\n (r: CommandResult) => r.exitCode === 0\n )\n if (!hasStarted) {\n throw new TimeoutError('Could not start Xvfb')\n }\n\n await sbx.startXfce4()\n\n return sbx\n }\n\n /**\n * Wait for a command to return a specific result.\n * @param cmd - The command to run.\n * @param onResult - The function to check the result of the command.\n * @param timeout - The maximum time to wait for the command to return the result.\n * @param interval - The interval to wait between checks.\n * @returns `true` if the command returned the result within the timeout, otherwise `false`.\n */\n async waitAndVerify(\n cmd: string,\n onResult: (result: CommandResult) => boolean,\n timeout: number = 10,\n interval: number = 0.5\n ): Promise<boolean> {\n let elapsed = 0\n\n while (elapsed < timeout) {\n try {\n if (onResult(await this.commands.run(cmd))) {\n return true\n }\n } catch (e) {\n if (e instanceof CommandExitError) {\n continue\n }\n throw e\n }\n\n await new Promise((resolve) => setTimeout(resolve, interval * 1000))\n elapsed += interval\n }\n\n return false\n }\n\n /**\n * Start xfce4 session if logged out or not running.\n */\n private async startXfce4(): Promise<void> {\n if (\n this.lastXfce4Pid === null ||\n (\n await this.commands.run(\n `ps aux | grep ${this.lastXfce4Pid} | grep -v grep | head -n 1`\n )\n ).stdout\n .trim()\n .includes('[xfce4-session] <defunct>')\n ) {\n const result = await this.commands.run('startxfce4', {\n background: true,\n timeoutMs: 0,\n })\n this.lastXfce4Pid = result.pid\n }\n }\n\n /**\n * Take a screenshot and save it to the given name.\n * @param format - The format of the screenshot.\n * @returns A Uint8Array bytes representation of the screenshot.\n */\n async screenshot(): Promise<Uint8Array>\n /**\n * Take a screenshot and save it to the given name.\n * @param format - The format of the screenshot.\n * @returns A Uint8Array bytes representation of the screenshot.\n */\n async screenshot(format: 'bytes'): Promise<Uint8Array>\n /**\n * Take a screenshot and save it to the given name.\n * @returns A Blob representation of the screenshot.\n */\n async screenshot(format: 'blob'): Promise<Blob>\n /**\n * Take a screenshot and save it to the given name.\n * @returns A ReadableStream of bytes representation of the screenshot.\n */\n async screenshot(format: 'stream'): Promise<ReadableStream<Uint8Array>>\n async screenshot(format: 'bytes' | 'blob' | 'stream' = 'bytes') {\n const path = `/tmp/screenshot-${generateRandomString()}.png`\n await this.commands.run(`scrot --pointer ${path}`)\n\n // @ts-expect-error\n const file = await this.files.read(path, { format })\n this.files.remove(path)\n return file\n }\n\n /**\n * Left click on the mouse position.\n */\n async leftClick(x?: number, y?: number): Promise<void> {\n if (x && y) {\n await this.moveMouse(x, y)\n }\n\n await this.commands.run('xdotool click 1')\n }\n\n /**\n * Double left click on the mouse position.\n */\n async doubleClick(x?: number, y?: number): Promise<void> {\n if (x && y) {\n await this.moveMouse(x, y)\n }\n\n await this.commands.run('xdotool click --repeat 2 1')\n }\n\n /**\n * Right click on the mouse position.\n */\n async rightClick(x?: number, y?: number): Promise<void> {\n if (x && y) {\n await this.moveMouse(x, y)\n }\n\n await this.commands.run('xdotool click 3')\n }\n\n /**\n * Middle click on the mouse position.\n */\n async middleClick(x?: number, y?: number): Promise<void> {\n if (x && y) {\n await this.moveMouse(x, y)\n }\n\n await this.commands.run('xdotool click 2')\n }\n\n /**\n * Scroll the mouse wheel by the given amount.\n * @param direction - The direction to scroll. Can be \"up\" or \"down\".\n * @param amount - The amount to scroll.\n */\n async scroll(\n direction: 'up' | 'down' = 'down',\n amount: number = 1\n ): Promise<void> {\n const button = direction === 'up' ? '4' : '5'\n await this.commands.run(`xdotool click --repeat ${amount} ${button}`)\n }\n\n /**\n * Move the mouse to the given coordinates.\n * @param x - The x coordinate.\n * @param y - The y coordinate.\n */\n async moveMouse(x: number, y: number): Promise<void> {\n await this.commands.run(`xdotool mousemove --sync ${x} ${y}`)\n }\n\n /**\n * Press the mouse button.\n */\n async mousePress(\n button: 'left' | 'right' | 'middle' = 'left'\n ): Promise<void> {\n await this.commands.run(`xdotool mousedown ${MOUSE_BUTTONS[button]}`)\n }\n\n /**\n * Release the mouse button.\n */\n async mouseRelease(\n button: 'left' | 'right' | 'middle' = 'left'\n ): Promise<void> {\n await this.commands.run(`xdotool mouseup ${MOUSE_BUTTONS[button]}`)\n }\n\n /**\n * Get the current cursor position.\n * @returns A object with the x and y coordinates\n * @throws Error if cursor position cannot be determined\n */\n async getCursorPosition(): Promise<CursorPosition> {\n const result = await this.commands.run('xdotool getmouselocation')\n\n const match = result.stdout.match(/x:(\\d+)\\s+y:(\\d+)/)\n if (!match) {\n throw new Error(\n `Failed to parse cursor position from output: ${result.stdout}`\n )\n }\n\n const [, x, y] = match\n if (!x || !y) {\n throw new Error(`Invalid cursor position values: x=${x}, y=${y}`)\n }\n\n return { x: parseInt(x), y: parseInt(y) }\n }\n\n /**\n * Get the current screen size.\n * @returns An {@link ScreenSize} object\n * @throws Error if screen size cannot be determined\n */\n async getScreenSize(): Promise<ScreenSize> {\n const result = await this.commands.run('xrandr')\n\n const match = result.stdout.match(/(\\d+x\\d+)/)\n if (!match) {\n throw new Error(\n `Failed to parse screen size from output: ${result.stdout}`\n )\n }\n\n try {\n const [width, height] = match[1].split('x').map((val) => parseInt(val))\n return { width, height }\n } catch (error) {\n throw new Error(`Invalid screen size format: ${match[1]}`)\n }\n }\n\n private *breakIntoChunks(text: string, n: number): Generator<string> {\n for (let i = 0; i < text.length; i += n) {\n yield text.slice(i, i + n)\n }\n }\n\n private quoteString(s: string): string {\n if (!s) {\n return \"''\"\n }\n\n if (!/[^\\w@%+=:,./-]/.test(s)) {\n return s\n }\n\n // use single quotes, and put single quotes into double quotes\n // the string $'b is then quoted as '$'\"'\"'b'\n return \"'\" + s.replace(/'/g, \"'\\\"'\\\"'\") + \"'\"\n }\n\n /**\n * Write the given text at the current cursor position.\n * @param text - The text to write.\n * @param options - An object containing the chunk size and delay between each chunk of text.\n * @param options.chunkSize - The size of each chunk of text to write. Default is 25 characters.\n * @param options.delayInMs - The delay between each chunk of text. Default is 75 ms.\n */\n async write(\n text: string,\n options: { chunkSize: number; delayInMs: number } = {\n chunkSize: 25,\n delayInMs: 75,\n }\n ): Promise<void> {\n const chunks = this.breakIntoChunks(text, options.chunkSize)\n\n for (const chunk of chunks) {\n await this.commands.run(\n `xdotool type --delay ${options.delayInMs} ${this.quoteString(chunk)}`\n )\n }\n }\n\n /**\n * Press a key.\n * @param key - The key to press (e.g. \"enter\", \"space\", \"backspace\", etc.). Can be a single key or an array of keys.\n */\n async press(key: string | string[]): Promise<void> {\n if (Array.isArray(key)) {\n key = key.map(mapKey).join('+')\n } else {\n key = mapKey(key)\n }\n\n await this.commands.run(`xdotool key ${key}`)\n }\n\n /**\n * Drag the mouse from the given position to the given position.\n * @param from - The starting position.\n * @param to - The ending position.\n */\n async drag(\n [x1, y1]: [number, number],\n [x2, y2]: [number, number]\n ): Promise<void> {\n await this.moveMouse(x1, y1)\n await this.mousePress()\n await this.moveMouse(x2, y2)\n await this.mouseRelease()\n }\n\n /**\n * Wait for the given amount of time.\n * @param ms - The amount of time to wait in milliseconds.\n */\n async wait(ms: number): Promise<void> {\n await this.commands.run(`sleep ${ms / 1000}`)\n }\n\n /**\n * Open a file or a URL in the default application.\n * @param fileOrUrl - The file or URL to open.\n */\n async open(fileOrUrl: string): Promise<void> {\n await this.commands.run(`xdg-open ${fileOrUrl}`, {\n background: true,\n })\n }\n\n /**\n * Get the current window ID.\n * @returns The ID of the current window.\n */\n async getCurrentWindowId(): Promise<string> {\n const result = await this.commands.run('xdotool getwindowfocus')\n return result.stdout.trim()\n }\n\n /**\n * Get the window ID of the window with the given title.\n * @param title - The title of the window.\n * @returns The ID of the window.\n */\n async getApplicationWindows(application: string): Promise<string[]> {\n const result = await this.commands.run(\n `xdotool search --onlyvisible --class ${application}`\n )\n\n return result.stdout.trim().split('\\n')\n }\n\n /**\n * Get the title of the window with the given ID.\n * @param windowId - The ID of the window.\n * @returns The title of the window.\n */\n async getWindowTitle(windowId: string): Promise<string> {\n const result = await this.commands.run(`xdotool getwindowname ${windowId}`)\n\n return result.stdout.trim()\n }\n\n /**\n * Launch an application.\n * @param application - The application to launch.\n * @param uri - The URI to open in the application.\n */\n async launch(application: string, uri?: string): Promise<void> {\n await this.commands.run(`gtk-launch ${application} ${uri ?? ''}`, {\n background: true,\n timeoutMs: 0,\n })\n }\n}\n\ninterface VNCServerOptions {\n vncPort?: number\n port?: number\n requireAuth?: boolean\n windowId?: string\n}\n\ninterface UrlOptions {\n autoConnect?: boolean\n viewOnly?: boolean\n resize?: 'off' | 'scale' | 'remote'\n authKey?: string\n}\n\n// Modified VNCServer class\nclass VNCServer {\n private vncPort: number = 5900\n private port: number = 6080\n private novncAuthEnabled: boolean = false\n private url: URL | null = null\n private novncHandle: CommandHandle | null = null\n private password: string | undefined\n private readonly novncCommand: string\n private readonly desktop: Sandbox\n\n constructor(desktop: Sandbox) {\n this.desktop = desktop\n this.novncCommand =\n `cd /opt/noVNC/utils && ./novnc_proxy --vnc localhost:${this.vncPort} ` +\n `--listen ${this.port} --web /opt/noVNC > /tmp/novnc.log 2>&1`\n }\n\n public getAuthKey(): string {\n if (!this.password) {\n throw new Error(\n 'Unable to retrieve stream auth key, check if requireAuth is enabled'\n )\n }\n\n return this.password\n }\n\n /**\n * Set the VNC command to start the VNC server.\n */\n private async getVNCCommand(windowId?: string): Promise<string> {\n let pwdFlag = '-nopw'\n if (this.novncAuthEnabled) {\n // Create .vnc directory if it doesn't exist\n await this.desktop.commands.run('mkdir -p ~/.vnc')\n await this.desktop.commands.run(\n `x11vnc -storepasswd ${this.password} ~/.vnc/passwd`\n )\n pwdFlag = '-usepw'\n }\n\n return (\n `x11vnc -bg -display ${this.desktop.display} -forever -wait 50 -shared ` +\n `-rfbport ${this.vncPort} ${pwdFlag} 2>/tmp/x11vnc_stderr.log` +\n (windowId ? ` -id ${windowId}` : '')\n )\n }\n\n private async waitForPort(port: number): Promise<boolean> {\n return await this.desktop.waitAndVerify(\n `netstat -tuln | grep \":${port} \"`,\n (r: CommandResult) => r.stdout.trim() !== ''\n )\n }\n\n /**\n * Check if the VNC server is running.\n * @returns Whether the VNC server is running.\n */\n private async checkVNCRunning(): Promise<boolean> {\n try {\n const result = await this.desktop.commands.run('pgrep -x x11vnc')\n return result.stdout.trim() !== ''\n } catch (error) {\n return false\n }\n }\n\n /**\n * Get the URL to a web page with a stream of the desktop sandbox.\n * @param autoConnect - Whether to automatically connect to the server after opening the URL.\n * @param viewOnly - Whether to prevent user interaction through the client.\n * @param resize - Whether to resize the view when the window resizes.\n * @param authKey - The password to use to connect to the server.\n * @returns The URL to connect to the VNC server.\n */\n public getUrl({\n autoConnect = true,\n viewOnly = false,\n resize = 'scale',\n authKey,\n }: UrlOptions = {}): string {\n if (this.url === null) {\n throw new Error('Server is not running')\n }\n\n let url = new URL(this.url)\n if (autoConnect) {\n url.searchParams.set('autoconnect', 'true')\n }\n if (viewOnly) {\n url.searchParams.set('view_only', 'true')\n }\n if (resize) {\n url.searchParams.set('resize', resize)\n }\n if (authKey) {\n url.searchParams.set('password', authKey)\n }\n return url.toString()\n }\n\n /**\n * Start the VNC server.\n */\n public async start(opts: VNCServerOptions = {}): Promise<void> {\n // If stream is already running, throw an error.\n if (await this.checkVNCRunning()) {\n throw new Error('Stream is already running')\n }\n\n this.vncPort = opts.vncPort ?? this.vncPort\n this.port = opts.port ?? this.port\n this.novncAuthEnabled = opts.requireAuth ?? this.novncAuthEnabled\n this.password = this.novncAuthEnabled ? generateRandomString() : undefined\n this.url = new URL(`https://${this.desktop.getHost(this.port)}/vnc.html`)\n\n const vncCommand = await this.getVNCCommand(opts.windowId)\n await this.desktop.commands.run(vncCommand)\n\n this.novncHandle = await this.desktop.commands.run(this.novncCommand, {\n background: true,\n timeoutMs: 0,\n })\n if (!(await this.waitForPort(this.port))) {\n throw new Error('Could not start noVNC server')\n }\n }\n\n /**\n * Stop the VNC server.\n */\n public async stop(): Promise<void> {\n if (await this.checkVNCRunning()) {\n await this.desktop.commands.run('pkill x11vnc')\n }\n\n if (this.novncHandle) {\n await this.novncHandle.kill()\n this.novncHandle = null\n }\n }\n}\n","import { ConnectionOpts } from './connectionConfig';\nimport { Sandbox } from './sandbox';\nimport type { Sandbox as CodeInterpreterSandbox } from '../code-interpreter/sandbox';\nimport type {\n Sandbox as DesktopSandbox,\n SandboxOpts as DesktopSandboxOpts,\n} from '../desktop/sandbox';\nimport type {\n SandboxApiOpts,\n SandboxBetaCreateOpts,\n SandboxCloneOpts,\n SandboxCloneResult,\n SandboxCommitOpts,\n SandboxConnectOpts,\n SandboxEventsOpts,\n SandboxEventsResult,\n SandboxListOpts,\n SandboxMetrics,\n SandboxMetricsOpts,\n SandboxNetworkUpdateOpts,\n SandboxOpts,\n SandboxInfo,\n SandboxQuota,\n SandboxQuotaOpts,\n SandboxResetOpts,\n SandboxCommitResult,\n SnapshotInfo,\n SnapshotListOpts,\n SnapshotPaginator,\n} from './sandbox/sandboxApi';\nimport {\n Template,\n TemplateApi,\n type BuildInfo,\n type BuildOptions,\n type GetBuildStatusOptions,\n type TemplateClass,\n type TemplateDeleteOpts,\n type TemplateInfo,\n type TemplateListOpts,\n type TemplatePaginator,\n type TemplateTag,\n type TemplateTagInfo,\n type TemplateBuildStatusResponse,\n} from './template';\nimport type { TemplateOptions } from './template/types';\nimport { Volume, type VolumeAndToken, type VolumeInfo } from './volume';\nimport { Secret, type SecretBinding, type SecretWriteParams } from './secret';\n\ntype VolumeCreateOpts = ConnectionOpts & {\n quotaSizeGiB?: number;\n quotaInodes?: number;\n};\n\ntype RuntimeSandboxClass<TSandbox, TCreateOpts> = {\n create(opts?: TCreateOpts): Promise<TSandbox>;\n create(template: string, opts?: TCreateOpts): Promise<TSandbox>;\n betaCreate(opts?: SandboxBetaCreateOpts): Promise<TSandbox>;\n betaCreate(template: string, opts?: SandboxBetaCreateOpts): Promise<TSandbox>;\n connect(sandboxId: string, opts?: SandboxConnectOpts): Promise<TSandbox>;\n clone(\n sandboxId: string,\n opts?: SandboxCloneOpts\n ): Promise<SandboxCloneResult<TSandbox>>;\n};\n\ntype RuntimeSandboxLoader<TSandbox, TCreateOpts> = () => Promise<{\n Sandbox: RuntimeSandboxClass<TSandbox, TCreateOpts>;\n}>;\n\nfunction mergeConnectionOpts<T extends ConnectionOpts>(\n base: ConnectionOpts,\n next?: T\n): T {\n const baseHeaders = base.headers ?? {};\n const nextHeaders = next?.headers ?? {};\n\n return {\n ...base,\n ...(next ?? {}),\n headers: {\n ...baseHeaders,\n ...nextHeaders,\n },\n } as T;\n}\n\nclass RuntimeSandboxNamespace<TSandbox, TCreateOpts extends ConnectionOpts> {\n constructor(\n private readonly opts: ConnectionOpts,\n private readonly loadSandbox: RuntimeSandboxLoader<TSandbox, TCreateOpts>\n ) {}\n\n async create(opts?: TCreateOpts): Promise<TSandbox>;\n async create(template: string, opts?: TCreateOpts): Promise<TSandbox>;\n async create(\n templateOrOpts?: string | TCreateOpts,\n opts?: TCreateOpts\n ): Promise<TSandbox> {\n const { Sandbox: RuntimeSandbox } = await this.loadSandbox();\n\n if (typeof templateOrOpts === 'string') {\n return RuntimeSandbox.create(\n templateOrOpts,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n return RuntimeSandbox.create(\n mergeConnectionOpts(this.opts, templateOrOpts)\n );\n }\n\n async betaCreate(opts?: SandboxBetaCreateOpts): Promise<TSandbox>;\n async betaCreate(\n template: string,\n opts?: SandboxBetaCreateOpts\n ): Promise<TSandbox>;\n async betaCreate(\n templateOrOpts?: string | SandboxBetaCreateOpts,\n opts?: SandboxBetaCreateOpts\n ): Promise<TSandbox> {\n const { Sandbox: RuntimeSandbox } = await this.loadSandbox();\n\n if (typeof templateOrOpts === 'string') {\n return RuntimeSandbox.betaCreate(\n templateOrOpts,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n return RuntimeSandbox.betaCreate(\n mergeConnectionOpts(this.opts, templateOrOpts)\n );\n }\n\n async connect(\n sandboxId: string,\n opts?: SandboxConnectOpts\n ): Promise<TSandbox> {\n const { Sandbox: RuntimeSandbox } = await this.loadSandbox();\n\n return RuntimeSandbox.connect(\n sandboxId,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n get(sandboxId: string, opts?: SandboxConnectOpts): Promise<TSandbox> {\n return this.connect(sandboxId, opts);\n }\n\n list(opts?: SandboxListOpts) {\n return Sandbox.list(mergeConnectionOpts(this.opts, opts));\n }\n\n kill(sandboxId: string, opts?: SandboxApiOpts): Promise<boolean> {\n return Sandbox.kill(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n pause(sandboxId: string, opts?: SandboxApiOpts): Promise<boolean> {\n return Sandbox.pause(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n betaPause(sandboxId: string, opts?: SandboxApiOpts): Promise<boolean> {\n return Sandbox.betaPause(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n async clone(\n sandboxId: string,\n opts?: SandboxCloneOpts\n ): Promise<SandboxCloneResult<TSandbox>> {\n const { Sandbox: RuntimeSandbox } = await this.loadSandbox();\n\n return RuntimeSandbox.clone(\n sandboxId,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n reset(sandboxId: string, opts?: SandboxResetOpts): Promise<boolean> {\n return Sandbox.reset(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n commit(sandboxId: string, opts?: SandboxCommitOpts): Promise<SandboxCommitResult> {\n return Sandbox.commit(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n setNetwork(\n sandboxId: string,\n opts?: SandboxNetworkUpdateOpts\n ): Promise<void> {\n return Sandbox.setNetwork(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n createSnapshot(\n sandboxId: string,\n opts?: SandboxApiOpts\n ): Promise<SnapshotInfo> {\n return Sandbox.createSnapshot(\n sandboxId,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n listSnapshots(opts?: SnapshotListOpts): SnapshotPaginator {\n return Sandbox.listSnapshots(mergeConnectionOpts(this.opts, opts));\n }\n\n deleteSnapshot(snapshotId: string, opts?: SandboxApiOpts): Promise<boolean> {\n return Sandbox.deleteSnapshot(\n snapshotId,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n setTimeout(\n sandboxId: string,\n timeoutMs: number,\n opts?: SandboxApiOpts\n ): Promise<void> {\n return Sandbox.setTimeout(\n sandboxId,\n timeoutMs,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n getInfo(sandboxId: string, opts?: SandboxApiOpts): Promise<SandboxInfo> {\n return Sandbox.getInfo(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n getMetrics(\n sandboxId: string,\n opts?: SandboxMetricsOpts\n ): Promise<SandboxMetrics[]> {\n return Sandbox.getMetrics(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n getQuota(opts?: SandboxQuotaOpts): Promise<SandboxQuota> {\n return Sandbox.getQuota(mergeConnectionOpts(this.opts, opts));\n }\n\n getEvents(opts?: SandboxEventsOpts): Promise<SandboxEventsResult> {\n return Sandbox.getEvents(mergeConnectionOpts(this.opts, opts));\n }\n\n}\n\nclass SandboxNamespace {\n constructor(private readonly opts: ConnectionOpts) {}\n\n async create(opts?: SandboxOpts): Promise<Sandbox>;\n async create(template: string, opts?: SandboxOpts): Promise<Sandbox>;\n async create(\n templateOrOpts?: string | SandboxOpts,\n opts?: SandboxOpts\n ): Promise<Sandbox> {\n if (typeof templateOrOpts === 'string') {\n return Sandbox.create(\n templateOrOpts,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n return Sandbox.create(mergeConnectionOpts(this.opts, templateOrOpts));\n }\n\n async betaCreate(opts?: SandboxBetaCreateOpts): Promise<Sandbox>;\n async betaCreate(\n template: string,\n opts?: SandboxBetaCreateOpts\n ): Promise<Sandbox>;\n async betaCreate(\n templateOrOpts?: string | SandboxBetaCreateOpts,\n opts?: SandboxBetaCreateOpts\n ): Promise<Sandbox> {\n if (typeof templateOrOpts === 'string') {\n return Sandbox.betaCreate(\n templateOrOpts,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n return Sandbox.betaCreate(mergeConnectionOpts(this.opts, templateOrOpts));\n }\n\n async connect(\n sandboxId: string,\n opts?: SandboxConnectOpts\n ): Promise<Sandbox> {\n return Sandbox.connect(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n async get(sandboxId: string, opts?: SandboxConnectOpts): Promise<Sandbox> {\n return this.connect(sandboxId, opts);\n }\n\n list(opts?: SandboxListOpts) {\n return Sandbox.list(mergeConnectionOpts(this.opts, opts));\n }\n\n async kill(sandboxId: string, opts?: SandboxApiOpts): Promise<boolean> {\n return Sandbox.kill(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n setTimeout(\n sandboxId: string,\n timeoutMs: number,\n opts?: SandboxApiOpts\n ): Promise<void> {\n return Sandbox.setTimeout(\n sandboxId,\n timeoutMs,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n getInfo(sandboxId: string, opts?: SandboxApiOpts): Promise<SandboxInfo> {\n return Sandbox.getInfo(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n getMetrics(\n sandboxId: string,\n opts?: SandboxMetricsOpts\n ): Promise<SandboxMetrics[]> {\n return Sandbox.getMetrics(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n pause(sandboxId: string, opts?: SandboxApiOpts): Promise<boolean> {\n return Sandbox.pause(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n betaPause(sandboxId: string, opts?: SandboxApiOpts): Promise<boolean> {\n return Sandbox.betaPause(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n clone(\n sandboxId: string,\n opts?: SandboxCloneOpts\n ): Promise<SandboxCloneResult<Sandbox>> {\n return Sandbox.clone(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n reset(sandboxId: string, opts?: SandboxResetOpts): Promise<boolean> {\n return Sandbox.reset(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n commit(sandboxId: string, opts?: SandboxCommitOpts): Promise<SandboxCommitResult> {\n return Sandbox.commit(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n setNetwork(\n sandboxId: string,\n opts?: SandboxNetworkUpdateOpts\n ): Promise<void> {\n return Sandbox.setNetwork(sandboxId, mergeConnectionOpts(this.opts, opts));\n }\n\n createSnapshot(\n sandboxId: string,\n opts?: SandboxApiOpts\n ): Promise<SnapshotInfo> {\n return Sandbox.createSnapshot(\n sandboxId,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n listSnapshots(opts?: SnapshotListOpts): SnapshotPaginator {\n return Sandbox.listSnapshots(mergeConnectionOpts(this.opts, opts));\n }\n\n deleteSnapshot(snapshotId: string, opts?: SandboxApiOpts): Promise<boolean> {\n return Sandbox.deleteSnapshot(\n snapshotId,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n getQuota(opts?: SandboxQuotaOpts): Promise<SandboxQuota> {\n return Sandbox.getQuota(mergeConnectionOpts(this.opts, opts));\n }\n\n getEvents(opts?: SandboxEventsOpts): Promise<SandboxEventsResult> {\n return Sandbox.getEvents(mergeConnectionOpts(this.opts, opts));\n }\n\n}\n\nclass TemplateNamespace {\n constructor(private readonly opts: ConnectionOpts) {}\n\n new(options?: TemplateOptions) {\n return Template(options);\n }\n\n list(opts?: TemplateListOpts): TemplatePaginator {\n return Template.list(mergeConnectionOpts(this.opts, opts));\n }\n\n get(templateId: string, opts?: ConnectionOpts) {\n return Template.get(templateId, mergeConnectionOpts(this.opts, opts));\n }\n\n delete(templateId: string, opts?: TemplateDeleteOpts): Promise<boolean> {\n return TemplateApi.deleteTemplate(\n templateId,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n async build(\n template: TemplateClass,\n name: string,\n options?: Omit<BuildOptions, 'alias'>\n ): Promise<BuildInfo>;\n async build(\n template: TemplateClass,\n options: BuildOptions\n ): Promise<BuildInfo>;\n async build(\n template: TemplateClass,\n nameOrOptions: string | BuildOptions,\n options?: Omit<BuildOptions, 'alias'>\n ): Promise<BuildInfo> {\n if (typeof nameOrOptions === 'string') {\n return Template.build(\n template,\n nameOrOptions,\n mergeConnectionOpts(this.opts, options)\n );\n }\n\n return Template.build(\n template,\n mergeConnectionOpts(this.opts, nameOrOptions)\n );\n }\n\n async buildInBackground(\n template: TemplateClass,\n name: string,\n options?: Omit<BuildOptions, 'alias'>\n ): Promise<BuildInfo>;\n async buildInBackground(\n template: TemplateClass,\n options: BuildOptions\n ): Promise<BuildInfo>;\n async buildInBackground(\n template: TemplateClass,\n nameOrOptions: string | BuildOptions,\n options?: Omit<BuildOptions, 'alias'>\n ): Promise<BuildInfo> {\n if (typeof nameOrOptions === 'string') {\n return Template.buildInBackground(\n template,\n nameOrOptions,\n mergeConnectionOpts(this.opts, options)\n );\n }\n\n return Template.buildInBackground(\n template,\n mergeConnectionOpts(this.opts, nameOrOptions)\n );\n }\n\n getBuildStatus(\n data: Pick<BuildInfo, 'templateId' | 'buildId'>,\n options?: GetBuildStatusOptions\n ): Promise<TemplateBuildStatusResponse> {\n return Template.getBuildStatus(\n data,\n mergeConnectionOpts(this.opts, options)\n );\n }\n\n exists(name: string, options?: ConnectionOpts): Promise<boolean> {\n return Template.exists(name, mergeConnectionOpts(this.opts, options));\n }\n\n aliasExists(alias: string, options?: ConnectionOpts): Promise<boolean> {\n return Template.aliasExists(alias, mergeConnectionOpts(this.opts, options));\n }\n\n assignTags(\n targetName: string,\n tags: string | string[],\n options?: ConnectionOpts\n ): Promise<TemplateTagInfo> {\n return Template.assignTags(\n targetName,\n tags,\n mergeConnectionOpts(this.opts, options)\n );\n }\n\n removeTags(\n name: string,\n tags: string | string[],\n options?: ConnectionOpts\n ): Promise<void> {\n return Template.removeTags(\n name,\n tags,\n mergeConnectionOpts(this.opts, options)\n );\n }\n\n getTags(\n templateId: string,\n options?: ConnectionOpts\n ): Promise<TemplateTag[]> {\n return Template.getTags(\n templateId,\n mergeConnectionOpts(this.opts, options)\n );\n }\n\n toJSON = Template.toJSON;\n toDockerfile = Template.toDockerfile;\n}\n\nclass VolumeNamespace {\n constructor(private readonly opts: ConnectionOpts) {}\n\n create(name: string, opts?: VolumeCreateOpts): Promise<Volume> {\n return Volume.create(name, mergeConnectionOpts(this.opts, opts));\n }\n\n connect(volumeId: string, opts?: ConnectionOpts): Promise<Volume> {\n return Volume.connect(volumeId, mergeConnectionOpts(this.opts, opts));\n }\n\n getInfo(volumeId: string, opts?: ConnectionOpts): Promise<VolumeAndToken> {\n return Volume.getInfo(volumeId, mergeConnectionOpts(this.opts, opts));\n }\n\n list(opts?: ConnectionOpts): Promise<VolumeInfo[]> {\n return Volume.list(mergeConnectionOpts(this.opts, opts));\n }\n\n updateQuota(\n volumeId: string,\n params: { quotaSizeGiB?: number; quotaInodes?: number },\n opts?: ConnectionOpts\n ): Promise<VolumeAndToken> {\n return Volume.updateQuota(\n volumeId,\n params,\n mergeConnectionOpts(this.opts, opts)\n );\n }\n\n destroy(volumeId: string, opts?: ConnectionOpts): Promise<boolean> {\n return Volume.destroy(volumeId, mergeConnectionOpts(this.opts, opts));\n }\n}\n\nclass SecretNamespace {\n constructor(private readonly opts: ConnectionOpts) {}\n\n create(\n params: SecretWriteParams,\n opts?: ConnectionOpts\n ): Promise<SecretBinding> {\n return Secret.create(params, mergeConnectionOpts(this.opts, opts));\n }\n\n list(opts?: ConnectionOpts): Promise<SecretBinding[]> {\n return Secret.list(mergeConnectionOpts(this.opts, opts));\n }\n\n get(name: string, opts?: ConnectionOpts): Promise<SecretBinding> {\n return Secret.get(name, mergeConnectionOpts(this.opts, opts));\n }\n\n update(\n params: SecretWriteParams,\n opts?: ConnectionOpts\n ): Promise<SecretBinding> {\n return Secret.update(params, mergeConnectionOpts(this.opts, opts));\n }\n\n delete(name: string, opts?: ConnectionOpts): Promise<string> {\n return Secret.delete(name, mergeConnectionOpts(this.opts, opts));\n }\n}\n\n/**\n * High-level PPIO client for accessing core SDK resources.\n */\nexport class PPIO {\n readonly sandbox: SandboxNamespace;\n readonly template: TemplateNamespace;\n readonly volume: VolumeNamespace;\n readonly secret: SecretNamespace;\n readonly codeInterpreter: RuntimeSandboxNamespace<\n CodeInterpreterSandbox,\n SandboxOpts\n >;\n readonly code_interpreter: RuntimeSandboxNamespace<\n CodeInterpreterSandbox,\n SandboxOpts\n >;\n readonly desktop: RuntimeSandboxNamespace<DesktopSandbox, DesktopSandboxOpts>;\n\n constructor(private readonly opts: ConnectionOpts = {}) {\n this.sandbox = new SandboxNamespace(opts);\n this.template = new TemplateNamespace(opts);\n this.volume = new VolumeNamespace(opts);\n this.secret = new SecretNamespace(opts);\n this.codeInterpreter = new RuntimeSandboxNamespace<\n CodeInterpreterSandbox,\n SandboxOpts\n >(\n opts,\n () =>\n import('../code-interpreter/sandbox') as Promise<{\n Sandbox: RuntimeSandboxClass<CodeInterpreterSandbox, SandboxOpts>;\n }>\n );\n this.code_interpreter = this.codeInterpreter;\n this.desktop = new RuntimeSandboxNamespace<\n DesktopSandbox,\n DesktopSandboxOpts\n >(\n opts,\n () =>\n import('../desktop/sandbox') as Promise<{\n Sandbox: RuntimeSandboxClass<DesktopSandbox, DesktopSandboxOpts>;\n }>\n );\n }\n\n async create(opts?: SandboxOpts): Promise<Sandbox>;\n async create(template: string, opts?: SandboxOpts): Promise<Sandbox>;\n async create(\n templateOrOpts?: string | SandboxOpts,\n opts?: SandboxOpts\n ): Promise<Sandbox> {\n if (typeof templateOrOpts === 'string') {\n return this.sandbox.create(templateOrOpts, opts);\n }\n\n return this.sandbox.create(templateOrOpts);\n }\n\n connect(sandboxId: string, opts?: SandboxConnectOpts): Promise<Sandbox> {\n return this.sandbox.connect(sandboxId, opts);\n }\n\n get(sandboxId: string, opts?: SandboxConnectOpts): Promise<Sandbox> {\n return this.sandbox.get(sandboxId, opts);\n }\n}\n","/**\n * CIDR range that represents all traffic.\n */\nexport const ALL_TRAFFIC = '0.0.0.0/0'\n","export { ApiClient } from './api'\nexport type { components, paths } from './api'\n\nexport { PPIO } from './client'\n\nexport { ConnectionConfig } from './connectionConfig'\nexport type { ConnectionOpts, Username } from './connectionConfig'\nexport {\n AuthenticationError,\n FileNotFoundError,\n GitAuthError,\n GitUpstreamError,\n InvalidArgumentError,\n NotEnoughSpaceError,\n NotFoundError,\n SandboxError,\n SandboxNotFoundError,\n TemplateError,\n TimeoutError,\n RateLimitError,\n BuildError,\n FileUploadError,\n SecretError,\n VolumeError,\n} from './errors'\nexport type { Logger } from './logs'\n\nexport { getSignature } from './sandbox/signature'\n\nexport { FileType } from './sandbox/filesystem'\nexport type {\n WriteInfo,\n EntryInfo,\n Filesystem,\n FilesystemWriteOpts,\n FilesystemReadOpts,\n} from './sandbox/filesystem'\nexport { FilesystemEventType } from './sandbox/filesystem/watchHandle'\nexport type {\n FilesystemEvent,\n WatchHandle,\n} from './sandbox/filesystem/watchHandle'\n\nexport { CommandExitError } from './sandbox/commands/commandHandle'\nexport type {\n CommandResult,\n Stdout,\n Stderr,\n PtyOutput,\n CommandHandle,\n} from './sandbox/commands/commandHandle'\nexport type {\n SandboxInfo,\n SandboxMetrics,\n SandboxOpts,\n SandboxApiOpts,\n SandboxConnectOpts,\n SandboxBetaCreateOpts,\n SandboxMetricsOpts,\n SandboxCloneOpts,\n SandboxCloneResult,\n SandboxCommitOpts,\n SandboxCommitResult,\n SandboxResetOpts,\n SandboxState,\n SandboxListOpts,\n SandboxPaginator,\n SandboxNetworkOpts,\n SandboxNetworkUpdateOpts,\n SandboxLifecycle,\n SandboxInfoLifecycle,\n SnapshotInfo,\n SnapshotListOpts,\n SnapshotPaginator,\n SandboxQuota,\n SandboxQuotaLimit,\n SandboxQuotaUsage,\n SandboxQuotaOpts,\n SandboxEventItem,\n SandboxEventsOpts,\n SandboxEventsResult,\n} from './sandbox/sandboxApi'\n\nexport type { McpServer } from './sandbox/mcp'\n\nexport { ALL_TRAFFIC } from './sandbox/network'\n\nexport type {\n ProcessInfo,\n CommandRequestOpts,\n CommandConnectOpts,\n CommandStartOpts,\n Commands,\n Pty,\n} from './sandbox/commands'\n\nexport { Git } from './sandbox/git'\nexport type {\n GitRequestOpts,\n GitCloneOpts,\n GitInitOpts,\n GitRemoteAddOpts,\n GitCommitOpts,\n GitAddOpts,\n GitDeleteBranchOpts,\n GitPushOpts,\n GitPullOpts,\n GitDangerouslyAuthenticateOpts,\n GitConfigOpts,\n GitConfigScope,\n GitBranches,\n GitFileStatus,\n GitStatus,\n} from './sandbox/git'\n\nexport { Volume } from './volume'\nexport type { VolumeInfo, VolumeAndToken } from './volume'\n\nexport { Secret } from './secret'\nexport type { SecretBinding, SecretWriteParams } from './secret'\n\nexport { Sandbox }\nimport { Sandbox } from './sandbox'\n\nexport default Sandbox\n\nexport * from './template'\n\nexport {\n ReadyCmd,\n waitForPort,\n waitForURL,\n waitForProcess,\n waitForFile,\n waitForTimeout,\n} from './template/readycmd'\n\nexport {\n LogEntry,\n LogEntryStart,\n LogEntryEnd,\n type LogEntryLevel,\n defaultBuildLogger,\n} from './template/logger'\n\nexport {\n type ImageConfig,\n type RegistryCredentials,\n clearImageConfigCache,\n effectiveStartCmd,\n fetchImageConfig,\n parseImageRef,\n unsupportedBase,\n} from './template/imageConfig'\n","export * from '../core'\n\nexport { Sandbox } from './sandbox'\nexport type {\n Context,\n RunCodeOpts,\n CreateCodeContextOpts,\n CodeContextRequestOpts,\n} from './sandbox'\nexport type {\n Logs,\n ExecutionError,\n Result,\n Execution,\n MIMEType,\n RawData,\n OutputMessage,\n} from './messaging'\nexport type {\n ScaleType,\n ChartType,\n ChartTypes,\n Chart,\n BarChart,\n BarData,\n LineChart,\n ScatterChart,\n BoxAndWhiskerChart,\n BoxAndWhiskerData,\n PieChart,\n PieData,\n SuperChart,\n PointData,\n} from './charts'\nimport { Sandbox } from './sandbox'\n\nexport default Sandbox\n"],"mappings":"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","names":["_a","platform","module","import_platform","platform","_a","request","_a","message","createClient","_a","_a","import_openapi_fetch","init_api","createClient","DEFAULT_ERROR_MAP","import_connect","_a","import_connect","init_api","_a","pid","import_connect","import_compare_versions","init_api","_a","pid","import_codegenv2","FilesystemEventType","_a","import_connect","import_compare_versions","FileType","Filesystem","init_api","path","_a","name","path","init_utils","init_utils","_a","path","fetch","paths","path","_a","_a","e","import_compare_versions","res","err","path","_b","sandboxId","body","path","import_compare_versions","init_api","_a","Filesystem","path","chalk","path","_a","fs","crypto","stats","content","init_utils","_a","init_utils","fs","_a","import_node_fs","_a","_a","init_utils","version","src","path","paths","_b","_c","_d","_a","init_utils","init_consts","Sandbox","init_sandbox","init_utils","init_consts","_a","error","init_utils","sandbox_exports","Sandbox","init_sandbox","init_utils","_a","path","_a","FileType","Sandbox","init_sandbox"]}
|