@computesdk/docker 1.1.7 → 1.2.0

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/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as computesdk from 'computesdk';
2
- import { Runtime, CreateSandboxOptions, ExecutionResult, RunCommandOptions, SandboxInfo, FileEntry } from 'computesdk';
2
+ import { Runtime } from 'computesdk';
3
3
  import Docker, { DockerOptions, ContainerCreateOptions, ContainerStartOptions, Container } from 'dockerode';
4
4
 
5
5
  /** When the provider should clean up containers it created */
@@ -78,43 +78,7 @@ interface DockerSandboxHandle {
78
78
  image: string;
79
79
  createdAt: Date;
80
80
  }
81
- /** URL options for port-forwarded services */
82
- interface DockerUrlOptions {
83
- port: number;
84
- protocol?: 'http' | 'https';
85
- host?: string;
86
- }
87
- /** Optional FS helpers you might expose */
88
- interface DockerSandboxFileSystem {
89
- readFile(path: string): Promise<string>;
90
- writeFile(path: string, content: string): Promise<void>;
91
- mkdir(path: string): Promise<void>;
92
- readdir(path: string): Promise<FileEntry[]>;
93
- exists(path: string): Promise<boolean>;
94
- remove(path: string): Promise<void>;
95
- }
96
- /** Strongly-typed sandbox API shape */
97
- interface DockerSandboxAPI {
98
- sandboxId: string;
99
- provider: 'docker';
100
- runCode(code: string, runtime?: Runtime): Promise<ExecutionResult>;
101
- runCommand(command: string, args?: string[], options?: RunCommandOptions): Promise<ExecutionResult>;
102
- getInfo(): Promise<SandboxInfo>;
103
- getUrl(options: DockerUrlOptions): Promise<string>;
104
- getProvider(): any;
105
- getInstance(): DockerSandboxHandle;
106
- kill(): Promise<void>;
107
- destroy(): Promise<void>;
108
- filesystem: DockerSandboxFileSystem;
109
- }
110
- /** Factory return shape mirroring your createE2BCompute helper */
111
- interface CreateDockerCompute {
112
- sandbox: {
113
- create(options?: CreateSandboxOptions): Promise<DockerSandboxAPI>;
114
- };
115
- }
116
81
 
117
82
  declare const docker: (config: DockerConfig) => computesdk.Provider<DockerSandboxHandle, any, any>;
118
- declare function createDockerCompute(config: DockerConfig): CreateDockerCompute;
119
83
 
120
- export { createDockerCompute, docker };
84
+ export { docker };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as computesdk from 'computesdk';
2
- import { Runtime, CreateSandboxOptions, ExecutionResult, RunCommandOptions, SandboxInfo, FileEntry } from 'computesdk';
2
+ import { Runtime } from 'computesdk';
3
3
  import Docker, { DockerOptions, ContainerCreateOptions, ContainerStartOptions, Container } from 'dockerode';
4
4
 
5
5
  /** When the provider should clean up containers it created */
@@ -78,43 +78,7 @@ interface DockerSandboxHandle {
78
78
  image: string;
79
79
  createdAt: Date;
80
80
  }
81
- /** URL options for port-forwarded services */
82
- interface DockerUrlOptions {
83
- port: number;
84
- protocol?: 'http' | 'https';
85
- host?: string;
86
- }
87
- /** Optional FS helpers you might expose */
88
- interface DockerSandboxFileSystem {
89
- readFile(path: string): Promise<string>;
90
- writeFile(path: string, content: string): Promise<void>;
91
- mkdir(path: string): Promise<void>;
92
- readdir(path: string): Promise<FileEntry[]>;
93
- exists(path: string): Promise<boolean>;
94
- remove(path: string): Promise<void>;
95
- }
96
- /** Strongly-typed sandbox API shape */
97
- interface DockerSandboxAPI {
98
- sandboxId: string;
99
- provider: 'docker';
100
- runCode(code: string, runtime?: Runtime): Promise<ExecutionResult>;
101
- runCommand(command: string, args?: string[], options?: RunCommandOptions): Promise<ExecutionResult>;
102
- getInfo(): Promise<SandboxInfo>;
103
- getUrl(options: DockerUrlOptions): Promise<string>;
104
- getProvider(): any;
105
- getInstance(): DockerSandboxHandle;
106
- kill(): Promise<void>;
107
- destroy(): Promise<void>;
108
- filesystem: DockerSandboxFileSystem;
109
- }
110
- /** Factory return shape mirroring your createE2BCompute helper */
111
- interface CreateDockerCompute {
112
- sandbox: {
113
- create(options?: CreateSandboxOptions): Promise<DockerSandboxAPI>;
114
- };
115
- }
116
81
 
117
82
  declare const docker: (config: DockerConfig) => computesdk.Provider<DockerSandboxHandle, any, any>;
118
- declare function createDockerCompute(config: DockerConfig): CreateDockerCompute;
119
83
 
120
- export { createDockerCompute, docker };
84
+ export { docker };
package/dist/index.js CHANGED
@@ -30,7 +30,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
- createDockerCompute: () => createDockerCompute,
34
33
  docker: () => docker
35
34
  });
36
35
  module.exports = __toCommonJS(index_exports);
@@ -322,43 +321,20 @@ var docker = (0, import_computesdk.createProvider)({
322
321
  }
323
322
  }
324
323
  return {
325
- stdout,
326
- stderr,
324
+ output: stdout + stderr,
327
325
  exitCode,
328
- executionTime: Date.now() - start,
329
- sandboxId: handle.containerId,
330
- provider: PROVIDER
326
+ language: rt
331
327
  };
332
328
  },
333
- runCommand: async (handle, command, args = [], options) => {
329
+ runCommand: async (handle, command, args = []) => {
334
330
  const start = Date.now();
335
- const { command: finalCmd, args: finalArgs, isBackground } = (0, import_computesdk.createBackgroundCommand)(command, args, options);
336
- let shell = finalArgs.length ? `${finalCmd} ${finalArgs.join(" ")}` : finalCmd;
337
- let pid;
338
- if (isBackground) {
339
- shell = `(${shell}) & echo $!`;
340
- const r = await runExec(handle, shell);
341
- const m = r.stdout.trim().split(/\s+/).pop();
342
- pid = m && /^\d+$/.test(m) ? Number(m) : void 0;
343
- return {
344
- stdout: r.stdout,
345
- stderr: r.stderr,
346
- exitCode: r.exitCode,
347
- executionTime: Date.now() - start,
348
- sandboxId: handle.containerId,
349
- provider: PROVIDER,
350
- isBackground: true,
351
- ...pid ? { pid } : {}
352
- };
353
- }
331
+ const shell = args.length ? `${command} ${args.join(" ")}` : command;
354
332
  const { stdout, stderr, exitCode } = await runExec(handle, shell);
355
333
  return {
356
334
  stdout,
357
335
  stderr,
358
336
  exitCode,
359
- executionTime: Date.now() - start,
360
- sandboxId: handle.containerId,
361
- provider: PROVIDER
337
+ durationMs: Date.now() - start
362
338
  };
363
339
  },
364
340
  getInfo: async (handle) => {
@@ -448,23 +424,8 @@ var docker = (0, import_computesdk.createProvider)({
448
424
  }
449
425
  }
450
426
  });
451
- function createDockerCompute(config) {
452
- const provider = docker(config);
453
- return {
454
- sandbox: {
455
- create: async (options) => {
456
- const sb = await provider.sandbox.create(options);
457
- return {
458
- ...sb,
459
- getInstance: () => sb.getInstance()
460
- };
461
- }
462
- }
463
- };
464
- }
465
427
  // Annotate the CommonJS export names for ESM import in node:
466
428
  0 && (module.exports = {
467
- createDockerCompute,
468
429
  docker
469
430
  });
