{"version":3,"file":"sandbox-DgtY5hvt.mjs","names":["stopPromise: Promise<void> | undefined"],"sources":["../src/core/sandbox.ts"],"sourcesContent":["import { normalizeError, SandboxError } from \"./errors\";\nimport type { SandboxProvider } from \"./provider\";\nimport type { FileValue, RunOptions, Sandbox } from \"./types\";\n\nexport interface CreateSandboxOptions<TProvider extends SandboxProvider<unknown>> {\n  provider: TProvider;\n  cwd?: string;\n  env?: Readonly<Record<string, string>>;\n  timeout?: number;\n  signal?: AbortSignal;\n}\n\ntype RawOf<TProvider> = TProvider extends SandboxProvider<infer TRaw> ? TRaw : never;\n\nfunction validateCwd(cwd: string): string {\n  if (!cwd.startsWith(\"/\") || cwd.includes(\"\\0\")) {\n    throw new SandboxError({\n      code: \"invalid_input\",\n      provider: \"core\",\n      operation: \"create\",\n      message: \"cwd must be an absolute path\",\n    });\n  }\n  return cwd.replace(/\\/$/, \"\") || \"/\";\n}\n\nfunction validatePath(cwd: string, value: string): string {\n  if (!value || value.includes(\"\\0\") || value.split(\"/\").includes(\"..\")) {\n    throw new SandboxError({\n      code: \"invalid_input\",\n      provider: \"core\",\n      operation: \"path\",\n      message: `Invalid sandbox path: ${value}`,\n    });\n  }\n  if (value.startsWith(\"/\")) return value.replace(/\\/{2,}/g, \"/\");\n  return `${cwd}/${value}`.replace(/\\/{2,}/g, \"/\");\n}\n\n/**\n * Creates a normalized sandbox. Prefer `await using` so cleanup runs when the scope exits.\n */\nexport async function createSandbox<TProvider extends SandboxProvider<unknown>>(\n  options: CreateSandboxOptions<TProvider>,\n): Promise<Sandbox<RawOf<TProvider>>> {\n  const cwd = validateCwd(options.cwd ?? \"/workspace\");\n  const env = options.env ?? {};\n  let runtime;\n  try {\n    runtime = await options.provider.create({\n      cwd,\n      env,\n      timeout: options.timeout,\n      signal: options.signal,\n    });\n  } catch (error) {\n    throw normalizeError(options.provider.id, \"sandbox.create\", error);\n  }\n  let stopPromise: Promise<void> | undefined;\n  const stop = async () => {\n    stopPromise ??= call(\"sandbox.stop\", () => runtime.stop());\n    return stopPromise;\n  };\n  const call = async <T>(operation: string, fn: () => Promise<T>): Promise<T> => {\n    try {\n      return await fn();\n    } catch (error) {\n      throw normalizeError(options.provider.id, operation, error);\n    }\n  };\n  return {\n    id: runtime.id,\n    provider: options.provider.id,\n    cwd,\n    capabilities: runtime.capabilities,\n    raw: runtime.raw as RawOf<TProvider>,\n    files: {\n      write: async (path: string, value: FileValue) =>\n        call(\"files.write\", () => runtime.files.write(validatePath(cwd, path), value)),\n      read: async (path: string) =>\n        call(\"files.read\", () => runtime.files.read(validatePath(cwd, path))),\n      text: async (path: string) =>\n        new TextDecoder().decode(\n          await call(\"files.read\", () => runtime.files.read(validatePath(cwd, path))),\n        ),\n      list: async (path = \".\") =>\n        call(\"files.list\", () => runtime.files.list(path === \".\" ? cwd : validatePath(cwd, path))),\n      mkdir: async (path: string) =>\n        call(\"files.mkdir\", () => runtime.files.mkdir(validatePath(cwd, path))),\n      remove: async (path: string) =>\n        call(\"files.remove\", () => runtime.files.remove(validatePath(cwd, path))),\n      exists: async (path: string) =>\n        call(\"files.exists\", () => runtime.files.exists(validatePath(cwd, path))),\n    },\n    processes: {\n      start: (command, runOptions = {}) =>\n        call(\"process.start\", () => runtime.start(command, normalizeRunOptions(cwd, runOptions))),\n    },\n    ports: { expose: (port) => call(\"ports.expose\", () => runtime.expose(port)) },\n    snapshots: {\n      create: (snapshotOptions) =>\n        call(\"snapshot.create\", () => runtime.snapshots.create(snapshotOptions)),\n      delete: (snapshot) => call(\"snapshot.delete\", () => runtime.snapshots.delete(snapshot)),\n      restore: (snapshot) => call(\"snapshot.restore\", () => runtime.snapshots.restore(snapshot)),\n    },\n    run: (command, runOptions = {}) =>\n      call(\"process.run\", () => runtime.run(command, normalizeRunOptions(cwd, runOptions))),\n    stop,\n    [Symbol.asyncDispose]: stop,\n  };\n}\n\nfunction normalizeRunOptions(cwd: string, options: RunOptions): RunOptions {\n  return { ...options, cwd: options.cwd ? validatePath(cwd, options.cwd) : cwd };\n}\n\n/**\n * Runs a callback with a sandbox and stops it afterward.\n *\n * Prefer `await using` with `createSandbox()` in new code. This helper remains useful for\n * callback-style code and runtimes that do not parse explicit resource management syntax.\n */\nexport async function withSandbox<TProvider extends SandboxProvider<unknown>, TResult>(\n  options: CreateSandboxOptions<TProvider>,\n  callback: (sandbox: Sandbox<RawOf<TProvider>>) => TResult | Promise<TResult>,\n): Promise<TResult> {\n  const sandbox = await createSandbox(options);\n  try {\n    const result = await callback(sandbox);\n    await sandbox.stop();\n    return result;\n  } catch (error) {\n    try {\n      await sandbox.stop();\n    } catch (cleanupError) {\n      if (error instanceof Error) {\n        Object.defineProperty(error, \"cleanupError\", { value: cleanupError, enumerable: false });\n      }\n    }\n    throw error;\n  }\n}\n"],"mappings":"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"}