@cloudflare/sandbox 0.13.0-next.776.1 → 1.0.0-rc.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.
Files changed (63) hide show
  1. package/README.md +62 -219
  2. package/dist/index.d.mts +548 -0
  3. package/dist/index.mjs +2452 -0
  4. package/package.json +17 -118
  5. package/Dockerfile +0 -368
  6. package/dist/bridge/index.d.ts +0 -181
  7. package/dist/bridge/index.d.ts.map +0 -1
  8. package/dist/bridge/index.js +0 -3053
  9. package/dist/bridge/index.js.map +0 -1
  10. package/dist/contexts-1EsLHByO.d.ts +0 -463
  11. package/dist/contexts-1EsLHByO.d.ts.map +0 -1
  12. package/dist/dist-Duor5GbS.js +0 -752
  13. package/dist/dist-Duor5GbS.js.map +0 -1
  14. package/dist/errors/index.d.ts +0 -4
  15. package/dist/errors/index.js +0 -4
  16. package/dist/errors-CXR0xBpw.js +0 -285
  17. package/dist/errors-CXR0xBpw.js.map +0 -1
  18. package/dist/errors-QYlSkVGz.js +0 -893
  19. package/dist/errors-QYlSkVGz.js.map +0 -1
  20. package/dist/extensions/index.d.ts +0 -4
  21. package/dist/extensions/index.js +0 -6
  22. package/dist/extensions-CFB2xHqY.js +0 -1023
  23. package/dist/extensions-CFB2xHqY.js.map +0 -1
  24. package/dist/filesystem-BWAZCZER.d.ts +0 -732
  25. package/dist/filesystem-BWAZCZER.d.ts.map +0 -1
  26. package/dist/git/index.d.ts +0 -63
  27. package/dist/git/index.d.ts.map +0 -1
  28. package/dist/git/index.js +0 -338
  29. package/dist/git/index.js.map +0 -1
  30. package/dist/index-Bs4bqXDR.d.ts +0 -438
  31. package/dist/index-Bs4bqXDR.d.ts.map +0 -1
  32. package/dist/index-HNYBk-az.d.ts +0 -444
  33. package/dist/index-HNYBk-az.d.ts.map +0 -1
  34. package/dist/index.d.ts +0 -576
  35. package/dist/index.d.ts.map +0 -1
  36. package/dist/index.js +0 -33
  37. package/dist/index.js.map +0 -1
  38. package/dist/interpreter/index.d.ts +0 -311
  39. package/dist/interpreter/index.d.ts.map +0 -1
  40. package/dist/interpreter/index.js +0 -292
  41. package/dist/interpreter/index.js.map +0 -1
  42. package/dist/openai/index.d.ts +0 -68
  43. package/dist/openai/index.d.ts.map +0 -1
  44. package/dist/openai/index.js +0 -367
  45. package/dist/openai/index.js.map +0 -1
  46. package/dist/opencode/index.d.ts +0 -182
  47. package/dist/opencode/index.d.ts.map +0 -1
  48. package/dist/opencode/index.js +0 -454
  49. package/dist/opencode/index.js.map +0 -1
  50. package/dist/process-types-GStiZ8f8.d.ts +0 -73
  51. package/dist/process-types-GStiZ8f8.d.ts.map +0 -1
  52. package/dist/sandbox-BbAabq93.d.ts +0 -42
  53. package/dist/sandbox-BbAabq93.d.ts.map +0 -1
  54. package/dist/sandbox-cmlgGVYX.js +0 -10056
  55. package/dist/sandbox-cmlgGVYX.js.map +0 -1
  56. package/dist/sidecar/index.d.ts +0 -77
  57. package/dist/sidecar/index.d.ts.map +0 -1
  58. package/dist/sidecar/index.js +0 -201
  59. package/dist/sidecar/index.js.map +0 -1
  60. package/dist/xterm/index.d.ts +0 -93
  61. package/dist/xterm/index.d.ts.map +0 -1
  62. package/dist/xterm/index.js +0 -220
  63. package/dist/xterm/index.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":["env","body: ErrorResponse","parts: string[]","iterator: AsyncIterator<string | Uint8Array>","sandboxIdParameter","getSandboxFromSDK","env","body: TunnelRequest","remoteOptions: RemoteMountBucketOptions","r2BindingOptions: R2BindingMountBucketOptions","stream: ReadableStream<Uint8Array>","tarBytes: Uint8Array","body: MountBucketRequest","body: UnmountBucketRequest","errors: string[]","response: RunningResponse","body: ExecRequest","options: {\n timeout?: number;\n cwd?: string;\n env?: Record<string, string>;\n }","body: unknown","body: unknown","options: CreateTerminalOptions","env: Record<string, string>","env","openapiAuth: MiddlewareHandler<{ Bindings: BridgeEnv }>","DEFAULT_CONFIG: Required<WarmPoolConfig>","containerUUID","destroyed: string[]","missing: string[]","env","cfEnv","passThrough: Record<string, unknown>"],"sources":["../../src/bridge/pool.ts","../../src/bridge/helpers.ts","../../src/bridge/openapi/common.ts","../../src/bridge/openapi/files.ts","../../src/bridge/openapi/lifecycle.ts","../../src/bridge/openapi/processes.ts","../../src/bridge/openapi/terminals.ts","../../src/bridge/openapi.ts","../../src/bridge/openapi-html.ts","../../src/bridge/routes/common.ts","../../src/bridge/routes/files.ts","../../src/bridge/routes/lifecycle.ts","../../src/bridge/routes/processes.ts","../../src/bridge/routes/terminals.ts","../../src/bridge/routes.ts","../../src/bridge/warm-pool.ts","../../src/bridge/index.ts"],"sourcesContent":["/**\n * Pool management helpers for the bridge.\n */\n\nimport type { BridgeEnv } from './types';\n\n/**\n * Prime the warm pool — pushes current configuration to the WarmPool\n * Durable Object so it starts its alarm loop.\n *\n * Called by the scheduled() handler and by POST /pool/prime.\n */\nexport async function primePool(\n env: BridgeEnv,\n warmPoolBinding: string\n): Promise<void> {\n const warmTarget =\n Number.parseInt((env.WARM_POOL_TARGET as string) || '0', 10) || 0;\n const refreshInterval =\n Number.parseInt(\n (env.WARM_POOL_REFRESH_INTERVAL as string) || '10000',\n 10\n ) || 10_000;\n\n const ns = env[warmPoolBinding] as DurableObjectNamespace;\n const poolId = ns.idFromName('global-pool');\n const poolStub = ns.get(poolId);\n await (poolStub as any).configure({ warmTarget, refreshInterval });\n}\n","/**\n * Utility functions used by the bridge routes.\n */\n\nimport { streamFile } from '../file-stream';\nimport type { ErrorResponse } from './types';\n\n// ---------------------------------------------------------------------------\n// Encoding helpers\n// ---------------------------------------------------------------------------\n\n/**\n * UTF-8-safe base64 encoding.\n * btoa() only handles latin-1; encode to UTF-8 bytes first via TextEncoder.\n */\nexport function toBase64(str: string): string {\n const bytes = new TextEncoder().encode(str);\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\n/** RFC 4648 base32 encoding (lowercase). Returns only [a-z2-7]. */\nexport function base32Encode(data: Uint8Array): string {\n const alphabet = 'abcdefghijklmnopqrstuvwxyz234567';\n let bits = 0;\n let value = 0;\n let out = '';\n for (const byte of data) {\n value = (value << 8) | byte;\n bits += 8;\n while (bits >= 5) {\n out += alphabet[(value >>> (bits - 5)) & 0x1f];\n bits -= 5;\n }\n }\n if (bits > 0) {\n out += alphabet[(value << (5 - bits)) & 0x1f];\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Response helpers\n// ---------------------------------------------------------------------------\n\nexport function errorJson(\n error: string,\n code: string,\n status: number\n): Response {\n const body: ErrorResponse = { error, code };\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'Content-Type': 'application/json' }\n });\n}\n\n// ---------------------------------------------------------------------------\n// Shell quoting\n// ---------------------------------------------------------------------------\n\n/**\n * Shell-quote a single argv token so it is safe to embed in a sh command\n * string. Tokens that contain only safe characters are returned unchanged\n * for readability. All others are wrapped in ANSI-C $'...' quoting which\n * can represent newlines, tabs, and other control characters as escape\n * sequences — unlike plain single quotes which pass content literally and\n * break when the value contains a real newline.\n */\nexport function shellQuote(arg: string): string {\n // Fast path: arg contains only safe characters.\n if (/^[A-Za-z0-9@%+=:,./-]+$/.test(arg)) {\n return arg;\n }\n // Use $'...' (ANSI-C quoting) which supports escape sequences.\n // Escape backslashes first, then single quotes and control characters.\n const escaped = arg\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/'/g, \"\\\\'\")\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t');\n return `$'${escaped}'`;\n}\n\n// ---------------------------------------------------------------------------\n// Path validation\n// ---------------------------------------------------------------------------\n\n/**\n * POSIX-normalise a path (resolve `.` / `..` segments) and verify it lives\n * under /workspace. Returns the resolved absolute path on success, or null\n * if the path escapes the workspace.\n */\nexport function resolveWorkspacePath(userPath: string): string | null {\n // Treat relative paths as relative to /workspace\n const abs = userPath.startsWith('/') ? userPath : `/workspace/${userPath}`;\n\n // Normalise: split on '/', resolve '.' and '..'\n const parts: string[] = [];\n for (const seg of abs.split('/')) {\n if (seg === '' || seg === '.') continue;\n if (seg === '..') {\n parts.pop();\n } else {\n parts.push(seg);\n }\n }\n const resolved = `/${parts.join('/')}`;\n\n // Must be exactly /workspace or start with /workspace/\n if (resolved === '/workspace' || resolved.startsWith('/workspace/')) {\n return resolved;\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Terminal ID validation\n// ---------------------------------------------------------------------------\n\n/**\n * Validate a terminal ID. Rejects path traversal, control chars, and excessive length.\n * Returns the validated ID or null if invalid.\n */\nexport function validateTerminalId(id: string): string | null {\n if (!/^[a-zA-Z0-9._-]{1,128}$/.test(id)) return null;\n if (id.includes('..')) return null;\n return id;\n}\n\n// ---------------------------------------------------------------------------\n// SSE-to-binary stream conversion\n// ---------------------------------------------------------------------------\n\n/**\n * Convert an SSE stream from readFileStream() into a raw byte stream.\n * Decodes base64 chunks for binary files and UTF-8-encodes text chunks.\n */\nexport function sseToByteStream(\n sse: ReadableStream<Uint8Array>\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n const iterator: AsyncIterator<string | Uint8Array> =\n streamFile(sse)[Symbol.asyncIterator]();\n let finished = false;\n\n async function finish(cancelSource: boolean): Promise<void> {\n if (finished) return;\n finished = true;\n if (!cancelSource) return;\n await iterator.return?.().catch(() => undefined);\n }\n\n return new ReadableStream<Uint8Array>(\n {\n async pull(controller) {\n try {\n const result = await iterator.next();\n if (result.done) {\n await finish(false);\n controller.close();\n return;\n }\n controller.enqueue(\n result.value instanceof Uint8Array\n ? result.value\n : encoder.encode(result.value)\n );\n } catch (error) {\n await finish(true);\n controller.error(error);\n }\n },\n async cancel() {\n await finish(true);\n }\n },\n { highWaterMark: 0 }\n );\n}\n\nexport function withStreamCleanup(\n source: ReadableStream<Uint8Array>,\n cleanup: () => Promise<void>\n): ReadableStream<Uint8Array> {\n const reader = source.getReader();\n let finished = false;\n\n async function finish(cancelSource: boolean): Promise<void> {\n if (finished) return;\n finished = true;\n if (cancelSource) {\n await reader.cancel().catch(() => undefined);\n }\n reader.releaseLock();\n await cleanup().catch(() => undefined);\n }\n\n return new ReadableStream<Uint8Array>(\n {\n async pull(controller) {\n try {\n const result = await reader.read();\n if (result.done) {\n await finish(false);\n controller.close();\n return;\n }\n controller.enqueue(result.value);\n } catch (error) {\n await finish(true);\n controller.error(error);\n }\n },\n async cancel() {\n await finish(true);\n }\n },\n { highWaterMark: 0 }\n );\n}\n","/**\n * OpenAPI 3.1 schema for the Cloudflare Sandbox Service API.\n *\n * Served at GET /v1/openapi.json (requires Bearer token auth).\n */\n\nexport const OPENAPI_BASE = {\n openapi: '3.1.0',\n info: {\n title: 'Cloudflare Sandbox Service API',\n version: '1.0.0',\n description:\n 'HTTP API consumed by the Python `CloudflareSandboxClient`. ' +\n 'Forwards each operation to a named Cloudflare Sandbox Durable Object via the `@cloudflare/sandbox` SDK.'\n },\n components: {\n securitySchemes: {\n BearerAuth: {\n type: 'http',\n scheme: 'bearer',\n description:\n 'API token set via `wrangler secret put SANDBOX_API_KEY`. The /openapi.* routes also accept the token as a `?token=` query parameter.'\n }\n },\n schemas: {\n ProcessCreateRequest: {\n type: 'object',\n required: ['argv'],\n properties: {\n argv: {\n type: 'array',\n items: { type: 'string' },\n minItems: 1,\n description: 'Argv array to launch directly.',\n example: ['sh', '-lc', 'echo hello']\n },\n timeout: {\n type: 'integer',\n description:\n 'Remote process lifetime deadline in milliseconds. When reached, the sandbox may stop the process and the process exit outcome reports `timedOut: true`; this is not caller-local observation cancellation.',\n example: 30000\n },\n cwd: {\n type: 'string',\n description:\n 'Working directory for the command (defaults to sandbox cwd).',\n example: '/workspace'\n },\n env: {\n type: 'object',\n additionalProperties: { type: 'string' },\n description: 'Environment overrides for the process.'\n }\n }\n },\n ProcessStatus: {\n oneOf: [\n {\n type: 'object',\n required: ['id', 'pid', 'command', 'state', 'startedAt'],\n properties: {\n id: { type: 'string' },\n pid: { type: 'integer' },\n command: { type: 'array', items: { type: 'string' } },\n cwd: { type: 'string' },\n state: { const: 'running' },\n startedAt: { type: 'string' }\n }\n },\n {\n type: 'object',\n required: [\n 'id',\n 'pid',\n 'command',\n 'state',\n 'startedAt',\n 'endedAt',\n 'exit'\n ],\n properties: {\n id: { type: 'string' },\n pid: { type: 'integer' },\n command: { type: 'array', items: { type: 'string' } },\n cwd: { type: 'string' },\n state: { const: 'exited' },\n startedAt: { type: 'string' },\n endedAt: { type: 'string' },\n exit: {\n type: 'object',\n required: ['code', 'timedOut'],\n properties: {\n code: { type: 'integer' },\n signal: { type: 'integer' },\n timedOut: { type: 'boolean' }\n }\n }\n }\n },\n {\n type: 'object',\n required: [\n 'id',\n 'pid',\n 'command',\n 'state',\n 'startedAt',\n 'endedAt',\n 'error'\n ],\n properties: {\n id: { type: 'string' },\n pid: { type: 'integer' },\n command: { type: 'array', items: { type: 'string' } },\n cwd: { type: 'string' },\n state: { const: 'error' },\n startedAt: { type: 'string' },\n endedAt: { type: 'string' },\n error: {\n type: 'object',\n required: ['code', 'message'],\n properties: {\n code: { type: 'string' },\n message: { type: 'string' }\n }\n }\n }\n }\n ],\n discriminator: { propertyName: 'state' }\n },\n\n WriteResponse: {\n type: 'object',\n required: ['ok'],\n properties: {\n ok: {\n type: 'boolean',\n enum: [true],\n description: 'Always `true` on success.'\n }\n }\n },\n RunningResponse: {\n type: 'object',\n required: ['running'],\n properties: {\n running: {\n type: 'boolean',\n description:\n '`true` if the sandbox container is alive and responding.'\n }\n }\n },\n OkResponse: {\n type: 'object',\n required: ['ok'],\n properties: {\n ok: {\n type: 'boolean',\n enum: [true],\n description: 'Always `true` on success.'\n }\n }\n },\n MountBucketCredentials: {\n type: 'object',\n required: ['accessKeyId', 'secretAccessKey'],\n properties: {\n accessKeyId: {\n type: 'string',\n description: 'S3-compatible access key ID.'\n },\n secretAccessKey: {\n type: 'string',\n description: 'S3-compatible secret access key.'\n }\n }\n },\n MountBucketRequestOptions: {\n type: 'object',\n properties: {\n endpoint: {\n type: 'string',\n description:\n 'S3-compatible endpoint URL for remote mounts. Mutually exclusive with top-level `binding`.',\n example: 'https://YOUR_ACCOUNT_ID.r2.cloudflarestorage.com'\n },\n readOnly: {\n type: 'boolean',\n description: 'Mount filesystem as read-only (default: false).',\n default: false\n },\n prefix: {\n type: 'string',\n description:\n 'Optional prefix/subdirectory within the bucket to mount. Must start with `/`. Trailing slashes are stripped automatically.',\n example: '/uploads/images'\n },\n credentials: {\n $ref: '#/components/schemas/MountBucketCredentials',\n description:\n 'Explicit credentials. When omitted, the SDK auto-detects from Worker secrets (R2_ACCESS_KEY_ID / R2_SECRET_ACCESS_KEY or AWS equivalents).'\n },\n credentialProxy: {\n type: 'boolean',\n description:\n 'Keep credentials in the Durable Object and sign intercepted s3fs requests from the Worker. Credentials may be explicit or auto-detected from Worker secrets.',\n default: false\n },\n s3fsOptions: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Advanced: Override or extend s3fs mount options for both remote mounts and R2 binding mounts.',\n example: ['nomultipart']\n }\n }\n },\n MountBucketRequest: {\n type: 'object',\n required: ['mountPath', 'options'],\n properties: {\n bucket: {\n type: 'string',\n description:\n 'Remote bucket name for endpoint-based S3-compatible mounts.',\n example: 'my-r2-bucket'\n },\n binding: {\n type: 'string',\n description:\n 'Worker R2 binding name for credential-less R2 binding mounts. Mutually exclusive with `options.endpoint`.',\n example: 'MY_BUCKET'\n },\n mountPath: {\n type: 'string',\n description: 'Absolute path in the container to mount at.',\n example: '/mnt/data'\n },\n options: {\n $ref: '#/components/schemas/MountBucketRequestOptions'\n }\n }\n },\n UnmountBucketRequest: {\n type: 'object',\n required: ['mountPath'],\n properties: {\n mountPath: {\n type: 'string',\n description: 'Absolute path where the bucket is currently mounted.',\n example: '/mnt/data'\n }\n }\n },\n TunnelRequest: {\n type: 'object',\n properties: {\n name: {\n type: 'string',\n description:\n 'Subdomain prefix for a named tunnel, such as `app`. Do not pass a full hostname. Omit to create or reuse an ephemeral tunnel.',\n example: 'app'\n }\n }\n },\n Tunnel: {\n type: 'object',\n required: ['id', 'port', 'url', 'hostname', 'createdAt'],\n properties: {\n id: { type: 'string' },\n port: {\n type: 'integer',\n description: 'Container port served by the tunnel.',\n example: 8080\n },\n url: {\n type: 'string',\n format: 'uri',\n example: 'https://app.example.com'\n },\n hostname: {\n type: 'string',\n example: 'app.example.com'\n },\n createdAt: {\n type: 'string',\n format: 'date-time'\n },\n name: {\n type: 'string',\n description: 'Present for named tunnels only.',\n example: 'app'\n }\n }\n },\n ErrorResponse: {\n type: 'object',\n required: ['error', 'code'],\n properties: {\n error: {\n type: 'string',\n description: 'Human-readable error description.'\n },\n code: {\n type: 'string',\n description: 'Stable machine-readable error code.',\n enum: [\n 'unauthorized',\n 'invalid_request',\n 'exec_error',\n 'exec_transport_error',\n 'workspace_read_not_found',\n 'workspace_archive_read_error',\n 'workspace_archive_write_error',\n 'capacity_exceeded',\n 'pool_error',\n 'mount_error',\n 'unmount_error',\n 'tunnel_error'\n ]\n }\n }\n },\n PoolStats: {\n type: 'object',\n required: ['warm', 'assigned', 'total', 'config', 'maxInstances'],\n properties: {\n warm: {\n type: 'integer',\n description: 'Number of warm (unassigned) containers ready for use.'\n },\n assigned: {\n type: 'integer',\n description: 'Number of containers assigned to sandbox IDs.'\n },\n total: {\n type: 'integer',\n description: 'Total containers tracked by the pool.'\n },\n config: {\n type: 'object',\n properties: {\n warmTarget: { type: 'integer' },\n refreshInterval: { type: 'integer' }\n }\n },\n maxInstances: {\n type: ['integer', 'null'],\n description:\n 'Inferred max_instances limit, or null if not yet known.'\n }\n }\n }\n },\n responses: {\n Unauthorized: {\n description: 'Missing or invalid Bearer token.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: { error: 'Unauthorized', code: 'unauthorized' }\n }\n }\n },\n InvalidRequest: {\n description: 'Malformed request body or missing required fields.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: {\n error: 'argv must be a non-empty array',\n code: 'invalid_request'\n }\n }\n }\n },\n NotFound: {\n description: 'Requested resource was not found.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: { error: 'Process not found', code: 'not_found' }\n }\n }\n },\n BadGateway: {\n description: 'Sandbox operation failed.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: { error: 'process launch failed', code: 'process_error' }\n }\n }\n }\n }\n },\n security: [{ BearerAuth: [] }]\n} as const;\n","export const FILESPaths = {\n '/v1/sandbox/{id}/file/{path}': {\n get: {\n operationId: 'readFile',\n summary: 'Read a file from the sandbox filesystem',\n 'x-codeSamples': [\n {\n lang: 'curl',\n label: 'cURL',\n source:\n 'curl -X GET https://$HOST/v1/sandbox/my-sandbox/file/workspace/main.py \\\\\\n' +\n ' -H \"Authorization: Bearer $SANDBOX_API_KEY\" \\\\\\n' +\n ' -o main.py'\n }\n ],\n parameters: [\n {\n name: 'id',\n in: 'path',\n required: true,\n schema: { type: 'string' },\n description: 'Sandbox instance name.'\n },\n {\n name: 'path',\n in: 'path',\n required: true,\n schema: { type: 'string' },\n description:\n 'File path inside the sandbox, without leading slash (e.g. workspace/main.py). Must resolve within /workspace.'\n }\n ],\n responses: {\n '200': {\n description: 'Raw file bytes.',\n content: {\n 'application/octet-stream': {\n schema: { type: 'string', format: 'binary' }\n }\n }\n },\n '400': { $ref: '#/components/responses/InvalidRequest' },\n '401': { $ref: '#/components/responses/Unauthorized' },\n '403': {\n description: 'Path resolves outside /workspace.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: {\n error: 'path must resolve to a location within /workspace',\n code: 'invalid_request'\n }\n }\n }\n },\n '404': {\n description: 'File not found in the sandbox.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: {\n error: 'File not found: /workspace/foo.txt',\n code: 'workspace_read_not_found'\n }\n }\n }\n },\n '502': {\n description: 'SDK read call failed.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: {\n error: 'read failed: connection reset',\n code: 'exec_transport_error'\n }\n }\n }\n }\n }\n },\n put: {\n operationId: 'writeFile',\n summary: 'Write a file into the sandbox filesystem',\n 'x-codeSamples': [\n {\n lang: 'curl',\n label: 'cURL',\n source:\n 'curl -X PUT https://$HOST/v1/sandbox/my-sandbox/file/workspace/main.py \\\\\\n' +\n ' -H \"Authorization: Bearer $SANDBOX_API_KEY\" \\\\\\n' +\n ' -H \"Content-Type: application/octet-stream\" \\\\\\n' +\n ' --data-binary @main.py'\n }\n ],\n parameters: [\n {\n name: 'id',\n in: 'path',\n required: true,\n schema: { type: 'string' },\n description: 'Sandbox instance name.'\n },\n {\n name: 'path',\n in: 'path',\n required: true,\n schema: { type: 'string' },\n description:\n 'File path inside the sandbox, without leading slash (e.g. workspace/main.py). Must resolve within /workspace.'\n }\n ],\n requestBody: {\n required: true,\n description: 'Raw file content to write.',\n content: {\n 'application/octet-stream': {\n schema: { type: 'string', format: 'binary' }\n }\n }\n },\n responses: {\n '200': {\n description: 'File written successfully.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/WriteResponse' }\n }\n }\n },\n '400': { $ref: '#/components/responses/InvalidRequest' },\n '401': { $ref: '#/components/responses/Unauthorized' },\n '403': {\n description: 'Path resolves outside /workspace.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: {\n error: 'path must resolve to a location within /workspace',\n code: 'invalid_request'\n }\n }\n }\n },\n '502': {\n description: 'SDK write call failed.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: {\n error: 'write failed: connection reset',\n code: 'workspace_archive_write_error'\n }\n }\n }\n }\n }\n }\n },\n '/v1/sandbox/{id}/persist': {\n post: {\n operationId: 'persistWorkspace',\n summary: 'Serialize the sandbox workspace to a tar archive',\n description:\n 'Archives the /workspace directory inside the sandbox and streams the resulting tar back as raw bytes.',\n 'x-codeSamples': [\n {\n lang: 'curl',\n label: 'cURL',\n source:\n 'curl -X POST https://$HOST/v1/sandbox/my-sandbox/persist \\\\\\n' +\n ' -H \"Authorization: Bearer $SANDBOX_API_KEY\" \\\\\\n' +\n ' -o workspace.tar'\n }\n ],\n parameters: [\n {\n name: 'id',\n in: 'path',\n required: true,\n schema: { type: 'string' },\n description: 'Sandbox instance name.'\n },\n {\n name: 'excludes',\n in: 'query',\n required: false,\n schema: { type: 'string' },\n description:\n 'Comma-separated list of relative paths to exclude from the archive.',\n example: '__pycache__,.venv'\n }\n ],\n responses: {\n '200': {\n description: 'Raw tar archive bytes.',\n content: {\n 'application/octet-stream': {\n schema: { type: 'string', format: 'binary' }\n }\n }\n },\n '400': {\n description: 'Invalid exclude paths (e.g. path traversal).',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: {\n error: 'exclude paths must not contain \"..\"',\n code: 'invalid_request'\n }\n }\n }\n },\n '401': { $ref: '#/components/responses/Unauthorized' },\n '502': {\n description: 'tar command failed inside the sandbox.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: {\n error: 'tar failed (exit 1): ...',\n code: 'workspace_archive_read_error'\n }\n }\n }\n }\n }\n }\n },\n '/v1/sandbox/{id}/hydrate': {\n post: {\n operationId: 'hydrateWorkspace',\n summary: 'Populate the sandbox workspace from a tar archive',\n description:\n 'Accepts a raw tar archive as the request body and extracts it into /workspace inside the sandbox.',\n 'x-codeSamples': [\n {\n lang: 'curl',\n label: 'cURL',\n source:\n 'curl -X POST https://$HOST/v1/sandbox/my-sandbox/hydrate \\\\\\n' +\n ' -H \"Authorization: Bearer $SANDBOX_API_KEY\" \\\\\\n' +\n ' -H \"Content-Type: application/octet-stream\" \\\\\\n' +\n ' --data-binary @workspace.tar'\n }\n ],\n parameters: [\n {\n name: 'id',\n in: 'path',\n required: true,\n schema: { type: 'string' },\n description: 'Sandbox instance name.'\n }\n ],\n requestBody: {\n required: true,\n description: 'Raw tar archive bytes.',\n content: {\n 'application/octet-stream': {\n schema: { type: 'string', format: 'binary' }\n }\n }\n },\n responses: {\n '200': {\n description: 'Archive extracted successfully.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/OkResponse' }\n }\n }\n },\n '400': { $ref: '#/components/responses/InvalidRequest' },\n '401': { $ref: '#/components/responses/Unauthorized' },\n '502': {\n description: 'tar extract failed inside the sandbox.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: {\n error: 'tar extract failed (exit 1): ...',\n code: 'workspace_archive_write_error'\n }\n }\n }\n }\n }\n }\n },\n '/v1/sandbox/{id}/mount': {\n post: {\n operationId: 'mountBucket',\n summary: 'Mount an S3-compatible bucket into the container',\n description:\n 'Mounts an S3-compatible bucket (R2, S3, GCS, etc.) as a local directory via s3fs-FUSE. ' +\n 'Credentials are optional — the SDK auto-detects from Worker secrets when omitted.',\n 'x-codeSamples': [\n {\n lang: 'curl',\n label: 'cURL',\n source:\n 'curl -X POST https://$HOST/v1/sandbox/my-sandbox/mount \\\\\\n' +\n ' -H \"Authorization: Bearer $SANDBOX_API_KEY\" \\\\\\n' +\n ' -H \"Content-Type: application/json\" \\\\\\n' +\n ' -d \\'{\"bucket\":\"my-bucket\",\"mountPath\":\"/mnt/data\",\"options\":{\"endpoint\":\"https://ACCT.r2.cloudflarestorage.com\"}}\\''\n }\n ],\n parameters: [\n {\n name: 'id',\n in: 'path',\n required: true,\n schema: { type: 'string' },\n description: 'Sandbox instance name.'\n }\n ],\n requestBody: {\n required: true,\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/MountBucketRequest' }\n }\n }\n },\n responses: {\n '200': {\n description: 'Bucket mounted successfully.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/OkResponse' }\n }\n }\n },\n '400': { $ref: '#/components/responses/InvalidRequest' },\n '401': { $ref: '#/components/responses/Unauthorized' },\n '502': {\n description:\n 'SDK mount call failed (invalid config, duplicate mount, or s3fs error).',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: {\n error: 'mount failed: Mount path already in use',\n code: 'mount_error'\n }\n }\n }\n }\n }\n }\n },\n '/v1/sandbox/{id}/unmount': {\n post: {\n operationId: 'unmountBucket',\n summary: 'Unmount a previously mounted bucket',\n description:\n 'Unmounts a bucket filesystem that was previously mounted via `/v1/sandbox/{id}/mount`.',\n 'x-codeSamples': [\n {\n lang: 'curl',\n label: 'cURL',\n source:\n 'curl -X POST https://$HOST/v1/sandbox/my-sandbox/unmount \\\\\\n' +\n ' -H \"Authorization: Bearer $SANDBOX_API_KEY\" \\\\\\n' +\n ' -H \"Content-Type: application/json\" \\\\\\n' +\n ' -d \\'{\"mountPath\":\"/mnt/data\"}\\''\n }\n ],\n parameters: [\n {\n name: 'id',\n in: 'path',\n required: true,\n schema: { type: 'string' },\n description: 'Sandbox instance name.'\n }\n ],\n requestBody: {\n required: true,\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/UnmountBucketRequest' }\n }\n }\n },\n responses: {\n '200': {\n description: 'Bucket unmounted successfully.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/OkResponse' }\n }\n }\n },\n '400': { $ref: '#/components/responses/InvalidRequest' },\n '401': { $ref: '#/components/responses/Unauthorized' },\n '502': {\n description:\n 'SDK unmount call failed (no active mount or unmount error).',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: {\n error: 'unmount failed: No active mount found',\n code: 'unmount_error'\n }\n }\n }\n }\n }\n }\n }\n} as const;\n","export const LIFECYCLEPaths = {\n '/v1/sandbox': {\n post: {\n operationId: 'createSandbox',\n summary: 'Create a new sandbox',\n description:\n 'Generates a new unique sandbox ID. Use this ID with all `/v1/sandbox/{id}/*` routes.',\n 'x-codeSamples': [\n {\n lang: 'curl',\n label: 'cURL',\n source:\n 'curl -X POST https://$HOST/v1/sandbox \\\\\\n -H \"Authorization: Bearer $SANDBOX_API_KEY\"'\n }\n ],\n responses: {\n '200': {\n description: 'New sandbox created.',\n content: {\n 'application/json': {\n schema: {\n type: 'object',\n required: ['id'],\n properties: {\n id: {\n type: 'string',\n description:\n 'Unique sandbox ID for use with `/v1/sandbox/{id}/*` routes.',\n example: 'mfrggzdfmy2tqnrzgezdgnbv'\n }\n }\n }\n }\n }\n },\n '401': { $ref: '#/components/responses/Unauthorized' }\n }\n }\n },\n '/v1/sandbox/{id}': {\n delete: {\n operationId: 'deleteSandbox',\n summary: 'Destroy a sandbox instance (best-effort)',\n description:\n 'Calls destroy() on the sandbox Durable Object to release container resources. ' +\n 'Best-effort: unknown sandbox IDs return 204 without allocating a container.',\n 'x-codeSamples': [\n {\n lang: 'curl',\n label: 'cURL',\n source:\n 'curl -X DELETE https://$HOST/v1/sandbox/my-sandbox \\\\\\n' +\n ' -H \"Authorization: Bearer $SANDBOX_API_KEY\"'\n }\n ],\n parameters: [\n {\n name: 'id',\n in: 'path',\n required: true,\n schema: { type: 'string' },\n description: 'Sandbox instance name.'\n }\n ],\n responses: {\n '204': {\n description:\n 'Sandbox destroyed (best-effort). Container resources are released.'\n },\n '401': { $ref: '#/components/responses/Unauthorized' }\n }\n }\n },\n '/health': {\n get: {\n operationId: 'healthCheck',\n summary: 'Worker health check',\n description: 'Simple liveness probe. Not protected by authentication.',\n 'x-codeSamples': [\n {\n lang: 'curl',\n label: 'cURL',\n source: 'curl https://$HOST/health'\n }\n ],\n security: [],\n responses: {\n '200': {\n description: 'Worker is up.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/OkResponse' }\n }\n }\n }\n }\n }\n },\n '/v1/openapi.json': {\n get: {\n operationId: 'getOpenApiSchema',\n summary: 'OpenAPI schema',\n description: 'Returns this OpenAPI 3.1 schema document.',\n 'x-codeSamples': [\n {\n lang: 'curl',\n label: 'cURL',\n source:\n 'curl https://$HOST/v1/openapi.json \\\\\\n' +\n ' -H \"Authorization: Bearer $SANDBOX_API_KEY\"'\n }\n ],\n responses: {\n '200': {\n description: 'OpenAPI schema document.',\n content: {\n 'application/json': {\n schema: { type: 'object' }\n }\n }\n },\n '401': { $ref: '#/components/responses/Unauthorized' }\n }\n }\n },\n '/v1/pool/stats': {\n get: {\n operationId: 'getPoolStats',\n summary: 'Pool statistics',\n description:\n 'Returns current warm pool statistics including warm/assigned counts and configuration.',\n 'x-codeSamples': [\n {\n lang: 'curl',\n label: 'cURL',\n source:\n 'curl https://$HOST/v1/pool/stats \\\\\\n' +\n ' -H \"Authorization: Bearer $SANDBOX_API_KEY\"'\n }\n ],\n responses: {\n '200': {\n description: 'Pool statistics.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/PoolStats' }\n }\n }\n },\n '401': { $ref: '#/components/responses/Unauthorized' }\n }\n }\n },\n '/v1/pool/shutdown-prewarmed': {\n post: {\n operationId: 'shutdownPrewarmed',\n summary: 'Shutdown pre-warmed containers',\n description:\n 'Destroys all idle (unassigned) warm containers. Does not affect containers assigned to sandbox instances.',\n 'x-codeSamples': [\n {\n lang: 'curl',\n label: 'cURL',\n source:\n 'curl -X POST https://$HOST/v1/pool/shutdown-prewarmed \\\\\\n' +\n ' -H \"Authorization: Bearer $SANDBOX_API_KEY\"'\n }\n ],\n responses: {\n '200': {\n description: 'All pre-warmed containers destroyed.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/OkResponse' }\n }\n }\n },\n '401': { $ref: '#/components/responses/Unauthorized' }\n }\n }\n },\n '/v1/pool/prime': {\n post: {\n operationId: 'primePool',\n summary: 'Prime the warm pool',\n description:\n 'Pushes the current pool configuration and starts the alarm loop. ' +\n 'Called automatically by the cron trigger; can also be called manually after deploy.',\n 'x-codeSamples': [\n {\n lang: 'curl',\n label: 'cURL',\n source:\n 'curl -X POST https://$HOST/v1/pool/prime \\\\\\n' +\n ' -H \"Authorization: Bearer $SANDBOX_API_KEY\"'\n }\n ],\n responses: {\n '200': {\n description: 'Pool primed successfully.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/OkResponse' }\n }\n }\n },\n '401': { $ref: '#/components/responses/Unauthorized' }\n }\n }\n }\n} as const;\n","const sandboxIdParameter = {\n name: 'id',\n in: 'path',\n required: true,\n schema: { type: 'string' },\n description: 'Sandbox instance name.'\n} as const;\n\nconst processIdParameter = {\n name: 'processId',\n in: 'path',\n required: true,\n schema: { type: 'string' }\n} as const;\n\nconst processStatusResponse = {\n description: 'Process status.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ProcessStatus' }\n }\n }\n} as const;\n\nexport const PROCESSESPaths = {\n '/v1/sandbox/{id}/processes': {\n post: {\n operationId: 'createProcess',\n summary: 'Launch a sandbox process',\n parameters: [sandboxIdParameter],\n requestBody: {\n required: true,\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ProcessCreateRequest' }\n }\n }\n },\n responses: {\n '200': processStatusResponse,\n '400': { $ref: '#/components/responses/InvalidRequest' },\n '401': { $ref: '#/components/responses/Unauthorized' },\n '403': { $ref: '#/components/responses/InvalidRequest' },\n '502': { $ref: '#/components/responses/BadGateway' }\n }\n },\n get: {\n operationId: 'listProcesses',\n summary: 'List sandbox processes',\n parameters: [sandboxIdParameter],\n responses: {\n '200': {\n description: 'Process statuses.',\n content: {\n 'application/json': {\n schema: {\n type: 'array',\n items: { $ref: '#/components/schemas/ProcessStatus' }\n }\n }\n }\n },\n '401': { $ref: '#/components/responses/Unauthorized' }\n }\n }\n },\n '/v1/sandbox/{id}/processes/{processId}': {\n get: {\n operationId: 'getProcess',\n summary: 'Get a sandbox process',\n parameters: [sandboxIdParameter, processIdParameter],\n responses: {\n '200': processStatusResponse,\n '401': { $ref: '#/components/responses/Unauthorized' },\n '404': { $ref: '#/components/responses/NotFound' }\n }\n }\n },\n '/v1/sandbox/{id}/processes/{processId}/logs': {\n get: {\n operationId: 'readProcessLogs',\n summary: 'Stream sandbox process logs',\n description:\n 'Returns Server-Sent Events. stdout/stderr event data is base64-encoded at the bridge boundary only.',\n parameters: [\n sandboxIdParameter,\n processIdParameter,\n { name: 'since', in: 'query', schema: { type: 'string' } },\n { name: 'replay', in: 'query', schema: { type: 'boolean' } },\n { name: 'follow', in: 'query', schema: { type: 'boolean' } }\n ],\n responses: {\n '200': {\n description: 'SSE stream of process log events.',\n content: { 'text/event-stream': { schema: { type: 'string' } } }\n },\n '401': { $ref: '#/components/responses/Unauthorized' },\n '404': { $ref: '#/components/responses/NotFound' }\n }\n }\n },\n '/v1/sandbox/{id}/processes/{processId}/kill': {\n post: {\n operationId: 'signalSandboxProcess',\n summary: 'Signal a sandbox process',\n parameters: [sandboxIdParameter, processIdParameter],\n requestBody: {\n required: false,\n content: {\n 'application/json': {\n schema: {\n type: 'object',\n properties: {\n signal: {\n type: 'integer',\n minimum: 1,\n maximum: 64,\n default: 15\n }\n }\n }\n }\n }\n },\n responses: {\n '204': { description: 'Signal sent.' },\n '400': { $ref: '#/components/responses/InvalidRequest' },\n '401': { $ref: '#/components/responses/Unauthorized' },\n '404': { $ref: '#/components/responses/NotFound' }\n }\n }\n },\n '/v1/sandbox/{id}/tunnel/{port}': {\n post: {\n operationId: 'createTunnel',\n summary: 'Create or reuse a tunnel for a sandbox port',\n parameters: [\n sandboxIdParameter,\n {\n name: 'port',\n in: 'path',\n required: true,\n schema: { type: 'integer', minimum: 1024, maximum: 65535 }\n }\n ],\n responses: {\n '200': { description: 'Tunnel created or reused.' },\n '400': { $ref: '#/components/responses/InvalidRequest' },\n '401': { $ref: '#/components/responses/Unauthorized' },\n '502': { $ref: '#/components/responses/BadGateway' }\n }\n },\n delete: {\n operationId: 'deleteTunnel',\n summary: 'Delete the tunnel for a sandbox port',\n parameters: [\n sandboxIdParameter,\n {\n name: 'port',\n in: 'path',\n required: true,\n schema: { type: 'integer', minimum: 1024, maximum: 65535 }\n }\n ],\n responses: {\n '204': { description: 'Tunnel deleted or already absent.' },\n '400': { $ref: '#/components/responses/InvalidRequest' },\n '401': { $ref: '#/components/responses/Unauthorized' },\n '502': { $ref: '#/components/responses/BadGateway' }\n }\n }\n },\n '/v1/sandbox/{id}/running': {\n get: {\n operationId: 'isSandboxRunning',\n summary: 'Check whether the sandbox container is alive',\n parameters: [sandboxIdParameter],\n responses: {\n '200': {\n description: 'Liveness status.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/RunningResponse' }\n }\n }\n },\n '401': { $ref: '#/components/responses/Unauthorized' }\n }\n }\n }\n} as const;\n","const terminalSnapshotSchema = {\n type: 'object',\n required: ['id', 'command', 'status'],\n properties: {\n id: { type: 'string' },\n pid: { type: 'integer' },\n command: { type: 'array', items: { type: 'string' } },\n cwd: { type: 'string' },\n status: { type: 'string', enum: ['running', 'exited'] },\n exit: {\n type: 'object',\n properties: {\n code: { type: 'integer', nullable: true },\n signal: { oneOf: [{ type: 'string' }, { type: 'integer' }] },\n timedOut: { type: 'boolean' }\n }\n }\n }\n} as const;\n\nconst terminalIdParameter = {\n name: 'terminalId',\n in: 'path',\n required: true,\n schema: { type: 'string', pattern: '^[a-zA-Z0-9._-]{1,128}$' }\n} as const;\n\nconst sandboxIdParameter = {\n name: 'id',\n in: 'path',\n required: true,\n schema: { type: 'string' },\n description: 'Sandbox instance name.'\n} as const;\n\nconst terminalErrorResponses = {\n '400': {\n description: 'Invalid request.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' }\n }\n }\n },\n '401': { $ref: '#/components/responses/Unauthorized' },\n '502': {\n description: 'Terminal operation failed.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' }\n }\n }\n }\n} as const;\n\nexport const TERMINALSPaths = {\n '/v1/sandbox/{id}/terminals': {\n post: {\n operationId: 'createTerminal',\n summary: 'Create a terminal',\n requestBody: {\n required: true,\n content: {\n 'application/json': {\n schema: {\n type: 'object',\n required: ['argv'],\n properties: {\n argv: { type: 'array', items: { type: 'string' }, minItems: 1 },\n cwd: { type: 'string' },\n env: {\n type: 'object',\n additionalProperties: { type: 'string' }\n },\n cols: { type: 'integer' },\n rows: { type: 'integer' }\n }\n }\n }\n }\n },\n parameters: [sandboxIdParameter],\n responses: {\n '200': {\n description: 'Terminal created with a generated ID.',\n content: { 'application/json': { schema: terminalSnapshotSchema } }\n },\n ...terminalErrorResponses\n }\n },\n get: {\n operationId: 'listTerminals',\n summary: 'List terminals',\n parameters: [sandboxIdParameter],\n responses: {\n '200': {\n description: 'Terminal snapshots.',\n content: {\n 'application/json': {\n schema: { type: 'array', items: terminalSnapshotSchema }\n }\n }\n },\n ...terminalErrorResponses\n }\n }\n },\n '/v1/sandbox/{id}/terminals/{terminalId}': {\n get: {\n operationId: 'getTerminal',\n summary: 'Get a terminal snapshot',\n parameters: [sandboxIdParameter, terminalIdParameter],\n responses: {\n '200': {\n description: 'Terminal snapshot.',\n content: { 'application/json': { schema: terminalSnapshotSchema } }\n },\n '404': { description: 'Terminal not found.' },\n ...terminalErrorResponses\n }\n }\n },\n '/v1/sandbox/{id}/terminals/{terminalId}/connect': {\n get: {\n operationId: 'connectTerminal',\n summary: 'Connect to a terminal WebSocket',\n description:\n 'WebSocket binary client frames are terminal input bytes. JSON client controls are resize, interrupt, and terminate. Server output is a JSON chunk control immediately followed by one binary frame. Cursor advances after the binary frame is consumed.',\n parameters: [\n sandboxIdParameter,\n terminalIdParameter,\n {\n name: 'cursor',\n in: 'query',\n required: false,\n schema: { type: 'string' }\n },\n {\n name: 'cols',\n in: 'query',\n required: false,\n schema: { type: 'integer' }\n },\n {\n name: 'rows',\n in: 'query',\n required: false,\n schema: { type: 'integer' }\n }\n ],\n responses: {\n '101': { description: 'WebSocket upgrade successful.' },\n '404': { description: 'Terminal not found.' },\n ...terminalErrorResponses\n }\n }\n },\n '/v1/sandbox/{id}/terminals/{terminalId}/interrupt': {\n post: {\n operationId: 'interruptTerminal',\n summary: 'Interrupt a terminal',\n parameters: [sandboxIdParameter, terminalIdParameter],\n responses: {\n '204': { description: 'Interrupt signal sent.' },\n '404': { description: 'Terminal not found.' },\n ...terminalErrorResponses\n }\n }\n },\n '/v1/sandbox/{id}/terminals/{terminalId}/terminate': {\n post: {\n operationId: 'terminateTerminal',\n summary: 'Terminate a terminal',\n parameters: [sandboxIdParameter, terminalIdParameter],\n responses: {\n '204': { description: 'Terminate signal sent.' },\n '404': { description: 'Terminal not found.' },\n ...terminalErrorResponses\n }\n }\n }\n} as const;\n","import { OPENAPI_BASE } from './openapi/common';\nimport { FILESPaths } from './openapi/files';\nimport { LIFECYCLEPaths } from './openapi/lifecycle';\nimport { PROCESSESPaths } from './openapi/processes';\nimport { TERMINALSPaths } from './openapi/terminals';\n\nexport const OPENAPI_SCHEMA = {\n ...OPENAPI_BASE,\n paths: {\n ...LIFECYCLEPaths,\n ...PROCESSESPaths,\n ...FILESPaths,\n ...TERMINALSPaths\n }\n} as const;\n","/**\n * Renders an OpenAPI 3.x schema object as a self-contained HTML page.\n *\n * No external dependencies — pure HTML/CSS/JS generated server-side.\n * The schema is embedded as JSON and rendered client-side via a small\n * inline script.\n */\n\nexport function renderOpenApiHtml(schema: Record<string, unknown>): string {\n const json = JSON.stringify(schema);\n\n return /* html */ `<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>${esc((schema.info as Record<string, string>)?.title ?? 'API Reference')}</title>\n <style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n\n :root {\n --bg: #0f1117;\n --surface: #1a1d27;\n --border: #2a2d3a;\n --text: #e2e8f0;\n --muted: #8892a4;\n --accent: #6366f1;\n --get: #22c55e;\n --post: #3b82f6;\n --put: #f59e0b;\n --delete: #ef4444;\n --patch: #a855f7;\n --radius: 6px;\n --font-mono: ui-monospace, \"Cascadia Code\", \"Fira Code\", monospace;\n }\n\n body {\n background: var(--bg);\n color: var(--text);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n font-size: 14px;\n line-height: 1.6;\n display: flex;\n min-height: 100vh;\n }\n\n /* ── Sidebar ── */\n #sidebar {\n width: 260px;\n min-width: 260px;\n background: var(--surface);\n border-right: 1px solid var(--border);\n padding: 24px 0;\n position: sticky;\n top: 0;\n height: 100vh;\n overflow-y: auto;\n }\n #sidebar h1 {\n font-size: 13px;\n font-weight: 600;\n color: var(--text);\n padding: 0 20px 16px;\n border-bottom: 1px solid var(--border);\n margin-bottom: 12px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n #sidebar .version {\n font-size: 11px;\n color: var(--muted);\n font-weight: 400;\n }\n .nav-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 6px 20px;\n cursor: pointer;\n border-left: 2px solid transparent;\n transition: background 0.15s, border-color 0.15s;\n text-decoration: none;\n color: var(--muted);\n font-size: 13px;\n }\n .nav-item:hover { background: rgba(255,255,255,0.04); color: var(--text); }\n .nav-item.active { border-left-color: var(--accent); color: var(--text); background: rgba(99,102,241,0.08); }\n\n /* ── Main ── */\n #main {\n flex: 1;\n padding: 40px 48px;\n max-width: 900px;\n }\n\n /* ── Info block ── */\n #info { margin-bottom: 48px; }\n #info h2 { font-size: 28px; font-weight: 700; margin-bottom: 8px; }\n #info p { color: var(--muted); max-width: 680px; }\n #info .meta { display: flex; gap: 16px; margin-top: 12px; flex-wrap: wrap; }\n #info .badge {\n font-size: 11px;\n padding: 2px 8px;\n border-radius: 99px;\n border: 1px solid var(--border);\n color: var(--muted);\n font-family: var(--font-mono);\n }\n\n /* ── Endpoint card ── */\n .endpoint {\n border: 1px solid var(--border);\n border-radius: var(--radius);\n margin-bottom: 16px;\n overflow: hidden;\n }\n .endpoint-header {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 14px 18px;\n cursor: pointer;\n background: var(--surface);\n user-select: none;\n transition: background 0.15s;\n }\n .endpoint-header:hover { background: #1e2130; }\n .endpoint-header.open { background: #1e2130; border-bottom: 1px solid var(--border); }\n\n .method {\n font-family: var(--font-mono);\n font-size: 11px;\n font-weight: 700;\n padding: 3px 8px;\n border-radius: 4px;\n min-width: 58px;\n text-align: center;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n .method-get { background: rgba(34,197,94,.15); color: var(--get); }\n .method-post { background: rgba(59,130,246,.15); color: var(--post); }\n .method-put { background: rgba(245,158,11,.15); color: var(--put); }\n .method-delete { background: rgba(239,68,68,.15); color: var(--delete); }\n .method-patch { background: rgba(168,85,247,.15); color: var(--patch); }\n\n .endpoint-path {\n font-family: var(--font-mono);\n font-size: 13px;\n color: var(--text);\n flex: 1;\n }\n .endpoint-summary { font-size: 13px; color: var(--muted); }\n .chevron { color: var(--muted); font-size: 10px; transition: transform 0.2s; }\n .endpoint-header.open .chevron { transform: rotate(90deg); }\n\n /* ── Endpoint body ── */\n .endpoint-body { padding: 20px 18px; display: none; }\n .endpoint-body.open { display: block; }\n .endpoint-desc { color: var(--muted); margin-bottom: 16px; font-size: 13px; }\n\n /* ── Section labels ── */\n .section-label {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--muted);\n margin: 20px 0 10px;\n }\n .section-label:first-child { margin-top: 0; }\n\n /* ── Params table ── */\n table { width: 100%; border-collapse: collapse; font-size: 13px; }\n th {\n text-align: left;\n padding: 6px 10px;\n font-weight: 600;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--muted);\n border-bottom: 1px solid var(--border);\n }\n td {\n padding: 8px 10px;\n border-bottom: 1px solid var(--border);\n vertical-align: top;\n }\n tr:last-child td { border-bottom: none; }\n .param-name { font-family: var(--font-mono); color: var(--text); }\n .param-in { font-size: 11px; color: var(--muted); }\n .param-type { font-family: var(--font-mono); font-size: 11px; color: var(--accent); }\n .required { color: var(--delete); font-size: 10px; font-weight: 700; margin-left: 4px; }\n\n /* ── Response rows ── */\n .response-group { margin-bottom: 4px; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }\n .response-header {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 10px 14px;\n cursor: pointer;\n background: var(--surface);\n user-select: none;\n transition: background 0.15s;\n font-size: 13px;\n }\n .response-header:hover { background: #1e2130; }\n .response-header.open { border-bottom: 1px solid var(--border); }\n .response-detail { padding: 12px 14px; display: none; font-size: 13px; }\n .response-detail.open { display: block; }\n .response-detail .section-label { margin-top: 14px; }\n .response-detail .section-label:first-child { margin-top: 0; }\n .status-code {\n font-family: var(--font-mono);\n font-size: 12px;\n font-weight: 700;\n min-width: 40px;\n }\n .s2xx { color: var(--get); }\n .s4xx { color: var(--put); }\n .s5xx { color: var(--delete); }\n .response-desc { color: var(--muted); flex: 1; }\n .response-content-type { font-size: 11px; color: var(--muted); font-family: var(--font-mono); }\n .resp-chevron { color: var(--muted); font-size: 10px; transition: transform 0.2s; margin-left: auto; }\n .response-header.open .resp-chevron { transform: rotate(90deg); }\n\n /* ── Code block ── */\n pre {\n background: #0a0c12;\n border: 1px solid var(--border);\n border-radius: var(--radius);\n padding: 14px 16px;\n font-family: var(--font-mono);\n font-size: 12px;\n overflow-x: auto;\n color: var(--text);\n margin-top: 8px;\n }\n pre.example-block { margin-top: 4px; }\n\n /* ── Code samples ── */\n .code-samples { margin-top: 4px; }\n .code-sample-label {\n font-size: 11px;\n font-weight: 600;\n color: var(--muted);\n font-family: var(--font-mono);\n margin-bottom: 2px;\n }\n </style>\n</head>\n<body>\n <nav id=\"sidebar\"><h1 id=\"nav-title\"></h1></nav>\n <main id=\"main\"><div id=\"info\"></div><div id=\"endpoints\"></div></main>\n\n <script>\n const schema = ${json};\n\n // ── helpers ──────────────────────────────────────────────────────\n function esc(s) {\n return String(s ?? '').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');\n }\n function el(tag, attrs, ...children) {\n const e = document.createElement(tag);\n for (const [k, v] of Object.entries(attrs ?? {})) {\n if (k === 'class') e.className = v;\n else if (k === 'html') e.innerHTML = v;\n else e.setAttribute(k, v);\n }\n for (const c of children) {\n if (c == null) continue;\n e.append(typeof c === 'string' ? document.createTextNode(c) : c);\n }\n return e;\n }\n function statusClass(code) {\n const n = parseInt(code);\n if (n >= 500) return 's5xx';\n if (n >= 400) return 's4xx';\n return 's2xx';\n }\n function schemaType(s) {\n if (!s) return '';\n if (s.$ref) return s.$ref.split('/').pop();\n if (s.type === 'array') return s.items ? schemaType(s.items) + '[]' : 'array';\n return s.format ? s.type + '<' + s.format + '>' : (s.type ?? '');\n }\n function resolveRef(ref) {\n const parts = ref.replace(/^#\\\\//, '').split('/');\n return parts.reduce((o, k) => o?.[k], schema);\n }\n function resolveResponse(resp) {\n return resp?.$ref ? resolveRef(resp.$ref) : resp;\n }\n\n // ── info ─────────────────────────────────────────────────────────\n const info = schema.info ?? {};\n document.title = info.title ?? 'API Reference';\n document.getElementById('nav-title').innerHTML =\n esc(info.title ?? 'API Reference') +\n (info.version ? \\` <span class=\"version\">v\\${esc(info.version)}</span>\\` : '');\n\n const infoEl = document.getElementById('info');\n infoEl.append(\n el('h2', {}, info.title ?? 'API Reference'),\n el('div', {class:'meta'},\n info.version ? el('span', {class:'badge'}, 'v' + info.version) : null,\n el('span', {class:'badge'}, 'OpenAPI ' + (schema.openapi ?? '3.x')),\n ),\n info.description ? el('p', {html: esc(info.description).replace(/\\`([^\\`]+)\\`/g, '<code>$1</code>')}) : null,\n );\n\n // ── endpoints ────────────────────────────────────────────────────\n const container = document.getElementById('endpoints');\n const nav = document.getElementById('sidebar');\n const methods = ['get','post','put','patch','delete'];\n\n for (const [path, pathItem] of Object.entries(schema.paths ?? {})) {\n for (const method of methods) {\n const op = pathItem[method];\n if (!op) continue;\n\n const id = method + '_' + path.replace(/[^a-z0-9]/gi, '_');\n\n // nav link\n const navLink = el('a', {class:'nav-item', href:'#'+id});\n navLink.append(\n el('span', {class:'method method-'+method}, method),\n el('span', {}, path),\n );\n nav.append(navLink);\n\n // card header\n const header = el('div', {class:'endpoint-header', id});\n header.append(\n el('span', {class:'method method-'+method}, method),\n el('span', {class:'endpoint-path'}, path),\n op.summary ? el('span', {class:'endpoint-summary'}, op.summary) : null,\n el('span', {class:'chevron'}, '▶'),\n );\n\n // card body\n const body = el('div', {class:'endpoint-body'});\n\n if (op.description) {\n body.append(el('p', {class:'endpoint-desc', html:\n esc(op.description).replace(/\\`([^\\`]+)\\`/g,'<code>$1</code>')}));\n }\n\n // parameters\n const params = op.parameters ?? [];\n if (params.length) {\n body.append(el('div', {class:'section-label'}, 'Parameters'));\n const tbl = el('table', {});\n tbl.append(el('thead', {}, el('tr', {},\n el('th',{},'Name'), el('th',{},'In'), el('th',{},'Type'), el('th',{},'Description')\n )));\n const tbody = el('tbody', {});\n for (const p of params) {\n const nameCell = el('td', {class:'param-name'}, p.name);\n if (p.required) nameCell.append(el('span', {class:'required'}, '*'));\n tbody.append(el('tr', {},\n nameCell,\n el('td', {class:'param-in'}, p.in),\n el('td', {class:'param-type'}, schemaType(p.schema)),\n el('td', {class:'response-desc'}, p.description ?? ''),\n ));\n }\n tbl.append(tbody);\n body.append(tbl);\n }\n\n // request body\n if (op.requestBody) {\n body.append(el('div', {class:'section-label'}, 'Request Body'));\n const content = op.requestBody.content ?? {};\n for (const [ct, media] of Object.entries(content)) {\n body.append(el('div', {class:'param-in'}, ct));\n if (media.schema) {\n const resolved = media.schema.$ref ? resolveRef(media.schema.$ref) : media.schema;\n if (resolved?.properties) {\n const tbl = el('table', {});\n tbl.append(el('thead', {}, el('tr', {},\n el('th',{},'Field'), el('th',{},'Type'), el('th',{},'Description')\n )));\n const tbody = el('tbody', {});\n const required = new Set(resolved.required ?? []);\n for (const [name, prop] of Object.entries(resolved.properties)) {\n const nameCell = el('td', {class:'param-name'}, name);\n if (required.has(name)) nameCell.append(el('span', {class:'required'}, '*'));\n tbody.append(el('tr', {},\n nameCell,\n el('td', {class:'param-type'}, schemaType(prop)),\n el('td', {class:'response-desc'}, prop.description ?? ''),\n ));\n }\n tbl.append(tbody);\n body.append(tbl);\n }\n }\n }\n }\n\n // responses\n if (op.responses) {\n body.append(el('div', {class:'section-label'}, 'Responses'));\n const wrap = el('div', {});\n for (const [code, resp] of Object.entries(op.responses)) {\n const resolved = resolveResponse(resp);\n const hasContent = resolved?.content && Object.keys(resolved.content).length > 0;\n\n const group = el('div', {class:'response-group'});\n const respHeader = el('div', {class:'response-header'});\n respHeader.append(\n el('span', {class:'status-code ' + statusClass(code)}, code),\n el('span', {class:'response-desc'}, resolved?.description ?? ''),\n hasContent ? el('span', {class:'resp-chevron'}, '\\u25B6') : null,\n );\n group.append(respHeader);\n\n if (hasContent) {\n const detail = el('div', {class:'response-detail'});\n for (const [ct, media] of Object.entries(resolved.content)) {\n detail.append(el('div', {class:'response-content-type'}, ct));\n\n // Render response schema fields\n if (media.schema) {\n const resolvedSchema = media.schema.$ref ? resolveRef(media.schema.$ref) : media.schema;\n if (resolvedSchema?.properties) {\n detail.append(el('div', {class:'section-label'}, 'Schema'));\n const tbl = el('table', {});\n tbl.append(el('thead', {}, el('tr', {},\n el('th',{},'Field'), el('th',{},'Type'), el('th',{},'Description')\n )));\n const tbody = el('tbody', {});\n const required = new Set(resolvedSchema.required ?? []);\n for (const [name, prop] of Object.entries(resolvedSchema.properties)) {\n const nameCell = el('td', {class:'param-name'}, name);\n if (required.has(name)) nameCell.append(el('span', {class:'required'}, '*'));\n tbody.append(el('tr', {},\n nameCell,\n el('td', {class:'param-type'}, schemaType(prop)),\n el('td', {class:'response-desc'}, prop.description ?? ''),\n ));\n }\n tbl.append(tbody);\n detail.append(tbl);\n }\n }\n\n // Render response example\n if (media.example !== undefined) {\n detail.append(el('div', {class:'section-label'}, 'Example'));\n detail.append(el('pre', {class:'example-block'}, JSON.stringify(media.example, null, 2)));\n }\n if (media.examples) {\n detail.append(el('div', {class:'section-label'}, 'Examples'));\n for (const [exName, exObj] of Object.entries(media.examples)) {\n const val = exObj?.value ?? exObj;\n detail.append(el('pre', {class:'example-block'}, '// ' + exName + '\\\\n' + JSON.stringify(val, null, 2)));\n }\n }\n }\n\n respHeader.addEventListener('click', () => {\n const open = respHeader.classList.toggle('open');\n detail.classList.toggle('open', open);\n });\n group.append(detail);\n }\n\n wrap.append(group);\n }\n body.append(wrap);\n }\n\n // x-codeSamples\n const samples = op['x-codeSamples'];\n if (samples && samples.length) {\n body.append(el('div', {class:'section-label'}, 'Example'));\n const samplesWrap = el('div', {class:'code-samples'});\n for (const sample of samples) {\n samplesWrap.append(\n el('div', {class:'code-sample-label'}, sample.label ?? sample.lang ?? 'Example'),\n el('pre', {}, sample.source),\n );\n }\n body.append(samplesWrap);\n }\n\n // toggle\n header.addEventListener('click', () => {\n const open = header.classList.toggle('open');\n body.classList.toggle('open', open);\n // sync nav highlight\n document.querySelectorAll('.nav-item').forEach(n => n.classList.remove('active'));\n if (open) navLink.classList.add('active');\n });\n\n const card = el('div', {class:'endpoint'});\n card.append(header, body);\n container.append(card);\n }\n }\n\n // highlight nav on scroll\n const observer = new IntersectionObserver(entries => {\n for (const entry of entries) {\n if (entry.isIntersecting) {\n const id = entry.target.id;\n document.querySelectorAll('.nav-item').forEach(n => {\n n.classList.toggle('active', n.getAttribute('href') === '#' + id);\n });\n }\n }\n }, { threshold: 0.5 });\n document.querySelectorAll('.endpoint-header[id]').forEach(h => observer.observe(h));\n </script>\n</body>\n</html>`;\n}\n\nfunction esc(s: unknown): string {\n return String(s ?? '')\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n}\n","import type {\n ISandbox,\n MountBucketOptions,\n R2BindingMountBucketOptions,\n RemoteMountBucketOptions,\n TunnelInfo,\n TunnelOptions\n} from '@repo/shared';\nimport type { Sandbox } from '../../sandbox';\nimport { getSandbox as getSandboxFromSDK } from '../../sandbox';\nimport { SandboxSecurityError, validateTunnelName } from '../../security';\nimport { errorJson } from '../helpers';\nimport type {\n BridgeEnv,\n MountBucketRequest,\n MountBucketRequestOptions,\n TunnelRequest\n} from '../types';\n\nexport type BridgeApp = import('hono').Hono<{\n Bindings: BridgeEnv;\n Variables: { containerUUID: string };\n}>;\n\nexport type BridgeSandbox = ISandbox & {\n /** Internal non-waking lifecycle query used only by the bridge. */\n isRuntimeActive(): Promise<boolean>;\n createWorkspaceArchive(options: {\n root: string;\n excludes?: readonly string[];\n }): Promise<string>;\n extractWorkspaceArchive(options: {\n root: string;\n archivePath: string;\n }): Promise<void>;\n cleanupWorkspaceArchive(archivePath: string): Promise<void>;\n cleanupMountDirectory(mountPath: string): Promise<void>;\n destroy(): Promise<void>;\n tunnels: {\n get(port: number, options?: TunnelOptions): Promise<TunnelInfo>;\n destroy(port: number): Promise<void>;\n };\n};\n\nexport interface WarmPoolStub {\n configure(options: {\n warmTarget: number;\n refreshInterval: number;\n }): Promise<void>;\n getContainer(sandboxId: string): Promise<string>;\n lookupContainer(sandboxId: string): Promise<string | null>;\n getStats(): Promise<unknown>;\n shutdownPrewarmed(): Promise<void>;\n reportStopped(containerUUID: string): Promise<void>;\n}\n\nexport function getSandbox<T extends Sandbox<unknown>>(\n ns: DurableObjectNamespace<T>,\n containerUUID: string\n): BridgeSandbox {\n return getSandboxFromSDK(ns, containerUUID) as unknown as BridgeSandbox;\n}\n\nexport function getSandboxNs(\n env: BridgeEnv,\n sandboxBinding: string\n): DurableObjectNamespace<Sandbox<unknown>> {\n return env[sandboxBinding] as DurableObjectNamespace<Sandbox<unknown>>;\n}\n\nexport function getWarmPoolNs(\n env: BridgeEnv,\n warmPoolBinding: string\n): DurableObjectNamespace {\n return env[warmPoolBinding] as DurableObjectNamespace;\n}\n\nexport function getWarmPoolStub(\n env: BridgeEnv,\n warmPoolBinding: string\n): WarmPoolStub {\n const poolNs = getWarmPoolNs(env, warmPoolBinding);\n const poolId = poolNs.idFromName('global-pool');\n return poolNs.get(poolId) as unknown as WarmPoolStub;\n}\n\nfunction hasEndpoint(\n options: MountBucketRequestOptions\n): options is MountBucketRequestOptions & { endpoint: string } {\n return 'endpoint' in options && typeof options.endpoint === 'string';\n}\n\nfunction hasEndpointProperty(options: MountBucketRequestOptions): boolean {\n return 'endpoint' in options && options.endpoint !== undefined;\n}\n\nfunction hasCredentials(\n options: MountBucketRequestOptions\n): options is MountBucketRequestOptions & {\n credentials: { accessKeyId: string; secretAccessKey: string };\n} {\n return 'credentials' in options && options.credentials !== undefined;\n}\n\nfunction isStringArray(value: unknown): value is string[] {\n return (\n Array.isArray(value) && value.every((item) => typeof item === 'string')\n );\n}\n\nexport function parseTunnelOptions(\n rawBody: string\n): TunnelOptions | Response | undefined {\n if (!rawBody.trim()) return undefined;\n\n let body: TunnelRequest;\n try {\n body = JSON.parse(rawBody) as TunnelRequest;\n } catch {\n return errorJson('Invalid JSON body', 'invalid_request', 400);\n }\n\n if (\n !body ||\n typeof body !== 'object' ||\n Array.isArray(body) ||\n body.name === undefined\n ) {\n return undefined;\n }\n\n if (typeof body.name !== 'string') {\n return errorJson(\n 'name must be a string when provided',\n 'invalid_request',\n 400\n );\n }\n\n try {\n validateTunnelName(body.name);\n } catch (err) {\n if (err instanceof SandboxSecurityError) {\n return errorJson(err.message, 'invalid_request', 400);\n }\n throw err;\n }\n\n return { name: body.name };\n}\n\nexport function validateMountOptions(\n options: MountBucketRequestOptions,\n binding?: string\n): Response | null {\n if ('endpoint' in options && !hasEndpoint(options)) {\n return errorJson(\n 'options.endpoint must be a string when provided',\n 'invalid_request',\n 400\n );\n }\n if (binding !== undefined && typeof binding !== 'string') {\n return errorJson(\n 'binding must be a string when provided',\n 'invalid_request',\n 400\n );\n }\n if (binding === '') {\n return errorJson(\n 'binding must be a non-empty string when provided',\n 'invalid_request',\n 400\n );\n }\n if (binding !== undefined && hasEndpointProperty(options)) {\n return errorJson(\n 'Provide either binding or options.endpoint, not both',\n 'invalid_request',\n 400\n );\n }\n if (\n options.s3fsOptions !== undefined &&\n !isStringArray(options.s3fsOptions)\n ) {\n return errorJson(\n 'options.s3fsOptions must be an array of strings when provided',\n 'invalid_request',\n 400\n );\n }\n if (options.readOnly !== undefined && typeof options.readOnly !== 'boolean') {\n return errorJson(\n 'options.readOnly must be a boolean when provided',\n 'invalid_request',\n 400\n );\n }\n if (options.prefix !== undefined && typeof options.prefix !== 'string') {\n return errorJson(\n 'options.prefix must be a string when provided',\n 'invalid_request',\n 400\n );\n }\n if (\n 'credentialProxy' in options &&\n options.credentialProxy !== undefined &&\n typeof options.credentialProxy !== 'boolean'\n ) {\n return errorJson(\n 'options.credentialProxy must be a boolean when provided',\n 'invalid_request',\n 400\n );\n }\n if (\n 'credentials' in options &&\n options.credentials !== undefined &&\n (typeof options.credentials !== 'object' ||\n options.credentials === null ||\n typeof options.credentials.accessKeyId !== 'string' ||\n typeof options.credentials.secretAccessKey !== 'string')\n ) {\n return errorJson(\n 'options.credentials must include string accessKeyId and secretAccessKey',\n 'invalid_request',\n 400\n );\n }\n return null;\n}\n\nexport function resolveMountBucketName(\n body: MountBucketRequest\n): string | Response {\n if (hasEndpoint(body.options)) {\n if (body.bucket && typeof body.bucket === 'string') return body.bucket;\n return errorJson(\n 'bucket must be a non-empty string for remote mounts',\n 'invalid_request',\n 400\n );\n }\n if (body.binding !== undefined) return body.binding;\n return errorJson(\n 'binding must be a non-empty string for R2 binding mounts',\n 'invalid_request',\n 400\n );\n}\n\nexport function toSDKMountOptions(\n options: MountBucketRequestOptions\n): MountBucketOptions {\n if (hasEndpoint(options)) {\n const remoteOptions: RemoteMountBucketOptions = {\n endpoint: options.endpoint\n };\n if (options.readOnly !== undefined)\n remoteOptions.readOnly = options.readOnly;\n if (options.prefix !== undefined) remoteOptions.prefix = options.prefix;\n if (hasCredentials(options)) {\n remoteOptions.credentials = {\n accessKeyId: options.credentials.accessKeyId,\n secretAccessKey: options.credentials.secretAccessKey\n };\n }\n if (options.s3fsOptions !== undefined)\n remoteOptions.s3fsOptions = options.s3fsOptions;\n if (\n 'credentialProxy' in options &&\n typeof options.credentialProxy === 'boolean'\n ) {\n remoteOptions.credentialProxy = options.credentialProxy;\n }\n return remoteOptions;\n }\n\n const r2BindingOptions: R2BindingMountBucketOptions = {};\n if (options.readOnly !== undefined)\n r2BindingOptions.readOnly = options.readOnly;\n if (options.prefix !== undefined) r2BindingOptions.prefix = options.prefix;\n if (options.s3fsOptions !== undefined)\n r2BindingOptions.s3fsOptions = options.s3fsOptions;\n return r2BindingOptions;\n}\n","import { errorJson, resolveWorkspacePath, sseToByteStream } from '../helpers';\nimport type { WriteResponse } from '../types';\nimport { type BridgeApp, getSandbox, getSandboxNs } from './common';\n\nexport function registerFileRoutes(\n app: BridgeApp,\n apiPrefix: string,\n sandboxBinding: string\n): void {\n // ------------------------------------------------------------------\n // GET /sandbox/:id/file/*\n // ------------------------------------------------------------------\n\n app.get(`${apiPrefix}/sandbox/:id/file/*`, async (c) => {\n const sandboxId = c.req.param('id');\n\n // Extract everything after /file/ in the URL path\n const fullPath = c.req.path;\n const marker = `${apiPrefix}/sandbox/${sandboxId}/file/`;\n const relativePath = fullPath.slice(marker.length);\n\n if (!relativePath) {\n return errorJson('file path must not be empty', 'invalid_request', 400);\n }\n\n // Prepend / to make it absolute before validation\n const resolvedPath = resolveWorkspacePath(`/${relativePath}`);\n if (!resolvedPath) {\n return errorJson(\n 'path must resolve to a location within /workspace',\n 'invalid_request',\n 403\n );\n }\n\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n try {\n const stream = await sandbox.readFileStream(resolvedPath);\n return new Response(sseToByteStream(stream), {\n status: 200,\n headers: { 'Content-Type': 'application/octet-stream' }\n });\n } catch (err) {\n const code = (err as { code?: string }).code;\n if (code === 'FILE_NOT_FOUND') {\n return errorJson(\n `File not found: ${resolvedPath}`,\n 'workspace_read_not_found',\n 404\n );\n }\n const msg = err instanceof Error ? err.message : String(err);\n return errorJson(`read failed: ${msg}`, 'exec_transport_error', 502);\n }\n });\n\n // ------------------------------------------------------------------\n // PUT /sandbox/:id/file/*\n // ------------------------------------------------------------------\n\n app.put(`${apiPrefix}/sandbox/:id/file/*`, async (c) => {\n const sandboxId = c.req.param('id');\n\n // Extract everything after /file/ in the URL path\n const fullPath = c.req.path;\n const marker = `${apiPrefix}/sandbox/${sandboxId}/file/`;\n const relativePath = fullPath.slice(marker.length);\n\n if (!relativePath) {\n return errorJson('file path must not be empty', 'invalid_request', 400);\n }\n\n // Prepend / to make it absolute before validation\n const resolvedPath = resolveWorkspacePath(`/${relativePath}`);\n if (!resolvedPath) {\n return errorJson(\n 'path must resolve to a location within /workspace',\n 'invalid_request',\n 403\n );\n }\n\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n try {\n const buffer = await c.req.arrayBuffer();\n const MAX_WRITE_BYTES = 32 * 1024 * 1024; // 32 MiB — matches RPC payload limit\n if (buffer.byteLength > MAX_WRITE_BYTES) {\n return errorJson(\n `payload too large: ${buffer.byteLength} bytes exceeds the ${MAX_WRITE_BYTES}-byte limit`,\n 'payload_too_large',\n 413\n );\n }\n\n const bytes = new Uint8Array(buffer);\n let b64 = '';\n const CHUNK = 6144; // 6144 = 3 * 2048 — no intermediate padding\n for (let i = 0; i < bytes.length; i += CHUNK) {\n b64 += btoa(String.fromCharCode(...bytes.subarray(i, i + CHUNK)));\n }\n await sandbox.writeFile(resolvedPath, b64, { encoding: 'base64' });\n const response: WriteResponse = { ok: true };\n return c.json(response);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return errorJson(\n `write failed: ${msg}`,\n 'workspace_archive_write_error',\n 502\n );\n }\n });\n}\n","import {\n base32Encode,\n errorJson,\n sseToByteStream,\n withStreamCleanup\n} from '../helpers';\nimport { primePool } from '../pool';\nimport type { MountBucketRequest, UnmountBucketRequest } from '../types';\nimport {\n type BridgeApp,\n getSandbox,\n getSandboxNs,\n getWarmPoolStub,\n resolveMountBucketName,\n toSDKMountOptions,\n validateMountOptions\n} from './common';\n\nexport function registerLifecycleRoutes(\n app: BridgeApp,\n apiPrefix: string,\n healthPath: string,\n sandboxBinding: string,\n warmPoolBinding: string\n): void {\n // ------------------------------------------------------------------\n // POST /sandbox\n // ------------------------------------------------------------------\n\n app.post(`${apiPrefix}/sandbox`, (c) => {\n const bytes = new Uint8Array(15);\n crypto.getRandomValues(bytes);\n return c.json({ id: base32Encode(bytes) });\n });\n\n // ------------------------------------------------------------------\n // POST /sandbox/:id/persist\n // ------------------------------------------------------------------\n\n app.post(`${apiPrefix}/sandbox/:id/persist`, async (c) => {\n const root = '/workspace';\n\n // Decode any exclude paths passed from the client layer.\n const excludesParam = c.req.query('excludes') ?? '';\n const excludes = excludesParam\n ? excludesParam.split(',').filter((s) => s.length > 0)\n : [];\n\n // Validate excludes don't contain path traversal\n for (const ex of excludes) {\n if (ex.includes('..')) {\n return errorJson(\n 'exclude paths must not contain \"..\"',\n 'invalid_request',\n 400\n );\n }\n }\n\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n\n try {\n const archivePath = await sandbox.createWorkspaceArchive({\n root,\n excludes\n });\n let stream: ReadableStream<Uint8Array>;\n try {\n stream = await sandbox.readFileStream(archivePath);\n } catch (error) {\n await sandbox\n .cleanupWorkspaceArchive(archivePath)\n .catch(() => undefined);\n throw error;\n }\n\n const cleanupPath = archivePath;\n const responseStream = withStreamCleanup(sseToByteStream(stream), () =>\n sandbox.cleanupWorkspaceArchive(cleanupPath)\n );\n return new Response(responseStream, {\n status: 200,\n headers: { 'Content-Type': 'application/octet-stream' }\n });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return errorJson(\n `persist failed: ${msg}`,\n 'workspace_archive_read_error',\n 502\n );\n }\n });\n\n // ------------------------------------------------------------------\n // POST /sandbox/:id/hydrate\n // ------------------------------------------------------------------\n\n app.post(`${apiPrefix}/sandbox/:id/hydrate`, async (c) => {\n const root = '/workspace';\n\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n\n // Read the raw tar bytes from the request body.\n let tarBytes: Uint8Array;\n try {\n const buffer = await c.req.arrayBuffer();\n tarBytes = new Uint8Array(buffer);\n } catch {\n return errorJson('Could not read request body', 'invalid_request', 400);\n }\n\n if (tarBytes.byteLength === 0) {\n return errorJson('Empty tar payload', 'invalid_request', 400);\n }\n\n const MAX_HYDRATE_BYTES = 32 * 1024 * 1024; // 32 MiB\n if (tarBytes.byteLength > MAX_HYDRATE_BYTES) {\n return errorJson(\n `tar payload too large: ${tarBytes.byteLength} bytes exceeds the ${MAX_HYDRATE_BYTES}-byte limit`,\n 'invalid_request',\n 400\n );\n }\n\n const tmpPath = `/tmp/sandbox-hydrate-${Date.now()}-${crypto.randomUUID()}.tar`;\n try {\n let b64 = '';\n const CHUNK = 6144; // 6144 = 3 * 2048 — no intermediate padding\n for (let i = 0; i < tarBytes.length; i += CHUNK) {\n b64 += btoa(String.fromCharCode(...tarBytes.subarray(i, i + CHUNK)));\n }\n await sandbox.writeFile(tmpPath, b64, { encoding: 'base64' });\n\n await sandbox.extractWorkspaceArchive({ root, archivePath: tmpPath });\n\n return c.json({ ok: true });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return errorJson(\n `hydrate failed: ${msg}`,\n 'workspace_archive_write_error',\n 502\n );\n } finally {\n await sandbox.cleanupWorkspaceArchive(tmpPath).catch(() => undefined);\n }\n });\n\n // ------------------------------------------------------------------\n // POST /sandbox/:id/mount\n // ------------------------------------------------------------------\n\n app.post(`${apiPrefix}/sandbox/:id/mount`, async (c) => {\n let body: MountBucketRequest;\n try {\n body = await c.req.json<MountBucketRequest>();\n } catch {\n return errorJson('Invalid JSON body', 'invalid_request', 400);\n }\n\n if (\n body.bucket !== undefined &&\n (typeof body.bucket !== 'string' || body.bucket === '')\n ) {\n return errorJson(\n 'bucket must be a non-empty string',\n 'invalid_request',\n 400\n );\n }\n if (!body.mountPath || typeof body.mountPath !== 'string') {\n return errorJson(\n 'mountPath must be a non-empty string',\n 'invalid_request',\n 400\n );\n }\n if (!body.mountPath.startsWith('/')) {\n return errorJson(\n 'mountPath must be an absolute path (start with /)',\n 'invalid_request',\n 400\n );\n }\n if (\n !body.options ||\n typeof body.options !== 'object' ||\n Array.isArray(body.options)\n ) {\n return errorJson('options must be an object', 'invalid_request', 400);\n }\n const optionsError = validateMountOptions(body.options, body.binding);\n if (optionsError) return optionsError;\n const bucketName = resolveMountBucketName(body);\n if (bucketName instanceof Response) return bucketName;\n\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n const sdkOptions = toSDKMountOptions(body.options);\n\n try {\n await sandbox.mountBucket(bucketName, body.mountPath, sdkOptions);\n return c.json({ ok: true });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return errorJson(`mount failed: ${msg}`, 'mount_error', 502);\n }\n });\n\n // ------------------------------------------------------------------\n // POST /sandbox/:id/unmount\n // ------------------------------------------------------------------\n\n app.post(`${apiPrefix}/sandbox/:id/unmount`, async (c) => {\n let body: UnmountBucketRequest;\n try {\n body = await c.req.json<UnmountBucketRequest>();\n } catch {\n return errorJson('Invalid JSON body', 'invalid_request', 400);\n }\n\n if (!body.mountPath || typeof body.mountPath !== 'string') {\n return errorJson(\n 'mountPath must be a non-empty string',\n 'invalid_request',\n 400\n );\n }\n if (!body.mountPath.startsWith('/')) {\n return errorJson(\n 'mountPath must be an absolute path (start with /)',\n 'invalid_request',\n 400\n );\n }\n\n // Normalize to resolve '..' / '.' segments, then reject the filesystem\n // root so the post-unmount rm -rf cleanup cannot be destructive.\n const normalizedPath = new URL(body.mountPath, 'file:///').pathname;\n if (normalizedPath === '/') {\n return errorJson(\n 'mountPath must not resolve to / (filesystem root)',\n 'invalid_request',\n 400\n );\n }\n\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n\n try {\n await sandbox.unmountBucket(normalizedPath);\n\n try {\n await sandbox.cleanupMountDirectory(normalizedPath);\n } catch {\n // Best-effort — the unmount itself already succeeded\n }\n\n return c.json({ ok: true });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return errorJson(`unmount failed: ${msg}`, 'unmount_error', 502);\n }\n });\n\n // ------------------------------------------------------------------\n // DELETE /sandbox/:id\n // ------------------------------------------------------------------\n\n app.delete(`${apiPrefix}/sandbox/:id`, async (c) => {\n const containerUUID = c.get('containerUUID');\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n containerUUID\n );\n\n try {\n await sandbox.destroy();\n } catch {\n // Best-effort — container may already be gone\n }\n\n // Release the WarmPool assignment so it doesn't track a dead container\n try {\n const poolStub = getWarmPoolStub(c.env, warmPoolBinding);\n await poolStub.reportStopped(containerUUID);\n } catch {\n // Best-effort\n }\n\n return new Response(null, { status: 204 });\n });\n\n // ------------------------------------------------------------------\n // Health check\n // ------------------------------------------------------------------\n\n app.get(healthPath, (c) => {\n const errors: string[] = [];\n\n if (!c.env[sandboxBinding]) {\n errors.push(\n `Missing required Durable Object binding \"${sandboxBinding}\". Ensure your wrangler.jsonc has a binding named \"${sandboxBinding}\".`\n );\n }\n if (!c.env[warmPoolBinding]) {\n errors.push(\n `Missing required Durable Object binding \"${warmPoolBinding}\". Ensure your wrangler.jsonc has a binding named \"${warmPoolBinding}\".`\n );\n }\n\n if (errors.length > 0) {\n return c.json({ ok: false, errors }, 503);\n }\n\n return c.json({ ok: true });\n });\n\n // ------------------------------------------------------------------\n // Pool management routes\n // ------------------------------------------------------------------\n\n app.use(`${apiPrefix}/pool/*`, async (c, next) => {\n const token = c.env.SANDBOX_API_KEY as string | undefined;\n if (token) {\n const authHeader = c.req.header('Authorization') ?? '';\n const provided = authHeader.startsWith('Bearer ')\n ? authHeader.slice(7)\n : '';\n if (provided !== token) {\n return errorJson('Unauthorized', 'unauthorized', 401);\n }\n }\n return next();\n });\n\n app.get(`${apiPrefix}/pool/stats`, async (c) => {\n const warmTarget =\n Number.parseInt((c.env.WARM_POOL_TARGET as string) || '0', 10) || 0;\n const refreshInterval =\n Number.parseInt(\n (c.env.WARM_POOL_REFRESH_INTERVAL as string) || '10000',\n 10\n ) || 10_000;\n\n const poolStub = getWarmPoolStub(c.env, warmPoolBinding);\n\n try {\n await poolStub.configure({ warmTarget, refreshInterval });\n } catch {\n // Continue — stats should still be readable even if config push fails.\n }\n\n const stats = await poolStub.getStats();\n return c.json(stats);\n });\n\n app.post(`${apiPrefix}/pool/shutdown-prewarmed`, async (c) => {\n const warmTarget =\n Number.parseInt((c.env.WARM_POOL_TARGET as string) || '0', 10) || 0;\n const refreshInterval =\n Number.parseInt(\n (c.env.WARM_POOL_REFRESH_INTERVAL as string) || '10000',\n 10\n ) || 10_000;\n\n const poolStub = getWarmPoolStub(c.env, warmPoolBinding);\n\n try {\n await poolStub.configure({ warmTarget, refreshInterval });\n } catch {\n // Continue.\n }\n\n await poolStub.shutdownPrewarmed();\n return c.json({ ok: true });\n });\n\n app.post(`${apiPrefix}/pool/prime`, async (c) => {\n await primePool(c.env, warmPoolBinding);\n return c.json({ ok: true });\n });\n}\n","import type { ProcessLogEvent } from '@repo/shared';\nimport { validatePort } from '../../security';\nimport { errorJson, resolveWorkspacePath } from '../helpers';\nimport type { ExecRequest, RunningResponse } from '../types';\nimport {\n type BridgeApp,\n getSandbox,\n getSandboxNs,\n parseTunnelOptions\n} from './common';\n\nexport function registerProcessRoutes(\n app: BridgeApp,\n apiPrefix: string,\n sandboxBinding: string\n): void {\n // ------------------------------------------------------------------\n // /sandbox/:id/processes\n // ------------------------------------------------------------------\n\n app.post(`${apiPrefix}/sandbox/:id/processes`, async (c) => {\n const body = await parseProcessRequest(c.req.raw);\n if (body instanceof Response) return body;\n\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n const options = processOptions(body);\n if (options instanceof Response) return options;\n\n try {\n const process = await sandbox.exec(body.argv, options);\n return c.json(await process.status());\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return errorJson(`process launch failed: ${msg}`, 'process_error', 502);\n }\n });\n\n app.get(`${apiPrefix}/sandbox/:id/processes`, async (c) => {\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n return c.json(await sandbox.listProcesses());\n });\n\n app.get(`${apiPrefix}/sandbox/:id/processes/:processId`, async (c) => {\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n const process = await sandbox.getProcess(c.req.param('processId'));\n if (!process) return errorJson('Process not found', 'not_found', 404);\n return c.json(await process.status());\n });\n\n app.get(`${apiPrefix}/sandbox/:id/processes/:processId/logs`, async (c) => {\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n const process = await sandbox.getProcess(c.req.param('processId'));\n if (!process) return errorJson('Process not found', 'not_found', 404);\n\n const replay = parseBoolean(c.req.query('replay'));\n const follow = parseBoolean(c.req.query('follow'));\n const logs = await process.logs({\n since: c.req.query('since'),\n replay,\n follow\n });\n return new Response(processLogsToSSE(logs), {\n headers: {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache'\n }\n });\n });\n\n app.post(`${apiPrefix}/sandbox/:id/processes/:processId/kill`, async (c) => {\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n const process = await sandbox.getProcess(c.req.param('processId'));\n if (!process) return errorJson('Process not found', 'not_found', 404);\n const signal = await parseKillRequest(c.req.raw);\n if (signal instanceof Response) return signal;\n await process.kill(signal);\n return c.body(null, 204);\n });\n\n // ------------------------------------------------------------------\n // POST /sandbox/:id/tunnel/:port\n // DELETE /sandbox/:id/tunnel/:port\n // ------------------------------------------------------------------\n\n app.post(`${apiPrefix}/sandbox/:id/tunnel/:port`, async (c) => {\n const port = Number(c.req.param('port'));\n if (!validatePort(port)) {\n return errorJson('Invalid port', 'invalid_request', 400);\n }\n\n const options = parseTunnelOptions(await c.req.text());\n if (options instanceof Response) return options;\n\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n\n try {\n const tunnel = await sandbox.tunnels.get(port, options);\n return c.json(tunnel);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return errorJson(`tunnel failed: ${msg}`, 'tunnel_error', 502);\n }\n });\n\n app.delete(`${apiPrefix}/sandbox/:id/tunnel/:port`, async (c) => {\n const port = Number(c.req.param('port'));\n if (!validatePort(port)) {\n return errorJson('Invalid port', 'invalid_request', 400);\n }\n\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n\n try {\n await sandbox.tunnels.destroy(port);\n return c.body(null, 204);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return errorJson(`tunnel failed: ${msg}`, 'tunnel_error', 502);\n }\n });\n\n // ------------------------------------------------------------------\n // GET /sandbox/:id/running\n // ------------------------------------------------------------------\n\n app.get(`${apiPrefix}/sandbox/:id/running`, async (c) => {\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n\n try {\n const running = await sandbox.isRuntimeActive();\n const response: RunningResponse = { running };\n return c.json(response);\n } catch {\n const response: RunningResponse = { running: false };\n return c.json(response);\n }\n });\n}\n\nasync function parseProcessRequest(\n request: Request\n): Promise<ExecRequest | Response> {\n let body: ExecRequest;\n try {\n body = await request.json<ExecRequest>();\n } catch {\n return errorJson('Invalid JSON body', 'invalid_request', 400);\n }\n if (!Array.isArray(body.argv) || body.argv.length === 0) {\n return errorJson('argv must be a non-empty array', 'invalid_request', 400);\n }\n if (body.argv.some((item) => typeof item !== 'string')) {\n return errorJson('argv items must be strings', 'invalid_request', 400);\n }\n if (body.argv[0].length === 0) {\n return errorJson(\n 'argv executable must be non-empty',\n 'invalid_request',\n 400\n );\n }\n return body;\n}\n\nfunction processOptions(\n body: ExecRequest\n): { timeout?: number; cwd?: string; env?: Record<string, string> } | Response {\n const options: {\n timeout?: number;\n cwd?: string;\n env?: Record<string, string>;\n } = {};\n if (body.timeout !== undefined) {\n if (\n typeof body.timeout !== 'number' ||\n !Number.isFinite(body.timeout) ||\n body.timeout <= 0\n ) {\n return errorJson(\n 'timeout must be a positive finite number',\n 'invalid_request',\n 400\n );\n }\n options.timeout = body.timeout;\n }\n if (typeof body.cwd === 'string') {\n const cwd = resolveWorkspacePath(body.cwd);\n if (!cwd) {\n return errorJson(\n 'cwd must resolve to a location within /workspace',\n 'invalid_request',\n 403\n );\n }\n options.cwd = cwd;\n }\n if ('env' in body && body.env !== undefined) {\n if (!isStringRecord(body.env)) {\n return errorJson(\n 'env must be an object of strings',\n 'invalid_request',\n 400\n );\n }\n options.env = body.env;\n }\n return options;\n}\n\nasync function parseKillRequest(request: Request): Promise<number | Response> {\n if (!request.headers.get('content-type')) return 15;\n let body: unknown;\n try {\n body = await request.json();\n } catch {\n return errorJson('Invalid JSON body', 'invalid_request', 400);\n }\n if (typeof body !== 'object' || body === null || Array.isArray(body)) {\n return errorJson('Request body must be an object', 'invalid_request', 400);\n }\n const signal = (body as { signal?: unknown }).signal;\n if (signal === undefined) return 15;\n if (\n typeof signal !== 'number' ||\n !Number.isInteger(signal) ||\n signal < 1 ||\n signal > 64\n ) {\n return errorJson(\n 'signal must be an integer between 1 and 64',\n 'invalid_request',\n 400\n );\n }\n return signal;\n}\n\nfunction parseBoolean(value: string | undefined): boolean | undefined {\n if (value === undefined) return undefined;\n return value === 'true' || value === '1';\n}\n\nfunction isStringRecord(value: unknown): value is Record<string, string> {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n Object.values(value).every((item) => typeof item === 'string')\n );\n}\n\nfunction processLogsToSSE(\n logs: ReadableStream<ProcessLogEvent>\n): ReadableStream<Uint8Array> {\n const reader = logs.getReader();\n const encoder = new TextEncoder();\n let finished = false;\n\n async function finish(cancelSource: boolean): Promise<void> {\n if (finished) return;\n finished = true;\n if (cancelSource) await reader.cancel().catch(() => undefined);\n reader.releaseLock();\n }\n\n return new ReadableStream<Uint8Array>(\n {\n async pull(controller) {\n try {\n const result = await reader.read();\n if (result.done) {\n await finish(false);\n controller.close();\n return;\n }\n const event = result.value;\n const data =\n event.type === 'stdout' || event.type === 'stderr'\n ? {\n type: event.type,\n cursor: event.cursor,\n timestamp: event.timestamp,\n data: bytesToBase64(event.data)\n }\n : event;\n controller.enqueue(\n encoder.encode(`data: ${JSON.stringify(data)}\\n\\n`)\n );\n } catch (error) {\n await finish(true);\n controller.error(error);\n }\n },\n async cancel() {\n await finish(true);\n }\n },\n { highWaterMark: 0 }\n );\n}\n\nfunction bytesToBase64(data: Uint8Array): string {\n let binary = '';\n for (const byte of data) binary += String.fromCharCode(byte);\n return btoa(binary);\n}\n","import type { CreateTerminalOptions, SandboxCommand } from '@repo/shared';\nimport { errorJson, validateTerminalId } from '../helpers';\nimport { type BridgeApp, getSandbox, getSandboxNs } from './common';\n\nfunction parsePositiveInteger(\n value: string | undefined,\n name: string\n): number | Response | undefined {\n if (value === undefined) return undefined;\n const parsed = Number(value);\n if (!Number.isInteger(parsed) || parsed <= 0) {\n return errorJson(\n `${name} must be a positive integer`,\n 'invalid_request',\n 400\n );\n }\n return parsed;\n}\n\nfunction isSandboxCommand(value: unknown): value is SandboxCommand {\n return (\n Array.isArray(value) &&\n value.length > 0 &&\n value.every((item) => typeof item === 'string')\n );\n}\n\nfunction parseCreateTerminalBody(\n rawBody: string\n): CreateTerminalOptions | Response {\n let body: unknown;\n try {\n body = JSON.parse(rawBody);\n } catch {\n return errorJson('Invalid JSON body', 'invalid_request', 400);\n }\n\n if (!body || typeof body !== 'object' || Array.isArray(body)) {\n return errorJson('Request body must be an object', 'invalid_request', 400);\n }\n\n const record = body as Record<string, unknown>;\n const argv = record.argv;\n if (!isSandboxCommand(argv)) {\n return errorJson(\n 'argv must be a non-empty string array',\n 'invalid_request',\n 400\n );\n }\n\n const options: CreateTerminalOptions = { command: argv };\n if (record.cwd !== undefined) {\n if (typeof record.cwd !== 'string')\n return errorJson('cwd must be a string', 'invalid_request', 400);\n options.cwd = record.cwd;\n }\n if (record.env !== undefined) {\n if (\n !record.env ||\n typeof record.env !== 'object' ||\n Array.isArray(record.env)\n ) {\n return errorJson('env must be an object', 'invalid_request', 400);\n }\n const env: Record<string, string> = {};\n for (const [key, value] of Object.entries(record.env)) {\n if (typeof value !== 'string')\n return errorJson('env values must be strings', 'invalid_request', 400);\n env[key] = value;\n }\n options.env = env;\n }\n if (record.cols !== undefined) {\n if (\n typeof record.cols !== 'number' ||\n !Number.isInteger(record.cols) ||\n record.cols <= 0\n )\n return errorJson(\n 'cols must be a positive integer',\n 'invalid_request',\n 400\n );\n options.cols = record.cols;\n }\n if (record.rows !== undefined) {\n if (\n typeof record.rows !== 'number' ||\n !Number.isInteger(record.rows) ||\n record.rows <= 0\n )\n return errorJson(\n 'rows must be a positive integer',\n 'invalid_request',\n 400\n );\n options.rows = record.rows;\n }\n return options;\n}\n\nfunction terminalError(error: unknown): Response {\n const message = error instanceof Error ? error.message : String(error);\n return errorJson(`terminal failed: ${message}`, 'exec_transport_error', 502);\n}\n\nexport function registerTerminalRoutes(\n app: BridgeApp,\n apiPrefix: string,\n sandboxBinding: string\n): void {\n app.post(`${apiPrefix}/sandbox/:id/terminals`, async (c) => {\n const parsed = parseCreateTerminalBody(await c.req.text());\n if (parsed instanceof Response) return parsed;\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n try {\n const terminal = await sandbox.createTerminal(parsed);\n return c.json(await terminal.getSnapshot());\n } catch (error) {\n return terminalError(error);\n }\n });\n\n app.get(`${apiPrefix}/sandbox/:id/terminals`, async (c) => {\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n try {\n const terminals = await sandbox.listTerminals();\n return c.json(\n await Promise.all(terminals.map((terminal) => terminal.getSnapshot()))\n );\n } catch (error) {\n return terminalError(error);\n }\n });\n\n app.get(`${apiPrefix}/sandbox/:id/terminals/:terminalId`, async (c) => {\n const terminalId = validateTerminalId(c.req.param('terminalId'));\n if (!terminalId)\n return errorJson('Invalid terminal ID format', 'invalid_request', 400);\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n try {\n const terminal = await sandbox.getTerminal(terminalId);\n if (!terminal) return errorJson('Terminal not found', 'not_found', 404);\n return c.json(await terminal.getSnapshot());\n } catch (error) {\n return terminalError(error);\n }\n });\n\n app.get(\n `${apiPrefix}/sandbox/:id/terminals/:terminalId/connect`,\n async (c) => {\n const upgrade = c.req.header('Upgrade');\n if (!upgrade || upgrade.toLowerCase() !== 'websocket') {\n return errorJson('WebSocket upgrade required', 'invalid_request', 400);\n }\n const terminalId = validateTerminalId(c.req.param('terminalId'));\n if (!terminalId)\n return errorJson('Invalid terminal ID format', 'invalid_request', 400);\n const cols = parsePositiveInteger(c.req.query('cols'), 'cols');\n if (cols instanceof Response) return cols;\n const rows = parsePositiveInteger(c.req.query('rows'), 'rows');\n if (rows instanceof Response) return rows;\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n try {\n const terminal = await sandbox.getTerminal(terminalId);\n if (!terminal) return errorJson('Terminal not found', 'not_found', 404);\n return await terminal.connect(c.req.raw, {\n cursor: c.req.query('cursor'),\n cols,\n rows\n });\n } catch (error) {\n return terminalError(error);\n }\n }\n );\n\n app.post(\n `${apiPrefix}/sandbox/:id/terminals/:terminalId/interrupt`,\n async (c) => {\n const terminalId = validateTerminalId(c.req.param('terminalId'));\n if (!terminalId)\n return errorJson('Invalid terminal ID format', 'invalid_request', 400);\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n try {\n const terminal = await sandbox.getTerminal(terminalId);\n if (!terminal) return errorJson('Terminal not found', 'not_found', 404);\n await terminal.interrupt();\n return new Response(null, { status: 204 });\n } catch (error) {\n return terminalError(error);\n }\n }\n );\n\n app.post(\n `${apiPrefix}/sandbox/:id/terminals/:terminalId/terminate`,\n async (c) => {\n const terminalId = validateTerminalId(c.req.param('terminalId'));\n if (!terminalId)\n return errorJson('Invalid terminal ID format', 'invalid_request', 400);\n const sandbox = getSandbox(\n getSandboxNs(c.env, sandboxBinding),\n c.get('containerUUID')\n );\n try {\n const terminal = await sandbox.getTerminal(terminalId);\n if (!terminal) return errorJson('Terminal not found', 'not_found', 404);\n await terminal.terminate();\n return new Response(null, { status: 204 });\n } catch (error) {\n return terminalError(error);\n }\n }\n );\n}\n","import { Hono, type MiddlewareHandler } from 'hono';\nimport type { Sandbox } from '../sandbox';\nimport { errorJson } from './helpers';\nimport { OPENAPI_SCHEMA } from './openapi';\nimport { renderOpenApiHtml } from './openapi-html';\nimport { getWarmPoolStub } from './routes/common';\nimport { registerFileRoutes } from './routes/files';\nimport { registerLifecycleRoutes } from './routes/lifecycle';\nimport { registerProcessRoutes } from './routes/processes';\nimport { registerTerminalRoutes } from './routes/terminals';\nimport type { BridgeEnv } from './types';\n\nexport interface RouteConfig {\n sandboxBinding: string;\n warmPoolBinding: string;\n apiPrefix: string;\n healthPath: string;\n}\n\ntype SandboxRoutePoolMode = 'allocate' | 'lookup' | 'unmatched';\n\nfunction sandboxRoutePoolMode(\n method: string,\n routePath: string\n): SandboxRoutePoolMode {\n if (method === 'GET' && routePath === '/running') return 'lookup';\n if (\n method === 'GET' &&\n (routePath === '/processes' ||\n /^\\/processes\\/[^/]+(?:\\/logs)?$/.test(routePath))\n ) {\n return 'lookup';\n }\n if (method === 'POST' && /^\\/processes\\/[^/]+\\/kill$/.test(routePath)) {\n return 'lookup';\n }\n if (\n method === 'GET' &&\n (routePath === '/terminals' ||\n /^\\/terminals\\/[^/]+(?:\\/connect)?$/.test(routePath))\n ) {\n return 'lookup';\n }\n if (\n method === 'POST' &&\n /^\\/terminals\\/[^/]+\\/(interrupt|terminate)$/.test(routePath)\n ) {\n return 'lookup';\n }\n\n if (\n method === 'POST' &&\n [\n '/processes',\n '/terminals',\n '/persist',\n '/hydrate',\n '/mount',\n '/unmount'\n ].includes(routePath)\n ) {\n return 'allocate';\n }\n if (\n (method === 'GET' || method === 'PUT') &&\n routePath.startsWith('/file/')\n ) {\n return 'allocate';\n }\n if (\n (method === 'POST' || method === 'DELETE') &&\n /^\\/tunnel\\/[^/]+$/.test(routePath)\n ) {\n return 'allocate';\n }\n return 'unmatched';\n}\n\nfunction missingRuntimeResponse(routePath: string): Response {\n if (routePath === '/running') {\n return Response.json({ running: false });\n }\n if (routePath === '/processes' || routePath === '/terminals') {\n return Response.json([]);\n }\n if (routePath.startsWith('/terminals/')) {\n return errorJson('Terminal not found', 'not_found', 404);\n }\n return errorJson('Process not found', 'not_found', 404);\n}\n\nexport function createBridgeApp(\n config: RouteConfig\n): Hono<{ Bindings: BridgeEnv; Variables: { containerUUID: string } }> {\n const app = new Hono<{\n Bindings: BridgeEnv;\n Variables: { containerUUID: string };\n }>();\n\n const { sandboxBinding, warmPoolBinding, apiPrefix } = config;\n\n app.use(`${apiPrefix}/sandbox/*`, async (c, next) => {\n const url = new URL(c.req.url);\n const pathParts = url.pathname.split('/');\n const prefixParts = apiPrefix.split('/').filter(Boolean);\n const sandboxId = pathParts[prefixParts.length + 2];\n if (sandboxId && !/^[a-z2-7]{1,128}$/.test(sandboxId)) {\n return errorJson('Invalid sandbox ID format', 'invalid_request', 400);\n }\n\n const token = c.env.SANDBOX_API_KEY as string | undefined;\n if (token) {\n const authHeader = c.req.header('Authorization') ?? '';\n const provided = authHeader.toLowerCase().startsWith('bearer ')\n ? authHeader.slice(7)\n : '';\n if (provided !== token) {\n return errorJson('Unauthorized', 'unauthorized', 401);\n }\n }\n return next();\n });\n\n app.use(`${apiPrefix}/sandbox/:id/*`, async (c, next) => {\n const url = new URL(c.req.url);\n const sandboxId = c.req.param('id');\n const routePath = url.pathname.slice(\n `${apiPrefix}/sandbox/${sandboxId}`.length\n );\n const poolMode = sandboxRoutePoolMode(c.req.method, routePath);\n if (poolMode === 'unmatched') return next();\n\n const warmTarget =\n Number.parseInt((c.env.WARM_POOL_TARGET as string) || '0', 10) || 0;\n const refreshInterval =\n Number.parseInt(\n (c.env.WARM_POOL_REFRESH_INTERVAL as string) || '10000',\n 10\n ) || 10_000;\n const poolStub = getWarmPoolStub(c.env, warmPoolBinding);\n\n try {\n await poolStub.configure({ warmTarget, refreshInterval });\n const containerUUID =\n poolMode === 'lookup'\n ? await poolStub.lookupContainer(sandboxId)\n : await poolStub.getContainer(sandboxId);\n if (!containerUUID) return missingRuntimeResponse(routePath);\n c.set('containerUUID', containerUUID);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (msg.includes('instance limit reached')) {\n return errorJson(msg, 'capacity_exceeded', 503);\n }\n return errorJson(`pool error: ${msg}`, 'pool_error', 502);\n }\n\n return next();\n });\n\n app.use(`${apiPrefix}/sandbox/:id`, async (c, next) => {\n if (c.req.method !== 'DELETE') return next();\n\n const sandboxId = c.req.param('id');\n const poolStub = getWarmPoolStub(c.env, warmPoolBinding);\n\n try {\n const containerUUID = await poolStub.lookupContainer(sandboxId);\n if (!containerUUID) {\n return new Response(null, { status: 204 });\n }\n c.set('containerUUID', containerUUID);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return errorJson(`pool error: ${msg}`, 'pool_error', 502);\n }\n\n return next();\n });\n\n registerLifecycleRoutes(\n app,\n apiPrefix,\n config.healthPath,\n sandboxBinding,\n warmPoolBinding\n );\n registerProcessRoutes(app, apiPrefix, sandboxBinding);\n registerFileRoutes(app, apiPrefix, sandboxBinding);\n registerTerminalRoutes(app, apiPrefix, sandboxBinding);\n registerOpenApiRoutes(app, apiPrefix);\n\n return app;\n}\n\nfunction registerOpenApiRoutes(\n app: Hono<{ Bindings: BridgeEnv; Variables: { containerUUID: string } }>,\n apiPrefix: string\n): void {\n const openapiAuth: MiddlewareHandler<{ Bindings: BridgeEnv }> = async (\n c,\n next\n ) => {\n const token = c.env.SANDBOX_API_KEY as string | undefined;\n if (token) {\n const authHeader = c.req.header('Authorization') ?? '';\n const provided = authHeader.startsWith('Bearer ')\n ? authHeader.slice(7)\n : '';\n const queryToken = c.req.query('token') ?? '';\n if (provided !== token && queryToken !== token) {\n return errorJson('Unauthorized', 'unauthorized', 401);\n }\n }\n return next();\n };\n\n const openapiHtmlHandler = () =>\n new Response(renderOpenApiHtml(OPENAPI_SCHEMA as Record<string, unknown>), {\n headers: { 'Content-Type': 'text/html; charset=utf-8' }\n });\n\n app.get(`${apiPrefix}/openapi.json`, openapiAuth, (c) =>\n c.json(OPENAPI_SCHEMA)\n );\n app.get(`${apiPrefix}/openapi.html`, openapiAuth, openapiHtmlHandler);\n app.get(`${apiPrefix}/openapi`, openapiAuth, openapiHtmlHandler);\n}\n","/**\n * WarmPool — Durable Object that maintains a pool of pre-started sandbox containers.\n *\n * The pool keeps N idle containers standing by so new sandboxes boot instantly.\n * Once a container is assigned to a sandbox ID, it is consumed and never returned\n * to the pool.\n *\n * Configuration is pushed in via `configure()` on every request (idempotent)\n * so changes to wrangler vars take effect without manual intervention.\n */\n\nimport { DurableObject } from 'cloudflare:workers';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface WarmPoolConfig {\n /** Target number of warm (unassigned) containers to maintain. @default 0 */\n warmTarget?: number;\n /** How often to check and replenish warm containers (ms). @default 10000 */\n refreshInterval?: number;\n}\n\nexport interface PoolStats {\n /** Number of warm (unassigned) containers ready for use */\n warm: number;\n /** Number of containers assigned to sandbox IDs */\n assigned: number;\n /** Total containers tracked by the pool */\n total: number;\n /** Current pool configuration */\n config: Required<WarmPoolConfig>;\n /** Inferred max_instances limit, or null if not yet known */\n maxInstances: number | null;\n}\n\n// ---------------------------------------------------------------------------\n// Container RPC shapes (inherited by Sandbox from Container)\n// ---------------------------------------------------------------------------\n\ninterface ContainerRpc {\n startAndWaitForPorts(): Promise<void>;\n destroy(): Promise<void>;\n renewActivityTimeout(): void;\n}\n\ninterface ContainerState {\n lastChange: number;\n status: 'running' | 'stopping' | 'stopped' | 'healthy' | 'stopped_with_code';\n exitCode?: number;\n}\n\ninterface ContainerWithState {\n getState(): Promise<ContainerState>;\n}\n\n// ---------------------------------------------------------------------------\n// Defaults\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_CONFIG: Required<WarmPoolConfig> = {\n warmTarget: 0,\n refreshInterval: 10_000\n};\n\n// ---------------------------------------------------------------------------\n// WarmPool Durable Object\n// ---------------------------------------------------------------------------\n\n/**\n * The WarmPool expects an environment with a `Sandbox` Durable Object binding.\n * This interface describes the minimum shape; the actual binding name is\n * configurable via the bridge, but defaults to \"Sandbox\".\n */\ninterface WarmPoolEnv {\n Sandbox: DurableObjectNamespace;\n [key: string]: unknown;\n}\n\nexport class WarmPool extends DurableObject<WarmPoolEnv> {\n private config: Required<WarmPoolConfig> = { ...DEFAULT_CONFIG };\n\n /** Container UUIDs that are warm and available for assignment */\n private warmContainers: Set<string> = new Set();\n\n /** Maps caller-provided sandbox IDs to container UUIDs (1:1, no sharing) */\n private assignments: Map<string, string> = new Map();\n\n /** Containers currently starting — excluded from health checks */\n private startingContainers: Set<string> = new Set();\n\n /** Inferred max_instances limit learned from Cloudflare errors, or null */\n private knownMaxInstances: number | null = null;\n\n private capacityExhausted = false;\n private initialized = false;\n\n // =======================================================================\n // Public RPC methods\n // =======================================================================\n\n /**\n * Get a container UUID for the given sandbox ID.\n * - If this ID already has an assigned container that's still running, return it.\n * - Otherwise assign a warm container (or start a new one).\n */\n async getContainer(sandboxId: string): Promise<string> {\n await this.init();\n\n const existing = this.assignments.get(sandboxId);\n if (existing) {\n const running = await this.isContainerRunning(existing);\n if (running) return existing;\n this.assignments.delete(sandboxId);\n await this.persist();\n }\n\n // Try to pop a warm container\n if (this.warmContainers.size > 0) {\n const containerUUID = this.warmContainers.values().next().value as string;\n this.warmContainers.delete(containerUUID);\n this.assignments.set(sandboxId, containerUUID);\n await this.persist();\n return containerUUID;\n }\n\n // Check capacity before starting on-demand\n if (this.remainingCapacity() <= 0) {\n this.throwCapacityError();\n }\n\n // Start one on-demand\n const containerUUID = await this.startContainer();\n if (containerUUID) {\n this.assignments.set(sandboxId, containerUUID);\n await this.persist();\n return containerUUID;\n }\n\n if (this.capacityExhausted) {\n this.throwCapacityError();\n }\n\n throw new Error('Failed to start container');\n }\n\n /**\n * Look up an existing container assignment without allocating.\n * Returns the container UUID if the sandbox ID has an active assignment, null otherwise.\n * Used by DELETE to avoid starting a container just to destroy it.\n */\n async lookupContainer(sandboxId: string): Promise<string | null> {\n await this.init();\n const existing = this.assignments.get(sandboxId);\n if (existing) {\n return existing;\n }\n return null;\n }\n\n /**\n * Report that a container has stopped — removes it from tracking.\n */\n async reportStopped(containerUUID: string): Promise<void> {\n await this.init();\n this.removeContainer(containerUUID);\n await this.persist();\n }\n\n /**\n * Get current pool statistics.\n */\n async getStats(): Promise<PoolStats> {\n await this.init();\n return {\n warm: this.warmContainers.size,\n assigned: this.assignments.size,\n total: this.warmContainers.size + this.assignments.size,\n config: this.config,\n maxInstances: this.knownMaxInstances\n };\n }\n\n /**\n * Update pool configuration. Idempotent — called on every request to keep\n * config in sync with wrangler vars across deploys.\n */\n async configure(config: WarmPoolConfig): Promise<void> {\n await this.init();\n this.config = { ...DEFAULT_CONFIG, ...config };\n await this.ctx.storage.put('config', this.config);\n }\n\n /**\n * Shutdown all pre-warmed (unassigned) containers.\n * Does not affect containers that are assigned to sandbox IDs.\n */\n async shutdownPrewarmed(): Promise<void> {\n await this.init();\n\n for (const containerUUID of [...this.warmContainers]) {\n try {\n const stub = this.getSandboxStub(containerUUID);\n await (stub as unknown as ContainerRpc).destroy();\n this.warmContainers.delete(containerUUID);\n } catch (error) {\n console.error({\n message: 'Failed to destroy container',\n component: 'warm-pool',\n containerUUID,\n error\n });\n }\n }\n\n await this.persist();\n }\n\n // =======================================================================\n // Alarm handler\n // =======================================================================\n\n async alarm(): Promise<void> {\n await this.init();\n\n this.capacityExhausted = false;\n\n try {\n await this.checkContainerHealth();\n await this.adjustPool();\n await this.keepWarmContainersAlive();\n } catch (error) {\n console.error({\n message: 'Alarm handler error',\n component: 'warm-pool',\n error\n });\n }\n\n await this.ctx.storage.setAlarm(Date.now() + this.config.refreshInterval);\n }\n\n // =======================================================================\n // Private — initialisation & persistence\n // =======================================================================\n\n private async init(): Promise<void> {\n if (this.initialized) return;\n\n const storedWarm =\n await this.ctx.storage.get<Set<string>>('warmContainers');\n if (storedWarm) this.warmContainers = new Set(storedWarm);\n\n const storedAssignments =\n await this.ctx.storage.get<Map<string, string>>('assignments');\n if (storedAssignments) this.assignments = new Map(storedAssignments);\n\n const storedConfig = await this.ctx.storage.get<WarmPoolConfig>('config');\n if (storedConfig) this.config = { ...DEFAULT_CONFIG, ...storedConfig };\n\n const storedMax = await this.ctx.storage.get<number>('knownMaxInstances');\n if (storedMax !== undefined) this.knownMaxInstances = storedMax;\n\n this.initialized = true;\n await this.scheduleRefresh();\n }\n\n private async persist(): Promise<void> {\n await this.ctx.storage.put('warmContainers', this.warmContainers);\n await this.ctx.storage.put('assignments', this.assignments);\n if (this.knownMaxInstances !== null) {\n await this.ctx.storage.put('knownMaxInstances', this.knownMaxInstances);\n } else {\n await this.ctx.storage.delete('knownMaxInstances');\n }\n }\n\n private async scheduleRefresh(): Promise<void> {\n const alarm = await this.ctx.storage.getAlarm();\n if (!alarm) {\n await this.ctx.storage.setAlarm(Date.now() + this.config.refreshInterval);\n }\n }\n\n // =======================================================================\n // Private — container lifecycle\n // =======================================================================\n\n private async startContainer(): Promise<string | null> {\n const containerUUID = crypto.randomUUID();\n this.startingContainers.add(containerUUID);\n\n try {\n const stub = this.getSandboxStub(containerUUID);\n await (stub as unknown as ContainerRpc).startAndWaitForPorts();\n console.info({\n message: 'Container started',\n component: 'warm-pool',\n containerUUID\n });\n return containerUUID;\n } catch (error) {\n if (this.isMaxInstancesError(error)) {\n await this.recordCapacityLimit();\n } else {\n console.error({\n message: 'Failed to start container',\n component: 'warm-pool',\n containerUUID,\n error\n });\n }\n return null;\n } finally {\n this.startingContainers.delete(containerUUID);\n }\n }\n\n private async isContainerRunning(containerUUID: string): Promise<boolean> {\n if (this.startingContainers.has(containerUUID)) return true;\n\n try {\n const stub = this.getSandboxStub(containerUUID);\n const state = await (stub as unknown as ContainerWithState).getState();\n return state.status === 'running' || state.status === 'healthy';\n } catch (error) {\n console.warn({\n message: 'Failed to check container status, assuming stopped',\n component: 'warm-pool',\n containerUUID,\n error\n });\n return false;\n }\n }\n\n private async checkContainerHealth(): Promise<void> {\n const allUUIDs = [...this.warmContainers, ...this.assignments.values()];\n\n let anyRemoved = false;\n for (const uuid of allUUIDs) {\n const running = await this.isContainerRunning(uuid);\n if (!running) {\n console.info({\n message: 'Container not running, removing from pool',\n component: 'warm-pool',\n containerUUID: uuid\n });\n if (this.removeContainer(uuid)) anyRemoved = true;\n }\n }\n\n if (anyRemoved) await this.persist();\n }\n\n /**\n * Renew activity timeout on all warm containers to prevent them from sleeping.\n */\n private async keepWarmContainersAlive(): Promise<void> {\n for (const containerUUID of this.warmContainers) {\n try {\n const stub = this.getSandboxStub(containerUUID);\n (stub as unknown as ContainerRpc).renewActivityTimeout();\n } catch (error) {\n console.error({\n message: 'Failed to renew activity timeout',\n component: 'warm-pool',\n containerUUID,\n error\n });\n }\n }\n }\n\n /**\n * Scale the warm pool towards warmTarget, respecting inferred max_instances.\n */\n private async adjustPool(): Promise<void> {\n let diff = this.config.warmTarget - this.warmContainers.size;\n\n if (diff > 0) {\n const capacity = this.remainingCapacity();\n\n // Probe with one start to detect if max_instances was increased\n if (capacity === 0 && this.knownMaxInstances !== null) {\n console.info({\n message: 'Pool at inferred limit, probing for capacity changes',\n component: 'warm-pool',\n knownMaxInstances: this.knownMaxInstances\n });\n const probeUUID = await this.startContainer();\n if (probeUUID) {\n console.info({\n message: 'Probe succeeded, clearing cached limit',\n component: 'warm-pool'\n });\n this.knownMaxInstances = null;\n this.warmContainers.add(probeUUID);\n diff--;\n await this.persist();\n } else {\n await this.persist();\n return;\n }\n }\n\n const toStart = Math.min(diff, this.remainingCapacity());\n if (toStart <= 0) {\n console.log({\n message: 'Cannot scale up pool',\n component: 'warm-pool',\n needed: diff,\n available: this.remainingCapacity(),\n warm: this.warmContainers.size,\n assigned: this.assignments.size,\n knownMaxInstances: this.knownMaxInstances ?? 'unknown'\n });\n return;\n }\n\n console.info({\n message: 'Scaling up pool',\n component: 'warm-pool',\n starting: toStart,\n needed: diff,\n capacity: this.remainingCapacity()\n });\n for (let i = 0; i < toStart; i++) {\n if (this.capacityExhausted) {\n console.log({\n message: 'Capacity exhausted mid-loop, stopping further starts',\n component: 'warm-pool'\n });\n break;\n }\n const uuid = await this.startContainer();\n if (uuid) this.warmContainers.add(uuid);\n }\n await this.persist();\n } else if (diff < 0) {\n const excess = -diff;\n console.info({\n message: 'Scaling down pool',\n component: 'warm-pool',\n destroying: excess\n });\n\n const toDestroy = [...this.warmContainers].slice(0, excess);\n const destroyed: string[] = [];\n\n for (const uuid of toDestroy) {\n try {\n const stub = this.getSandboxStub(uuid);\n await (stub as unknown as ContainerRpc).destroy();\n destroyed.push(uuid);\n } catch (error) {\n console.error({\n message: 'Failed to destroy container',\n component: 'warm-pool',\n containerUUID: uuid,\n error\n });\n }\n }\n\n for (const uuid of destroyed) {\n this.warmContainers.delete(uuid);\n }\n await this.persist();\n }\n }\n\n // =======================================================================\n // Private — helpers\n // =======================================================================\n\n private removeContainer(containerUUID: string): boolean {\n let removed = false;\n\n if (this.warmContainers.delete(containerUUID)) removed = true;\n\n for (const [sandboxId, uuid] of this.assignments) {\n if (uuid === containerUUID) {\n this.assignments.delete(sandboxId);\n removed = true;\n break;\n }\n }\n\n return removed;\n }\n\n private remainingCapacity(): number {\n if (this.knownMaxInstances === null) return Infinity;\n return Math.max(\n 0,\n this.knownMaxInstances -\n (this.warmContainers.size + this.assignments.size)\n );\n }\n\n private isMaxInstancesError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error);\n return message.includes(\n 'Maximum number of running container instances exceeded'\n );\n }\n\n private async recordCapacityLimit(): Promise<void> {\n const currentTotal = this.warmContainers.size + this.assignments.size;\n this.knownMaxInstances = currentTotal;\n this.capacityExhausted = true;\n console.warn({\n message: 'Hit max_instances limit',\n component: 'warm-pool',\n inferredCeiling: currentTotal,\n warm: this.warmContainers.size,\n assigned: this.assignments.size\n });\n await this.ctx.storage.put('knownMaxInstances', this.knownMaxInstances);\n }\n\n private throwCapacityError(): never {\n const total = this.warmContainers.size + this.assignments.size;\n throw new Error(\n `Cannot start container: instance limit reached (${total}/${this.knownMaxInstances}). ` +\n 'All container slots are in use. Wait for existing containers to stop.'\n );\n }\n\n private getSandboxStub(containerUUID: string): DurableObjectStub {\n const id = this.env.Sandbox.idFromName(containerUUID);\n return this.env.Sandbox.get(id);\n }\n}\n","/**\n * @cloudflare/sandbox/bridge — Bridge factory for Cloudflare Sandbox Workers.\n *\n * Usage:\n * ```ts\n * import { bridge } from \"@cloudflare/sandbox/bridge\";\n * export { Sandbox } from \"@cloudflare/sandbox\";\n * export { WarmPool } from \"@cloudflare/sandbox/bridge\";\n *\n * export default bridge({\n * async fetch(request, env, ctx) {\n * return new Response(\"OK\");\n * },\n * async scheduled(controller, env, ctx) {\n * // custom scheduled logic\n * }\n * });\n * ```\n */\n\nimport { env as cfEnv } from 'cloudflare:workers';\nimport { primePool } from './pool';\nimport { createBridgeApp, type RouteConfig } from './routes';\nimport type { BridgeConfig, BridgeEnv, WorkerHandlers } from './types';\n\n// Re-export helpers that may be useful for testing / advanced use\nexport { resolveWorkspacePath, shellQuote } from './helpers';\nexport type { BridgeConfig, BridgeEnv, WorkerHandlers } from './types';\nexport type { PoolStats, WarmPoolConfig } from './warm-pool';\n// Re-export types and utilities consumers may need\nexport { WarmPool } from './warm-pool';\n\ninterface CheckBindingsOptions {\n sandboxBinding: string;\n warmPoolBinding: string;\n}\n\n/**\n * Log an error if the required Durable Object bindings are missing from the\n * module-level environment. The `cloudflare:workers` env exposes binding stubs\n * at module evaluation time, so a missing key means the wrangler.jsonc\n * configuration is wrong. The health endpoint performs the same validation at\n * request time and returns a 503.\n */\nfunction checkBindings(\n env: Record<string, unknown>,\n options: CheckBindingsOptions\n): void {\n const { sandboxBinding, warmPoolBinding } = options;\n const missing: string[] = [];\n\n if (!env[sandboxBinding]) missing.push(sandboxBinding);\n if (!env[warmPoolBinding]) missing.push(warmPoolBinding);\n\n if (missing.length > 0) {\n for (const binding of missing) {\n console.error({\n message: `Missing required binding \"${binding}\"`,\n component: 'bridge',\n binding,\n hint: `Ensure your wrangler.jsonc has a Durable Object binding named \"${binding}\".`\n });\n }\n }\n\n if (!env.SANDBOX_API_KEY) {\n console.warn({\n message: 'SANDBOX_API_KEY is not set \\u2014 auth is disabled',\n component: 'bridge',\n hint: 'Set via `wrangler secret put SANDBOX_API_KEY`.'\n });\n }\n}\n\n/**\n * Create a Worker export that wraps user handlers with bridge functionality.\n *\n * The bridge:\n * 1. Checks that required Durable Object bindings exist (logs errors if missing).\n * 2. Wraps `fetch()` to serve bridge API routes first, then falls through to the user handler.\n * 3. Wraps `scheduled()` to prime the warm pool, then calls the user handler.\n * 4. Passes through all other properties unchanged.\n *\n * @param worker - The user's worker handlers (fetch, scheduled, and any others).\n * @param config - Optional configuration for binding names and route paths.\n */\nexport function bridge(\n worker: WorkerHandlers,\n config?: BridgeConfig\n): ExportedHandler<BridgeEnv> {\n const sandboxBinding = config?.bindings?.sandbox ?? 'Sandbox';\n const warmPoolBinding = config?.bindings?.warmPool ?? 'WarmPool';\n const apiPrefix = config?.apiRoutePrefix ?? '/v1';\n const healthPath = config?.healthRoute ?? '/health';\n\n // Check bindings at module evaluation time\n checkBindings(cfEnv as unknown as Record<string, unknown>, {\n sandboxBinding,\n warmPoolBinding\n });\n\n // Build the Hono app with the configured routes\n const routeConfig: RouteConfig = {\n sandboxBinding,\n warmPoolBinding,\n apiPrefix,\n healthPath\n };\n const app = createBridgeApp(routeConfig);\n\n // Collect pass-through properties from the worker (everything except fetch/scheduled)\n const passThrough: Record<string, unknown> = {};\n for (const key of Object.keys(worker)) {\n if (key !== 'fetch' && key !== 'scheduled') {\n passThrough[key] = worker[key];\n }\n }\n\n return {\n ...passThrough,\n\n async fetch(\n request: Request,\n env: BridgeEnv,\n ctx: ExecutionContext\n ): Promise<Response> {\n // 1. Try bridge API routes\n const url = new URL(request.url);\n if (\n url.pathname.startsWith(`${apiPrefix}/`) ||\n url.pathname === apiPrefix ||\n url.pathname === healthPath\n ) {\n return app.fetch(request, env, ctx);\n }\n\n // 2. Fall through to user handler\n if (worker.fetch) {\n return worker.fetch(request, env, ctx);\n }\n\n return new Response('Not Found', { status: 404 });\n },\n\n async scheduled(\n controller: ScheduledController,\n env: BridgeEnv,\n ctx: ExecutionContext\n ): Promise<void> {\n // Prime the warm pool on every scheduled trigger\n await primePool(env, warmPoolBinding);\n\n // Then call user's scheduled handler if provided\n if (worker.scheduled) {\n await worker.scheduled(controller, env, ctx);\n }\n }\n };\n}\n"],"mappings":"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,SAAS,CAAC,cAAc;MACzB;KACF;IACF;GACD,oBAAoB;IAClB,MAAM;IACN,UAAU,CAAC,aAAa,UAAU;IAClC,YAAY;KACV,QAAQ;MACN,MAAM;MACN,aACE;MACF,SAAS;MACV;KACD,SAAS;MACP,MAAM;MACN,aACE;MACF,SAAS;MACV;KACD,WAAW;MACT,MAAM;MACN,aAAa;MACb,SAAS;MACV;KACD,SAAS,EACP,MAAM,kDACP;KACF;IACF;GACD,sBAAsB;IACpB,MAAM;IACN,UAAU,CAAC,YAAY;IACvB,YAAY,EACV,WAAW;KACT,MAAM;KACN,aAAa;KACb,SAAS;KACV,EACF;IACF;GACD,eAAe;IACb,MAAM;IACN,YAAY,EACV,MAAM;KACJ,MAAM;KACN,aACE;KACF,SAAS;KACV,EACF;IACF;GACD,QAAQ;IACN,MAAM;IACN,UAAU;KAAC;KAAM;KAAQ;KAAO;KAAY;KAAY;IACxD,YAAY;KACV,IAAI,EAAE,MAAM,UAAU;KACtB,MAAM;MACJ,MAAM;MACN,aAAa;MACb,SAAS;MACV;KACD,KAAK;MACH,MAAM;MACN,QAAQ;MACR,SAAS;MACV;KACD,UAAU;MACR,MAAM;MACN,SAAS;MACV;KACD,WAAW;MACT,MAAM;MACN,QAAQ;MACT;KACD,MAAM;MACJ,MAAM;MACN,aAAa;MACb,SAAS;MACV;KACF;IACF;GACD,eAAe;IACb,MAAM;IACN,UAAU,CAAC,SAAS,OAAO;IAC3B,YAAY;KACV,OAAO;MACL,MAAM;MACN,aAAa;MACd;KACD,MAAM;MACJ,MAAM;MACN,aAAa;MACb,MAAM;OACJ;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACD;MACF;KACF;IACF;GACD,WAAW;IACT,MAAM;IACN,UAAU;KAAC;KAAQ;KAAY;KAAS;KAAU;KAAe;IACjE,YAAY;KACV,MAAM;MACJ,MAAM;MACN,aAAa;MACd;KACD,UAAU;MACR,MAAM;MACN,aAAa;MACd;KACD,OAAO;MACL,MAAM;MACN,aAAa;MACd;KACD,QAAQ;MACN,MAAM;MACN,YAAY;OACV,YAAY,EAAE,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QACE;GACH,CACF;EACD,WAAW;GACT,OAAO;IACL,aAAa;IACb,SAAS,EACP,oBAAoB,EAClB,QAAQ;KACN,MAAM;KACN,UAAU,CAAC,KAAK;KAChB,YAAY,EACV,IAAI;MACF,MAAM;MACN,aACE;MACF,SAAS;MACV,EACF;KACF,EACF,EACF;IACF;GACD,OAAO,EAAE,MAAM,uCAAuC;GACvD;EACF,EACF;CACD,oBAAoB,EAClB,QAAQ;EACN,aAAa;EACb,SAAS;EACT,aACE;EAEF,iBAAiB,CACf;GACE,MAAM;GACN,OAAO;GACP,QACE;GAEH,CACF;EACD,YAAY,CACV;GACE,MAAM;GACN,IAAI;GACJ,UAAU;GACV,QAAQ,EAAE,MAAM,UAAU;GAC1B,aAAa;GACd,CACF;EACD,WAAW;GACT,OAAO,EACL,aACE,sEACH;GACD,OAAO,EAAE,MAAM,uCAAuC;GACvD;EACF,EACF;CACD,WAAW,EACT,KAAK;EACH,aAAa;EACb,SAAS;EACT,aAAa;EACb,iBAAiB,CACf;GACE,MAAM;GACN,OAAO;GACP,QAAQ;GACT,CACF;EACD,UAAU,EAAE;EACZ,WAAW,EACT,OAAO;GACL,aAAa;GACb,SAAS,EACP,oBAAoB,EAClB,QAAQ,EAAE,MAAM,mCAAmC,EACpD,EACF;GACF,EACF;EACF,EACF;CACD,oBAAoB,EAClB,KAAK;EACH,aAAa;EACb,SAAS;EACT,aAAa;EACb,iBAAiB,CACf;GACE,MAAM;GACN,OAAO;GACP,QACE;GAEH,CACF;EACD,WAAW;GACT,OAAO;IACL,aAAa;IACb,SAAS,EACP,oBAAoB,EAClB,QAAQ,EAAE,MAAM,UAAU,EAC3B,EACF;IACF;GACD,OAAO,EAAE,MAAM,uCAAuC;GACvD;EACF,EACF;CACD,kBAAkB,EAChB,KAAK;EACH,aAAa;EACb,SAAS;EACT,aACE;EACF,iBAAiB,CACf;GACE,MAAM;GACN,OAAO;GACP,QACE;GAEH,CACF;EACD,WAAW;GACT,OAAO;IACL,aAAa;IACb,SAAS,EACP,oBAAoB,EAClB,QAAQ,EAAE,MAAM,kCAAkC,EACnD,EACF;IACF;GA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"}