@cloudflare/sandbox 0.8.10 → 0.8.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bridge/index.d.ts +187 -0
- package/dist/bridge/index.d.ts.map +1 -0
- package/dist/bridge/index.js +2499 -0
- package/dist/bridge/index.js.map +1 -0
- package/dist/{contexts-DqnVW04M.d.ts → contexts-icMN26lE.d.ts} +1 -1
- package/dist/{contexts-DqnVW04M.d.ts.map → contexts-icMN26lE.d.ts.map} +1 -1
- package/dist/{dist-CR1a2zcN.js → dist-Ilf8VjmX.js} +1 -1
- package/dist/{dist-CR1a2zcN.js.map → dist-Ilf8VjmX.js.map} +1 -1
- package/dist/{errors-DJtO4mmS.js → errors-Bz21XTBJ.js} +1 -1
- package/dist/{errors-DJtO4mmS.js.map → errors-Bz21XTBJ.js.map} +1 -1
- package/dist/file-stream-Bn2PceyF.js +6262 -0
- package/dist/file-stream-Bn2PceyF.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +5 -6261
- package/dist/openai/index.d.ts +1 -1
- package/dist/openai/index.js +1 -1
- package/dist/opencode/index.d.ts +2 -2
- package/dist/opencode/index.js +2 -2
- package/dist/{sandbox-CbGbomnq.d.ts → sandbox-C0Tjs0dj.d.ts} +1 -1
- package/dist/{sandbox-CbGbomnq.d.ts.map → sandbox-C0Tjs0dj.d.ts.map} +1 -1
- package/package.json +8 -2
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["env","body: ErrorResponse","parts: string[]","getSandbox","_getSandbox","env","body: ExecRequest","executor:\n | BridgeSandbox\n | Awaited<ReturnType<BridgeSandbox['getSession']>>","opts: { timeout?: number; cwd?: string }","lastWrite: Promise<void>","opts: PtyOptions","tarBytes: Uint8Array","body: MountBucketRequest","sdkOptions: {\n endpoint: string;\n readOnly?: boolean;\n prefix?: string;\n credentials?: { accessKeyId: string; secretAccessKey: string };\n }","body: UnmountBucketRequest","body: { id?: string; cwd?: string; env?: Record<string, string> }","errors: string[]","openapiAuth: MiddlewareHandler<{ Bindings: BridgeEnv }>","DEFAULT_CONFIG: Required<WarmPoolConfig>","containerUUID","stopped: string[]","missing: string[]","env","cfEnv","passThrough: Record<string, unknown>"],"sources":["../../src/bridge/pool.ts","../../src/bridge/helpers.ts","../../src/bridge/openapi.ts","../../src/bridge/openapi-html.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// Session ID validation\n// ---------------------------------------------------------------------------\n\n/**\n * Validate a session ID. Rejects path traversal, control chars, and excessive length.\n * Returns the validated ID or null if invalid.\n */\nexport function validateSessionId(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 return new ReadableStream<Uint8Array>({\n async start(controller) {\n try {\n for await (const chunk of streamFile(sse)) {\n controller.enqueue(\n chunk instanceof Uint8Array ? chunk : encoder.encode(chunk)\n );\n }\n controller.close();\n } catch (err) {\n controller.error(err);\n }\n }\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_SCHEMA = {\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 ExecRequest: {\n type: 'object',\n required: ['argv'],\n properties: {\n argv: {\n type: 'array',\n items: { type: 'string' },\n minItems: 1,\n description:\n 'Argv array — already shell-expanded by the Python layer if shell=True.',\n example: ['sh', '-lc', 'echo hello']\n },\n timeout_ms: {\n type: 'integer',\n description: 'Per-call timeout in milliseconds.',\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 }\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 required: ['endpoint'],\n properties: {\n endpoint: {\n type: 'string',\n description: 'S3-compatible endpoint URL.',\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 and end with `/`.',\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 }\n },\n MountBucketRequest: {\n type: 'object',\n required: ['bucket', 'mountPath', 'options'],\n properties: {\n bucket: {\n type: 'string',\n description: 'Bucket name.',\n example: 'my-r2-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 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 'session_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 }\n },\n security: [{ BearerAuth: [] }],\n paths: {\n '/v1/sandbox': {\n post: {\n operationId: 'createSandbox',\n summary: 'Create a new sandbox session',\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 session 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}/exec': {\n post: {\n operationId: 'execCommand',\n summary: 'Execute a command in the sandbox',\n description:\n 'Runs a shell command inside the named sandbox and streams output as Server-Sent Events (SSE). ' +\n 'Events: `stdout` (base64 chunk), `stderr` (base64 chunk), `exit` (JSON with exit_code), `error` (JSON with error and code). ' +\n 'The stream terminates after an `exit` or `error` event.',\n 'x-codeSamples': [\n {\n lang: 'curl',\n label: 'cURL',\n source:\n 'curl -N -X POST https://$HOST/v1/sandbox/my-sandbox/exec \\\\\\n' +\n ' -H \"Authorization: Bearer $SANDBOX_API_KEY\" \\\\\\n' +\n ' -H \"Content-Type: application/json\" \\\\\\n' +\n ' -d \\'{\"argv\":[\"sh\",\"-lc\",\"echo hello\"]}\\''\n }\n ],\n parameters: [\n {\n name: 'id',\n in: 'path',\n required: true,\n schema: { type: 'string' },\n description: 'Sandbox instance name (maps to a Durable Object key).'\n },\n {\n name: 'Session-Id',\n in: 'header',\n required: false,\n schema: { type: 'string', pattern: '^[a-zA-Z0-9._-]{1,128}$' },\n description:\n 'Scope this operation to a specific session. Uses the default session if omitted.'\n }\n ],\n requestBody: {\n required: true,\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ExecRequest' }\n }\n }\n },\n responses: {\n '200': {\n description:\n 'SSE stream of command output. Events:\\n' +\n '- `event: stdout` — data is a base64-encoded chunk of stdout\\n' +\n '- `event: stderr` — data is a base64-encoded chunk of stderr\\n' +\n '- `event: exit` — data is JSON `{\"exit_code\": N}` (terminal)\\n' +\n '- `event: error` — data is JSON `{\"error\": \"...\", \"code\": \"...\"}` (terminal)',\n content: {\n 'text/event-stream': {\n schema: { type: 'string' }\n }\n }\n },\n '400': { $ref: '#/components/responses/InvalidRequest' },\n '401': { $ref: '#/components/responses/Unauthorized' },\n '403': {\n description: 'cwd resolves outside /workspace.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: {\n error: 'cwd must resolve to a location within /workspace',\n code: 'invalid_request'\n }\n }\n }\n },\n '502': {\n description:\n 'SDK transport error before the SSE stream could be established. ' +\n 'Once the stream is open, errors are delivered as `event: error` SSE events instead.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: {\n error: 'exec failed: connection reset',\n code: 'exec_transport_error'\n }\n }\n }\n }\n }\n }\n },\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 name: 'Session-Id',\n in: 'header',\n required: false,\n schema: { type: 'string', pattern: '^[a-zA-Z0-9._-]{1,128}$' },\n description:\n 'Scope this operation to a specific session. Uses the default session if omitted.'\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 name: 'Session-Id',\n in: 'header',\n required: false,\n schema: { type: 'string', pattern: '^[a-zA-Z0-9._-]{1,128}$' },\n description:\n 'Scope this operation to a specific session. Uses the default session if omitted.'\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}/pty': {\n get: {\n operationId: 'ptyTerminal',\n summary: 'Open a PTY terminal session via WebSocket',\n description:\n 'Upgrades the HTTP connection to a WebSocket and proxies it to a PTY shell inside the sandbox.\\n\\n' +\n '**WebSocket frame protocol:**\\n\\n' +\n '| Direction | Frame type | Content |\\n' +\n '|-----------|------------|--------------------------------------------------|\\n' +\n '| Client → Server | Binary | UTF-8 encoded keystrokes / input |\\n' +\n '| Server → Client | Binary | Terminal output (including ANSI escape sequences) |\\n' +\n '| Client → Server | Text (JSON) | Control messages, e.g. `{\"type\":\"resize\",\"cols\":120,\"rows\":30}` |\\n' +\n '| Server → Client | Text (JSON) | Status messages: `ready`, `exit`, `error` |\\n\\n' +\n '**Status messages (server → client):**\\n' +\n '- `{\"type\":\"ready\"}` — PTY is accepting input\\n' +\n '- `{\"type\":\"exit\",\"code\":0,\"signal\":\"SIGTERM\"}` — PTY exited\\n' +\n '- `{\"type\":\"error\",\"message\":\"...\"}` — error occurred\\n\\n' +\n 'If the client disconnects, the PTY stays alive; reconnecting replays buffered output.',\n 'x-codeSamples': [\n {\n lang: 'JavaScript',\n label: 'WebSocket',\n source:\n 'const ws = new WebSocket(\"wss://$HOST/v1/sandbox/my-sandbox/pty?cols=120&rows=30\");\\n' +\n 'ws.binaryType = \"arraybuffer\";\\n' +\n 'ws.onmessage = (e) => { /* handle binary output or JSON status */ };'\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: 'cols',\n in: 'query',\n required: false,\n schema: { type: 'integer', default: 80 },\n description: 'Terminal width in columns.'\n },\n {\n name: 'rows',\n in: 'query',\n required: false,\n schema: { type: 'integer', default: 24 },\n description: 'Terminal height in rows.'\n },\n {\n name: 'shell',\n in: 'query',\n required: false,\n schema: { type: 'string' },\n description:\n 'Shell binary to run (e.g. `/bin/bash`). Uses the container default if omitted.'\n },\n {\n name: 'session',\n in: 'query',\n required: false,\n schema: { type: 'string' },\n description:\n 'SDK session ID. If provided, the PTY is scoped to this session.'\n },\n {\n name: 'Session-Id',\n in: 'header',\n required: false,\n schema: { type: 'string', pattern: '^[a-zA-Z0-9._-]{1,128}$' },\n description:\n 'Scope this operation to a specific session. Uses the default session if omitted.'\n }\n ],\n responses: {\n '101': {\n description:\n 'WebSocket upgrade successful. Binary and text frames flow bidirectionally as described above.'\n },\n '400': {\n description:\n 'Missing `Upgrade: websocket` header or invalid query parameters.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: {\n error: 'WebSocket upgrade required',\n code: 'invalid_request'\n }\n }\n }\n },\n '401': { $ref: '#/components/responses/Unauthorized' },\n '502': {\n description: 'SDK terminal() call failed.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: {\n error: 'terminal failed: connection reset',\n code: 'exec_transport_error'\n }\n }\n }\n }\n }\n }\n },\n '/v1/sandbox/{id}/running': {\n get: {\n operationId: 'isSandboxRunning',\n summary: 'Check whether the sandbox container is alive',\n description:\n 'Executes a no-op command inside the sandbox. Always returns HTTP 200; inspect the `running` field.',\n 'x-codeSamples': [\n {\n lang: 'curl',\n label: 'cURL',\n source:\n 'curl -X GET https://$HOST/v1/sandbox/my-sandbox/running \\\\\\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 '200': {\n description:\n 'Liveness status (always returned, even when not running).',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/RunningResponse' }\n }\n }\n },\n '401': { $ref: '#/components/responses/Unauthorized' }\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 '/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 '/v1/sandbox/{id}/session': {\n post: {\n operationId: 'createSession',\n summary: 'Create an execution session',\n description:\n 'Sessions isolate working directory and environment variables across commands. ' +\n 'The returned session ID is used with the `Session-Id` header on exec, file, and PTY endpoints.',\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: false,\n content: {\n 'application/json': {\n schema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Custom session ID. Auto-generated if omitted.'\n },\n cwd: {\n type: 'string',\n description: 'Initial working directory for the session.'\n },\n env: {\n type: 'object',\n additionalProperties: { type: 'string' },\n description: 'Environment variables scoped to this session.'\n }\n }\n }\n }\n }\n },\n responses: {\n '200': {\n description: 'Session created.',\n content: {\n 'application/json': {\n schema: {\n type: 'object',\n required: ['id'],\n properties: {\n id: {\n type: 'string',\n description: 'Session ID to pass via `Session-Id` header.'\n }\n }\n }\n }\n }\n },\n '401': { $ref: '#/components/responses/Unauthorized' },\n '502': {\n description: 'Session creation failed.',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: {\n error: 'session creation failed',\n code: 'session_error'\n }\n }\n }\n }\n }\n }\n },\n '/v1/sandbox/{id}/session/{sid}': {\n delete: {\n operationId: 'deleteSession',\n summary: 'Delete an execution session',\n description:\n 'Removes a named session. The default session cannot be deleted.',\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: 'sid',\n in: 'path',\n required: true,\n schema: { type: 'string' },\n description: 'Session ID to delete.'\n }\n ],\n responses: {\n '200': {\n description: 'Session deleted.',\n content: {\n 'application/json': {\n schema: {\n type: 'object',\n required: ['success', 'sessionId'],\n properties: {\n success: {\n type: 'boolean',\n description: '`true` if the session was deleted.'\n },\n sessionId: {\n type: 'string',\n description: 'ID of the deleted session.'\n }\n }\n }\n }\n }\n },\n '401': { $ref: '#/components/responses/Unauthorized' },\n '502': {\n description:\n 'Session deletion failed (e.g. cannot delete default session).',\n content: {\n 'application/json': {\n schema: { $ref: '#/components/schemas/ErrorResponse' },\n example: {\n error: 'cannot delete the default session',\n code: 'session_error'\n }\n }\n }\n }\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 'Stops all idle (unassigned) warm containers. Does not affect containers assigned to sandbox sessions.',\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 stopped.',\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 }\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,'&').replace(/</g,'<').replace(/>/g,'>');\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, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n}\n","/**\n * Hono application containing all bridge API routes.\n *\n * This module creates the Hono app parameterised by the bridge configuration\n * (binding names, route prefixes). The app is created once by the bridge()\n * factory and reused for all requests.\n */\n\nimport type { ExecutionSession, ISandbox, PtyOptions } from '@repo/shared';\nimport { Hono, type MiddlewareHandler } from 'hono';\nimport type { Sandbox } from '../sandbox';\nimport { getSandbox as _getSandbox } from '../sandbox';\nimport {\n base32Encode,\n errorJson,\n resolveWorkspacePath,\n shellQuote,\n sseToByteStream,\n toBase64,\n validateSessionId\n} from './helpers';\nimport { OPENAPI_SCHEMA } from './openapi';\nimport { renderOpenApiHtml } from './openapi-html';\nimport { primePool } from './pool';\nimport type {\n BridgeEnv,\n ExecRequest,\n MountBucketRequest,\n RunningResponse,\n UnmountBucketRequest,\n WriteResponse\n} from './types';\n\n// ---------------------------------------------------------------------------\n// BridgeSandbox type\n// ---------------------------------------------------------------------------\n\n/**\n * The SDK's getSandbox() proxy exposes methods not declared on ISandbox\n * (terminal, destroy) or declared with a narrower return type (getSession\n * without terminal). This type extends ISandbox with those extra methods\n * so call sites get type safety without per-call casts.\n */\ntype BridgeSandbox = ISandbox & {\n terminal(request: Request, options?: PtyOptions): Promise<Response>;\n getSession(sessionId: string): Promise<\n ExecutionSession & {\n terminal(request: Request, options?: PtyOptions): Promise<Response>;\n }\n >;\n destroy(): Promise<void>;\n};\n\n/** Typed wrapper around the SDK's getSandbox() that returns a BridgeSandbox. */\nfunction getSandbox<T extends Sandbox<any>>(\n ns: DurableObjectNamespace<T>,\n containerUUID: string\n): BridgeSandbox {\n return _getSandbox(ns, containerUUID) as unknown as BridgeSandbox;\n}\n\n// ---------------------------------------------------------------------------\n// Route configuration\n// ---------------------------------------------------------------------------\n\nexport interface RouteConfig {\n sandboxBinding: string;\n warmPoolBinding: string;\n apiPrefix: string;\n healthPath: string;\n}\n\n// ---------------------------------------------------------------------------\n// App factory\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 // Helper to get the Sandbox DO namespace from env\n function getSandboxNs(env: BridgeEnv): DurableObjectNamespace<any> {\n return env[sandboxBinding] as DurableObjectNamespace<any>;\n }\n\n function getWarmPoolNs(env: BridgeEnv): DurableObjectNamespace {\n return env[warmPoolBinding] as DurableObjectNamespace;\n }\n\n // ------------------------------------------------------------------\n // Auth middleware — applies to all /sandbox/* routes\n // ------------------------------------------------------------------\n\n app.use(`${apiPrefix}/sandbox/*`, async (c, next) => {\n // Validate sandbox ID format\n const url = new URL(c.req.url);\n const pathParts = url.pathname.split('/');\n // Path is {prefix}/sandbox/:id/... — find the ID\n const prefixParts = apiPrefix.split('/').filter(Boolean);\n const sandboxId = pathParts[prefixParts.length + 2]; // +1 for leading empty, +1 for \"sandbox\"\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 // ------------------------------------------------------------------\n // POST /sandbox\n // ------------------------------------------------------------------\n\n app.post(`${apiPrefix}/sandbox`, async (c) => {\n // Auth — same logic as the /sandbox/* middleware\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\n // Generate a sandbox ID: 16 random bytes → base32 (lowercase a-z, 2-7), 26 chars\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n const id = base32Encode(bytes);\n return c.json({ id });\n });\n\n // ------------------------------------------------------------------\n // Pool resolution middleware — maps sandbox ID to container UUID\n // ------------------------------------------------------------------\n\n app.use(`${apiPrefix}/sandbox/:id/*`, async (c, next) => {\n const sandboxId = c.req.param('id');\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\n const poolNs = getWarmPoolNs(c.env);\n const poolId = poolNs.idFromName('global-pool');\n const poolStub = poolNs.get(poolId);\n\n try {\n await (poolStub as any).configure({ warmTarget, refreshInterval });\n const containerUUID = await (poolStub as any).getContainer(sandboxId);\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 // Pool resolution for bare DELETE /sandbox/:id (no trailing path).\n // Uses lookupContainer() to avoid allocating a container just to destroy it.\n app.use(`${apiPrefix}/sandbox/:id`, async (c, next) => {\n // Pool resolution — only for DELETE (the only bare-path handler)\n if (c.req.method !== 'DELETE') return next();\n\n const sandboxId = c.req.param('id');\n\n const poolNs = getWarmPoolNs(c.env);\n const poolId = poolNs.idFromName('global-pool');\n const poolStub = poolNs.get(poolId);\n\n // Lookup only — don't allocate a new container just to destroy it\n try {\n const containerUUID = await (poolStub as any).lookupContainer(sandboxId);\n if (!containerUUID) {\n // No container exists for this sandbox — nothing to destroy\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 // ------------------------------------------------------------------\n // POST /sandbox/:id/exec\n // ------------------------------------------------------------------\n\n app.post(`${apiPrefix}/sandbox/:id/exec`, async (c) => {\n let body: ExecRequest;\n try {\n body = await c.req.json<ExecRequest>();\n } catch {\n return errorJson('Invalid JSON body', 'invalid_request', 400);\n }\n\n if (!Array.isArray(body.argv) || body.argv.length === 0) {\n return errorJson(\n 'argv must be a non-empty array',\n 'invalid_request',\n 400\n );\n }\n\n const sandbox = getSandbox(getSandboxNs(c.env), c.get('containerUUID'));\n const rawSessionId = c.req.header('Session-Id');\n let executor:\n | BridgeSandbox\n | Awaited<ReturnType<BridgeSandbox['getSession']>> = sandbox;\n if (rawSessionId) {\n const sessionId = validateSessionId(rawSessionId);\n if (!sessionId)\n return errorJson('Invalid session ID format', 'invalid_request', 400);\n executor = await sandbox.getSession(sessionId);\n }\n\n const command = body.argv.map(shellQuote).join(' ');\n\n const opts: { timeout?: number; cwd?: string } = {};\n if (typeof body.timeout_ms === 'number') {\n opts.timeout = body.timeout_ms;\n }\n if (typeof body.cwd === 'string') {\n const resolvedCwd = resolveWorkspacePath(body.cwd);\n if (!resolvedCwd) {\n return errorJson(\n 'cwd must resolve to a location within /workspace',\n 'invalid_request',\n 403\n );\n }\n opts.cwd = resolvedCwd;\n }\n\n // --- SSE streaming response ---\n const { readable, writable } = new TransformStream();\n const writer = writable.getWriter();\n const encoder = new TextEncoder();\n\n let closed = false;\n let lastWrite: Promise<void> = Promise.resolve();\n\n /** Write a single SSE event. Chains on the previous write to respect backpressure. */\n function writeSSE(event: string, data: string): void {\n if (closed) return;\n // SSE spec: each line of data needs its own \"data:\" prefix\n const payload = data\n .split('\\n')\n .map((line) => `data: ${line}`)\n .join('\\n');\n lastWrite = lastWrite.then(() =>\n writer.write(encoder.encode(`event: ${event}\\n${payload}\\n\\n`))\n );\n }\n\n function closeStream(): void {\n if (closed) return;\n closed = true;\n lastWrite.then(() => writer.close()).catch(() => {});\n }\n\n executor\n .exec(command, {\n ...opts,\n stream: true,\n onOutput(stream: 'stdout' | 'stderr', data: string) {\n writeSSE(stream, toBase64(data));\n },\n onComplete(result: { exitCode: number }) {\n writeSSE('exit', JSON.stringify({ exit_code: result.exitCode }));\n closeStream();\n },\n onError(err: Error) {\n writeSSE(\n 'error',\n JSON.stringify({ error: err.message, code: 'exec_error' })\n );\n closeStream();\n }\n })\n .catch((err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err);\n writeSSE(\n 'error',\n JSON.stringify({\n error: `exec failed: ${msg}`,\n code: 'exec_transport_error'\n })\n );\n closeStream();\n });\n\n return new Response(readable, {\n status: 200,\n headers: {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache'\n }\n });\n });\n\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(getSandboxNs(c.env), c.get('containerUUID'));\n const rawSessionId = c.req.header('Session-Id');\n let executor:\n | BridgeSandbox\n | Awaited<ReturnType<BridgeSandbox['getSession']>> = sandbox;\n if (rawSessionId) {\n const sessionId = validateSessionId(rawSessionId);\n if (!sessionId)\n return errorJson('Invalid session ID format', 'invalid_request', 400);\n executor = await sandbox.getSession(sessionId);\n }\n\n try {\n const stream = await executor.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(getSandboxNs(c.env), c.get('containerUUID'));\n const rawSessionId = c.req.header('Session-Id');\n let executor:\n | BridgeSandbox\n | Awaited<ReturnType<BridgeSandbox['getSession']>> = sandbox;\n if (rawSessionId) {\n const sessionId = validateSessionId(rawSessionId);\n if (!sessionId)\n return errorJson('Invalid session ID format', 'invalid_request', 400);\n executor = await sandbox.getSession(sessionId);\n }\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 executor.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 // ------------------------------------------------------------------\n // GET /sandbox/:id/running\n // ------------------------------------------------------------------\n\n app.get(`${apiPrefix}/sandbox/:id/running`, async (c) => {\n const sandbox = getSandbox(getSandboxNs(c.env), c.get('containerUUID'));\n\n try {\n await sandbox.exec('true');\n const response: RunningResponse = { running: true };\n return c.json(response);\n } catch {\n const response: RunningResponse = { running: false };\n return c.json(response);\n }\n });\n\n // ------------------------------------------------------------------\n // GET /sandbox/:id/pty (WebSocket upgrade)\n // ------------------------------------------------------------------\n\n app.get(`${apiPrefix}/sandbox/:id/pty`, async (c) => {\n // 1. Require WebSocket upgrade\n const upgrade = c.req.header('Upgrade');\n if (!upgrade || upgrade.toLowerCase() !== 'websocket') {\n return errorJson('WebSocket upgrade required', 'invalid_request', 400);\n }\n\n const sandbox = getSandbox(getSandboxNs(c.env), c.get('containerUUID'));\n\n // 2. Parse PtyOptions from query params\n const colsParam = c.req.query('cols');\n const rowsParam = c.req.query('rows');\n const shell = c.req.query('shell');\n const sessionId = c.req.header('Session-Id') || c.req.query('session');\n\n const cols = colsParam ? Number(colsParam) : 80;\n const rows = rowsParam ? Number(rowsParam) : 24;\n\n if (Number.isNaN(cols) || Number.isNaN(rows)) {\n return errorJson(\n 'cols and rows must be valid numbers',\n 'invalid_request',\n 400\n );\n }\n\n const opts: PtyOptions = { cols, rows };\n if (shell) {\n opts.shell = shell;\n }\n\n try {\n if (sessionId) {\n const validatedId = validateSessionId(sessionId);\n if (!validatedId)\n return errorJson('Invalid session ID format', 'invalid_request', 400);\n const sess = await sandbox.getSession(validatedId);\n return await sess.terminal(c.req.raw, opts);\n }\n return await sandbox.terminal(c.req.raw, opts);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return errorJson(`terminal failed: ${msg}`, 'exec_transport_error', 502);\n }\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(getSandboxNs(c.env), c.get('containerUUID'));\n\n const tmpPath = `/tmp/sandbox-persist-${Date.now()}.tar`;\n const excludeArgs = excludes\n .map((rel) => `--exclude ${shellQuote('./' + rel.replace(/^\\.\\//, ''))}`)\n .join(' ');\n const tarCmd = excludeArgs\n ? `tar cf ${shellQuote(tmpPath)} ${excludeArgs} -C ${shellQuote(root)} .`\n : `tar cf ${shellQuote(tmpPath)} -C ${shellQuote(root)} .`;\n\n try {\n const result = await sandbox.exec(tarCmd);\n\n if (result.exitCode !== 0) {\n return errorJson(\n `tar failed (exit ${result.exitCode}): ${result.stderr}`,\n 'workspace_archive_read_error',\n 502\n );\n }\n\n const stream = await sandbox.readFileStream(tmpPath);\n\n // Best-effort cleanup; don't await so we don't delay the response.\n sandbox.exec(`rm -f ${shellQuote(tmpPath)}`).catch(() => {});\n\n return new Response(sseToByteStream(stream), {\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(getSandboxNs(c.env), c.get('containerUUID'));\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 try {\n await sandbox.exec(`mkdir -p ${shellQuote(root)}`);\n\n const tmpPath = `/tmp/sandbox-hydrate-${Date.now()}.tar`;\n\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 const extractResult = await sandbox.exec(\n `tar xf ${shellQuote(tmpPath)} -C ${shellQuote(root)} && rm -f ${shellQuote(tmpPath)}`\n );\n if (extractResult.exitCode !== 0) {\n return errorJson(\n `tar extract failed (exit ${extractResult.exitCode}): ${extractResult.stderr}`,\n 'workspace_archive_write_error',\n 502\n );\n }\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 }\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 (!body.bucket || typeof body.bucket !== 'string') {\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 (!body.options || typeof body.options !== 'object') {\n return errorJson('options must be an object', 'invalid_request', 400);\n }\n if (!body.options.endpoint || typeof body.options.endpoint !== 'string') {\n return errorJson(\n 'options.endpoint must be a non-empty string',\n 'invalid_request',\n 400\n );\n }\n\n const sandbox = getSandbox(getSandboxNs(c.env), c.get('containerUUID'));\n\n const sdkOptions: {\n endpoint: string;\n readOnly?: boolean;\n prefix?: string;\n credentials?: { accessKeyId: string; secretAccessKey: string };\n } = {\n endpoint: body.options.endpoint\n };\n\n if (body.options.readOnly !== undefined) {\n sdkOptions.readOnly = body.options.readOnly;\n }\n if (body.options.prefix !== undefined) {\n sdkOptions.prefix = body.options.prefix;\n }\n if (body.options.credentials) {\n sdkOptions.credentials = {\n accessKeyId: body.options.credentials.accessKeyId,\n secretAccessKey: body.options.credentials.secretAccessKey\n };\n }\n\n try {\n await sandbox.mountBucket(body.bucket, 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(getSandboxNs(c.env), c.get('containerUUID'));\n\n try {\n await sandbox.unmountBucket(normalizedPath);\n\n // The SDK unmounts the filesystem but does not remove the mount point\n // directory. Verify the path is no longer an active mount before removing\n // it — if fusermount failed silently we must not delete bucket contents.\n const quoted = shellQuote(normalizedPath);\n try {\n await sandbox.exec(`mountpoint -q ${quoted} || rmdir ${quoted}`);\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 // POST /sandbox/:id/session\n // ------------------------------------------------------------------\n\n app.post(`${apiPrefix}/sandbox/:id/session`, async (c) => {\n const sandbox = getSandbox(getSandboxNs(c.env), c.get('containerUUID'));\n\n let body: { id?: string; cwd?: string; env?: Record<string, string> } = {};\n try {\n body = await c.req.json();\n } catch {\n // Empty body is fine — all fields are optional\n }\n\n try {\n const session = await sandbox.createSession(body);\n return c.json({ id: session.id });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return errorJson(`session create failed: ${msg}`, 'session_error', 502);\n }\n });\n\n // ------------------------------------------------------------------\n // DELETE /sandbox/:id/session/:sid\n // ------------------------------------------------------------------\n\n app.delete(`${apiPrefix}/sandbox/:id/session/:sid`, async (c) => {\n const sandbox = getSandbox(getSandboxNs(c.env), c.get('containerUUID'));\n const sid = c.req.param('sid');\n\n try {\n const result = await sandbox.deleteSession(sid);\n return c.json(result);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return errorJson(`session delete failed: ${msg}`, 'session_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(getSandboxNs(c.env), containerUUID);\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 poolNs = getWarmPoolNs(c.env);\n const poolId = poolNs.idFromName('global-pool');\n const poolStub = poolNs.get(poolId);\n await (poolStub as any).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(config.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 poolNs = getWarmPoolNs(c.env);\n const poolId = poolNs.idFromName('global-pool');\n const poolStub = poolNs.get(poolId);\n\n try {\n await (poolStub as any).configure({ warmTarget, refreshInterval });\n } catch {\n // Continue — stats should still be readable even if config push fails.\n }\n\n const stats = await (poolStub as any).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 poolNs = getWarmPoolNs(c.env);\n const poolId = poolNs.idFromName('global-pool');\n const poolStub = poolNs.get(poolId);\n\n try {\n await (poolStub as any).configure({ warmTarget, refreshInterval });\n } catch {\n // Continue.\n }\n\n await (poolStub as any).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 // ------------------------------------------------------------------\n // OpenAPI routes\n // ------------------------------------------------------------------\n\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 // Also accept the API key as a ?token= query parameter so browsers\n // and tools can load the spec without custom headers.\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 return app;\n}\n","/**\n * WarmPool — Durable Object that maintains a pool of pre-started sandbox containers.\n *\n * Adapted from https://github.com/mikenomitch/cf-container-warm-pool\n * Inlined and tailored for the @cloudflare/sandbox SDK.\n *\n * The pool keeps N idle containers standing by so new sandbox sessions boot\n * instantly. Once a container is assigned to a sandbox ID it is consumed and\n * never returned 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 stop(signal?: string): 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).stop();\n this.warmContainers.delete(containerUUID);\n } catch (error) {\n console.error({\n message: 'Failed to stop 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 stopping: excess\n });\n\n const toStop = [...this.warmContainers].slice(0, excess);\n const stopped: string[] = [];\n\n for (const uuid of toStop) {\n try {\n const stub = this.getSandboxStub(uuid);\n await (stub as unknown as ContainerRpc).stop();\n stopped.push(uuid);\n } catch (error) {\n console.error({\n message: 'Failed to stop container',\n component: 'warm-pool',\n containerUUID: uuid,\n error\n });\n }\n }\n\n for (const uuid of stopped) {\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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CAAC,KAAK;IAChB,YAAY,EACV,IAAI;KACF,MAAM;KACN,MAAM,CAAC,KAAK;KACZ,aAAa;KACd,EACF;IACF;GACD,wBAAwB;IACtB,MAAM;IACN,UAAU,CAAC,eAAe,kBAAkB;IAC5C,YAAY;KACV,aAAa;MACX,MAAM;MACN,aAAa;MACd;KACD,iBAAiB;MACf,MAAM;MACN,aAAa;MACd;KACF;IACF;GACD,2BAA2B;IACzB,MAAM;IACN,UAAU,CAAC,WAAW;IACtB,YAAY;KACV,UAAU;MACR,MAAM;MACN,aAAa;MACb,SAAS;MACV;KACD,UAAU;MACR,MAAM;MACN,aAAa;MACb,SAAS;MACV;KACD,QAAQ;MACN,MAAM;MACN,aACE;MACF,SAAS;MACV;KACD,aAAa;MACX,MAAM;MACN,aACE;MACH;KACF;IACF;GACD,oBAAoB;IAClB,MAAM;IACN,UAAU;KAAC;KAAU;KAAa;KAAU;IAC5C,YAAY;KACV,QAAQ;MACN,MAAM;MACN,aAAa;MACb,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,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,MAAM,WAAW;OAC/B,iBAAiB,EAAE,MAAM,WAAW;OACrC;MACF;KACD,cAAc;MACZ,MAAM,CAAC,WAAW,OAAO;MACzB,aACE;MACH;KACF;IACF;GACF;EACD,WAAW;GACT,cAAc;IACZ,aAAa;IACb,SAAS,EACP,oBAAoB;KAClB,QAAQ,EAAE,MAAM,sCAAsC;KACtD,SAAS;MAAE,OAAO;MAAgB,MAAM;MAAgB;KACzD,EACF;IACF;GACD,gBAAgB;IACd,aAAa;IACb,SAAS,EACP,oBAAoB;KAClB,QAAQ,EAAE,MAAM,sCAAsC;KACtD,SAAS;MACP,OAAO;MACP,MAAM;MACP;KACF,EACF;IACF;GACF;EACF;CACD,UAAU,CAAC,EAAE,YAAY,EAAE,EAAE,CAAC;CAC9B,OAAO;EACL,eAAe,EACb,MAAM;GACJ,aAAa;GACb,SAAS;GACT,aACE;GACF,iBAAiB,CACf;IACE,MAAM;IACN,OAAO;IACP,QACE;IACH,CACF;GACD,WAAW;IACT,OAAO;KACL,aAAa;KACb,SAAS,EACP,oBAAoB,EAClB,QAAQ;MACN,MAAM;MACN,UAAU,CAAC,KAAK;MAChB,YAAY,EACV,IAAI;OACF,MAAM;OACN,aACE;OACF,SAAS;OACV,EACF;MACF,EACF,EACF;KACF;IACD,OAAO,EAAE,MAAM,uCAAuC;IACvD;GACF,EACF;EACD,yBAAyB,EACvB,MAAM;GACJ,aAAa;GACb,SAAS;GACT,aACE;GAGF,iBAAiB,CACf;IACE,MAAM;IACN,OAAO;IACP,QACE;IAIH,CACF;GACD,YAAY,CACV;IACE,MAAM;IACN,IAAI;IACJ,UAAU;IACV,QAAQ,EAAE,MAAM,UAAU;IAC1B,aAAa;IACd,EACD;IACE,MAAM;IACN,IAAI;IACJ,UAAU;IACV,QAAQ;KAAE,MAAM;KAAU,SAAS;KAA2B;IAC9D,aACE;IACH,CACF;GACD,aAAa;IACX,UAAU;IACV,SAAS,EACP,oBAAoB,EAClB,QAAQ,EAAE,MAAM,oCAAoC,EACrD,EACF;IACF;GACD,WAAW;IACT,OAAO;KACL,aACE;KAKF,SAAS,EACP,qBAAqB,EACnB,QAAQ,EAAE,MAAM,UAAU,EAC3B,EACF;KACF;IACD,OAAO,EAAE,MAAM,yCAAyC;IACxD,OAAO,EAAE,MAAM,uCAAuC;IACtD,OAAO;KACL,aAAa;KACb,SAAS,EACP,oBAAoB;MAClB,QAAQ,EAAE,MAAM,sCAAsC;MACtD,SAAS;OACP,OAAO;OACP,MAAM;OACP;MACF,EACF;KACF;IACD,OAAO;KACL,aACE;KAEF,SAAS,EACP,oBAAoB;MAClB,QAAQ,EAAE,MAAM,sCAAsC;MACtD,SAAS;OACP,OAAO;OACP,MAAM;OACP;MACF,EACF;KACF;IACF;GACF,EACF;EACD,gCAAgC;GAC9B,KAAK;IACH,aAAa;IACb,SAAS;IACT,iBAAiB,CACf;KACE,MAAM;KACN,OAAO;KACP,QACE;KAGH,CACF;IACD,YAAY;KACV;MACE,MAAM;MACN,IAAI;MACJ,UAAU;MACV,QAAQ,EAAE,MAAM,UAAU;MAC1B,aAAa;MACd;KACD;MACE,MAAM;MACN,IAAI;MACJ,UAAU;MACV,QAAQ,EAAE,MAAM,UAAU;MAC1B,aACE;MACH;KACD;MACE,MAAM;MACN,IAAI;MACJ,UAAU;MACV,QAAQ;OAAE,MAAM;OAAU,SAAS;OAA2B;MAC9D,aACE;MACH;KACF;IACD,WAAW;KACT,OAAO;MACL,aAAa;MACb,SAAS,EACP,4BAA4B,EAC1B,QAAQ;OAAE,MAAM;OAAU,QAAQ;OAAU,EAC7C,EACF;MACF;KACD,OAAO,EAAE,MAAM,yCAAyC;KACxD,OAAO,EAAE,MAAM,uCAAuC;KACtD,OAAO;MACL,aAAa;MACb,SAAS,EACP,oBAAoB;OAClB,QAAQ,EAAE,MAAM,sCAAsC;OACtD,SAAS;QACP,OAAO;QACP,MAAM;QACP;OACF,EACF;MACF;KACD,OAAO;MACL,aAAa;MACb,SAAS,EACP,oBAAoB;OAClB,QAAQ,EAAE,MAAM,sCAAsC;OACtD,SAAS;QACP,OAAO;QACP,MAAM;QACP;OACF,EACF;MACF;KACD,OAAO;MACL,aAAa;MACb,SAAS,EACP,oBAAoB;OAClB,QAAQ,EAAE,MAAM,sCAAsC;OACtD,SAAS;QACP,OAAO;QACP,MAAM;QACP;OACF,EACF;MACF;KACF;IACF;GACD,KAAK;IACH,aAAa;IACb,SAAS;IACT,iBAAiB,CACf;KACE,MAAM;KACN,OAAO;KACP,QACE;KAIH,CACF;IACD,YAAY;KACV;MACE,MAAM;MACN,IAAI;MACJ,UAAU;MACV,QAAQ,EAAE,MAAM,UAAU;MAC1B,aAAa;MACd;KACD;MACE,MAAM;MACN,IAAI;MACJ,UAAU;MACV,QAAQ,EAAE,MAAM,UAAU;MAC1B,aACE;MACH;KACD;MACE,MAAM;MACN,IAAI;MACJ,UAAU;MACV,QAAQ;OAAE,MAAM;OAAU,SAAS;OAA2B;MAC9D,aACE;MACH;KACF;IACD,aAAa;KACX,UAAU;KACV,aAAa;KACb,SAAS,EACP,4BAA4B,EAC1B,QAAQ;MAAE,MAAM;MAAU,QAAQ;MAAU,EAC7C,EACF;KACF;IACD,WAAW;KACT,OAAO;MACL,aAAa;MACb,SAAS,EACP,oBAAoB,EAClB,QAAQ,EAAE,MAAM,sCAAsC,EACvD,EACF;MACF;KACD,OAAO,EAAE,MAAM,yCAAyC;KACxD,OAAO,EAAE,MAAM,uCAAuC;KACtD,OAAO;MACL,aAAa;MACb,SAAS,EACP,oBAAoB;OAClB,QAAQ,EAAE,MAAM,sCAAsC;OACtD,SAAS;QACP,OAAO;QACP,MAAM;QACP;OACF,EACF;MACF;KACD,OAAO;MACL,aAAa;MACb,SAAS,EACP,oBAAoB;OAClB,QAAQ,EAAE,MAAM,sCAAsC;OACtD,SAAS;QACP,OAAO;QACP,MAAM;QACP;OACF,EACF;MACF;KACF;IACF;GACF;EACD,wBAAwB,EACtB,KAAK;GACH,aAAa;GACb,SAAS;GACT,aACE;GAaF,iBAAiB,CACf;IACE,MAAM;IACN,OAAO;IACP,QACE;IAGH,CACF;GACD,YAAY;IACV;KACE,MAAM;KACN,IAAI;KACJ,UAAU;KACV,QAAQ,EAAE,MAAM,UAAU;KAC1B,aAAa;KACd;IACD;KACE,MAAM;KACN,IAAI;KACJ,UAAU;KACV,QAAQ;MAAE,MAAM;MAAW,SAAS;MAAI;KACxC,aAAa;KACd;IACD;KACE,MAAM;KACN,IAAI;KACJ,UAAU;KACV,QAAQ;MAAE,MAAM;MAAW,SAAS;MAAI;KACxC,aAAa;KACd;IACD;KACE,MAAM;KACN,IAAI;KACJ,UAAU;KACV,QAAQ,EAAE,MAAM,UAAU;KAC1B,aACE;KACH;IACD;KACE,MAAM;KACN,IAAI;KACJ,UAAU;KACV,QAAQ,EAAE,MAAM,UAAU;KAC1B,aACE;KACH;IACD;KACE,MAAM;KACN,IAAI;KACJ,UAAU;KACV,QAAQ;MAAE,MAAM;MAAU,SAAS;MAA2B;KAC9D,aACE;KACH;IACF;GACD,WAAW;IACT,OAAO,EACL,aACE,iGACH;IACD,OAAO;KACL,aACE;KACF,SAAS,EACP,oBAAoB;MAClB,QAAQ,EAAE,MAAM,sCAAsC;MACtD,SAAS;OACP,OAAO;OACP,MAAM;OACP;MACF,EACF;KACF;IACD,OAAO,EAAE,MAAM,uCAAuC;IACtD,OAAO;KACL,aAAa;KACb,SAAS,EACP,oBAAoB;MAClB,QAAQ,EAAE,MAAM,sCAAsC;MACtD,SAAS;OACP,OAAO;OACP,MAAM;OACP;MACF,EACF;KACF;IACF;GACF,EACF;EACD,4BAA4B,EAC1B,KAAK;GACH,aAAa;GACb,SAAS;GACT,aACE;GACF,iBAAiB,CACf;IACE,MAAM;IACN,OAAO;IACP,QACE;IAEH,CACF;GACD,YAAY,CACV;IACE,MAAM;IACN,IAAI;IACJ,UAAU;IACV,QAAQ,EAAE,MAAM,UAAU;IAC1B,aAAa;IACd,CACF;GACD,WAAW;IACT,OAAO;KACL,aACE;KACF,SAAS,EACP,oBAAoB,EAClB,QAAQ,EAAE,MAAM,wCAAwC,EACzD,EACF;KACF;IACD,OAAO,EAAE,MAAM,uCAAuC;IACvD;GACF,EACF;EACD,4BAA4B,EAC1B,MAAM;GACJ,aAAa;GACb,SAAS;GACT,aACE;GACF,iBAAiB,CACf;IACE,MAAM;IACN,OAAO;IACP,QACE;IAGH,CACF;GACD,YAAY,CACV;IACE,MAAM;IACN,IAAI;IACJ,UAAU;IACV,QAAQ,EAAE,MAAM,UAAU;IAC1B,aAAa;IACd,EACD;IACE,MAAM;IACN,IAAI;IACJ,UAAU;IACV,QAAQ,EAAE,MAAM,UAAU;IAC1B,aACE;IACF,SAAS;IACV,CACF;GACD,WAAW;IACT,OAAO;KACL,aAAa;KACb,SAAS,EACP,4BAA4B,EAC1B,QAAQ;MAAE,MAAM;MAAU,QAAQ;MAAU,EAC7C,EACF;KACF;IACD,OAAO;KACL,aAAa;KACb,SAAS,EACP,oBAAoB;MAClB,QAAQ,EAAE,MAAM,sCAAsC;MACtD,SAAS;OACP,OAAO;OACP,MAAM;OACP;MACF,EACF;KACF;IACD,OAAO,EAAE,MAAM,uCAAuC;IACtD,OAAO;KACL,aAAa;KACb,SAAS,EACP,oBAAoB;MAClB,QAAQ,EAAE,MAAM,sCAAsC;MACtD,SAAS;OACP,OAAO;OACP,MAAM;OACP;MACF,EACF;KACF;IACF;GACF,EACF;EACD,4BAA4B,EAC1B,MAAM;GACJ,aAAa;GACb,SAAS;GACT,aACE;GACF,iBAAiB,CACf;IACE,MAAM;IACN,OAAO;IACP,QACE;IAIH,CACF;GACD,YAAY,CACV;IACE,MAAM;IACN,IAAI;IACJ,UAAU;IACV,QAAQ,EAAE,MAAM,UAAU;IAC1B,aAAa;IACd,CACF;GACD,aAAa;IACX,UAAU;IACV,aAAa;IACb,SAAS,EACP,4BAA4B,EAC1B,QAAQ;KAAE,MAAM;KAAU,QAAQ;KAAU,EAC7C,EACF;IACF;GACD,WAAW;IACT,OAAO;KACL,aAAa;KACb,SAAS,EACP,oBAAoB,EAClB,QAAQ,EAAE,MAAM,mCAAmC,EACpD,EACF;KACF;IACD,OAAO,EAAE,MAAM,yCAAyC;IACxD,OAAO,EAAE,MAAM,uCAAuC;IACtD,OAAO;KACL,aAAa;KACb,SAAS,EACP,oBAAoB;MAClB,QAAQ,EAAE,MAAM,sCAAsC;MACtD,SAAS;OACP,OAAO;OACP,MAAM;OACP;MACF,EACF;KACF;IACF;GACF,EACF;EACD,0BAA0B,EACxB,MAAM;GACJ,aAAa;GACb,SAAS;GACT,aACE;GAEF,iBAAiB,CACf;IACE,MAAM;IACN,OAAO;IACP,QACE;IAIH,CACF;GACD,YAAY,CACV;IACE,MAAM;IACN,IAAI;IACJ,UAAU;IACV,QAAQ,EAAE,MAAM,UAAU;IAC1B,aAAa;IACd,CACF;GACD,aAAa;IACX,UAAU;IACV,SAAS,EACP,oBAAoB,EAClB,QAAQ,EAAE,MAAM,2CAA2C,EAC5D,EACF;IACF;GACD,WAAW;IACT,OAAO;KACL,aAAa;KACb,SAAS,EACP,oBAAoB,EAClB,QAAQ,EAAE,MAAM,mCAAmC,EACpD,EACF;KACF;IACD,OAAO,EAAE,MAAM,yCAAyC;IACxD,OAAO,EAAE,MAAM,uCAAuC;IACtD,OAAO;KACL,aACE;KACF,SAAS,EACP,oBAAoB;MAClB,QAAQ,EAAE,MAAM,sCAAsC;MACtD,SAAS;OACP,OAAO;OACP,MAAM;OACP;MACF,EACF;KACF;IACF;GACF,EACF;EACD,4BAA4B,EAC1B,MAAM;GACJ,aAAa;GACb,SAAS;GACT,aACE;GACF,iBAAiB,CACf;IACE,MAAM;IACN,OAAO;IACP,QACE;IAIH,CACF;GACD,YAAY,CACV;IACE,MAAM;IACN,IAAI;IACJ,UAAU;IACV,QAAQ,EAAE,MAAM,UAAU;IAC1B,aAAa;IACd,CACF;GACD,aAAa;IACX,UAAU;IACV,SAAS,EACP,oBAAoB,EAClB,QAAQ,EAAE,MAAM,6CAA6C,EAC9D,EACF;IACF;GACD,WAAW;IACT,OAAO;KACL,aAAa;KACb,SAAS,EACP,oBAAoB,EAClB,QAAQ,EAAE,MAAM,mCAAmC,EACpD,EACF;KACF;IACD,OAAO,EAAE,MAAM,yCAAyC;IACxD,OAAO,EAAE,MAAM,uCAAuC;IACtD,OAAO;KACL,aACE;KACF,SAAS,EACP,oBAAoB;MAClB,QAAQ,EAAE,MAAM,sCAAsC;MACtD,SAAS;OACP,OAAO;OACP,MAAM;OACP;MACF,EACF;KACF;IACF;GACF,EACF;EACD,oBAAoB,EAClB,QAAQ;GACN,aAAa;GACb,SAAS;GACT,aACE;GAEF,iBAAiB,CACf;IACE,MAAM;IACN,OAAO;IACP,QACE;IAEH,CACF;GACD,YAAY,CACV;IACE,MAAM;IACN,IAAI;IACJ,UAAU;IACV,QAAQ,EAAE,MAAM,UAAU;IAC1B,aAAa;IACd,CACF;GACD,WAAW;IACT,OAAO,EACL,aACE,sEACH;IACD,OAAO,EAAE,MAAM,uCAAuC;IACvD;GACF,EACF;EACD,4BAA4B,EAC1B,MAAM;GACJ,aAAa;GACb,SAAS;GACT,aACE;GAEF,YAAY,CACV;IACE,MAAM;IACN,IAAI;IACJ,UAAU;IACV,QAAQ,EAAE,MAAM,UAAU;IAC1B,aAAa;IACd,CACF;GACD,aAAa;IACX,UAAU;IACV,SAAS,EACP,oBAAoB,EAClB,QAAQ;KACN,MAAM;KACN,YAAY;MACV,IAAI;OACF,MAAM;OACN,aAAa;OACd;MACD,KAAK;OACH,MAAM;OACN,aAAa;OACd;MACD,KAAK;OACH,MAAM;OACN,sBAAsB,EAAE,MAAM,UAAU;OACxC,aAAa;OACd;MACF;KACF,EACF,EACF;IACF;GACD,WAAW;IACT,OAAO;KACL,aAAa;KACb,SAAS,EACP,oBAAoB,EAClB,QAAQ;MACN,MAAM;MACN,UAAU,CAAC,KAAK;MAChB,YAAY,EACV,IAAI;OACF,MAAM;OACN,aAAa;OACd,EACF;MACF,EACF,EACF;KACF;IACD,OAAO,EAAE,MAAM,uCAAuC;IACtD,OAAO;KACL,aAAa;KACb,SAAS,EACP,oBAAoB;MAClB,QAAQ,EAAE,MAAM,sCAAsC;MACtD,SAAS;OACP,OAAO;OACP,MAAM;OACP;MACF,EACF;KACF;IACF;GACF,EACF;EACD,kCAAkC,EAChC,QAAQ;GACN,aAAa;GACb,SAAS;GACT,aACE;GACF,YAAY,CACV;IACE,MAAM;IACN,IAAI;IACJ,UAAU;IACV,QAAQ,EAAE,MAAM,UAAU;IAC1B,aAAa;IACd,EACD;IACE,MAAM;IACN,IAAI;IACJ,UAAU;IACV,QAAQ,EAAE,MAAM,UAAU;IAC1B,aAAa;IACd,CACF;GACD,WAAW;IACT,OAAO;KACL,aAAa;KACb,SAAS,EACP,oBAAoB,EAClB,QAAQ;MACN,MAAM;MACN,UAAU,CAAC,WAAW,YAAY;MAClC,YAAY;OACV,SAAS;QACP,MAAM;QACN,aAAa;QACd;OACD,WAAW;QACT,MAAM;QACN,aAAa;QACd;OACF;MACF,EACF,EACF;KACF;IACD,OAAO,EAAE,MAAM,uCAAuC;IACtD,OAAO;KACL,aACE;KACF,SAAS,EACP,oBAAoB;MAClB,QAAQ,EAAE,MAAM,sCAAsC;MACtD,SAAS;OACP,OAAO;OACP,MAAM;OACP;MACF,EACF;KACF;IACF;GACF,EACF;EACD,WAAW,EACT,KAAK;GACH,aAAa;GACb,SAAS;GACT,aAAa;GACb,iBAAiB,CACf;IACE,MAAM;IACN,OAAO;IACP,QAAQ;IACT,CACF;GACD,UAAU,EAAE;GACZ,WAAW,EACT,OAAO;IACL,aAAa;IACb,SAAS,EACP,oBAAoB,EAClB,QAAQ,EAAE,MAAM,mCAAmC,EACpD,EACF;IACF,EACF;GACF,EACF;EACD,oBAAoB,EAClB,KAAK;GACH,aAAa;GACb,SAAS;GACT,aAAa;GACb,iBAAiB,CACf;IACE,MAAM;IACN,OAAO;IACP,QACE;IAEH,CACF;GACD,WAAW;IACT,OAAO;KACL,aAAa;KACb,SAAS,EACP,oBAAoB,EAClB,QAAQ,EAAE,MAAM,UAAU,EAC3B,EACF;KACF;IACD,OAAO,EAAE,MAAM,uCAAuC;IACvD;GACF,EACF;EACD,kBAAkB,EAChB,KAAK;GACH,aAAa;GACb,SAAS;GACT,aACE;GACF,iBAAiB,CACf;IACE,MAAM;IACN,OAAO;IACP,QACE;IAEH,CACF;GACD,WAAW;IACT,OAAO;KACL,aAAa;KACb,SAAS,EACP,oBAAoB,EAClB,QAAQ,EAAE,MAAM,kCAAkC,EACnD,EACF;KACF;IACD,OAAO,EAAE,MAAM,uCAAuC;IACvD;GACF,EACF;EACD,+BAA+B,EAC7B,MAAM;GACJ,aAAa;GACb,SAAS;GACT,aACE;GACF,iBAAiB,CACf;IACE,MAAM;IACN,OAAO;IACP,QACE;IAEH,CACF;GACD,WAAW;IACT,OAAO;KACL,aAAa;KACb,SAAS,EACP,oBAAoB,EAClB,QAAQ,EAAE,MAAM,mCAAmC,EACpD,EACF;KACF;IACD,OAAO,EAAE,MAAM,uCAAuC;IACvD;GACF,EACF;EACD,kBAAkB,EAChB,MAAM;GACJ,aAAa;GACb,SAAS;GACT,aACE;GAEF,iBAAiB,CACf;IACE,MAAM;IACN,OAAO;IACP,QACE;IAEH,CACF;GACD,WAAW;IACT,OAAO;KACL,aAAa;KACb,SAAS,EACP,oBAAoB,EAClB,QAAQ,EAAE,MAAM,mCAAmC,EACpD,EACF;KACF;IACD,OAAO,EAAE,MAAM,uCAAuC;IACvD;GACF,EACF;EACF;CACF;;;;;;;;;;;AC3tCD,SAAgB,kBAAkB,QAAyC;CACzE,MAAM,OAAO,KAAK,UAAU,OAAO;AAEnC,QAAkB;;;;;WAKT,IAAK,OAAO,MAAiC,SAAS,gBAAgB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAmP7D,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0Q1B,SAAS,IAAI,GAAoB;AAC/B,QAAO,OAAO,KAAK,GAAG,CACnB,QAAQ,MAAM,QAAQ,CACtB,QAAQ,MAAM,OAAO,CACrB,QAAQ,MAAM,OAAO;;;;;;AC3d1B,SAASC,aACP,IACA,eACe;AACf,QAAOC,WAAY,IAAI,cAAc;;AAkBvC,SAAgB,gBACd,QACqE;CACrE,MAAM,MAAM,IAAI,MAGZ;CAEJ,MAAM,EAAE,gBAAgB,iBAAiB,cAAc;CAGvD,SAAS,aAAa,OAA6C;AACjE,SAAOC,MAAI;;CAGb,SAAS,cAAc,OAAwC;AAC7D,SAAOA,MAAI;;AAOb,KAAI,IAAI,GAAG,UAAU,aAAa,OAAO,GAAG,SAAS;EAMnD,MAAM,YAJM,IAAI,IAAI,EAAE,IAAI,IAAI,CACR,SAAS,MAAM,IAAI,CAErB,UAAU,MAAM,IAAI,CAAC,OAAO,QAAQ,CAChB,SAAS;AACjD,MAAI,aAAa,CAAC,oBAAoB,KAAK,UAAU,CACnD,QAAO,UAAU,6BAA6B,mBAAmB,IAAI;EAGvE,MAAM,QAAQ,EAAE,IAAI;AACpB,MAAI,OAAO;GACT,MAAM,aAAa,EAAE,IAAI,OAAO,gBAAgB,IAAI;AAIpD,QAHiB,WAAW,aAAa,CAAC,WAAW,UAAU,GAC3D,WAAW,MAAM,EAAE,GACnB,QACa,MACf,QAAO,UAAU,gBAAgB,gBAAgB,IAAI;;AAGzD,SAAO,MAAM;GACb;AAMF,KAAI,KAAK,GAAG,UAAU,WAAW,OAAO,MAAM;EAE5C,MAAM,QAAQ,EAAE,IAAI;AACpB,MAAI,OAAO;GACT,MAAM,aAAa,EAAE,IAAI,OAAO,gBAAgB,IAAI;AAIpD,QAHiB,WAAW,aAAa,CAAC,WAAW,UAAU,GAC3D,WAAW,MAAM,EAAE,GACnB,QACa,MACf,QAAO,UAAU,gBAAgB,gBAAgB,IAAI;;EAKzD,MAAM,QAAQ,IAAI,WAAW,GAAG;AAChC,SAAO,gBAAgB,MAAM;EAC7B,MAAM,KAAK,aAAa,MAAM;AAC9B,SAAO,EAAE,KAAK,EAAE,IAAI,CAAC;GACrB;AAMF,KAAI,IAAI,GAAG,UAAU,iBAAiB,OAAO,GAAG,SAAS;EACvD,MAAM,YAAY,EAAE,IAAI,MAAM,KAAK;EAEnC,MAAM,aACJ,OAAO,SAAU,EAAE,IAAI,oBAA+B,KAAK,GAAG,IAAI;EACpE,MAAM,kBACJ,OAAO,SACJ,EAAE,IAAI,8BAAyC,SAChD,GACD,IAAI;EAEP,MAAM,SAAS,cAAc,EAAE,IAAI;EACnC,MAAM,SAAS,OAAO,WAAW,cAAc;EAC/C,MAAM,WAAW,OAAO,IAAI,OAAO;AAEnC,MAAI;AACF,SAAO,SAAiB,UAAU;IAAE;IAAY;IAAiB,CAAC;GAClE,MAAM,gBAAgB,MAAO,SAAiB,aAAa,UAAU;AACrE,KAAE,IAAI,iBAAiB,cAAc;WAC9B,KAAK;GACZ,MAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAC5D,OAAI,IAAI,SAAS,yBAAyB,CACxC,QAAO,UAAU,KAAK,qBAAqB,IAAI;AAEjD,UAAO,UAAU,eAAe,OAAO,cAAc,IAAI;;AAG3D,SAAO,MAAM;GACb;AAIF,KAAI,IAAI,GAAG,UAAU,eAAe,OAAO,GAAG,SAAS;AAErD,MAAI,EAAE,IAAI,WAAW,SAAU,QAAO,MAAM;EAE5C,MAAM,YAAY,EAAE,IAAI,MAAM,KAAK;EAEnC,MAAM,SAAS,cAAc,EAAE,IAAI;EACnC,MAAM,SAAS,OAAO,WAAW,cAAc;EAC/C,MAAM,WAAW,OAAO,IAAI,OAAO;AAGnC,MAAI;GACF,MAAM,gBAAgB,MAAO,SAAiB,gBAAgB,UAAU;AACxE,OAAI,CAAC,cAEH,QAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,CAAC;AAE5C,KAAE,IAAI,iBAAiB,cAAc;WAC9B,KAAK;AAEZ,UAAO,UAAU,eADL,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,IACrB,cAAc,IAAI;;AAG3D,SAAO,MAAM;GACb;AAMF,KAAI,KAAK,GAAG,UAAU,oBAAoB,OAAO,MAAM;EACrD,IAAIC;AACJ,MAAI;AACF,UAAO,MAAM,EAAE,IAAI,MAAmB;UAChC;AACN,UAAO,UAAU,qBAAqB,mBAAmB,IAAI;;AAG/D,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,IAAI,KAAK,KAAK,WAAW,EACpD,QAAO,UACL,kCACA,mBACA,IACD;EAGH,MAAM,UAAUH,aAAW,aAAa,EAAE,IAAI,EAAE,EAAE,IAAI,gBAAgB,CAAC;EACvE,MAAM,eAAe,EAAE,IAAI,OAAO,aAAa;EAC/C,IAAII,WAEmD;AACvD,MAAI,cAAc;GAChB,MAAM,YAAY,kBAAkB,aAAa;AACjD,OAAI,CAAC,UACH,QAAO,UAAU,6BAA6B,mBAAmB,IAAI;AACvE,cAAW,MAAM,QAAQ,WAAW,UAAU;;EAGhD,MAAM,UAAU,KAAK,KAAK,IAAI,WAAW,CAAC,KAAK,IAAI;EAEnD,MAAMC,OAA2C,EAAE;AACnD,MAAI,OAAO,KAAK,eAAe,SAC7B,MAAK,UAAU,KAAK;AAEtB,MAAI,OAAO,KAAK,QAAQ,UAAU;GAChC,MAAM,cAAc,qBAAqB,KAAK,IAAI;AAClD,OAAI,CAAC,YACH,QAAO,UACL,oDACA,mBACA,IACD;AAEH,QAAK,MAAM;;EAIb,MAAM,EAAE,UAAU,aAAa,IAAI,iBAAiB;EACpD,MAAM,SAAS,SAAS,WAAW;EACnC,MAAM,UAAU,IAAI,aAAa;EAEjC,IAAI,SAAS;EACb,IAAIC,YAA2B,QAAQ,SAAS;;EAGhD,SAAS,SAAS,OAAe,MAAoB;AACnD,OAAI,OAAQ;GAEZ,MAAM,UAAU,KACb,MAAM,KAAK,CACX,KAAK,SAAS,SAAS,OAAO,CAC9B,KAAK,KAAK;AACb,eAAY,UAAU,WACpB,OAAO,MAAM,QAAQ,OAAO,UAAU,MAAM,IAAI,QAAQ,MAAM,CAAC,CAChE;;EAGH,SAAS,cAAoB;AAC3B,OAAI,OAAQ;AACZ,YAAS;AACT,aAAU,WAAW,OAAO,OAAO,CAAC,CAAC,YAAY,GAAG;;AAGtD,WACG,KAAK,SAAS;GACb,GAAG;GACH,QAAQ;GACR,SAAS,QAA6B,MAAc;AAClD,aAAS,QAAQ,SAAS,KAAK,CAAC;;GAElC,WAAW,QAA8B;AACvC,aAAS,QAAQ,KAAK,UAAU,EAAE,WAAW,OAAO,UAAU,CAAC,CAAC;AAChE,iBAAa;;GAEf,QAAQ,KAAY;AAClB,aACE,SACA,KAAK,UAAU;KAAE,OAAO,IAAI;KAAS,MAAM;KAAc,CAAC,CAC3D;AACD,iBAAa;;GAEhB,CAAC,CACD,OAAO,QAAiB;GACvB,MAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAC5D,YACE,SACA,KAAK,UAAU;IACb,OAAO,gBAAgB;IACvB,MAAM;IACP,CAAC,CACH;AACD,gBAAa;IACb;AAEJ,SAAO,IAAI,SAAS,UAAU;GAC5B,QAAQ;GACR,SAAS;IACP,gBAAgB;IAChB,iBAAiB;IAClB;GACF,CAAC;GACF;AAMF,KAAI,IAAI,GAAG,UAAU,sBAAsB,OAAO,MAAM;EACtD,MAAM,YAAY,EAAE,IAAI,MAAM,KAAK;EAGnC,MAAM,WAAW,EAAE,IAAI;EACvB,MAAM,SAAS,GAAG,UAAU,WAAW,UAAU;EACjD,MAAM,eAAe,SAAS,MAAM,OAAO,OAAO;AAElD,MAAI,CAAC,aACH,QAAO,UAAU,+BAA+B,mBAAmB,IAAI;EAIzE,MAAM,eAAe,qBAAqB,MAAM,aAAa;AAC7D,MAAI,CAAC,aACH,QAAO,UACL,qDACA,mBACA,IACD;EAGH,MAAM,UAAUN,aAAW,aAAa,EAAE,IAAI,EAAE,EAAE,IAAI,gBAAgB,CAAC;EACvE,MAAM,eAAe,EAAE,IAAI,OAAO,aAAa;EAC/C,IAAII,WAEmD;AACvD,MAAI,cAAc;GAChB,MAAM,YAAY,kBAAkB,aAAa;AACjD,OAAI,CAAC,UACH,QAAO,UAAU,6BAA6B,mBAAmB,IAAI;AACvE,cAAW,MAAM,QAAQ,WAAW,UAAU;;AAGhD,MAAI;GACF,MAAM,SAAS,MAAM,SAAS,eAAe,aAAa;AAC1D,UAAO,IAAI,SAAS,gBAAgB,OAAO,EAAE;IAC3C,QAAQ;IACR,SAAS,EAAE,gBAAgB,4BAA4B;IACxD,CAAC;WACK,KAAK;AAEZ,OADc,IAA0B,SAC3B,iBACX,QAAO,UACL,mBAAmB,gBACnB,4BACA,IACD;AAGH,UAAO,UAAU,gBADL,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,IACpB,wBAAwB,IAAI;;GAEtE;AAMF,KAAI,IAAI,GAAG,UAAU,sBAAsB,OAAO,MAAM;EACtD,MAAM,YAAY,EAAE,IAAI,MAAM,KAAK;EAGnC,MAAM,WAAW,EAAE,IAAI;EACvB,MAAM,SAAS,GAAG,UAAU,WAAW,UAAU;EACjD,MAAM,eAAe,SAAS,MAAM,OAAO,OAAO;AAElD,MAAI,CAAC,aACH,QAAO,UAAU,+BAA+B,mBAAmB,IAAI;EAIzE,MAAM,eAAe,qBAAqB,MAAM,aAAa;AAC7D,MAAI,CAAC,aACH,QAAO,UACL,qDACA,mBACA,IACD;EAGH,MAAM,UAAUJ,aAAW,aAAa,EAAE,IAAI,EAAE,EAAE,IAAI,gBAAgB,CAAC;EACvE,MAAM,eAAe,EAAE,IAAI,OAAO,aAAa;EAC/C,IAAII,WAEmD;AACvD,MAAI,cAAc;GAChB,MAAM,YAAY,kBAAkB,aAAa;AACjD,OAAI,CAAC,UACH,QAAO,UAAU,6BAA6B,mBAAmB,IAAI;AACvE,cAAW,MAAM,QAAQ,WAAW,UAAU;;AAGhD,MAAI;GACF,MAAM,SAAS,MAAM,EAAE,IAAI,aAAa;GACxC,MAAM,kBAAkB,KAAK,OAAO;AACpC,OAAI,OAAO,aAAa,gBACtB,QAAO,UACL,sBAAsB,OAAO,WAAW,qBAAqB,gBAAgB,cAC7E,qBACA,IACD;GAGH,MAAM,QAAQ,IAAI,WAAW,OAAO;GACpC,IAAI,MAAM;GACV,MAAM,QAAQ;AACd,QAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,MACrC,QAAO,KAAK,OAAO,aAAa,GAAG,MAAM,SAAS,GAAG,IAAI,MAAM,CAAC,CAAC;AAEnE,SAAM,SAAS,UAAU,cAAc,KAAK,EAAE,UAAU,UAAU,CAAC;AAEnE,UAAO,EAAE,KADuB,EAAE,IAAI,MAAM,CACrB;WAChB,KAAK;AAEZ,UAAO,UACL,iBAFU,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,IAG1D,iCACA,IACD;;GAEH;AAMF,KAAI,IAAI,GAAG,UAAU,uBAAuB,OAAO,MAAM;EACvD,MAAM,UAAUJ,aAAW,aAAa,EAAE,IAAI,EAAE,EAAE,IAAI,gBAAgB,CAAC;AAEvE,MAAI;AACF,SAAM,QAAQ,KAAK,OAAO;AAE1B,UAAO,EAAE,KADyB,EAAE,SAAS,MAAM,CAC5B;UACjB;AAEN,UAAO,EAAE,KADyB,EAAE,SAAS,OAAO,CAC7B;;GAEzB;AAMF,KAAI,IAAI,GAAG,UAAU,mBAAmB,OAAO,MAAM;EAEnD,MAAM,UAAU,EAAE,IAAI,OAAO,UAAU;AACvC,MAAI,CAAC,WAAW,QAAQ,aAAa,KAAK,YACxC,QAAO,UAAU,8BAA8B,mBAAmB,IAAI;EAGxE,MAAM,UAAUA,aAAW,aAAa,EAAE,IAAI,EAAE,EAAE,IAAI,gBAAgB,CAAC;EAGvE,MAAM,YAAY,EAAE,IAAI,MAAM,OAAO;EACrC,MAAM,YAAY,EAAE,IAAI,MAAM,OAAO;EACrC,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ;EAClC,MAAM,YAAY,EAAE,IAAI,OAAO,aAAa,IAAI,EAAE,IAAI,MAAM,UAAU;EAEtE,MAAM,OAAO,YAAY,OAAO,UAAU,GAAG;EAC7C,MAAM,OAAO,YAAY,OAAO,UAAU,GAAG;AAE7C,MAAI,OAAO,MAAM,KAAK,IAAI,OAAO,MAAM,KAAK,CAC1C,QAAO,UACL,uCACA,mBACA,IACD;EAGH,MAAMO,OAAmB;GAAE;GAAM;GAAM;AACvC,MAAI,MACF,MAAK,QAAQ;AAGf,MAAI;AACF,OAAI,WAAW;IACb,MAAM,cAAc,kBAAkB,UAAU;AAChD,QAAI,CAAC,YACH,QAAO,UAAU,6BAA6B,mBAAmB,IAAI;AAEvE,WAAO,OADM,MAAM,QAAQ,WAAW,YAAY,EAChC,SAAS,EAAE,IAAI,KAAK,KAAK;;AAE7C,UAAO,MAAM,QAAQ,SAAS,EAAE,IAAI,KAAK,KAAK;WACvC,KAAK;AAEZ,UAAO,UAAU,oBADL,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,IAChB,wBAAwB,IAAI;;GAE1E;AAMF,KAAI,KAAK,GAAG,UAAU,uBAAuB,OAAO,MAAM;EACxD,MAAM,OAAO;EAGb,MAAM,gBAAgB,EAAE,IAAI,MAAM,WAAW,IAAI;EACjD,MAAM,WAAW,gBACb,cAAc,MAAM,IAAI,CAAC,QAAQ,MAAM,EAAE,SAAS,EAAE,GACpD,EAAE;AAGN,OAAK,MAAM,MAAM,SACf,KAAI,GAAG,SAAS,KAAK,CACnB,QAAO,UACL,yCACA,mBACA,IACD;EAIL,MAAM,UAAUP,aAAW,aAAa,EAAE,IAAI,EAAE,EAAE,IAAI,gBAAgB,CAAC;EAEvE,MAAM,UAAU,wBAAwB,KAAK,KAAK,CAAC;EACnD,MAAM,cAAc,SACjB,KAAK,QAAQ,aAAa,WAAW,OAAO,IAAI,QAAQ,SAAS,GAAG,CAAC,GAAG,CACxE,KAAK,IAAI;EACZ,MAAM,SAAS,cACX,UAAU,WAAW,QAAQ,CAAC,GAAG,YAAY,MAAM,WAAW,KAAK,CAAC,MACpE,UAAU,WAAW,QAAQ,CAAC,MAAM,WAAW,KAAK,CAAC;AAEzD,MAAI;GACF,MAAM,SAAS,MAAM,QAAQ,KAAK,OAAO;AAEzC,OAAI,OAAO,aAAa,EACtB,QAAO,UACL,oBAAoB,OAAO,SAAS,KAAK,OAAO,UAChD,gCACA,IACD;GAGH,MAAM,SAAS,MAAM,QAAQ,eAAe,QAAQ;AAGpD,WAAQ,KAAK,SAAS,WAAW,QAAQ,GAAG,CAAC,YAAY,GAAG;AAE5D,UAAO,IAAI,SAAS,gBAAgB,OAAO,EAAE;IAC3C,QAAQ;IACR,SAAS,EAAE,gBAAgB,4BAA4B;IACxD,CAAC;WACK,KAAK;AAEZ,UAAO,UACL,mBAFU,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,IAG1D,gCACA,IACD;;GAEH;AAMF,KAAI,KAAK,GAAG,UAAU,uBAAuB,OAAO,MAAM;EACxD,MAAM,OAAO;EAEb,MAAM,UAAUA,aAAW,aAAa,EAAE,IAAI,EAAE,EAAE,IAAI,gBAAgB,CAAC;EAGvE,IAAIQ;AACJ,MAAI;GACF,MAAM,SAAS,MAAM,EAAE,IAAI,aAAa;AACxC,cAAW,IAAI,WAAW,OAAO;UAC3B;AACN,UAAO,UAAU,+BAA+B,mBAAmB,IAAI;;AAGzE,MAAI,SAAS,eAAe,EAC1B,QAAO,UAAU,qBAAqB,mBAAmB,IAAI;EAG/D,MAAM,oBAAoB,KAAK,OAAO;AACtC,MAAI,SAAS,aAAa,kBACxB,QAAO,UACL,0BAA0B,SAAS,WAAW,qBAAqB,kBAAkB,cACrF,mBACA,IACD;AAGH,MAAI;AACF,SAAM,QAAQ,KAAK,YAAY,WAAW,KAAK,GAAG;GAElD,MAAM,UAAU,wBAAwB,KAAK,KAAK,CAAC;GAEnD,IAAI,MAAM;GACV,MAAM,QAAQ;AACd,QAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK,MACxC,QAAO,KAAK,OAAO,aAAa,GAAG,SAAS,SAAS,GAAG,IAAI,MAAM,CAAC,CAAC;AAEtE,SAAM,QAAQ,UAAU,SAAS,KAAK,EAAE,UAAU,UAAU,CAAC;GAE7D,MAAM,gBAAgB,MAAM,QAAQ,KAClC,UAAU,WAAW,QAAQ,CAAC,MAAM,WAAW,KAAK,CAAC,YAAY,WAAW,QAAQ,GACrF;AACD,OAAI,cAAc,aAAa,EAC7B,QAAO,UACL,4BAA4B,cAAc,SAAS,KAAK,cAAc,UACtE,iCACA,IACD;AAGH,UAAO,EAAE,KAAK,EAAE,IAAI,MAAM,CAAC;WACpB,KAAK;AAEZ,UAAO,UACL,mBAFU,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,IAG1D,iCACA,IACD;;GAEH;AAMF,KAAI,KAAK,GAAG,UAAU,qBAAqB,OAAO,MAAM;EACtD,IAAIC;AACJ,MAAI;AACF,UAAO,MAAM,EAAE,IAAI,MAA0B;UACvC;AACN,UAAO,UAAU,qBAAqB,mBAAmB,IAAI;;AAG/D,MAAI,CAAC,KAAK,UAAU,OAAO,KAAK,WAAW,SACzC,QAAO,UACL,qCACA,mBACA,IACD;AAEH,MAAI,CAAC,KAAK,aAAa,OAAO,KAAK,cAAc,SAC/C,QAAO,UACL,wCACA,mBACA,IACD;AAEH,MAAI,CAAC,KAAK,UAAU,WAAW,IAAI,CACjC,QAAO,UACL,qDACA,mBACA,IACD;AAEH,MAAI,CAAC,KAAK,WAAW,OAAO,KAAK,YAAY,SAC3C,QAAO,UAAU,6BAA6B,mBAAmB,IAAI;AAEvE,MAAI,CAAC,KAAK,QAAQ,YAAY,OAAO,KAAK,QAAQ,aAAa,SAC7D,QAAO,UACL,+CACA,mBACA,IACD;EAGH,MAAM,UAAUT,aAAW,aAAa,EAAE,IAAI,EAAE,EAAE,IAAI,gBAAgB,CAAC;EAEvE,MAAMU,aAKF,EACF,UAAU,KAAK,QAAQ,UACxB;AAED,MAAI,KAAK,QAAQ,aAAa,OAC5B,YAAW,WAAW,KAAK,QAAQ;AAErC,MAAI,KAAK,QAAQ,WAAW,OAC1B,YAAW,SAAS,KAAK,QAAQ;AAEnC,MAAI,KAAK,QAAQ,YACf,YAAW,cAAc;GACvB,aAAa,KAAK,QAAQ,YAAY;GACtC,iBAAiB,KAAK,QAAQ,YAAY;GAC3C;AAGH,MAAI;AACF,SAAM,QAAQ,YAAY,KAAK,QAAQ,KAAK,WAAW,WAAW;AAClE,UAAO,EAAE,KAAK,EAAE,IAAI,MAAM,CAAC;WACpB,KAAK;AAEZ,UAAO,UAAU,iBADL,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,IACnB,eAAe,IAAI;;GAE9D;AAMF,KAAI,KAAK,GAAG,UAAU,uBAAuB,OAAO,MAAM;EACxD,IAAIC;AACJ,MAAI;AACF,UAAO,MAAM,EAAE,IAAI,MAA4B;UACzC;AACN,UAAO,UAAU,qBAAqB,mBAAmB,IAAI;;AAG/D,MAAI,CAAC,KAAK,aAAa,OAAO,KAAK,cAAc,SAC/C,QAAO,UACL,wCACA,mBACA,IACD;AAEH,MAAI,CAAC,KAAK,UAAU,WAAW,IAAI,CACjC,QAAO,UACL,qDACA,mBACA,IACD;EAKH,MAAM,iBAAiB,IAAI,IAAI,KAAK,WAAW,WAAW,CAAC;AAC3D,MAAI,mBAAmB,IACrB,QAAO,UACL,qDACA,mBACA,IACD;EAGH,MAAM,UAAUX,aAAW,aAAa,EAAE,IAAI,EAAE,EAAE,IAAI,gBAAgB,CAAC;AAEvE,MAAI;AACF,SAAM,QAAQ,cAAc,eAAe;GAK3C,MAAM,SAAS,WAAW,eAAe;AACzC,OAAI;AACF,UAAM,QAAQ,KAAK,iBAAiB,OAAO,YAAY,SAAS;WAC1D;AAIR,UAAO,EAAE,KAAK,EAAE,IAAI,MAAM,CAAC;WACpB,KAAK;AAEZ,UAAO,UAAU,mBADL,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,IACjB,iBAAiB,IAAI;;GAElE;AAMF,KAAI,KAAK,GAAG,UAAU,uBAAuB,OAAO,MAAM;EACxD,MAAM,UAAUA,aAAW,aAAa,EAAE,IAAI,EAAE,EAAE,IAAI,gBAAgB,CAAC;EAEvE,IAAIY,OAAoE,EAAE;AAC1E,MAAI;AACF,UAAO,MAAM,EAAE,IAAI,MAAM;UACnB;AAIR,MAAI;GACF,MAAM,UAAU,MAAM,QAAQ,cAAc,KAAK;AACjD,UAAO,EAAE,KAAK,EAAE,IAAI,QAAQ,IAAI,CAAC;WAC1B,KAAK;AAEZ,UAAO,UAAU,0BADL,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,IACV,iBAAiB,IAAI;;GAEzE;AAMF,KAAI,OAAO,GAAG,UAAU,4BAA4B,OAAO,MAAM;EAC/D,MAAM,UAAUZ,aAAW,aAAa,EAAE,IAAI,EAAE,EAAE,IAAI,gBAAgB,CAAC;EACvE,MAAM,MAAM,EAAE,IAAI,MAAM,MAAM;AAE9B,MAAI;GACF,MAAM,SAAS,MAAM,QAAQ,cAAc,IAAI;AAC/C,UAAO,EAAE,KAAK,OAAO;WACd,KAAK;AAEZ,UAAO,UAAU,0BADL,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,IACV,iBAAiB,IAAI;;GAEzE;AAMF,KAAI,OAAO,GAAG,UAAU,eAAe,OAAO,MAAM;EAClD,MAAM,gBAAgB,EAAE,IAAI,gBAAgB;EAC5C,MAAM,UAAUA,aAAW,aAAa,EAAE,IAAI,EAAE,cAAc;AAE9D,MAAI;AACF,SAAM,QAAQ,SAAS;UACjB;AAKR,MAAI;GACF,MAAM,SAAS,cAAc,EAAE,IAAI;GACnC,MAAM,SAAS,OAAO,WAAW,cAAc;AAE/C,SADiB,OAAO,IAAI,OAAO,CACX,cAAc,cAAc;UAC9C;AAIR,SAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,CAAC;GAC1C;AAMF,KAAI,IAAI,OAAO,aAAa,MAAM;EAChC,MAAMa,SAAmB,EAAE;AAE3B,MAAI,CAAC,EAAE,IAAI,gBACT,QAAO,KACL,4CAA4C,eAAe,qDAAqD,eAAe,IAChI;AAEH,MAAI,CAAC,EAAE,IAAI,iBACT,QAAO,KACL,4CAA4C,gBAAgB,qDAAqD,gBAAgB,IAClI;AAGH,MAAI,OAAO,SAAS,EAClB,QAAO,EAAE,KAAK;GAAE,IAAI;GAAO;GAAQ,EAAE,IAAI;AAG3C,SAAO,EAAE,KAAK,EAAE,IAAI,MAAM,CAAC;GAC3B;AAMF,KAAI,IAAI,GAAG,UAAU,UAAU,OAAO,GAAG,SAAS;EAChD,MAAM,QAAQ,EAAE,IAAI;AACpB,MAAI,OAAO;GACT,MAAM,aAAa,EAAE,IAAI,OAAO,gBAAgB,IAAI;AAIpD,QAHiB,WAAW,WAAW,UAAU,GAC7C,WAAW,MAAM,EAAE,GACnB,QACa,MACf,QAAO,UAAU,gBAAgB,gBAAgB,IAAI;;AAGzD,SAAO,MAAM;GACb;AAEF,KAAI,IAAI,GAAG,UAAU,cAAc,OAAO,MAAM;EAC9C,MAAM,aACJ,OAAO,SAAU,EAAE,IAAI,oBAA+B,KAAK,GAAG,IAAI;EACpE,MAAM,kBACJ,OAAO,SACJ,EAAE,IAAI,8BAAyC,SAChD,GACD,IAAI;EAEP,MAAM,SAAS,cAAc,EAAE,IAAI;EACnC,MAAM,SAAS,OAAO,WAAW,cAAc;EAC/C,MAAM,WAAW,OAAO,IAAI,OAAO;AAEnC,MAAI;AACF,SAAO,SAAiB,UAAU;IAAE;IAAY;IAAiB,CAAC;UAC5D;EAIR,MAAM,QAAQ,MAAO,SAAiB,UAAU;AAChD,SAAO,EAAE,KAAK,MAAM;GACpB;AAEF,KAAI,KAAK,GAAG,UAAU,2BAA2B,OAAO,MAAM;EAC5D,MAAM,aACJ,OAAO,SAAU,EAAE,IAAI,oBAA+B,KAAK,GAAG,IAAI;EACpE,MAAM,kBACJ,OAAO,SACJ,EAAE,IAAI,8BAAyC,SAChD,GACD,IAAI;EAEP,MAAM,SAAS,cAAc,EAAE,IAAI;EACnC,MAAM,SAAS,OAAO,WAAW,cAAc;EAC/C,MAAM,WAAW,OAAO,IAAI,OAAO;AAEnC,MAAI;AACF,SAAO,SAAiB,UAAU;IAAE;IAAY;IAAiB,CAAC;UAC5D;AAIR,QAAO,SAAiB,mBAAmB;AAC3C,SAAO,EAAE,KAAK,EAAE,IAAI,MAAM,CAAC;GAC3B;AAEF,KAAI,KAAK,GAAG,UAAU,cAAc,OAAO,MAAM;AAC/C,QAAM,UAAU,EAAE,KAAK,gBAAgB;AACvC,SAAO,EAAE,KAAK,EAAE,IAAI,MAAM,CAAC;GAC3B;CAMF,MAAMC,cAA0D,OAC9D,GACA,SACG;EACH,MAAM,QAAQ,EAAE,IAAI;AACpB,MAAI,OAAO;GACT,MAAM,aAAa,EAAE,IAAI,OAAO,gBAAgB,IAAI;GACpD,MAAM,WAAW,WAAW,WAAW,UAAU,GAC7C,WAAW,MAAM,EAAE,GACnB;GAGJ,MAAM,aAAa,EAAE,IAAI,MAAM,QAAQ,IAAI;AAC3C,OAAI,aAAa,SAAS,eAAe,MACvC,QAAO,UAAU,gBAAgB,gBAAgB,IAAI;;AAGzD,SAAO,MAAM;;CAGf,MAAM,2BACJ,IAAI,SAAS,kBAAkB,eAA0C,EAAE,EACzE,SAAS,EAAE,gBAAgB,4BAA4B,EACxD,CAAC;AAEJ,KAAI,IAAI,GAAG,UAAU,gBAAgB,cAAc,MACjD,EAAE,KAAK,eAAe,CACvB;AACD,KAAI,IAAI,GAAG,UAAU,gBAAgB,aAAa,mBAAmB;AACrE,KAAI,IAAI,GAAG,UAAU,WAAW,aAAa,mBAAmB;AAEhE,QAAO;;;;;;;;;;;;;;;;;;ACr5BT,MAAMC,iBAA2C;CAC/C,YAAY;CACZ,iBAAiB;CAClB;AAgBD,IAAa,WAAb,cAA8B,cAA2B;CACvD,AAAQ,SAAmC,EAAE,GAAG,gBAAgB;;CAGhE,AAAQ,iCAA8B,IAAI,KAAK;;CAG/C,AAAQ,8BAAmC,IAAI,KAAK;;CAGpD,AAAQ,qCAAkC,IAAI,KAAK;;CAGnD,AAAQ,oBAAmC;CAE3C,AAAQ,oBAAoB;CAC5B,AAAQ,cAAc;;;;;;CAWtB,MAAM,aAAa,WAAoC;AACrD,QAAM,KAAK,MAAM;EAEjB,MAAM,WAAW,KAAK,YAAY,IAAI,UAAU;AAChD,MAAI,UAAU;AAEZ,OADgB,MAAM,KAAK,mBAAmB,SAAS,CAC1C,QAAO;AACpB,QAAK,YAAY,OAAO,UAAU;AAClC,SAAM,KAAK,SAAS;;AAItB,MAAI,KAAK,eAAe,OAAO,GAAG;GAChC,MAAMC,kBAAgB,KAAK,eAAe,QAAQ,CAAC,MAAM,CAAC;AAC1D,QAAK,eAAe,OAAOA,gBAAc;AACzC,QAAK,YAAY,IAAI,WAAWA,gBAAc;AAC9C,SAAM,KAAK,SAAS;AACpB,UAAOA;;AAIT,MAAI,KAAK,mBAAmB,IAAI,EAC9B,MAAK,oBAAoB;EAI3B,MAAM,gBAAgB,MAAM,KAAK,gBAAgB;AACjD,MAAI,eAAe;AACjB,QAAK,YAAY,IAAI,WAAW,cAAc;AAC9C,SAAM,KAAK,SAAS;AACpB,UAAO;;AAGT,MAAI,KAAK,kBACP,MAAK,oBAAoB;AAG3B,QAAM,IAAI,MAAM,4BAA4B;;;;;;;CAQ9C,MAAM,gBAAgB,WAA2C;AAC/D,QAAM,KAAK,MAAM;EACjB,MAAM,WAAW,KAAK,YAAY,IAAI,UAAU;AAChD,MAAI,SACF,QAAO;AAET,SAAO;;;;;CAMT,MAAM,cAAc,eAAsC;AACxD,QAAM,KAAK,MAAM;AACjB,OAAK,gBAAgB,cAAc;AACnC,QAAM,KAAK,SAAS;;;;;CAMtB,MAAM,WAA+B;AACnC,QAAM,KAAK,MAAM;AACjB,SAAO;GACL,MAAM,KAAK,eAAe;GAC1B,UAAU,KAAK,YAAY;GAC3B,OAAO,KAAK,eAAe,OAAO,KAAK,YAAY;GACnD,QAAQ,KAAK;GACb,cAAc,KAAK;GACpB;;;;;;CAOH,MAAM,UAAU,QAAuC;AACrD,QAAM,KAAK,MAAM;AACjB,OAAK,SAAS;GAAE,GAAG;GAAgB,GAAG;GAAQ;AAC9C,QAAM,KAAK,IAAI,QAAQ,IAAI,UAAU,KAAK,OAAO;;;;;;CAOnD,MAAM,oBAAmC;AACvC,QAAM,KAAK,MAAM;AAEjB,OAAK,MAAM,iBAAiB,CAAC,GAAG,KAAK,eAAe,CAClD,KAAI;AAEF,SADa,KAAK,eAAe,cAAc,CACP,MAAM;AAC9C,QAAK,eAAe,OAAO,cAAc;WAClC,OAAO;AACd,WAAQ,MAAM;IACZ,SAAS;IACT,WAAW;IACX;IACA;IACD,CAAC;;AAIN,QAAM,KAAK,SAAS;;CAOtB,MAAM,QAAuB;AAC3B,QAAM,KAAK,MAAM;AAEjB,OAAK,oBAAoB;AAEzB,MAAI;AACF,SAAM,KAAK,sBAAsB;AACjC,SAAM,KAAK,YAAY;AACvB,SAAM,KAAK,yBAAyB;WAC7B,OAAO;AACd,WAAQ,MAAM;IACZ,SAAS;IACT,WAAW;IACX;IACD,CAAC;;AAGJ,QAAM,KAAK,IAAI,QAAQ,SAAS,KAAK,KAAK,GAAG,KAAK,OAAO,gBAAgB;;CAO3E,MAAc,OAAsB;AAClC,MAAI,KAAK,YAAa;EAEtB,MAAM,aACJ,MAAM,KAAK,IAAI,QAAQ,IAAiB,iBAAiB;AAC3D,MAAI,WAAY,MAAK,iBAAiB,IAAI,IAAI,WAAW;EAEzD,MAAM,oBACJ,MAAM,KAAK,IAAI,QAAQ,IAAyB,cAAc;AAChE,MAAI,kBAAmB,MAAK,cAAc,IAAI,IAAI,kBAAkB;EAEpE,MAAM,eAAe,MAAM,KAAK,IAAI,QAAQ,IAAoB,SAAS;AACzE,MAAI,aAAc,MAAK,SAAS;GAAE,GAAG;GAAgB,GAAG;GAAc;EAEtE,MAAM,YAAY,MAAM,KAAK,IAAI,QAAQ,IAAY,oBAAoB;AACzE,MAAI,cAAc,OAAW,MAAK,oBAAoB;AAEtD,OAAK,cAAc;AACnB,QAAM,KAAK,iBAAiB;;CAG9B,MAAc,UAAyB;AACrC,QAAM,KAAK,IAAI,QAAQ,IAAI,kBAAkB,KAAK,eAAe;AACjE,QAAM,KAAK,IAAI,QAAQ,IAAI,eAAe,KAAK,YAAY;AAC3D,MAAI,KAAK,sBAAsB,KAC7B,OAAM,KAAK,IAAI,QAAQ,IAAI,qBAAqB,KAAK,kBAAkB;MAEvE,OAAM,KAAK,IAAI,QAAQ,OAAO,oBAAoB;;CAItD,MAAc,kBAAiC;AAE7C,MAAI,CADU,MAAM,KAAK,IAAI,QAAQ,UAAU,CAE7C,OAAM,KAAK,IAAI,QAAQ,SAAS,KAAK,KAAK,GAAG,KAAK,OAAO,gBAAgB;;CAQ7E,MAAc,iBAAyC;EACrD,MAAM,gBAAgB,OAAO,YAAY;AACzC,OAAK,mBAAmB,IAAI,cAAc;AAE1C,MAAI;AAEF,SADa,KAAK,eAAe,cAAc,CACP,sBAAsB;AAC9D,WAAQ,KAAK;IACX,SAAS;IACT,WAAW;IACX;IACD,CAAC;AACF,UAAO;WACA,OAAO;AACd,OAAI,KAAK,oBAAoB,MAAM,CACjC,OAAM,KAAK,qBAAqB;OAEhC,SAAQ,MAAM;IACZ,SAAS;IACT,WAAW;IACX;IACA;IACD,CAAC;AAEJ,UAAO;YACC;AACR,QAAK,mBAAmB,OAAO,cAAc;;;CAIjD,MAAc,mBAAmB,eAAyC;AACxE,MAAI,KAAK,mBAAmB,IAAI,cAAc,CAAE,QAAO;AAEvD,MAAI;GAEF,MAAM,QAAQ,MADD,KAAK,eAAe,cAAc,CACa,UAAU;AACtE,UAAO,MAAM,WAAW,aAAa,MAAM,WAAW;WAC/C,OAAO;AACd,WAAQ,KAAK;IACX,SAAS;IACT,WAAW;IACX;IACA;IACD,CAAC;AACF,UAAO;;;CAIX,MAAc,uBAAsC;EAClD,MAAM,WAAW,CAAC,GAAG,KAAK,gBAAgB,GAAG,KAAK,YAAY,QAAQ,CAAC;EAEvE,IAAI,aAAa;AACjB,OAAK,MAAM,QAAQ,SAEjB,KAAI,CADY,MAAM,KAAK,mBAAmB,KAAK,EACrC;AACZ,WAAQ,KAAK;IACX,SAAS;IACT,WAAW;IACX,eAAe;IAChB,CAAC;AACF,OAAI,KAAK,gBAAgB,KAAK,CAAE,cAAa;;AAIjD,MAAI,WAAY,OAAM,KAAK,SAAS;;;;;CAMtC,MAAc,0BAAyC;AACrD,OAAK,MAAM,iBAAiB,KAAK,eAC/B,KAAI;AAEF,GADa,KAAK,eAAe,cAAc,CACb,sBAAsB;WACjD,OAAO;AACd,WAAQ,MAAM;IACZ,SAAS;IACT,WAAW;IACX;IACA;IACD,CAAC;;;;;;CAQR,MAAc,aAA4B;EACxC,IAAI,OAAO,KAAK,OAAO,aAAa,KAAK,eAAe;AAExD,MAAI,OAAO,GAAG;AAIZ,OAHiB,KAAK,mBAAmB,KAGxB,KAAK,KAAK,sBAAsB,MAAM;AACrD,YAAQ,KAAK;KACX,SAAS;KACT,WAAW;KACX,mBAAmB,KAAK;KACzB,CAAC;IACF,MAAM,YAAY,MAAM,KAAK,gBAAgB;AAC7C,QAAI,WAAW;AACb,aAAQ,KAAK;MACX,SAAS;MACT,WAAW;MACZ,CAAC;AACF,UAAK,oBAAoB;AACzB,UAAK,eAAe,IAAI,UAAU;AAClC;AACA,WAAM,KAAK,SAAS;WACf;AACL,WAAM,KAAK,SAAS;AACpB;;;GAIJ,MAAM,UAAU,KAAK,IAAI,MAAM,KAAK,mBAAmB,CAAC;AACxD,OAAI,WAAW,GAAG;AAChB,YAAQ,IAAI;KACV,SAAS;KACT,WAAW;KACX,QAAQ;KACR,WAAW,KAAK,mBAAmB;KACnC,MAAM,KAAK,eAAe;KAC1B,UAAU,KAAK,YAAY;KAC3B,mBAAmB,KAAK,qBAAqB;KAC9C,CAAC;AACF;;AAGF,WAAQ,KAAK;IACX,SAAS;IACT,WAAW;IACX,UAAU;IACV,QAAQ;IACR,UAAU,KAAK,mBAAmB;IACnC,CAAC;AACF,QAAK,IAAI,IAAI,GAAG,IAAI,SAAS,KAAK;AAChC,QAAI,KAAK,mBAAmB;AAC1B,aAAQ,IAAI;MACV,SAAS;MACT,WAAW;MACZ,CAAC;AACF;;IAEF,MAAM,OAAO,MAAM,KAAK,gBAAgB;AACxC,QAAI,KAAM,MAAK,eAAe,IAAI,KAAK;;AAEzC,SAAM,KAAK,SAAS;aACX,OAAO,GAAG;GACnB,MAAM,SAAS,CAAC;AAChB,WAAQ,KAAK;IACX,SAAS;IACT,WAAW;IACX,UAAU;IACX,CAAC;GAEF,MAAM,SAAS,CAAC,GAAG,KAAK,eAAe,CAAC,MAAM,GAAG,OAAO;GACxD,MAAMC,UAAoB,EAAE;AAE5B,QAAK,MAAM,QAAQ,OACjB,KAAI;AAEF,UADa,KAAK,eAAe,KAAK,CACE,MAAM;AAC9C,YAAQ,KAAK,KAAK;YACX,OAAO;AACd,YAAQ,MAAM;KACZ,SAAS;KACT,WAAW;KACX,eAAe;KACf;KACD,CAAC;;AAIN,QAAK,MAAM,QAAQ,QACjB,MAAK,eAAe,OAAO,KAAK;AAElC,SAAM,KAAK,SAAS;;;CAQxB,AAAQ,gBAAgB,eAAgC;EACtD,IAAI,UAAU;AAEd,MAAI,KAAK,eAAe,OAAO,cAAc,CAAE,WAAU;AAEzD,OAAK,MAAM,CAAC,WAAW,SAAS,KAAK,YACnC,KAAI,SAAS,eAAe;AAC1B,QAAK,YAAY,OAAO,UAAU;AAClC,aAAU;AACV;;AAIJ,SAAO;;CAGT,AAAQ,oBAA4B;AAClC,MAAI,KAAK,sBAAsB,KAAM,QAAO;AAC5C,SAAO,KAAK,IACV,GACA,KAAK,qBACF,KAAK,eAAe,OAAO,KAAK,YAAY,MAChD;;CAGH,AAAQ,oBAAoB,OAAyB;AAEnD,UADgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EACvD,SACb,yDACD;;CAGH,MAAc,sBAAqC;EACjD,MAAM,eAAe,KAAK,eAAe,OAAO,KAAK,YAAY;AACjE,OAAK,oBAAoB;AACzB,OAAK,oBAAoB;AACzB,UAAQ,KAAK;GACX,SAAS;GACT,WAAW;GACX,iBAAiB;GACjB,MAAM,KAAK,eAAe;GAC1B,UAAU,KAAK,YAAY;GAC5B,CAAC;AACF,QAAM,KAAK,IAAI,QAAQ,IAAI,qBAAqB,KAAK,kBAAkB;;CAGzE,AAAQ,qBAA4B;EAClC,MAAM,QAAQ,KAAK,eAAe,OAAO,KAAK,YAAY;AAC1D,QAAM,IAAI,MACR,mDAAmD,MAAM,GAAG,KAAK,kBAAkB,0EAEpF;;CAGH,AAAQ,eAAe,eAA0C;EAC/D,MAAM,KAAK,KAAK,IAAI,QAAQ,WAAW,cAAc;AACrD,SAAO,KAAK,IAAI,QAAQ,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC5enC,SAAS,cACP,OACA,SACM;CACN,MAAM,EAAE,gBAAgB,oBAAoB;CAC5C,MAAMC,UAAoB,EAAE;AAE5B,KAAI,CAACC,MAAI,gBAAiB,SAAQ,KAAK,eAAe;AACtD,KAAI,CAACA,MAAI,iBAAkB,SAAQ,KAAK,gBAAgB;AAExD,KAAI,QAAQ,SAAS,EACnB,MAAK,MAAM,WAAW,QACpB,SAAQ,MAAM;EACZ,SAAS,6BAA6B,QAAQ;EAC9C,WAAW;EACX;EACA,MAAM,kEAAkE,QAAQ;EACjF,CAAC;AAIN,KAAI,CAACA,MAAI,gBACP,SAAQ,KAAK;EACX,SAAS;EACT,WAAW;EACX,MAAM;EACP,CAAC;;;;;;;;;;;;;;AAgBN,SAAgB,OACd,QACA,QAC4B;CAC5B,MAAM,iBAAiB,QAAQ,UAAU,WAAW;CACpD,MAAM,kBAAkB,QAAQ,UAAU,YAAY;CACtD,MAAM,YAAY,QAAQ,kBAAkB;CAC5C,MAAM,aAAa,QAAQ,eAAe;AAG1C,eAAcC,KAA6C;EACzD;EACA;EACD,CAAC;CASF,MAAM,MAAM,gBANqB;EAC/B;EACA;EACA;EACA;EACD,CACuC;CAGxC,MAAMC,cAAuC,EAAE;AAC/C,MAAK,MAAM,OAAO,OAAO,KAAK,OAAO,CACnC,KAAI,QAAQ,WAAW,QAAQ,YAC7B,aAAY,OAAO,OAAO;AAI9B,QAAO;EACL,GAAG;EAEH,MAAM,MACJ,SACA,OACA,KACmB;GAEnB,MAAM,MAAM,IAAI,IAAI,QAAQ,IAAI;AAChC,OACE,IAAI,SAAS,WAAW,YAAY,IAAI,IACxC,IAAI,aAAa,aACjB,IAAI,aAAa,WAEjB,QAAO,IAAI,MAAM,SAASF,OAAK,IAAI;AAIrC,OAAI,OAAO,MACT,QAAO,OAAO,MAAM,SAASA,OAAK,IAAI;AAGxC,UAAO,IAAI,SAAS,aAAa,EAAE,QAAQ,KAAK,CAAC;;EAGnD,MAAM,UACJ,YACA,OACA,KACe;AAEf,SAAM,UAAUA,OAAK,gBAAgB;AAGrC,OAAI,OAAO,UACT,OAAM,OAAO,UAAU,YAAYA,OAAK,IAAI;;EAGjD"}
|
|
@@ -225,4 +225,4 @@ interface DesktopCoordinateErrorContext {
|
|
|
225
225
|
}
|
|
226
226
|
//#endregion
|
|
227
227
|
export { DesktopCoordinateErrorContext as a, OpencodeStartupContext as c, ErrorResponse as d, OperationType as f, BackupRestoreContext as i, ProcessExitedBeforeReadyContext as l, BackupExpiredContext as n, DesktopErrorContext as o, ErrorCode as p, BackupNotFoundContext as r, InvalidBackupConfigContext as s, BackupCreateContext as t, ProcessReadyTimeoutContext as u };
|
|
228
|
-
//# sourceMappingURL=contexts-
|
|
228
|
+
//# sourceMappingURL=contexts-icMN26lE.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contexts-DqnVW04M.d.ts","names":["ErrorCode","ErrorCode","Operation","OperationType","ErrorResponse","TContext","Record","ServiceError","ServiceResult","T","OperationType","FileNotFoundContext","FileExistsContext","FileTooLargeContext","FileSystemContext","CommandNotFoundContext","CommandErrorContext","ProcessNotFoundContext","ProcessErrorContext","SessionAlreadyExistsContext","SessionDestroyedContext","ProcessReadyTimeoutContext","ProcessExitedBeforeReadyContext","PortAlreadyExposedContext","PortNotExposedContext","InvalidPortContext","PortErrorContext","GitRepositoryNotFoundContext","GitAuthFailedContext","GitBranchNotFoundContext","GitErrorContext","InterpreterNotReadyContext","ContextNotFoundContext","CodeExecutionContext","ValidationFailedContext","Array","BucketMountContext","MissingCredentialsContext","InvalidMountConfigContext","BackupCreateContext","BackupRestoreContext","BackupNotFoundContext","BackupExpiredContext","InvalidBackupConfigContext","OpencodeStartupContext","InternalErrorContext","DesktopErrorContext","DesktopCoordinateErrorContext"],"sources":["../../shared/dist/errors/codes.d.ts","../../shared/dist/errors/types.d.ts","../../shared/dist/errors/contexts.d.ts"],"sourcesContent":["/**\n * Centralized error code registry\n * Each code maps to a specific error type with consistent semantics\n */\nexport declare const ErrorCode: {\n readonly FILE_NOT_FOUND: \"FILE_NOT_FOUND\";\n readonly PERMISSION_DENIED: \"PERMISSION_DENIED\";\n readonly FILE_EXISTS: \"FILE_EXISTS\";\n readonly IS_DIRECTORY: \"IS_DIRECTORY\";\n readonly NOT_DIRECTORY: \"NOT_DIRECTORY\";\n readonly FILE_TOO_LARGE: \"FILE_TOO_LARGE\";\n readonly NO_SPACE: \"NO_SPACE\";\n readonly TOO_MANY_FILES: \"TOO_MANY_FILES\";\n readonly RESOURCE_BUSY: \"RESOURCE_BUSY\";\n readonly READ_ONLY: \"READ_ONLY\";\n readonly NAME_TOO_LONG: \"NAME_TOO_LONG\";\n readonly TOO_MANY_LINKS: \"TOO_MANY_LINKS\";\n readonly FILESYSTEM_ERROR: \"FILESYSTEM_ERROR\";\n readonly COMMAND_NOT_FOUND: \"COMMAND_NOT_FOUND\";\n readonly COMMAND_PERMISSION_DENIED: \"COMMAND_PERMISSION_DENIED\";\n readonly INVALID_COMMAND: \"INVALID_COMMAND\";\n readonly COMMAND_EXECUTION_ERROR: \"COMMAND_EXECUTION_ERROR\";\n readonly STREAM_START_ERROR: \"STREAM_START_ERROR\";\n readonly PROCESS_NOT_FOUND: \"PROCESS_NOT_FOUND\";\n readonly PROCESS_PERMISSION_DENIED: \"PROCESS_PERMISSION_DENIED\";\n readonly PROCESS_ERROR: \"PROCESS_ERROR\";\n readonly SESSION_ALREADY_EXISTS: \"SESSION_ALREADY_EXISTS\";\n readonly SESSION_DESTROYED: \"SESSION_DESTROYED\";\n readonly PORT_ALREADY_EXPOSED: \"PORT_ALREADY_EXPOSED\";\n readonly PORT_IN_USE: \"PORT_IN_USE\";\n readonly PORT_NOT_EXPOSED: \"PORT_NOT_EXPOSED\";\n readonly INVALID_PORT_NUMBER: \"INVALID_PORT_NUMBER\";\n readonly INVALID_PORT: \"INVALID_PORT\";\n readonly SERVICE_NOT_RESPONDING: \"SERVICE_NOT_RESPONDING\";\n readonly PORT_OPERATION_ERROR: \"PORT_OPERATION_ERROR\";\n readonly CUSTOM_DOMAIN_REQUIRED: \"CUSTOM_DOMAIN_REQUIRED\";\n readonly GIT_REPOSITORY_NOT_FOUND: \"GIT_REPOSITORY_NOT_FOUND\";\n readonly GIT_BRANCH_NOT_FOUND: \"GIT_BRANCH_NOT_FOUND\";\n readonly GIT_AUTH_FAILED: \"GIT_AUTH_FAILED\";\n readonly GIT_NETWORK_ERROR: \"GIT_NETWORK_ERROR\";\n readonly INVALID_GIT_URL: \"INVALID_GIT_URL\";\n readonly GIT_CLONE_FAILED: \"GIT_CLONE_FAILED\";\n readonly GIT_CHECKOUT_FAILED: \"GIT_CHECKOUT_FAILED\";\n readonly GIT_OPERATION_FAILED: \"GIT_OPERATION_FAILED\";\n readonly BUCKET_MOUNT_ERROR: \"BUCKET_MOUNT_ERROR\";\n readonly BUCKET_UNMOUNT_ERROR: \"BUCKET_UNMOUNT_ERROR\";\n readonly S3FS_MOUNT_ERROR: \"S3FS_MOUNT_ERROR\";\n readonly MISSING_CREDENTIALS: \"MISSING_CREDENTIALS\";\n readonly INVALID_MOUNT_CONFIG: \"INVALID_MOUNT_CONFIG\";\n readonly BACKUP_CREATE_FAILED: \"BACKUP_CREATE_FAILED\";\n readonly BACKUP_RESTORE_FAILED: \"BACKUP_RESTORE_FAILED\";\n readonly BACKUP_NOT_FOUND: \"BACKUP_NOT_FOUND\";\n readonly BACKUP_EXPIRED: \"BACKUP_EXPIRED\";\n readonly INVALID_BACKUP_CONFIG: \"INVALID_BACKUP_CONFIG\";\n readonly INTERPRETER_NOT_READY: \"INTERPRETER_NOT_READY\";\n readonly CONTEXT_NOT_FOUND: \"CONTEXT_NOT_FOUND\";\n readonly CODE_EXECUTION_ERROR: \"CODE_EXECUTION_ERROR\";\n readonly PYTHON_NOT_AVAILABLE: \"PYTHON_NOT_AVAILABLE\";\n readonly JAVASCRIPT_NOT_AVAILABLE: \"JAVASCRIPT_NOT_AVAILABLE\";\n readonly OPENCODE_STARTUP_FAILED: \"OPENCODE_STARTUP_FAILED\";\n readonly PROCESS_READY_TIMEOUT: \"PROCESS_READY_TIMEOUT\";\n readonly PROCESS_EXITED_BEFORE_READY: \"PROCESS_EXITED_BEFORE_READY\";\n readonly DESKTOP_NOT_STARTED: \"DESKTOP_NOT_STARTED\";\n readonly DESKTOP_START_FAILED: \"DESKTOP_START_FAILED\";\n readonly DESKTOP_UNAVAILABLE: \"DESKTOP_UNAVAILABLE\";\n readonly DESKTOP_PROCESS_CRASHED: \"DESKTOP_PROCESS_CRASHED\";\n readonly DESKTOP_INVALID_OPTIONS: \"DESKTOP_INVALID_OPTIONS\";\n readonly DESKTOP_INVALID_COORDINATES: \"DESKTOP_INVALID_COORDINATES\";\n readonly WATCH_NOT_FOUND: \"WATCH_NOT_FOUND\";\n readonly WATCH_START_ERROR: \"WATCH_START_ERROR\";\n readonly WATCH_STOP_ERROR: \"WATCH_STOP_ERROR\";\n readonly VALIDATION_FAILED: \"VALIDATION_FAILED\";\n readonly INVALID_JSON_RESPONSE: \"INVALID_JSON_RESPONSE\";\n readonly UNKNOWN_ERROR: \"UNKNOWN_ERROR\";\n readonly INTERNAL_ERROR: \"INTERNAL_ERROR\";\n};\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\n//# sourceMappingURL=codes.d.ts.map","import type { ErrorCode } from './codes';\n/**\n * Standard operation types\n */\nexport declare const Operation: {\n readonly FILE_READ: \"file.read\";\n readonly FILE_WRITE: \"file.write\";\n readonly FILE_DELETE: \"file.delete\";\n readonly FILE_MOVE: \"file.move\";\n readonly FILE_RENAME: \"file.rename\";\n readonly FILE_STAT: \"file.stat\";\n readonly DIRECTORY_CREATE: \"directory.create\";\n readonly DIRECTORY_LIST: \"directory.list\";\n readonly COMMAND_EXECUTE: \"command.execute\";\n readonly COMMAND_STREAM: \"command.stream\";\n readonly PROCESS_START: \"process.start\";\n readonly PROCESS_KILL: \"process.kill\";\n readonly PROCESS_LIST: \"process.list\";\n readonly PROCESS_GET: \"process.get\";\n readonly PROCESS_LOGS: \"process.logs\";\n readonly PORT_EXPOSE: \"port.expose\";\n readonly PORT_UNEXPOSE: \"port.unexpose\";\n readonly PORT_LIST: \"port.list\";\n readonly PORT_PROXY: \"port.proxy\";\n readonly GIT_CLONE: \"git.clone\";\n readonly GIT_CHECKOUT: \"git.checkout\";\n readonly GIT_OPERATION: \"git.operation\";\n readonly BACKUP_CREATE: \"backup.create\";\n readonly BACKUP_RESTORE: \"backup.restore\";\n readonly BACKUP_UNMOUNT: \"backup.unmount\";\n readonly DESKTOP_START: \"desktop.start\";\n readonly DESKTOP_STOP: \"desktop.stop\";\n readonly DESKTOP_SCREENSHOT: \"desktop.screenshot\";\n readonly DESKTOP_MOUSE: \"desktop.mouse\";\n readonly DESKTOP_KEYBOARD: \"desktop.keyboard\";\n readonly DESKTOP_STATUS: \"desktop.status\";\n readonly CODE_EXECUTE: \"code.execute\";\n readonly CODE_CONTEXT_CREATE: \"code.context.create\";\n readonly CODE_CONTEXT_DELETE: \"code.context.delete\";\n};\nexport type OperationType = (typeof Operation)[keyof typeof Operation];\n/**\n * Standard error response format with generic context type\n * TContext allows type-safe access to error-specific context\n */\nexport interface ErrorResponse<TContext = Record<string, unknown>> {\n /**\n * Error type code (machine-readable)\n */\n code: ErrorCode;\n /**\n * Human-readable error message\n */\n message: string;\n /**\n * Operation that was attempted (useful for debugging and logging)\n */\n operation?: OperationType;\n /**\n * Structured error context with relevant details\n * Type varies based on error code\n */\n context: TContext;\n /**\n * HTTP status code (for client SDK)\n */\n httpStatus: number;\n /**\n * Timestamp when error occurred\n */\n timestamp: string;\n /**\n * Actionable suggestion for fixing the error\n */\n suggestion?: string;\n /**\n * Link to documentation\n */\n documentation?: string;\n}\n/**\n * Container ServiceError (lightweight, enriched by handlers)\n */\nexport interface ServiceError {\n message: string;\n code: ErrorCode;\n details?: Record<string, unknown>;\n}\n/**\n * ServiceResult type for container services\n */\nexport type ServiceResult<T> = {\n success: true;\n data: T;\n} | {\n success: false;\n error: ServiceError;\n};\n//# sourceMappingURL=types.d.ts.map","import type { OperationType } from './types';\n/**\n * File system error contexts\n */\nexport interface FileNotFoundContext {\n path: string;\n operation: OperationType;\n}\nexport interface FileExistsContext {\n path: string;\n operation: OperationType;\n}\nexport interface FileTooLargeContext {\n path: string;\n operation: OperationType;\n maxSize: number;\n actualSize: number;\n}\nexport interface FileSystemContext {\n path: string;\n operation: OperationType;\n stderr?: string;\n exitCode?: number;\n}\n/**\n * Command error contexts\n */\nexport interface CommandNotFoundContext {\n command: string;\n}\nexport interface CommandErrorContext {\n command: string;\n exitCode?: number;\n stdout?: string;\n stderr?: string;\n}\n/**\n * Process error contexts\n */\nexport interface ProcessNotFoundContext {\n processId: string;\n}\nexport interface ProcessErrorContext {\n processId: string;\n pid?: number;\n exitCode?: number;\n stderr?: string;\n}\nexport interface SessionAlreadyExistsContext {\n sessionId: string;\n}\nexport interface SessionDestroyedContext {\n sessionId: string;\n}\n/**\n * Process readiness error contexts\n */\nexport interface ProcessReadyTimeoutContext {\n processId: string;\n command: string;\n condition: string;\n timeout: number;\n}\nexport interface ProcessExitedBeforeReadyContext {\n processId: string;\n command: string;\n condition: string;\n exitCode: number;\n}\n/**\n * Port error contexts\n */\nexport interface PortAlreadyExposedContext {\n port: number;\n portName?: string;\n}\nexport interface PortNotExposedContext {\n port: number;\n}\nexport interface InvalidPortContext {\n port: number;\n reason: string;\n}\nexport interface PortErrorContext {\n port: number;\n portName?: string;\n stderr?: string;\n}\n/**\n * Git error contexts\n */\nexport interface GitRepositoryNotFoundContext {\n repository: string;\n}\nexport interface GitAuthFailedContext {\n repository: string;\n}\nexport interface GitBranchNotFoundContext {\n branch: string;\n repository?: string;\n}\nexport interface GitErrorContext {\n repository?: string;\n branch?: string;\n targetDir?: string;\n stderr?: string;\n exitCode?: number;\n}\n/**\n * Code interpreter error contexts\n */\nexport interface InterpreterNotReadyContext {\n retryAfter?: number;\n progress?: number;\n}\nexport interface ContextNotFoundContext {\n contextId: string;\n}\nexport interface CodeExecutionContext {\n contextId?: string;\n ename?: string;\n evalue?: string;\n traceback?: string[];\n}\n/**\n * Validation error contexts\n */\nexport interface ValidationFailedContext {\n validationErrors: Array<{\n field: string;\n message: string;\n code?: string;\n }>;\n}\n/**\n * Bucket mounting error contexts\n */\nexport interface BucketMountContext {\n bucket: string;\n mountPath: string;\n endpoint: string;\n stderr?: string;\n exitCode?: number;\n}\nexport interface MissingCredentialsContext {\n bucket: string;\n endpoint: string;\n}\nexport interface InvalidMountConfigContext {\n bucket?: string;\n mountPath?: string;\n endpoint?: string;\n reason?: string;\n}\n/**\n * Backup error contexts\n */\nexport interface BackupCreateContext {\n dir: string;\n backupId?: string;\n stderr?: string;\n exitCode?: number;\n}\nexport interface BackupRestoreContext {\n dir: string;\n backupId: string;\n stderr?: string;\n exitCode?: number;\n}\nexport interface BackupNotFoundContext {\n backupId: string;\n}\nexport interface BackupExpiredContext {\n backupId: string;\n expiredAt?: string;\n}\nexport interface InvalidBackupConfigContext {\n reason: string;\n}\n/**\n * OpenCode error contexts\n */\nexport interface OpencodeStartupContext {\n port: number;\n stderr?: string;\n command?: string;\n}\n/**\n * Generic error contexts\n */\nexport interface InternalErrorContext {\n originalError?: string;\n stack?: string;\n [key: string]: unknown;\n}\n/**\n * Desktop error contexts\n */\nexport interface DesktopErrorContext {\n process?: string;\n stderr?: string;\n crashedProcess?: string;\n reason?: string;\n}\nexport interface DesktopCoordinateErrorContext {\n x: number;\n y: number;\n displayWidth: number;\n displayHeight: number;\n}\n//# sourceMappingURL=contexts.d.ts.map"],"mappings":";;AAIA;AAwEA;;cAxEqBA;;ECAAE,SAAAA,iBAmCpB,EAAA,mBAAA;EACWC,SAAAA,WAAa,EAAA,aAAWD;EAKnBE,SAAAA,YAAa,EAAAC,cAAA;EAAYC,SAAAA,aAAAA,EAAAA,eAAAA;EAIhCL,SAAAA,cAAAA,EAAAA,gBAAAA;EAQME,SAAAA,QAAAA,EAAAA,UAAAA;EAKHE,SAAAA,cAAAA,EAAAA,gBAAAA;EAAQ,SAAA,aAAA,EAAA,eAAA;;;;ECLJgB,SAAAA,gBAAAA,EAAAA,kBAA0B;EAM1BC,SAAAA,iBAAAA,EAAAA,mBAA+B;EA8F/BiB,SAAAA,yBAAmB,EAAA,2BAAA;EAMnBC,SAAAA,eAAoB,EAAA,iBAAA;EAMpBC,SAAAA,uBAAqB,EAAA,yBAAA;EAGrBC,SAAAA,kBAAoB,EAAA,oBAAA;EAIpBC,SAAAA,iBAAAA,EAAAA,mBAA0B;EAM1BC,SAAAA,yBAAsB,EAAA,2BAAA;EAgBtBE,SAAAA,aAAmB,EAAA,eAAA;EAMnBC,SAAAA,sBAAAA,EAA6B,wBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KFhIlC/C,SAAAA,WAAoBA,wBAAwBA;;;AAxExD;AAwEA;;cCxEqBE;;EAAAA,SAAAA,UAmCpB,EAAA,YAAA;EACWC,SAAAA,WAAa,EAAA,aAAWD;EAKnBE,SAAAA,SAAa,EAAA,WAAAC;EAAYC,SAAAA,WAAAA,EAAAA,aAAAA;EAIhCL,SAAAA,SAAAA,EAAAA,WAAAA;EAQME,SAAAA,gBAAAA,EAAAA,kBAAAA;EAKHE,SAAAA,cAAAA,EAAAA,gBAAAA;EAAQ,SAAA,eAAA,EAAA,iBAAA;;;;ECLJgB,SAAAA,YAAAA,EAAAA,cAA0B;EAM1BC,SAAAA,WAAAA,EAAAA,aAA+B;EA8F/BiB,SAAAA,YAAAA,EAAmB,cAAA;EAMnBC,SAAAA,WAAAA,EAAAA,aAAoB;EAMpBC,SAAAA,aAAAA,EAAqB,eAAA;EAGrBC,SAAAA,SAAAA,EAAAA,WAAoB;EAIpBC,SAAAA,UAAAA,EAAAA,YAA0B;EAM1BC,SAAAA,SAAAA,EAAAA,WAAsB;EAgBtBE,SAAAA,YAAAA,EAAmB,cAAA;EAMnBC,SAAAA,aAAAA,EAAAA,eAA6B;;;;;;;;;;;;;;KDpKlC5C,aAAAA,WAAwBD,wBAAwBA;;;;;UAK3CE,yBAAyBE;;;;QAIhCL;;;;;;;;cAQME;;;;;WAKHE;;;;;;;;;;;;;;;;;;;;;;;;UCLIgB,0BAAAA;;;;;;UAMAC,+BAAAA;;;;;;;;;UA8FAiB,mBAAAA;;;;;;UAMAC,oBAAAA;;;;;;UAMAC,qBAAAA;;;UAGAC,oBAAAA;;;;UAIAC,0BAAAA;;;;;;UAMAC,sBAAAA;;;;;;;;UAgBAE,mBAAAA;;;;;;UAMAC,6BAAAA"}
|
|
1
|
+
{"version":3,"file":"contexts-icMN26lE.d.ts","names":["ErrorCode","ErrorCode","Operation","OperationType","ErrorResponse","TContext","Record","ServiceError","ServiceResult","T","OperationType","FileNotFoundContext","FileExistsContext","FileTooLargeContext","FileSystemContext","CommandNotFoundContext","CommandErrorContext","ProcessNotFoundContext","ProcessErrorContext","SessionAlreadyExistsContext","SessionDestroyedContext","ProcessReadyTimeoutContext","ProcessExitedBeforeReadyContext","PortAlreadyExposedContext","PortNotExposedContext","InvalidPortContext","PortErrorContext","GitRepositoryNotFoundContext","GitAuthFailedContext","GitBranchNotFoundContext","GitErrorContext","InterpreterNotReadyContext","ContextNotFoundContext","CodeExecutionContext","ValidationFailedContext","Array","BucketMountContext","MissingCredentialsContext","InvalidMountConfigContext","BackupCreateContext","BackupRestoreContext","BackupNotFoundContext","BackupExpiredContext","InvalidBackupConfigContext","OpencodeStartupContext","InternalErrorContext","DesktopErrorContext","DesktopCoordinateErrorContext"],"sources":["../../shared/dist/errors/codes.d.ts","../../shared/dist/errors/types.d.ts","../../shared/dist/errors/contexts.d.ts"],"sourcesContent":["/**\n * Centralized error code registry\n * Each code maps to a specific error type with consistent semantics\n */\nexport declare const ErrorCode: {\n readonly FILE_NOT_FOUND: \"FILE_NOT_FOUND\";\n readonly PERMISSION_DENIED: \"PERMISSION_DENIED\";\n readonly FILE_EXISTS: \"FILE_EXISTS\";\n readonly IS_DIRECTORY: \"IS_DIRECTORY\";\n readonly NOT_DIRECTORY: \"NOT_DIRECTORY\";\n readonly FILE_TOO_LARGE: \"FILE_TOO_LARGE\";\n readonly NO_SPACE: \"NO_SPACE\";\n readonly TOO_MANY_FILES: \"TOO_MANY_FILES\";\n readonly RESOURCE_BUSY: \"RESOURCE_BUSY\";\n readonly READ_ONLY: \"READ_ONLY\";\n readonly NAME_TOO_LONG: \"NAME_TOO_LONG\";\n readonly TOO_MANY_LINKS: \"TOO_MANY_LINKS\";\n readonly FILESYSTEM_ERROR: \"FILESYSTEM_ERROR\";\n readonly COMMAND_NOT_FOUND: \"COMMAND_NOT_FOUND\";\n readonly COMMAND_PERMISSION_DENIED: \"COMMAND_PERMISSION_DENIED\";\n readonly INVALID_COMMAND: \"INVALID_COMMAND\";\n readonly COMMAND_EXECUTION_ERROR: \"COMMAND_EXECUTION_ERROR\";\n readonly STREAM_START_ERROR: \"STREAM_START_ERROR\";\n readonly PROCESS_NOT_FOUND: \"PROCESS_NOT_FOUND\";\n readonly PROCESS_PERMISSION_DENIED: \"PROCESS_PERMISSION_DENIED\";\n readonly PROCESS_ERROR: \"PROCESS_ERROR\";\n readonly SESSION_ALREADY_EXISTS: \"SESSION_ALREADY_EXISTS\";\n readonly SESSION_DESTROYED: \"SESSION_DESTROYED\";\n readonly PORT_ALREADY_EXPOSED: \"PORT_ALREADY_EXPOSED\";\n readonly PORT_IN_USE: \"PORT_IN_USE\";\n readonly PORT_NOT_EXPOSED: \"PORT_NOT_EXPOSED\";\n readonly INVALID_PORT_NUMBER: \"INVALID_PORT_NUMBER\";\n readonly INVALID_PORT: \"INVALID_PORT\";\n readonly SERVICE_NOT_RESPONDING: \"SERVICE_NOT_RESPONDING\";\n readonly PORT_OPERATION_ERROR: \"PORT_OPERATION_ERROR\";\n readonly CUSTOM_DOMAIN_REQUIRED: \"CUSTOM_DOMAIN_REQUIRED\";\n readonly GIT_REPOSITORY_NOT_FOUND: \"GIT_REPOSITORY_NOT_FOUND\";\n readonly GIT_BRANCH_NOT_FOUND: \"GIT_BRANCH_NOT_FOUND\";\n readonly GIT_AUTH_FAILED: \"GIT_AUTH_FAILED\";\n readonly GIT_NETWORK_ERROR: \"GIT_NETWORK_ERROR\";\n readonly INVALID_GIT_URL: \"INVALID_GIT_URL\";\n readonly GIT_CLONE_FAILED: \"GIT_CLONE_FAILED\";\n readonly GIT_CHECKOUT_FAILED: \"GIT_CHECKOUT_FAILED\";\n readonly GIT_OPERATION_FAILED: \"GIT_OPERATION_FAILED\";\n readonly BUCKET_MOUNT_ERROR: \"BUCKET_MOUNT_ERROR\";\n readonly BUCKET_UNMOUNT_ERROR: \"BUCKET_UNMOUNT_ERROR\";\n readonly S3FS_MOUNT_ERROR: \"S3FS_MOUNT_ERROR\";\n readonly MISSING_CREDENTIALS: \"MISSING_CREDENTIALS\";\n readonly INVALID_MOUNT_CONFIG: \"INVALID_MOUNT_CONFIG\";\n readonly BACKUP_CREATE_FAILED: \"BACKUP_CREATE_FAILED\";\n readonly BACKUP_RESTORE_FAILED: \"BACKUP_RESTORE_FAILED\";\n readonly BACKUP_NOT_FOUND: \"BACKUP_NOT_FOUND\";\n readonly BACKUP_EXPIRED: \"BACKUP_EXPIRED\";\n readonly INVALID_BACKUP_CONFIG: \"INVALID_BACKUP_CONFIG\";\n readonly INTERPRETER_NOT_READY: \"INTERPRETER_NOT_READY\";\n readonly CONTEXT_NOT_FOUND: \"CONTEXT_NOT_FOUND\";\n readonly CODE_EXECUTION_ERROR: \"CODE_EXECUTION_ERROR\";\n readonly PYTHON_NOT_AVAILABLE: \"PYTHON_NOT_AVAILABLE\";\n readonly JAVASCRIPT_NOT_AVAILABLE: \"JAVASCRIPT_NOT_AVAILABLE\";\n readonly OPENCODE_STARTUP_FAILED: \"OPENCODE_STARTUP_FAILED\";\n readonly PROCESS_READY_TIMEOUT: \"PROCESS_READY_TIMEOUT\";\n readonly PROCESS_EXITED_BEFORE_READY: \"PROCESS_EXITED_BEFORE_READY\";\n readonly DESKTOP_NOT_STARTED: \"DESKTOP_NOT_STARTED\";\n readonly DESKTOP_START_FAILED: \"DESKTOP_START_FAILED\";\n readonly DESKTOP_UNAVAILABLE: \"DESKTOP_UNAVAILABLE\";\n readonly DESKTOP_PROCESS_CRASHED: \"DESKTOP_PROCESS_CRASHED\";\n readonly DESKTOP_INVALID_OPTIONS: \"DESKTOP_INVALID_OPTIONS\";\n readonly DESKTOP_INVALID_COORDINATES: \"DESKTOP_INVALID_COORDINATES\";\n readonly WATCH_NOT_FOUND: \"WATCH_NOT_FOUND\";\n readonly WATCH_START_ERROR: \"WATCH_START_ERROR\";\n readonly WATCH_STOP_ERROR: \"WATCH_STOP_ERROR\";\n readonly VALIDATION_FAILED: \"VALIDATION_FAILED\";\n readonly INVALID_JSON_RESPONSE: \"INVALID_JSON_RESPONSE\";\n readonly UNKNOWN_ERROR: \"UNKNOWN_ERROR\";\n readonly INTERNAL_ERROR: \"INTERNAL_ERROR\";\n};\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\n//# sourceMappingURL=codes.d.ts.map","import type { ErrorCode } from './codes';\n/**\n * Standard operation types\n */\nexport declare const Operation: {\n readonly FILE_READ: \"file.read\";\n readonly FILE_WRITE: \"file.write\";\n readonly FILE_DELETE: \"file.delete\";\n readonly FILE_MOVE: \"file.move\";\n readonly FILE_RENAME: \"file.rename\";\n readonly FILE_STAT: \"file.stat\";\n readonly DIRECTORY_CREATE: \"directory.create\";\n readonly DIRECTORY_LIST: \"directory.list\";\n readonly COMMAND_EXECUTE: \"command.execute\";\n readonly COMMAND_STREAM: \"command.stream\";\n readonly PROCESS_START: \"process.start\";\n readonly PROCESS_KILL: \"process.kill\";\n readonly PROCESS_LIST: \"process.list\";\n readonly PROCESS_GET: \"process.get\";\n readonly PROCESS_LOGS: \"process.logs\";\n readonly PORT_EXPOSE: \"port.expose\";\n readonly PORT_UNEXPOSE: \"port.unexpose\";\n readonly PORT_LIST: \"port.list\";\n readonly PORT_PROXY: \"port.proxy\";\n readonly GIT_CLONE: \"git.clone\";\n readonly GIT_CHECKOUT: \"git.checkout\";\n readonly GIT_OPERATION: \"git.operation\";\n readonly BACKUP_CREATE: \"backup.create\";\n readonly BACKUP_RESTORE: \"backup.restore\";\n readonly BACKUP_UNMOUNT: \"backup.unmount\";\n readonly DESKTOP_START: \"desktop.start\";\n readonly DESKTOP_STOP: \"desktop.stop\";\n readonly DESKTOP_SCREENSHOT: \"desktop.screenshot\";\n readonly DESKTOP_MOUSE: \"desktop.mouse\";\n readonly DESKTOP_KEYBOARD: \"desktop.keyboard\";\n readonly DESKTOP_STATUS: \"desktop.status\";\n readonly CODE_EXECUTE: \"code.execute\";\n readonly CODE_CONTEXT_CREATE: \"code.context.create\";\n readonly CODE_CONTEXT_DELETE: \"code.context.delete\";\n};\nexport type OperationType = (typeof Operation)[keyof typeof Operation];\n/**\n * Standard error response format with generic context type\n * TContext allows type-safe access to error-specific context\n */\nexport interface ErrorResponse<TContext = Record<string, unknown>> {\n /**\n * Error type code (machine-readable)\n */\n code: ErrorCode;\n /**\n * Human-readable error message\n */\n message: string;\n /**\n * Operation that was attempted (useful for debugging and logging)\n */\n operation?: OperationType;\n /**\n * Structured error context with relevant details\n * Type varies based on error code\n */\n context: TContext;\n /**\n * HTTP status code (for client SDK)\n */\n httpStatus: number;\n /**\n * Timestamp when error occurred\n */\n timestamp: string;\n /**\n * Actionable suggestion for fixing the error\n */\n suggestion?: string;\n /**\n * Link to documentation\n */\n documentation?: string;\n}\n/**\n * Container ServiceError (lightweight, enriched by handlers)\n */\nexport interface ServiceError {\n message: string;\n code: ErrorCode;\n details?: Record<string, unknown>;\n}\n/**\n * ServiceResult type for container services\n */\nexport type ServiceResult<T> = {\n success: true;\n data: T;\n} | {\n success: false;\n error: ServiceError;\n};\n//# sourceMappingURL=types.d.ts.map","import type { OperationType } from './types';\n/**\n * File system error contexts\n */\nexport interface FileNotFoundContext {\n path: string;\n operation: OperationType;\n}\nexport interface FileExistsContext {\n path: string;\n operation: OperationType;\n}\nexport interface FileTooLargeContext {\n path: string;\n operation: OperationType;\n maxSize: number;\n actualSize: number;\n}\nexport interface FileSystemContext {\n path: string;\n operation: OperationType;\n stderr?: string;\n exitCode?: number;\n}\n/**\n * Command error contexts\n */\nexport interface CommandNotFoundContext {\n command: string;\n}\nexport interface CommandErrorContext {\n command: string;\n exitCode?: number;\n stdout?: string;\n stderr?: string;\n}\n/**\n * Process error contexts\n */\nexport interface ProcessNotFoundContext {\n processId: string;\n}\nexport interface ProcessErrorContext {\n processId: string;\n pid?: number;\n exitCode?: number;\n stderr?: string;\n}\nexport interface SessionAlreadyExistsContext {\n sessionId: string;\n}\nexport interface SessionDestroyedContext {\n sessionId: string;\n}\n/**\n * Process readiness error contexts\n */\nexport interface ProcessReadyTimeoutContext {\n processId: string;\n command: string;\n condition: string;\n timeout: number;\n}\nexport interface ProcessExitedBeforeReadyContext {\n processId: string;\n command: string;\n condition: string;\n exitCode: number;\n}\n/**\n * Port error contexts\n */\nexport interface PortAlreadyExposedContext {\n port: number;\n portName?: string;\n}\nexport interface PortNotExposedContext {\n port: number;\n}\nexport interface InvalidPortContext {\n port: number;\n reason: string;\n}\nexport interface PortErrorContext {\n port: number;\n portName?: string;\n stderr?: string;\n}\n/**\n * Git error contexts\n */\nexport interface GitRepositoryNotFoundContext {\n repository: string;\n}\nexport interface GitAuthFailedContext {\n repository: string;\n}\nexport interface GitBranchNotFoundContext {\n branch: string;\n repository?: string;\n}\nexport interface GitErrorContext {\n repository?: string;\n branch?: string;\n targetDir?: string;\n stderr?: string;\n exitCode?: number;\n}\n/**\n * Code interpreter error contexts\n */\nexport interface InterpreterNotReadyContext {\n retryAfter?: number;\n progress?: number;\n}\nexport interface ContextNotFoundContext {\n contextId: string;\n}\nexport interface CodeExecutionContext {\n contextId?: string;\n ename?: string;\n evalue?: string;\n traceback?: string[];\n}\n/**\n * Validation error contexts\n */\nexport interface ValidationFailedContext {\n validationErrors: Array<{\n field: string;\n message: string;\n code?: string;\n }>;\n}\n/**\n * Bucket mounting error contexts\n */\nexport interface BucketMountContext {\n bucket: string;\n mountPath: string;\n endpoint: string;\n stderr?: string;\n exitCode?: number;\n}\nexport interface MissingCredentialsContext {\n bucket: string;\n endpoint: string;\n}\nexport interface InvalidMountConfigContext {\n bucket?: string;\n mountPath?: string;\n endpoint?: string;\n reason?: string;\n}\n/**\n * Backup error contexts\n */\nexport interface BackupCreateContext {\n dir: string;\n backupId?: string;\n stderr?: string;\n exitCode?: number;\n}\nexport interface BackupRestoreContext {\n dir: string;\n backupId: string;\n stderr?: string;\n exitCode?: number;\n}\nexport interface BackupNotFoundContext {\n backupId: string;\n}\nexport interface BackupExpiredContext {\n backupId: string;\n expiredAt?: string;\n}\nexport interface InvalidBackupConfigContext {\n reason: string;\n}\n/**\n * OpenCode error contexts\n */\nexport interface OpencodeStartupContext {\n port: number;\n stderr?: string;\n command?: string;\n}\n/**\n * Generic error contexts\n */\nexport interface InternalErrorContext {\n originalError?: string;\n stack?: string;\n [key: string]: unknown;\n}\n/**\n * Desktop error contexts\n */\nexport interface DesktopErrorContext {\n process?: string;\n stderr?: string;\n crashedProcess?: string;\n reason?: string;\n}\nexport interface DesktopCoordinateErrorContext {\n x: number;\n y: number;\n displayWidth: number;\n displayHeight: number;\n}\n//# sourceMappingURL=contexts.d.ts.map"],"mappings":";;AAIA;AAwEA;;cAxEqBA;;ECAAE,SAAAA,iBAmCpB,EAAA,mBAAA;EACWC,SAAAA,WAAa,EAAA,aAAWD;EAKnBE,SAAAA,YAAa,EAAAC,cAAA;EAAYC,SAAAA,aAAAA,EAAAA,eAAAA;EAIhCL,SAAAA,cAAAA,EAAAA,gBAAAA;EAQME,SAAAA,QAAAA,EAAAA,UAAAA;EAKHE,SAAAA,cAAAA,EAAAA,gBAAAA;EAAQ,SAAA,aAAA,EAAA,eAAA;;;;ECLJgB,SAAAA,gBAAAA,EAAAA,kBAA0B;EAM1BC,SAAAA,iBAAAA,EAAAA,mBAA+B;EA8F/BiB,SAAAA,yBAAmB,EAAA,2BAAA;EAMnBC,SAAAA,eAAoB,EAAA,iBAAA;EAMpBC,SAAAA,uBAAqB,EAAA,yBAAA;EAGrBC,SAAAA,kBAAoB,EAAA,oBAAA;EAIpBC,SAAAA,iBAAAA,EAAAA,mBAA0B;EAM1BC,SAAAA,yBAAsB,EAAA,2BAAA;EAgBtBE,SAAAA,aAAmB,EAAA,eAAA;EAMnBC,SAAAA,sBAAAA,EAA6B,wBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KFhIlC/C,SAAAA,WAAoBA,wBAAwBA;;;AAxExD;AAwEA;;cCxEqBE;;EAAAA,SAAAA,UAmCpB,EAAA,YAAA;EACWC,SAAAA,WAAa,EAAA,aAAWD;EAKnBE,SAAAA,SAAa,EAAA,WAAAC;EAAYC,SAAAA,WAAAA,EAAAA,aAAAA;EAIhCL,SAAAA,SAAAA,EAAAA,WAAAA;EAQME,SAAAA,gBAAAA,EAAAA,kBAAAA;EAKHE,SAAAA,cAAAA,EAAAA,gBAAAA;EAAQ,SAAA,eAAA,EAAA,iBAAA;;;;ECLJgB,SAAAA,YAAAA,EAAAA,cAA0B;EAM1BC,SAAAA,WAAAA,EAAAA,aAA+B;EA8F/BiB,SAAAA,YAAAA,EAAmB,cAAA;EAMnBC,SAAAA,WAAAA,EAAAA,aAAoB;EAMpBC,SAAAA,aAAAA,EAAqB,eAAA;EAGrBC,SAAAA,SAAAA,EAAAA,WAAoB;EAIpBC,SAAAA,UAAAA,EAAAA,YAA0B;EAM1BC,SAAAA,SAAAA,EAAAA,WAAsB;EAgBtBE,SAAAA,YAAAA,EAAmB,cAAA;EAMnBC,SAAAA,aAAAA,EAAAA,eAA6B;;;;;;;;;;;;;;KDpKlC5C,aAAAA,WAAwBD,wBAAwBA;;;;;UAK3CE,yBAAyBE;;;;QAIhCL;;;;;;;;cAQME;;;;;WAKHE;;;;;;;;;;;;;;;;;;;;;;;;UCLIgB,0BAAAA;;;;;;UAMAC,+BAAAA;;;;;;;;;UA8FAiB,mBAAAA;;;;;;UAMAC,oBAAAA;;;;;;UAMAC,qBAAAA;;;UAGAC,oBAAAA;;;;UAIAC,0BAAAA;;;;;;UAMAC,sBAAAA;;;;;;;;UAgBAE,mBAAAA;;;;;;UAMAC,6BAAAA"}
|
|
@@ -974,4 +974,4 @@ function generateRequestId() {
|
|
|
974
974
|
|
|
975
975
|
//#endregion
|
|
976
976
|
export { GitLogger as _, isExecResult as a, getEnvString as b, parseSSEFrames as c, createNoOpLogger as d, TraceContext as f, DEFAULT_GIT_CLONE_TIMEOUT_MS as g, ResultImpl as h, isWSStreamChunk as i, shellEscape as l, Execution as m, isWSError as n, isProcess as o, logCanonicalEvent as p, isWSResponse as r, isProcessStatus as s, generateRequestId as t, createLogger as u, extractRepoName as v, partitionEnvVars as x, filterEnvVars as y };
|
|
977
|
-
//# sourceMappingURL=dist-
|
|
977
|
+
//# sourceMappingURL=dist-Ilf8VjmX.js.map
|