470
431
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types/types.ts"],"sourcesContent":["import Docker from 'dockerode';\nimport { PassThrough } from 'stream';\nimport { createProvider, createBackgroundCommand } from 'computesdk';\nimport type {\n Runtime,\n ExecutionResult,\n RunCommandOptions,\n CreateSandboxOptions,\n SandboxInfo,\n FileEntry,\n} from 'computesdk';\n\nimport { defaultDockerConfig } from './types/types';\nimport type {\n DockerConfig,\n DockerSandboxHandle,\n DockerSandboxAPI,\n CreateDockerCompute,\n DockerImage,\n PortBindings,\n} from './types/types';\n\nconst PROVIDER = 'docker' as const;\nconst LABEL_KEY = 'com.computesdk.sandbox';\nconst LABEL_RUNTIME = 'com.computesdk.runtime';\nconst KEEPALIVE_CMD = ['/bin/sh', '-c', 'while :; do sleep 3600; done'];\n\nfunction pick<T>(val: T | undefined, fallback: T): T {\n return typeof val === 'undefined' ? fallback : val;\n}\n\nasync function ensureImage(docker: Docker, image: DockerImage): Promise<void> {\n const policy = image.pullPolicy ?? 'ifNotPresent';\n if (policy === 'never') return;\n\n const images = await docker.listImages();\n const hasImage = images.some(img => (img.RepoTags || []).includes(image.name));\n\n if (policy === 'always' || (policy === 'ifNotPresent' && !hasImage)) {\n await new Promise<void>((resolve, reject) => {\n const cb = (err: any, stream?: NodeJS.ReadableStream) => {\n if (err) return reject(err);\n if (!stream) return reject(new Error('docker.pull returned no stream'));\n (docker as any).modem.followProgress(stream, (err2: any) => (err2 ? reject(err2) : resolve()));\n };\n if (image.auth) docker.pull(image.name, { authconfig: image.auth } as any, cb);\n else docker.pull(image.name, cb);\n });\n }\n}\n\nasync function waitUntilRunning(container: Docker.Container, timeoutMs = 4000) {\n const start = Date.now();\n try {\n const s = await container.inspect();\n if (s.State?.Running) return;\n } catch { /* ignore */ }\n\n while (Date.now() - start < timeoutMs) {\n const s = await container.inspect();\n if (s.State?.Running) return;\n await new Promise(r => setTimeout(r, 100));\n }\n throw new Error('Container did not reach Running state in time');\n}\n\nasync function runExec(\n handle: DockerSandboxHandle,\n shellCommand: string,\n attachTTY = false\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n await waitUntilRunning(handle.container);\n\n const exec = await handle.container.exec({\n Cmd: ['/bin/sh', '-c', shellCommand],\n AttachStdout: true,\n AttachStderr: true,\n Tty: attachTTY,\n });\n\n const stream = (await exec.start({ hijack: true, stdin: false })) as NodeJS.ReadableStream;\n\n let stdout = '';\n let stderr = '';\n\n await new Promise<void>((resolve, reject) => {\n if (attachTTY) {\n stream.on('data', (chunk: Buffer) => (stdout += chunk.toString('utf8')));\n stream.on('end', resolve);\n stream.on('error', reject);\n return;\n }\n const out = new PassThrough();\n const err = new PassThrough();\n out.on('data', (c: Buffer) => (stdout += c.toString('utf8')));\n err.on('data', (c: Buffer) => (stderr += c.toString('utf8')));\n (handle.docker as any).modem.demuxStream(stream as any, out as any, err as any);\n stream.on('end', resolve);\n stream.on('error', reject);\n });\n\n const inspect = await exec.inspect();\n const exitCode = inspect.ExitCode ?? 0;\n return { stdout, stderr, exitCode };\n}\n\nfunction toHostBindings(ports?: PortBindings) {\n if (!ports) return undefined;\n const exposed: Record<string, {}> = {};\n const bindings: Record<string, Array<{ HostPort?: string; HostIp?: string }>> = {};\n for (const key of Object.keys(ports)) {\n exposed[key] = {};\n bindings[key] = (ports as any)[key].map((p: any) => ({\n HostPort: p.hostPort ? String(p.hostPort) : undefined,\n HostIp: p.hostIP,\n }));\n }\n return { ExposedPorts: exposed, PortBindings: bindings };\n}\n\nfunction dockerHostNameFromEnv(): string {\n const hostEnv = process.env.DOCKER_HOST;\n if (hostEnv?.startsWith('tcp://')) {\n try {\n const u = new URL(hostEnv);\n return u.hostname || 'localhost';\n } catch { /* noop */ }\n }\n return 'localhost';\n}\n\nfunction pickImageForRuntime(runtime: Runtime, configured?: DockerImage): DockerImage {\n // If user supplied an image that already matches, use it. Otherwise pick a sensible default.\n if (configured?.name) {\n if (runtime === 'python' && /python|conda|pypy/i.test(configured.name)) return configured;\n if (runtime === 'node' && /node/i.test(configured.name)) return configured;\n }\n return {\n name: runtime === 'python' ? 'python:3.11-slim' : 'node:20-alpine',\n pullPolicy: configured?.pullPolicy ?? 'ifNotPresent',\n auth: configured?.auth,\n };\n}\n\nexport const docker = createProvider<DockerSandboxHandle, DockerConfig>({\n name: PROVIDER,\n methods: {\n sandbox: {\n create: async (config: DockerConfig, options?: CreateSandboxOptions) => {\n const cfg: DockerConfig = { ...defaultDockerConfig, ...config };\n const effectiveRuntime: Runtime = (options?.runtime ?? cfg.runtime ?? 'python') as Runtime;\n\n if (effectiveRuntime !== 'python' && effectiveRuntime !== 'node') {\n throw new Error(`Docker provider supports only 'python' or 'node'. Received: ${String(effectiveRuntime)}`);\n }\n\n const docker = new Docker(cfg.connection as any);\n\n // Reattach?\n if (options?.sandboxId) {\n try {\n const container = docker.getContainer(options.sandboxId);\n const info = await container.inspect();\n return {\n sandbox: <DockerSandboxHandle>{\n docker,\n container,\n containerId: options.sandboxId,\n image: info.Config?.Image ?? cfg.image.name,\n createdAt: new Date(info.Created || Date.now()),\n },\n sandboxId: options.sandboxId,\n };\n } catch (err) {\n // Failed to reattach to existing container; will create a new one.\n console.warn(`Could not reattach to Docker container with ID ${options.sandboxId}:`, err);\n }\n }\n\n // Choose image based on runtime if needed\n const chosenImage = pickImageForRuntime(effectiveRuntime, cfg.image);\n await ensureImage(docker, chosenImage);\n\n // Build container create options\n const hb = toHostBindings(cfg.container?.ports);\n const createOptions = {\n Image: chosenImage.name,\n Tty: pick(cfg.container?.tty, false),\n OpenStdin: pick(cfg.container?.openStdin, false),\n Labels: { [LABEL_KEY]: 'true', [LABEL_RUNTIME]: effectiveRuntime }, // <-- store runtime per sandbox\n WorkingDir: cfg.container?.workdir,\n Env: cfg.container?.env\n ? Object.entries(cfg.container.env).map(([k, v]) => `${k}=${v}`)\n : undefined,\n Cmd: KEEPALIVE_CMD, // keep container alive\n HostConfig: {\n AutoRemove: cfg.container?.autoRemove ?? false, // keep around for exec/FS ops\n Binds: cfg.container?.binds,\n NetworkMode: cfg.container?.networkMode,\n Privileged: cfg.container?.privileged,\n CapAdd: cfg.container?.capabilities?.add,\n CapDrop: cfg.container?.capabilities?.drop,\n LogConfig: cfg.container?.logDriver\n ? { Type: cfg.container.logDriver, Config: cfg.container.logOpts || {} }\n : undefined,\n Resources: cfg.container?.resources,\n DeviceRequests: cfg.container?.gpus\n ? [\n {\n Driver: 'nvidia',\n Count:\n cfg.container.gpus === 'all'\n ? -1\n : typeof cfg.container.gpus === 'number'\n ? cfg.container.gpus\n : 1,\n DeviceIDs:\n typeof cfg.container.gpus === 'string' && cfg.container.gpus !== 'all'\n ? [String(cfg.container.gpus)]\n : undefined,\n Capabilities: [['gpu']],\n },\n ]\n : undefined,\n ...(hb ? { PortBindings: hb.PortBindings } : {}),\n },\n ...(hb ? { ExposedPorts: hb.ExposedPorts } : {}),\n ...(cfg.createOptions || {}),\n } as import('dockerode').ContainerCreateOptions;\n\n const container = await docker.createContainer(createOptions);\n await container.start(cfg.startOptions || {});\n await waitUntilRunning(container);\n\n const inspect = await container.inspect();\n const handle: DockerSandboxHandle = {\n docker,\n container,\n containerId: inspect.Id,\n image: inspect.Config?.Image ?? chosenImage.name,\n createdAt: new Date(inspect.Created || Date.now()),\n };\n\n return { sandbox: handle, sandboxId: handle.containerId };\n },\n\n getById: async (config: DockerConfig, sandboxId: string) => {\n const docker = new Docker((config || defaultDockerConfig).connection as any);\n try {\n const container = docker.getContainer(sandboxId);\n const info = await container.inspect();\n return {\n sandbox: <DockerSandboxHandle>{\n docker,\n container,\n containerId: sandboxId,\n image: info.Config?.Image ?? '',\n createdAt: new Date(info.Created || Date.now()),\n },\n sandboxId,\n };\n } catch {\n return null;\n }\n },\n\n list: async (config: DockerConfig) => {\n const docker = new Docker((config || defaultDockerConfig).connection as any);\n try {\n const items = await docker.listContainers({\n all: true,\n filters: { label: [LABEL_KEY] } as any,\n });\n return items.map(ci => ({\n sandbox: <DockerSandboxHandle>{\n docker,\n container: docker.getContainer(ci.Id),\n containerId: ci.Id,\n image: ci.Image,\n createdAt: new Date((ci as any).Created * 1000),\n },\n sandboxId: ci.Id,\n }));\n } catch {\n return [];\n }\n },\n\n destroy: async (config: DockerConfig, sandboxId: string) => {\n const docker = new Docker((config || defaultDockerConfig).connection as any);\n try {\n const c = docker.getContainer(sandboxId);\n try { await c.stop({ t: 5 } as any); } catch { /* stopped */ }\n await c.remove({ force: true });\n } catch {\n // ok if already gone\n }\n },\n\n runCode: async (handle: DockerSandboxHandle, code: string, runtime?: Runtime): Promise<ExecutionResult> => {\n const start = Date.now();\n\n // Resolve runtime: param → label → error\n let rt: Runtime | undefined = runtime;\n if (!rt) {\n const info = await handle.container.inspect();\n rt = (info.Config?.Labels?.[LABEL_RUNTIME] as Runtime) || undefined;\n }\n if (rt !== 'python' && rt !== 'node') {\n throw new Error(`Docker runtime must be 'python' or 'node'. Pass runtime in config or as a parameter.`);\n }\n\n // Write to file, then execute. This is robust on Alpine/Debian.\n const tmpFile = rt === 'python' ? '/tmp/compute_code.py' : '/tmp/compute_code.js';\n const b64 = Buffer.from(code, 'utf8').toString('base64');\n const makeAndRun =\n `printf '%s' \"${b64}\" | base64 -d > ${tmpFile} && ` +\n (rt === 'python' ? `python3 ${tmpFile}` : `node ${tmpFile}`);\n\n const { stdout, stderr, exitCode } = await runExec(handle, makeAndRun);\n\n if (exitCode !== 0 && stderr) {\n // Throw ONLY on syntax errors (SDK contract)\n const isSyntax =\n stderr.includes('SyntaxError') ||\n stderr.includes('invalid syntax') ||\n stderr.includes('Unexpected token') ||\n stderr.includes('Unexpected identifier');\n if (isSyntax) {\n const last = stderr.trim().split('\\n').slice(-1)[0] || 'Syntax error';\n throw new Error(`Syntax error: ${last}`);\n }\n }\n\n return {\n stdout,\n stderr,\n exitCode,\n executionTime: Date.now() - start,\n sandboxId: handle.containerId,\n provider: PROVIDER,\n };\n },\n\n runCommand: async (\n handle: DockerSandboxHandle,\n command: string,\n args: string[] = [],\n options?: RunCommandOptions\n ): Promise<ExecutionResult> => {\n const start = Date.now();\n const { command: finalCmd, args: finalArgs, isBackground } = createBackgroundCommand(command, args, options);\n let shell = finalArgs.length ? `${finalCmd} ${finalArgs.join(' ')}` : finalCmd;\n\n let pid: number | undefined;\n\n if (isBackground) {\n shell = `(${shell}) & echo $!`;\n const r = await runExec(handle, shell);\n const m = r.stdout.trim().split(/\\s+/).pop();\n pid = m && /^\\d+$/.test(m) ? Number(m) : undefined;\n return {\n stdout: r.stdout,\n stderr: r.stderr,\n exitCode: r.exitCode,\n executionTime: Date.now() - start,\n sandboxId: handle.containerId,\n provider: PROVIDER,\n isBackground: true,\n ...(pid ? { pid } : {}),\n };\n }\n\n const { stdout, stderr, exitCode } = await runExec(handle, shell);\n\n return {\n stdout,\n stderr,\n exitCode,\n executionTime: Date.now() - start,\n sandboxId: handle.containerId,\n provider: PROVIDER,\n };\n },\n\n getInfo: async (handle: DockerSandboxHandle): Promise<SandboxInfo> => {\n const info = await handle.container.inspect();\n const state = info.State || {};\n return {\n id: handle.containerId,\n provider: PROVIDER,\n runtime: (info.Config?.Labels?.[LABEL_RUNTIME] as Runtime) || 'python',\n status: state.Running ? 'running' : 'stopped',\n createdAt: new Date(info.Created || handle.createdAt),\n timeout: 300000,\n metadata: {\n image: info.Config?.Image,\n name: info.Name,\n },\n };\n },\n\n getUrl: async (handle: DockerSandboxHandle, options: { port: number; protocol?: string }): Promise<string> => {\n const info = await handle.container.inspect();\n const protocol = options.protocol || 'http';\n const portKeyTcp = `${options.port}/tcp`;\n\n const ports = info.NetworkSettings?.Ports || {};\n const bindings = ports[portKeyTcp] || ports[`${options.port}/udp`] || [];\n\n let host = dockerHostNameFromEnv();\n let hostPort = String(options.port);\n\n if (Array.isArray(bindings) && bindings.length > 0) {\n hostPort = bindings[0].HostPort || hostPort;\n } else {\n const ip =\n info.NetworkSettings?.IPAddress ||\n Object.values(info.NetworkSettings?.Networks || {})[0]?.IPAddress;\n if (ip) host = ip;\n }\n\n return `${protocol}://${host}:${hostPort}`;\n },\n\n filesystem: {\n readFile: async (handle: DockerSandboxHandle, path: string): Promise<string> => {\n const cmd = `if [ -f ${JSON.stringify(path)} ]; then base64 ${JSON.stringify(path)} | tr -d '\\\\n'; else exit 1; fi`;\n const { stdout, exitCode, stderr } = await runExec(handle, cmd);\n if (exitCode !== 0) throw new Error(stderr || `File not found: ${path}`);\n return Buffer.from(stdout, 'base64').toString('utf8');\n },\n\n writeFile: async (handle: DockerSandboxHandle, path: string, content: string): Promise<void> => {\n const b64 = Buffer.from(content, 'utf8').toString('base64');\n const cmd = `mkdir -p $(dirname ${JSON.stringify(path)}) && echo \"${b64}\" | base64 -d > ${JSON.stringify(path)}`;\n const { exitCode, stderr } = await runExec(handle, cmd);\n if (exitCode !== 0) throw new Error(stderr || `Failed to write: ${path}`);\n },\n\n mkdir: async (handle: DockerSandboxHandle, path: string): Promise<void> => {\n const { exitCode, stderr } = await runExec(handle, `mkdir -p ${JSON.stringify(path)}`);\n if (exitCode !== 0) throw new Error(stderr || `Failed to mkdir: ${path}`);\n },\n\n readdir: async (handle: DockerSandboxHandle, path: string): Promise<FileEntry[]> => {\n const { stdout, exitCode, stderr } = await runExec(\n handle,\n `if [ -d ${JSON.stringify(path)} ]; then ls -la ${JSON.stringify(path)}; else exit 1; fi`\n );\n if (exitCode !== 0) throw new Error(stderr || `Not a directory: ${path}`);\n\n const lines = stdout.split('\\n').slice(1);\n const entries: FileEntry[] = [];\n for (const line of lines) {\n const parts = line.trim().split(/\\s+/);\n if (parts.length < 9) continue;\n const name = parts.slice(8).join(' ');\n if (name === '.' || name === '..') continue;\n const isDir = parts[0].startsWith('d');\n const size = Number(parts[4]) || 0;\n entries.push({\n name,\n path: `${path.replace(/\\/$/, '')}/${name}`,\n isDirectory: isDir,\n size,\n lastModified: new Date(),\n });\n }\n return entries;\n },\n\n exists: async (handle: DockerSandboxHandle, path: string): Promise<boolean> => {\n const { exitCode } = await runExec(handle, `test -e ${JSON.stringify(path)}`);\n return exitCode === 0;\n },\n\n remove: async (handle: DockerSandboxHandle, path: string): Promise<void> => {\n const { exitCode, stderr } = await runExec(handle, `rm -rf ${JSON.stringify(path)}`);\n if (exitCode !== 0) throw new Error(stderr || `Failed to remove: ${path}`);\n },\n },\n\n getInstance: (handle: DockerSandboxHandle): DockerSandboxHandle => handle,\n },\n },\n});\n\n// ---------------------- convenience creator (optional) ----------------------\n\nexport function createDockerCompute(config: DockerConfig): CreateDockerCompute {\n const provider = docker(config);\n return {\n sandbox: {\n create: async (options) => {\n const sb = await provider.sandbox.create(options);\n return {\n ...sb,\n getInstance: (): DockerSandboxHandle => sb.getInstance() as DockerSandboxHandle,\n } as unknown as DockerSandboxAPI;\n },\n },\n };\n}\n","import type Docker from 'dockerode';\nimport type {\n DockerOptions,\n Container,\n ContainerCreateOptions,\n ContainerStartOptions,\n ContainerInspectInfo,\n ContainerInfo,\n Exec,\n ImageInfo,\n ImageBuildOptions,\n Network,\n} from 'dockerode';\n\nimport type {\n Runtime,\n FileEntry,\n ExecutionResult,\n RunCommandOptions,\n CreateSandboxOptions,\n SandboxInfo,\n} from 'computesdk';\n\n/** When the provider should clean up containers it created */\nexport type CleanupPolicy = 'always' | 'onSuccess' | 'never';\n\n/** Image pull strategy */\nexport type PullPolicy = 'always' | 'ifNotPresent' | 'never';\n\n/** Connection to the Docker daemon (exactly what dockerode accepts) */\nexport type DockerConnection = DockerOptions;\n\n/** Auth when pulling private images (Engine API AuthConfig shape) */\nexport interface RegistryAuth {\n username?: string;\n password?: string;\n serveraddress?: string;\n identitytoken?: string;\n registrytoken?: string;\n}\n\n/** Default image & pull policy for sandboxes */\nexport interface DockerImage {\n name: string; // e.g. 'python:3.11-slim'\n pullPolicy?: PullPolicy; // default: 'ifNotPresent'\n auth?: RegistryAuth;\n}\n\n/** Convenience shape for port bindings */\nexport type PortBindings = Record<\n `${number}/${'tcp' | 'udp'}`,\n Array<{ hostPort?: number; hostIP?: string }>\n>;\n\n/** Subset of HostConfig resources & knobs that are commonly used */\nexport interface ResourceLimits {\n cpuShares?: number;\n cpuQuota?: number;\n cpuPeriod?: number;\n nanoCPUs?: number;\n memory?: number;\n memorySwap?: number;\n pidsLimit?: number;\n}\n\n/** Declarative container defaults that we’ll translate into dockerode create options */\nexport interface ContainerDefaults {\n user?: string;\n workdir?: string;\n env?: Record<string, string>;\n binds?: string[];\n ports?: PortBindings;\n networkMode?: string;\n privileged?: boolean;\n capabilities?: { add?: string[]; drop?: string[] };\n gpus?: 'all' | number | string;\n resources?: ResourceLimits;\n logDriver?: string;\n logOpts?: Record<string, string>;\n autoRemove?: boolean;\n tty?: boolean;\n openStdin?: boolean;\n}\n\n/** Provider-level configuration for Docker */\nexport interface DockerConfig {\n connection?: DockerConnection;\n runtime?: Runtime; // 'python' | 'node'\n timeout?: number;\n image: DockerImage;\n container?: ContainerDefaults;\n createOptions?: ContainerCreateOptions;\n startOptions?: ContainerStartOptions;\n cleanup?: CleanupPolicy;\n streamLogs?: boolean;\n}\n\n/** What we keep for each running sandbox */\nexport interface DockerSandboxHandle {\n docker: Docker;\n container: Container;\n containerId: string;\n image: string;\n createdAt: Date;\n}\n\n/** URL options for port-forwarded services */\nexport interface DockerUrlOptions {\n port: number;\n protocol?: 'http' | 'https';\n host?: string;\n}\n\n/** Optional FS helpers you might expose */\nexport interface DockerSandboxFileSystem {\n readFile(path: string): Promise<string>;\n writeFile(path: string, content: string): Promise<void>;\n mkdir(path: string): Promise<void>;\n readdir(path: string): Promise<FileEntry[]>;\n exists(path: string): Promise<boolean>;\n remove(path: string): Promise<void>;\n}\n\n/** Strongly-typed sandbox API shape */\nexport interface DockerSandboxAPI {\n sandboxId: string;\n provider: 'docker';\n runCode(code: string, runtime?: Runtime): Promise<ExecutionResult>;\n runCommand(command: string, args?: string[], options?: RunCommandOptions): Promise<ExecutionResult>;\n getInfo(): Promise<SandboxInfo>;\n getUrl(options: DockerUrlOptions): Promise<string>;\n getProvider(): any;\n getInstance(): DockerSandboxHandle;\n kill(): Promise<void>;\n destroy(): Promise<void>;\n filesystem: DockerSandboxFileSystem;\n}\n\n/** Factory return shape mirroring your createE2BCompute helper */\nexport interface CreateDockerCompute {\n sandbox: {\n create(options?: CreateSandboxOptions): Promise<DockerSandboxAPI>;\n };\n}\n\n/** Sensible, safe defaults */\nexport const defaultDockerConfig: DockerConfig = {\n connection: {\n // Let dockerode fall back to DOCKER_HOST or /var/run/docker.sock\n timeout: 60_000,\n version: 'v1.43',\n },\n runtime: 'python',\n timeout: 300_000, // 5 minutes\n image: {\n name: 'python:3.11-slim',\n pullPolicy: 'ifNotPresent',\n },\n container: {\n workdir: '/workspace',\n env: {},\n autoRemove: false, // Keep container around for exec/FS/background\n tty: false, // Non-tty so we can demux stdout/stderr\n openStdin: false,\n resources: { memory: 512 * 1024 * 1024 },\n },\n cleanup: 'always',\n streamLogs: false,\n};\n\n/** Re-exports for convenience */\nexport type {\n Docker,\n Container,\n Exec,\n ContainerCreateOptions,\n ContainerStartOptions,\n ContainerInspectInfo,\n ContainerInfo,\n ImageInfo,\n ImageBuildOptions,\n Network,\n};\n"],"mappings":"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","names":["docker","Docker","container"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types/types.ts"],"sourcesContent":["import Docker from 'dockerode';\nimport { PassThrough } from 'stream';\nimport { createProvider } from 'computesdk';\nimport type {\n Runtime,\n CodeResult,\n CommandResult,\n RunCommandOptions,\n CreateSandboxOptions,\n SandboxInfo,\n FileEntry,\n} from 'computesdk';\n\nimport { defaultDockerConfig } from './types/types';\nimport type {\n DockerConfig,\n DockerSandboxHandle,\n DockerImage,\n PortBindings,\n} from './types/types';\n\nconst PROVIDER = 'docker' as const;\nconst LABEL_KEY = 'com.computesdk.sandbox';\nconst LABEL_RUNTIME = 'com.computesdk.runtime';\nconst KEEPALIVE_CMD = ['/bin/sh', '-c', 'while :; do sleep 3600; done'];\n\nfunction pick<T>(val: T | undefined, fallback: T): T {\n return typeof val === 'undefined' ? fallback : val;\n}\n\nasync function ensureImage(docker: Docker, image: DockerImage): Promise<void> {\n const policy = image.pullPolicy ?? 'ifNotPresent';\n if (policy === 'never') return;\n\n const images = await docker.listImages();\n const hasImage = images.some(img => (img.RepoTags || []).includes(image.name));\n\n if (policy === 'always' || (policy === 'ifNotPresent' && !hasImage)) {\n await new Promise<void>((resolve, reject) => {\n const cb = (err: any, stream?: NodeJS.ReadableStream) => {\n if (err) return reject(err);\n if (!stream) return reject(new Error('docker.pull returned no stream'));\n (docker as any).modem.followProgress(stream, (err2: any) => (err2 ? reject(err2) : resolve()));\n };\n if (image.auth) docker.pull(image.name, { authconfig: image.auth } as any, cb);\n else docker.pull(image.name, cb);\n });\n }\n}\n\nasync function waitUntilRunning(container: Docker.Container, timeoutMs = 4000) {\n const start = Date.now();\n try {\n const s = await container.inspect();\n if (s.State?.Running) return;\n } catch { /* ignore */ }\n\n while (Date.now() - start < timeoutMs) {\n const s = await container.inspect();\n if (s.State?.Running) return;\n await new Promise(r => setTimeout(r, 100));\n }\n throw new Error('Container did not reach Running state in time');\n}\n\nasync function runExec(\n handle: DockerSandboxHandle,\n shellCommand: string,\n attachTTY = false\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n await waitUntilRunning(handle.container);\n\n const exec = await handle.container.exec({\n Cmd: ['/bin/sh', '-c', shellCommand],\n AttachStdout: true,\n AttachStderr: true,\n Tty: attachTTY,\n });\n\n const stream = (await exec.start({ hijack: true, stdin: false })) as NodeJS.ReadableStream;\n\n let stdout = '';\n let stderr = '';\n\n await new Promise<void>((resolve, reject) => {\n if (attachTTY) {\n stream.on('data', (chunk: Buffer) => (stdout += chunk.toString('utf8')));\n stream.on('end', resolve);\n stream.on('error', reject);\n return;\n }\n const out = new PassThrough();\n const err = new PassThrough();\n out.on('data', (c: Buffer) => (stdout += c.toString('utf8')));\n err.on('data', (c: Buffer) => (stderr += c.toString('utf8')));\n (handle.docker as any).modem.demuxStream(stream as any, out as any, err as any);\n stream.on('end', resolve);\n stream.on('error', reject);\n });\n\n const inspect = await exec.inspect();\n const exitCode = inspect.ExitCode ?? 0;\n return { stdout, stderr, exitCode };\n}\n\nfunction toHostBindings(ports?: PortBindings) {\n if (!ports) return undefined;\n const exposed: Record<string, {}> = {};\n const bindings: Record<string, Array<{ HostPort?: string; HostIp?: string }>> = {};\n for (const key of Object.keys(ports)) {\n exposed[key] = {};\n bindings[key] = (ports as any)[key].map((p: any) => ({\n HostPort: p.hostPort ? String(p.hostPort) : undefined,\n HostIp: p.hostIP,\n }));\n }\n return { ExposedPorts: exposed, PortBindings: bindings };\n}\n\nfunction dockerHostNameFromEnv(): string {\n const hostEnv = process.env.DOCKER_HOST;\n if (hostEnv?.startsWith('tcp://')) {\n try {\n const u = new URL(hostEnv);\n return u.hostname || 'localhost';\n } catch { /* noop */ }\n }\n return 'localhost';\n}\n\nfunction pickImageForRuntime(runtime: Runtime, configured?: DockerImage): DockerImage {\n // If user supplied an image that already matches, use it. Otherwise pick a sensible default.\n if (configured?.name) {\n if (runtime === 'python' && /python|conda|pypy/i.test(configured.name)) return configured;\n if (runtime === 'node' && /node/i.test(configured.name)) return configured;\n }\n return {\n name: runtime === 'python' ? 'python:3.11-slim' : 'node:20-alpine',\n pullPolicy: configured?.pullPolicy ?? 'ifNotPresent',\n auth: configured?.auth,\n };\n}\n\nexport const docker = createProvider<DockerSandboxHandle, DockerConfig>({\n name: PROVIDER,\n methods: {\n sandbox: {\n create: async (config: DockerConfig, options?: CreateSandboxOptions) => {\n const cfg: DockerConfig = { ...defaultDockerConfig, ...config };\n const effectiveRuntime: Runtime = (options?.runtime ?? cfg.runtime ?? 'python') as Runtime;\n\n if (effectiveRuntime !== 'python' && effectiveRuntime !== 'node') {\n throw new Error(`Docker provider supports only 'python' or 'node'. Received: ${String(effectiveRuntime)}`);\n }\n\n const docker = new Docker(cfg.connection as any);\n\n // Reattach?\n if (options?.sandboxId) {\n try {\n const container = docker.getContainer(options.sandboxId);\n const info = await container.inspect();\n return {\n sandbox: <DockerSandboxHandle>{\n docker,\n container,\n containerId: options.sandboxId,\n image: info.Config?.Image ?? cfg.image.name,\n createdAt: new Date(info.Created || Date.now()),\n },\n sandboxId: options.sandboxId,\n };\n } catch (err) {\n // Failed to reattach to existing container; will create a new one.\n console.warn(`Could not reattach to Docker container with ID ${options.sandboxId}:`, err);\n }\n }\n\n // Choose image based on runtime if needed\n const chosenImage = pickImageForRuntime(effectiveRuntime, cfg.image);\n await ensureImage(docker, chosenImage);\n\n // Build container create options\n const hb = toHostBindings(cfg.container?.ports);\n const createOptions = {\n Image: chosenImage.name,\n Tty: pick(cfg.container?.tty, false),\n OpenStdin: pick(cfg.container?.openStdin, false),\n Labels: { [LABEL_KEY]: 'true', [LABEL_RUNTIME]: effectiveRuntime }, // <-- store runtime per sandbox\n WorkingDir: cfg.container?.workdir,\n Env: cfg.container?.env\n ? Object.entries(cfg.container.env).map(([k, v]) => `${k}=${v}`)\n : undefined,\n Cmd: KEEPALIVE_CMD, // keep container alive\n HostConfig: {\n AutoRemove: cfg.container?.autoRemove ?? false, // keep around for exec/FS ops\n Binds: cfg.container?.binds,\n NetworkMode: cfg.container?.networkMode,\n Privileged: cfg.container?.privileged,\n CapAdd: cfg.container?.capabilities?.add,\n CapDrop: cfg.container?.capabilities?.drop,\n LogConfig: cfg.container?.logDriver\n ? { Type: cfg.container.logDriver, Config: cfg.container.logOpts || {} }\n : undefined,\n Resources: cfg.container?.resources,\n DeviceRequests: cfg.container?.gpus\n ? [\n {\n Driver: 'nvidia',\n Count:\n cfg.container.gpus === 'all'\n ? -1\n : typeof cfg.container.gpus === 'number'\n ? cfg.container.gpus\n : 1,\n DeviceIDs:\n typeof cfg.container.gpus === 'string' && cfg.container.gpus !== 'all'\n ? [String(cfg.container.gpus)]\n : undefined,\n Capabilities: [['gpu']],\n },\n ]\n : undefined,\n ...(hb ? { PortBindings: hb.PortBindings } : {}),\n },\n ...(hb ? { ExposedPorts: hb.ExposedPorts } : {}),\n ...(cfg.createOptions || {}),\n } as import('dockerode').ContainerCreateOptions;\n\n const container = await docker.createContainer(createOptions);\n await container.start(cfg.startOptions || {});\n await waitUntilRunning(container);\n\n const inspect = await container.inspect();\n const handle: DockerSandboxHandle = {\n docker,\n container,\n containerId: inspect.Id,\n image: inspect.Config?.Image ?? chosenImage.name,\n createdAt: new Date(inspect.Created || Date.now()),\n };\n\n return { sandbox: handle, sandboxId: handle.containerId };\n },\n\n getById: async (config: DockerConfig, sandboxId: string) => {\n const docker = new Docker((config || defaultDockerConfig).connection as any);\n try {\n const container = docker.getContainer(sandboxId);\n const info = await container.inspect();\n return {\n sandbox: <DockerSandboxHandle>{\n docker,\n container,\n containerId: sandboxId,\n image: info.Config?.Image ?? '',\n createdAt: new Date(info.Created || Date.now()),\n },\n sandboxId,\n };\n } catch {\n return null;\n }\n },\n\n list: async (config: DockerConfig) => {\n const docker = new Docker((config || defaultDockerConfig).connection as any);\n try {\n const items = await docker.listContainers({\n all: true,\n filters: { label: [LABEL_KEY] } as any,\n });\n return items.map(ci => ({\n sandbox: <DockerSandboxHandle>{\n docker,\n container: docker.getContainer(ci.Id),\n containerId: ci.Id,\n image: ci.Image,\n createdAt: new Date((ci as any).Created * 1000),\n },\n sandboxId: ci.Id,\n }));\n } catch {\n return [];\n }\n },\n\n destroy: async (config: DockerConfig, sandboxId: string) => {\n const docker = new Docker((config || defaultDockerConfig).connection as any);\n try {\n const c = docker.getContainer(sandboxId);\n try { await c.stop({ t: 5 } as any); } catch { /* stopped */ }\n await c.remove({ force: true });\n } catch {\n // ok if already gone\n }\n },\n\n runCode: async (handle: DockerSandboxHandle, code: string, runtime?: Runtime): Promise<CodeResult> => {\n const start = Date.now();\n\n // Resolve runtime: param → label → error\n let rt: Runtime | undefined = runtime;\n if (!rt) {\n const info = await handle.container.inspect();\n rt = (info.Config?.Labels?.[LABEL_RUNTIME] as Runtime) || undefined;\n }\n if (rt !== 'python' && rt !== 'node') {\n throw new Error(`Docker runtime must be 'python' or 'node'. Pass runtime in config or as a parameter.`);\n }\n\n // Write to file, then execute. This is robust on Alpine/Debian.\n const tmpFile = rt === 'python' ? '/tmp/compute_code.py' : '/tmp/compute_code.js';\n const b64 = Buffer.from(code, 'utf8').toString('base64');\n const makeAndRun =\n `printf '%s' \"${b64}\" | base64 -d > ${tmpFile} && ` +\n (rt === 'python' ? `python3 ${tmpFile}` : `node ${tmpFile}`);\n\n const { stdout, stderr, exitCode } = await runExec(handle, makeAndRun);\n\n if (exitCode !== 0 && stderr) {\n // Throw ONLY on syntax errors (SDK contract)\n const isSyntax =\n stderr.includes('SyntaxError') ||\n stderr.includes('invalid syntax') ||\n stderr.includes('Unexpected token') ||\n stderr.includes('Unexpected identifier');\n if (isSyntax) {\n const last = stderr.trim().split('\\n').slice(-1)[0] || 'Syntax error';\n throw new Error(`Syntax error: ${last}`);\n }\n }\n\n return {\n output: stdout + stderr,\n exitCode,\n language: rt,\n };\n },\n\n runCommand: async (\n handle: DockerSandboxHandle,\n command: string,\n args: string[] = []\n ): Promise<CommandResult> => {\n const start = Date.now();\n const shell = args.length ? `${command} ${args.join(' ')}` : command;\n\n const { stdout, stderr, exitCode } = await runExec(handle, shell);\n\n return {\n stdout,\n stderr,\n exitCode,\n durationMs: Date.now() - start,\n };\n },\n\n getInfo: async (handle: DockerSandboxHandle): Promise<SandboxInfo> => {\n const info = await handle.container.inspect();\n const state = info.State || {};\n return {\n id: handle.containerId,\n provider: PROVIDER,\n runtime: (info.Config?.Labels?.[LABEL_RUNTIME] as Runtime) || 'python',\n status: state.Running ? 'running' : 'stopped',\n createdAt: new Date(info.Created || handle.createdAt),\n timeout: 300000,\n metadata: {\n image: info.Config?.Image,\n name: info.Name,\n },\n };\n },\n\n getUrl: async (handle: DockerSandboxHandle, options: { port: number; protocol?: string }): Promise<string> => {\n const info = await handle.container.inspect();\n const protocol = options.protocol || 'http';\n const portKeyTcp = `${options.port}/tcp`;\n\n const ports = info.NetworkSettings?.Ports || {};\n const bindings = ports[portKeyTcp] || ports[`${options.port}/udp`] || [];\n\n let host = dockerHostNameFromEnv();\n let hostPort = String(options.port);\n\n if (Array.isArray(bindings) && bindings.length > 0) {\n hostPort = bindings[0].HostPort || hostPort;\n } else {\n const ip =\n info.NetworkSettings?.IPAddress ||\n Object.values(info.NetworkSettings?.Networks || {})[0]?.IPAddress;\n if (ip) host = ip;\n }\n\n return `${protocol}://${host}:${hostPort}`;\n },\n\n filesystem: {\n readFile: async (handle: DockerSandboxHandle, path: string): Promise<string> => {\n const cmd = `if [ -f ${JSON.stringify(path)} ]; then base64 ${JSON.stringify(path)} | tr -d '\\\\n'; else exit 1; fi`;\n const { stdout, exitCode, stderr } = await runExec(handle, cmd);\n if (exitCode !== 0) throw new Error(stderr || `File not found: ${path}`);\n return Buffer.from(stdout, 'base64').toString('utf8');\n },\n\n writeFile: async (handle: DockerSandboxHandle, path: string, content: string): Promise<void> => {\n const b64 = Buffer.from(content, 'utf8').toString('base64');\n const cmd = `mkdir -p $(dirname ${JSON.stringify(path)}) && echo \"${b64}\" | base64 -d > ${JSON.stringify(path)}`;\n const { exitCode, stderr } = await runExec(handle, cmd);\n if (exitCode !== 0) throw new Error(stderr || `Failed to write: ${path}`);\n },\n\n mkdir: async (handle: DockerSandboxHandle, path: string): Promise<void> => {\n const { exitCode, stderr } = await runExec(handle, `mkdir -p ${JSON.stringify(path)}`);\n if (exitCode !== 0) throw new Error(stderr || `Failed to mkdir: ${path}`);\n },\n\n readdir: async (handle: DockerSandboxHandle, path: string): Promise<FileEntry[]> => {\n const { stdout, exitCode, stderr } = await runExec(\n handle,\n `if [ -d ${JSON.stringify(path)} ]; then ls -la ${JSON.stringify(path)}; else exit 1; fi`\n );\n if (exitCode !== 0) throw new Error(stderr || `Not a directory: ${path}`);\n\n const lines = stdout.split('\\n').slice(1);\n const entries: FileEntry[] = [];\n for (const line of lines) {\n const parts = line.trim().split(/\\s+/);\n if (parts.length < 9) continue;\n const name = parts.slice(8).join(' ');\n if (name === '.' || name === '..') continue;\n const isDir = parts[0].startsWith('d');\n const size = Number(parts[4]) || 0;\n entries.push({\n name,\n path: `${path.replace(/\\/$/, '')}/${name}`,\n isDirectory: isDir,\n size,\n lastModified: new Date(),\n });\n }\n return entries;\n },\n\n exists: async (handle: DockerSandboxHandle, path: string): Promise<boolean> => {\n const { exitCode } = await runExec(handle, `test -e ${JSON.stringify(path)}`);\n return exitCode === 0;\n },\n\n remove: async (handle: DockerSandboxHandle, path: string): Promise<void> => {\n const { exitCode, stderr } = await runExec(handle, `rm -rf ${JSON.stringify(path)}`);\n if (exitCode !== 0) throw new Error(stderr || `Failed to remove: ${path}`);\n },\n },\n\n getInstance: (handle: DockerSandboxHandle): DockerSandboxHandle => handle,\n },\n },\n});\n\n","import type Docker from 'dockerode';\nimport type {\n DockerOptions,\n Container,\n ContainerCreateOptions,\n ContainerStartOptions,\n ContainerInspectInfo,\n ContainerInfo,\n Exec,\n ImageInfo,\n ImageBuildOptions,\n Network,\n} from 'dockerode';\n\nimport type {\n Runtime,\n FileEntry,\n RunCommandOptions,\n CreateSandboxOptions,\n SandboxInfo,\n} from 'computesdk';\n\n/** When the provider should clean up containers it created */\nexport type CleanupPolicy = 'always' | 'onSuccess' | 'never';\n\n/** Image pull strategy */\nexport type PullPolicy = 'always' | 'ifNotPresent' | 'never';\n\n/** Connection to the Docker daemon (exactly what dockerode accepts) */\nexport type DockerConnection = DockerOptions;\n\n/** Auth when pulling private images (Engine API AuthConfig shape) */\nexport interface RegistryAuth {\n username?: string;\n password?: string;\n serveraddress?: string;\n identitytoken?: string;\n registrytoken?: string;\n}\n\n/** Default image & pull policy for sandboxes */\nexport interface DockerImage {\n name: string; // e.g. 'python:3.11-slim'\n pullPolicy?: PullPolicy; // default: 'ifNotPresent'\n auth?: RegistryAuth;\n}\n\n/** Convenience shape for port bindings */\nexport type PortBindings = Record<\n `${number}/${'tcp' | 'udp'}`,\n Array<{ hostPort?: number; hostIP?: string }>\n>;\n\n/** Subset of HostConfig resources & knobs that are commonly used */\nexport interface ResourceLimits {\n cpuShares?: number;\n cpuQuota?: number;\n cpuPeriod?: number;\n nanoCPUs?: number;\n memory?: number;\n memorySwap?: number;\n pidsLimit?: number;\n}\n\n/** Declarative container defaults that we’ll translate into dockerode create options */\nexport interface ContainerDefaults {\n user?: string;\n workdir?: string;\n env?: Record<string, string>;\n binds?: string[];\n ports?: PortBindings;\n networkMode?: string;\n privileged?: boolean;\n capabilities?: { add?: string[]; drop?: string[] };\n gpus?: 'all' | number | string;\n resources?: ResourceLimits;\n logDriver?: string;\n logOpts?: Record<string, string>;\n autoRemove?: boolean;\n tty?: boolean;\n openStdin?: boolean;\n}\n\n/** Provider-level configuration for Docker */\nexport interface DockerConfig {\n connection?: DockerConnection;\n runtime?: Runtime; // 'python' | 'node'\n timeout?: number;\n image: DockerImage;\n container?: ContainerDefaults;\n createOptions?: ContainerCreateOptions;\n startOptions?: ContainerStartOptions;\n cleanup?: CleanupPolicy;\n streamLogs?: boolean;\n}\n\n/** What we keep for each running sandbox */\nexport interface DockerSandboxHandle {\n docker: Docker;\n container: Container;\n containerId: string;\n image: string;\n createdAt: Date;\n}\n\n/** URL options for port-forwarded services */\nexport interface DockerUrlOptions {\n port: number;\n protocol?: 'http' | 'https';\n host?: string;\n}\n\n/** Optional FS helpers you might expose */\nexport interface DockerSandboxFileSystem {\n readFile(path: string): Promise<string>;\n writeFile(path: string, content: string): Promise<void>;\n mkdir(path: string): Promise<void>;\n readdir(path: string): Promise<FileEntry[]>;\n exists(path: string): Promise<boolean>;\n remove(path: string): Promise<void>;\n}\n\n/** Sensible, safe defaults */\nexport const defaultDockerConfig: DockerConfig = {\n connection: {\n // Let dockerode fall back to DOCKER_HOST or /var/run/docker.sock\n timeout: 60_000,\n version: 'v1.43',\n },\n runtime: 'python',\n timeout: 300_000, // 5 minutes\n image: {\n name: 'python:3.11-slim',\n pullPolicy: 'ifNotPresent',\n },\n container: {\n workdir: '/workspace',\n env: {},\n autoRemove: false, // Keep container around for exec/FS/background\n tty: false, // Non-tty so we can demux stdout/stderr\n openStdin: false,\n resources: { memory: 512 * 1024 * 1024 },\n },\n cleanup: 'always',\n streamLogs: false,\n};\n\n/** Re-exports for convenience */\nexport type {\n Docker,\n Container,\n Exec,\n ContainerCreateOptions,\n ContainerStartOptions,\n ContainerInspectInfo,\n ContainerInfo,\n ImageInfo,\n ImageBuildOptions,\n Network,\n};\n"],"mappings":"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","names":["docker","Docker","container"]}
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/index.ts
2
2
  import Docker from "dockerode";
3
3
  import { PassThrough } from "stream";
4
- import { createProvider, createBackgroundCommand } from "computesdk";
4
+ import { createProvider } from "computesdk";
5
5
 
6
6
  // src/types/types.ts
7
7
  var defaultDockerConfig = {
@@ -287,43 +287,20 @@ var docker = createProvider({
287
287
  }
288
288
  }
289
289
  return {
290
- stdout,
291
- stderr,
290
+ output: stdout + stderr,
292
291
  exitCode,
293
- executionTime: Date.now() - start,
294
- sandboxId: handle.containerId,
295
- provider: PROVIDER
292
+ language: rt
296
293
  };
297
294
  },
298
- runCommand: async (handle, command, args = [], options) => {
295
+ runCommand: async (handle, command, args = []) => {
299
296
  const start = Date.now();
300
- const { command: finalCmd, args: finalArgs, isBackground } = createBackgroundCommand(command, args, options);
301
- let shell = finalArgs.length ? `${finalCmd} ${finalArgs.join(" ")}` : finalCmd;
302
- let pid;
303
- if (isBackground) {
304
- shell = `(${shell}) & echo $!`;
305
- const r = await runExec(handle, shell);
306
- const m = r.stdout.trim().split(/\s+/).pop();
307
- pid = m && /^\d+$/.test(m) ? Number(m) : void 0;
308
- return {
309
- stdout: r.stdout,
310
- stderr: r.stderr,
311
- exitCode: r.exitCode,
312
- executionTime: Date.now() - start,
313
- sandboxId: handle.containerId,
314
- provider: PROVIDER,
315
- isBackground: true,
316
- ...pid ? { pid } : {}
317
- };
318
- }
297
+ const shell = args.length ? `${command} ${args.join(" ")}` : command;
319
298
  const { stdout, stderr, exitCode } = await runExec(handle, shell);
320
299
  return {
321
300
  stdout,
322
301
  stderr,
323
302
  exitCode,
324
- executionTime: Date.now() - start,
325
- sandboxId: handle.containerId,
326
- provider: PROVIDER
303
+ durationMs: Date.now() - start
327
304
  };
328
305
  },
329
306
  getInfo: async (handle) => {
@@ -413,22 +390,7 @@ var docker = createProvider({
413
390
  }
414
391
  }
415
392
  });
416
- function createDockerCompute(config) {
417
- const provider = docker(config);
418
- return {
419
- sandbox: {
420
- create: async (options) => {
421
- const sb = await provider.sandbox.create(options);
422
- return {
423
- ...sb,
424
- getInstance: () => sb.getInstance()
425
- };
426
- }
427
- }
428
- };
429
- }
430
393
  export {
431
- createDockerCompute,
432
394
  docker
433
395
  };
434
396
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types/types.ts"],"sourcesContent":["import Docker from 'dockerode';\nimport { PassThrough } from 'stream';\nimport { createProvider, createBackgroundCommand } from 'computesdk';\nimport type {\n Runtime,\n ExecutionResult,\n RunCommandOptions,\n CreateSandboxOptions,\n SandboxInfo,\n FileEntry,\n} from 'computesdk';\n\nimport { defaultDockerConfig } from './types/types';\nimport type {\n DockerConfig,\n DockerSandboxHandle,\n DockerSandboxAPI,\n CreateDockerCompute,\n DockerImage,\n PortBindings,\n} from './types/types';\n\nconst PROVIDER = 'docker' as const;\nconst LABEL_KEY = 'com.computesdk.sandbox';\nconst LABEL_RUNTIME = 'com.computesdk.runtime';\nconst KEEPALIVE_CMD = ['/bin/sh', '-c', 'while :; do sleep 3600; done'];\n\nfunction pick<T>(val: T | undefined, fallback: T): T {\n return typeof val === 'undefined' ? fallback : val;\n}\n\nasync function ensureImage(docker: Docker, image: DockerImage): Promise<void> {\n const policy = image.pullPolicy ?? 'ifNotPresent';\n if (policy === 'never') return;\n\n const images = await docker.listImages();\n const hasImage = images.some(img => (img.RepoTags || []).includes(image.name));\n\n if (policy === 'always' || (policy === 'ifNotPresent' && !hasImage)) {\n await new Promise<void>((resolve, reject) => {\n const cb = (err: any, stream?: NodeJS.ReadableStream) => {\n if (err) return reject(err);\n if (!stream) return reject(new Error('docker.pull returned no stream'));\n (docker as any).modem.followProgress(stream, (err2: any) => (err2 ? reject(err2) : resolve()));\n };\n if (image.auth) docker.pull(image.name, { authconfig: image.auth } as any, cb);\n else docker.pull(image.name, cb);\n });\n }\n}\n\nasync function waitUntilRunning(container: Docker.Container, timeoutMs = 4000) {\n const start = Date.now();\n try {\n const s = await container.inspect();\n if (s.State?.Running) return;\n } catch { /* ignore */ }\n\n while (Date.now() - start < timeoutMs) {\n const s = await container.inspect();\n if (s.State?.Running) return;\n await new Promise(r => setTimeout(r, 100));\n }\n throw new Error('Container did not reach Running state in time');\n}\n\nasync function runExec(\n handle: DockerSandboxHandle,\n shellCommand: string,\n attachTTY = false\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n await waitUntilRunning(handle.container);\n\n const exec = await handle.container.exec({\n Cmd: ['/bin/sh', '-c', shellCommand],\n AttachStdout: true,\n AttachStderr: true,\n Tty: attachTTY,\n });\n\n const stream = (await exec.start({ hijack: true, stdin: false })) as NodeJS.ReadableStream;\n\n let stdout = '';\n let stderr = '';\n\n await new Promise<void>((resolve, reject) => {\n if (attachTTY) {\n stream.on('data', (chunk: Buffer) => (stdout += chunk.toString('utf8')));\n stream.on('end', resolve);\n stream.on('error', reject);\n return;\n }\n const out = new PassThrough();\n const err = new PassThrough();\n out.on('data', (c: Buffer) => (stdout += c.toString('utf8')));\n err.on('data', (c: Buffer) => (stderr += c.toString('utf8')));\n (handle.docker as any).modem.demuxStream(stream as any, out as any, err as any);\n stream.on('end', resolve);\n stream.on('error', reject);\n });\n\n const inspect = await exec.inspect();\n const exitCode = inspect.ExitCode ?? 0;\n return { stdout, stderr, exitCode };\n}\n\nfunction toHostBindings(ports?: PortBindings) {\n if (!ports) return undefined;\n const exposed: Record<string, {}> = {};\n const bindings: Record<string, Array<{ HostPort?: string; HostIp?: string }>> = {};\n for (const key of Object.keys(ports)) {\n exposed[key] = {};\n bindings[key] = (ports as any)[key].map((p: any) => ({\n HostPort: p.hostPort ? String(p.hostPort) : undefined,\n HostIp: p.hostIP,\n }));\n }\n return { ExposedPorts: exposed, PortBindings: bindings };\n}\n\nfunction dockerHostNameFromEnv(): string {\n const hostEnv = process.env.DOCKER_HOST;\n if (hostEnv?.startsWith('tcp://')) {\n try {\n const u = new URL(hostEnv);\n return u.hostname || 'localhost';\n } catch { /* noop */ }\n }\n return 'localhost';\n}\n\nfunction pickImageForRuntime(runtime: Runtime, configured?: DockerImage): DockerImage {\n // If user supplied an image that already matches, use it. Otherwise pick a sensible default.\n if (configured?.name) {\n if (runtime === 'python' && /python|conda|pypy/i.test(configured.name)) return configured;\n if (runtime === 'node' && /node/i.test(configured.name)) return configured;\n }\n return {\n name: runtime === 'python' ? 'python:3.11-slim' : 'node:20-alpine',\n pullPolicy: configured?.pullPolicy ?? 'ifNotPresent',\n auth: configured?.auth,\n };\n}\n\nexport const docker = createProvider<DockerSandboxHandle, DockerConfig>({\n name: PROVIDER,\n methods: {\n sandbox: {\n create: async (config: DockerConfig, options?: CreateSandboxOptions) => {\n const cfg: DockerConfig = { ...defaultDockerConfig, ...config };\n const effectiveRuntime: Runtime = (options?.runtime ?? cfg.runtime ?? 'python') as Runtime;\n\n if (effectiveRuntime !== 'python' && effectiveRuntime !== 'node') {\n throw new Error(`Docker provider supports only 'python' or 'node'. Received: ${String(effectiveRuntime)}`);\n }\n\n const docker = new Docker(cfg.connection as any);\n\n // Reattach?\n if (options?.sandboxId) {\n try {\n const container = docker.getContainer(options.sandboxId);\n const info = await container.inspect();\n return {\n sandbox: <DockerSandboxHandle>{\n docker,\n container,\n containerId: options.sandboxId,\n image: info.Config?.Image ?? cfg.image.name,\n createdAt: new Date(info.Created || Date.now()),\n },\n sandboxId: options.sandboxId,\n };\n } catch (err) {\n // Failed to reattach to existing container; will create a new one.\n console.warn(`Could not reattach to Docker container with ID ${options.sandboxId}:`, err);\n }\n }\n\n // Choose image based on runtime if needed\n const chosenImage = pickImageForRuntime(effectiveRuntime, cfg.image);\n await ensureImage(docker, chosenImage);\n\n // Build container create options\n const hb = toHostBindings(cfg.container?.ports);\n const createOptions = {\n Image: chosenImage.name,\n Tty: pick(cfg.container?.tty, false),\n OpenStdin: pick(cfg.container?.openStdin, false),\n Labels: { [LABEL_KEY]: 'true', [LABEL_RUNTIME]: effectiveRuntime }, // <-- store runtime per sandbox\n WorkingDir: cfg.container?.workdir,\n Env: cfg.container?.env\n ? Object.entries(cfg.container.env).map(([k, v]) => `${k}=${v}`)\n : undefined,\n Cmd: KEEPALIVE_CMD, // keep container alive\n HostConfig: {\n AutoRemove: cfg.container?.autoRemove ?? false, // keep around for exec/FS ops\n Binds: cfg.container?.binds,\n NetworkMode: cfg.container?.networkMode,\n Privileged: cfg.container?.privileged,\n CapAdd: cfg.container?.capabilities?.add,\n CapDrop: cfg.container?.capabilities?.drop,\n LogConfig: cfg.container?.logDriver\n ? { Type: cfg.container.logDriver, Config: cfg.container.logOpts || {} }\n : undefined,\n Resources: cfg.container?.resources,\n DeviceRequests: cfg.container?.gpus\n ? [\n {\n Driver: 'nvidia',\n Count:\n cfg.container.gpus === 'all'\n ? -1\n : typeof cfg.container.gpus === 'number'\n ? cfg.container.gpus\n : 1,\n DeviceIDs:\n typeof cfg.container.gpus === 'string' && cfg.container.gpus !== 'all'\n ? [String(cfg.container.gpus)]\n : undefined,\n Capabilities: [['gpu']],\n },\n ]\n : undefined,\n ...(hb ? { PortBindings: hb.PortBindings } : {}),\n },\n ...(hb ? { ExposedPorts: hb.ExposedPorts } : {}),\n ...(cfg.createOptions || {}),\n } as import('dockerode').ContainerCreateOptions;\n\n const container = await docker.createContainer(createOptions);\n await container.start(cfg.startOptions || {});\n await waitUntilRunning(container);\n\n const inspect = await container.inspect();\n const handle: DockerSandboxHandle = {\n docker,\n container,\n containerId: inspect.Id,\n image: inspect.Config?.Image ?? chosenImage.name,\n createdAt: new Date(inspect.Created || Date.now()),\n };\n\n return { sandbox: handle, sandboxId: handle.containerId };\n },\n\n getById: async (config: DockerConfig, sandboxId: string) => {\n const docker = new Docker((config || defaultDockerConfig).connection as any);\n try {\n const container = docker.getContainer(sandboxId);\n const info = await container.inspect();\n return {\n sandbox: <DockerSandboxHandle>{\n docker,\n container,\n containerId: sandboxId,\n image: info.Config?.Image ?? '',\n createdAt: new Date(info.Created || Date.now()),\n },\n sandboxId,\n };\n } catch {\n return null;\n }\n },\n\n list: async (config: DockerConfig) => {\n const docker = new Docker((config || defaultDockerConfig).connection as any);\n try {\n const items = await docker.listContainers({\n all: true,\n filters: { label: [LABEL_KEY] } as any,\n });\n return items.map(ci => ({\n sandbox: <DockerSandboxHandle>{\n docker,\n container: docker.getContainer(ci.Id),\n containerId: ci.Id,\n image: ci.Image,\n createdAt: new Date((ci as any).Created * 1000),\n },\n sandboxId: ci.Id,\n }));\n } catch {\n return [];\n }\n },\n\n destroy: async (config: DockerConfig, sandboxId: string) => {\n const docker = new Docker((config || defaultDockerConfig).connection as any);\n try {\n const c = docker.getContainer(sandboxId);\n try { await c.stop({ t: 5 } as any); } catch { /* stopped */ }\n await c.remove({ force: true });\n } catch {\n // ok if already gone\n }\n },\n\n runCode: async (handle: DockerSandboxHandle, code: string, runtime?: Runtime): Promise<ExecutionResult> => {\n const start = Date.now();\n\n // Resolve runtime: param → label → error\n let rt: Runtime | undefined = runtime;\n if (!rt) {\n const info = await handle.container.inspect();\n rt = (info.Config?.Labels?.[LABEL_RUNTIME] as Runtime) || undefined;\n }\n if (rt !== 'python' && rt !== 'node') {\n throw new Error(`Docker runtime must be 'python' or 'node'. Pass runtime in config or as a parameter.`);\n }\n\n // Write to file, then execute. This is robust on Alpine/Debian.\n const tmpFile = rt === 'python' ? '/tmp/compute_code.py' : '/tmp/compute_code.js';\n const b64 = Buffer.from(code, 'utf8').toString('base64');\n const makeAndRun =\n `printf '%s' \"${b64}\" | base64 -d > ${tmpFile} && ` +\n (rt === 'python' ? `python3 ${tmpFile}` : `node ${tmpFile}`);\n\n const { stdout, stderr, exitCode } = await runExec(handle, makeAndRun);\n\n if (exitCode !== 0 && stderr) {\n // Throw ONLY on syntax errors (SDK contract)\n const isSyntax =\n stderr.includes('SyntaxError') ||\n stderr.includes('invalid syntax') ||\n stderr.includes('Unexpected token') ||\n stderr.includes('Unexpected identifier');\n if (isSyntax) {\n const last = stderr.trim().split('\\n').slice(-1)[0] || 'Syntax error';\n throw new Error(`Syntax error: ${last}`);\n }\n }\n\n return {\n stdout,\n stderr,\n exitCode,\n executionTime: Date.now() - start,\n sandboxId: handle.containerId,\n provider: PROVIDER,\n };\n },\n\n runCommand: async (\n handle: DockerSandboxHandle,\n command: string,\n args: string[] = [],\n options?: RunCommandOptions\n ): Promise<ExecutionResult> => {\n const start = Date.now();\n const { command: finalCmd, args: finalArgs, isBackground } = createBackgroundCommand(command, args, options);\n let shell = finalArgs.length ? `${finalCmd} ${finalArgs.join(' ')}` : finalCmd;\n\n let pid: number | undefined;\n\n if (isBackground) {\n shell = `(${shell}) & echo $!`;\n const r = await runExec(handle, shell);\n const m = r.stdout.trim().split(/\\s+/).pop();\n pid = m && /^\\d+$/.test(m) ? Number(m) : undefined;\n return {\n stdout: r.stdout,\n stderr: r.stderr,\n exitCode: r.exitCode,\n executionTime: Date.now() - start,\n sandboxId: handle.containerId,\n provider: PROVIDER,\n isBackground: true,\n ...(pid ? { pid } : {}),\n };\n }\n\n const { stdout, stderr, exitCode } = await runExec(handle, shell);\n\n return {\n stdout,\n stderr,\n exitCode,\n executionTime: Date.now() - start,\n sandboxId: handle.containerId,\n provider: PROVIDER,\n };\n },\n\n getInfo: async (handle: DockerSandboxHandle): Promise<SandboxInfo> => {\n const info = await handle.container.inspect();\n const state = info.State || {};\n return {\n id: handle.containerId,\n provider: PROVIDER,\n runtime: (info.Config?.Labels?.[LABEL_RUNTIME] as Runtime) || 'python',\n status: state.Running ? 'running' : 'stopped',\n createdAt: new Date(info.Created || handle.createdAt),\n timeout: 300000,\n metadata: {\n image: info.Config?.Image,\n name: info.Name,\n },\n };\n },\n\n getUrl: async (handle: DockerSandboxHandle, options: { port: number; protocol?: string }): Promise<string> => {\n const info = await handle.container.inspect();\n const protocol = options.protocol || 'http';\n const portKeyTcp = `${options.port}/tcp`;\n\n const ports = info.NetworkSettings?.Ports || {};\n const bindings = ports[portKeyTcp] || ports[`${options.port}/udp`] || [];\n\n let host = dockerHostNameFromEnv();\n let hostPort = String(options.port);\n\n if (Array.isArray(bindings) && bindings.length > 0) {\n hostPort = bindings[0].HostPort || hostPort;\n } else {\n const ip =\n info.NetworkSettings?.IPAddress ||\n Object.values(info.NetworkSettings?.Networks || {})[0]?.IPAddress;\n if (ip) host = ip;\n }\n\n return `${protocol}://${host}:${hostPort}`;\n },\n\n filesystem: {\n readFile: async (handle: DockerSandboxHandle, path: string): Promise<string> => {\n const cmd = `if [ -f ${JSON.stringify(path)} ]; then base64 ${JSON.stringify(path)} | tr -d '\\\\n'; else exit 1; fi`;\n const { stdout, exitCode, stderr } = await runExec(handle, cmd);\n if (exitCode !== 0) throw new Error(stderr || `File not found: ${path}`);\n return Buffer.from(stdout, 'base64').toString('utf8');\n },\n\n writeFile: async (handle: DockerSandboxHandle, path: string, content: string): Promise<void> => {\n const b64 = Buffer.from(content, 'utf8').toString('base64');\n const cmd = `mkdir -p $(dirname ${JSON.stringify(path)}) && echo \"${b64}\" | base64 -d > ${JSON.stringify(path)}`;\n const { exitCode, stderr } = await runExec(handle, cmd);\n if (exitCode !== 0) throw new Error(stderr || `Failed to write: ${path}`);\n },\n\n mkdir: async (handle: DockerSandboxHandle, path: string): Promise<void> => {\n const { exitCode, stderr } = await runExec(handle, `mkdir -p ${JSON.stringify(path)}`);\n if (exitCode !== 0) throw new Error(stderr || `Failed to mkdir: ${path}`);\n },\n\n readdir: async (handle: DockerSandboxHandle, path: string): Promise<FileEntry[]> => {\n const { stdout, exitCode, stderr } = await runExec(\n handle,\n `if [ -d ${JSON.stringify(path)} ]; then ls -la ${JSON.stringify(path)}; else exit 1; fi`\n );\n if (exitCode !== 0) throw new Error(stderr || `Not a directory: ${path}`);\n\n const lines = stdout.split('\\n').slice(1);\n const entries: FileEntry[] = [];\n for (const line of lines) {\n const parts = line.trim().split(/\\s+/);\n if (parts.length < 9) continue;\n const name = parts.slice(8).join(' ');\n if (name === '.' || name === '..') continue;\n const isDir = parts[0].startsWith('d');\n const size = Number(parts[4]) || 0;\n entries.push({\n name,\n path: `${path.replace(/\\/$/, '')}/${name}`,\n isDirectory: isDir,\n size,\n lastModified: new Date(),\n });\n }\n return entries;\n },\n\n exists: async (handle: DockerSandboxHandle, path: string): Promise<boolean> => {\n const { exitCode } = await runExec(handle, `test -e ${JSON.stringify(path)}`);\n return exitCode === 0;\n },\n\n remove: async (handle: DockerSandboxHandle, path: string): Promise<void> => {\n const { exitCode, stderr } = await runExec(handle, `rm -rf ${JSON.stringify(path)}`);\n if (exitCode !== 0) throw new Error(stderr || `Failed to remove: ${path}`);\n },\n },\n\n getInstance: (handle: DockerSandboxHandle): DockerSandboxHandle => handle,\n },\n },\n});\n\n// ---------------------- convenience creator (optional) ----------------------\n\nexport function createDockerCompute(config: DockerConfig): CreateDockerCompute {\n const provider = docker(config);\n return {\n sandbox: {\n create: async (options) => {\n const sb = await provider.sandbox.create(options);\n return {\n ...sb,\n getInstance: (): DockerSandboxHandle => sb.getInstance() as DockerSandboxHandle,\n } as unknown as DockerSandboxAPI;\n },\n },\n };\n}\n","import type Docker from 'dockerode';\nimport type {\n DockerOptions,\n Container,\n ContainerCreateOptions,\n ContainerStartOptions,\n ContainerInspectInfo,\n ContainerInfo,\n Exec,\n ImageInfo,\n ImageBuildOptions,\n Network,\n} from 'dockerode';\n\nimport type {\n Runtime,\n FileEntry,\n ExecutionResult,\n RunCommandOptions,\n CreateSandboxOptions,\n SandboxInfo,\n} from 'computesdk';\n\n/** When the provider should clean up containers it created */\nexport type CleanupPolicy = 'always' | 'onSuccess' | 'never';\n\n/** Image pull strategy */\nexport type PullPolicy = 'always' | 'ifNotPresent' | 'never';\n\n/** Connection to the Docker daemon (exactly what dockerode accepts) */\nexport type DockerConnection = DockerOptions;\n\n/** Auth when pulling private images (Engine API AuthConfig shape) */\nexport interface RegistryAuth {\n username?: string;\n password?: string;\n serveraddress?: string;\n identitytoken?: string;\n registrytoken?: string;\n}\n\n/** Default image & pull policy for sandboxes */\nexport interface DockerImage {\n name: string; // e.g. 'python:3.11-slim'\n pullPolicy?: PullPolicy; // default: 'ifNotPresent'\n auth?: RegistryAuth;\n}\n\n/** Convenience shape for port bindings */\nexport type PortBindings = Record<\n `${number}/${'tcp' | 'udp'}`,\n Array<{ hostPort?: number; hostIP?: string }>\n>;\n\n/** Subset of HostConfig resources & knobs that are commonly used */\nexport interface ResourceLimits {\n cpuShares?: number;\n cpuQuota?: number;\n cpuPeriod?: number;\n nanoCPUs?: number;\n memory?: number;\n memorySwap?: number;\n pidsLimit?: number;\n}\n\n/** Declarative container defaults that we’ll translate into dockerode create options */\nexport interface ContainerDefaults {\n user?: string;\n workdir?: string;\n env?: Record<string, string>;\n binds?: string[];\n ports?: PortBindings;\n networkMode?: string;\n privileged?: boolean;\n capabilities?: { add?: string[]; drop?: string[] };\n gpus?: 'all' | number | string;\n resources?: ResourceLimits;\n logDriver?: string;\n logOpts?: Record<string, string>;\n autoRemove?: boolean;\n tty?: boolean;\n openStdin?: boolean;\n}\n\n/** Provider-level configuration for Docker */\nexport interface DockerConfig {\n connection?: DockerConnection;\n runtime?: Runtime; // 'python' | 'node'\n timeout?: number;\n image: DockerImage;\n container?: ContainerDefaults;\n createOptions?: ContainerCreateOptions;\n startOptions?: ContainerStartOptions;\n cleanup?: CleanupPolicy;\n streamLogs?: boolean;\n}\n\n/** What we keep for each running sandbox */\nexport interface DockerSandboxHandle {\n docker: Docker;\n container: Container;\n containerId: string;\n image: string;\n createdAt: Date;\n}\n\n/** URL options for port-forwarded services */\nexport interface DockerUrlOptions {\n port: number;\n protocol?: 'http' | 'https';\n host?: string;\n}\n\n/** Optional FS helpers you might expose */\nexport interface DockerSandboxFileSystem {\n readFile(path: string): Promise<string>;\n writeFile(path: string, content: string): Promise<void>;\n mkdir(path: string): Promise<void>;\n readdir(path: string): Promise<FileEntry[]>;\n exists(path: string): Promise<boolean>;\n remove(path: string): Promise<void>;\n}\n\n/** Strongly-typed sandbox API shape */\nexport interface DockerSandboxAPI {\n sandboxId: string;\n provider: 'docker';\n runCode(code: string, runtime?: Runtime): Promise<ExecutionResult>;\n runCommand(command: string, args?: string[], options?: RunCommandOptions): Promise<ExecutionResult>;\n getInfo(): Promise<SandboxInfo>;\n getUrl(options: DockerUrlOptions): Promise<string>;\n getProvider(): any;\n getInstance(): DockerSandboxHandle;\n kill(): Promise<void>;\n destroy(): Promise<void>;\n filesystem: DockerSandboxFileSystem;\n}\n\n/** Factory return shape mirroring your createE2BCompute helper */\nexport interface CreateDockerCompute {\n sandbox: {\n create(options?: CreateSandboxOptions): Promise<DockerSandboxAPI>;\n };\n}\n\n/** Sensible, safe defaults */\nexport const defaultDockerConfig: DockerConfig = {\n connection: {\n // Let dockerode fall back to DOCKER_HOST or /var/run/docker.sock\n timeout: 60_000,\n version: 'v1.43',\n },\n runtime: 'python',\n timeout: 300_000, // 5 minutes\n image: {\n name: 'python:3.11-slim',\n pullPolicy: 'ifNotPresent',\n },\n container: {\n workdir: '/workspace',\n env: {},\n autoRemove: false, // Keep container around for exec/FS/background\n tty: false, // Non-tty so we can demux stdout/stderr\n openStdin: false,\n resources: { memory: 512 * 1024 * 1024 },\n },\n cleanup: 'always',\n streamLogs: false,\n};\n\n/** Re-exports for convenience */\nexport type {\n Docker,\n Container,\n Exec,\n ContainerCreateOptions,\n ContainerStartOptions,\n ContainerInspectInfo,\n ContainerInfo,\n ImageInfo,\n ImageBuildOptions,\n Network,\n};\n"],"mappings":"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","names":["docker","container"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types/types.ts"],"sourcesContent":["import Docker from 'dockerode';\nimport { PassThrough } from 'stream';\nimport { createProvider } from 'computesdk';\nimport type {\n Runtime,\n CodeResult,\n CommandResult,\n RunCommandOptions,\n CreateSandboxOptions,\n SandboxInfo,\n FileEntry,\n} from 'computesdk';\n\nimport { defaultDockerConfig } from './types/types';\nimport type {\n DockerConfig,\n DockerSandboxHandle,\n DockerImage,\n PortBindings,\n} from './types/types';\n\nconst PROVIDER = 'docker' as const;\nconst LABEL_KEY = 'com.computesdk.sandbox';\nconst LABEL_RUNTIME = 'com.computesdk.runtime';\nconst KEEPALIVE_CMD = ['/bin/sh', '-c', 'while :; do sleep 3600; done'];\n\nfunction pick<T>(val: T | undefined, fallback: T): T {\n return typeof val === 'undefined' ? fallback : val;\n}\n\nasync function ensureImage(docker: Docker, image: DockerImage): Promise<void> {\n const policy = image.pullPolicy ?? 'ifNotPresent';\n if (policy === 'never') return;\n\n const images = await docker.listImages();\n const hasImage = images.some(img => (img.RepoTags || []).includes(image.name));\n\n if (policy === 'always' || (policy === 'ifNotPresent' && !hasImage)) {\n await new Promise<void>((resolve, reject) => {\n const cb = (err: any, stream?: NodeJS.ReadableStream) => {\n if (err) return reject(err);\n if (!stream) return reject(new Error('docker.pull returned no stream'));\n (docker as any).modem.followProgress(stream, (err2: any) => (err2 ? reject(err2) : resolve()));\n };\n if (image.auth) docker.pull(image.name, { authconfig: image.auth } as any, cb);\n else docker.pull(image.name, cb);\n });\n }\n}\n\nasync function waitUntilRunning(container: Docker.Container, timeoutMs = 4000) {\n const start = Date.now();\n try {\n const s = await container.inspect();\n if (s.State?.Running) return;\n } catch { /* ignore */ }\n\n while (Date.now() - start < timeoutMs) {\n const s = await container.inspect();\n if (s.State?.Running) return;\n await new Promise(r => setTimeout(r, 100));\n }\n throw new Error('Container did not reach Running state in time');\n}\n\nasync function runExec(\n handle: DockerSandboxHandle,\n shellCommand: string,\n attachTTY = false\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n await waitUntilRunning(handle.container);\n\n const exec = await handle.container.exec({\n Cmd: ['/bin/sh', '-c', shellCommand],\n AttachStdout: true,\n AttachStderr: true,\n Tty: attachTTY,\n });\n\n const stream = (await exec.start({ hijack: true, stdin: false })) as NodeJS.ReadableStream;\n\n let stdout = '';\n let stderr = '';\n\n await new Promise<void>((resolve, reject) => {\n if (attachTTY) {\n stream.on('data', (chunk: Buffer) => (stdout += chunk.toString('utf8')));\n stream.on('end', resolve);\n stream.on('error', reject);\n return;\n }\n const out = new PassThrough();\n const err = new PassThrough();\n out.on('data', (c: Buffer) => (stdout += c.toString('utf8')));\n err.on('data', (c: Buffer) => (stderr += c.toString('utf8')));\n (handle.docker as any).modem.demuxStream(stream as any, out as any, err as any);\n stream.on('end', resolve);\n stream.on('error', reject);\n });\n\n const inspect = await exec.inspect();\n const exitCode = inspect.ExitCode ?? 0;\n return { stdout, stderr, exitCode };\n}\n\nfunction toHostBindings(ports?: PortBindings) {\n if (!ports) return undefined;\n const exposed: Record<string, {}> = {};\n const bindings: Record<string, Array<{ HostPort?: string; HostIp?: string }>> = {};\n for (const key of Object.keys(ports)) {\n exposed[key] = {};\n bindings[key] = (ports as any)[key].map((p: any) => ({\n HostPort: p.hostPort ? String(p.hostPort) : undefined,\n HostIp: p.hostIP,\n }));\n }\n return { ExposedPorts: exposed, PortBindings: bindings };\n}\n\nfunction dockerHostNameFromEnv(): string {\n const hostEnv = process.env.DOCKER_HOST;\n if (hostEnv?.startsWith('tcp://')) {\n try {\n const u = new URL(hostEnv);\n return u.hostname || 'localhost';\n } catch { /* noop */ }\n }\n return 'localhost';\n}\n\nfunction pickImageForRuntime(runtime: Runtime, configured?: DockerImage): DockerImage {\n // If user supplied an image that already matches, use it. Otherwise pick a sensible default.\n if (configured?.name) {\n if (runtime === 'python' && /python|conda|pypy/i.test(configured.name)) return configured;\n if (runtime === 'node' && /node/i.test(configured.name)) return configured;\n }\n return {\n name: runtime === 'python' ? 'python:3.11-slim' : 'node:20-alpine',\n pullPolicy: configured?.pullPolicy ?? 'ifNotPresent',\n auth: configured?.auth,\n };\n}\n\nexport const docker = createProvider<DockerSandboxHandle, DockerConfig>({\n name: PROVIDER,\n methods: {\n sandbox: {\n create: async (config: DockerConfig, options?: CreateSandboxOptions) => {\n const cfg: DockerConfig = { ...defaultDockerConfig, ...config };\n const effectiveRuntime: Runtime = (options?.runtime ?? cfg.runtime ?? 'python') as Runtime;\n\n if (effectiveRuntime !== 'python' && effectiveRuntime !== 'node') {\n throw new Error(`Docker provider supports only 'python' or 'node'. Received: ${String(effectiveRuntime)}`);\n }\n\n const docker = new Docker(cfg.connection as any);\n\n // Reattach?\n if (options?.sandboxId) {\n try {\n const container = docker.getContainer(options.sandboxId);\n const info = await container.inspect();\n return {\n sandbox: <DockerSandboxHandle>{\n docker,\n container,\n containerId: options.sandboxId,\n image: info.Config?.Image ?? cfg.image.name,\n createdAt: new Date(info.Created || Date.now()),\n },\n sandboxId: options.sandboxId,\n };\n } catch (err) {\n // Failed to reattach to existing container; will create a new one.\n console.warn(`Could not reattach to Docker container with ID ${options.sandboxId}:`, err);\n }\n }\n\n // Choose image based on runtime if needed\n const chosenImage = pickImageForRuntime(effectiveRuntime, cfg.image);\n await ensureImage(docker, chosenImage);\n\n // Build container create options\n const hb = toHostBindings(cfg.container?.ports);\n const createOptions = {\n Image: chosenImage.name,\n Tty: pick(cfg.container?.tty, false),\n OpenStdin: pick(cfg.container?.openStdin, false),\n Labels: { [LABEL_KEY]: 'true', [LABEL_RUNTIME]: effectiveRuntime }, // <-- store runtime per sandbox\n WorkingDir: cfg.container?.workdir,\n Env: cfg.container?.env\n ? Object.entries(cfg.container.env).map(([k, v]) => `${k}=${v}`)\n : undefined,\n Cmd: KEEPALIVE_CMD, // keep container alive\n HostConfig: {\n AutoRemove: cfg.container?.autoRemove ?? false, // keep around for exec/FS ops\n Binds: cfg.container?.binds,\n NetworkMode: cfg.container?.networkMode,\n Privileged: cfg.container?.privileged,\n CapAdd: cfg.container?.capabilities?.add,\n CapDrop: cfg.container?.capabilities?.drop,\n LogConfig: cfg.container?.logDriver\n ? { Type: cfg.container.logDriver, Config: cfg.container.logOpts || {} }\n : undefined,\n Resources: cfg.container?.resources,\n DeviceRequests: cfg.container?.gpus\n ? [\n {\n Driver: 'nvidia',\n Count:\n cfg.container.gpus === 'all'\n ? -1\n : typeof cfg.container.gpus === 'number'\n ? cfg.container.gpus\n : 1,\n DeviceIDs:\n typeof cfg.container.gpus === 'string' && cfg.container.gpus !== 'all'\n ? [String(cfg.container.gpus)]\n : undefined,\n Capabilities: [['gpu']],\n },\n ]\n : undefined,\n ...(hb ? { PortBindings: hb.PortBindings } : {}),\n },\n ...(hb ? { ExposedPorts: hb.ExposedPorts } : {}),\n ...(cfg.createOptions || {}),\n } as import('dockerode').ContainerCreateOptions;\n\n const container = await docker.createContainer(createOptions);\n await container.start(cfg.startOptions || {});\n await waitUntilRunning(container);\n\n const inspect = await container.inspect();\n const handle: DockerSandboxHandle = {\n docker,\n container,\n containerId: inspect.Id,\n image: inspect.Config?.Image ?? chosenImage.name,\n createdAt: new Date(inspect.Created || Date.now()),\n };\n\n return { sandbox: handle, sandboxId: handle.containerId };\n },\n\n getById: async (config: DockerConfig, sandboxId: string) => {\n const docker = new Docker((config || defaultDockerConfig).connection as any);\n try {\n const container = docker.getContainer(sandboxId);\n const info = await container.inspect();\n return {\n sandbox: <DockerSandboxHandle>{\n docker,\n container,\n containerId: sandboxId,\n image: info.Config?.Image ?? '',\n createdAt: new Date(info.Created || Date.now()),\n },\n sandboxId,\n };\n } catch {\n return null;\n }\n },\n\n list: async (config: DockerConfig) => {\n const docker = new Docker((config || defaultDockerConfig).connection as any);\n try {\n const items = await docker.listContainers({\n all: true,\n filters: { label: [LABEL_KEY] } as any,\n });\n return items.map(ci => ({\n sandbox: <DockerSandboxHandle>{\n docker,\n container: docker.getContainer(ci.Id),\n containerId: ci.Id,\n image: ci.Image,\n createdAt: new Date((ci as any).Created * 1000),\n },\n sandboxId: ci.Id,\n }));\n } catch {\n return [];\n }\n },\n\n destroy: async (config: DockerConfig, sandboxId: string) => {\n const docker = new Docker((config || defaultDockerConfig).connection as any);\n try {\n const c = docker.getContainer(sandboxId);\n try { await c.stop({ t: 5 } as any); } catch { /* stopped */ }\n await c.remove({ force: true });\n } catch {\n // ok if already gone\n }\n },\n\n runCode: async (handle: DockerSandboxHandle, code: string, runtime?: Runtime): Promise<CodeResult> => {\n const start = Date.now();\n\n // Resolve runtime: param → label → error\n let rt: Runtime | undefined = runtime;\n if (!rt) {\n const info = await handle.container.inspect();\n rt = (info.Config?.Labels?.[LABEL_RUNTIME] as Runtime) || undefined;\n }\n if (rt !== 'python' && rt !== 'node') {\n throw new Error(`Docker runtime must be 'python' or 'node'. Pass runtime in config or as a parameter.`);\n }\n\n // Write to file, then execute. This is robust on Alpine/Debian.\n const tmpFile = rt === 'python' ? '/tmp/compute_code.py' : '/tmp/compute_code.js';\n const b64 = Buffer.from(code, 'utf8').toString('base64');\n const makeAndRun =\n `printf '%s' \"${b64}\" | base64 -d > ${tmpFile} && ` +\n (rt === 'python' ? `python3 ${tmpFile}` : `node ${tmpFile}`);\n\n const { stdout, stderr, exitCode } = await runExec(handle, makeAndRun);\n\n if (exitCode !== 0 && stderr) {\n // Throw ONLY on syntax errors (SDK contract)\n const isSyntax =\n stderr.includes('SyntaxError') ||\n stderr.includes('invalid syntax') ||\n stderr.includes('Unexpected token') ||\n stderr.includes('Unexpected identifier');\n if (isSyntax) {\n const last = stderr.trim().split('\\n').slice(-1)[0] || 'Syntax error';\n throw new Error(`Syntax error: ${last}`);\n }\n }\n\n return {\n output: stdout + stderr,\n exitCode,\n language: rt,\n };\n },\n\n runCommand: async (\n handle: DockerSandboxHandle,\n command: string,\n args: string[] = []\n ): Promise<CommandResult> => {\n const start = Date.now();\n const shell = args.length ? `${command} ${args.join(' ')}` : command;\n\n const { stdout, stderr, exitCode } = await runExec(handle, shell);\n\n return {\n stdout,\n stderr,\n exitCode,\n durationMs: Date.now() - start,\n };\n },\n\n getInfo: async (handle: DockerSandboxHandle): Promise<SandboxInfo> => {\n const info = await handle.container.inspect();\n const state = info.State || {};\n return {\n id: handle.containerId,\n provider: PROVIDER,\n runtime: (info.Config?.Labels?.[LABEL_RUNTIME] as Runtime) || 'python',\n status: state.Running ? 'running' : 'stopped',\n createdAt: new Date(info.Created || handle.createdAt),\n timeout: 300000,\n metadata: {\n image: info.Config?.Image,\n name: info.Name,\n },\n };\n },\n\n getUrl: async (handle: DockerSandboxHandle, options: { port: number; protocol?: string }): Promise<string> => {\n const info = await handle.container.inspect();\n const protocol = options.protocol || 'http';\n const portKeyTcp = `${options.port}/tcp`;\n\n const ports = info.NetworkSettings?.Ports || {};\n const bindings = ports[portKeyTcp] || ports[`${options.port}/udp`] || [];\n\n let host = dockerHostNameFromEnv();\n let hostPort = String(options.port);\n\n if (Array.isArray(bindings) && bindings.length > 0) {\n hostPort = bindings[0].HostPort || hostPort;\n } else {\n const ip =\n info.NetworkSettings?.IPAddress ||\n Object.values(info.NetworkSettings?.Networks || {})[0]?.IPAddress;\n if (ip) host = ip;\n }\n\n return `${protocol}://${host}:${hostPort}`;\n },\n\n filesystem: {\n readFile: async (handle: DockerSandboxHandle, path: string): Promise<string> => {\n const cmd = `if [ -f ${JSON.stringify(path)} ]; then base64 ${JSON.stringify(path)} | tr -d '\\\\n'; else exit 1; fi`;\n const { stdout, exitCode, stderr } = await runExec(handle, cmd);\n if (exitCode !== 0) throw new Error(stderr || `File not found: ${path}`);\n return Buffer.from(stdout, 'base64').toString('utf8');\n },\n\n writeFile: async (handle: DockerSandboxHandle, path: string, content: string): Promise<void> => {\n const b64 = Buffer.from(content, 'utf8').toString('base64');\n const cmd = `mkdir -p $(dirname ${JSON.stringify(path)}) && echo \"${b64}\" | base64 -d > ${JSON.stringify(path)}`;\n const { exitCode, stderr } = await runExec(handle, cmd);\n if (exitCode !== 0) throw new Error(stderr || `Failed to write: ${path}`);\n },\n\n mkdir: async (handle: DockerSandboxHandle, path: string): Promise<void> => {\n const { exitCode, stderr } = await runExec(handle, `mkdir -p ${JSON.stringify(path)}`);\n if (exitCode !== 0) throw new Error(stderr || `Failed to mkdir: ${path}`);\n },\n\n readdir: async (handle: DockerSandboxHandle, path: string): Promise<FileEntry[]> => {\n const { stdout, exitCode, stderr } = await runExec(\n handle,\n `if [ -d ${JSON.stringify(path)} ]; then ls -la ${JSON.stringify(path)}; else exit 1; fi`\n );\n if (exitCode !== 0) throw new Error(stderr || `Not a directory: ${path}`);\n\n const lines = stdout.split('\\n').slice(1);\n const entries: FileEntry[] = [];\n for (const line of lines) {\n const parts = line.trim().split(/\\s+/);\n if (parts.length < 9) continue;\n const name = parts.slice(8).join(' ');\n if (name === '.' || name === '..') continue;\n const isDir = parts[0].startsWith('d');\n const size = Number(parts[4]) || 0;\n entries.push({\n name,\n path: `${path.replace(/\\/$/, '')}/${name}`,\n isDirectory: isDir,\n size,\n lastModified: new Date(),\n });\n }\n return entries;\n },\n\n exists: async (handle: DockerSandboxHandle, path: string): Promise<boolean> => {\n const { exitCode } = await runExec(handle, `test -e ${JSON.stringify(path)}`);\n return exitCode === 0;\n },\n\n remove: async (handle: DockerSandboxHandle, path: string): Promise<void> => {\n const { exitCode, stderr } = await runExec(handle, `rm -rf ${JSON.stringify(path)}`);\n if (exitCode !== 0) throw new Error(stderr || `Failed to remove: ${path}`);\n },\n },\n\n getInstance: (handle: DockerSandboxHandle): DockerSandboxHandle => handle,\n },\n },\n});\n\n","import type Docker from 'dockerode';\nimport type {\n DockerOptions,\n Container,\n ContainerCreateOptions,\n ContainerStartOptions,\n ContainerInspectInfo,\n ContainerInfo,\n Exec,\n ImageInfo,\n ImageBuildOptions,\n Network,\n} from 'dockerode';\n\nimport type {\n Runtime,\n FileEntry,\n RunCommandOptions,\n CreateSandboxOptions,\n SandboxInfo,\n} from 'computesdk';\n\n/** When the provider should clean up containers it created */\nexport type CleanupPolicy = 'always' | 'onSuccess' | 'never';\n\n/** Image pull strategy */\nexport type PullPolicy = 'always' | 'ifNotPresent' | 'never';\n\n/** Connection to the Docker daemon (exactly what dockerode accepts) */\nexport type DockerConnection = DockerOptions;\n\n/** Auth when pulling private images (Engine API AuthConfig shape) */\nexport interface RegistryAuth {\n username?: string;\n password?: string;\n serveraddress?: string;\n identitytoken?: string;\n registrytoken?: string;\n}\n\n/** Default image & pull policy for sandboxes */\nexport interface DockerImage {\n name: string; // e.g. 'python:3.11-slim'\n pullPolicy?: PullPolicy; // default: 'ifNotPresent'\n auth?: RegistryAuth;\n}\n\n/** Convenience shape for port bindings */\nexport type PortBindings = Record<\n `${number}/${'tcp' | 'udp'}`,\n Array<{ hostPort?: number; hostIP?: string }>\n>;\n\n/** Subset of HostConfig resources & knobs that are commonly used */\nexport interface ResourceLimits {\n cpuShares?: number;\n cpuQuota?: number;\n cpuPeriod?: number;\n nanoCPUs?: number;\n memory?: number;\n memorySwap?: number;\n pidsLimit?: number;\n}\n\n/** Declarative container defaults that we’ll translate into dockerode create options */\nexport interface ContainerDefaults {\n user?: string;\n workdir?: string;\n env?: Record<string, string>;\n binds?: string[];\n ports?: PortBindings;\n networkMode?: string;\n privileged?: boolean;\n capabilities?: { add?: string[]; drop?: string[] };\n gpus?: 'all' | number | string;\n resources?: ResourceLimits;\n logDriver?: string;\n logOpts?: Record<string, string>;\n autoRemove?: boolean;\n tty?: boolean;\n openStdin?: boolean;\n}\n\n/** Provider-level configuration for Docker */\nexport interface DockerConfig {\n connection?: DockerConnection;\n runtime?: Runtime; // 'python' | 'node'\n timeout?: number;\n image: DockerImage;\n container?: ContainerDefaults;\n createOptions?: ContainerCreateOptions;\n startOptions?: ContainerStartOptions;\n cleanup?: CleanupPolicy;\n streamLogs?: boolean;\n}\n\n/** What we keep for each running sandbox */\nexport interface DockerSandboxHandle {\n docker: Docker;\n container: Container;\n containerId: string;\n image: string;\n createdAt: Date;\n}\n\n/** URL options for port-forwarded services */\nexport interface DockerUrlOptions {\n port: number;\n protocol?: 'http' | 'https';\n host?: string;\n}\n\n/** Optional FS helpers you might expose */\nexport interface DockerSandboxFileSystem {\n readFile(path: string): Promise<string>;\n writeFile(path: string, content: string): Promise<void>;\n mkdir(path: string): Promise<void>;\n readdir(path: string): Promise<FileEntry[]>;\n exists(path: string): Promise<boolean>;\n remove(path: string): Promise<void>;\n}\n\n/** Sensible, safe defaults */\nexport const defaultDockerConfig: DockerConfig = {\n connection: {\n // Let dockerode fall back to DOCKER_HOST or /var/run/docker.sock\n timeout: 60_000,\n version: 'v1.43',\n },\n runtime: 'python',\n timeout: 300_000, // 5 minutes\n image: {\n name: 'python:3.11-slim',\n pullPolicy: 'ifNotPresent',\n },\n container: {\n workdir: '/workspace',\n env: {},\n autoRemove: false, // Keep container around for exec/FS/background\n tty: false, // Non-tty so we can demux stdout/stderr\n openStdin: false,\n resources: { memory: 512 * 1024 * 1024 },\n },\n cleanup: 'always',\n streamLogs: false,\n};\n\n/** Re-exports for convenience */\nexport type {\n Docker,\n Container,\n Exec,\n ContainerCreateOptions,\n ContainerStartOptions,\n ContainerInspectInfo,\n ContainerInfo,\n ImageInfo,\n ImageBuildOptions,\n Network,\n};\n"],"mappings":"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","names":["docker","container"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@computesdk/docker",
3
- "version": "1.1.7",
3
+ "version": "1.2.0",
4
4
  "description": "Docker provider for ComputeSDK",
5
5
  "author": "IberAI",
6
6
  "license": "MIT",
@@ -19,7 +19,7 @@
19
19
  ],
20
20
  "dependencies": {
21
21
  "dockerode": "^4.0.8",
22
- "computesdk": "1.8.7"
22
+ "computesdk": "1.9.0"
23
23
  },
24
24
  "keywords": [
25
25
  "docker",