{"version":3,"file":"index.mjs","names":["native: AsciiBoxSandbox | undefined"],"sources":["../../../src/providers/box/index.ts"],"sourcesContent":["import { BoxApi, Configuration, type Box as NativeBox } from \"@asciidev/box-sdk\";\nimport { SandboxError } from \"../../core/errors\";\nimport type { SandboxProvider } from \"../../core/provider\";\nimport type { CommandInput } from \"../../core/types\";\nimport { withManagedSessions } from \"../../internal/managed-provider\";\nimport {\n  commandString,\n  portResult,\n  toUint8Array,\n  unsupported,\n  unsupportedSnapshots,\n} from \"../../internal/provider-utils\";\nimport { boxCapabilities } from \"../capabilities\";\n\nconst DEFAULT_BASE_URL = \"https://ascii.dev/api/box/v1\";\nconst MAX_COMMAND_TIMEOUT_MS = 60_000;\n\nexport interface BoxOptions {\n  /** Box API key. Defaults to BOX_API_KEY. */\n  apiKey?: string;\n  /** Box API base URL. Defaults to BOX_BASE_URL, then the public v1 endpoint. */\n  baseUrl?: string;\n  /** Seconds before Box automatically archives. The service default is one hour. */\n  ttlSeconds?: number | null;\n  /** Withhold account-level secrets from the Box. */\n  noEnv?: boolean;\n  /** Friendly Box name applied after provisioning. */\n  name?: string;\n  /** Return ungated hosted URLs instead of protected URLs. Defaults to true. */\n  public?: boolean;\n  /** Maximum time to wait for provisioning, in milliseconds. Defaults to 10 minutes. */\n  readyTimeout?: number;\n}\n\nexport interface AsciiBoxSandbox {\n  readonly client: BoxApi;\n  box: NativeBox;\n  readonly readyTimeoutMs: number;\n}\n\nexport { boxCapabilities } from \"../capabilities\";\n\nexport function box(options: BoxOptions = {}): SandboxProvider<AsciiBoxSandbox> {\n  const readyTimeoutMs = options.readyTimeout ?? 600_000;\n  const publicPorts = options.public ?? true;\n\n  const provider: SandboxProvider<AsciiBoxSandbox> = {\n    id: \"box\",\n    capabilities: boxCapabilities,\n    async create(createOptions) {\n      const apiKey = options.apiKey ?? process.env.BOX_API_KEY;\n      if (!apiKey) {\n        throw new SandboxError({\n          code: \"authentication\",\n          provider: \"box\",\n          operation: \"sandbox.create\",\n          message: \"BOX_API_KEY is required to create an Ascii Box\",\n        });\n      }\n      const client = new BoxApi(\n        new Configuration({\n          basePath: options.baseUrl ?? process.env.BOX_BASE_URL ?? DEFAULT_BASE_URL,\n          accessToken: apiKey,\n        }),\n      );\n      assertNotAborted(createOptions.signal);\n      const created = await client.create(\n        {\n          createBoxRequest: {\n            ttlSeconds: options.ttlSeconds,\n            noEnv: options.noEnv,\n            env: { ...createOptions.env },\n          },\n        },\n        { signal: createOptions.signal },\n      );\n      const id = created.box.id;\n      let native: AsciiBoxSandbox | undefined;\n      try {\n        const ready = await waitUntilBoxReady(\n          client,\n          id,\n          createOptions.signal,\n          createOptions.timeout ?? readyTimeoutMs,\n        );\n        native = { client, box: ready, readyTimeoutMs };\n        if (options.name) {\n          native.box = (\n            await client.update({ boxId: id, updateBoxRequest: { name: options.name } })\n          ).box;\n        }\n\n        const remoteRoot = toRemotePath(createOptions.cwd);\n        const mkdir = await execute(client, id, {\n          command: commandString({ command: \"mkdir\", args: [\"-p\", \"--\", remoteRoot] }),\n          timeoutMs: MAX_COMMAND_TIMEOUT_MS,\n          signal: createOptions.signal,\n        });\n        assertSucceeded(mkdir, \"sandbox.create.cwd\");\n        return {\n          id,\n          raw: native,\n          capabilities: boxCapabilities,\n          files: {\n            async write(path, value) {\n              const remotePath = toRemotePath(path);\n              const parent = remotePath.includes(\"/\")\n                ? remotePath.slice(0, remotePath.lastIndexOf(\"/\"))\n                : \".\";\n              const mkdirResult = await execute(client, id, {\n                command: commandString({ command: \"mkdir\", args: [\"-p\", \"--\", parent] }),\n                timeoutMs: MAX_COMMAND_TIMEOUT_MS,\n              });\n              assertSucceeded(mkdirResult, \"files.write.mkdir\");\n              await client.writeFile({\n                boxId: id,\n                fileWriteRequest: {\n                  path: remotePath,\n                  content: Buffer.from(await toUint8Array(value)).toString(\"base64\"),\n                  encoding: \"base64\",\n                },\n              });\n            },\n            async read(path) {\n              const response = await client.readFile({\n                boxId: id,\n                path: toRemotePath(path),\n                encoding: \"base64\",\n              });\n              return new Uint8Array(Buffer.from(response.content, \"base64\"));\n            },\n            async list(path) {\n              const result = await execute(client, id, {\n                command: commandString({\n                  command: \"python3\",\n                  args: [\"-c\", DIRECTORY_LIST_SCRIPT, toRemotePath(path)],\n                }),\n                timeoutMs: MAX_COMMAND_TIMEOUT_MS,\n              });\n              assertSucceeded(result, \"files.list\");\n              const entries = JSON.parse(result.stdout) as NativeDirectoryEntry[];\n              return entries.map((entry) => ({\n                name: entry.name,\n                path: toVirtualPath(entry.path),\n                type: entry.type,\n                size: entry.type === \"file\" ? entry.size : undefined,\n              }));\n            },\n            async mkdir(path) {\n              const result = await execute(client, id, {\n                command: commandString({\n                  command: \"mkdir\",\n                  args: [\"-p\", \"--\", toRemotePath(path)],\n                }),\n                timeoutMs: MAX_COMMAND_TIMEOUT_MS,\n              });\n              assertSucceeded(result, \"files.mkdir\");\n            },\n            async remove(path) {\n              const result = await execute(client, id, {\n                command: commandString({\n                  command: \"rm\",\n                  args: [\"-rf\", \"--\", toRemotePath(path)],\n                }),\n                timeoutMs: MAX_COMMAND_TIMEOUT_MS,\n              });\n              assertSucceeded(result, \"files.remove\");\n            },\n            async exists(path) {\n              const result = await execute(client, id, {\n                command: commandString({\n                  command: \"test\",\n                  args: [\"-e\", toRemotePath(path)],\n                }),\n                timeoutMs: MAX_COMMAND_TIMEOUT_MS,\n              });\n              if (result.exitCode === 0) return true;\n              if (result.exitCode === 1) return false;\n              assertSucceeded(result, \"files.exists\");\n              return false;\n            },\n          },\n          async run(command, runOptions) {\n            const result = await execute(client, id, {\n              command: withEnvironment(command, runOptions.env),\n              cwd: toRemotePath(runOptions.cwd!),\n              timeoutMs: runOptions.timeout,\n              signal: runOptions.signal,\n            });\n            if (result.timedOut) {\n              throw new SandboxError({\n                code: \"timeout\",\n                provider: \"box\",\n                operation: \"process.run\",\n                message: `Command timed out after ${runOptions.timeout ?? 30_000}ms`,\n              });\n            }\n            return {\n              stdout: result.stdout,\n              stderr: result.stderr,\n              exitCode: result.exitCode ?? 1,\n              success: result.success,\n              signal: result.signal ?? undefined,\n              durationMs:\n                result.startedAt && result.finishedAt\n                  ? result.finishedAt.getTime() - result.startedAt.getTime()\n                  : undefined,\n            };\n          },\n          async start() {\n            unsupported(\"box\", \"process.start\");\n          },\n          async expose(port) {\n            const visibility = publicPorts ? \"--public\" : \"--private\";\n            const hosted = await execute(client, id, {\n              command: `host ${port} ${visibility}`,\n              timeoutMs: MAX_COMMAND_TIMEOUT_MS,\n            });\n            assertSucceeded(hosted, \"ports.expose\");\n            const resolved = await execute(client, id, {\n              command: `host url ${port}${publicPorts ? \" --public\" : \"\"}`,\n              timeoutMs: MAX_COMMAND_TIMEOUT_MS,\n            });\n            assertSucceeded(resolved, \"ports.expose.url\");\n            const url =\n              findUrl(`${resolved.stdout}\\n${resolved.stderr}`) ??\n              findUrl(`${hosted.stdout}\\n${hosted.stderr}`);\n            if (!url) throw new Error(`Box host command did not return a URL for port ${port}`);\n            const protectedUrl = new URL(url).searchParams.has(\"_token\");\n            const exposedUrl = protectedUrl ? withoutProtectedToken(url) : url;\n            return portResult(\n              port,\n              exposedUrl,\n              !protectedUrl,\n              protectedUrl,\n              protectedUrl\n                ? async (path = \"/\", init = {}) => fetch(withProtectedPath(url, path), init)\n                : undefined,\n            );\n          },\n          snapshots: unsupportedSnapshots(\"box\"),\n          async stop() {\n            await destroyBox(client, id, readyTimeoutMs);\n          },\n        };\n      } catch (error) {\n        await destroyBox(client, id, readyTimeoutMs).catch(() => undefined);\n        throw error;\n      }\n    },\n  };\n\n  return withManagedSessions(provider, [], {\n    async stop(sandbox) {\n      await sandbox.raw.client.stop({ boxId: sandbox.id });\n      sandbox.raw.box = await waitForState(\n        sandbox.raw.client,\n        sandbox.id,\n        [\"archived\"],\n        sandbox.raw.readyTimeoutMs,\n      );\n    },\n    async resume(sandbox) {\n      await sandbox.raw.client.resume({ boxId: sandbox.id });\n      sandbox.raw.box = await waitUntilBoxReady(\n        sandbox.raw.client,\n        sandbox.id,\n        undefined,\n        sandbox.raw.readyTimeoutMs,\n      );\n    },\n    async destroy(sandbox) {\n      await destroyBox(sandbox.raw.client, sandbox.id, sandbox.raw.readyTimeoutMs);\n    },\n  });\n}\n\ninterface NativeDirectoryEntry {\n  name: string;\n  path: string;\n  type: \"file\" | \"directory\" | \"symlink\" | \"unknown\";\n  size: number;\n}\n\nconst DIRECTORY_LIST_SCRIPT = [\n  \"import json, os, sys\",\n  \"result = []\",\n  \"for entry in os.scandir(sys.argv[1]):\",\n  \"    kind = 'symlink' if entry.is_symlink() else ('directory' if entry.is_dir() else ('file' if entry.is_file() else 'unknown'))\",\n  \"    result.append({'name': entry.name, 'path': entry.path, 'type': kind, 'size': entry.stat(follow_symlinks=False).st_size})\",\n  \"print(json.dumps(result))\",\n].join(\"\\n\");\n\ntype CommandResponse = Awaited<ReturnType<BoxApi[\"command\"]>>;\n\nasync function execute(\n  client: BoxApi,\n  boxId: string,\n  options: {\n    command: string;\n    cwd?: string;\n    timeoutMs?: number;\n    signal?: AbortSignal;\n  },\n): Promise<CommandResponse> {\n  assertNotAborted(options.signal);\n  if (options.timeoutMs !== undefined && options.timeoutMs > MAX_COMMAND_TIMEOUT_MS) {\n    throw new SandboxError({\n      code: \"invalid_input\",\n      provider: \"box\",\n      operation: \"process.run\",\n      message: \"Ascii Box commands support a maximum timeout of 60000ms\",\n    });\n  }\n  return client.command(\n    {\n      boxId,\n      commandRequest: {\n        command: options.command,\n        cwd: options.cwd,\n        timeoutSeconds:\n          options.timeoutMs === undefined\n            ? undefined\n            : Math.max(1, Math.ceil(options.timeoutMs / 1_000)),\n      },\n    },\n    { signal: options.signal },\n  );\n}\n\nfunction withEnvironment(\n  input: CommandInput,\n  environment: Readonly<Record<string, string>> | undefined,\n): string {\n  const command = commandString(input);\n  const entries = Object.entries(environment ?? {});\n  if (entries.length === 0) return command;\n  const assignments = entries.map(([key, value]) => shellQuote(`${key}=${value}`));\n  return `env ${assignments.join(\" \")} sh -c ${shellQuote(command)}`;\n}\n\nfunction toRemotePath(path: string): string {\n  return path === \"/\" ? \".\" : path.replace(/^\\/+/, \"\");\n}\n\nfunction toVirtualPath(path: string): string {\n  return `/${path.replace(/^\\.\\/?/, \"\")}`.replace(/\\/$/, \"\") || \"/\";\n}\n\nfunction assertSucceeded(result: CommandResponse, operation: string): void {\n  if (result.exitCode === 0) return;\n  throw new Error(\n    `${operation} failed: ${result.stderr || result.stdout || `exit ${result.exitCode}`}`,\n  );\n}\n\nfunction findUrl(output: string): string | undefined {\n  return output.match(/https:\\/\\/[^\\s\"']+/)?.[0]?.replace(/[),.;]+$/, \"\");\n}\n\nfunction withProtectedPath(base: string, path: string): URL {\n  const protectedUrl = new URL(base);\n  const target = new URL(path, base);\n  if (target.origin !== protectedUrl.origin) {\n    throw new SandboxError({\n      code: \"invalid_input\",\n      provider: \"box\",\n      operation: \"port.request\",\n      message: \"Protected Ascii Box preview requests must stay on the preview origin\",\n    });\n  }\n  for (const [key, value] of protectedUrl.searchParams) target.searchParams.set(key, value);\n  return target;\n}\n\nfunction withoutProtectedToken(url: string): string {\n  const exposed = new URL(url);\n  exposed.searchParams.delete(\"_token\");\n  return exposed.toString();\n}\n\nasync function waitForState(\n  client: BoxApi,\n  boxId: string,\n  states: ReadonlyArray<NativeBox[\"state\"]>,\n  timeoutMs: number,\n): Promise<NativeBox> {\n  const deadline = Date.now() + timeoutMs;\n  for (;;) {\n    const current = (await client.get({ boxId })).box;\n    if (states.includes(current.state)) return current;\n    if (current.state === \"error\") throw new Error(\"Box entered terminal state error\");\n    if (Date.now() >= deadline) throw new Error(\"Timed out waiting for Box state\");\n    await new Promise((resolve) => setTimeout(resolve, 1_000));\n  }\n}\n\nasync function destroyBox(client: BoxApi, boxId: string, timeoutMs: number): Promise<void> {\n  try {\n    await client.remove({ boxId });\n    return;\n  } catch (error) {\n    if (!hasResponseStatus(error, 409)) throw error;\n  }\n  await client.stop({ boxId });\n  await waitForState(client, boxId, [\"archived\"], timeoutMs);\n  await client.remove({ boxId });\n}\n\nfunction hasResponseStatus(error: unknown, status: number): boolean {\n  return (\n    typeof error === \"object\" &&\n    error !== null &&\n    \"response\" in error &&\n    typeof error.response === \"object\" &&\n    error.response !== null &&\n    \"status\" in error.response &&\n    error.response.status === status\n  );\n}\n\nasync function waitUntilBoxReady(\n  client: BoxApi,\n  boxId: string,\n  signal?: AbortSignal,\n  timeoutMs = 600_000,\n): Promise<NativeBox> {\n  const deadline = Date.now() + timeoutMs;\n  for (;;) {\n    assertNotAborted(signal);\n    const current = (await client.get({ boxId }, { signal })).box;\n    if ([\"ready\", \"idle\", \"running\"].includes(current.state)) return current;\n    if ([\"archived\", \"archiving\", \"error\"].includes(current.state)) {\n      throw new Error(`Box entered terminal state ${current.state}`);\n    }\n    const remainingMs = deadline - Date.now();\n    if (remainingMs <= 0) {\n      throw new Error(`Sandbox creation timed out after ${timeoutMs}ms`);\n    }\n    await abortableDelay(Math.min(1_000, remainingMs), signal);\n  }\n}\n\nfunction abortableDelay(ms: number, signal?: AbortSignal): Promise<void> {\n  if (!signal) return new Promise((resolve) => setTimeout(resolve, ms));\n  assertNotAborted(signal);\n  return new Promise((resolve, reject) => {\n    const timer = setTimeout(() => {\n      signal.removeEventListener(\"abort\", onAbort);\n      resolve();\n    }, ms);\n    const onAbort = () => {\n      clearTimeout(timer);\n      reject(signal.reason ?? new DOMException(\"Aborted\", \"AbortError\"));\n    };\n    signal.addEventListener(\"abort\", onAbort, { once: true });\n  });\n}\n\nfunction assertNotAborted(signal?: AbortSignal): void {\n  if (signal?.aborted) throw signal.reason ?? new DOMException(\"Aborted\", \"AbortError\");\n}\n\nfunction shellQuote(value: string): string {\n  return `'${value.replaceAll(\"'\", `'\"'\"'`)}'`;\n}\n\nexport type BoxSandbox = AsciiBoxSandbox;\n"],"mappings":"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"}