tensorlake 0.4.41 → 0.4.42
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/bin/darwin-arm64/tensorlake +0 -0
- package/dist/bin/darwin-arm64/tl +0 -0
- package/dist/bin/linux-x64/tensorlake +0 -0
- package/dist/bin/linux-x64/tl +0 -0
- package/dist/bin/win32-x64/tensorlake.exe +0 -0
- package/dist/bin/win32-x64/tl.exe +0 -0
- package/dist/index.cjs +18 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +18 -14
- package/dist/index.js.map +1 -1
- package/dist/sandbox-image.cjs +9 -5
- package/dist/sandbox-image.cjs.map +1 -1
- package/dist/sandbox-image.js +9 -5
- package/dist/sandbox-image.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sandbox-image.ts","../src/models.ts","../src/defaults.ts","../src/errors.ts","../src/http.ts","../src/sse.ts","../src/url.ts","../src/sandbox.ts","../src/client.ts","../src/image.ts"],"sourcesContent":["import { readFile, readdir, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport {\n type CommandResult,\n type ProcessInfo,\n type SnapshotInfo,\n} from \"./models.js\";\nimport { type OutputResponse, ProcessStatus } from \"./models.js\";\nimport { SandboxClient } from \"./client.js\";\nimport { Image, dockerfileContent } from \"./image.js\";\n\nconst BUILD_SANDBOX_PIP_ENV = { PIP_BREAK_SYSTEM_PACKAGES: \"1\" } as const;\nconst IGNORED_DOCKERFILE_INSTRUCTIONS = new Set([\n \"CMD\",\n \"ENTRYPOINT\",\n \"EXPOSE\",\n \"HEALTHCHECK\",\n \"LABEL\",\n \"STOPSIGNAL\",\n \"VOLUME\",\n]);\nconst UNSUPPORTED_DOCKERFILE_INSTRUCTIONS = new Set([\n \"ARG\",\n \"ONBUILD\",\n \"SHELL\",\n \"USER\",\n]);\n\nexport interface DockerfileInstruction {\n keyword: string;\n value: string;\n lineNumber: number;\n}\n\nexport interface DockerfileBuildPlan {\n dockerfilePath: string;\n contextDir: string;\n registeredName: string;\n dockerfileText: string;\n baseImage?: string;\n instructions: DockerfileInstruction[];\n}\n\nexport interface CreateSandboxImageOptions {\n registeredName?: string;\n cpus?: number;\n memoryMb?: number;\n isPublic?: boolean;\n contextDir?: string;\n}\n\nexport type SandboxImageSource = string | Image;\n\ninterface BuildContext {\n apiUrl: string;\n apiKey?: string;\n personalAccessToken?: string;\n namespace: string;\n organizationId?: string;\n projectId?: string;\n debug: boolean;\n}\n\ninterface BuildSandbox {\n sandboxId: string;\n run(\n command: string,\n options?: {\n args?: string[];\n env?: Record<string, string>;\n workingDir?: string;\n timeout?: number;\n },\n ): Promise<CommandResult>;\n startProcess(\n command: string,\n options?: {\n args?: string[];\n env?: Record<string, string>;\n workingDir?: string;\n },\n ): Promise<ProcessInfo>;\n getStdout(pid: number): Promise<OutputResponse>;\n getStderr(pid: number): Promise<OutputResponse>;\n getProcess(pid: number): Promise<ProcessInfo>;\n writeFile(path: string, content: Uint8Array): Promise<void>;\n terminate(): Promise<void>;\n}\n\ninterface BuildClient {\n createAndConnect(options: {\n image?: string;\n cpus?: number;\n memoryMb?: number;\n }): Promise<BuildSandbox>;\n snapshotAndWait(\n sandboxId: string,\n options?: { timeout?: number; pollInterval?: number },\n ): Promise<SnapshotInfo>;\n close(): void;\n}\n\ninterface CreateSandboxImageDeps {\n emit?: (event: Record<string, unknown>) => void;\n createClient?: (context: BuildContext) => BuildClient;\n registerImage?: (\n context: BuildContext,\n name: string,\n dockerfile: string,\n snapshotId: string,\n snapshotUri: string,\n isPublic: boolean,\n ) => Promise<Record<string, unknown>>;\n sleep?: (ms: number) => Promise<void>;\n}\n\nexport function defaultRegisteredName(dockerfilePath: string): string {\n const parsed = path.parse(dockerfilePath);\n if (parsed.name.toLowerCase() === \"dockerfile\") {\n const parentName = path.basename(path.dirname(dockerfilePath)).trim();\n return parentName || \"sandbox-image\";\n }\n return parsed.name || \"sandbox-image\";\n}\n\nexport function logicalDockerfileLines(\n dockerfileText: string,\n): Array<{ lineNumber: number; line: string }> {\n const logicalLines: Array<{ lineNumber: number; line: string }> = [];\n let parts: string[] = [];\n let startLine: number | null = null;\n\n for (const [index, rawLine] of dockerfileText.split(/\\r?\\n/).entries()) {\n const lineNumber = index + 1;\n const stripped = rawLine.trim();\n if (parts.length === 0 && (!stripped || stripped.startsWith(\"#\"))) {\n continue;\n }\n\n if (startLine == null) {\n startLine = lineNumber;\n }\n\n let line = rawLine.replace(/\\s+$/, \"\");\n const continued = line.endsWith(\"\\\\\");\n if (continued) {\n line = line.slice(0, -1);\n }\n\n const normalized = line.trim();\n if (normalized && !normalized.startsWith(\"#\")) {\n parts.push(normalized);\n }\n\n if (continued) {\n continue;\n }\n\n if (parts.length > 0) {\n logicalLines.push({\n lineNumber: startLine ?? lineNumber,\n line: parts.join(\" \"),\n });\n }\n parts = [];\n startLine = null;\n }\n\n if (parts.length > 0) {\n logicalLines.push({\n lineNumber: startLine ?? 1,\n line: parts.join(\" \"),\n });\n }\n\n return logicalLines;\n}\n\nfunction splitInstruction(\n line: string,\n lineNumber: number,\n): { keyword: string; value: string } {\n const trimmed = line.trim();\n if (!trimmed) {\n throw new Error(`line ${lineNumber}: empty Dockerfile instruction`);\n }\n const match = trimmed.match(/^(\\S+)(?:\\s+(.*))?$/);\n if (!match) {\n throw new Error(`line ${lineNumber}: invalid Dockerfile instruction`);\n }\n return {\n keyword: match[1].toUpperCase(),\n value: (match[2] ?? \"\").trim(),\n };\n}\n\nfunction shellSplit(input: string): string[] {\n const tokens: string[] = [];\n let current = \"\";\n let quote: \"'\" | '\"' | null = null;\n let escape = false;\n\n for (let i = 0; i < input.length; i++) {\n const char = input[i];\n\n if (escape) {\n current += char;\n escape = false;\n continue;\n }\n\n if (quote == null) {\n if (/\\s/.test(char)) {\n if (current) {\n tokens.push(current);\n current = \"\";\n }\n continue;\n }\n if (char === \"'\" || char === '\"') {\n quote = char;\n continue;\n }\n if (char === \"\\\\\") {\n escape = true;\n continue;\n }\n current += char;\n continue;\n }\n\n if (quote === \"'\") {\n if (char === \"'\") {\n quote = null;\n } else {\n current += char;\n }\n continue;\n }\n\n if (char === '\"') {\n quote = null;\n continue;\n }\n if (char === \"\\\\\") {\n const next = input[++i];\n if (next == null) {\n throw new Error(`unterminated escape sequence in '${input}'`);\n }\n current += next;\n continue;\n }\n current += char;\n }\n\n if (escape) {\n throw new Error(`unterminated escape sequence in '${input}'`);\n }\n if (quote != null) {\n throw new Error(`unterminated quoted string in '${input}'`);\n }\n if (current) {\n tokens.push(current);\n }\n return tokens;\n}\n\nfunction shellQuote(value: string): string {\n if (!value) {\n return \"''\";\n }\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n\nfunction stripLeadingFlags(value: string): {\n flags: Record<string, string>;\n remaining: string;\n} {\n const flags: Record<string, string> = {};\n let remaining = value.trimStart();\n\n while (remaining.startsWith(\"--\")) {\n const firstSpace = remaining.indexOf(\" \");\n if (firstSpace === -1) {\n throw new Error(`invalid Dockerfile flag syntax: ${value}`);\n }\n\n const token = remaining.slice(0, firstSpace);\n const rest = remaining.slice(firstSpace + 1).trimStart();\n const flagBody = token.slice(2);\n\n if (flagBody.includes(\"=\")) {\n const [key, flagValue] = flagBody.split(/=(.*)/s, 2);\n flags[key] = flagValue;\n remaining = rest;\n continue;\n }\n\n const [flagValue, ...restTokens] = shellSplit(rest);\n if (flagValue == null) {\n throw new Error(`missing value for Dockerfile flag '${token}'`);\n }\n flags[flagBody] = flagValue;\n remaining = restTokens.join(\" \");\n }\n\n return { flags, remaining };\n}\n\nfunction parseFromValue(value: string, lineNumber: number): string {\n const { remaining } = stripLeadingFlags(value);\n const tokens = shellSplit(remaining);\n if (tokens.length === 0) {\n throw new Error(`line ${lineNumber}: FROM must include a base image`);\n }\n if (tokens.length > 1 && tokens[1].toLowerCase() !== \"as\") {\n throw new Error(`line ${lineNumber}: unsupported FROM syntax '${value}'`);\n }\n return tokens[0];\n}\n\nfunction parseCopyLikeValues(\n value: string,\n lineNumber: number,\n keyword: string,\n): {\n flags: Record<string, string>;\n sources: string[];\n destination: string;\n} {\n const { flags, remaining } = stripLeadingFlags(value);\n if (\"from\" in flags) {\n throw new Error(\n `line ${lineNumber}: ${keyword} --from is not supported for sandbox image creation`,\n );\n }\n\n const payload = remaining.trim();\n if (!payload) {\n throw new Error(\n `line ${lineNumber}: ${keyword} must include source and destination`,\n );\n }\n\n let parts: string[];\n if (payload.startsWith(\"[\")) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(payload);\n } catch (error) {\n throw new Error(\n `line ${lineNumber}: invalid JSON array syntax for ${keyword}: ${(error as Error).message}`,\n );\n }\n if (\n !Array.isArray(parsed) ||\n parsed.length < 2 ||\n parsed.some((item) => typeof item !== \"string\")\n ) {\n throw new Error(\n `line ${lineNumber}: ${keyword} JSON array form requires at least two string values`,\n );\n }\n parts = parsed as string[];\n } else {\n parts = shellSplit(payload);\n if (parts.length < 2) {\n throw new Error(\n `line ${lineNumber}: ${keyword} must include at least one source and one destination`,\n );\n }\n }\n\n return {\n flags,\n sources: parts.slice(0, -1),\n destination: parts[parts.length - 1],\n };\n}\n\nfunction parseEnvPairs(value: string, lineNumber: number): Array<[string, string]> {\n const tokens = shellSplit(value);\n if (tokens.length === 0) {\n throw new Error(`line ${lineNumber}: ENV must include a key and value`);\n }\n\n if (tokens.every((token) => token.includes(\"=\"))) {\n return tokens.map((token) => {\n const [key, envValue] = token.split(/=(.*)/s, 2);\n if (!key) {\n throw new Error(`line ${lineNumber}: invalid ENV token '${token}'`);\n }\n return [key, envValue] as [string, string];\n });\n }\n\n if (tokens.length < 2) {\n throw new Error(`line ${lineNumber}: ENV must include a key and value`);\n }\n\n return [[tokens[0], tokens.slice(1).join(\" \")]];\n}\n\nfunction resolveContainerPath(containerPath: string, workingDir: string): string {\n if (!containerPath) {\n return workingDir;\n }\n const normalized = containerPath.startsWith(\"/\")\n ? path.posix.normalize(containerPath)\n : path.posix.normalize(path.posix.join(workingDir, containerPath));\n return normalized.startsWith(\"/\") ? normalized : `/${normalized}`;\n}\n\nfunction buildPlanFromDockerfileText(\n dockerfileText: string,\n dockerfilePath: string,\n contextDir: string,\n registeredName?: string,\n): DockerfileBuildPlan {\n let baseImage: string | undefined;\n const instructions: DockerfileInstruction[] = [];\n\n for (const logicalLine of logicalDockerfileLines(dockerfileText)) {\n const { keyword, value } = splitInstruction(\n logicalLine.line,\n logicalLine.lineNumber,\n );\n if (keyword === \"FROM\") {\n if (baseImage != null) {\n throw new Error(\n `line ${logicalLine.lineNumber}: multi-stage Dockerfiles are not supported for sandbox image creation`,\n );\n }\n baseImage = parseFromValue(value, logicalLine.lineNumber);\n continue;\n }\n\n if (UNSUPPORTED_DOCKERFILE_INSTRUCTIONS.has(keyword)) {\n throw new Error(\n `line ${logicalLine.lineNumber}: Dockerfile instruction '${keyword}' is not supported for sandbox image creation`,\n );\n }\n\n instructions.push({\n keyword,\n value,\n lineNumber: logicalLine.lineNumber,\n });\n }\n\n if (!baseImage) {\n throw new Error(\"Dockerfile must contain a FROM instruction\");\n }\n\n return {\n dockerfilePath,\n contextDir,\n registeredName: registeredName ?? defaultRegisteredName(dockerfilePath),\n dockerfileText,\n baseImage,\n instructions,\n };\n}\n\nexport async function loadDockerfilePlan(\n dockerfilePath: string,\n registeredName?: string,\n): Promise<DockerfileBuildPlan> {\n const resolvedPath = path.resolve(dockerfilePath);\n const fileStats = await stat(resolvedPath).catch(() => null);\n if (!fileStats?.isFile()) {\n throw new Error(`Dockerfile not found: ${dockerfilePath}`);\n }\n\n const dockerfileText = await readFile(resolvedPath, \"utf8\");\n return buildPlanFromDockerfileText(\n dockerfileText,\n resolvedPath,\n path.dirname(resolvedPath),\n registeredName,\n );\n}\n\nexport function loadImagePlan(\n image: Image,\n options: Pick<CreateSandboxImageOptions, \"registeredName\" | \"contextDir\"> = {},\n): DockerfileBuildPlan {\n const contextDir = path.resolve(options.contextDir ?? process.cwd());\n const dockerfileText = dockerfileContent(image);\n const logicalLines = logicalDockerfileLines(dockerfileText);\n const instructions = image.baseImage == null ? logicalLines : logicalLines.slice(1);\n\n return {\n dockerfilePath: path.join(contextDir, \"Dockerfile\"),\n contextDir,\n registeredName: options.registeredName ?? image.name,\n dockerfileText,\n baseImage: image.baseImage ?? undefined,\n instructions: instructions.map(({ line, lineNumber }) => {\n const parsed = splitInstruction(line, lineNumber);\n return {\n keyword: parsed.keyword,\n value: parsed.value,\n lineNumber,\n };\n }),\n };\n}\n\nfunction defaultEmit(event: Record<string, unknown>) {\n process.stdout.write(`${JSON.stringify(event)}\\n`);\n}\n\nfunction debugEnabled(): boolean {\n return [\"1\", \"true\", \"yes\", \"on\"].includes(\n (process.env.TENSORLAKE_DEBUG ?? \"\").toLowerCase(),\n );\n}\n\nfunction buildContextFromEnv(): BuildContext {\n return {\n apiUrl: process.env.TENSORLAKE_API_URL ?? \"https://api.tensorlake.ai\",\n apiKey: process.env.TENSORLAKE_API_KEY,\n personalAccessToken: process.env.TENSORLAKE_PAT,\n namespace: process.env.INDEXIFY_NAMESPACE ?? \"default\",\n organizationId: process.env.TENSORLAKE_ORGANIZATION_ID,\n projectId: process.env.TENSORLAKE_PROJECT_ID,\n debug: debugEnabled(),\n };\n}\n\nfunction createDefaultClient(context: BuildContext): BuildClient {\n return new SandboxClient({\n apiUrl: context.apiUrl,\n apiKey: context.apiKey ?? context.personalAccessToken,\n organizationId: context.organizationId,\n projectId: context.projectId,\n namespace: context.namespace,\n });\n}\n\nasync function runChecked(\n sandbox: BuildSandbox,\n command: string,\n args: string[],\n env?: Record<string, string>,\n workingDir?: string,\n): Promise<CommandResult> {\n const result = await sandbox.run(command, {\n args,\n env,\n workingDir,\n });\n if (result.exitCode !== 0) {\n throw new Error(\n `Command '${command} ${args.join(\" \")}' failed with exit code ${result.exitCode}`,\n );\n }\n return result;\n}\n\nasync function runStreaming(\n sandbox: BuildSandbox,\n emit: (event: Record<string, unknown>) => void,\n sleep: (ms: number) => Promise<void>,\n command: string,\n args: string[] = [],\n env?: Record<string, string>,\n workingDir?: string,\n) {\n const proc = await sandbox.startProcess(command, {\n args,\n env,\n workingDir,\n });\n\n let stdoutSeen = 0;\n let stderrSeen = 0;\n let info: ProcessInfo;\n\n while (true) {\n const stdoutResp = await sandbox.getStdout(proc.pid);\n emitOutputLines(emit, \"stdout\", stdoutResp, stdoutSeen);\n stdoutSeen = stdoutResp.lines.length;\n\n const stderrResp = await sandbox.getStderr(proc.pid);\n emitOutputLines(emit, \"stderr\", stderrResp, stderrSeen);\n stderrSeen = stderrResp.lines.length;\n\n info = await sandbox.getProcess(proc.pid);\n if (info.status !== ProcessStatus.RUNNING) {\n const finalStdout = await sandbox.getStdout(proc.pid);\n emitOutputLines(emit, \"stdout\", finalStdout, stdoutSeen);\n stdoutSeen = finalStdout.lines.length;\n\n const finalStderr = await sandbox.getStderr(proc.pid);\n emitOutputLines(emit, \"stderr\", finalStderr, stderrSeen);\n break;\n }\n\n await sleep(300);\n }\n\n for (let i = 0; i < 10; i++) {\n if (info.exitCode != null || info.signal != null) {\n break;\n }\n await sleep(200);\n info = await sandbox.getProcess(proc.pid);\n }\n\n const exitCode =\n info.exitCode != null ? info.exitCode : info.signal != null ? -info.signal : 0;\n if (exitCode !== 0) {\n throw new Error(\n `Command '${command} ${args.join(\" \")}' failed with exit code ${exitCode}`,\n );\n }\n}\n\nfunction emitOutputLines(\n emit: (event: Record<string, unknown>) => void,\n stream: \"stdout\" | \"stderr\",\n response: OutputResponse,\n seen: number,\n) {\n for (const line of response.lines.slice(seen)) {\n emit({ type: \"build_log\", stream, message: line });\n }\n}\n\nfunction isPathWithinContext(contextDir: string, localPath: string): boolean {\n const relative = path.relative(contextDir, localPath);\n return relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative));\n}\n\nfunction resolveContextSourcePath(contextDir: string, source: string): string {\n const resolvedContextDir = path.resolve(contextDir);\n const resolvedSource = path.resolve(resolvedContextDir, source);\n if (!isPathWithinContext(resolvedContextDir, resolvedSource)) {\n throw new Error(`Local path escapes the build context: ${source}`);\n }\n return resolvedSource;\n}\n\nasync function copyLocalPathToSandbox(\n sandbox: BuildSandbox,\n localPath: string,\n remotePath: string,\n) {\n const fileStats = await stat(localPath).catch(() => null);\n if (!fileStats) {\n throw new Error(`Local path not found: ${localPath}`);\n }\n\n if (fileStats.isFile()) {\n await runChecked(sandbox, \"mkdir\", [\"-p\", path.posix.dirname(remotePath)]);\n await sandbox.writeFile(remotePath, await readFile(localPath));\n return;\n }\n\n if (!fileStats.isDirectory()) {\n throw new Error(`Local path not found: ${localPath}`);\n }\n\n const entries = await readdir(localPath, { withFileTypes: true });\n for (const entry of entries) {\n const sourcePath = path.join(localPath, entry.name);\n const destinationPath = path.posix.join(remotePath, entry.name);\n if (entry.isDirectory()) {\n await runChecked(sandbox, \"mkdir\", [\"-p\", destinationPath]);\n await copyLocalPathToSandbox(sandbox, sourcePath, destinationPath);\n } else if (entry.isFile()) {\n await runChecked(\n sandbox,\n \"mkdir\",\n [\"-p\", path.posix.dirname(destinationPath)],\n );\n await sandbox.writeFile(destinationPath, await readFile(sourcePath));\n }\n }\n}\n\nasync function persistEnvVar(\n sandbox: BuildSandbox,\n processEnv: Record<string, string>,\n key: string,\n value: string,\n) {\n const exportLine = `export ${key}=${shellQuote(value)}`;\n await runChecked(\n sandbox,\n \"sh\",\n [\"-c\", `printf '%s\\\\n' ${shellQuote(exportLine)} >> /etc/environment`],\n processEnv,\n );\n}\n\nasync function copyFromContext(\n sandbox: BuildSandbox,\n emit: (event: Record<string, unknown>) => void,\n contextDir: string,\n sources: string[],\n destination: string,\n workingDir: string,\n keyword: string,\n) {\n const destinationPath = resolveContainerPath(destination, workingDir);\n if (sources.length > 1 && !destinationPath.endsWith(\"/\")) {\n throw new Error(\n `${keyword} with multiple sources requires a directory destination ending in '/'`,\n );\n }\n\n for (const source of sources) {\n const localSource = resolveContextSourcePath(contextDir, source);\n const localStats = await stat(localSource).catch(() => null);\n if (!localStats) {\n throw new Error(`Local path not found: ${localSource}`);\n }\n\n let remoteDestination = destinationPath;\n if (sources.length > 1) {\n remoteDestination = path.posix.join(\n destinationPath.replace(/\\/$/, \"\"),\n path.posix.basename(source.replace(/\\/$/, \"\")),\n );\n } else if (localStats.isFile() && destinationPath.endsWith(\"/\")) {\n remoteDestination = path.posix.join(\n destinationPath.replace(/\\/$/, \"\"),\n path.basename(source),\n );\n }\n\n emit({\n type: \"status\",\n message: `${keyword} ${source} -> ${remoteDestination}`,\n });\n await copyLocalPathToSandbox(sandbox, localSource, remoteDestination);\n }\n}\n\nasync function addUrlToSandbox(\n sandbox: BuildSandbox,\n emit: (event: Record<string, unknown>) => void,\n url: string,\n destination: string,\n workingDir: string,\n processEnv: Record<string, string>,\n sleep: (ms: number) => Promise<void>,\n) {\n let destinationPath = resolveContainerPath(destination, workingDir);\n const parsedUrl = new URL(url);\n const fileName = path.posix.basename(parsedUrl.pathname.replace(/\\/$/, \"\")) || \"downloaded\";\n if (destinationPath.endsWith(\"/\")) {\n destinationPath = path.posix.join(destinationPath.replace(/\\/$/, \"\"), fileName);\n }\n\n const parentDir = path.posix.dirname(destinationPath) || \"/\";\n emit({\n type: \"status\",\n message: `ADD ${url} -> ${destinationPath}`,\n });\n await runChecked(sandbox, \"mkdir\", [\"-p\", parentDir], processEnv);\n await runStreaming(\n sandbox,\n emit,\n sleep,\n \"sh\",\n [\n \"-c\",\n `curl -fsSL --location ${shellQuote(url)} -o ${shellQuote(destinationPath)}`,\n ],\n processEnv,\n workingDir,\n );\n}\n\nasync function executeDockerfilePlan(\n sandbox: BuildSandbox,\n plan: DockerfileBuildPlan,\n emit: (event: Record<string, unknown>) => void,\n sleep: (ms: number) => Promise<void>,\n) {\n const processEnv: Record<string, string> = { ...BUILD_SANDBOX_PIP_ENV };\n let workingDir = \"/\";\n\n for (const instruction of plan.instructions) {\n const { keyword, value, lineNumber } = instruction;\n\n if (keyword === \"RUN\") {\n emit({ type: \"status\", message: `RUN ${value}` });\n await runStreaming(\n sandbox,\n emit,\n sleep,\n \"sh\",\n [\"-c\", value],\n processEnv,\n workingDir,\n );\n continue;\n }\n\n if (keyword === \"WORKDIR\") {\n const tokens = shellSplit(value);\n if (tokens.length !== 1) {\n throw new Error(`line ${lineNumber}: WORKDIR must include exactly one path`);\n }\n workingDir = resolveContainerPath(tokens[0], workingDir);\n emit({ type: \"status\", message: `WORKDIR ${workingDir}` });\n await runChecked(sandbox, \"mkdir\", [\"-p\", workingDir], processEnv);\n continue;\n }\n\n if (keyword === \"ENV\") {\n for (const [key, envValue] of parseEnvPairs(value, lineNumber)) {\n emit({ type: \"status\", message: `ENV ${key}=${envValue}` });\n processEnv[key] = envValue;\n await persistEnvVar(sandbox, processEnv, key, envValue);\n }\n continue;\n }\n\n if (keyword === \"COPY\") {\n const { sources, destination } = parseCopyLikeValues(\n value,\n lineNumber,\n keyword,\n );\n await copyFromContext(\n sandbox,\n emit,\n plan.contextDir,\n sources,\n destination,\n workingDir,\n keyword,\n );\n continue;\n }\n\n if (keyword === \"ADD\") {\n const { sources, destination } = parseCopyLikeValues(\n value,\n lineNumber,\n keyword,\n );\n if (\n sources.length === 1 &&\n /^https?:\\/\\//.test(sources[0])\n ) {\n await addUrlToSandbox(\n sandbox,\n emit,\n sources[0],\n destination,\n workingDir,\n processEnv,\n sleep,\n );\n } else {\n await copyFromContext(\n sandbox,\n emit,\n plan.contextDir,\n sources,\n destination,\n workingDir,\n keyword,\n );\n }\n continue;\n }\n\n if (IGNORED_DOCKERFILE_INSTRUCTIONS.has(keyword)) {\n emit({\n type: \"warning\",\n message: `Skipping Dockerfile instruction '${keyword}' during snapshot materialization. It is still preserved in the registered Dockerfile.`,\n });\n continue;\n }\n\n throw new Error(\n `line ${lineNumber}: Dockerfile instruction '${keyword}' is not supported for sandbox image creation`,\n );\n }\n}\n\nasync function registerImage(\n context: BuildContext,\n name: string,\n dockerfile: string,\n snapshotId: string,\n snapshotUri: string,\n isPublic: boolean,\n): Promise<Record<string, unknown>> {\n if (!context.organizationId || !context.projectId) {\n throw new Error(\n \"Organization ID and Project ID are required. Run 'tl login' and 'tl init'.\",\n );\n }\n\n const bearerToken = context.apiKey ?? context.personalAccessToken;\n if (!bearerToken) {\n throw new Error(\"Missing TENSORLAKE_API_KEY or TENSORLAKE_PAT.\");\n }\n\n const baseUrl = context.apiUrl.replace(/\\/+$/, \"\");\n const url =\n `${baseUrl}/platform/v1/organizations/` +\n `${encodeURIComponent(context.organizationId)}/projects/` +\n `${encodeURIComponent(context.projectId)}/sandbox-templates`;\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${bearerToken}`,\n \"Content-Type\": \"application/json\",\n };\n if (context.personalAccessToken && !context.apiKey) {\n headers[\"X-Forwarded-Organization-Id\"] = context.organizationId;\n headers[\"X-Forwarded-Project-Id\"] = context.projectId;\n }\n\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n name,\n dockerfile,\n snapshotId,\n snapshotUri,\n isPublic,\n }),\n });\n\n if (!response.ok) {\n throw new Error(\n `${response.status} ${response.statusText}: ${await response.text()}`,\n );\n }\n\n const text = await response.text();\n return text ? (JSON.parse(text) as Record<string, unknown>) : {};\n}\n\nexport async function createSandboxImage(\n source: SandboxImageSource,\n options: CreateSandboxImageOptions = {},\n deps: CreateSandboxImageDeps = {},\n) {\n const emit = deps.emit ?? defaultEmit;\n const sleep = deps.sleep ?? ((ms: number) => new Promise((r) => setTimeout(r, ms)));\n const context = buildContextFromEnv();\n const clientFactory = deps.createClient ?? createDefaultClient;\n const register =\n deps.registerImage ??\n ((...args) => registerImage(...args));\n\n const sourceLabel =\n typeof source === \"string\" ? source : `Image(${source.name})`;\n emit({ type: \"status\", message: `Loading ${sourceLabel}...` });\n const plan =\n typeof source === \"string\"\n ? await loadDockerfilePlan(source, options.registeredName)\n : loadImagePlan(source, options);\n emit({\n type: \"status\",\n message:\n plan.baseImage == null\n ? \"Starting build sandbox with the default server image...\"\n : `Starting build sandbox from ${plan.baseImage}...`,\n });\n\n const client = clientFactory(context);\n let sandbox: BuildSandbox | undefined;\n\n try {\n sandbox = await client.createAndConnect({\n ...(plan.baseImage == null ? {} : { image: plan.baseImage }),\n cpus: options.cpus ?? 2.0,\n memoryMb: options.memoryMb ?? 4096,\n });\n\n emit({\n type: \"status\",\n message: `Materializing image in sandbox ${sandbox.sandboxId}...`,\n });\n await executeDockerfilePlan(sandbox, plan, emit, sleep);\n\n emit({ type: \"status\", message: \"Creating snapshot...\" });\n const snapshot = await client.snapshotAndWait(sandbox.sandboxId);\n emit({\n type: \"snapshot_created\",\n snapshot_id: snapshot.snapshotId,\n snapshot_uri: snapshot.snapshotUri ?? null,\n });\n\n if (!snapshot.snapshotUri) {\n throw new Error(\n `Snapshot ${snapshot.snapshotId} is missing snapshotUri and cannot be registered as a sandbox image.`,\n );\n }\n\n emit({\n type: \"status\",\n message: `Registering image '${plan.registeredName}'...`,\n });\n const result = await register(\n context,\n plan.registeredName,\n plan.dockerfileText,\n snapshot.snapshotId,\n snapshot.snapshotUri,\n options.isPublic ?? false,\n );\n\n emit({\n type: \"image_registered\",\n name: plan.registeredName,\n image_id:\n (typeof result.id === \"string\" && result.id) ||\n (typeof result.templateId === \"string\" && result.templateId) ||\n \"\",\n });\n emit({ type: \"done\" });\n return result;\n } finally {\n if (sandbox) {\n try {\n await sandbox.terminate();\n } catch {}\n }\n client.close();\n }\n}\n\nexport async function runCreateSandboxImageCli(argv = process.argv.slice(2)) {\n const parsed = parseArgs({\n args: argv,\n allowPositionals: true,\n options: {\n name: { type: \"string\", short: \"n\" },\n cpus: { type: \"string\" },\n memory: { type: \"string\" },\n public: { type: \"boolean\", default: false },\n },\n });\n\n const dockerfilePath = parsed.positionals[0];\n if (!dockerfilePath) {\n throw new Error(\"Usage: tensorlake-create-sandbox-image <dockerfile_path> [--name NAME] [--cpus N] [--memory MB] [--public]\");\n }\n\n const cpus =\n parsed.values.cpus != null ? Number(parsed.values.cpus) : undefined;\n const memoryMb =\n parsed.values.memory != null ? Number(parsed.values.memory) : undefined;\n if (cpus != null && !Number.isFinite(cpus)) {\n throw new Error(`Invalid --cpus value: ${parsed.values.cpus}`);\n }\n if (memoryMb != null && !Number.isInteger(memoryMb)) {\n throw new Error(`Invalid --memory value: ${parsed.values.memory}`);\n }\n\n await createSandboxImage(dockerfilePath, {\n registeredName: parsed.values.name,\n cpus,\n memoryMb,\n isPublic: parsed.values.public,\n });\n}\n","// --- Enums ---\n\nexport enum SandboxStatus {\n PENDING = \"pending\",\n RUNNING = \"running\",\n SNAPSHOTTING = \"snapshotting\",\n SUSPENDING = \"suspending\",\n SUSPENDED = \"suspended\",\n TERMINATED = \"terminated\",\n}\n\nexport enum SnapshotStatus {\n IN_PROGRESS = \"in_progress\",\n COMPLETED = \"completed\",\n FAILED = \"failed\",\n}\n\nexport enum ProcessStatus {\n RUNNING = \"running\",\n EXITED = \"exited\",\n SIGNALED = \"signaled\",\n}\n\nexport enum StdinMode {\n CLOSED = \"closed\",\n PIPE = \"pipe\",\n}\n\nexport enum OutputMode {\n CAPTURE = \"capture\",\n DISCARD = \"discard\",\n}\n\nexport enum ContainerState {\n IDLE = \"Idle\",\n RUNNING = \"Running\",\n}\n\n// --- Resource / Network ---\n\nexport interface ContainerResourcesInfo {\n cpus: number;\n memoryMb: number;\n ephemeralDiskMb: number;\n}\n\nexport interface NetworkConfig {\n allowInternetAccess: boolean;\n allowOut: string[];\n denyOut: string[];\n}\n\n// --- Sandbox lifecycle ---\n\nexport interface CreateSandboxOptions {\n /** Optional sandbox image name, such as `ubuntu-minimal` or a registered Sandbox Image. When omitted, Tensorlake uses the default managed environment. */\n image?: string;\n cpus?: number;\n memoryMb?: number;\n ephemeralDiskMb?: number;\n secretNames?: string[];\n timeoutSecs?: number;\n entrypoint?: string[];\n allowInternetAccess?: boolean;\n allowOut?: string[];\n denyOut?: string[];\n snapshotId?: string;\n /** Optional name for the sandbox. Named sandboxes support suspend/resume. When absent the sandbox is ephemeral. */\n name?: string;\n}\n\nexport interface UpdateSandboxOptions {\n /** New name for the sandbox. Naming an ephemeral sandbox enables suspend/resume. */\n name?: string;\n /** Whether exposed user ports should be reachable without TensorLake auth. */\n allowUnauthenticatedAccess?: boolean;\n /** User ports that should be routable through the sandbox proxy. Port 9501 is reserved. */\n exposedPorts?: number[];\n}\n\nexport interface CreateSandboxResponse {\n sandboxId: string;\n status: SandboxStatus;\n}\n\nexport interface SandboxInfo {\n sandboxId: string;\n namespace: string;\n status: SandboxStatus;\n /** Resolved sandbox image name. */\n image?: string;\n resources: ContainerResourcesInfo;\n secretNames: string[];\n timeoutSecs?: number;\n entrypoint?: string[];\n network?: NetworkConfig;\n poolId?: string;\n outcome?: string;\n createdAt?: Date;\n terminatedAt?: Date;\n name?: string;\n allowUnauthenticatedAccess?: boolean;\n exposedPorts?: number[];\n sandboxUrl?: string;\n}\n\nexport interface SandboxPortAccess {\n allowUnauthenticatedAccess: boolean;\n exposedPorts: number[];\n sandboxUrl?: string;\n}\n\n// --- Snapshots ---\n\nexport interface CreateSnapshotResponse {\n snapshotId: string;\n status: SnapshotStatus;\n}\n\nexport interface SnapshotInfo {\n snapshotId: string;\n namespace: string;\n sandboxId: string;\n baseImage: string;\n status: SnapshotStatus;\n error?: string;\n snapshotUri?: string;\n sizeBytes?: number;\n createdAt?: Date;\n}\n\nexport interface SnapshotAndWaitOptions {\n timeout?: number;\n pollInterval?: number;\n}\n\n// --- Pools ---\n\nexport interface CreatePoolOptions {\n /** Sandbox image name, such as `ubuntu-minimal` or a registered Sandbox Image. */\n image: string;\n cpus?: number;\n memoryMb?: number;\n ephemeralDiskMb?: number;\n secretNames?: string[];\n timeoutSecs?: number;\n entrypoint?: string[];\n maxContainers?: number;\n warmContainers?: number;\n}\n\nexport interface UpdatePoolOptions {\n /** Sandbox image name, such as `ubuntu-minimal` or a registered Sandbox Image. */\n image: string;\n cpus?: number;\n memoryMb?: number;\n ephemeralDiskMb?: number;\n secretNames?: string[];\n timeoutSecs?: number;\n entrypoint?: string[];\n maxContainers?: number;\n warmContainers?: number;\n}\n\nexport interface CreateSandboxPoolResponse {\n poolId: string;\n namespace: string;\n}\n\nexport interface PoolContainerInfo {\n id: string;\n state: string;\n sandboxId?: string;\n executorId: string;\n}\n\nexport interface SandboxPoolInfo {\n poolId: string;\n namespace: string;\n /** Sandbox image name backing the pool. */\n image: string;\n resources: ContainerResourcesInfo;\n secretNames: string[];\n timeoutSecs: number;\n entrypoint?: string[];\n maxContainers?: number;\n warmContainers?: number;\n containers?: PoolContainerInfo[];\n createdAt?: Date;\n updatedAt?: Date;\n}\n\n// --- Process management ---\n\nexport interface StartProcessOptions {\n args?: string[];\n env?: Record<string, string>;\n workingDir?: string;\n stdinMode?: StdinMode;\n stdoutMode?: OutputMode;\n stderrMode?: OutputMode;\n}\n\nexport interface ProcessInfo {\n pid: number;\n status: ProcessStatus;\n exitCode?: number;\n signal?: number;\n stdinWritable: boolean;\n command: string;\n args: string[];\n startedAt: Date;\n endedAt?: Date;\n}\n\nexport interface SendSignalResponse {\n success: boolean;\n}\n\nexport interface OutputResponse {\n pid: number;\n lines: string[];\n lineCount: number;\n}\n\nexport interface OutputEvent {\n line: string;\n timestamp: Date;\n stream?: string;\n}\n\n// --- Run ---\n\nexport interface RunOptions {\n args?: string[];\n env?: Record<string, string>;\n workingDir?: string;\n timeout?: number;\n}\n\nexport interface CommandResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n}\n\n// --- File operations ---\n\nexport interface DirectoryEntry {\n name: string;\n isDir: boolean;\n size?: number;\n modifiedAt?: Date;\n}\n\nexport interface ListDirectoryResponse {\n path: string;\n entries: DirectoryEntry[];\n}\n\n// --- PTY ---\n\nexport interface CreatePtySessionOptions {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n workingDir?: string;\n rows?: number;\n cols?: number;\n}\n\nexport interface PtySessionInfo {\n sessionId: string;\n token: string;\n}\n\n// --- Health ---\n\nexport interface HealthResponse {\n healthy: boolean;\n}\n\nexport interface DaemonInfo {\n version: string;\n uptimeSecs: number;\n runningProcesses: number;\n totalProcesses: number;\n}\n\n// --- Client options ---\n\nexport interface SandboxClientOptions {\n apiUrl?: string;\n apiKey?: string;\n organizationId?: string;\n projectId?: string;\n namespace?: string;\n maxRetries?: number;\n retryBackoffMs?: number;\n}\n\nexport interface SandboxOptions {\n sandboxId: string;\n proxyUrl?: string;\n apiKey?: string;\n organizationId?: string;\n projectId?: string;\n}\n\nexport interface CreateAndConnectOptions extends CreateSandboxOptions {\n poolId?: string;\n proxyUrl?: string;\n startupTimeout?: number;\n}\n\n// --- JSON key conversion helpers ---\n\nconst CAMEL_TO_SNAKE_RE = /[A-Z]/g;\n\n/** Convert a camelCase string to snake_case. */\nexport function camelToSnake(str: string): string {\n return str.replace(CAMEL_TO_SNAKE_RE, (ch) => \"_\" + ch.toLowerCase());\n}\n\n/** Convert a snake_case string to camelCase. */\nexport function snakeToCamel(str: string): string {\n return str.replace(/_([a-z])/g, (_, ch) => ch.toUpperCase());\n}\n\n/** Recursively convert all object keys from camelCase to snake_case. */\nexport function toSnakeKeys(obj: unknown): unknown {\n if (Array.isArray(obj)) return obj.map(toSnakeKeys);\n if (obj !== null && typeof obj === \"object\" && !(obj instanceof Date)) {\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj as Record<string, unknown>)) {\n result[camelToSnake(k)] = toSnakeKeys(v);\n }\n return result;\n }\n return obj;\n}\n\n/**\n * Parse a numeric timestamp into a Date.\n *\n * Handles seconds, milliseconds, and microseconds by checking magnitude.\n */\nexport function parseTimestamp(v: unknown): Date | undefined {\n if (v == null) return undefined;\n if (v instanceof Date) return v;\n if (typeof v === \"string\") {\n const parsed = Date.parse(v);\n return Number.isNaN(parsed) ? undefined : new Date(parsed);\n }\n const ts = Number(v);\n if (isNaN(ts)) return undefined;\n if (ts > 1e15) return new Date(ts / 1000); // microseconds → ms\n if (ts > 1e12) return new Date(ts); // already ms\n return new Date(ts * 1000); // seconds → ms\n}\n\n/**\n * Recursively convert all object keys from snake_case to camelCase,\n * with special handling for `id` → contextual name and timestamp parsing.\n */\nexport function fromSnakeKeys(\n obj: unknown,\n idField?: string,\n): unknown {\n if (Array.isArray(obj)) return obj.map((item) => fromSnakeKeys(item, idField));\n if (obj !== null && typeof obj === \"object\" && !(obj instanceof Date)) {\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj as Record<string, unknown>)) {\n let key: string;\n if (k === \"id\" && idField) {\n key = idField;\n } else {\n key = snakeToCamel(k);\n }\n\n // Parse timestamp fields\n if (\n key.endsWith(\"At\") ||\n key === \"timestamp\" ||\n key === \"startedAt\" ||\n key === \"endedAt\"\n ) {\n result[key] = parseTimestamp(v);\n } else if (typeof v === \"object\" && v !== null && !Array.isArray(v)) {\n result[key] = fromSnakeKeys(v);\n } else if (Array.isArray(v)) {\n result[key] = v.map((item) => fromSnakeKeys(item));\n } else {\n // Normalize null → undefined so optional fields match TypeScript's ? convention.\n result[key] = v === null ? undefined : v;\n }\n }\n return result;\n }\n return obj;\n}\n","export const API_URL =\n process.env.TENSORLAKE_API_URL ?? \"https://api.tensorlake.ai\";\nexport const API_KEY = process.env.TENSORLAKE_API_KEY ?? undefined;\nexport const NAMESPACE = process.env.INDEXIFY_NAMESPACE ?? \"default\";\nexport const SANDBOX_PROXY_URL =\n process.env.TENSORLAKE_SANDBOX_PROXY_URL ?? \"https://sandbox.tensorlake.ai\";\n\nexport const DEFAULT_HTTP_TIMEOUT_MS = 30_000;\nexport const MAX_RETRIES = 3;\nexport const RETRY_BACKOFF_MS = 500;\nexport const RETRYABLE_STATUS_CODES = new Set([429, 502, 503, 504]);\n","/** Base exception for all sandbox-related errors. */\nexport class SandboxException extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"SandboxException\";\n }\n}\n\n/** General sandbox operation error. */\nexport class SandboxError extends SandboxException {\n constructor(message: string) {\n super(message);\n this.name = \"SandboxError\";\n }\n}\n\n/** Raised when the client cannot connect to the API server. */\nexport class SandboxConnectionError extends SandboxError {\n constructor(message: string) {\n super(`Connection error: ${message}`);\n this.name = \"SandboxConnectionError\";\n }\n}\n\n/** Raised when a sandbox is not found. */\nexport class SandboxNotFoundError extends SandboxError {\n readonly sandboxId: string;\n\n constructor(sandboxId: string) {\n super(`Sandbox not found: ${sandboxId}`);\n this.name = \"SandboxNotFoundError\";\n this.sandboxId = sandboxId;\n }\n}\n\n/** Raised when a sandbox pool is not found. */\nexport class PoolNotFoundError extends SandboxError {\n readonly poolId: string;\n\n constructor(poolId: string) {\n super(`Sandbox pool not found: ${poolId}`);\n this.name = \"PoolNotFoundError\";\n this.poolId = poolId;\n }\n}\n\n/** Raised when attempting to delete a pool that is in use. */\nexport class PoolInUseError extends SandboxError {\n readonly poolId: string;\n\n constructor(poolId: string, message?: string) {\n const base = `Cannot delete pool ${poolId}: pool is in use`;\n super(message ? `${base} - ${message}` : base);\n this.name = \"PoolInUseError\";\n this.poolId = poolId;\n }\n}\n\n/** Raised when the remote API returns an error. */\nexport class RemoteAPIError extends SandboxError {\n readonly statusCode: number;\n readonly responseMessage: string;\n\n constructor(statusCode: number, message: string) {\n super(`API error (status ${statusCode}): ${message}`);\n this.name = \"RemoteAPIError\";\n this.statusCode = statusCode;\n this.responseMessage = message;\n }\n}\n\n/** Raised when request output is fetched before the request has completed. */\nexport class RequestNotFinishedError extends Error {\n constructor() {\n super(\"Request has not finished yet\");\n this.name = \"RequestNotFinishedError\";\n }\n}\n\n/** Raised when a request completed unsuccessfully. */\nexport class RequestFailedError extends Error {\n readonly failure: string;\n\n constructor(failure: string) {\n super(`Request failed: ${failure}`);\n this.name = \"RequestFailedError\";\n this.failure = failure;\n }\n}\n\n/** Raised when a request surfaced an application-level error. */\nexport class RequestExecutionError extends Error {\n readonly functionName?: string;\n\n constructor(message: string, functionName?: string) {\n super(\n functionName ? `Request error in ${functionName}: ${message}` : message,\n );\n this.name = \"RequestExecutionError\";\n this.functionName = functionName;\n }\n}\n","import * as defaults from \"./defaults.js\";\nimport {\n PoolInUseError,\n PoolNotFoundError,\n RemoteAPIError,\n SandboxConnectionError,\n SandboxNotFoundError,\n} from \"./errors.js\";\n\nexport interface HttpClientOptions {\n baseUrl: string;\n apiKey?: string;\n organizationId?: string;\n projectId?: string;\n hostHeader?: string;\n maxRetries?: number;\n retryBackoffMs?: number;\n timeoutMs?: number;\n}\n\ntype RequestBody = BodyInit | Uint8Array | ArrayBuffer;\n\nexport interface HttpRequestOptions {\n body?: RequestBody | null;\n headers?: Record<string, string>;\n json?: unknown;\n signal?: AbortSignal;\n allowHttpErrors?: boolean;\n}\n\n/**\n * Internal HTTP client with retry logic, auth headers, and error mapping.\n *\n * Uses native `fetch`. Retries on transient status codes (429, 502, 503, 504)\n * with exponential backoff.\n */\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly headers: Record<string, string>;\n private readonly maxRetries: number;\n private readonly retryBackoffMs: number;\n private readonly timeoutMs: number;\n private abortController: AbortController | null = null;\n\n constructor(options: HttpClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, \"\");\n this.maxRetries = options.maxRetries ?? defaults.MAX_RETRIES;\n this.retryBackoffMs = options.retryBackoffMs ?? defaults.RETRY_BACKOFF_MS;\n this.timeoutMs = options.timeoutMs ?? defaults.DEFAULT_HTTP_TIMEOUT_MS;\n\n this.headers = {};\n if (options.apiKey) {\n this.headers[\"Authorization\"] = `Bearer ${options.apiKey}`;\n }\n if (options.organizationId) {\n this.headers[\"X-Forwarded-Organization-Id\"] = options.organizationId;\n }\n if (options.projectId) {\n this.headers[\"X-Forwarded-Project-Id\"] = options.projectId;\n }\n if (options.hostHeader) {\n this.headers[\"Host\"] = options.hostHeader;\n }\n }\n\n close(): void {\n this.abortController?.abort();\n this.abortController = null;\n }\n\n /** Make a JSON request, returning the parsed response body. */\n async requestJson<T>(\n method: string,\n path: string,\n options?: {\n body?: unknown;\n headers?: Record<string, string>;\n signal?: AbortSignal;\n },\n ): Promise<T> {\n const response = await this.requestResponse(method, path, {\n json: options?.body,\n headers: options?.headers,\n signal: options?.signal,\n });\n const text = await response.text();\n if (!text) return undefined as T;\n return JSON.parse(text) as T;\n }\n\n /** Make a request returning raw bytes. */\n async requestBytes(\n method: string,\n path: string,\n options?: {\n body?: RequestBody | null;\n contentType?: string;\n headers?: Record<string, string>;\n signal?: AbortSignal;\n },\n ): Promise<Uint8Array> {\n const headers = { ...(options?.headers ?? {}) };\n if (options?.contentType) {\n headers[\"Content-Type\"] = options.contentType;\n }\n\n const response = await this.requestResponse(\n method,\n path,\n {\n body: options?.body,\n headers,\n signal: options?.signal,\n },\n );\n const buffer = await response.arrayBuffer();\n return new Uint8Array(buffer);\n }\n\n /** Make a request and return the raw Response (for SSE streaming). */\n async requestStream(\n method: string,\n path: string,\n options?: { signal?: AbortSignal },\n ): Promise<ReadableStream<Uint8Array>> {\n const response = await this.requestResponse(\n method,\n path,\n {\n headers: { Accept: \"text/event-stream\" },\n signal: options?.signal,\n },\n );\n if (!response.body) {\n throw new RemoteAPIError(response.status, \"No response body for SSE stream\");\n }\n return response.body;\n }\n\n /** Make a request and return the raw Response. */\n async requestResponse(\n method: string,\n path: string,\n options?: HttpRequestOptions,\n ): Promise<Response> {\n const headers = {\n ...this.headers,\n ...(options?.headers ?? {}),\n };\n const hasJsonBody = options?.json !== undefined;\n if (hasJsonBody && !hasHeader(headers, \"Content-Type\")) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const body = hasJsonBody\n ? JSON.stringify(options?.json)\n : normalizeRequestBody(options?.body);\n\n return this.doFetch(\n method,\n path,\n body,\n headers,\n options?.signal,\n options?.allowHttpErrors ?? false,\n );\n }\n\n private async doFetch(\n method: string,\n path: string,\n body: BodyInit | undefined,\n headers: Record<string, string>,\n signal?: AbortSignal,\n allowHttpErrors = false,\n ): Promise<Response> {\n const url = `${this.baseUrl}${path}`;\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n if (attempt > 0) {\n const delay = this.retryBackoffMs * Math.pow(2, attempt - 1);\n await sleep(delay);\n }\n\n this.abortController = new AbortController();\n const timeoutId = setTimeout(\n () => this.abortController?.abort(),\n this.timeoutMs,\n );\n\n // Combine external signal with internal timeout\n const combinedSignal = signal\n ? anySignal([signal, this.abortController.signal])\n : this.abortController.signal;\n\n try {\n const response = await fetch(url, {\n method,\n headers,\n body,\n signal: combinedSignal,\n });\n\n clearTimeout(timeoutId);\n\n if (response.ok) return response;\n\n // Check if retryable\n if (\n defaults.RETRYABLE_STATUS_CODES.has(response.status) &&\n attempt < this.maxRetries\n ) {\n lastError = new RemoteAPIError(\n response.status,\n await response.text().catch(() => \"\"),\n );\n continue;\n }\n\n if (allowHttpErrors) {\n return response;\n }\n\n // Non-retryable error — throw mapped error\n const errorBody = await response.text().catch(() => \"\");\n throwMappedError(response.status, errorBody, path);\n } catch (err) {\n clearTimeout(timeoutId);\n\n if (err instanceof RemoteAPIError || err instanceof SandboxNotFoundError ||\n err instanceof PoolNotFoundError || err instanceof PoolInUseError) {\n throw err;\n }\n\n if (signal?.aborted) {\n throw new SandboxConnectionError(\"Request aborted\");\n }\n\n // Network / timeout error\n lastError =\n err instanceof Error ? err : new Error(String(err));\n\n if (attempt >= this.maxRetries) {\n throw new SandboxConnectionError(lastError.message);\n }\n }\n }\n\n throw new SandboxConnectionError(lastError?.message ?? \"Request failed\");\n }\n}\n\nfunction hasHeader(headers: Record<string, string>, name: string): boolean {\n const lowered = name.toLowerCase();\n return Object.keys(headers).some((key) => key.toLowerCase() === lowered);\n}\n\nfunction normalizeRequestBody(body?: RequestBody | null): BodyInit | undefined {\n if (body == null) {\n return undefined;\n }\n if (body instanceof Uint8Array) {\n return Uint8Array.from(body).buffer;\n }\n return body;\n}\n\n/** Map HTTP status codes to specific error types. */\nfunction throwMappedError(\n status: number,\n body: string,\n path: string,\n): never {\n let message = body;\n try {\n const parsed = JSON.parse(body);\n if (parsed.message) message = parsed.message;\n else if (parsed.error) message = parsed.error;\n } catch {\n // use raw body\n }\n\n if (status === 404) {\n // Determine entity type from path\n if (path.includes(\"sandbox-pools\") || path.includes(\"pools\")) {\n const match = path.match(/sandbox-pools\\/([^/]+)/);\n if (match) throw new PoolNotFoundError(match[1]);\n }\n if (path.includes(\"sandboxes\")) {\n const match = path.match(/sandboxes\\/([^/]+)/);\n if (match) throw new SandboxNotFoundError(match[1]);\n }\n throw new RemoteAPIError(404, message);\n }\n\n if (status === 409) {\n if (path.includes(\"sandbox-pools\") || path.includes(\"pools\")) {\n const match = path.match(/sandbox-pools\\/([^/]+)/);\n if (match) throw new PoolInUseError(match[1], message);\n }\n }\n\n throw new RemoteAPIError(status, message);\n}\n\n/** Combine multiple AbortSignals into one that aborts when any fires. */\nfunction anySignal(signals: AbortSignal[]): AbortSignal {\n const controller = new AbortController();\n for (const signal of signals) {\n if (signal.aborted) {\n controller.abort(signal.reason);\n return controller.signal;\n }\n signal.addEventListener(\"abort\", () => controller.abort(signal.reason), {\n once: true,\n });\n }\n return controller.signal;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","export interface SSEMessage {\n data: string;\n event?: string;\n id?: string;\n}\n\n/**\n * Parse a Server-Sent Events stream into raw SSE messages.\n */\nexport async function* parseSSEMessages(\n stream: ReadableStream<Uint8Array>,\n signal?: AbortSignal,\n): AsyncIterable<SSEMessage> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n if (signal?.aborted) break;\n\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const parts = buffer.split(/\\r?\\n\\r?\\n/);\n buffer = parts.pop() ?? \"\";\n\n for (const part of parts) {\n const lines = part.split(/\\r?\\n/);\n const dataLines: string[] = [];\n let event: string | undefined;\n let id: string | undefined;\n\n for (const line of lines) {\n if (!line || line.startsWith(\":\")) continue;\n\n const separator = line.indexOf(\":\");\n const field = separator === -1 ? line : line.slice(0, separator);\n let value = separator === -1 ? \"\" : line.slice(separator + 1);\n if (value.startsWith(\" \")) {\n value = value.slice(1);\n }\n\n if (field === \"data\") {\n dataLines.push(value);\n } else if (field === \"event\") {\n event = value;\n } else if (field === \"id\") {\n id = value;\n }\n }\n\n if (dataLines.length > 0 || event || id) {\n yield { data: dataLines.join(\"\\n\"), event, id };\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/**\n * Parse a Server-Sent Events stream from a ReadableStream<Uint8Array>.\n *\n * Yields parsed JSON objects for each `data:` line. Handles reconnection\n * by simply yielding events as they arrive.\n */\nexport async function* parseSSEStream<T>(\n stream: ReadableStream<Uint8Array>,\n signal?: AbortSignal,\n): AsyncIterable<T> {\n for await (const message of parseSSEMessages(stream, signal)) {\n if (!message.data) continue;\n try {\n yield JSON.parse(message.data) as T;\n } catch {\n // Skip malformed JSON\n }\n }\n}\n","import * as defaults from \"./defaults.js\";\n\n/** Check whether a URL points to localhost. */\nexport function isLocalhost(apiUrl: string): boolean {\n try {\n const parsed = new URL(apiUrl);\n return parsed.hostname === \"localhost\" || parsed.hostname === \"127.0.0.1\";\n } catch {\n return false;\n }\n}\n\n/**\n * Derive the sandbox proxy URL from the API URL.\n *\n * Priority:\n * 1. TENSORLAKE_SANDBOX_PROXY_URL env var\n * 2. `http://localhost:9443` for localhost API URLs\n * 3. Transform `api.X` → `sandbox.X`\n * 4. Default fallback\n */\nexport function resolveProxyUrl(apiUrl: string): string {\n const explicit = process.env.TENSORLAKE_SANDBOX_PROXY_URL;\n if (explicit) return explicit;\n\n if (isLocalhost(apiUrl)) return \"http://localhost:9443\";\n\n try {\n const parsed = new URL(apiUrl);\n const host = parsed.hostname;\n if (host.startsWith(\"api.\")) {\n const proxyHost = \"sandbox.\" + host.slice(4);\n return `${parsed.protocol}//${proxyHost}`;\n }\n } catch {\n // fall through to default\n }\n\n return defaults.SANDBOX_PROXY_URL;\n}\n\n/**\n * Resolve the proxy target for a specific sandbox.\n *\n * - Localhost: base URL stays the same, Host header set to `{sandboxId}.local`\n * - Cloud: sandbox ID becomes a subdomain of the proxy host\n *\n * Returns `{ baseUrl, hostHeader }`.\n */\nexport function resolveProxyTarget(\n proxyUrl: string,\n sandboxId: string,\n): { baseUrl: string; hostHeader: string | undefined } {\n try {\n const parsed = new URL(proxyUrl);\n const host = parsed.hostname;\n\n if (host === \"localhost\" || host === \"127.0.0.1\") {\n return {\n baseUrl: proxyUrl.replace(/\\/+$/, \"\"),\n hostHeader: `${sandboxId}.local`,\n };\n }\n\n const port = parsed.port ? `:${parsed.port}` : \"\";\n return {\n baseUrl: `${parsed.protocol}//${sandboxId}.${host}${port}`,\n hostHeader: undefined,\n };\n } catch {\n return {\n baseUrl: `${proxyUrl.replace(/\\/+$/, \"\")}/${sandboxId}`,\n hostHeader: undefined,\n };\n }\n}\n\n/**\n * Build a lifecycle API path.\n *\n * - Localhost (namespaced): `/v1/namespaces/{namespace}/{path}`\n * - Cloud (flat): `/{path}`\n */\nexport function lifecyclePath(\n path: string,\n isLocal: boolean,\n namespace: string,\n): string {\n if (isLocal) {\n return `/v1/namespaces/${namespace}/${path}`;\n }\n return `/${path}`;\n}\n","import type { SandboxClient } from \"./client.js\";\nimport * as defaults from \"./defaults.js\";\nimport { SandboxError } from \"./errors.js\";\nimport { HttpClient } from \"./http.js\";\nimport {\n type CommandResult,\n type CreatePtySessionOptions,\n type DaemonInfo,\n type DirectoryEntry,\n type HealthResponse,\n type ListDirectoryResponse,\n OutputMode,\n type OutputEvent,\n type OutputResponse,\n type ProcessInfo,\n ProcessStatus,\n type PtySessionInfo,\n type RunOptions,\n type SandboxOptions,\n type SendSignalResponse,\n type StartProcessOptions,\n StdinMode,\n fromSnakeKeys,\n} from \"./models.js\";\nimport { parseSSEStream } from \"./sse.js\";\nimport { resolveProxyTarget } from \"./url.js\";\nimport WebSocket, { type RawData } from \"ws\";\n\nconst PTY_OP_DATA = 0x00;\nconst PTY_OP_RESIZE = 0x01;\nconst PTY_OP_READY = 0x02;\nconst PTY_OP_EXIT = 0x03;\n\nexport type PtyDataHandler = (data: Uint8Array) => void;\nexport type PtyExitHandler = (exitCode: number) => void;\n\nexport interface PtyConnectionOptions {\n onData?: PtyDataHandler;\n onExit?: PtyExitHandler;\n}\n\nexport interface CreatePtyOptions\n extends CreatePtySessionOptions,\n PtyConnectionOptions {}\n\nexport class Pty {\n readonly sessionId: string;\n readonly token: string;\n\n private readonly wsUrl: string;\n private readonly wsHeaders: Record<string, string>;\n private readonly killSession: () => Promise<void>;\n private socket: WebSocket | null = null;\n private connectPromise: Promise<this> | null = null;\n private intentionalDisconnect = false;\n private exitCode: number | null = null;\n private waitSettled = false;\n private readonly dataHandlers = new Set<PtyDataHandler>();\n private readonly exitHandlers = new Set<PtyExitHandler>();\n private readonly waitPromise: Promise<number>;\n private resolveWait!: (exitCode: number) => void;\n private rejectWait!: (error: unknown) => void;\n\n constructor(options: {\n sessionId: string;\n token: string;\n wsUrl: string;\n wsHeaders: Record<string, string>;\n killSession: () => Promise<void>;\n }) {\n this.sessionId = options.sessionId;\n this.token = options.token;\n this.wsUrl = options.wsUrl;\n this.wsHeaders = options.wsHeaders;\n this.killSession = options.killSession;\n this.waitPromise = new Promise<number>((resolve, reject) => {\n this.resolveWait = resolve;\n this.rejectWait = reject;\n });\n }\n\n onData(handler: PtyDataHandler): () => void {\n this.dataHandlers.add(handler);\n return () => this.dataHandlers.delete(handler);\n }\n\n onExit(handler: PtyExitHandler): () => void {\n this.exitHandlers.add(handler);\n if (this.exitCode != null) {\n queueMicrotask(() => handler(this.exitCode!));\n }\n return () => this.exitHandlers.delete(handler);\n }\n\n async connect(): Promise<this> {\n if (this.socket?.readyState === WebSocket.OPEN) {\n return this;\n }\n if (this.connectPromise) {\n return this.connectPromise;\n }\n\n this.intentionalDisconnect = false;\n\n this.connectPromise = new Promise<this>((resolve, reject) => {\n let opened = false;\n const socket = new WebSocket(this.wsUrl, {\n headers: this.wsHeaders,\n });\n this.socket = socket;\n\n socket.on(\"open\", async () => {\n try {\n await sendPtyFrame(socket, Buffer.from([PTY_OP_READY]));\n opened = true;\n resolve(this);\n } catch (error) {\n reject(error);\n }\n });\n\n socket.on(\"message\", (message: RawData) => {\n const bytes = normalizePtyMessage(message);\n const opcode = bytes[0];\n\n if (opcode === PTY_OP_DATA) {\n const payload = bytes.subarray(1);\n for (const handler of this.dataHandlers) {\n handler(payload);\n }\n return;\n }\n\n if (opcode === PTY_OP_EXIT && bytes.length >= 5) {\n this.finishWait(bytes.readInt32BE(1));\n }\n });\n\n socket.on(\"close\", (code: number, reason: Buffer) => {\n const closeReason = Buffer.isBuffer(reason)\n ? reason.toString(\"utf8\")\n : String(reason);\n\n if (this.socket === socket) {\n this.socket = null;\n }\n this.connectPromise = null;\n\n if (this.exitCode != null) {\n this.finishWait(this.exitCode);\n return;\n }\n\n if (closeReason.startsWith(\"exit:\")) {\n const parsed = Number.parseInt(closeReason.slice(5), 10);\n this.finishWait(Number.isNaN(parsed) ? -1 : parsed);\n return;\n }\n\n if (this.intentionalDisconnect) {\n this.intentionalDisconnect = false;\n return;\n }\n\n if (!opened) {\n reject(new SandboxError(\n `PTY websocket closed before READY completed: ${code} ${closeReason || \"no reason\"}`,\n ));\n return;\n }\n\n if (closeReason === \"session terminated\") {\n this.failWait(new SandboxError(\"PTY session terminated\"));\n return;\n }\n\n this.failWait(\n new SandboxError(\n `PTY websocket closed unexpectedly: ${code} ${closeReason || \"no reason\"}`,\n ),\n );\n });\n\n socket.on(\"error\", (error: Error) => {\n if (!opened) {\n reject(error);\n }\n });\n });\n\n return this.connectPromise;\n }\n\n async sendInput(input: string | Uint8Array): Promise<void> {\n const socket = this.requireOpenSocket();\n await sendPtyFrame(socket, encodePtyInput(input));\n }\n\n async resize(cols: number, rows: number): Promise<void> {\n const socket = this.requireOpenSocket();\n await sendPtyFrame(socket, encodePtyResize(cols, rows));\n }\n\n disconnect(code = 1000, reason = \"client disconnect\"): void {\n if (!this.socket) return;\n this.intentionalDisconnect = true;\n this.socket.close(code, reason);\n }\n\n wait(): Promise<number> {\n return this.waitPromise;\n }\n\n async kill(): Promise<void> {\n await this.killSession();\n }\n\n private requireOpenSocket(): WebSocket {\n if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {\n throw new SandboxError(\"PTY is not connected\");\n }\n return this.socket;\n }\n\n private finishWait(exitCode: number): void {\n if (this.waitSettled) return;\n this.waitSettled = true;\n this.exitCode = exitCode;\n for (const handler of this.exitHandlers) {\n handler(exitCode);\n }\n this.resolveWait(exitCode);\n }\n\n private failWait(error: unknown): void {\n if (this.waitSettled) return;\n this.waitSettled = true;\n this.rejectWait(error);\n }\n}\n\nfunction normalizePtyMessage(message: RawData): Buffer {\n if (Buffer.isBuffer(message)) return message;\n if (Array.isArray(message)) {\n return Buffer.concat(message.map((part) => Buffer.from(part)));\n }\n return Buffer.from(message);\n}\n\nfunction encodePtyInput(input: string | Uint8Array): Buffer {\n const payload =\n typeof input === \"string\" ? Buffer.from(input, \"utf8\") : Buffer.from(input);\n return Buffer.concat([Buffer.from([PTY_OP_DATA]), payload]);\n}\n\nfunction encodePtyResize(cols: number, rows: number): Buffer {\n const frame = Buffer.alloc(5);\n frame[0] = PTY_OP_RESIZE;\n frame.writeUInt16BE(cols, 1);\n frame.writeUInt16BE(rows, 3);\n return frame;\n}\n\nfunction sendPtyFrame(socket: WebSocket, frame: Buffer): Promise<void> {\n return new Promise((resolve, reject) => {\n socket.send(frame, (error?: Error) => (error ? reject(error) : resolve()));\n });\n}\n\n/**\n * Client for interacting with a running sandbox.\n *\n * Provides process management, file operations, and I/O streaming\n * through the sandbox proxy.\n */\nexport class Sandbox {\n readonly sandboxId: string;\n private readonly http: HttpClient;\n private readonly baseUrl: string;\n private readonly wsHeaders: Record<string, string>;\n private ownsSandbox = false;\n private lifecycleClient: SandboxClient | null = null;\n\n constructor(options: SandboxOptions) {\n this.sandboxId = options.sandboxId;\n\n const proxyUrl = options.proxyUrl ?? defaults.SANDBOX_PROXY_URL;\n const { baseUrl, hostHeader } = resolveProxyTarget(proxyUrl, options.sandboxId);\n this.baseUrl = baseUrl;\n this.wsHeaders = {};\n if (options.apiKey) {\n this.wsHeaders.Authorization = `Bearer ${options.apiKey}`;\n }\n if (options.organizationId) {\n this.wsHeaders[\"X-Forwarded-Organization-Id\"] = options.organizationId;\n }\n if (options.projectId) {\n this.wsHeaders[\"X-Forwarded-Project-Id\"] = options.projectId;\n }\n if (hostHeader) {\n this.wsHeaders.Host = hostHeader;\n }\n\n this.http = new HttpClient({\n baseUrl,\n apiKey: options.apiKey,\n organizationId: options.organizationId,\n projectId: options.projectId,\n hostHeader,\n });\n }\n\n /** @internal Used by SandboxClient.createAndConnect to set ownership. */\n _setOwner(client: SandboxClient): void {\n this.ownsSandbox = true;\n this.lifecycleClient = client;\n }\n\n close(): void {\n this.http.close();\n }\n\n async terminate(): Promise<void> {\n const client = this.lifecycleClient;\n this.ownsSandbox = false;\n this.lifecycleClient = null;\n this.close();\n if (client) {\n await client.delete(this.sandboxId);\n }\n }\n\n // --- High-level convenience ---\n\n async run(command: string, options?: RunOptions): Promise<CommandResult> {\n const proc = await this.startProcess(command, {\n args: options?.args,\n env: options?.env,\n workingDir: options?.workingDir,\n });\n\n const deadline = options?.timeout\n ? Date.now() + options.timeout * 1000\n : null;\n\n let info: ProcessInfo;\n while (true) {\n info = await this.getProcess(proc.pid);\n if (info.status !== ProcessStatus.RUNNING) break;\n if (deadline && Date.now() > deadline) {\n await this.killProcess(proc.pid);\n throw new SandboxError(`Command timed out after ${options!.timeout}s`);\n }\n await sleep(100);\n }\n\n const stdoutResp = await this.getStdout(proc.pid);\n const stderrResp = await this.getStderr(proc.pid);\n\n let exitCode: number;\n if (info.exitCode != null) {\n exitCode = info.exitCode;\n } else if (info.signal != null) {\n exitCode = -info.signal;\n } else {\n exitCode = -1;\n }\n\n return {\n exitCode,\n stdout: stdoutResp.lines.join(\"\\n\"),\n stderr: stderrResp.lines.join(\"\\n\"),\n };\n }\n\n // --- Process management ---\n\n async startProcess(\n command: string,\n options?: StartProcessOptions,\n ): Promise<ProcessInfo> {\n const payload: Record<string, unknown> = { command };\n if (options?.args != null) payload.args = options.args;\n if (options?.env != null) payload.env = options.env;\n if (options?.workingDir != null) payload.working_dir = options.workingDir;\n if (options?.stdinMode != null && options.stdinMode !== StdinMode.CLOSED) {\n payload.stdin_mode = options.stdinMode;\n }\n if (options?.stdoutMode != null && options.stdoutMode !== OutputMode.CAPTURE) {\n payload.stdout_mode = options.stdoutMode;\n }\n if (options?.stderrMode != null && options.stderrMode !== OutputMode.CAPTURE) {\n payload.stderr_mode = options.stderrMode;\n }\n\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"POST\",\n \"/api/v1/processes\",\n { body: payload },\n );\n return fromSnakeKeys(raw) as ProcessInfo;\n }\n\n async listProcesses(): Promise<ProcessInfo[]> {\n const raw = await this.http.requestJson<{ processes: Record<string, unknown>[] }>(\n \"GET\",\n \"/api/v1/processes\",\n );\n return (raw.processes ?? []).map((p) => fromSnakeKeys(p) as ProcessInfo);\n }\n\n async getProcess(pid: number): Promise<ProcessInfo> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n `/api/v1/processes/${pid}`,\n );\n return fromSnakeKeys(raw) as ProcessInfo;\n }\n\n async killProcess(pid: number): Promise<void> {\n await this.http.requestJson(\"DELETE\", `/api/v1/processes/${pid}`);\n }\n\n async sendSignal(pid: number, signal: number): Promise<SendSignalResponse> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"POST\",\n `/api/v1/processes/${pid}/signal`,\n { body: { signal } },\n );\n return fromSnakeKeys(raw) as SendSignalResponse;\n }\n\n // --- Process I/O ---\n\n async writeStdin(pid: number, data: Uint8Array): Promise<void> {\n await this.http.requestBytes(\"POST\", `/api/v1/processes/${pid}/stdin`, {\n body: data,\n contentType: \"application/octet-stream\",\n });\n }\n\n async closeStdin(pid: number): Promise<void> {\n await this.http.requestJson(\"POST\", `/api/v1/processes/${pid}/stdin/close`);\n }\n\n async getStdout(pid: number): Promise<OutputResponse> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n `/api/v1/processes/${pid}/stdout`,\n );\n return fromSnakeKeys(raw) as OutputResponse;\n }\n\n async getStderr(pid: number): Promise<OutputResponse> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n `/api/v1/processes/${pid}/stderr`,\n );\n return fromSnakeKeys(raw) as OutputResponse;\n }\n\n async getOutput(pid: number): Promise<OutputResponse> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n `/api/v1/processes/${pid}/output`,\n );\n return fromSnakeKeys(raw) as OutputResponse;\n }\n\n // --- Streaming (SSE) ---\n\n async *followStdout(\n pid: number,\n options?: { signal?: AbortSignal },\n ): AsyncIterable<OutputEvent> {\n const stream = await this.http.requestStream(\n \"GET\",\n `/api/v1/processes/${pid}/stdout/follow`,\n options,\n );\n for await (const raw of parseSSEStream<Record<string, unknown>>(\n stream,\n options?.signal,\n )) {\n yield fromSnakeKeys(raw) as OutputEvent;\n }\n }\n\n async *followStderr(\n pid: number,\n options?: { signal?: AbortSignal },\n ): AsyncIterable<OutputEvent> {\n const stream = await this.http.requestStream(\n \"GET\",\n `/api/v1/processes/${pid}/stderr/follow`,\n options,\n );\n for await (const raw of parseSSEStream<Record<string, unknown>>(\n stream,\n options?.signal,\n )) {\n yield fromSnakeKeys(raw) as OutputEvent;\n }\n }\n\n async *followOutput(\n pid: number,\n options?: { signal?: AbortSignal },\n ): AsyncIterable<OutputEvent> {\n const stream = await this.http.requestStream(\n \"GET\",\n `/api/v1/processes/${pid}/output/follow`,\n options,\n );\n for await (const raw of parseSSEStream<Record<string, unknown>>(\n stream,\n options?.signal,\n )) {\n yield fromSnakeKeys(raw) as OutputEvent;\n }\n }\n\n // --- File operations ---\n\n async readFile(path: string): Promise<Uint8Array> {\n return this.http.requestBytes(\n \"GET\",\n `/api/v1/files?path=${encodeURIComponent(path)}`,\n );\n }\n\n async writeFile(path: string, content: Uint8Array): Promise<void> {\n await this.http.requestBytes(\n \"PUT\",\n `/api/v1/files?path=${encodeURIComponent(path)}`,\n { body: content, contentType: \"application/octet-stream\" },\n );\n }\n\n async deleteFile(path: string): Promise<void> {\n await this.http.requestJson(\n \"DELETE\",\n `/api/v1/files?path=${encodeURIComponent(path)}`,\n );\n }\n\n async listDirectory(path: string): Promise<ListDirectoryResponse> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n `/api/v1/files/list?path=${encodeURIComponent(path)}`,\n );\n return fromSnakeKeys(raw) as ListDirectoryResponse;\n }\n\n // --- PTY ---\n\n async createPtySession(\n options: CreatePtySessionOptions,\n ): Promise<PtySessionInfo> {\n const payload: Record<string, unknown> = {\n command: options.command,\n rows: options.rows ?? 24,\n cols: options.cols ?? 80,\n };\n if (options.args != null) payload.args = options.args;\n if (options.env != null) payload.env = options.env;\n if (options.workingDir != null) payload.working_dir = options.workingDir;\n\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"POST\",\n \"/api/v1/pty\",\n { body: payload },\n );\n return fromSnakeKeys(raw) as PtySessionInfo;\n }\n\n async createPty(options: CreatePtyOptions): Promise<Pty> {\n const { onData, onExit, ...createOptions } = options;\n const session = await this.createPtySession(createOptions);\n try {\n return await this.connectPty(session.sessionId, session.token, { onData, onExit });\n } catch (error) {\n try {\n await this.http.requestResponse(\"DELETE\", `/api/v1/pty/${session.sessionId}`);\n } catch {}\n throw error;\n }\n }\n\n async connectPty(\n sessionId: string,\n token: string,\n options?: PtyConnectionOptions,\n ): Promise<Pty> {\n const wsUrl = new URL(this.ptyWsUrl(sessionId, token));\n const authToken = wsUrl.searchParams.get(\"token\") ?? token;\n\n const pty = new Pty({\n sessionId,\n token: authToken,\n wsUrl: wsUrl.toString(),\n wsHeaders: {\n ...this.wsHeaders,\n \"X-PTY-Token\": authToken,\n },\n killSession: async () => {\n await this.http.requestResponse(\"DELETE\", `/api/v1/pty/${sessionId}`);\n },\n });\n\n if (options?.onData) {\n pty.onData(options.onData);\n }\n if (options?.onExit) {\n pty.onExit(options.onExit);\n }\n\n await pty.connect();\n return pty;\n }\n\n ptyWsUrl(sessionId: string, token: string): string {\n let wsBase: string;\n if (this.baseUrl.startsWith(\"https://\")) {\n wsBase = \"wss://\" + this.baseUrl.slice(8);\n } else if (this.baseUrl.startsWith(\"http://\")) {\n wsBase = \"ws://\" + this.baseUrl.slice(7);\n } else {\n wsBase = this.baseUrl;\n }\n return `${wsBase}/api/v1/pty/${sessionId}/ws?token=${token}`;\n }\n\n // --- Health ---\n\n async health(): Promise<HealthResponse> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n \"/api/v1/health\",\n );\n return fromSnakeKeys(raw) as HealthResponse;\n }\n\n async info(): Promise<DaemonInfo> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n \"/api/v1/info\",\n );\n return fromSnakeKeys(raw) as DaemonInfo;\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import * as defaults from \"./defaults.js\";\nimport { SandboxError } from \"./errors.js\";\nimport { HttpClient } from \"./http.js\";\nimport {\n type CreateAndConnectOptions,\n type CreatePoolOptions,\n type CreateSandboxOptions,\n type CreateSandboxPoolResponse,\n type CreateSandboxResponse,\n type CreateSnapshotResponse,\n type SandboxClientOptions,\n type SandboxInfo,\n type SandboxPortAccess,\n type SandboxPoolInfo,\n SandboxStatus,\n type SnapshotAndWaitOptions,\n type SnapshotInfo,\n SnapshotStatus,\n type UpdatePoolOptions,\n type UpdateSandboxOptions,\n fromSnakeKeys,\n toSnakeKeys,\n} from \"./models.js\";\nimport { Sandbox } from \"./sandbox.js\";\nimport { isLocalhost, lifecyclePath, resolveProxyUrl } from \"./url.js\";\n\n/**\n * Client for managing TensorLake sandboxes, pools, and snapshots.\n *\n * Use `SandboxClient.forCloud()` or `SandboxClient.forLocalhost()` for\n * clearer construction depending on your deployment target.\n */\nexport class SandboxClient {\n private readonly http: HttpClient;\n private readonly apiUrl: string;\n private readonly apiKey: string | undefined;\n private readonly organizationId: string | undefined;\n private readonly projectId: string | undefined;\n private readonly namespace: string;\n private readonly local: boolean;\n\n constructor(options?: SandboxClientOptions) {\n this.apiUrl = options?.apiUrl ?? defaults.API_URL;\n this.apiKey = options?.apiKey ?? defaults.API_KEY;\n this.organizationId = options?.organizationId;\n this.projectId = options?.projectId;\n this.namespace = options?.namespace ?? defaults.NAMESPACE;\n this.local = isLocalhost(this.apiUrl);\n\n this.http = new HttpClient({\n baseUrl: this.apiUrl,\n apiKey: this.apiKey,\n organizationId: this.organizationId,\n projectId: this.projectId,\n maxRetries: options?.maxRetries ?? defaults.MAX_RETRIES,\n retryBackoffMs: options?.retryBackoffMs ?? defaults.RETRY_BACKOFF_MS,\n });\n }\n\n /** Create a client for the TensorLake cloud platform. */\n static forCloud(options?: {\n apiKey?: string;\n organizationId?: string;\n projectId?: string;\n apiUrl?: string;\n }): SandboxClient {\n return new SandboxClient({\n apiUrl: options?.apiUrl ?? \"https://api.tensorlake.ai\",\n apiKey: options?.apiKey,\n organizationId: options?.organizationId,\n projectId: options?.projectId,\n });\n }\n\n /** Create a client for a local Indexify server. */\n static forLocalhost(options?: {\n apiUrl?: string;\n namespace?: string;\n }): SandboxClient {\n return new SandboxClient({\n apiUrl: options?.apiUrl ?? \"http://localhost:8900\",\n namespace: options?.namespace ?? \"default\",\n });\n }\n\n close(): void {\n this.http.close();\n }\n\n // --- Path helper ---\n\n private path(subpath: string): string {\n return lifecyclePath(subpath, this.local, this.namespace);\n }\n\n // --- Sandbox CRUD ---\n\n async create(options?: CreateSandboxOptions): Promise<CreateSandboxResponse> {\n const body: Record<string, unknown> = {\n resources: {\n cpus: options?.cpus ?? 1.0,\n memory_mb: options?.memoryMb ?? 1024,\n ephemeral_disk_mb: options?.ephemeralDiskMb ?? 1024,\n },\n };\n\n if (options?.image != null) body.image = options.image;\n if (options?.secretNames != null) body.secret_names = options.secretNames;\n if (options?.timeoutSecs != null) body.timeout_secs = options.timeoutSecs;\n if (options?.entrypoint != null) body.entrypoint = options.entrypoint;\n if (options?.snapshotId != null) body.snapshot_id = options.snapshotId;\n if (options?.name != null) body.name = options.name;\n\n if (\n options?.allowInternetAccess === false ||\n options?.allowOut != null ||\n options?.denyOut != null\n ) {\n body.network = {\n allow_internet_access: options?.allowInternetAccess ?? true,\n allow_out: options?.allowOut ?? [],\n deny_out: options?.denyOut ?? [],\n };\n }\n\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"POST\",\n this.path(\"sandboxes\"),\n { body },\n );\n return fromSnakeKeys(raw, \"sandboxId\") as CreateSandboxResponse;\n }\n\n async get(sandboxId: string): Promise<SandboxInfo> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n this.path(`sandboxes/${sandboxId}`),\n );\n return fromSnakeKeys(raw, \"sandboxId\") as SandboxInfo;\n }\n\n async list(): Promise<SandboxInfo[]> {\n const raw = await this.http.requestJson<{ sandboxes: Record<string, unknown>[] }>(\n \"GET\",\n this.path(\"sandboxes\"),\n );\n return (raw.sandboxes ?? []).map(\n (s) => fromSnakeKeys(s, \"sandboxId\") as SandboxInfo,\n );\n }\n\n async update(sandboxId: string, options: UpdateSandboxOptions): Promise<SandboxInfo> {\n const body: Record<string, unknown> = {};\n if (options.name != null) body.name = options.name;\n if (options.allowUnauthenticatedAccess != null) {\n body.allow_unauthenticated_access = options.allowUnauthenticatedAccess;\n }\n if (options.exposedPorts != null) {\n body.exposed_ports = normalizeUserPorts(options.exposedPorts);\n }\n if (Object.keys(body).length === 0) {\n throw new SandboxError(\"At least one sandbox update field must be provided.\");\n }\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"PATCH\",\n this.path(`sandboxes/${sandboxId}`),\n { body },\n );\n return fromSnakeKeys(raw, \"sandboxId\") as SandboxInfo;\n }\n\n async getPortAccess(sandboxId: string): Promise<SandboxPortAccess> {\n const info = await this.get(sandboxId);\n return {\n allowUnauthenticatedAccess: info.allowUnauthenticatedAccess ?? false,\n exposedPorts: dedupeAndSortPorts(info.exposedPorts ?? []),\n sandboxUrl: info.sandboxUrl,\n };\n }\n\n async exposePorts(\n sandboxId: string,\n ports: number[],\n options?: { allowUnauthenticatedAccess?: boolean },\n ): Promise<SandboxInfo> {\n const requestedPorts = normalizeUserPorts(ports);\n const current = await this.getPortAccess(sandboxId);\n const desiredPorts = dedupeAndSortPorts([\n ...current.exposedPorts,\n ...requestedPorts,\n ]);\n return this.update(sandboxId, {\n allowUnauthenticatedAccess:\n options?.allowUnauthenticatedAccess ??\n current.allowUnauthenticatedAccess,\n exposedPorts: desiredPorts,\n });\n }\n\n async unexposePorts(\n sandboxId: string,\n ports: number[],\n ): Promise<SandboxInfo> {\n const requestedPorts = normalizeUserPorts(ports);\n const current = await this.getPortAccess(sandboxId);\n const toRemove = new Set(requestedPorts);\n const desiredPorts = current.exposedPorts.filter((port) => !toRemove.has(port));\n return this.update(sandboxId, {\n allowUnauthenticatedAccess: desiredPorts.length\n ? current.allowUnauthenticatedAccess\n : false,\n exposedPorts: desiredPorts,\n });\n }\n\n async delete(sandboxId: string): Promise<void> {\n await this.http.requestJson(\n \"DELETE\",\n this.path(`sandboxes/${sandboxId}`),\n );\n }\n\n async suspend(sandboxId: string): Promise<void> {\n await this.http.requestResponse(\n \"POST\",\n this.path(`sandboxes/${sandboxId}/suspend`),\n );\n }\n\n async resume(sandboxId: string): Promise<void> {\n await this.http.requestResponse(\n \"POST\",\n this.path(`sandboxes/${sandboxId}/resume`),\n );\n }\n\n async claim(poolId: string): Promise<CreateSandboxResponse> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"POST\",\n this.path(`sandbox-pools/${poolId}/sandboxes`),\n );\n return fromSnakeKeys(raw, \"sandboxId\") as CreateSandboxResponse;\n }\n\n // --- Snapshots ---\n\n async snapshot(sandboxId: string): Promise<CreateSnapshotResponse> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"POST\",\n this.path(`sandboxes/${sandboxId}/snapshot`),\n );\n return fromSnakeKeys(raw, \"snapshotId\") as CreateSnapshotResponse;\n }\n\n async getSnapshot(snapshotId: string): Promise<SnapshotInfo> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n this.path(`snapshots/${snapshotId}`),\n );\n return fromSnakeKeys(raw, \"snapshotId\") as SnapshotInfo;\n }\n\n async listSnapshots(): Promise<SnapshotInfo[]> {\n const raw = await this.http.requestJson<{ snapshots: Record<string, unknown>[] }>(\n \"GET\",\n this.path(\"snapshots\"),\n );\n return (raw.snapshots ?? []).map(\n (s) => fromSnakeKeys(s, \"snapshotId\") as SnapshotInfo,\n );\n }\n\n async deleteSnapshot(snapshotId: string): Promise<void> {\n await this.http.requestJson(\n \"DELETE\",\n this.path(`snapshots/${snapshotId}`),\n );\n }\n\n async snapshotAndWait(\n sandboxId: string,\n options?: SnapshotAndWaitOptions,\n ): Promise<SnapshotInfo> {\n const timeout = options?.timeout ?? 300;\n const pollInterval = options?.pollInterval ?? 1;\n\n const result = await this.snapshot(sandboxId);\n const deadline = Date.now() + timeout * 1000;\n\n while (Date.now() < deadline) {\n const info = await this.getSnapshot(result.snapshotId);\n if (info.status === SnapshotStatus.COMPLETED) return info;\n if (info.status === SnapshotStatus.FAILED) {\n throw new SandboxError(\n `Snapshot ${result.snapshotId} failed: ${info.error}`,\n );\n }\n await sleep(pollInterval * 1000);\n }\n\n throw new SandboxError(\n `Snapshot ${result.snapshotId} did not complete within ${timeout}s`,\n );\n }\n\n // --- Pools ---\n\n async createPool(options: CreatePoolOptions): Promise<CreateSandboxPoolResponse> {\n const body: Record<string, unknown> = {\n image: options.image,\n resources: {\n cpus: options.cpus ?? 1.0,\n memory_mb: options.memoryMb ?? 1024,\n ephemeral_disk_mb: options.ephemeralDiskMb ?? 1024,\n },\n timeout_secs: options.timeoutSecs ?? 0,\n };\n\n if (options.secretNames != null) body.secret_names = options.secretNames;\n if (options.entrypoint != null) body.entrypoint = options.entrypoint;\n if (options.maxContainers != null) body.max_containers = options.maxContainers;\n if (options.warmContainers != null) body.warm_containers = options.warmContainers;\n\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"POST\",\n this.path(\"sandbox-pools\"),\n { body },\n );\n return fromSnakeKeys(raw, \"poolId\") as CreateSandboxPoolResponse;\n }\n\n async getPool(poolId: string): Promise<SandboxPoolInfo> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n this.path(`sandbox-pools/${poolId}`),\n );\n return fromSnakeKeys(raw, \"poolId\") as SandboxPoolInfo;\n }\n\n async listPools(): Promise<SandboxPoolInfo[]> {\n const raw = await this.http.requestJson<{ pools: Record<string, unknown>[] }>(\n \"GET\",\n this.path(\"sandbox-pools\"),\n );\n return (raw.pools ?? []).map(\n (p) => fromSnakeKeys(p, \"poolId\") as SandboxPoolInfo,\n );\n }\n\n async updatePool(\n poolId: string,\n options: UpdatePoolOptions,\n ): Promise<SandboxPoolInfo> {\n const body: Record<string, unknown> = {\n image: options.image,\n resources: {\n cpus: options.cpus ?? 1.0,\n memory_mb: options.memoryMb ?? 1024,\n ephemeral_disk_mb: options.ephemeralDiskMb ?? 1024,\n },\n timeout_secs: options.timeoutSecs ?? 0,\n };\n\n if (options.secretNames != null) body.secret_names = options.secretNames;\n if (options.entrypoint != null) body.entrypoint = options.entrypoint;\n if (options.maxContainers != null) body.max_containers = options.maxContainers;\n if (options.warmContainers != null) body.warm_containers = options.warmContainers;\n\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"PUT\",\n this.path(`sandbox-pools/${poolId}`),\n { body },\n );\n return fromSnakeKeys(raw, \"poolId\") as SandboxPoolInfo;\n }\n\n async deletePool(poolId: string): Promise<void> {\n await this.http.requestJson(\n \"DELETE\",\n this.path(`sandbox-pools/${poolId}`),\n );\n }\n\n // --- Connect ---\n\n connect(sandboxId: string, proxyUrl?: string): Sandbox {\n const resolvedProxy = proxyUrl ?? resolveProxyUrl(this.apiUrl);\n return new Sandbox({\n sandboxId,\n proxyUrl: resolvedProxy,\n apiKey: this.apiKey,\n organizationId: this.organizationId,\n projectId: this.projectId,\n });\n }\n\n async createAndConnect(\n options?: CreateAndConnectOptions,\n ): Promise<Sandbox> {\n const startupTimeout = options?.startupTimeout ?? 60;\n\n let result: CreateSandboxResponse;\n if (options?.poolId != null) {\n result = await this.claim(options.poolId);\n } else {\n result = await this.create(options);\n }\n\n const deadline = Date.now() + startupTimeout * 1000;\n\n while (Date.now() < deadline) {\n const info = await this.get(result.sandboxId);\n if (info.status === SandboxStatus.RUNNING) {\n const sandbox = this.connect(result.sandboxId, options?.proxyUrl);\n sandbox._setOwner(this);\n return sandbox;\n }\n if (info.status === SandboxStatus.TERMINATED) {\n throw new SandboxError(\n `Sandbox ${result.sandboxId} terminated during startup`,\n );\n }\n await sleep(500);\n }\n\n // Timed out — clean up\n try {\n await this.delete(result.sandboxId);\n } catch {\n // ignore cleanup failures\n }\n throw new SandboxError(\n `Sandbox ${result.sandboxId} did not start within ${startupTimeout}s`,\n );\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nconst RESERVED_SANDBOX_MANAGEMENT_PORT = 9501;\n\nfunction normalizeUserPorts(ports: number[]): number[] {\n return dedupeAndSortPorts(ports.map(validateUserPort));\n}\n\nfunction validateUserPort(port: number): number {\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new SandboxError(`invalid port '${port}'`);\n }\n if (port === RESERVED_SANDBOX_MANAGEMENT_PORT) {\n throw new SandboxError(\"port 9501 is reserved for sandbox management\");\n }\n return port;\n}\n\nfunction dedupeAndSortPorts(ports: number[]): number[] {\n return [...new Set(ports)].sort((a, b) => a - b);\n}\n","import { randomUUID } from \"node:crypto\";\n\nexport const ImageBuildOperationType = {\n ADD: \"ADD\",\n COPY: \"COPY\",\n ENV: \"ENV\",\n RUN: \"RUN\",\n WORKDIR: \"WORKDIR\",\n} as const;\n\nexport type ImageBuildOperationType =\n (typeof ImageBuildOperationType)[keyof typeof ImageBuildOperationType];\n\nexport interface ImageBuildOperation {\n type: ImageBuildOperationType;\n args: string[];\n options: Record<string, string>;\n}\n\nexport interface ImageOptions {\n name?: string;\n tag?: string;\n baseImage?: string | null;\n}\n\nfunction cloneOperation(op: ImageBuildOperation): ImageBuildOperation {\n return {\n type: op.type,\n args: [...op.args],\n options: { ...op.options },\n };\n}\n\nexport class Image {\n readonly _id: string;\n readonly _name: string;\n readonly _tag: string;\n readonly _baseImage: string | null;\n readonly _buildOperations: ImageBuildOperation[];\n\n constructor();\n constructor(name: string, tag?: string, baseImage?: string | null);\n constructor(options: ImageOptions);\n constructor(\n nameOrOptions: string | ImageOptions = {},\n tag = \"latest\",\n baseImage: string | null = null,\n ) {\n this._id = randomUUID();\n this._buildOperations = [];\n\n if (typeof nameOrOptions === \"string\") {\n this._name = nameOrOptions;\n this._tag = tag;\n this._baseImage = baseImage;\n return;\n }\n\n this._name = nameOrOptions.name ?? \"default\";\n this._tag = nameOrOptions.tag ?? \"latest\";\n this._baseImage = nameOrOptions.baseImage ?? null;\n }\n\n get name(): string {\n return this._name;\n }\n\n get tag(): string {\n return this._tag;\n }\n\n get baseImage(): string | null {\n return this._baseImage;\n }\n\n get buildOperations(): ImageBuildOperation[] {\n return this._buildOperations.map(cloneOperation);\n }\n\n add(\n src: string,\n dest: string,\n options: Record<string, string> | undefined = undefined,\n ): this {\n return this._addOperation({\n type: ImageBuildOperationType.ADD,\n args: [src, dest],\n options: options == null ? {} : { ...options },\n });\n }\n\n copy(\n src: string,\n dest: string,\n options: Record<string, string> | undefined = undefined,\n ): this {\n return this._addOperation({\n type: ImageBuildOperationType.COPY,\n args: [src, dest],\n options: options == null ? {} : { ...options },\n });\n }\n\n env(key: string, value: string): this {\n return this._addOperation({\n type: ImageBuildOperationType.ENV,\n args: [key, value],\n options: {},\n });\n }\n\n run(\n commands: string | string[],\n options: Record<string, string> | undefined = undefined,\n ): this {\n return this._addOperation({\n type: ImageBuildOperationType.RUN,\n args: Array.isArray(commands) ? [...commands] : [commands],\n options: options == null ? {} : { ...options },\n });\n }\n\n workdir(directory: string): this {\n return this._addOperation({\n type: ImageBuildOperationType.WORKDIR,\n args: [directory],\n options: {},\n });\n }\n\n private _addOperation(op: ImageBuildOperation): this {\n this._buildOperations.push(op);\n return this;\n }\n}\n\nfunction renderOptions(options: Record<string, string>): string {\n const entries = Object.entries(options);\n if (entries.length === 0) {\n return \"\";\n }\n return ` ${entries.map(([key, value]) => `--${key}=${value}`).join(\" \")}`;\n}\n\nfunction renderBuildOp(op: ImageBuildOperation): string {\n const options = renderOptions(op.options);\n if (op.type === ImageBuildOperationType.ENV) {\n return `ENV${options} ${op.args[0]}=${JSON.stringify(op.args[1])}`;\n }\n return `${op.type}${options} ${op.args.join(\" \")}`;\n}\n\nexport function dockerfileContent(image: Image): string {\n const lines = image.baseImage == null ? [] : [`FROM ${image.baseImage}`];\n lines.push(...image.buildOperations.map((op) => renderBuildOp(op)));\n return lines.join(\"\\n\");\n}\n"],"mappings":"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","names":["path","value","path","WebSocket","sleep","path","sleep","path","flagValue","sleep"]}
|
|
1
|
+
{"version":3,"sources":["../src/sandbox-image.ts","../src/models.ts","../src/defaults.ts","../src/errors.ts","../src/http.ts","../src/sse.ts","../src/url.ts","../src/sandbox.ts","../src/client.ts","../src/image.ts"],"sourcesContent":["import { readFile, readdir, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport {\n type CommandResult,\n type ProcessInfo,\n type SnapshotInfo,\n} from \"./models.js\";\nimport { type OutputResponse, ProcessStatus } from \"./models.js\";\nimport { SandboxClient } from \"./client.js\";\nimport { Image, dockerfileContent } from \"./image.js\";\n\nconst BUILD_SANDBOX_PIP_ENV = { PIP_BREAK_SYSTEM_PACKAGES: \"1\" } as const;\nconst IGNORED_DOCKERFILE_INSTRUCTIONS = new Set([\n \"CMD\",\n \"ENTRYPOINT\",\n \"EXPOSE\",\n \"HEALTHCHECK\",\n \"LABEL\",\n \"STOPSIGNAL\",\n \"VOLUME\",\n]);\nconst UNSUPPORTED_DOCKERFILE_INSTRUCTIONS = new Set([\n \"ARG\",\n \"ONBUILD\",\n \"SHELL\",\n \"USER\",\n]);\n\nexport interface DockerfileInstruction {\n keyword: string;\n value: string;\n lineNumber: number;\n}\n\nexport interface DockerfileBuildPlan {\n dockerfilePath: string;\n contextDir: string;\n registeredName: string;\n dockerfileText: string;\n baseImage?: string;\n instructions: DockerfileInstruction[];\n}\n\nexport interface CreateSandboxImageOptions {\n registeredName?: string;\n cpus?: number;\n memoryMb?: number;\n isPublic?: boolean;\n contextDir?: string;\n}\n\nexport type SandboxImageSource = string | Image;\n\ninterface BuildContext {\n apiUrl: string;\n apiKey?: string;\n personalAccessToken?: string;\n namespace: string;\n organizationId?: string;\n projectId?: string;\n debug: boolean;\n}\n\ninterface BuildSandbox {\n sandboxId: string;\n run(\n command: string,\n options?: {\n args?: string[];\n env?: Record<string, string>;\n workingDir?: string;\n timeout?: number;\n },\n ): Promise<CommandResult>;\n startProcess(\n command: string,\n options?: {\n args?: string[];\n env?: Record<string, string>;\n workingDir?: string;\n },\n ): Promise<ProcessInfo>;\n getStdout(pid: number): Promise<OutputResponse>;\n getStderr(pid: number): Promise<OutputResponse>;\n getProcess(pid: number): Promise<ProcessInfo>;\n writeFile(path: string, content: Uint8Array): Promise<void>;\n terminate(): Promise<void>;\n}\n\ninterface BuildClient {\n createAndConnect(options: {\n image?: string;\n cpus?: number;\n memoryMb?: number;\n }): Promise<BuildSandbox>;\n snapshotAndWait(\n sandboxId: string,\n options?: { timeout?: number; pollInterval?: number },\n ): Promise<SnapshotInfo>;\n close(): void;\n}\n\ninterface CreateSandboxImageDeps {\n emit?: (event: Record<string, unknown>) => void;\n createClient?: (context: BuildContext) => BuildClient;\n registerImage?: (\n context: BuildContext,\n name: string,\n dockerfile: string,\n snapshotId: string,\n snapshotUri: string,\n isPublic: boolean,\n ) => Promise<Record<string, unknown>>;\n sleep?: (ms: number) => Promise<void>;\n}\n\nexport function defaultRegisteredName(dockerfilePath: string): string {\n const parsed = path.parse(dockerfilePath);\n if (parsed.name.toLowerCase() === \"dockerfile\") {\n const parentName = path.basename(path.dirname(dockerfilePath)).trim();\n return parentName || \"sandbox-image\";\n }\n return parsed.name || \"sandbox-image\";\n}\n\nexport function logicalDockerfileLines(\n dockerfileText: string,\n): Array<{ lineNumber: number; line: string }> {\n const logicalLines: Array<{ lineNumber: number; line: string }> = [];\n let parts: string[] = [];\n let startLine: number | null = null;\n\n for (const [index, rawLine] of dockerfileText.split(/\\r?\\n/).entries()) {\n const lineNumber = index + 1;\n const stripped = rawLine.trim();\n if (parts.length === 0 && (!stripped || stripped.startsWith(\"#\"))) {\n continue;\n }\n\n if (startLine == null) {\n startLine = lineNumber;\n }\n\n let line = rawLine.replace(/\\s+$/, \"\");\n const continued = line.endsWith(\"\\\\\");\n if (continued) {\n line = line.slice(0, -1);\n }\n\n const normalized = line.trim();\n if (normalized && !normalized.startsWith(\"#\")) {\n parts.push(normalized);\n }\n\n if (continued) {\n continue;\n }\n\n if (parts.length > 0) {\n logicalLines.push({\n lineNumber: startLine ?? lineNumber,\n line: parts.join(\" \"),\n });\n }\n parts = [];\n startLine = null;\n }\n\n if (parts.length > 0) {\n logicalLines.push({\n lineNumber: startLine ?? 1,\n line: parts.join(\" \"),\n });\n }\n\n return logicalLines;\n}\n\nfunction splitInstruction(\n line: string,\n lineNumber: number,\n): { keyword: string; value: string } {\n const trimmed = line.trim();\n if (!trimmed) {\n throw new Error(`line ${lineNumber}: empty Dockerfile instruction`);\n }\n const match = trimmed.match(/^(\\S+)(?:\\s+(.*))?$/);\n if (!match) {\n throw new Error(`line ${lineNumber}: invalid Dockerfile instruction`);\n }\n return {\n keyword: match[1].toUpperCase(),\n value: (match[2] ?? \"\").trim(),\n };\n}\n\nfunction shellSplit(input: string): string[] {\n const tokens: string[] = [];\n let current = \"\";\n let quote: \"'\" | '\"' | null = null;\n let escape = false;\n\n for (let i = 0; i < input.length; i++) {\n const char = input[i];\n\n if (escape) {\n current += char;\n escape = false;\n continue;\n }\n\n if (quote == null) {\n if (/\\s/.test(char)) {\n if (current) {\n tokens.push(current);\n current = \"\";\n }\n continue;\n }\n if (char === \"'\" || char === '\"') {\n quote = char;\n continue;\n }\n if (char === \"\\\\\") {\n escape = true;\n continue;\n }\n current += char;\n continue;\n }\n\n if (quote === \"'\") {\n if (char === \"'\") {\n quote = null;\n } else {\n current += char;\n }\n continue;\n }\n\n if (char === '\"') {\n quote = null;\n continue;\n }\n if (char === \"\\\\\") {\n const next = input[++i];\n if (next == null) {\n throw new Error(`unterminated escape sequence in '${input}'`);\n }\n current += next;\n continue;\n }\n current += char;\n }\n\n if (escape) {\n throw new Error(`unterminated escape sequence in '${input}'`);\n }\n if (quote != null) {\n throw new Error(`unterminated quoted string in '${input}'`);\n }\n if (current) {\n tokens.push(current);\n }\n return tokens;\n}\n\nfunction shellQuote(value: string): string {\n if (!value) {\n return \"''\";\n }\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n\nfunction stripLeadingFlags(value: string): {\n flags: Record<string, string>;\n remaining: string;\n} {\n const flags: Record<string, string> = {};\n let remaining = value.trimStart();\n\n while (remaining.startsWith(\"--\")) {\n const firstSpace = remaining.indexOf(\" \");\n if (firstSpace === -1) {\n throw new Error(`invalid Dockerfile flag syntax: ${value}`);\n }\n\n const token = remaining.slice(0, firstSpace);\n const rest = remaining.slice(firstSpace + 1).trimStart();\n const flagBody = token.slice(2);\n\n if (flagBody.includes(\"=\")) {\n const [key, flagValue] = flagBody.split(/=(.*)/s, 2);\n flags[key] = flagValue;\n remaining = rest;\n continue;\n }\n\n const [flagValue, ...restTokens] = shellSplit(rest);\n if (flagValue == null) {\n throw new Error(`missing value for Dockerfile flag '${token}'`);\n }\n flags[flagBody] = flagValue;\n remaining = restTokens.join(\" \");\n }\n\n return { flags, remaining };\n}\n\nfunction parseFromValue(value: string, lineNumber: number): string {\n const { remaining } = stripLeadingFlags(value);\n const tokens = shellSplit(remaining);\n if (tokens.length === 0) {\n throw new Error(`line ${lineNumber}: FROM must include a base image`);\n }\n if (tokens.length > 1 && tokens[1].toLowerCase() !== \"as\") {\n throw new Error(`line ${lineNumber}: unsupported FROM syntax '${value}'`);\n }\n return tokens[0];\n}\n\nfunction parseCopyLikeValues(\n value: string,\n lineNumber: number,\n keyword: string,\n): {\n flags: Record<string, string>;\n sources: string[];\n destination: string;\n} {\n const { flags, remaining } = stripLeadingFlags(value);\n if (\"from\" in flags) {\n throw new Error(\n `line ${lineNumber}: ${keyword} --from is not supported for sandbox image creation`,\n );\n }\n\n const payload = remaining.trim();\n if (!payload) {\n throw new Error(\n `line ${lineNumber}: ${keyword} must include source and destination`,\n );\n }\n\n let parts: string[];\n if (payload.startsWith(\"[\")) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(payload);\n } catch (error) {\n throw new Error(\n `line ${lineNumber}: invalid JSON array syntax for ${keyword}: ${(error as Error).message}`,\n );\n }\n if (\n !Array.isArray(parsed) ||\n parsed.length < 2 ||\n parsed.some((item) => typeof item !== \"string\")\n ) {\n throw new Error(\n `line ${lineNumber}: ${keyword} JSON array form requires at least two string values`,\n );\n }\n parts = parsed as string[];\n } else {\n parts = shellSplit(payload);\n if (parts.length < 2) {\n throw new Error(\n `line ${lineNumber}: ${keyword} must include at least one source and one destination`,\n );\n }\n }\n\n return {\n flags,\n sources: parts.slice(0, -1),\n destination: parts[parts.length - 1],\n };\n}\n\nfunction parseEnvPairs(value: string, lineNumber: number): Array<[string, string]> {\n const tokens = shellSplit(value);\n if (tokens.length === 0) {\n throw new Error(`line ${lineNumber}: ENV must include a key and value`);\n }\n\n if (tokens.every((token) => token.includes(\"=\"))) {\n return tokens.map((token) => {\n const [key, envValue] = token.split(/=(.*)/s, 2);\n if (!key) {\n throw new Error(`line ${lineNumber}: invalid ENV token '${token}'`);\n }\n return [key, envValue] as [string, string];\n });\n }\n\n if (tokens.length < 2) {\n throw new Error(`line ${lineNumber}: ENV must include a key and value`);\n }\n\n return [[tokens[0], tokens.slice(1).join(\" \")]];\n}\n\nfunction resolveContainerPath(containerPath: string, workingDir: string): string {\n if (!containerPath) {\n return workingDir;\n }\n const normalized = containerPath.startsWith(\"/\")\n ? path.posix.normalize(containerPath)\n : path.posix.normalize(path.posix.join(workingDir, containerPath));\n return normalized.startsWith(\"/\") ? normalized : `/${normalized}`;\n}\n\nfunction buildPlanFromDockerfileText(\n dockerfileText: string,\n dockerfilePath: string,\n contextDir: string,\n registeredName?: string,\n): DockerfileBuildPlan {\n let baseImage: string | undefined;\n const instructions: DockerfileInstruction[] = [];\n\n for (const logicalLine of logicalDockerfileLines(dockerfileText)) {\n const { keyword, value } = splitInstruction(\n logicalLine.line,\n logicalLine.lineNumber,\n );\n if (keyword === \"FROM\") {\n if (baseImage != null) {\n throw new Error(\n `line ${logicalLine.lineNumber}: multi-stage Dockerfiles are not supported for sandbox image creation`,\n );\n }\n baseImage = parseFromValue(value, logicalLine.lineNumber);\n continue;\n }\n\n if (UNSUPPORTED_DOCKERFILE_INSTRUCTIONS.has(keyword)) {\n throw new Error(\n `line ${logicalLine.lineNumber}: Dockerfile instruction '${keyword}' is not supported for sandbox image creation`,\n );\n }\n\n instructions.push({\n keyword,\n value,\n lineNumber: logicalLine.lineNumber,\n });\n }\n\n if (!baseImage) {\n throw new Error(\"Dockerfile must contain a FROM instruction\");\n }\n\n return {\n dockerfilePath,\n contextDir,\n registeredName: registeredName ?? defaultRegisteredName(dockerfilePath),\n dockerfileText,\n baseImage,\n instructions,\n };\n}\n\nexport async function loadDockerfilePlan(\n dockerfilePath: string,\n registeredName?: string,\n): Promise<DockerfileBuildPlan> {\n const resolvedPath = path.resolve(dockerfilePath);\n const fileStats = await stat(resolvedPath).catch(() => null);\n if (!fileStats?.isFile()) {\n throw new Error(`Dockerfile not found: ${dockerfilePath}`);\n }\n\n const dockerfileText = await readFile(resolvedPath, \"utf8\");\n return buildPlanFromDockerfileText(\n dockerfileText,\n resolvedPath,\n path.dirname(resolvedPath),\n registeredName,\n );\n}\n\nexport function loadImagePlan(\n image: Image,\n options: Pick<CreateSandboxImageOptions, \"registeredName\" | \"contextDir\"> = {},\n): DockerfileBuildPlan {\n const contextDir = path.resolve(options.contextDir ?? process.cwd());\n const dockerfileText = dockerfileContent(image);\n const logicalLines = logicalDockerfileLines(dockerfileText);\n const instructions = image.baseImage == null ? logicalLines : logicalLines.slice(1);\n\n return {\n dockerfilePath: path.join(contextDir, \"Dockerfile\"),\n contextDir,\n registeredName: options.registeredName ?? image.name,\n dockerfileText,\n baseImage: image.baseImage ?? undefined,\n instructions: instructions.map(({ line, lineNumber }) => {\n const parsed = splitInstruction(line, lineNumber);\n return {\n keyword: parsed.keyword,\n value: parsed.value,\n lineNumber,\n };\n }),\n };\n}\n\nfunction defaultEmit(event: Record<string, unknown>) {\n process.stdout.write(`${JSON.stringify(event)}\\n`);\n}\n\nfunction debugEnabled(): boolean {\n return [\"1\", \"true\", \"yes\", \"on\"].includes(\n (process.env.TENSORLAKE_DEBUG ?? \"\").toLowerCase(),\n );\n}\n\nfunction buildContextFromEnv(): BuildContext {\n return {\n apiUrl: process.env.TENSORLAKE_API_URL ?? \"https://api.tensorlake.ai\",\n apiKey: process.env.TENSORLAKE_API_KEY,\n personalAccessToken: process.env.TENSORLAKE_PAT,\n namespace: process.env.INDEXIFY_NAMESPACE ?? \"default\",\n organizationId: process.env.TENSORLAKE_ORGANIZATION_ID,\n projectId: process.env.TENSORLAKE_PROJECT_ID,\n debug: debugEnabled(),\n };\n}\n\nfunction createDefaultClient(context: BuildContext): BuildClient {\n return new SandboxClient({\n apiUrl: context.apiUrl,\n apiKey: context.apiKey ?? context.personalAccessToken,\n organizationId: context.organizationId,\n projectId: context.projectId,\n namespace: context.namespace,\n });\n}\n\nasync function runChecked(\n sandbox: BuildSandbox,\n command: string,\n args: string[],\n env?: Record<string, string>,\n workingDir?: string,\n): Promise<CommandResult> {\n const result = await sandbox.run(command, {\n args,\n env,\n workingDir,\n });\n if (result.exitCode !== 0) {\n throw new Error(\n `Command '${command} ${args.join(\" \")}' failed with exit code ${result.exitCode}`,\n );\n }\n return result;\n}\n\nasync function runStreaming(\n sandbox: BuildSandbox,\n emit: (event: Record<string, unknown>) => void,\n sleep: (ms: number) => Promise<void>,\n command: string,\n args: string[] = [],\n env?: Record<string, string>,\n workingDir?: string,\n) {\n const proc = await sandbox.startProcess(command, {\n args,\n env,\n workingDir,\n });\n\n let stdoutSeen = 0;\n let stderrSeen = 0;\n let info: ProcessInfo;\n\n while (true) {\n const stdoutResp = await sandbox.getStdout(proc.pid);\n emitOutputLines(emit, \"stdout\", stdoutResp, stdoutSeen);\n stdoutSeen = stdoutResp.lines.length;\n\n const stderrResp = await sandbox.getStderr(proc.pid);\n emitOutputLines(emit, \"stderr\", stderrResp, stderrSeen);\n stderrSeen = stderrResp.lines.length;\n\n info = await sandbox.getProcess(proc.pid);\n if (info.status !== ProcessStatus.RUNNING) {\n const finalStdout = await sandbox.getStdout(proc.pid);\n emitOutputLines(emit, \"stdout\", finalStdout, stdoutSeen);\n stdoutSeen = finalStdout.lines.length;\n\n const finalStderr = await sandbox.getStderr(proc.pid);\n emitOutputLines(emit, \"stderr\", finalStderr, stderrSeen);\n break;\n }\n\n await sleep(300);\n }\n\n for (let i = 0; i < 10; i++) {\n if (info.exitCode != null || info.signal != null) {\n break;\n }\n await sleep(200);\n info = await sandbox.getProcess(proc.pid);\n }\n\n const exitCode =\n info.exitCode != null ? info.exitCode : info.signal != null ? -info.signal : 0;\n if (exitCode !== 0) {\n throw new Error(\n `Command '${command} ${args.join(\" \")}' failed with exit code ${exitCode}`,\n );\n }\n}\n\nfunction emitOutputLines(\n emit: (event: Record<string, unknown>) => void,\n stream: \"stdout\" | \"stderr\",\n response: OutputResponse,\n seen: number,\n) {\n for (const line of response.lines.slice(seen)) {\n emit({ type: \"build_log\", stream, message: line });\n }\n}\n\nfunction isPathWithinContext(contextDir: string, localPath: string): boolean {\n const relative = path.relative(contextDir, localPath);\n return relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative));\n}\n\nfunction resolveContextSourcePath(contextDir: string, source: string): string {\n const resolvedContextDir = path.resolve(contextDir);\n const resolvedSource = path.resolve(resolvedContextDir, source);\n if (!isPathWithinContext(resolvedContextDir, resolvedSource)) {\n throw new Error(`Local path escapes the build context: ${source}`);\n }\n return resolvedSource;\n}\n\nasync function copyLocalPathToSandbox(\n sandbox: BuildSandbox,\n localPath: string,\n remotePath: string,\n) {\n const fileStats = await stat(localPath).catch(() => null);\n if (!fileStats) {\n throw new Error(`Local path not found: ${localPath}`);\n }\n\n if (fileStats.isFile()) {\n await runChecked(sandbox, \"mkdir\", [\"-p\", path.posix.dirname(remotePath)]);\n await sandbox.writeFile(remotePath, await readFile(localPath));\n return;\n }\n\n if (!fileStats.isDirectory()) {\n throw new Error(`Local path not found: ${localPath}`);\n }\n\n const entries = await readdir(localPath, { withFileTypes: true });\n for (const entry of entries) {\n const sourcePath = path.join(localPath, entry.name);\n const destinationPath = path.posix.join(remotePath, entry.name);\n if (entry.isDirectory()) {\n await runChecked(sandbox, \"mkdir\", [\"-p\", destinationPath]);\n await copyLocalPathToSandbox(sandbox, sourcePath, destinationPath);\n } else if (entry.isFile()) {\n await runChecked(\n sandbox,\n \"mkdir\",\n [\"-p\", path.posix.dirname(destinationPath)],\n );\n await sandbox.writeFile(destinationPath, await readFile(sourcePath));\n }\n }\n}\n\nasync function persistEnvVar(\n sandbox: BuildSandbox,\n processEnv: Record<string, string>,\n key: string,\n value: string,\n) {\n const exportLine = `export ${key}=${shellQuote(value)}`;\n await runChecked(\n sandbox,\n \"sh\",\n [\"-c\", `printf '%s\\\\n' ${shellQuote(exportLine)} >> /etc/environment`],\n processEnv,\n );\n}\n\nasync function copyFromContext(\n sandbox: BuildSandbox,\n emit: (event: Record<string, unknown>) => void,\n contextDir: string,\n sources: string[],\n destination: string,\n workingDir: string,\n keyword: string,\n) {\n const destinationPath = resolveContainerPath(destination, workingDir);\n if (sources.length > 1 && !destinationPath.endsWith(\"/\")) {\n throw new Error(\n `${keyword} with multiple sources requires a directory destination ending in '/'`,\n );\n }\n\n for (const source of sources) {\n const localSource = resolveContextSourcePath(contextDir, source);\n const localStats = await stat(localSource).catch(() => null);\n if (!localStats) {\n throw new Error(`Local path not found: ${localSource}`);\n }\n\n let remoteDestination = destinationPath;\n if (sources.length > 1) {\n remoteDestination = path.posix.join(\n destinationPath.replace(/\\/$/, \"\"),\n path.posix.basename(source.replace(/\\/$/, \"\")),\n );\n } else if (localStats.isFile() && destinationPath.endsWith(\"/\")) {\n remoteDestination = path.posix.join(\n destinationPath.replace(/\\/$/, \"\"),\n path.basename(source),\n );\n }\n\n emit({\n type: \"status\",\n message: `${keyword} ${source} -> ${remoteDestination}`,\n });\n await copyLocalPathToSandbox(sandbox, localSource, remoteDestination);\n }\n}\n\nasync function addUrlToSandbox(\n sandbox: BuildSandbox,\n emit: (event: Record<string, unknown>) => void,\n url: string,\n destination: string,\n workingDir: string,\n processEnv: Record<string, string>,\n sleep: (ms: number) => Promise<void>,\n) {\n let destinationPath = resolveContainerPath(destination, workingDir);\n const parsedUrl = new URL(url);\n const fileName = path.posix.basename(parsedUrl.pathname.replace(/\\/$/, \"\")) || \"downloaded\";\n if (destinationPath.endsWith(\"/\")) {\n destinationPath = path.posix.join(destinationPath.replace(/\\/$/, \"\"), fileName);\n }\n\n const parentDir = path.posix.dirname(destinationPath) || \"/\";\n emit({\n type: \"status\",\n message: `ADD ${url} -> ${destinationPath}`,\n });\n await runChecked(sandbox, \"mkdir\", [\"-p\", parentDir], processEnv);\n await runStreaming(\n sandbox,\n emit,\n sleep,\n \"sh\",\n [\n \"-c\",\n `curl -fsSL --location ${shellQuote(url)} -o ${shellQuote(destinationPath)}`,\n ],\n processEnv,\n workingDir,\n );\n}\n\nasync function executeDockerfilePlan(\n sandbox: BuildSandbox,\n plan: DockerfileBuildPlan,\n emit: (event: Record<string, unknown>) => void,\n sleep: (ms: number) => Promise<void>,\n) {\n const processEnv: Record<string, string> = { ...BUILD_SANDBOX_PIP_ENV };\n let workingDir = \"/\";\n\n for (const instruction of plan.instructions) {\n const { keyword, value, lineNumber } = instruction;\n\n if (keyword === \"RUN\") {\n emit({ type: \"status\", message: `RUN ${value}` });\n await runStreaming(\n sandbox,\n emit,\n sleep,\n \"sh\",\n [\"-c\", value],\n processEnv,\n workingDir,\n );\n continue;\n }\n\n if (keyword === \"WORKDIR\") {\n const tokens = shellSplit(value);\n if (tokens.length !== 1) {\n throw new Error(`line ${lineNumber}: WORKDIR must include exactly one path`);\n }\n workingDir = resolveContainerPath(tokens[0], workingDir);\n emit({ type: \"status\", message: `WORKDIR ${workingDir}` });\n await runChecked(sandbox, \"mkdir\", [\"-p\", workingDir], processEnv);\n continue;\n }\n\n if (keyword === \"ENV\") {\n for (const [key, envValue] of parseEnvPairs(value, lineNumber)) {\n emit({ type: \"status\", message: `ENV ${key}=${envValue}` });\n processEnv[key] = envValue;\n await persistEnvVar(sandbox, processEnv, key, envValue);\n }\n continue;\n }\n\n if (keyword === \"COPY\") {\n const { sources, destination } = parseCopyLikeValues(\n value,\n lineNumber,\n keyword,\n );\n await copyFromContext(\n sandbox,\n emit,\n plan.contextDir,\n sources,\n destination,\n workingDir,\n keyword,\n );\n continue;\n }\n\n if (keyword === \"ADD\") {\n const { sources, destination } = parseCopyLikeValues(\n value,\n lineNumber,\n keyword,\n );\n if (\n sources.length === 1 &&\n /^https?:\\/\\//.test(sources[0])\n ) {\n await addUrlToSandbox(\n sandbox,\n emit,\n sources[0],\n destination,\n workingDir,\n processEnv,\n sleep,\n );\n } else {\n await copyFromContext(\n sandbox,\n emit,\n plan.contextDir,\n sources,\n destination,\n workingDir,\n keyword,\n );\n }\n continue;\n }\n\n if (IGNORED_DOCKERFILE_INSTRUCTIONS.has(keyword)) {\n emit({\n type: \"warning\",\n message: `Skipping Dockerfile instruction '${keyword}' during snapshot materialization. It is still preserved in the registered Dockerfile.`,\n });\n continue;\n }\n\n throw new Error(\n `line ${lineNumber}: Dockerfile instruction '${keyword}' is not supported for sandbox image creation`,\n );\n }\n}\n\nasync function registerImage(\n context: BuildContext,\n name: string,\n dockerfile: string,\n snapshotId: string,\n snapshotUri: string,\n isPublic: boolean,\n): Promise<Record<string, unknown>> {\n if (!context.organizationId || !context.projectId) {\n throw new Error(\n \"Organization ID and Project ID are required. Run 'tl login' and 'tl init'.\",\n );\n }\n\n const bearerToken = context.apiKey ?? context.personalAccessToken;\n if (!bearerToken) {\n throw new Error(\"Missing TENSORLAKE_API_KEY or TENSORLAKE_PAT.\");\n }\n\n const baseUrl = context.apiUrl.replace(/\\/+$/, \"\");\n const url =\n `${baseUrl}/platform/v1/organizations/` +\n `${encodeURIComponent(context.organizationId)}/projects/` +\n `${encodeURIComponent(context.projectId)}/sandbox-templates`;\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${bearerToken}`,\n \"Content-Type\": \"application/json\",\n };\n if (context.personalAccessToken && !context.apiKey) {\n headers[\"X-Forwarded-Organization-Id\"] = context.organizationId;\n headers[\"X-Forwarded-Project-Id\"] = context.projectId;\n }\n\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n name,\n dockerfile,\n snapshotId,\n snapshotUri,\n isPublic,\n }),\n });\n\n if (!response.ok) {\n throw new Error(\n `${response.status} ${response.statusText}: ${await response.text()}`,\n );\n }\n\n const text = await response.text();\n return text ? (JSON.parse(text) as Record<string, unknown>) : {};\n}\n\nexport async function createSandboxImage(\n source: SandboxImageSource,\n options: CreateSandboxImageOptions = {},\n deps: CreateSandboxImageDeps = {},\n) {\n const emit = deps.emit ?? defaultEmit;\n const sleep = deps.sleep ?? ((ms: number) => new Promise((r) => setTimeout(r, ms)));\n const context = buildContextFromEnv();\n const clientFactory = deps.createClient ?? createDefaultClient;\n const register =\n deps.registerImage ??\n ((...args) => registerImage(...args));\n\n const sourceLabel =\n typeof source === \"string\" ? source : `Image(${source.name})`;\n emit({ type: \"status\", message: `Loading ${sourceLabel}...` });\n const plan =\n typeof source === \"string\"\n ? await loadDockerfilePlan(source, options.registeredName)\n : loadImagePlan(source, options);\n emit({\n type: \"status\",\n message:\n plan.baseImage == null\n ? \"Starting build sandbox with the default server image...\"\n : `Starting build sandbox from ${plan.baseImage}...`,\n });\n\n const client = clientFactory(context);\n let sandbox: BuildSandbox | undefined;\n\n try {\n sandbox = await client.createAndConnect({\n ...(plan.baseImage == null ? {} : { image: plan.baseImage }),\n cpus: options.cpus ?? 2.0,\n memoryMb: options.memoryMb ?? 4096,\n });\n\n emit({\n type: \"status\",\n message: `Materializing image in sandbox ${sandbox.sandboxId}...`,\n });\n await executeDockerfilePlan(sandbox, plan, emit, sleep);\n\n emit({ type: \"status\", message: \"Creating snapshot...\" });\n const snapshot = await client.snapshotAndWait(sandbox.sandboxId);\n emit({\n type: \"snapshot_created\",\n snapshot_id: snapshot.snapshotId,\n snapshot_uri: snapshot.snapshotUri ?? null,\n });\n\n if (!snapshot.snapshotUri) {\n throw new Error(\n `Snapshot ${snapshot.snapshotId} is missing snapshotUri and cannot be registered as a sandbox image.`,\n );\n }\n\n emit({\n type: \"status\",\n message: `Registering image '${plan.registeredName}'...`,\n });\n const result = await register(\n context,\n plan.registeredName,\n plan.dockerfileText,\n snapshot.snapshotId,\n snapshot.snapshotUri,\n options.isPublic ?? false,\n );\n\n emit({\n type: \"image_registered\",\n name: plan.registeredName,\n image_id:\n (typeof result.id === \"string\" && result.id) ||\n (typeof result.templateId === \"string\" && result.templateId) ||\n \"\",\n });\n emit({ type: \"done\" });\n return result;\n } finally {\n if (sandbox) {\n try {\n await sandbox.terminate();\n } catch {}\n }\n client.close();\n }\n}\n\nexport async function runCreateSandboxImageCli(argv = process.argv.slice(2)) {\n const parsed = parseArgs({\n args: argv,\n allowPositionals: true,\n options: {\n name: { type: \"string\", short: \"n\" },\n cpus: { type: \"string\" },\n memory: { type: \"string\" },\n public: { type: \"boolean\", default: false },\n },\n });\n\n const dockerfilePath = parsed.positionals[0];\n if (!dockerfilePath) {\n throw new Error(\"Usage: tensorlake-create-sandbox-image <dockerfile_path> [--name NAME] [--cpus N] [--memory MB] [--public]\");\n }\n\n const cpus =\n parsed.values.cpus != null ? Number(parsed.values.cpus) : undefined;\n const memoryMb =\n parsed.values.memory != null ? Number(parsed.values.memory) : undefined;\n if (cpus != null && !Number.isFinite(cpus)) {\n throw new Error(`Invalid --cpus value: ${parsed.values.cpus}`);\n }\n if (memoryMb != null && !Number.isInteger(memoryMb)) {\n throw new Error(`Invalid --memory value: ${parsed.values.memory}`);\n }\n\n await createSandboxImage(dockerfilePath, {\n registeredName: parsed.values.name,\n cpus,\n memoryMb,\n isPublic: parsed.values.public,\n });\n}\n","// --- Enums ---\n\nexport enum SandboxStatus {\n PENDING = \"pending\",\n RUNNING = \"running\",\n SNAPSHOTTING = \"snapshotting\",\n SUSPENDING = \"suspending\",\n SUSPENDED = \"suspended\",\n TERMINATED = \"terminated\",\n}\n\nexport enum SnapshotStatus {\n IN_PROGRESS = \"in_progress\",\n COMPLETED = \"completed\",\n FAILED = \"failed\",\n}\n\nexport enum ProcessStatus {\n RUNNING = \"running\",\n EXITED = \"exited\",\n SIGNALED = \"signaled\",\n}\n\nexport enum StdinMode {\n CLOSED = \"closed\",\n PIPE = \"pipe\",\n}\n\nexport enum OutputMode {\n CAPTURE = \"capture\",\n DISCARD = \"discard\",\n}\n\nexport enum ContainerState {\n IDLE = \"Idle\",\n RUNNING = \"Running\",\n}\n\n// --- Resource / Network ---\n\nexport interface ContainerResourcesInfo {\n cpus: number;\n memoryMb: number;\n ephemeralDiskMb: number;\n}\n\nexport interface NetworkConfig {\n allowInternetAccess: boolean;\n allowOut: string[];\n denyOut: string[];\n}\n\n// --- Sandbox lifecycle ---\n\nexport interface CreateSandboxOptions {\n /** Optional sandbox image name, such as `ubuntu-minimal` or a registered Sandbox Image. When omitted, Tensorlake uses the default managed environment. */\n image?: string;\n cpus?: number;\n memoryMb?: number;\n ephemeralDiskMb?: number;\n secretNames?: string[];\n timeoutSecs?: number;\n entrypoint?: string[];\n allowInternetAccess?: boolean;\n allowOut?: string[];\n denyOut?: string[];\n snapshotId?: string;\n /** Optional name for the sandbox. Named sandboxes support suspend/resume. When absent the sandbox is ephemeral. */\n name?: string;\n}\n\nexport interface UpdateSandboxOptions {\n /** New name for the sandbox. Naming an ephemeral sandbox enables suspend/resume. */\n name?: string;\n /** Whether exposed user ports should be reachable without TensorLake auth. */\n allowUnauthenticatedAccess?: boolean;\n /** User ports that should be routable through the sandbox proxy. Port 9501 is reserved. */\n exposedPorts?: number[];\n}\n\nexport interface CreateSandboxResponse {\n sandboxId: string;\n status: SandboxStatus;\n}\n\nexport interface SandboxInfo {\n sandboxId: string;\n namespace: string;\n status: SandboxStatus;\n /** Resolved sandbox image name. */\n image?: string;\n resources: ContainerResourcesInfo;\n secretNames: string[];\n timeoutSecs?: number;\n entrypoint?: string[];\n network?: NetworkConfig;\n poolId?: string;\n outcome?: string;\n createdAt?: Date;\n terminatedAt?: Date;\n name?: string;\n allowUnauthenticatedAccess?: boolean;\n exposedPorts?: number[];\n sandboxUrl?: string;\n}\n\nexport interface SandboxPortAccess {\n allowUnauthenticatedAccess: boolean;\n exposedPorts: number[];\n sandboxUrl?: string;\n}\n\n// --- Snapshots ---\n\nexport interface CreateSnapshotResponse {\n snapshotId: string;\n status: SnapshotStatus;\n}\n\nexport interface SnapshotInfo {\n snapshotId: string;\n namespace: string;\n sandboxId: string;\n baseImage: string;\n status: SnapshotStatus;\n error?: string;\n snapshotUri?: string;\n sizeBytes?: number;\n createdAt?: Date;\n}\n\nexport interface SnapshotAndWaitOptions {\n timeout?: number;\n pollInterval?: number;\n}\n\n// --- Pools ---\n\nexport interface CreatePoolOptions {\n /** Sandbox image name, such as `ubuntu-minimal` or a registered Sandbox Image. */\n image: string;\n cpus?: number;\n memoryMb?: number;\n ephemeralDiskMb?: number;\n secretNames?: string[];\n timeoutSecs?: number;\n entrypoint?: string[];\n maxContainers?: number;\n warmContainers?: number;\n}\n\nexport interface UpdatePoolOptions {\n /** Sandbox image name, such as `ubuntu-minimal` or a registered Sandbox Image. */\n image: string;\n cpus?: number;\n memoryMb?: number;\n ephemeralDiskMb?: number;\n secretNames?: string[];\n timeoutSecs?: number;\n entrypoint?: string[];\n maxContainers?: number;\n warmContainers?: number;\n}\n\nexport interface CreateSandboxPoolResponse {\n poolId: string;\n namespace: string;\n}\n\nexport interface PoolContainerInfo {\n id: string;\n state: string;\n sandboxId?: string;\n executorId: string;\n}\n\nexport interface SandboxPoolInfo {\n poolId: string;\n namespace: string;\n /** Sandbox image name backing the pool. */\n image: string;\n resources: ContainerResourcesInfo;\n secretNames: string[];\n timeoutSecs: number;\n entrypoint?: string[];\n maxContainers?: number;\n warmContainers?: number;\n containers?: PoolContainerInfo[];\n createdAt?: Date;\n updatedAt?: Date;\n}\n\n// --- Process management ---\n\nexport interface StartProcessOptions {\n args?: string[];\n env?: Record<string, string>;\n workingDir?: string;\n stdinMode?: StdinMode;\n stdoutMode?: OutputMode;\n stderrMode?: OutputMode;\n}\n\nexport interface ProcessInfo {\n pid: number;\n status: ProcessStatus;\n exitCode?: number;\n signal?: number;\n stdinWritable: boolean;\n command: string;\n args: string[];\n startedAt: Date;\n endedAt?: Date;\n}\n\nexport interface SendSignalResponse {\n success: boolean;\n}\n\nexport interface OutputResponse {\n pid: number;\n lines: string[];\n lineCount: number;\n}\n\nexport interface OutputEvent {\n line: string;\n timestamp: Date;\n stream?: string;\n}\n\n// --- Run ---\n\nexport interface RunOptions {\n args?: string[];\n env?: Record<string, string>;\n workingDir?: string;\n timeout?: number;\n}\n\nexport interface CommandResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n}\n\n// --- File operations ---\n\nexport interface DirectoryEntry {\n name: string;\n isDir: boolean;\n size?: number;\n modifiedAt?: Date;\n}\n\nexport interface ListDirectoryResponse {\n path: string;\n entries: DirectoryEntry[];\n}\n\n// --- PTY ---\n\nexport interface CreatePtySessionOptions {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n workingDir?: string;\n rows?: number;\n cols?: number;\n}\n\nexport interface PtySessionInfo {\n sessionId: string;\n token: string;\n}\n\n// --- Health ---\n\nexport interface HealthResponse {\n healthy: boolean;\n}\n\nexport interface DaemonInfo {\n version: string;\n uptimeSecs: number;\n runningProcesses: number;\n totalProcesses: number;\n}\n\n// --- Client options ---\n\nexport interface SandboxClientOptions {\n apiUrl?: string;\n apiKey?: string;\n organizationId?: string;\n projectId?: string;\n namespace?: string;\n maxRetries?: number;\n retryBackoffMs?: number;\n}\n\nexport interface SandboxOptions {\n sandboxId: string;\n proxyUrl?: string;\n apiKey?: string;\n organizationId?: string;\n projectId?: string;\n}\n\nexport interface CreateAndConnectOptions extends CreateSandboxOptions {\n poolId?: string;\n proxyUrl?: string;\n startupTimeout?: number;\n}\n\n// --- JSON key conversion helpers ---\n\nconst CAMEL_TO_SNAKE_RE = /[A-Z]/g;\n\n/** Convert a camelCase string to snake_case. */\nexport function camelToSnake(str: string): string {\n return str.replace(CAMEL_TO_SNAKE_RE, (ch) => \"_\" + ch.toLowerCase());\n}\n\n/** Convert a snake_case string to camelCase. */\nexport function snakeToCamel(str: string): string {\n return str.replace(/_([a-z])/g, (_, ch) => ch.toUpperCase());\n}\n\n/** Recursively convert all object keys from camelCase to snake_case. */\nexport function toSnakeKeys(obj: unknown): unknown {\n if (Array.isArray(obj)) return obj.map(toSnakeKeys);\n if (obj !== null && typeof obj === \"object\" && !(obj instanceof Date)) {\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj as Record<string, unknown>)) {\n result[camelToSnake(k)] = toSnakeKeys(v);\n }\n return result;\n }\n return obj;\n}\n\n/**\n * Parse a numeric timestamp into a Date.\n *\n * Handles seconds, milliseconds, and microseconds by checking magnitude.\n */\nexport function parseTimestamp(v: unknown): Date | undefined {\n if (v == null) return undefined;\n if (v instanceof Date) return v;\n if (typeof v === \"string\") {\n const parsed = Date.parse(v);\n return Number.isNaN(parsed) ? undefined : new Date(parsed);\n }\n const ts = Number(v);\n if (isNaN(ts)) return undefined;\n if (ts > 1e15) return new Date(ts / 1000); // microseconds → ms\n if (ts > 1e12) return new Date(ts); // already ms\n return new Date(ts * 1000); // seconds → ms\n}\n\n/**\n * Recursively convert all object keys from snake_case to camelCase,\n * with special handling for `id` → contextual name and timestamp parsing.\n */\nexport function fromSnakeKeys(\n obj: unknown,\n idField?: string,\n): unknown {\n if (Array.isArray(obj)) return obj.map((item) => fromSnakeKeys(item, idField));\n if (obj !== null && typeof obj === \"object\" && !(obj instanceof Date)) {\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj as Record<string, unknown>)) {\n let key: string;\n if (k === \"id\" && idField) {\n key = idField;\n } else {\n key = snakeToCamel(k);\n }\n\n // Parse timestamp fields\n if (\n key.endsWith(\"At\") ||\n key === \"timestamp\" ||\n key === \"startedAt\" ||\n key === \"endedAt\"\n ) {\n result[key] = parseTimestamp(v);\n } else if (typeof v === \"object\" && v !== null && !Array.isArray(v)) {\n result[key] = fromSnakeKeys(v);\n } else if (Array.isArray(v)) {\n result[key] = v.map((item) => fromSnakeKeys(item));\n } else {\n // Normalize null → undefined so optional fields match TypeScript's ? convention.\n result[key] = v === null ? undefined : v;\n }\n }\n return result;\n }\n return obj;\n}\n","export const API_URL =\n process.env.TENSORLAKE_API_URL ?? \"https://api.tensorlake.ai\";\nexport const API_KEY = process.env.TENSORLAKE_API_KEY ?? undefined;\nexport const NAMESPACE = process.env.INDEXIFY_NAMESPACE ?? \"default\";\nexport const SANDBOX_PROXY_URL =\n process.env.TENSORLAKE_SANDBOX_PROXY_URL ?? \"https://sandbox.tensorlake.ai\";\n\nexport const DEFAULT_HTTP_TIMEOUT_MS = 30_000;\nexport const MAX_RETRIES = 3;\nexport const RETRY_BACKOFF_MS = 500;\nexport const RETRYABLE_STATUS_CODES = new Set([429, 502, 503, 504]);\n","/** Base exception for all sandbox-related errors. */\nexport class SandboxException extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"SandboxException\";\n }\n}\n\n/** General sandbox operation error. */\nexport class SandboxError extends SandboxException {\n constructor(message: string) {\n super(message);\n this.name = \"SandboxError\";\n }\n}\n\n/** Raised when the client cannot connect to the API server. */\nexport class SandboxConnectionError extends SandboxError {\n constructor(message: string) {\n super(`Connection error: ${message}`);\n this.name = \"SandboxConnectionError\";\n }\n}\n\n/** Raised when a sandbox is not found. */\nexport class SandboxNotFoundError extends SandboxError {\n readonly sandboxId: string;\n\n constructor(sandboxId: string) {\n super(`Sandbox not found: ${sandboxId}`);\n this.name = \"SandboxNotFoundError\";\n this.sandboxId = sandboxId;\n }\n}\n\n/** Raised when a sandbox pool is not found. */\nexport class PoolNotFoundError extends SandboxError {\n readonly poolId: string;\n\n constructor(poolId: string) {\n super(`Sandbox pool not found: ${poolId}`);\n this.name = \"PoolNotFoundError\";\n this.poolId = poolId;\n }\n}\n\n/** Raised when attempting to delete a pool that is in use. */\nexport class PoolInUseError extends SandboxError {\n readonly poolId: string;\n\n constructor(poolId: string, message?: string) {\n const base = `Cannot delete pool ${poolId}: pool is in use`;\n super(message ? `${base} - ${message}` : base);\n this.name = \"PoolInUseError\";\n this.poolId = poolId;\n }\n}\n\n/** Raised when the remote API returns an error. */\nexport class RemoteAPIError extends SandboxError {\n readonly statusCode: number;\n readonly responseMessage: string;\n\n constructor(statusCode: number, message: string) {\n super(`API error (status ${statusCode}): ${message}`);\n this.name = \"RemoteAPIError\";\n this.statusCode = statusCode;\n this.responseMessage = message;\n }\n}\n\n/** Raised when request output is fetched before the request has completed. */\nexport class RequestNotFinishedError extends Error {\n constructor() {\n super(\"Request has not finished yet\");\n this.name = \"RequestNotFinishedError\";\n }\n}\n\n/** Raised when a request completed unsuccessfully. */\nexport class RequestFailedError extends Error {\n readonly failure: string;\n\n constructor(failure: string) {\n super(`Request failed: ${failure}`);\n this.name = \"RequestFailedError\";\n this.failure = failure;\n }\n}\n\n/** Raised when a request surfaced an application-level error. */\nexport class RequestExecutionError extends Error {\n readonly functionName?: string;\n\n constructor(message: string, functionName?: string) {\n super(\n functionName ? `Request error in ${functionName}: ${message}` : message,\n );\n this.name = \"RequestExecutionError\";\n this.functionName = functionName;\n }\n}\n","import * as defaults from \"./defaults.js\";\nimport {\n PoolInUseError,\n PoolNotFoundError,\n RemoteAPIError,\n SandboxConnectionError,\n SandboxNotFoundError,\n} from \"./errors.js\";\n\nexport interface HttpClientOptions {\n baseUrl: string;\n apiKey?: string;\n organizationId?: string;\n projectId?: string;\n hostHeader?: string;\n maxRetries?: number;\n retryBackoffMs?: number;\n timeoutMs?: number;\n}\n\ntype RequestBody = BodyInit | Uint8Array | ArrayBuffer;\n\nexport interface HttpRequestOptions {\n body?: RequestBody | null;\n headers?: Record<string, string>;\n json?: unknown;\n signal?: AbortSignal;\n allowHttpErrors?: boolean;\n}\n\n/**\n * Internal HTTP client with retry logic, auth headers, and error mapping.\n *\n * Uses native `fetch`. Retries on transient status codes (429, 502, 503, 504)\n * with exponential backoff.\n */\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly headers: Record<string, string>;\n private readonly maxRetries: number;\n private readonly retryBackoffMs: number;\n private readonly timeoutMs: number;\n private abortController: AbortController | null = null;\n\n constructor(options: HttpClientOptions) {\n const url = options.baseUrl;\n this.baseUrl = url.endsWith(\"/\") ? url.slice(0, -1) : url;\n this.maxRetries = options.maxRetries ?? defaults.MAX_RETRIES;\n this.retryBackoffMs = options.retryBackoffMs ?? defaults.RETRY_BACKOFF_MS;\n this.timeoutMs = options.timeoutMs ?? defaults.DEFAULT_HTTP_TIMEOUT_MS;\n\n this.headers = {};\n if (options.apiKey) {\n this.headers[\"Authorization\"] = `Bearer ${options.apiKey}`;\n }\n if (options.organizationId) {\n this.headers[\"X-Forwarded-Organization-Id\"] = options.organizationId;\n }\n if (options.projectId) {\n this.headers[\"X-Forwarded-Project-Id\"] = options.projectId;\n }\n if (options.hostHeader) {\n this.headers[\"Host\"] = options.hostHeader;\n }\n }\n\n close(): void {\n this.abortController?.abort();\n this.abortController = null;\n }\n\n /** Make a JSON request, returning the parsed response body. */\n async requestJson<T>(\n method: string,\n path: string,\n options?: {\n body?: unknown;\n headers?: Record<string, string>;\n signal?: AbortSignal;\n },\n ): Promise<T> {\n const response = await this.requestResponse(method, path, {\n json: options?.body,\n headers: options?.headers,\n signal: options?.signal,\n });\n const text = await response.text();\n if (!text) return undefined as T;\n return JSON.parse(text) as T;\n }\n\n /** Make a request returning raw bytes. */\n async requestBytes(\n method: string,\n path: string,\n options?: {\n body?: RequestBody | null;\n contentType?: string;\n headers?: Record<string, string>;\n signal?: AbortSignal;\n },\n ): Promise<Uint8Array> {\n const headers = { ...(options?.headers ?? {}) };\n if (options?.contentType) {\n headers[\"Content-Type\"] = options.contentType;\n }\n\n const response = await this.requestResponse(\n method,\n path,\n {\n body: options?.body,\n headers,\n signal: options?.signal,\n },\n );\n const buffer = await response.arrayBuffer();\n return new Uint8Array(buffer);\n }\n\n /** Make a request and return the raw Response (for SSE streaming). */\n async requestStream(\n method: string,\n path: string,\n options?: { signal?: AbortSignal },\n ): Promise<ReadableStream<Uint8Array>> {\n const response = await this.requestResponse(\n method,\n path,\n {\n headers: { Accept: \"text/event-stream\" },\n signal: options?.signal,\n },\n );\n if (!response.body) {\n throw new RemoteAPIError(response.status, \"No response body for SSE stream\");\n }\n return response.body;\n }\n\n /** Make a request and return the raw Response. */\n async requestResponse(\n method: string,\n path: string,\n options?: HttpRequestOptions,\n ): Promise<Response> {\n const headers = {\n ...this.headers,\n ...(options?.headers ?? {}),\n };\n const hasJsonBody = options?.json !== undefined;\n if (hasJsonBody && !hasHeader(headers, \"Content-Type\")) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const body = hasJsonBody\n ? JSON.stringify(options?.json)\n : normalizeRequestBody(options?.body);\n\n return this.doFetch(\n method,\n path,\n body,\n headers,\n options?.signal,\n options?.allowHttpErrors ?? false,\n );\n }\n\n private async doFetch(\n method: string,\n path: string,\n body: BodyInit | undefined,\n headers: Record<string, string>,\n signal?: AbortSignal,\n allowHttpErrors = false,\n ): Promise<Response> {\n const url = `${this.baseUrl}${path}`;\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n if (attempt > 0) {\n const delay = this.retryBackoffMs * Math.pow(2, attempt - 1);\n await sleep(delay);\n }\n\n this.abortController = new AbortController();\n const timeoutId = setTimeout(\n () => this.abortController?.abort(),\n this.timeoutMs,\n );\n\n // Combine external signal with internal timeout\n const combinedSignal = signal\n ? anySignal([signal, this.abortController.signal])\n : this.abortController.signal;\n\n try {\n const response = await fetch(url, {\n method,\n headers,\n body,\n signal: combinedSignal,\n });\n\n clearTimeout(timeoutId);\n\n if (response.ok) return response;\n\n // Check if retryable\n if (\n defaults.RETRYABLE_STATUS_CODES.has(response.status) &&\n attempt < this.maxRetries\n ) {\n lastError = new RemoteAPIError(\n response.status,\n await response.text().catch(() => \"\"),\n );\n continue;\n }\n\n if (allowHttpErrors) {\n return response;\n }\n\n // Non-retryable error — throw mapped error\n const errorBody = await response.text().catch(() => \"\");\n throwMappedError(response.status, errorBody, path);\n } catch (err) {\n clearTimeout(timeoutId);\n\n if (err instanceof RemoteAPIError || err instanceof SandboxNotFoundError ||\n err instanceof PoolNotFoundError || err instanceof PoolInUseError) {\n throw err;\n }\n\n if (signal?.aborted) {\n throw new SandboxConnectionError(\"Request aborted\");\n }\n\n // Network / timeout error\n lastError =\n err instanceof Error ? err : new Error(String(err));\n\n if (attempt >= this.maxRetries) {\n throw new SandboxConnectionError(lastError.message);\n }\n }\n }\n\n throw new SandboxConnectionError(lastError?.message ?? \"Request failed\");\n }\n}\n\nfunction hasHeader(headers: Record<string, string>, name: string): boolean {\n const lowered = name.toLowerCase();\n return Object.keys(headers).some((key) => key.toLowerCase() === lowered);\n}\n\nfunction normalizeRequestBody(body?: RequestBody | null): BodyInit | undefined {\n if (body == null) {\n return undefined;\n }\n if (body instanceof Uint8Array) {\n return Uint8Array.from(body).buffer;\n }\n return body;\n}\n\n/** Map HTTP status codes to specific error types. */\nfunction throwMappedError(\n status: number,\n body: string,\n path: string,\n): never {\n let message = body;\n try {\n const parsed = JSON.parse(body);\n if (parsed.message) message = parsed.message;\n else if (parsed.error) message = parsed.error;\n } catch {\n // use raw body\n }\n\n if (status === 404) {\n // Determine entity type from path\n if (path.includes(\"sandbox-pools\") || path.includes(\"pools\")) {\n const match = path.match(/sandbox-pools\\/([^/]+)/);\n if (match) throw new PoolNotFoundError(match[1]);\n }\n if (path.includes(\"sandboxes\")) {\n const match = path.match(/sandboxes\\/([^/]+)/);\n if (match) throw new SandboxNotFoundError(match[1]);\n }\n throw new RemoteAPIError(404, message);\n }\n\n if (status === 409) {\n if (path.includes(\"sandbox-pools\") || path.includes(\"pools\")) {\n const match = path.match(/sandbox-pools\\/([^/]+)/);\n if (match) throw new PoolInUseError(match[1], message);\n }\n }\n\n throw new RemoteAPIError(status, message);\n}\n\n/** Combine multiple AbortSignals into one that aborts when any fires. */\nfunction anySignal(signals: AbortSignal[]): AbortSignal {\n const controller = new AbortController();\n for (const signal of signals) {\n if (signal.aborted) {\n controller.abort(signal.reason);\n return controller.signal;\n }\n signal.addEventListener(\"abort\", () => controller.abort(signal.reason), {\n once: true,\n });\n }\n return controller.signal;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","export interface SSEMessage {\n data: string;\n event?: string;\n id?: string;\n}\n\n/**\n * Parse a Server-Sent Events stream into raw SSE messages.\n */\nexport async function* parseSSEMessages(\n stream: ReadableStream<Uint8Array>,\n signal?: AbortSignal,\n): AsyncIterable<SSEMessage> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n if (signal?.aborted) break;\n\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const parts = buffer.split(/\\r?\\n\\r?\\n/);\n buffer = parts.pop() ?? \"\";\n\n for (const part of parts) {\n const lines = part.split(/\\r?\\n/);\n const dataLines: string[] = [];\n let event: string | undefined;\n let id: string | undefined;\n\n for (const line of lines) {\n if (!line || line.startsWith(\":\")) continue;\n\n const separator = line.indexOf(\":\");\n const field = separator === -1 ? line : line.slice(0, separator);\n let value = separator === -1 ? \"\" : line.slice(separator + 1);\n if (value.startsWith(\" \")) {\n value = value.slice(1);\n }\n\n if (field === \"data\") {\n dataLines.push(value);\n } else if (field === \"event\") {\n event = value;\n } else if (field === \"id\") {\n id = value;\n }\n }\n\n if (dataLines.length > 0 || event || id) {\n yield { data: dataLines.join(\"\\n\"), event, id };\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/**\n * Parse a Server-Sent Events stream from a ReadableStream<Uint8Array>.\n *\n * Yields parsed JSON objects for each `data:` line. Handles reconnection\n * by simply yielding events as they arrive.\n */\nexport async function* parseSSEStream<T>(\n stream: ReadableStream<Uint8Array>,\n signal?: AbortSignal,\n): AsyncIterable<T> {\n for await (const message of parseSSEMessages(stream, signal)) {\n if (!message.data) continue;\n try {\n yield JSON.parse(message.data) as T;\n } catch {\n // Skip malformed JSON\n }\n }\n}\n","import * as defaults from \"./defaults.js\";\n\n/** Remove a trailing slash from a URL string if present. */\nfunction trimTrailingSlashes(url: string): string {\n return url.endsWith(\"/\") ? url.slice(0, -1) : url;\n}\n\n/** Check whether a URL points to localhost. */\nexport function isLocalhost(apiUrl: string): boolean {\n try {\n const parsed = new URL(apiUrl);\n return parsed.hostname === \"localhost\" || parsed.hostname === \"127.0.0.1\";\n } catch {\n return false;\n }\n}\n\n/**\n * Derive the sandbox proxy URL from the API URL.\n *\n * Priority:\n * 1. TENSORLAKE_SANDBOX_PROXY_URL env var\n * 2. `http://localhost:9443` for localhost API URLs\n * 3. Transform `api.X` → `sandbox.X`\n * 4. Default fallback\n */\nexport function resolveProxyUrl(apiUrl: string): string {\n const explicit = process.env.TENSORLAKE_SANDBOX_PROXY_URL;\n if (explicit) return explicit;\n\n if (isLocalhost(apiUrl)) return \"http://localhost:9443\";\n\n try {\n const parsed = new URL(apiUrl);\n const host = parsed.hostname;\n if (host.startsWith(\"api.\")) {\n const proxyHost = \"sandbox.\" + host.slice(4);\n return `${parsed.protocol}//${proxyHost}`;\n }\n } catch {\n // fall through to default\n }\n\n return defaults.SANDBOX_PROXY_URL;\n}\n\n/**\n * Resolve the proxy target for a specific sandbox.\n *\n * - Localhost: base URL stays the same, Host header set to `{sandboxId}.local`\n * - Cloud: sandbox ID becomes a subdomain of the proxy host\n *\n * Returns `{ baseUrl, hostHeader }`.\n */\nexport function resolveProxyTarget(\n proxyUrl: string,\n sandboxId: string,\n): { baseUrl: string; hostHeader: string | undefined } {\n try {\n const parsed = new URL(proxyUrl);\n const host = parsed.hostname;\n\n if (host === \"localhost\" || host === \"127.0.0.1\") {\n return {\n baseUrl: trimTrailingSlashes(proxyUrl),\n hostHeader: `${sandboxId}.local`,\n };\n }\n\n const port = parsed.port ? `:${parsed.port}` : \"\";\n return {\n baseUrl: `${parsed.protocol}//${sandboxId}.${host}${port}`,\n hostHeader: undefined,\n };\n } catch {\n return {\n baseUrl: `${trimTrailingSlashes(proxyUrl)}/${sandboxId}`,\n hostHeader: undefined,\n };\n }\n}\n\n/**\n * Build a lifecycle API path.\n *\n * - Localhost (namespaced): `/v1/namespaces/{namespace}/{path}`\n * - Cloud (flat): `/{path}`\n */\nexport function lifecyclePath(\n path: string,\n isLocal: boolean,\n namespace: string,\n): string {\n if (isLocal) {\n return `/v1/namespaces/${namespace}/${path}`;\n }\n return `/${path}`;\n}\n","import type { SandboxClient } from \"./client.js\";\nimport * as defaults from \"./defaults.js\";\nimport { SandboxError } from \"./errors.js\";\nimport { HttpClient } from \"./http.js\";\nimport {\n type CommandResult,\n type CreatePtySessionOptions,\n type DaemonInfo,\n type DirectoryEntry,\n type HealthResponse,\n type ListDirectoryResponse,\n OutputMode,\n type OutputEvent,\n type OutputResponse,\n type ProcessInfo,\n ProcessStatus,\n type PtySessionInfo,\n type RunOptions,\n type SandboxOptions,\n type SendSignalResponse,\n type StartProcessOptions,\n StdinMode,\n fromSnakeKeys,\n} from \"./models.js\";\nimport { parseSSEStream } from \"./sse.js\";\nimport { resolveProxyTarget } from \"./url.js\";\nimport WebSocket, { type RawData } from \"ws\";\n\nconst PTY_OP_DATA = 0x00;\nconst PTY_OP_RESIZE = 0x01;\nconst PTY_OP_READY = 0x02;\nconst PTY_OP_EXIT = 0x03;\n\nexport type PtyDataHandler = (data: Uint8Array) => void;\nexport type PtyExitHandler = (exitCode: number) => void;\n\nexport interface PtyConnectionOptions {\n onData?: PtyDataHandler;\n onExit?: PtyExitHandler;\n}\n\nexport interface CreatePtyOptions\n extends CreatePtySessionOptions,\n PtyConnectionOptions {}\n\nexport class Pty {\n readonly sessionId: string;\n readonly token: string;\n\n private readonly wsUrl: string;\n private readonly wsHeaders: Record<string, string>;\n private readonly killSession: () => Promise<void>;\n private socket: WebSocket | null = null;\n private connectPromise: Promise<this> | null = null;\n private intentionalDisconnect = false;\n private exitCode: number | null = null;\n private waitSettled = false;\n private readonly dataHandlers = new Set<PtyDataHandler>();\n private readonly exitHandlers = new Set<PtyExitHandler>();\n private readonly waitPromise: Promise<number>;\n private resolveWait!: (exitCode: number) => void;\n private rejectWait!: (error: unknown) => void;\n\n constructor(options: {\n sessionId: string;\n token: string;\n wsUrl: string;\n wsHeaders: Record<string, string>;\n killSession: () => Promise<void>;\n }) {\n this.sessionId = options.sessionId;\n this.token = options.token;\n this.wsUrl = options.wsUrl;\n this.wsHeaders = options.wsHeaders;\n this.killSession = options.killSession;\n this.waitPromise = new Promise<number>((resolve, reject) => {\n this.resolveWait = resolve;\n this.rejectWait = reject;\n });\n }\n\n onData(handler: PtyDataHandler): () => void {\n this.dataHandlers.add(handler);\n return () => this.dataHandlers.delete(handler);\n }\n\n onExit(handler: PtyExitHandler): () => void {\n this.exitHandlers.add(handler);\n if (this.exitCode != null) {\n queueMicrotask(() => handler(this.exitCode!));\n }\n return () => this.exitHandlers.delete(handler);\n }\n\n async connect(): Promise<this> {\n if (this.socket?.readyState === WebSocket.OPEN) {\n return this;\n }\n if (this.connectPromise) {\n return this.connectPromise;\n }\n\n this.intentionalDisconnect = false;\n\n this.connectPromise = new Promise<this>((resolve, reject) => {\n let opened = false;\n const socket = new WebSocket(this.wsUrl, {\n headers: this.wsHeaders,\n });\n this.socket = socket;\n\n socket.on(\"open\", async () => {\n try {\n await sendPtyFrame(socket, Buffer.from([PTY_OP_READY]));\n opened = true;\n resolve(this);\n } catch (error) {\n reject(error);\n }\n });\n\n socket.on(\"message\", (message: RawData) => {\n const bytes = normalizePtyMessage(message);\n const opcode = bytes[0];\n\n if (opcode === PTY_OP_DATA) {\n const payload = bytes.subarray(1);\n for (const handler of this.dataHandlers) {\n handler(payload);\n }\n return;\n }\n\n if (opcode === PTY_OP_EXIT && bytes.length >= 5) {\n this.finishWait(bytes.readInt32BE(1));\n }\n });\n\n socket.on(\"close\", (code: number, reason: Buffer) => {\n const closeReason = Buffer.isBuffer(reason)\n ? reason.toString(\"utf8\")\n : String(reason);\n\n if (this.socket === socket) {\n this.socket = null;\n }\n this.connectPromise = null;\n\n if (this.exitCode != null) {\n this.finishWait(this.exitCode);\n return;\n }\n\n if (closeReason.startsWith(\"exit:\")) {\n const parsed = Number.parseInt(closeReason.slice(5), 10);\n this.finishWait(Number.isNaN(parsed) ? -1 : parsed);\n return;\n }\n\n if (this.intentionalDisconnect) {\n this.intentionalDisconnect = false;\n return;\n }\n\n if (!opened) {\n reject(new SandboxError(\n `PTY websocket closed before READY completed: ${code} ${closeReason || \"no reason\"}`,\n ));\n return;\n }\n\n if (closeReason === \"session terminated\") {\n this.failWait(new SandboxError(\"PTY session terminated\"));\n return;\n }\n\n this.failWait(\n new SandboxError(\n `PTY websocket closed unexpectedly: ${code} ${closeReason || \"no reason\"}`,\n ),\n );\n });\n\n socket.on(\"error\", (error: Error) => {\n if (!opened) {\n reject(error);\n }\n });\n });\n\n return this.connectPromise;\n }\n\n async sendInput(input: string | Uint8Array): Promise<void> {\n const socket = this.requireOpenSocket();\n await sendPtyFrame(socket, encodePtyInput(input));\n }\n\n async resize(cols: number, rows: number): Promise<void> {\n const socket = this.requireOpenSocket();\n await sendPtyFrame(socket, encodePtyResize(cols, rows));\n }\n\n disconnect(code = 1000, reason = \"client disconnect\"): void {\n if (!this.socket) return;\n this.intentionalDisconnect = true;\n this.socket.close(code, reason);\n }\n\n wait(): Promise<number> {\n return this.waitPromise;\n }\n\n async kill(): Promise<void> {\n await this.killSession();\n }\n\n private requireOpenSocket(): WebSocket {\n if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {\n throw new SandboxError(\"PTY is not connected\");\n }\n return this.socket;\n }\n\n private finishWait(exitCode: number): void {\n if (this.waitSettled) return;\n this.waitSettled = true;\n this.exitCode = exitCode;\n for (const handler of this.exitHandlers) {\n handler(exitCode);\n }\n this.resolveWait(exitCode);\n }\n\n private failWait(error: unknown): void {\n if (this.waitSettled) return;\n this.waitSettled = true;\n this.rejectWait(error);\n }\n}\n\nfunction normalizePtyMessage(message: RawData): Buffer {\n if (Buffer.isBuffer(message)) return message;\n if (Array.isArray(message)) {\n return Buffer.concat(message.map((part) => Buffer.from(part)));\n }\n return Buffer.from(message);\n}\n\nfunction encodePtyInput(input: string | Uint8Array): Buffer {\n const payload =\n typeof input === \"string\" ? Buffer.from(input, \"utf8\") : Buffer.from(input);\n return Buffer.concat([Buffer.from([PTY_OP_DATA]), payload]);\n}\n\nfunction encodePtyResize(cols: number, rows: number): Buffer {\n const frame = Buffer.alloc(5);\n frame[0] = PTY_OP_RESIZE;\n frame.writeUInt16BE(cols, 1);\n frame.writeUInt16BE(rows, 3);\n return frame;\n}\n\nfunction sendPtyFrame(socket: WebSocket, frame: Buffer): Promise<void> {\n return new Promise((resolve, reject) => {\n socket.send(frame, (error?: Error) => (error ? reject(error) : resolve()));\n });\n}\n\n/**\n * Client for interacting with a running sandbox.\n *\n * Provides process management, file operations, and I/O streaming\n * through the sandbox proxy.\n */\nexport class Sandbox {\n readonly sandboxId: string;\n private readonly http: HttpClient;\n private readonly baseUrl: string;\n private readonly wsHeaders: Record<string, string>;\n private ownsSandbox = false;\n private lifecycleClient: SandboxClient | null = null;\n\n constructor(options: SandboxOptions) {\n this.sandboxId = options.sandboxId;\n\n const proxyUrl = options.proxyUrl ?? defaults.SANDBOX_PROXY_URL;\n const { baseUrl, hostHeader } = resolveProxyTarget(proxyUrl, options.sandboxId);\n this.baseUrl = baseUrl;\n this.wsHeaders = {};\n if (options.apiKey) {\n this.wsHeaders.Authorization = `Bearer ${options.apiKey}`;\n }\n if (options.organizationId) {\n this.wsHeaders[\"X-Forwarded-Organization-Id\"] = options.organizationId;\n }\n if (options.projectId) {\n this.wsHeaders[\"X-Forwarded-Project-Id\"] = options.projectId;\n }\n if (hostHeader) {\n this.wsHeaders.Host = hostHeader;\n }\n\n this.http = new HttpClient({\n baseUrl,\n apiKey: options.apiKey,\n organizationId: options.organizationId,\n projectId: options.projectId,\n hostHeader,\n });\n }\n\n /** @internal Used by SandboxClient.createAndConnect to set ownership. */\n _setOwner(client: SandboxClient): void {\n this.ownsSandbox = true;\n this.lifecycleClient = client;\n }\n\n close(): void {\n this.http.close();\n }\n\n async terminate(): Promise<void> {\n const client = this.lifecycleClient;\n this.ownsSandbox = false;\n this.lifecycleClient = null;\n this.close();\n if (client) {\n await client.delete(this.sandboxId);\n }\n }\n\n // --- High-level convenience ---\n\n async run(command: string, options?: RunOptions): Promise<CommandResult> {\n const proc = await this.startProcess(command, {\n args: options?.args,\n env: options?.env,\n workingDir: options?.workingDir,\n });\n\n const deadline = options?.timeout\n ? Date.now() + options.timeout * 1000\n : null;\n\n let info: ProcessInfo;\n while (true) {\n info = await this.getProcess(proc.pid);\n if (info.status !== ProcessStatus.RUNNING) break;\n if (deadline && Date.now() > deadline) {\n await this.killProcess(proc.pid);\n throw new SandboxError(`Command timed out after ${options!.timeout}s`);\n }\n await sleep(100);\n }\n\n const stdoutResp = await this.getStdout(proc.pid);\n const stderrResp = await this.getStderr(proc.pid);\n\n let exitCode: number;\n if (info.exitCode != null) {\n exitCode = info.exitCode;\n } else if (info.signal != null) {\n exitCode = -info.signal;\n } else {\n exitCode = -1;\n }\n\n return {\n exitCode,\n stdout: stdoutResp.lines.join(\"\\n\"),\n stderr: stderrResp.lines.join(\"\\n\"),\n };\n }\n\n // --- Process management ---\n\n async startProcess(\n command: string,\n options?: StartProcessOptions,\n ): Promise<ProcessInfo> {\n const payload: Record<string, unknown> = { command };\n if (options?.args != null) payload.args = options.args;\n if (options?.env != null) payload.env = options.env;\n if (options?.workingDir != null) payload.working_dir = options.workingDir;\n if (options?.stdinMode != null && options.stdinMode !== StdinMode.CLOSED) {\n payload.stdin_mode = options.stdinMode;\n }\n if (options?.stdoutMode != null && options.stdoutMode !== OutputMode.CAPTURE) {\n payload.stdout_mode = options.stdoutMode;\n }\n if (options?.stderrMode != null && options.stderrMode !== OutputMode.CAPTURE) {\n payload.stderr_mode = options.stderrMode;\n }\n\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"POST\",\n \"/api/v1/processes\",\n { body: payload },\n );\n return fromSnakeKeys(raw) as ProcessInfo;\n }\n\n async listProcesses(): Promise<ProcessInfo[]> {\n const raw = await this.http.requestJson<{ processes: Record<string, unknown>[] }>(\n \"GET\",\n \"/api/v1/processes\",\n );\n return (raw.processes ?? []).map((p) => fromSnakeKeys(p) as ProcessInfo);\n }\n\n async getProcess(pid: number): Promise<ProcessInfo> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n `/api/v1/processes/${pid}`,\n );\n return fromSnakeKeys(raw) as ProcessInfo;\n }\n\n async killProcess(pid: number): Promise<void> {\n await this.http.requestJson(\"DELETE\", `/api/v1/processes/${pid}`);\n }\n\n async sendSignal(pid: number, signal: number): Promise<SendSignalResponse> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"POST\",\n `/api/v1/processes/${pid}/signal`,\n { body: { signal } },\n );\n return fromSnakeKeys(raw) as SendSignalResponse;\n }\n\n // --- Process I/O ---\n\n async writeStdin(pid: number, data: Uint8Array): Promise<void> {\n await this.http.requestBytes(\"POST\", `/api/v1/processes/${pid}/stdin`, {\n body: data,\n contentType: \"application/octet-stream\",\n });\n }\n\n async closeStdin(pid: number): Promise<void> {\n await this.http.requestJson(\"POST\", `/api/v1/processes/${pid}/stdin/close`);\n }\n\n async getStdout(pid: number): Promise<OutputResponse> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n `/api/v1/processes/${pid}/stdout`,\n );\n return fromSnakeKeys(raw) as OutputResponse;\n }\n\n async getStderr(pid: number): Promise<OutputResponse> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n `/api/v1/processes/${pid}/stderr`,\n );\n return fromSnakeKeys(raw) as OutputResponse;\n }\n\n async getOutput(pid: number): Promise<OutputResponse> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n `/api/v1/processes/${pid}/output`,\n );\n return fromSnakeKeys(raw) as OutputResponse;\n }\n\n // --- Streaming (SSE) ---\n\n async *followStdout(\n pid: number,\n options?: { signal?: AbortSignal },\n ): AsyncIterable<OutputEvent> {\n const stream = await this.http.requestStream(\n \"GET\",\n `/api/v1/processes/${pid}/stdout/follow`,\n options,\n );\n for await (const raw of parseSSEStream<Record<string, unknown>>(\n stream,\n options?.signal,\n )) {\n yield fromSnakeKeys(raw) as OutputEvent;\n }\n }\n\n async *followStderr(\n pid: number,\n options?: { signal?: AbortSignal },\n ): AsyncIterable<OutputEvent> {\n const stream = await this.http.requestStream(\n \"GET\",\n `/api/v1/processes/${pid}/stderr/follow`,\n options,\n );\n for await (const raw of parseSSEStream<Record<string, unknown>>(\n stream,\n options?.signal,\n )) {\n yield fromSnakeKeys(raw) as OutputEvent;\n }\n }\n\n async *followOutput(\n pid: number,\n options?: { signal?: AbortSignal },\n ): AsyncIterable<OutputEvent> {\n const stream = await this.http.requestStream(\n \"GET\",\n `/api/v1/processes/${pid}/output/follow`,\n options,\n );\n for await (const raw of parseSSEStream<Record<string, unknown>>(\n stream,\n options?.signal,\n )) {\n yield fromSnakeKeys(raw) as OutputEvent;\n }\n }\n\n // --- File operations ---\n\n async readFile(path: string): Promise<Uint8Array> {\n return this.http.requestBytes(\n \"GET\",\n `/api/v1/files?path=${encodeURIComponent(path)}`,\n );\n }\n\n async writeFile(path: string, content: Uint8Array): Promise<void> {\n await this.http.requestBytes(\n \"PUT\",\n `/api/v1/files?path=${encodeURIComponent(path)}`,\n { body: content, contentType: \"application/octet-stream\" },\n );\n }\n\n async deleteFile(path: string): Promise<void> {\n await this.http.requestJson(\n \"DELETE\",\n `/api/v1/files?path=${encodeURIComponent(path)}`,\n );\n }\n\n async listDirectory(path: string): Promise<ListDirectoryResponse> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n `/api/v1/files/list?path=${encodeURIComponent(path)}`,\n );\n return fromSnakeKeys(raw) as ListDirectoryResponse;\n }\n\n // --- PTY ---\n\n async createPtySession(\n options: CreatePtySessionOptions,\n ): Promise<PtySessionInfo> {\n const payload: Record<string, unknown> = {\n command: options.command,\n rows: options.rows ?? 24,\n cols: options.cols ?? 80,\n };\n if (options.args != null) payload.args = options.args;\n if (options.env != null) payload.env = options.env;\n if (options.workingDir != null) payload.working_dir = options.workingDir;\n\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"POST\",\n \"/api/v1/pty\",\n { body: payload },\n );\n return fromSnakeKeys(raw) as PtySessionInfo;\n }\n\n async createPty(options: CreatePtyOptions): Promise<Pty> {\n const { onData, onExit, ...createOptions } = options;\n const session = await this.createPtySession(createOptions);\n try {\n return await this.connectPty(session.sessionId, session.token, { onData, onExit });\n } catch (error) {\n try {\n await this.http.requestResponse(\"DELETE\", `/api/v1/pty/${session.sessionId}`);\n } catch {}\n throw error;\n }\n }\n\n async connectPty(\n sessionId: string,\n token: string,\n options?: PtyConnectionOptions,\n ): Promise<Pty> {\n const wsUrl = new URL(this.ptyWsUrl(sessionId, token));\n const authToken = wsUrl.searchParams.get(\"token\") ?? token;\n\n const pty = new Pty({\n sessionId,\n token: authToken,\n wsUrl: wsUrl.toString(),\n wsHeaders: {\n ...this.wsHeaders,\n \"X-PTY-Token\": authToken,\n },\n killSession: async () => {\n await this.http.requestResponse(\"DELETE\", `/api/v1/pty/${sessionId}`);\n },\n });\n\n if (options?.onData) {\n pty.onData(options.onData);\n }\n if (options?.onExit) {\n pty.onExit(options.onExit);\n }\n\n await pty.connect();\n return pty;\n }\n\n ptyWsUrl(sessionId: string, token: string): string {\n let wsBase: string;\n if (this.baseUrl.startsWith(\"https://\")) {\n wsBase = \"wss://\" + this.baseUrl.slice(8);\n } else if (this.baseUrl.startsWith(\"http://\")) {\n wsBase = \"ws://\" + this.baseUrl.slice(7);\n } else {\n wsBase = this.baseUrl;\n }\n return `${wsBase}/api/v1/pty/${sessionId}/ws?token=${token}`;\n }\n\n // --- Health ---\n\n async health(): Promise<HealthResponse> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n \"/api/v1/health\",\n );\n return fromSnakeKeys(raw) as HealthResponse;\n }\n\n async info(): Promise<DaemonInfo> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n \"/api/v1/info\",\n );\n return fromSnakeKeys(raw) as DaemonInfo;\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import * as defaults from \"./defaults.js\";\nimport { SandboxError } from \"./errors.js\";\nimport { HttpClient } from \"./http.js\";\nimport {\n type CreateAndConnectOptions,\n type CreatePoolOptions,\n type CreateSandboxOptions,\n type CreateSandboxPoolResponse,\n type CreateSandboxResponse,\n type CreateSnapshotResponse,\n type SandboxClientOptions,\n type SandboxInfo,\n type SandboxPortAccess,\n type SandboxPoolInfo,\n SandboxStatus,\n type SnapshotAndWaitOptions,\n type SnapshotInfo,\n SnapshotStatus,\n type UpdatePoolOptions,\n type UpdateSandboxOptions,\n fromSnakeKeys,\n toSnakeKeys,\n} from \"./models.js\";\nimport { Sandbox } from \"./sandbox.js\";\nimport { isLocalhost, lifecyclePath, resolveProxyUrl } from \"./url.js\";\n\n/**\n * Client for managing TensorLake sandboxes, pools, and snapshots.\n *\n * Use `SandboxClient.forCloud()` or `SandboxClient.forLocalhost()` for\n * clearer construction depending on your deployment target.\n */\nexport class SandboxClient {\n private readonly http: HttpClient;\n private readonly apiUrl: string;\n private readonly apiKey: string | undefined;\n private readonly organizationId: string | undefined;\n private readonly projectId: string | undefined;\n private readonly namespace: string;\n private readonly local: boolean;\n\n constructor(options?: SandboxClientOptions) {\n this.apiUrl = options?.apiUrl ?? defaults.API_URL;\n this.apiKey = options?.apiKey ?? defaults.API_KEY;\n this.organizationId = options?.organizationId;\n this.projectId = options?.projectId;\n this.namespace = options?.namespace ?? defaults.NAMESPACE;\n this.local = isLocalhost(this.apiUrl);\n\n this.http = new HttpClient({\n baseUrl: this.apiUrl,\n apiKey: this.apiKey,\n organizationId: this.organizationId,\n projectId: this.projectId,\n maxRetries: options?.maxRetries ?? defaults.MAX_RETRIES,\n retryBackoffMs: options?.retryBackoffMs ?? defaults.RETRY_BACKOFF_MS,\n });\n }\n\n /** Create a client for the TensorLake cloud platform. */\n static forCloud(options?: {\n apiKey?: string;\n organizationId?: string;\n projectId?: string;\n apiUrl?: string;\n }): SandboxClient {\n return new SandboxClient({\n apiUrl: options?.apiUrl ?? \"https://api.tensorlake.ai\",\n apiKey: options?.apiKey,\n organizationId: options?.organizationId,\n projectId: options?.projectId,\n });\n }\n\n /** Create a client for a local Indexify server. */\n static forLocalhost(options?: {\n apiUrl?: string;\n namespace?: string;\n }): SandboxClient {\n return new SandboxClient({\n apiUrl: options?.apiUrl ?? \"http://localhost:8900\",\n namespace: options?.namespace ?? \"default\",\n });\n }\n\n close(): void {\n this.http.close();\n }\n\n // --- Path helper ---\n\n private path(subpath: string): string {\n return lifecyclePath(subpath, this.local, this.namespace);\n }\n\n // --- Sandbox CRUD ---\n\n async create(options?: CreateSandboxOptions): Promise<CreateSandboxResponse> {\n const body: Record<string, unknown> = {\n resources: {\n cpus: options?.cpus ?? 1.0,\n memory_mb: options?.memoryMb ?? 1024,\n ephemeral_disk_mb: options?.ephemeralDiskMb ?? 1024,\n },\n };\n\n if (options?.image != null) body.image = options.image;\n if (options?.secretNames != null) body.secret_names = options.secretNames;\n if (options?.timeoutSecs != null) body.timeout_secs = options.timeoutSecs;\n if (options?.entrypoint != null) body.entrypoint = options.entrypoint;\n if (options?.snapshotId != null) body.snapshot_id = options.snapshotId;\n if (options?.name != null) body.name = options.name;\n\n if (\n options?.allowInternetAccess === false ||\n options?.allowOut != null ||\n options?.denyOut != null\n ) {\n body.network = {\n allow_internet_access: options?.allowInternetAccess ?? true,\n allow_out: options?.allowOut ?? [],\n deny_out: options?.denyOut ?? [],\n };\n }\n\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"POST\",\n this.path(\"sandboxes\"),\n { body },\n );\n return fromSnakeKeys(raw, \"sandboxId\") as CreateSandboxResponse;\n }\n\n async get(sandboxId: string): Promise<SandboxInfo> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n this.path(`sandboxes/${sandboxId}`),\n );\n return fromSnakeKeys(raw, \"sandboxId\") as SandboxInfo;\n }\n\n async list(): Promise<SandboxInfo[]> {\n const raw = await this.http.requestJson<{ sandboxes: Record<string, unknown>[] }>(\n \"GET\",\n this.path(\"sandboxes\"),\n );\n return (raw.sandboxes ?? []).map(\n (s) => fromSnakeKeys(s, \"sandboxId\") as SandboxInfo,\n );\n }\n\n async update(sandboxId: string, options: UpdateSandboxOptions): Promise<SandboxInfo> {\n const body: Record<string, unknown> = {};\n if (options.name != null) body.name = options.name;\n if (options.allowUnauthenticatedAccess != null) {\n body.allow_unauthenticated_access = options.allowUnauthenticatedAccess;\n }\n if (options.exposedPorts != null) {\n body.exposed_ports = normalizeUserPorts(options.exposedPorts);\n }\n if (Object.keys(body).length === 0) {\n throw new SandboxError(\"At least one sandbox update field must be provided.\");\n }\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"PATCH\",\n this.path(`sandboxes/${sandboxId}`),\n { body },\n );\n return fromSnakeKeys(raw, \"sandboxId\") as SandboxInfo;\n }\n\n async getPortAccess(sandboxId: string): Promise<SandboxPortAccess> {\n const info = await this.get(sandboxId);\n return {\n allowUnauthenticatedAccess: info.allowUnauthenticatedAccess ?? false,\n exposedPorts: dedupeAndSortPorts(info.exposedPorts ?? []),\n sandboxUrl: info.sandboxUrl,\n };\n }\n\n async exposePorts(\n sandboxId: string,\n ports: number[],\n options?: { allowUnauthenticatedAccess?: boolean },\n ): Promise<SandboxInfo> {\n const requestedPorts = normalizeUserPorts(ports);\n const current = await this.getPortAccess(sandboxId);\n const desiredPorts = dedupeAndSortPorts([\n ...current.exposedPorts,\n ...requestedPorts,\n ]);\n return this.update(sandboxId, {\n allowUnauthenticatedAccess:\n options?.allowUnauthenticatedAccess ??\n current.allowUnauthenticatedAccess,\n exposedPorts: desiredPorts,\n });\n }\n\n async unexposePorts(\n sandboxId: string,\n ports: number[],\n ): Promise<SandboxInfo> {\n const requestedPorts = normalizeUserPorts(ports);\n const current = await this.getPortAccess(sandboxId);\n const toRemove = new Set(requestedPorts);\n const desiredPorts = current.exposedPorts.filter((port) => !toRemove.has(port));\n return this.update(sandboxId, {\n allowUnauthenticatedAccess: desiredPorts.length\n ? current.allowUnauthenticatedAccess\n : false,\n exposedPorts: desiredPorts,\n });\n }\n\n async delete(sandboxId: string): Promise<void> {\n await this.http.requestJson(\n \"DELETE\",\n this.path(`sandboxes/${sandboxId}`),\n );\n }\n\n async suspend(sandboxId: string): Promise<void> {\n await this.http.requestResponse(\n \"POST\",\n this.path(`sandboxes/${sandboxId}/suspend`),\n );\n }\n\n async resume(sandboxId: string): Promise<void> {\n await this.http.requestResponse(\n \"POST\",\n this.path(`sandboxes/${sandboxId}/resume`),\n );\n }\n\n async claim(poolId: string): Promise<CreateSandboxResponse> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"POST\",\n this.path(`sandbox-pools/${poolId}/sandboxes`),\n );\n return fromSnakeKeys(raw, \"sandboxId\") as CreateSandboxResponse;\n }\n\n // --- Snapshots ---\n\n async snapshot(sandboxId: string): Promise<CreateSnapshotResponse> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"POST\",\n this.path(`sandboxes/${sandboxId}/snapshot`),\n );\n return fromSnakeKeys(raw, \"snapshotId\") as CreateSnapshotResponse;\n }\n\n async getSnapshot(snapshotId: string): Promise<SnapshotInfo> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n this.path(`snapshots/${snapshotId}`),\n );\n return fromSnakeKeys(raw, \"snapshotId\") as SnapshotInfo;\n }\n\n async listSnapshots(): Promise<SnapshotInfo[]> {\n const raw = await this.http.requestJson<{ snapshots: Record<string, unknown>[] }>(\n \"GET\",\n this.path(\"snapshots\"),\n );\n return (raw.snapshots ?? []).map(\n (s) => fromSnakeKeys(s, \"snapshotId\") as SnapshotInfo,\n );\n }\n\n async deleteSnapshot(snapshotId: string): Promise<void> {\n await this.http.requestJson(\n \"DELETE\",\n this.path(`snapshots/${snapshotId}`),\n );\n }\n\n async snapshotAndWait(\n sandboxId: string,\n options?: SnapshotAndWaitOptions,\n ): Promise<SnapshotInfo> {\n const timeout = options?.timeout ?? 300;\n const pollInterval = options?.pollInterval ?? 1;\n\n const result = await this.snapshot(sandboxId);\n const deadline = Date.now() + timeout * 1000;\n\n while (Date.now() < deadline) {\n const info = await this.getSnapshot(result.snapshotId);\n if (info.status === SnapshotStatus.COMPLETED) return info;\n if (info.status === SnapshotStatus.FAILED) {\n throw new SandboxError(\n `Snapshot ${result.snapshotId} failed: ${info.error}`,\n );\n }\n await sleep(pollInterval * 1000);\n }\n\n throw new SandboxError(\n `Snapshot ${result.snapshotId} did not complete within ${timeout}s`,\n );\n }\n\n // --- Pools ---\n\n async createPool(options: CreatePoolOptions): Promise<CreateSandboxPoolResponse> {\n const body: Record<string, unknown> = {\n image: options.image,\n resources: {\n cpus: options.cpus ?? 1.0,\n memory_mb: options.memoryMb ?? 1024,\n ephemeral_disk_mb: options.ephemeralDiskMb ?? 1024,\n },\n timeout_secs: options.timeoutSecs ?? 0,\n };\n\n if (options.secretNames != null) body.secret_names = options.secretNames;\n if (options.entrypoint != null) body.entrypoint = options.entrypoint;\n if (options.maxContainers != null) body.max_containers = options.maxContainers;\n if (options.warmContainers != null) body.warm_containers = options.warmContainers;\n\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"POST\",\n this.path(\"sandbox-pools\"),\n { body },\n );\n return fromSnakeKeys(raw, \"poolId\") as CreateSandboxPoolResponse;\n }\n\n async getPool(poolId: string): Promise<SandboxPoolInfo> {\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"GET\",\n this.path(`sandbox-pools/${poolId}`),\n );\n return fromSnakeKeys(raw, \"poolId\") as SandboxPoolInfo;\n }\n\n async listPools(): Promise<SandboxPoolInfo[]> {\n const raw = await this.http.requestJson<{ pools: Record<string, unknown>[] }>(\n \"GET\",\n this.path(\"sandbox-pools\"),\n );\n return (raw.pools ?? []).map(\n (p) => fromSnakeKeys(p, \"poolId\") as SandboxPoolInfo,\n );\n }\n\n async updatePool(\n poolId: string,\n options: UpdatePoolOptions,\n ): Promise<SandboxPoolInfo> {\n const body: Record<string, unknown> = {\n image: options.image,\n resources: {\n cpus: options.cpus ?? 1.0,\n memory_mb: options.memoryMb ?? 1024,\n ephemeral_disk_mb: options.ephemeralDiskMb ?? 1024,\n },\n timeout_secs: options.timeoutSecs ?? 0,\n };\n\n if (options.secretNames != null) body.secret_names = options.secretNames;\n if (options.entrypoint != null) body.entrypoint = options.entrypoint;\n if (options.maxContainers != null) body.max_containers = options.maxContainers;\n if (options.warmContainers != null) body.warm_containers = options.warmContainers;\n\n const raw = await this.http.requestJson<Record<string, unknown>>(\n \"PUT\",\n this.path(`sandbox-pools/${poolId}`),\n { body },\n );\n return fromSnakeKeys(raw, \"poolId\") as SandboxPoolInfo;\n }\n\n async deletePool(poolId: string): Promise<void> {\n await this.http.requestJson(\n \"DELETE\",\n this.path(`sandbox-pools/${poolId}`),\n );\n }\n\n // --- Connect ---\n\n connect(identifier: string, proxyUrl?: string): Sandbox {\n const resolvedProxy = proxyUrl ?? resolveProxyUrl(this.apiUrl);\n return new Sandbox({\n sandboxId: identifier,\n proxyUrl: resolvedProxy,\n apiKey: this.apiKey,\n organizationId: this.organizationId,\n projectId: this.projectId,\n });\n }\n\n async createAndConnect(\n options?: CreateAndConnectOptions,\n ): Promise<Sandbox> {\n const startupTimeout = options?.startupTimeout ?? 60;\n\n let result: CreateSandboxResponse;\n if (options?.poolId != null) {\n result = await this.claim(options.poolId);\n } else {\n result = await this.create(options);\n }\n\n const deadline = Date.now() + startupTimeout * 1000;\n\n while (Date.now() < deadline) {\n const info = await this.get(result.sandboxId);\n if (info.status === SandboxStatus.RUNNING) {\n const sandbox = this.connect(result.sandboxId, options?.proxyUrl);\n sandbox._setOwner(this);\n return sandbox;\n }\n if (info.status === SandboxStatus.TERMINATED) {\n throw new SandboxError(\n `Sandbox ${result.sandboxId} terminated during startup`,\n );\n }\n await sleep(500);\n }\n\n // Timed out — clean up\n try {\n await this.delete(result.sandboxId);\n } catch {\n // ignore cleanup failures\n }\n throw new SandboxError(\n `Sandbox ${result.sandboxId} did not start within ${startupTimeout}s`,\n );\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nconst RESERVED_SANDBOX_MANAGEMENT_PORT = 9501;\n\nfunction normalizeUserPorts(ports: number[]): number[] {\n return dedupeAndSortPorts(ports.map(validateUserPort));\n}\n\nfunction validateUserPort(port: number): number {\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new SandboxError(`invalid port '${port}'`);\n }\n if (port === RESERVED_SANDBOX_MANAGEMENT_PORT) {\n throw new SandboxError(\"port 9501 is reserved for sandbox management\");\n }\n return port;\n}\n\nfunction dedupeAndSortPorts(ports: number[]): number[] {\n return [...new Set(ports)].sort((a, b) => a - b);\n}\n","import { randomUUID } from \"node:crypto\";\n\nexport const ImageBuildOperationType = {\n ADD: \"ADD\",\n COPY: \"COPY\",\n ENV: \"ENV\",\n RUN: \"RUN\",\n WORKDIR: \"WORKDIR\",\n} as const;\n\nexport type ImageBuildOperationType =\n (typeof ImageBuildOperationType)[keyof typeof ImageBuildOperationType];\n\nexport interface ImageBuildOperation {\n type: ImageBuildOperationType;\n args: string[];\n options: Record<string, string>;\n}\n\nexport interface ImageOptions {\n name?: string;\n tag?: string;\n baseImage?: string | null;\n}\n\nfunction cloneOperation(op: ImageBuildOperation): ImageBuildOperation {\n return {\n type: op.type,\n args: [...op.args],\n options: { ...op.options },\n };\n}\n\nexport class Image {\n readonly _id: string;\n readonly _name: string;\n readonly _tag: string;\n readonly _baseImage: string | null;\n readonly _buildOperations: ImageBuildOperation[];\n\n constructor();\n constructor(name: string, tag?: string, baseImage?: string | null);\n constructor(options: ImageOptions);\n constructor(\n nameOrOptions: string | ImageOptions = {},\n tag = \"latest\",\n baseImage: string | null = null,\n ) {\n this._id = randomUUID();\n this._buildOperations = [];\n\n if (typeof nameOrOptions === \"string\") {\n this._name = nameOrOptions;\n this._tag = tag;\n this._baseImage = baseImage;\n return;\n }\n\n this._name = nameOrOptions.name ?? \"default\";\n this._tag = nameOrOptions.tag ?? \"latest\";\n this._baseImage = nameOrOptions.baseImage ?? null;\n }\n\n get name(): string {\n return this._name;\n }\n\n get tag(): string {\n return this._tag;\n }\n\n get baseImage(): string | null {\n return this._baseImage;\n }\n\n get buildOperations(): ImageBuildOperation[] {\n return this._buildOperations.map(cloneOperation);\n }\n\n add(\n src: string,\n dest: string,\n options: Record<string, string> | undefined = undefined,\n ): this {\n return this._addOperation({\n type: ImageBuildOperationType.ADD,\n args: [src, dest],\n options: options == null ? {} : { ...options },\n });\n }\n\n copy(\n src: string,\n dest: string,\n options: Record<string, string> | undefined = undefined,\n ): this {\n return this._addOperation({\n type: ImageBuildOperationType.COPY,\n args: [src, dest],\n options: options == null ? {} : { ...options },\n });\n }\n\n env(key: string, value: string): this {\n return this._addOperation({\n type: ImageBuildOperationType.ENV,\n args: [key, value],\n options: {},\n });\n }\n\n run(\n commands: string | string[],\n options: Record<string, string> | undefined = undefined,\n ): this {\n return this._addOperation({\n type: ImageBuildOperationType.RUN,\n args: Array.isArray(commands) ? [...commands] : [commands],\n options: options == null ? {} : { ...options },\n });\n }\n\n workdir(directory: string): this {\n return this._addOperation({\n type: ImageBuildOperationType.WORKDIR,\n args: [directory],\n options: {},\n });\n }\n\n private _addOperation(op: ImageBuildOperation): this {\n this._buildOperations.push(op);\n return this;\n }\n}\n\nfunction renderOptions(options: Record<string, string>): string {\n const entries = Object.entries(options);\n if (entries.length === 0) {\n return \"\";\n }\n return ` ${entries.map(([key, value]) => `--${key}=${value}`).join(\" \")}`;\n}\n\nfunction renderBuildOp(op: ImageBuildOperation): string {\n const options = renderOptions(op.options);\n if (op.type === ImageBuildOperationType.ENV) {\n return `ENV${options} ${op.args[0]}=${JSON.stringify(op.args[1])}`;\n }\n return `${op.type}${options} ${op.args.join(\" \")}`;\n}\n\nexport function dockerfileContent(image: Image): string {\n const lines = image.baseImage == null ? [] : [`FROM ${image.baseImage}`];\n lines.push(...image.buildOperations.map((op) => renderBuildOp(op)));\n return lines.join(\"\\n\");\n}\n"],"mappings":"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","names":["path","value","path","WebSocket","sleep","path","sleep","path","flagValue","sleep"]}
|