ppio-sandbox 1.1.3-b3 → 1.1.3

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.
@@ -48,7 +48,7 @@ import createClient from "openapi-fetch";
48
48
  import platform from "platform";
49
49
 
50
50
  // package.json
51
- var version = "1.1.3-b3";
51
+ var version = "1.1.3";
52
52
 
53
53
  // src/core/api/metadata.ts
54
54
  function getRuntime() {
@@ -2721,4 +2721,4 @@ export {
2721
2721
  Sandbox,
2722
2722
  core_default
2723
2723
  };
2724
- //# sourceMappingURL=chunk-CWF5Y3T4.mjs.map
2724
+ //# sourceMappingURL=chunk-EISDT44U.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/api/index.ts","../src/core/api/metadata.ts","../package.json","../src/core/errors.ts","../src/core/logs.ts","../src/core/connectionConfig.ts","../src/core/utils.ts","../src/core/sandbox/signature.ts","../src/core/sandbox/filesystem/index.ts","../src/core/envd/api.ts","../src/core/envd/rpc.ts","../src/core/envd/filesystem/filesystem_pb.ts","../src/core/sandbox/filesystem/watchHandle.ts","../src/core/envd/versions.ts","../src/core/sandbox/commands/commandHandle.ts","../src/core/template/templateApi.ts","../src/core/sandbox/index.ts","../src/core/sandbox/commands/index.ts","../src/core/envd/process/process_pb.ts","../src/core/sandbox/commands/pty.ts","../src/core/sandbox/sandboxApi.ts","../src/core/index.ts"],"sourcesContent":["import createClient, { FetchResponse } from 'openapi-fetch'\n\nimport type { components, paths } from './schema.gen'\nimport { defaultHeaders } from './metadata'\nimport { ConnectionConfig } from '../connectionConfig'\nimport { AuthenticationError, RateLimitError, SandboxError } from '../errors'\nimport { createApiLogger } from '../logs'\n\nexport function handleApiError(\n response: FetchResponse<any, any, any>\n): Error | undefined {\n if (!response.error) {\n return\n }\n\n if (response.response.status === 429) {\n const message = 'Rate limit exceeded, please try again later'\n const content = response.error?.message ?? response.error\n\n if (content) {\n return new RateLimitError(`${message} - ${content}`)\n }\n return new RateLimitError(message)\n }\n\n const message = response.error?.message ?? response.error\n return new SandboxError(`${response.response.status}: ${message}`)\n}\n\n/**\n * Client for interacting with the PPIO agent sandbox API.\n */\nclass ApiClient {\n readonly api: ReturnType<typeof createClient<paths>>\n\n constructor(\n config: ConnectionConfig,\n opts: {\n requireAccessToken?: boolean\n requireApiKey?: boolean\n } = { requireAccessToken: false, requireApiKey: false }\n ) {\n if (opts?.requireApiKey && !config.apiKey) {\n throw new AuthenticationError(\n 'API key is required, please visit the Key Management page at https://ppio.com/settings/key-management to get your API key. ' +\n 'You can either set the environment variable `PPIO_API_KEY` ' +\n \"or you can pass it directly to the sandbox like Sandbox.create({ apiKey: 'sk_...' })\"\n )\n }\n\n if (opts?.requireAccessToken && !config.accessToken) {\n throw new AuthenticationError(\n 'Access token is required, please visit the Key Management page at https://ppio.com/settings/key-management to get your access token, which is same as the API key. ' +\n 'You can set the environment variable `PPIO_ACCESS_TOKEN` or pass the `accessToken` in options.'\n )\n }\n\n this.api = createClient<paths>({\n baseUrl: config.apiUrl,\n // keepalive: true, // TODO: Return keepalive\n headers: {\n ...defaultHeaders,\n ...(config.apiKey && { 'X-API-KEY': config.apiKey }),\n ...(config.accessToken && {\n Authorization: `Bearer ${config.accessToken}`,\n }),\n ...config.headers,\n },\n querySerializer: {\n array: {\n style: 'form',\n explode: false,\n },\n },\n })\n\n if (config.logger) {\n this.api.use(createApiLogger(config.logger))\n }\n }\n}\n\nexport type { components, paths }\nexport { ApiClient }\n","import platform from 'platform'\n\nimport { version } from '../../../package.json'\n\nexport { version }\n\ndeclare let window: any\n\ntype Runtime = 'node' | 'browser' | 'deno' | 'bun' | 'vercel-edge' | 'cloudflare-worker' | 'unknown'\n\nfunction getRuntime(): { runtime: Runtime; version: string } {\n // @ts-ignore\n if ((globalThis as any).Bun) {\n // @ts-ignore\n return { runtime: 'bun', version: globalThis.Bun.version }\n }\n\n // @ts-ignore\n if ((globalThis as any).Deno) {\n // @ts-ignore\n return { runtime: 'deno', version: globalThis.Deno.version.deno }\n }\n\n if ((globalThis as any).process?.release?.name === 'node') {\n return { runtime: 'node', version: platform.version || 'unknown' }\n }\n\n // @ts-ignore\n if (typeof EdgeRuntime === 'string') {\n return { runtime: 'vercel-edge', version: 'unknown' }\n }\n\n if ((globalThis as any).navigator?.userAgent === 'Cloudflare-Workers') {\n return { runtime: 'cloudflare-worker', version: 'unknown' }\n }\n\n if (typeof window !== 'undefined') {\n return { runtime: 'browser', version: platform.version || 'unknown' }\n }\n\n return { runtime: 'unknown', version: 'unknown' }\n}\n\nexport const { runtime, version: runtimeVersion } = getRuntime()\n\nexport const defaultHeaders = {\n browser: (typeof window !== 'undefined' && platform.name) || 'unknown',\n lang: 'js',\n lang_version: runtimeVersion,\n package_version: version,\n publisher: 'PPIO',\n sdk_runtime: runtime,\n system: platform.os?.family || 'unknown',\n}\n\nexport function getEnvVar(name: string) {\n if (runtime === 'deno') {\n // @ts-ignore\n return Deno.env.get(name)\n }\n\n if (typeof process === 'undefined') {\n return ''\n }\n\n return process.env[name]\n}\n","{\n \"name\": \"ppio-sandbox\",\n \"version\": \"1.1.3\",\n \"description\": \"PPIO Sandbox SDK for JavaScript/TypeScript - A comprehensive SDK for code execution, desktop automation, and cloud computing environments\",\n \"main\": \"dist/index.js\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.js\"\n },\n \"./code-interpreter\": {\n \"types\": \"./dist/code-interpreter.d.ts\",\n \"import\": \"./dist/code-interpreter.mjs\",\n \"require\": \"./dist/code-interpreter.js\"\n },\n \"./desktop\": {\n \"types\": \"./dist/desktop.d.ts\",\n \"import\": \"./dist/desktop.mjs\",\n \"require\": \"./dist/desktop.js\"\n }\n },\n \"files\": [\n \"dist/**/*\",\n \"README.md\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"check-deps\": \"knip\",\n \"update-deps\": \"ncu -u && pnpm i\",\n \"build\": \"tsc --noEmit && tsup\",\n \"dev\": \"tsup --watch\",\n \"lint:fix\": \"eslint src/**/*.ts --fix\",\n \"lint\": \"eslint src/**/*.ts tests/**/*.ts\",\n \"format\": \"prettier --write src/**/*.ts\",\n \"clean\": \"rimraf dist\",\n \"prepublishOnly\": \"pnpm build\",\n \"test:core\": \"vitest run ./src/core/ --reporter verbose --run\",\n \"test:code-interpreter\": \"vitest run ./src/code-interpreter/ --reporter verbose --run\",\n \"test:desktop\": \"vitest run ./src/desktop/ --reporter verbose --run\",\n \"generate:api\": \"python ./spec/remove_extra_tags.py sandboxes templates auth && openapi-typescript ./spec/openapi_generated.yml -x api_key --array-length --alphabetize --output src/core/api/schema.gen.ts\",\n \"generate:envd-api\": \"openapi-typescript ./spec/envd/envd.yaml -x api_key --array-length --alphabetize --output src/core/envd/schema.gen.ts\"\n },\n \"keywords\": [\n \"ppio\",\n \"ai-agent\",\n \"sandbox\",\n \"sdk\",\n \"typescript\",\n \"javascript\",\n \"code-interpreter\",\n \"desktop-automation\",\n \"cloud-computing\",\n \"remote-execution\",\n \"api-client\"\n ],\n \"author\": {\n \"name\": \"PPIO\",\n \"url\": \"https://ppio.com\"\n },\n \"engines\": {\n \"node\": \">=16.0.0\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^20.0.0\",\n \"@types/platform\": \"^1.3.6\",\n \"@types/react\": \"^19.1.12\",\n \"@typescript-eslint/eslint-plugin\": \"^6.0.0\",\n \"@typescript-eslint/parser\": \"^6.0.0\",\n \"eslint\": \"^8.0.0\",\n \"eslint-config-prettier\": \"^9.0.0\",\n \"eslint-plugin-prettier\": \"^5.0.0\",\n \"knip\": \"^5.43.6\",\n \"prettier\": \"^3.0.0\",\n \"react\": \"^18.3.1\",\n \"rimraf\": \"^5.0.0\",\n \"ts-jest\": \"^29.1.0\",\n \"ts-node\": \"^10.9.0\",\n \"typescript\": \"^5.0.0\",\n \"vitest\": \"^3.1.1\",\n \"tsup\": \"^8.4.0\",\n \"openapi-typescript\": \"^7.6.1\"\n },\n \"dependencies\": {\n \"@bufbuild/protobuf\": \"^2.6.2\",\n \"@connectrpc/connect\": \"2.0.0-rc.3\",\n \"@connectrpc/connect-web\": \"2.0.0-rc.3\",\n \"compare-versions\": \"^6.1.0\",\n \"openapi-fetch\": \"^0.9.7\",\n \"platform\": \"^1.3.6\"\n },\n \"bugs\": {\n \"url\": \"https://ppio.com/about?index=2\"\n },\n \"homepage\": \"https://ppio.com/ai-computing/sandbox\"\n}\n","// This is the message for the sandbox timeout error when the response code is 502/Unavailable\nexport function formatSandboxTimeoutError(message: string) {\n return new TimeoutError(\n `${message}: This error is likely due to sandbox timeout. You can modify the sandbox timeout by passing 'timeoutMs' when starting the sandbox or calling '.setTimeout' on the sandbox with the desired timeout.`\n )\n}\n\n/**\n * Base class for all sandbox errors.\n *\n * Thrown when general sandbox errors occur.\n */\nexport class SandboxError extends Error {\n constructor(message: any) {\n super(message)\n this.name = 'SandboxError'\n }\n}\n\n/**\n * Thrown when a timeout error occurs.\n *\n * The [unavailable] error type is caused by sandbox timeout.\n *\n * The [canceled] error type is caused by exceeding request timeout.\n *\n * The [deadline_exceeded] error type is caused by exceeding the timeout for command execution, watch, etc.\n *\n * The [unknown] error type is sometimes caused by the sandbox timeout when the request is not processed correctly.\n */\nexport class TimeoutError extends SandboxError {\n constructor(message: string) {\n super(message)\n this.name = 'TimeoutError'\n }\n}\n\n/**\n * Thrown when an invalid argument is provided.\n */\nexport class InvalidArgumentError extends SandboxError {\n constructor(message: string) {\n super(message)\n this.name = 'InvalidArgumentError'\n }\n}\n\n/**\n * Thrown when there is not enough disk space.\n */\nexport class NotEnoughSpaceError extends SandboxError {\n constructor(message: string) {\n super(message)\n this.name = 'NotEnoughSpaceError'\n }\n}\n\n/**\n * Thrown when a resource is not found.\n */\nexport class NotFoundError extends SandboxError {\n constructor(message: string) {\n super(message)\n this.name = 'NotFoundError'\n }\n}\n\n/**\n * Thrown when authentication fails.\n */\nexport class AuthenticationError extends SandboxError {\n constructor(message: any) {\n super(message)\n this.name = 'AuthenticationError'\n }\n}\n\n/**\n * Thrown when the template uses old envd version. It isn't compatible with the new SDK.\n */\nexport class TemplateError extends SandboxError {\n constructor(message: string) {\n super(message)\n this.name = 'TemplateError'\n }\n}\n\n/**\n * Thrown when the API rate limit is exceeded.\n */\nexport class RateLimitError extends SandboxError {\n constructor(message: any) {\n super(message)\n this.name = 'RateLimitError'\n }\n}\n","import type { Interceptor } from '@connectrpc/connect'\nimport type { Middleware } from 'openapi-fetch'\n\n/**\n * Logger interface compatible with {@link console} used for logging Sandbox messages.\n */\nexport interface Logger {\n /**\n * Debug level logging method.\n */\n debug?: (...args: any[]) => void\n /**\n * Info level logging method.\n */\n info?: (...args: any[]) => void\n /**\n * Warn level logging method.\n */\n warn?: (...args: any[]) => void\n /**\n * Error level logging method.\n */\n error?: (...args: any[]) => void\n}\n\nfunction formatLog(log: any) {\n return JSON.parse(JSON.stringify(log))\n}\n\nexport function createRpcLogger(logger: Logger): Interceptor {\n async function* logEach(stream: AsyncIterable<any>) {\n for await (const m of stream) {\n logger.debug?.('Response stream:', formatLog(m))\n yield m\n }\n }\n\n return (next) => async (req) => {\n logger.info?.(`Request: POST ${req.url}`)\n\n const res = await next(req)\n if (res.stream) {\n return {\n ...res,\n message: logEach(res.message),\n }\n } else {\n logger.info?.('Response:', formatLog(res.message))\n }\n\n return res\n }\n}\n\nexport function createApiLogger(logger: Logger): Middleware {\n return {\n async onRequest(req) {\n logger.info?.(`Request ${req.method} ${req.url}`)\n\n return req\n },\n async onResponse(res) {\n if (res.status >= 400) {\n logger.error?.('Response:', res.status, res.statusText)\n } else {\n logger.info?.('Response:', res.status, res.statusText)\n }\n\n return res\n },\n }\n}\n","import { Logger } from './logs'\nimport { getEnvVar, version } from './api/metadata'\n\nexport const REQUEST_TIMEOUT_MS = 1_800_000 // 1800 seconds\nexport const REQUEST_LONG_TIMEOUT_MS = 300_000 // 300 seconds\nexport const DEFAULT_SANDBOX_TIMEOUT_MS = 300_000 // 300 seconds\nexport const KEEPALIVE_PING_INTERVAL_SEC = 50 // 50 seconds\n\nexport const KEEPALIVE_PING_HEADER = 'Keepalive-Ping-Interval'\n\n/**\n * Connection options for requests to the API.\n */\nexport interface ConnectionOpts {\n /**\n * PPIO API key to use for authentication.\n *\n * @default PPIO_API_KEY // environment variable\n */\n apiKey?: string\n /**\n * PPIO access token to use for authentication.\n *\n * @default PPIO_ACCESS_TOKEN // environment variable\n */\n accessToken?: string\n /**\n * Domain to use for the API.\n *\n * @default PPIO_DOMAIN // environment variable or `ppio.com`\n */\n domain?: string\n /**\n * If true the SDK starts in the debug mode and connects to the local envd API server.\n * @internal\n * @default PPIO_DEBUG // environment variable or `false`\n */\n debug?: boolean\n /**\n * Timeout for requests to the API in **milliseconds**.\n *\n * @default 1_800_000 // 1800 seconds\n */\n requestTimeoutMs?: number\n /**\n * Logger to use for logging messages. It can accept any object that implements `Logger` interface—for example, {@link console}.\n */\n logger?: Logger\n\n /**\n * Additional headers to send with the request.\n */\n headers?: Record<string, string>\n\n /**\n * If true, the SDK will wait until sandbox pause succeeds\n * @internal\n */\n sync?: boolean\n}\n\n/**\n * Configuration for connecting to the API.\n */\nexport class ConnectionConfig {\n readonly debug: boolean\n readonly domain: string\n readonly apiUrl: string\n readonly logger?: Logger\n\n readonly requestTimeoutMs: number\n\n readonly apiKey?: string\n readonly accessToken?: string\n\n readonly headers?: Record<string, string>\n\n constructor(opts?: ConnectionOpts) {\n this.apiKey = opts?.apiKey || ConnectionConfig.apiKey\n this.debug = opts?.debug || ConnectionConfig.debug\n this.domain = opts?.domain || ConnectionConfig.domain\n this.accessToken = opts?.accessToken || ConnectionConfig.accessToken\n this.requestTimeoutMs = opts?.requestTimeoutMs ?? REQUEST_TIMEOUT_MS\n this.logger = opts?.logger\n this.headers = opts?.headers || {}\n this.headers['User-Agent'] = `ppio-sandbox-sdk-js/${version}`\n\n this.apiUrl = this.debug\n ? 'http://localhost:3000'\n : `https://api.${this.domain}`\n }\n\n private static get domain() {\n return getEnvVar('PPIO_DOMAIN') || 'sandbox.ppio.cn'\n }\n\n private static get debug() {\n return (getEnvVar('PPIO_DEBUG') || 'false').toLowerCase() === 'true'\n }\n\n private static get apiKey() {\n return getEnvVar('PPIO_API_KEY')\n }\n\n private static get accessToken() {\n return getEnvVar('PPIO_ACCESS_TOKEN')\n }\n\n getSignal(requestTimeoutMs?: number) {\n const timeout = requestTimeoutMs ?? this.requestTimeoutMs\n\n return timeout ? AbortSignal.timeout(timeout) : undefined\n }\n}\n\n/**\n * User used for the operation in the sandbox.\n */\nexport type Username = 'root' | 'user'\n\nexport const defaultUsername: Username = 'user'\n","export async function sha256(data: string): Promise<string> {\n // Use WebCrypto API if available\n if (typeof crypto !== 'undefined') {\n const encoder = new TextEncoder()\n const dataBuffer = encoder.encode(data)\n const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer)\n const hashArray = new Uint8Array(hashBuffer)\n return btoa(String.fromCharCode(...hashArray))\n }\n\n // Use Node.js crypto if WebCrypto is not available\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const { createHash } = require('node:crypto')\n const hash = createHash('sha256').update(data, 'utf8').digest()\n return hash.toString('base64')\n}\n\nexport function timeoutToSeconds(timeout: number): number {\n return Math.ceil(timeout / 1000)\n}\n","import { sha256 } from '../utils'\n\n/**\n * Get the URL signature for the specified path, operation and user.\n *\n * @param path Path to the file in the sandbox.\n *\n * @param operation File system operation. Can be either `read` or `write`.\n *\n * @param user Sandbox user.\n *\n * @param expirationInSeconds Optional signature expiration time in seconds.\n */\n\ninterface SignatureOpts {\n path: string\n operation: 'read' | 'write'\n user: string\n expirationInSeconds?: number\n envdAccessToken?: string\n}\n\nexport async function getSignature({\n path,\n operation,\n user,\n expirationInSeconds,\n envdAccessToken,\n}: SignatureOpts): Promise<{ signature: string; expiration: number | null }> {\n if (!envdAccessToken) {\n throw new Error(\n 'Access token is not set and signature cannot be generated!'\n )\n }\n\n // expiration is unix timestamp\n const signatureExpiration = expirationInSeconds\n ? Math.floor(Date.now() / 1000) + expirationInSeconds\n : null\n let signatureRaw: string\n\n if (signatureExpiration === null) {\n signatureRaw = `${path}:${operation}:${user}:${envdAccessToken}`\n } else {\n signatureRaw = `${path}:${operation}:${user}:${envdAccessToken}:${signatureExpiration.toString()}`\n }\n\n const hashBase64 = await sha256(signatureRaw)\n const signature = 'v1_' + hashBase64.replace(/=+$/, '')\n\n return {\n signature: signature,\n expiration: signatureExpiration,\n }\n}\n","import {\n createClient,\n Transport,\n Client,\n ConnectError,\n Code,\n} from '@connectrpc/connect'\nimport {\n ConnectionConfig,\n ConnectionOpts,\n defaultUsername,\n KEEPALIVE_PING_HEADER,\n KEEPALIVE_PING_INTERVAL_SEC,\n Username,\n} from '../../connectionConfig'\n\nimport { handleEnvdApiError, handleWatchDirStartEvent } from '../../envd/api'\nimport { authenticationHeader, handleRpcError } from '../../envd/rpc'\n\nimport { EnvdApiClient } from '../../envd/api'\nimport {\n FileType as FsFileType,\n Filesystem as FilesystemService,\n} from '../../envd/filesystem/filesystem_pb'\n\nimport { FilesystemEvent, WatchHandle } from './watchHandle'\n\nimport { compareVersions } from 'compare-versions'\nimport { InvalidArgumentError, TemplateError } from '../../errors'\nimport { ENVD_VERSION_RECURSIVE_WATCH } from '../../envd/versions'\nimport type { Timestamp } from '@bufbuild/protobuf/wkt'\n\n/**\n * Sandbox filesystem object information.\n */\nexport interface WriteInfo {\n /**\n * Name of the filesystem object.\n */\n name: string\n /**\n * Type of the filesystem object.\n */\n type?: FileType\n /**\n * Path to the filesystem object.\n */\n path: string\n}\n\nexport interface EntryInfo extends WriteInfo {\n /**\n * Size of the filesystem object in bytes.\n */\n size: number\n\n /**\n * File mode and permission bits.\n */\n mode: number\n\n /**\n * String representation of file permissions (e.g. 'rwxr-xr-x').\n */\n permissions: string\n\n /**\n * Owner of the filesystem object.\n */\n owner: string\n\n /**\n * Group owner of the filesystem object.\n */\n group: string\n\n /**\n * Last modification time of the filesystem object.\n */\n modifiedTime?: Date\n\n /**\n * If the filesystem object is a symlink, this is the target of the symlink.\n */\n symlinkTarget?: string\n}\n\n/**\n * Sandbox filesystem object type.\n */\nexport enum FileType {\n /**\n * Filesystem object is a file.\n */\n FILE = 'file',\n /**\n * Filesystem object is a directory.\n */\n DIR = 'dir',\n}\n\nexport type WriteEntry = {\n path: string\n data: string | ArrayBuffer | Blob | ReadableStream\n}\n\nfunction mapFileType(fileType: FsFileType) {\n switch (fileType) {\n case FsFileType.DIRECTORY:\n return FileType.DIR\n case FsFileType.FILE:\n return FileType.FILE\n }\n}\n\nfunction mapModifiedTime(modifiedTime: Timestamp | undefined) {\n if (!modifiedTime) return undefined\n\n return new Date(\n Number(modifiedTime.seconds) * 1000 +\n Math.floor(modifiedTime.nanos / 1_000_000)\n )\n}\n\n/**\n * Options for the sandbox filesystem operations.\n */\nexport interface FilesystemRequestOpts\n extends Partial<Pick<ConnectionOpts, 'requestTimeoutMs'>> {\n /**\n * User to use for the operation in the sandbox.\n * This affects the resolution of relative paths and ownership of the created filesystem objects.\n */\n user?: Username\n}\n\nexport interface FilesystemListOpts extends FilesystemRequestOpts {\n /**\n * Depth of the directory to list.\n */\n depth?: number\n}\n\n/**\n * Options for watching a directory.\n */\nexport interface WatchOpts extends FilesystemRequestOpts {\n /**\n * Timeout for the watch operation in **milliseconds**.\n * You can pass `0` to disable the timeout.\n *\n * @default 60_000 // 60 seconds\n */\n timeoutMs?: number\n /**\n * Callback to call when the watch operation stops.\n */\n onExit?: (err?: Error) => void | Promise<void>\n /**\n * Watch the directory recursively\n */\n recursive?: boolean\n}\n\n/**\n * Module for interacting with the sandbox filesystem.\n */\nexport class Filesystem {\n private readonly rpc: Client<typeof FilesystemService>\n\n private readonly defaultWatchTimeout = 60_000 // 60 seconds\n private readonly defaultWatchRecursive = false\n\n constructor(\n transport: Transport,\n private readonly envdApi: EnvdApiClient,\n private readonly connectionConfig: ConnectionConfig\n ) {\n this.rpc = createClient(FilesystemService, transport)\n }\n\n /**\n * Read file content as a `string`.\n *\n * You can pass `text`, `bytes`, `blob`, or `stream` to `opts.format` to change the return type.\n *\n * @param path path to the file.\n * @param opts connection options.\n * @param [opts.format] format of the file content—`text` by default.\n *\n * @returns file content as string\n */\n async read(\n path: string,\n opts?: FilesystemRequestOpts & { format?: 'text' }\n ): Promise<string>\n /**\n * Read file content as a `Uint8Array`.\n *\n * You can pass `text`, `bytes`, `blob`, or `stream` to `opts.format` to change the return type.\n *\n * @param path path to the file.\n * @param opts connection options.\n * @param [opts.format] format of the file content—`bytes`.\n *\n * @returns file content as `Uint8Array`\n */\n async read(\n path: string,\n opts?: FilesystemRequestOpts & { format: 'bytes' }\n ): Promise<Uint8Array>\n /**\n * Read file content as a `Blob`.\n *\n * You can pass `text`, `bytes`, `blob`, or `stream` to `opts.format` to change the return type.\n *\n * @param path path to the file.\n * @param opts connection options.\n * @param [opts.format] format of the file content—`blob`.\n *\n * @returns file content as `Blob`\n */\n async read(\n path: string,\n opts?: FilesystemRequestOpts & { format: 'blob' }\n ): Promise<Blob>\n /**\n * Read file content as a `ReadableStream`.\n *\n * You can pass `text`, `bytes`, `blob`, or `stream` to `opts.format` to change the return type.\n *\n * @param path path to the file.\n * @param opts connection options.\n * @param [opts.format] format of the file content—`stream`.\n *\n * @returns file content as `ReadableStream`\n */\n async read(\n path: string,\n opts?: FilesystemRequestOpts & { format: 'stream' }\n ): Promise<ReadableStream<Uint8Array>>\n async read(\n path: string,\n opts?: FilesystemRequestOpts & {\n format?: 'text' | 'stream' | 'bytes' | 'blob'\n }\n ): Promise<unknown> {\n const format = opts?.format ?? 'text'\n\n const res = await this.envdApi.api.GET('/files', {\n params: {\n query: {\n path,\n username: opts?.user || defaultUsername,\n },\n },\n parseAs: format === 'bytes' ? 'arrayBuffer' : format,\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n })\n\n const err = await handleEnvdApiError(res)\n if (err) {\n throw err\n }\n\n if (format === 'bytes') {\n return new Uint8Array(res.data as ArrayBuffer)\n }\n\n // When the file is empty, res.data is parsed as `{}`. This is a workaround to return an empty string.\n if (res.response.headers.get('content-length') === '0') {\n if (format === 'blob') {\n return new Blob([])\n }\n\n return ''\n }\n\n return res.data\n }\n\n /**\n * Write content to a file.\n *\n *\n * Writing to a file that doesn't exist creates the file.\n *\n * Writing to a file that already exists overwrites the file.\n *\n * Writing to a file at path that doesn't exist creates the necessary directories.\n *\n * @param path path to file.\n * @param data data to write to the file. Data can be a string, `ArrayBuffer`, `Blob`, or `ReadableStream`.\n * @param opts connection options.\n *\n * @returns information about the written file\n */\n async write(\n path: string,\n data: string | ArrayBuffer | Blob | ReadableStream,\n opts?: FilesystemRequestOpts\n ): Promise<WriteInfo>\n async write(\n files: WriteEntry[],\n opts?: FilesystemRequestOpts\n ): Promise<WriteInfo[]>\n async write(\n pathOrFiles: string | WriteEntry[],\n dataOrOpts?:\n | string\n | ArrayBuffer\n | Blob\n | ReadableStream\n | FilesystemRequestOpts,\n opts?: FilesystemRequestOpts\n ): Promise<WriteInfo | WriteInfo[]> {\n if (typeof pathOrFiles !== 'string' && !Array.isArray(pathOrFiles)) {\n throw new Error('Path or files are required')\n }\n\n if (typeof pathOrFiles === 'string' && Array.isArray(dataOrOpts)) {\n throw new Error(\n 'Cannot specify both path and array of files. You have to specify either path and data for a single file or an array for multiple files.'\n )\n }\n\n const { path, writeOpts, writeFiles } =\n typeof pathOrFiles === 'string'\n ? {\n path: pathOrFiles,\n writeOpts: opts as FilesystemRequestOpts,\n writeFiles: [\n {\n data: dataOrOpts as\n | string\n | ArrayBuffer\n | Blob\n | ReadableStream,\n },\n ],\n }\n : {\n path: undefined,\n writeOpts: dataOrOpts as FilesystemRequestOpts,\n writeFiles: pathOrFiles as WriteEntry[],\n }\n\n if (writeFiles.length === 0) return [] as WriteInfo[]\n\n const blobs = await Promise.all(\n writeFiles.map((f) => new Response(f.data).blob())\n )\n\n const res = await this.envdApi.api.POST('/files', {\n params: {\n query: {\n path,\n username: writeOpts?.user || defaultUsername,\n },\n },\n bodySerializer() {\n return blobs.reduce((fd, blob, i) => {\n // Important: RFC 7578, Section 4.2 requires that if a filename is provided,\n // the directory path information must not be used.\n // BUT in our case we need to use the directory path information with a custom\n // muktipart part name getter in envd.\n fd.append('file', blob, writeFiles[i].path)\n\n return fd\n }, new FormData())\n },\n body: {},\n headers: {\n 'Content-Type': 'multipart/form-data',\n 'Bun-Content-Type': 'temporary-fix', // https://github.com/oven-sh/bun/issues/14988\n },\n })\n\n const err = await handleEnvdApiError(res)\n if (err) {\n throw err\n }\n\n const files = res.data as WriteInfo[]\n if (!files) {\n throw new Error('Expected to receive information about written file')\n }\n\n return files.length === 1 && path ? files[0] : files\n }\n\n /**\n * List entries in a directory.\n *\n * @param path path to the directory.\n * @param opts connection options.\n *\n * @returns list of entries in the sandbox filesystem directory.\n */\n async list(path: string, opts?: FilesystemListOpts): Promise<EntryInfo[]> {\n if (typeof opts?.depth === 'number' && opts.depth < 1) {\n throw new InvalidArgumentError('depth should be at least one')\n }\n\n try {\n const res = await this.rpc.listDir(\n {\n path,\n depth: opts?.depth ?? 1,\n },\n {\n headers: authenticationHeader(opts?.user),\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n const entries: EntryInfo[] = []\n\n for (const e of res.entries) {\n const type = mapFileType(e.type)\n\n if (type) {\n entries.push({\n name: e.name,\n type,\n path: e.path,\n size: Number(e.size),\n mode: e.mode,\n permissions: e.permissions,\n owner: e.owner,\n group: e.group,\n modifiedTime: mapModifiedTime(e.modifiedTime),\n symlinkTarget: e.symlinkTarget,\n })\n }\n }\n\n return entries\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Create a new directory and all directories along the way if needed on the specified path.\n *\n * @param path path to a new directory. For example '/dirA/dirB' when creating 'dirB'.\n * @param opts connection options.\n *\n * @returns `true` if the directory was created, `false` if it already exists.\n */\n async makeDir(path: string, opts?: FilesystemRequestOpts): Promise<boolean> {\n try {\n await this.rpc.makeDir(\n { path },\n {\n headers: authenticationHeader(opts?.user),\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n return true\n } catch (err) {\n if (err instanceof ConnectError) {\n if (err.code === Code.AlreadyExists) {\n return false\n }\n }\n\n throw handleRpcError(err)\n }\n }\n\n /**\n * Rename a file or directory.\n *\n * @param oldPath path to the file or directory to rename.\n * @param newPath new path for the file or directory.\n * @param opts connection options.\n *\n * @returns information about renamed file or directory.\n */\n async rename(\n oldPath: string,\n newPath: string,\n opts?: FilesystemRequestOpts\n ): Promise<EntryInfo> {\n try {\n const res = await this.rpc.move(\n {\n source: oldPath,\n destination: newPath,\n },\n {\n headers: authenticationHeader(opts?.user),\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n const entry = res.entry\n if (!entry) {\n throw new Error('Expected to receive information about moved object')\n }\n\n return {\n name: entry.name,\n type: mapFileType(entry.type),\n path: entry.path,\n size: Number(entry.size),\n mode: entry.mode,\n permissions: entry.permissions,\n owner: entry.owner,\n group: entry.group,\n modifiedTime: mapModifiedTime(entry.modifiedTime),\n symlinkTarget: entry.symlinkTarget,\n }\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Remove a file or directory.\n *\n * @param path path to a file or directory.\n * @param opts connection options.\n */\n async remove(path: string, opts?: FilesystemRequestOpts): Promise<void> {\n try {\n await this.rpc.remove(\n { path },\n {\n headers: authenticationHeader(opts?.user),\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Check if a file or a directory exists.\n *\n * @param path path to a file or a directory\n * @param opts connection options.\n *\n * @returns `true` if the file or directory exists, `false` otherwise\n */\n async exists(path: string, opts?: FilesystemRequestOpts): Promise<boolean> {\n try {\n await this.rpc.stat(\n { path },\n {\n headers: authenticationHeader(opts?.user),\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n return true\n } catch (err) {\n if (err instanceof ConnectError) {\n if (err.code === Code.NotFound) {\n return false\n }\n }\n\n throw handleRpcError(err)\n }\n }\n\n /**\n * Get information about a file or directory.\n *\n * @param path path to a file or directory.\n * @param opts connection options.\n *\n * @returns information about the file or directory like name, type, and path.\n */\n async getInfo(\n path: string,\n opts?: FilesystemRequestOpts\n ): Promise<EntryInfo> {\n try {\n const res = await this.rpc.stat(\n { path },\n { headers: authenticationHeader(opts?.user) }\n )\n\n if (!res.entry) {\n throw new Error(\n 'Expected to receive information about the file or directory'\n )\n }\n\n return {\n name: res.entry.name,\n type: mapFileType(res.entry.type),\n path: res.entry.path,\n size: Number(res.entry.size),\n mode: res.entry.mode,\n permissions: res.entry.permissions,\n owner: res.entry.owner,\n group: res.entry.group,\n modifiedTime: mapModifiedTime(res.entry.modifiedTime),\n symlinkTarget: res.entry.symlinkTarget,\n }\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Start watching a directory for filesystem events.\n *\n * @param path path to directory to watch.\n * @param onEvent callback to call when an event in the directory occurs.\n * @param opts connection options.\n *\n * @returns `WatchHandle` object for stopping watching directory.\n */\n async watchDir(\n path: string,\n onEvent: (event: FilesystemEvent) => void | Promise<void>,\n opts?: WatchOpts & {\n onExit?: (err?: Error) => void | Promise<void>\n }\n ): Promise<WatchHandle> {\n if (\n opts?.recursive &&\n this.envdApi.version &&\n compareVersions(this.envdApi.version, ENVD_VERSION_RECURSIVE_WATCH) < 0\n ) {\n throw new TemplateError(\n 'You need to update the template to use recursive watching. ' +\n 'You can do this by running `ppio-sandbox-cli template build` in the directory with the template.'\n )\n }\n\n const requestTimeoutMs =\n opts?.requestTimeoutMs ?? this.connectionConfig.requestTimeoutMs\n\n const controller = new AbortController()\n\n const reqTimeout = requestTimeoutMs\n ? setTimeout(() => {\n controller.abort()\n }, requestTimeoutMs)\n : undefined\n\n const events = this.rpc.watchDir(\n {\n path,\n recursive: opts?.recursive ?? this.defaultWatchRecursive,\n },\n {\n headers: {\n ...authenticationHeader(opts?.user),\n [KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString(),\n },\n signal: controller.signal,\n timeoutMs: opts?.timeoutMs ?? this.defaultWatchTimeout,\n }\n )\n\n try {\n await handleWatchDirStartEvent(events)\n\n clearTimeout(reqTimeout)\n\n return new WatchHandle(\n () => controller.abort(),\n events,\n onEvent,\n opts?.onExit\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n}\n","import createClient, { FetchResponse } from 'openapi-fetch'\n\nimport type { components, paths } from './schema.gen'\nimport { ConnectionConfig } from '../connectionConfig'\nimport { createApiLogger } from '../logs'\nimport {\n SandboxError,\n InvalidArgumentError,\n NotFoundError,\n NotEnoughSpaceError,\n formatSandboxTimeoutError,\n AuthenticationError,\n} from '../errors'\nimport { StartResponse, ConnectResponse } from './process/process_pb'\nimport { Code, ConnectError } from '@connectrpc/connect'\nimport { WatchDirResponse } from './filesystem/filesystem_pb'\n\nexport async function handleEnvdApiError<A, B, C extends `${string}/${string}`>(\n res: FetchResponse<A, B, C>\n) {\n if (!res.error) {\n return\n }\n\n const message: string =\n typeof res.error == 'string'\n ? res.error\n : res.error?.message || (await res.response.text())\n\n switch (res.response.status) {\n case 400:\n return new InvalidArgumentError(message)\n case 401:\n return new AuthenticationError(message)\n case 404:\n return new NotFoundError(message)\n case 429:\n return new SandboxError(\n `${res.response.status}: ${message}: The requests are being rate limited.`\n )\n case 502:\n return formatSandboxTimeoutError(message)\n case 507:\n return new NotEnoughSpaceError(message)\n default:\n return new SandboxError(`${res.response.status}: ${message}`)\n }\n}\n\nexport async function handleProcessStartEvent(\n events: AsyncIterable<StartResponse | ConnectResponse>\n) {\n let startEvent: StartResponse | ConnectResponse\n\n try {\n startEvent = (await events[Symbol.asyncIterator]().next()).value\n } catch (err) {\n if (err instanceof ConnectError) {\n if (err.code === Code.Unavailable) {\n throw new NotFoundError('Sandbox is probably not running anymore')\n }\n }\n\n throw err\n }\n if (startEvent.event?.event.case !== 'start') {\n throw new Error('Expected start event')\n }\n\n return startEvent.event.event.value.pid\n}\n\nexport async function handleWatchDirStartEvent(\n events: AsyncIterable<WatchDirResponse>\n) {\n let startEvent: WatchDirResponse\n\n try {\n startEvent = (await events[Symbol.asyncIterator]().next()).value\n } catch (err) {\n if (err instanceof ConnectError) {\n if (err.code === Code.Unavailable) {\n throw new NotFoundError('Sandbox is probably not running anymore')\n }\n }\n\n throw err\n }\n if (startEvent.event?.case !== 'start') {\n throw new Error('Expected start event')\n }\n\n return startEvent.event.value\n}\n\nclass EnvdApiClient {\n readonly api: ReturnType<typeof createClient<paths>>\n readonly version: string | undefined\n\n constructor(\n config: Pick<ConnectionConfig, 'apiUrl' | 'logger' | 'accessToken'> & { fetch?: (request: Request) => ReturnType<typeof fetch>, headers?: Record<string, string> },\n metadata: {\n version?: string\n },\n ) {\n this.api = createClient({\n baseUrl: config.apiUrl,\n fetch: config?.fetch,\n headers: config?.headers,\n // keepalive: true, // TODO: Return keepalive\n })\n this.version = metadata.version\n\n if (config.logger) {\n this.api.use(createApiLogger(config.logger))\n }\n }\n}\n\nexport type { components, paths }\nexport { EnvdApiClient }\n","import { Code, ConnectError } from '@connectrpc/connect'\nimport { runtime } from '../api/metadata'\nimport { defaultUsername } from '../connectionConfig'\n\nimport { SandboxError, TimeoutError, formatSandboxTimeoutError, InvalidArgumentError, NotFoundError, AuthenticationError } from '../errors'\n\n\nexport function handleRpcError(err: unknown): Error {\n if (err instanceof ConnectError) {\n switch (err.code) {\n case Code.InvalidArgument:\n return new InvalidArgumentError(err.message)\n case Code.Unauthenticated:\n return new AuthenticationError(err.message)\n case Code.NotFound:\n return new NotFoundError(err.message)\n case Code.Unavailable:\n return formatSandboxTimeoutError(err.message)\n case Code.Canceled:\n return new TimeoutError(\n `${err.message}: This error is likely due to exceeding 'requestTimeoutMs'. You can pass the request timeout value as an option when making the request.`\n )\n case Code.DeadlineExceeded:\n return new TimeoutError(\n `${err.message}: This error is likely due to exceeding 'timeoutMs' — the total time a long running request (like command execution or directory watch) can be active. It can be modified by passing 'timeoutMs' when making the request. Use '0' to disable the timeout.`\n )\n default:\n return new SandboxError(`${err.code}: ${err.message}`)\n }\n }\n\n return err as Error\n}\n\nfunction encode64(value: string): string {\n switch (runtime) {\n case 'deno':\n return btoa(value)\n case 'node':\n return Buffer.from(value).toString('base64')\n case 'bun':\n return Buffer.from(value).toString('base64')\n default:\n return btoa(value)\n }\n}\n\nexport function authenticationHeader(username?: string): Record<string, string> {\n const value = `${username || defaultUsername}:`\n\n const encoded = encode64(value)\n\n return { 'Authorization': `Basic ${encoded}` }\n}\n","// @generated by protoc-gen-es v2.6.2 with parameter \"target=ts\"\n// @generated from file filesystem/filesystem.proto (package filesystem, syntax proto3)\n/* eslint-disable */\n\nimport type { GenEnum, GenFile, GenMessage, GenService } from \"@bufbuild/protobuf/codegenv2\";\nimport { enumDesc, fileDesc, messageDesc, serviceDesc } from \"@bufbuild/protobuf/codegenv2\";\nimport type { Timestamp } from \"@bufbuild/protobuf/wkt\";\nimport { file_google_protobuf_timestamp } from \"@bufbuild/protobuf/wkt\";\nimport type { Message } from \"@bufbuild/protobuf\";\n\n/**\n * Describes the file filesystem/filesystem.proto.\n */\nexport const file_filesystem_filesystem: GenFile = /*@__PURE__*/\n fileDesc(\"ChtmaWxlc3lzdGVtL2ZpbGVzeXN0ZW0ucHJvdG8SCmZpbGVzeXN0ZW0iMgoLTW92ZVJlcXVlc3QSDgoGc291cmNlGAEgASgJEhMKC2Rlc3RpbmF0aW9uGAIgASgJIjQKDE1vdmVSZXNwb25zZRIkCgVlbnRyeRgBIAEoCzIVLmZpbGVzeXN0ZW0uRW50cnlJbmZvIh4KDk1ha2VEaXJSZXF1ZXN0EgwKBHBhdGgYASABKAkiNwoPTWFrZURpclJlc3BvbnNlEiQKBWVudHJ5GAEgASgLMhUuZmlsZXN5c3RlbS5FbnRyeUluZm8iHQoNUmVtb3ZlUmVxdWVzdBIMCgRwYXRoGAEgASgJIhAKDlJlbW92ZVJlc3BvbnNlIhsKC1N0YXRSZXF1ZXN0EgwKBHBhdGgYASABKAkiNAoMU3RhdFJlc3BvbnNlEiQKBWVudHJ5GAEgASgLMhUuZmlsZXN5c3RlbS5FbnRyeUluZm8i/QEKCUVudHJ5SW5mbxIMCgRuYW1lGAEgASgJEiIKBHR5cGUYAiABKA4yFC5maWxlc3lzdGVtLkZpbGVUeXBlEgwKBHBhdGgYAyABKAkSDAoEc2l6ZRgEIAEoAxIMCgRtb2RlGAUgASgNEhMKC3Blcm1pc3Npb25zGAYgASgJEg0KBW93bmVyGAcgASgJEg0KBWdyb3VwGAggASgJEjEKDW1vZGlmaWVkX3RpbWUYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhsKDnN5bWxpbmtfdGFyZ2V0GAogASgJSACIAQFCEQoPX3N5bWxpbmtfdGFyZ2V0Ii0KDkxpc3REaXJSZXF1ZXN0EgwKBHBhdGgYASABKAkSDQoFZGVwdGgYAiABKA0iOQoPTGlzdERpclJlc3BvbnNlEiYKB2VudHJpZXMYASADKAsyFS5maWxlc3lzdGVtLkVudHJ5SW5mbyIyCg9XYXRjaERpclJlcXVlc3QSDAoEcGF0aBgBIAEoCRIRCglyZWN1cnNpdmUYAiABKAgiRAoPRmlsZXN5c3RlbUV2ZW50EgwKBG5hbWUYASABKAkSIwoEdHlwZRgCIAEoDjIVLmZpbGVzeXN0ZW0uRXZlbnRUeXBlIuABChBXYXRjaERpclJlc3BvbnNlEjgKBXN0YXJ0GAEgASgLMicuZmlsZXN5c3RlbS5XYXRjaERpclJlc3BvbnNlLlN0YXJ0RXZlbnRIABIxCgpmaWxlc3lzdGVtGAIgASgLMhsuZmlsZXN5c3RlbS5GaWxlc3lzdGVtRXZlbnRIABI7CglrZWVwYWxpdmUYAyABKAsyJi5maWxlc3lzdGVtLldhdGNoRGlyUmVzcG9uc2UuS2VlcEFsaXZlSAAaDAoKU3RhcnRFdmVudBoLCglLZWVwQWxpdmVCBwoFZXZlbnQiNwoUQ3JlYXRlV2F0Y2hlclJlcXVlc3QSDAoEcGF0aBgBIAEoCRIRCglyZWN1cnNpdmUYAiABKAgiKwoVQ3JlYXRlV2F0Y2hlclJlc3BvbnNlEhIKCndhdGNoZXJfaWQYASABKAkiLQoXR2V0V2F0Y2hlckV2ZW50c1JlcXVlc3QSEgoKd2F0Y2hlcl9pZBgBIAEoCSJHChhHZXRXYXRjaGVyRXZlbnRzUmVzcG9uc2USKwoGZXZlbnRzGAEgAygLMhsuZmlsZXN5c3RlbS5GaWxlc3lzdGVtRXZlbnQiKgoUUmVtb3ZlV2F0Y2hlclJlcXVlc3QSEgoKd2F0Y2hlcl9pZBgBIAEoCSIXChVSZW1vdmVXYXRjaGVyUmVzcG9uc2UqUgoIRmlsZVR5cGUSGQoVRklMRV9UWVBFX1VOU1BFQ0lGSUVEEAASEgoORklMRV9UWVBFX0ZJTEUQARIXChNGSUxFX1RZUEVfRElSRUNUT1JZEAIqmAEKCUV2ZW50VHlwZRIaChZFVkVOVF9UWVBFX1VOU1BFQ0lGSUVEEAASFQoRRVZFTlRfVFlQRV9DUkVBVEUQARIUChBFVkVOVF9UWVBFX1dSSVRFEAISFQoRRVZFTlRfVFlQRV9SRU1PVkUQAxIVChFFVkVOVF9UWVBFX1JFTkFNRRAEEhQKEEVWRU5UX1RZUEVfQ0hNT0QQBTKfBQoKRmlsZXN5c3RlbRI5CgRTdGF0EhcuZmlsZXN5c3RlbS5TdGF0UmVxdWVzdBoYLmZpbGVzeXN0ZW0uU3RhdFJlc3BvbnNlEkIKB01ha2VEaXISGi5maWxlc3lzdGVtLk1ha2VEaXJSZXF1ZXN0GhsuZmlsZXN5c3RlbS5NYWtlRGlyUmVzcG9uc2USOQoETW92ZRIXLmZpbGVzeXN0ZW0uTW92ZVJlcXVlc3QaGC5maWxlc3lzdGVtLk1vdmVSZXNwb25zZRJCCgdMaXN0RGlyEhouZmlsZXN5c3RlbS5MaXN0RGlyUmVxdWVzdBobLmZpbGVzeXN0ZW0uTGlzdERpclJlc3BvbnNlEj8KBlJlbW92ZRIZLmZpbGVzeXN0ZW0uUmVtb3ZlUmVxdWVzdBoaLmZpbGVzeXN0ZW0uUmVtb3ZlUmVzcG9uc2USRwoIV2F0Y2hEaXISGy5maWxlc3lzdGVtLldhdGNoRGlyUmVxdWVzdBocLmZpbGVzeXN0ZW0uV2F0Y2hEaXJSZXNwb25zZTABElQKDUNyZWF0ZVdhdGNoZXISIC5maWxlc3lzdGVtLkNyZWF0ZVdhdGNoZXJSZXF1ZXN0GiEuZmlsZXN5c3RlbS5DcmVhdGVXYXRjaGVyUmVzcG9uc2USXQoQR2V0V2F0Y2hlckV2ZW50cxIjLmZpbGVzeXN0ZW0uR2V0V2F0Y2hlckV2ZW50c1JlcXVlc3QaJC5maWxlc3lzdGVtLkdldFdhdGNoZXJFdmVudHNSZXNwb25zZRJUCg1SZW1vdmVXYXRjaGVyEiAuZmlsZXN5c3RlbS5SZW1vdmVXYXRjaGVyUmVxdWVzdBohLmZpbGVzeXN0ZW0uUmVtb3ZlV2F0Y2hlclJlc3BvbnNlQmkKDmNvbS5maWxlc3lzdGVtQg9GaWxlc3lzdGVtUHJvdG9QAaICA0ZYWKoCCkZpbGVzeXN0ZW3KAgpGaWxlc3lzdGVt4gIWRmlsZXN5c3RlbVxHUEJNZXRhZGF0YeoCCkZpbGVzeXN0ZW1iBnByb3RvMw\", [file_google_protobuf_timestamp]);\n\n/**\n * @generated from message filesystem.MoveRequest\n */\nexport type MoveRequest = Message<\"filesystem.MoveRequest\"> & {\n /**\n * @generated from field: string source = 1;\n */\n source: string;\n\n /**\n * @generated from field: string destination = 2;\n */\n destination: string;\n};\n\n/**\n * Describes the message filesystem.MoveRequest.\n * Use `create(MoveRequestSchema)` to create a new message.\n */\nexport const MoveRequestSchema: GenMessage<MoveRequest> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 0);\n\n/**\n * @generated from message filesystem.MoveResponse\n */\nexport type MoveResponse = Message<\"filesystem.MoveResponse\"> & {\n /**\n * @generated from field: filesystem.EntryInfo entry = 1;\n */\n entry?: EntryInfo;\n};\n\n/**\n * Describes the message filesystem.MoveResponse.\n * Use `create(MoveResponseSchema)` to create a new message.\n */\nexport const MoveResponseSchema: GenMessage<MoveResponse> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 1);\n\n/**\n * @generated from message filesystem.MakeDirRequest\n */\nexport type MakeDirRequest = Message<\"filesystem.MakeDirRequest\"> & {\n /**\n * @generated from field: string path = 1;\n */\n path: string;\n};\n\n/**\n * Describes the message filesystem.MakeDirRequest.\n * Use `create(MakeDirRequestSchema)` to create a new message.\n */\nexport const MakeDirRequestSchema: GenMessage<MakeDirRequest> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 2);\n\n/**\n * @generated from message filesystem.MakeDirResponse\n */\nexport type MakeDirResponse = Message<\"filesystem.MakeDirResponse\"> & {\n /**\n * @generated from field: filesystem.EntryInfo entry = 1;\n */\n entry?: EntryInfo;\n};\n\n/**\n * Describes the message filesystem.MakeDirResponse.\n * Use `create(MakeDirResponseSchema)` to create a new message.\n */\nexport const MakeDirResponseSchema: GenMessage<MakeDirResponse> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 3);\n\n/**\n * @generated from message filesystem.RemoveRequest\n */\nexport type RemoveRequest = Message<\"filesystem.RemoveRequest\"> & {\n /**\n * @generated from field: string path = 1;\n */\n path: string;\n};\n\n/**\n * Describes the message filesystem.RemoveRequest.\n * Use `create(RemoveRequestSchema)` to create a new message.\n */\nexport const RemoveRequestSchema: GenMessage<RemoveRequest> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 4);\n\n/**\n * @generated from message filesystem.RemoveResponse\n */\nexport type RemoveResponse = Message<\"filesystem.RemoveResponse\"> & {\n};\n\n/**\n * Describes the message filesystem.RemoveResponse.\n * Use `create(RemoveResponseSchema)` to create a new message.\n */\nexport const RemoveResponseSchema: GenMessage<RemoveResponse> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 5);\n\n/**\n * @generated from message filesystem.StatRequest\n */\nexport type StatRequest = Message<\"filesystem.StatRequest\"> & {\n /**\n * @generated from field: string path = 1;\n */\n path: string;\n};\n\n/**\n * Describes the message filesystem.StatRequest.\n * Use `create(StatRequestSchema)` to create a new message.\n */\nexport const StatRequestSchema: GenMessage<StatRequest> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 6);\n\n/**\n * @generated from message filesystem.StatResponse\n */\nexport type StatResponse = Message<\"filesystem.StatResponse\"> & {\n /**\n * @generated from field: filesystem.EntryInfo entry = 1;\n */\n entry?: EntryInfo;\n};\n\n/**\n * Describes the message filesystem.StatResponse.\n * Use `create(StatResponseSchema)` to create a new message.\n */\nexport const StatResponseSchema: GenMessage<StatResponse> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 7);\n\n/**\n * @generated from message filesystem.EntryInfo\n */\nexport type EntryInfo = Message<\"filesystem.EntryInfo\"> & {\n /**\n * @generated from field: string name = 1;\n */\n name: string;\n\n /**\n * @generated from field: filesystem.FileType type = 2;\n */\n type: FileType;\n\n /**\n * @generated from field: string path = 3;\n */\n path: string;\n\n /**\n * @generated from field: int64 size = 4;\n */\n size: bigint;\n\n /**\n * @generated from field: uint32 mode = 5;\n */\n mode: number;\n\n /**\n * @generated from field: string permissions = 6;\n */\n permissions: string;\n\n /**\n * @generated from field: string owner = 7;\n */\n owner: string;\n\n /**\n * @generated from field: string group = 8;\n */\n group: string;\n\n /**\n * @generated from field: google.protobuf.Timestamp modified_time = 9;\n */\n modifiedTime?: Timestamp;\n\n /**\n * If the entry is a symlink, this field contains the target of the symlink.\n *\n * @generated from field: optional string symlink_target = 10;\n */\n symlinkTarget?: string;\n};\n\n/**\n * Describes the message filesystem.EntryInfo.\n * Use `create(EntryInfoSchema)` to create a new message.\n */\nexport const EntryInfoSchema: GenMessage<EntryInfo> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 8);\n\n/**\n * @generated from message filesystem.ListDirRequest\n */\nexport type ListDirRequest = Message<\"filesystem.ListDirRequest\"> & {\n /**\n * @generated from field: string path = 1;\n */\n path: string;\n\n /**\n * @generated from field: uint32 depth = 2;\n */\n depth: number;\n};\n\n/**\n * Describes the message filesystem.ListDirRequest.\n * Use `create(ListDirRequestSchema)` to create a new message.\n */\nexport const ListDirRequestSchema: GenMessage<ListDirRequest> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 9);\n\n/**\n * @generated from message filesystem.ListDirResponse\n */\nexport type ListDirResponse = Message<\"filesystem.ListDirResponse\"> & {\n /**\n * @generated from field: repeated filesystem.EntryInfo entries = 1;\n */\n entries: EntryInfo[];\n};\n\n/**\n * Describes the message filesystem.ListDirResponse.\n * Use `create(ListDirResponseSchema)` to create a new message.\n */\nexport const ListDirResponseSchema: GenMessage<ListDirResponse> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 10);\n\n/**\n * @generated from message filesystem.WatchDirRequest\n */\nexport type WatchDirRequest = Message<\"filesystem.WatchDirRequest\"> & {\n /**\n * @generated from field: string path = 1;\n */\n path: string;\n\n /**\n * @generated from field: bool recursive = 2;\n */\n recursive: boolean;\n};\n\n/**\n * Describes the message filesystem.WatchDirRequest.\n * Use `create(WatchDirRequestSchema)` to create a new message.\n */\nexport const WatchDirRequestSchema: GenMessage<WatchDirRequest> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 11);\n\n/**\n * @generated from message filesystem.FilesystemEvent\n */\nexport type FilesystemEvent = Message<\"filesystem.FilesystemEvent\"> & {\n /**\n * @generated from field: string name = 1;\n */\n name: string;\n\n /**\n * @generated from field: filesystem.EventType type = 2;\n */\n type: EventType;\n};\n\n/**\n * Describes the message filesystem.FilesystemEvent.\n * Use `create(FilesystemEventSchema)` to create a new message.\n */\nexport const FilesystemEventSchema: GenMessage<FilesystemEvent> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 12);\n\n/**\n * @generated from message filesystem.WatchDirResponse\n */\nexport type WatchDirResponse = Message<\"filesystem.WatchDirResponse\"> & {\n /**\n * @generated from oneof filesystem.WatchDirResponse.event\n */\n event: {\n /**\n * @generated from field: filesystem.WatchDirResponse.StartEvent start = 1;\n */\n value: WatchDirResponse_StartEvent;\n case: \"start\";\n } | {\n /**\n * @generated from field: filesystem.FilesystemEvent filesystem = 2;\n */\n value: FilesystemEvent;\n case: \"filesystem\";\n } | {\n /**\n * @generated from field: filesystem.WatchDirResponse.KeepAlive keepalive = 3;\n */\n value: WatchDirResponse_KeepAlive;\n case: \"keepalive\";\n } | { case: undefined; value?: undefined };\n};\n\n/**\n * Describes the message filesystem.WatchDirResponse.\n * Use `create(WatchDirResponseSchema)` to create a new message.\n */\nexport const WatchDirResponseSchema: GenMessage<WatchDirResponse> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 13);\n\n/**\n * @generated from message filesystem.WatchDirResponse.StartEvent\n */\nexport type WatchDirResponse_StartEvent = Message<\"filesystem.WatchDirResponse.StartEvent\"> & {\n};\n\n/**\n * Describes the message filesystem.WatchDirResponse.StartEvent.\n * Use `create(WatchDirResponse_StartEventSchema)` to create a new message.\n */\nexport const WatchDirResponse_StartEventSchema: GenMessage<WatchDirResponse_StartEvent> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 13, 0);\n\n/**\n * @generated from message filesystem.WatchDirResponse.KeepAlive\n */\nexport type WatchDirResponse_KeepAlive = Message<\"filesystem.WatchDirResponse.KeepAlive\"> & {\n};\n\n/**\n * Describes the message filesystem.WatchDirResponse.KeepAlive.\n * Use `create(WatchDirResponse_KeepAliveSchema)` to create a new message.\n */\nexport const WatchDirResponse_KeepAliveSchema: GenMessage<WatchDirResponse_KeepAlive> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 13, 1);\n\n/**\n * @generated from message filesystem.CreateWatcherRequest\n */\nexport type CreateWatcherRequest = Message<\"filesystem.CreateWatcherRequest\"> & {\n /**\n * @generated from field: string path = 1;\n */\n path: string;\n\n /**\n * @generated from field: bool recursive = 2;\n */\n recursive: boolean;\n};\n\n/**\n * Describes the message filesystem.CreateWatcherRequest.\n * Use `create(CreateWatcherRequestSchema)` to create a new message.\n */\nexport const CreateWatcherRequestSchema: GenMessage<CreateWatcherRequest> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 14);\n\n/**\n * @generated from message filesystem.CreateWatcherResponse\n */\nexport type CreateWatcherResponse = Message<\"filesystem.CreateWatcherResponse\"> & {\n /**\n * @generated from field: string watcher_id = 1;\n */\n watcherId: string;\n};\n\n/**\n * Describes the message filesystem.CreateWatcherResponse.\n * Use `create(CreateWatcherResponseSchema)` to create a new message.\n */\nexport const CreateWatcherResponseSchema: GenMessage<CreateWatcherResponse> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 15);\n\n/**\n * @generated from message filesystem.GetWatcherEventsRequest\n */\nexport type GetWatcherEventsRequest = Message<\"filesystem.GetWatcherEventsRequest\"> & {\n /**\n * @generated from field: string watcher_id = 1;\n */\n watcherId: string;\n};\n\n/**\n * Describes the message filesystem.GetWatcherEventsRequest.\n * Use `create(GetWatcherEventsRequestSchema)` to create a new message.\n */\nexport const GetWatcherEventsRequestSchema: GenMessage<GetWatcherEventsRequest> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 16);\n\n/**\n * @generated from message filesystem.GetWatcherEventsResponse\n */\nexport type GetWatcherEventsResponse = Message<\"filesystem.GetWatcherEventsResponse\"> & {\n /**\n * @generated from field: repeated filesystem.FilesystemEvent events = 1;\n */\n events: FilesystemEvent[];\n};\n\n/**\n * Describes the message filesystem.GetWatcherEventsResponse.\n * Use `create(GetWatcherEventsResponseSchema)` to create a new message.\n */\nexport const GetWatcherEventsResponseSchema: GenMessage<GetWatcherEventsResponse> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 17);\n\n/**\n * @generated from message filesystem.RemoveWatcherRequest\n */\nexport type RemoveWatcherRequest = Message<\"filesystem.RemoveWatcherRequest\"> & {\n /**\n * @generated from field: string watcher_id = 1;\n */\n watcherId: string;\n};\n\n/**\n * Describes the message filesystem.RemoveWatcherRequest.\n * Use `create(RemoveWatcherRequestSchema)` to create a new message.\n */\nexport const RemoveWatcherRequestSchema: GenMessage<RemoveWatcherRequest> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 18);\n\n/**\n * @generated from message filesystem.RemoveWatcherResponse\n */\nexport type RemoveWatcherResponse = Message<\"filesystem.RemoveWatcherResponse\"> & {\n};\n\n/**\n * Describes the message filesystem.RemoveWatcherResponse.\n * Use `create(RemoveWatcherResponseSchema)` to create a new message.\n */\nexport const RemoveWatcherResponseSchema: GenMessage<RemoveWatcherResponse> = /*@__PURE__*/\n messageDesc(file_filesystem_filesystem, 19);\n\n/**\n * @generated from enum filesystem.FileType\n */\nexport enum FileType {\n /**\n * @generated from enum value: FILE_TYPE_UNSPECIFIED = 0;\n */\n UNSPECIFIED = 0,\n\n /**\n * @generated from enum value: FILE_TYPE_FILE = 1;\n */\n FILE = 1,\n\n /**\n * @generated from enum value: FILE_TYPE_DIRECTORY = 2;\n */\n DIRECTORY = 2,\n}\n\n/**\n * Describes the enum filesystem.FileType.\n */\nexport const FileTypeSchema: GenEnum<FileType> = /*@__PURE__*/\n enumDesc(file_filesystem_filesystem, 0);\n\n/**\n * @generated from enum filesystem.EventType\n */\nexport enum EventType {\n /**\n * @generated from enum value: EVENT_TYPE_UNSPECIFIED = 0;\n */\n UNSPECIFIED = 0,\n\n /**\n * @generated from enum value: EVENT_TYPE_CREATE = 1;\n */\n CREATE = 1,\n\n /**\n * @generated from enum value: EVENT_TYPE_WRITE = 2;\n */\n WRITE = 2,\n\n /**\n * @generated from enum value: EVENT_TYPE_REMOVE = 3;\n */\n REMOVE = 3,\n\n /**\n * @generated from enum value: EVENT_TYPE_RENAME = 4;\n */\n RENAME = 4,\n\n /**\n * @generated from enum value: EVENT_TYPE_CHMOD = 5;\n */\n CHMOD = 5,\n}\n\n/**\n * Describes the enum filesystem.EventType.\n */\nexport const EventTypeSchema: GenEnum<EventType> = /*@__PURE__*/\n enumDesc(file_filesystem_filesystem, 1);\n\n/**\n * @generated from service filesystem.Filesystem\n */\nexport const Filesystem: GenService<{\n /**\n * @generated from rpc filesystem.Filesystem.Stat\n */\n stat: {\n methodKind: \"unary\";\n input: typeof StatRequestSchema;\n output: typeof StatResponseSchema;\n },\n /**\n * @generated from rpc filesystem.Filesystem.MakeDir\n */\n makeDir: {\n methodKind: \"unary\";\n input: typeof MakeDirRequestSchema;\n output: typeof MakeDirResponseSchema;\n },\n /**\n * @generated from rpc filesystem.Filesystem.Move\n */\n move: {\n methodKind: \"unary\";\n input: typeof MoveRequestSchema;\n output: typeof MoveResponseSchema;\n },\n /**\n * @generated from rpc filesystem.Filesystem.ListDir\n */\n listDir: {\n methodKind: \"unary\";\n input: typeof ListDirRequestSchema;\n output: typeof ListDirResponseSchema;\n },\n /**\n * @generated from rpc filesystem.Filesystem.Remove\n */\n remove: {\n methodKind: \"unary\";\n input: typeof RemoveRequestSchema;\n output: typeof RemoveResponseSchema;\n },\n /**\n * @generated from rpc filesystem.Filesystem.WatchDir\n */\n watchDir: {\n methodKind: \"server_streaming\";\n input: typeof WatchDirRequestSchema;\n output: typeof WatchDirResponseSchema;\n },\n /**\n * Non-streaming versions of WatchDir\n *\n * @generated from rpc filesystem.Filesystem.CreateWatcher\n */\n createWatcher: {\n methodKind: \"unary\";\n input: typeof CreateWatcherRequestSchema;\n output: typeof CreateWatcherResponseSchema;\n },\n /**\n * @generated from rpc filesystem.Filesystem.GetWatcherEvents\n */\n getWatcherEvents: {\n methodKind: \"unary\";\n input: typeof GetWatcherEventsRequestSchema;\n output: typeof GetWatcherEventsResponseSchema;\n },\n /**\n * @generated from rpc filesystem.Filesystem.RemoveWatcher\n */\n removeWatcher: {\n methodKind: \"unary\";\n input: typeof RemoveWatcherRequestSchema;\n output: typeof RemoveWatcherResponseSchema;\n },\n}> = /*@__PURE__*/\n serviceDesc(file_filesystem_filesystem, 0);\n\n","import { handleRpcError } from '../../envd/rpc'\nimport {\n EventType,\n WatchDirResponse,\n} from '../../envd/filesystem/filesystem_pb'\n\n/**\n * Sandbox filesystem event types.\n */\nexport enum FilesystemEventType {\n /**\n * Filesystem object permissions were changed.\n */\n CHMOD = 'chmod',\n /**\n * Filesystem object was created.\n */\n CREATE = 'create',\n /**\n * Filesystem object was removed.\n */\n REMOVE = 'remove',\n /**\n * Filesystem object was renamed.\n */\n RENAME = 'rename',\n /**\n * Filesystem object was written to.\n */\n WRITE = 'write',\n}\n\nfunction mapEventType(type: EventType) {\n switch (type) {\n case EventType.CHMOD:\n return FilesystemEventType.CHMOD\n case EventType.CREATE:\n return FilesystemEventType.CREATE\n case EventType.REMOVE:\n return FilesystemEventType.REMOVE\n case EventType.RENAME:\n return FilesystemEventType.RENAME\n case EventType.WRITE:\n return FilesystemEventType.WRITE\n }\n}\n\n/**\n * Information about a filesystem event.\n */\nexport interface FilesystemEvent {\n /**\n * Relative path to the filesystem object.\n */\n name: string\n /**\n * Filesystem operation event type.\n */\n type: FilesystemEventType\n}\n\n/**\n * Handle for watching a directory in the sandbox filesystem.\n *\n * Use {@link WatchHandle.stop} to stop watching the directory.\n */\nexport class WatchHandle {\n constructor(\n private readonly handleStop: () => void,\n private readonly events: AsyncIterable<WatchDirResponse>,\n private readonly onEvent?: (event: FilesystemEvent) => void | Promise<void>,\n private readonly onExit?: (err?: Error) => void | Promise<void>\n ) {\n this.handleEvents()\n }\n\n /**\n * Stop watching the directory.\n */\n async stop() {\n this.handleStop()\n }\n\n private async *iterateEvents() {\n try {\n for await (const event of this.events) {\n switch (event.event.case) {\n case 'filesystem':\n yield event.event\n break\n }\n }\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n private async handleEvents() {\n try {\n for await (const event of this.iterateEvents()) {\n const eventType = mapEventType(event.value.type)\n if (eventType === undefined) {\n continue\n }\n\n this.onEvent?.({\n name: event.value.name,\n type: eventType,\n })\n }\n this.onExit?.()\n } catch (err) {\n this.onExit?.(err as Error)\n }\n }\n}\n","export const ENVD_VERSION_RECURSIVE_WATCH = '0.1.4'","import { handleRpcError } from '../../envd/rpc'\nimport { SandboxError } from '../../errors'\nimport { ConnectResponse, StartResponse } from '../../envd/process/process_pb'\n\ndeclare const __brand: unique symbol\ntype Brand<B> = { [__brand]: B }\nexport type Branded<T, B> = T & Brand<B>\n\nexport type Stdout = Branded<string, 'stdout'>\nexport type Stderr = Branded<string, 'stderr'>\nexport type PtyOutput = Branded<Uint8Array, 'pty'>\n\n/**\n * Command execution result.\n */\nexport interface CommandResult {\n /**\n * Command execution exit code.\n * `0` if the command finished successfully.\n */\n exitCode: number\n /**\n * Error message from command execution if it failed.\n */\n error?: string\n /**\n * Command stdout output.\n */\n stdout: string\n /**\n * Command stderr output.\n */\n stderr: string\n}\n\n/**\n * Error thrown when a command exits with a non-zero exit code.\n */\nexport class CommandExitError extends SandboxError implements CommandResult {\n constructor(private readonly result: CommandResult) {\n super(result.error)\n this.name = 'CommandExitError'\n }\n\n /**\n * Command execution exit code.\n * `0` if the command finished successfully.\n */\n get exitCode() {\n return this.result.exitCode\n }\n\n /**\n * Error message from command execution.\n */\n get error() {\n return this.result.error\n }\n\n /**\n * Command execution stdout output.\n */\n get stdout() {\n return this.result.stdout\n }\n\n /**\n * Command execution stderr output.\n */\n get stderr() {\n return this.result.stderr\n }\n}\n\n/**\n * Command execution handle.\n *\n * It provides methods for waiting for the command to finish, retrieving stdout/stderr, and killing the command.\n *\n * @property {number} pid process ID of the command.\n */\nexport class CommandHandle\n implements\n Omit<CommandResult, 'exitCode' | 'error'>,\n Partial<Pick<CommandResult, 'exitCode' | 'error'>>\n{\n private _stdout = ''\n private _stderr = ''\n\n private result?: CommandResult\n private iterationError?: Error\n\n private readonly _wait: Promise<void>\n\n /**\n * @hidden\n * @internal\n * @access protected\n */\n constructor(\n readonly pid: number,\n private readonly handleDisconnect: () => void,\n private readonly handleKill: () => Promise<boolean>,\n private readonly events: AsyncIterable<ConnectResponse | StartResponse>,\n private readonly onStdout?: (stdout: string) => void | Promise<void>,\n private readonly onStderr?: (stderr: string) => void | Promise<void>,\n private readonly onPty?: (pty: Uint8Array) => void | Promise<void>\n ) {\n this._wait = this.handleEvents()\n }\n\n /**\n * Command execution exit code.\n * `0` if the command finished successfully.\n * \n * It is `undefined` if the command is still running.\n */\n get exitCode() {\n return this.result?.exitCode\n }\n\n /**\n * Error message from command execution.\n */\n get error() {\n return this.result?.error\n }\n\n /**\n * Command execution stderr output.\n */\n get stderr() {\n return this._stderr\n }\n\n /**\n * Command execution stdout output.\n */\n get stdout() {\n return this._stdout\n }\n\n /**\n * Wait for the command to finish and return the result.\n * If the command exits with a non-zero exit code, it throws a `CommandExitError`.\n * \n * @returns `CommandResult` result of command execution.\n */\n async wait() {\n await this._wait\n\n if (this.iterationError) {\n throw this.iterationError\n }\n\n if (!this.result) {\n throw new SandboxError('Process exited without a result')\n }\n\n if (this.result.exitCode !== 0) {\n throw new CommandExitError(this.result)\n }\n\n return this.result\n }\n\n /**\n * Disconnect from the command.\n * \n * The command is not killed, but SDK stops receiving events from the command.\n * You can reconnect to the command using {@link Commands.connect}.\n */\n async disconnect() {\n this.handleDisconnect()\n }\n\n /**\n * Kill the command.\n * It uses `SIGKILL` signal to kill the command.\n * \n * @returns `true` if the command was killed successfully, `false` if the command was not found.\n */\n async kill() {\n return await this.handleKill()\n }\n\n private async *iterateEvents(): AsyncGenerator<\n [Stdout, null, null] | [null, Stderr, null] | [null, null, PtyOutput]\n > {\n for await (const event of this.events) {\n const e = event?.event?.event\n let out: string | undefined\n\n switch (e?.case) {\n case 'data':\n switch (e.value.output.case) {\n case 'stdout':\n out = new TextDecoder().decode(e.value.output.value)\n this._stdout += out\n yield [out as Stdout, null, null]\n break\n case 'stderr':\n out = new TextDecoder().decode(e.value.output.value)\n this._stderr += out\n yield [null, out as Stderr, null]\n break\n case 'pty':\n yield [null, null, e.value.output.value as PtyOutput]\n break\n }\n break\n case 'end':\n this.result = {\n exitCode: e.value.exitCode,\n error: e.value.error,\n stdout: this.stdout,\n stderr: this.stderr,\n }\n break\n }\n // TODO: Handle empty events like in python SDK\n }\n }\n\n private async handleEvents() {\n try {\n for await (const [stdout, stderr, pty] of this.iterateEvents()) {\n if (stdout !== null) {\n this.onStdout?.(stdout)\n } else if (stderr !== null) {\n this.onStderr?.(stderr)\n } else if (pty) {\n this.onPty?.(pty)\n }\n }\n } catch (e) {\n this.iterationError = handleRpcError(e)\n }\n }\n}\n","import { ApiClient, components, handleApiError } from '../api'\nimport { ConnectionConfig } from '../connectionConfig'\nimport { Template } from '../sandbox/sandboxApi'\n\n/**\n * Options for request to the Template API.\n */\nexport interface TemplateApiOpts {\n /**\n * API key for authentication.\n */\n apiKey?: string\n\n /**\n * Custom headers to be sent with the request.\n */\n headers?: Record<string, string>\n\n /**\n * Enable debug mode.\n */\n debug?: boolean\n\n /**\n * Custom domain for the API.\n */\n domain?: string\n\n /**\n * Request timeout in milliseconds.\n */\n requestTimeoutMs?: number\n}\n\n/**\n * Options for listing templates.\n */\nexport interface TemplateListOpts extends TemplateApiOpts {\n /**\n * Filter templates by type.\n * - \"template_build\": Include only original templates built from Dockerfile (default)\n * - \"snapshot_template\": Include only templates generated from snapshots/commits\n *\n * @default \"template_build\"\n */\n templateType?: 'template_build' | 'snapshot_template'\n\n /**\n * Page number (1-based).\n *\n * @default 1\n */\n page?: number\n\n /**\n * Number of items per page (max 100).\n *\n * @default 20\n */\n limit?: number\n}\n\n/**\n * Paginated response for template list.\n */\nexport interface PaginatedTemplatesResponse {\n /**\n * List of templates for the current page.\n */\n templates: Template[]\n\n /**\n * Current page number (1-based).\n */\n page: number\n\n /**\n * Number of items per page.\n */\n limit: number\n\n /**\n * Total number of templates.\n */\n total: number\n\n /**\n * Total number of pages.\n */\n totalPages: number\n}\n\n/**\n * Template API class for managing sandbox templates.\n */\nexport class TemplateApi {\n protected constructor() {}\n\n /**\n * List templates with pagination support (user's default team only).\n *\n * @param opts template list options.\n *\n * @returns paginated template list response.\n *\n * @example\n * ```ts\n * const response = await TemplateApi.listTemplates({\n * templateType: 'snapshot_template',\n * page: 1,\n * limit: 20,\n * })\n * console.log('Total templates:', response.total)\n * console.log('Templates:', response.templates)\n * ```\n */\n static async listTemplates(\n opts?: TemplateListOpts\n ): Promise<PaginatedTemplatesResponse> {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.GET('/v2/templates', {\n params: {\n query: {\n template_type: opts?.templateType,\n page: opts?.page,\n limit: opts?.limit,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n if (!res.data) {\n throw new Error('Template list response data is missing')\n }\n\n // Transform the response data\n const templates = (res.data.templates || []).map(\n (t: components['schemas']['Template']) => ({\n templateId: t.templateID,\n aliases: t.aliases,\n buildCount: t.buildCount,\n buildId: t.buildID,\n cpuCount: t.cpuCount,\n createdAt: new Date(t.createdAt),\n createdBy: t.createdBy,\n diskSizeMB: t.diskSizeMB,\n envdVersion: t.envdVersion,\n lastSpawnedAt: new Date(t.lastSpawnedAt),\n memoryMB: t.memoryMB,\n metadata: t.metadata,\n public: t.public,\n spawnCount: t.spawnCount,\n templateType: t.templateType,\n originSandboxID: t.originSandboxID,\n updatedAt: new Date(t.updatedAt),\n })\n )\n\n return {\n templates,\n page: res.data.page,\n limit: res.data.limit,\n total: res.data.total,\n totalPages: res.data.totalPages,\n }\n }\n\n /**\n * Delete a template by its ID.\n *\n * @param templateId template ID to delete.\n * @param opts API options.\n *\n * @returns `true` if the template was deleted successfully.\n *\n * @example\n * ```ts\n * await TemplateApi.deleteTemplate('template-id')\n * console.log('Template deleted successfully')\n * ```\n */\n static async deleteTemplate(\n templateId: string,\n opts?: TemplateApiOpts\n ): Promise<boolean> {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.DELETE('/templates/{templateID}', {\n params: {\n path: {\n templateID: templateId,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n // 204 No Content response indicates successful deletion\n return res.response.status === 204\n }\n}\n\n/**\n * Paginator for listing templates with pagination support.\n *\n * @example\n * ```ts\n * const paginator = new TemplatePaginator({ templateType: 'snapshot_template' })\n *\n * while (paginator.hasNext) {\n * const response = await paginator.nextPage()\n * console.log('Page:', response.page, 'of', response.totalPages)\n * console.log('Templates:', response.templates)\n * }\n * ```\n */\nexport class TemplatePaginator {\n private _hasNext: boolean\n private _currentPage: number\n private _totalPages?: number\n\n private readonly config: ConnectionConfig\n private client: ApiClient\n\n private readonly templateType?: 'template_build' | 'snapshot_template'\n private readonly limit: number\n\n constructor(opts?: TemplateListOpts) {\n this.config = new ConnectionConfig(opts)\n this.client = new ApiClient(this.config)\n\n this._hasNext = true\n this._currentPage = (opts?.page ?? 1) - 1 // Store 0-based internally\n this._totalPages = undefined\n\n this.templateType = opts?.templateType\n this.limit = opts?.limit ?? 20\n }\n\n /**\n * Returns true if there are more pages to fetch.\n */\n get hasNext(): boolean {\n return this._hasNext\n }\n\n /**\n * Returns the current page number (1-based).\n */\n get currentPage(): number {\n return this._currentPage + 1\n }\n\n /**\n * Returns the total number of pages (if known).\n */\n get totalPages(): number | undefined {\n return this._totalPages\n }\n\n /**\n * Get the next page of templates.\n *\n * @throws Error if there are no more pages to fetch. Call this method only if `hasNext` is `true`.\n *\n * @returns Paginated template list response.\n */\n async nextPage(): Promise<PaginatedTemplatesResponse> {\n if (!this.hasNext) {\n throw new Error('No more pages to fetch')\n }\n\n this._currentPage++\n\n const res = await this.client.api.GET('/v2/templates', {\n params: {\n query: {\n template_type: this.templateType,\n page: this._currentPage + 1, // API expects 1-based page\n limit: this.limit,\n },\n },\n signal: this.config.getSignal(),\n })\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n if (!res.data) {\n throw new Error('Template list response data is missing')\n }\n\n this._totalPages = res.data.totalPages\n this._hasNext = this._currentPage + 1 < res.data.totalPages\n\n // Transform the response data\n const templates = (res.data.templates || []).map(\n (t: components['schemas']['Template']) => ({\n templateId: t.templateID,\n aliases: t.aliases,\n buildCount: t.buildCount,\n buildId: t.buildID,\n cpuCount: t.cpuCount,\n createdAt: new Date(t.createdAt),\n createdBy: t.createdBy,\n diskSizeMB: t.diskSizeMB,\n envdVersion: t.envdVersion,\n lastSpawnedAt: new Date(t.lastSpawnedAt),\n memoryMB: t.memoryMB,\n metadata: t.metadata,\n public: t.public,\n spawnCount: t.spawnCount,\n templateType: t.templateType,\n originSandboxID: t.originSandboxID,\n updatedAt: new Date(t.updatedAt),\n })\n )\n\n return {\n templates,\n page: res.data.page,\n limit: res.data.limit,\n total: res.data.total,\n totalPages: res.data.totalPages,\n }\n }\n\n /**\n * Reset the paginator to the first page.\n */\n reset(): void {\n this._currentPage = 0\n this._hasNext = true\n this._totalPages = undefined\n }\n}\n\n","import { createConnectTransport } from '@connectrpc/connect-web';\n\nimport {\n ConnectionConfig,\n ConnectionOpts,\n DEFAULT_SANDBOX_TIMEOUT_MS,\n defaultUsername,\n Username,\n} from '../connectionConfig';\nimport { EnvdApiClient, handleEnvdApiError } from '../envd/api';\nimport { createRpcLogger } from '../logs';\nimport { Commands, Pty } from './commands';\nimport { Filesystem } from './filesystem';\nimport {\n SandboxApi,\n SandboxBetaCreateOpts,\n SandboxCloneOpts,\n SandboxCommitOpts,\n SandboxConnectOpts,\n SandboxListOpts,\n SandboxMetricsOpts,\n SandboxOpts,\n SandboxResetOpts,\n SandboxPaginator,\n Template,\n CloneResult,\n} from './sandboxApi';\nimport { getSignature } from './signature';\nimport { compareVersions } from 'compare-versions';\nimport { SandboxError } from '../errors';\n\n/**\n * Options for sandbox upload/download URL generation.\n */\nexport interface SandboxUrlOpts {\n /**\n * Use signature expiration for the URL.\n * Optional parameter to set the expiration time for the signature in seconds.\n */\n useSignatureExpiration?: number\n\n /**\n * User that will be used to access the file.\n */\n user?: Username\n}\n\n/**\n * PPIO agent sandbox is a secure and isolated cloud environment.\n *\n * The sandbox allows you to:\n * - Access Linux OS\n * - Create, list, and delete files and directories\n * - Run commands\n * - Run isolated code\n * - Access the internet\n *\n * Check docs [here](https://ppio.com/docs/sandbox/overview).\n *\n * Use {@link Sandbox.create} to create a new sandbox.\n *\n * @example\n * ```ts\n * import { Sandbox } from '@ppio-sandbox/core'\n *\n * const sandbox = await Sandbox.create()\n * ```\n */\nexport class Sandbox extends SandboxApi {\n protected static readonly defaultTemplate: string = 'base'\n protected static readonly defaultSandboxTimeoutMs = DEFAULT_SANDBOX_TIMEOUT_MS\n\n /**\n * Module for interacting with the sandbox filesystem\n */\n readonly files: Filesystem\n /**\n * Module for running commands in the sandbox\n */\n readonly commands: Commands\n /**\n * Module for interacting with the sandbox pseudo-terminals\n */\n readonly pty: Pty\n\n /**\n * Unique identifier of the sandbox.\n */\n readonly sandboxId: string\n\n /**\n * Domain where the sandbox is hosted.\n */\n readonly sandboxDomain: string\n\n protected readonly envdPort = 49983\n\n protected readonly connectionConfig: ConnectionConfig\n protected readonly envdAccessToken?: string\n private readonly envdApiUrl: string\n private readonly envdApi: EnvdApiClient\n\n /**\n * Use {@link Sandbox.create} to create a new Sandbox instead.\n *\n * @hidden\n * @hide\n * @internal\n * @access protected\n */\n constructor(\n opts: SandboxConnectOpts & {\n sandboxId: string\n sandboxDomain?: string\n envdVersion?: string\n envdAccessToken?: string\n }\n ) {\n super()\n\n this.connectionConfig = new ConnectionConfig(opts)\n\n this.sandboxId = opts.sandboxId\n this.sandboxDomain = opts.sandboxDomain ?? this.connectionConfig.domain\n\n this.envdAccessToken = opts.envdAccessToken\n this.envdApiUrl = `${\n this.connectionConfig.debug ? 'http' : 'https'\n }://${this.getHost(this.envdPort)}`\n\n const rpcTransport = createConnectTransport({\n baseUrl: this.envdApiUrl,\n useBinaryFormat: false,\n interceptors: opts?.logger ? [createRpcLogger(opts.logger)] : undefined,\n fetch: (url, options) => {\n // Patch fetch to always use redirect: \"follow\"\n // connect-web doesn't allow to configure redirect option - https://github.com/connectrpc/connect-es/pull/1082\n // connect-web package uses redirect: \"error\" which is not supported in edge runtimes\n\n const headers = new Headers(this.connectionConfig.headers)\n new Headers(options?.headers).forEach((value, key) =>\n headers.append(key, value)\n )\n\n if (this.envdAccessToken) {\n headers.append('X-Access-Token', this.envdAccessToken)\n }\n\n options = {\n ...(options ?? {}),\n headers: headers,\n redirect: 'follow',\n }\n\n return fetch(url, options)\n },\n })\n\n this.envdApi = new EnvdApiClient(\n {\n apiUrl: this.envdApiUrl,\n logger: opts?.logger,\n accessToken: this.envdAccessToken,\n headers: this.envdAccessToken\n ? { 'X-Access-Token': this.envdAccessToken }\n : {},\n },\n {\n version: opts?.envdVersion,\n }\n )\n this.files = new Filesystem(\n rpcTransport,\n this.envdApi,\n this.connectionConfig\n )\n this.commands = new Commands(rpcTransport, this.connectionConfig)\n this.pty = new Pty(rpcTransport, this.connectionConfig)\n }\n\n /**\n * List all sandboxes.\n *\n * @param opts connection options.\n *\n * @returns paginator for listing sandboxes.\n */\n static list(opts?: SandboxListOpts): SandboxPaginator {\n return new SandboxPaginator(opts)\n }\n\n /**\n * Create a new sandbox from the default `base` sandbox template.\n *\n * @param opts connection options.\n *\n * @returns sandbox instance for the new sandbox.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * ```\n * @constructs {@link Sandbox}\n */\n static async create<S extends typeof Sandbox>(\n this: S,\n opts?: SandboxOpts\n ): Promise<InstanceType<S>>\n\n /**\n * Create a new sandbox from the specified sandbox template.\n *\n * @param template sandbox template name or ID.\n * @param opts connection options.\n *\n * @returns sandbox instance for the new sandbox.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create('<template-name-or-id>')\n * ```\n * @constructs {@link Sandbox}\n */\n static async create<S extends typeof Sandbox>(\n this: S,\n template: string,\n opts?: SandboxOpts\n ): Promise<InstanceType<S>>\n static async create<S extends typeof Sandbox>(\n this: S,\n templateOrOpts?: SandboxOpts | string,\n opts?: SandboxOpts\n ): Promise<InstanceType<S>> {\n const { template, sandboxOpts } =\n typeof templateOrOpts === 'string'\n ? { template: templateOrOpts, sandboxOpts: opts }\n : { template: this.defaultTemplate, sandboxOpts: templateOrOpts }\n\n const config = new ConnectionConfig(sandboxOpts)\n if (config.debug) {\n return new this({\n sandboxId: 'debug_sandbox_id',\n ...config,\n }) as InstanceType<S>\n }\n\n const sandbox = await SandboxApi.createSandbox(\n template,\n sandboxOpts?.timeoutMs ?? this.defaultSandboxTimeoutMs,\n sandboxOpts\n )\n\n return new this({ ...sandbox, ...config }) as InstanceType<S>\n }\n\n /**\n * @beta This feature is in beta and may change in the future.\n *\n * Create a new sandbox from the default `base` sandbox template.\n *\n * @param opts connection options.\n *\n * @returns sandbox instance for the new sandbox.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.betaCreate()\n * ```\n * @constructs {@link Sandbox}\n */\n static async betaCreate<S extends typeof Sandbox>(\n this: S,\n opts?: SandboxBetaCreateOpts\n ): Promise<InstanceType<S>>\n\n /**\n * @beta This feature is in beta and may change in the future.\n *\n * Create a new sandbox from the specified sandbox template.\n *\n * @param template sandbox template name or ID.\n * @param opts connection options.\n *\n * @returns sandbox instance for the new sandbox.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.betaCreate('<template-name-or-id>')\n * ```\n * @constructs {@link Sandbox}\n */\n static async betaCreate<S extends typeof Sandbox>(\n this: S,\n template: string,\n opts?: SandboxBetaCreateOpts\n ): Promise<InstanceType<S>>\n static async betaCreate<S extends typeof Sandbox>(\n this: S,\n templateOrOpts?: SandboxBetaCreateOpts | string,\n opts?: SandboxBetaCreateOpts\n ): Promise<InstanceType<S>> {\n const { template, sandboxOpts } =\n typeof templateOrOpts === 'string'\n ? { template: templateOrOpts, sandboxOpts: opts }\n : { template: this.defaultTemplate, sandboxOpts: templateOrOpts }\n\n const config = new ConnectionConfig(sandboxOpts)\n if (config.debug) {\n return new this({\n sandboxId: 'debug_sandbox_id',\n ...config,\n }) as InstanceType<S>\n }\n\n const sandbox = await SandboxApi.createSandbox(\n template,\n sandboxOpts?.timeoutMs ?? this.defaultSandboxTimeoutMs,\n sandboxOpts\n )\n\n return new this({ ...sandbox, ...config }) as InstanceType<S>\n }\n\n /**\n * Connect to a sandbox. If the sandbox is paused, it will be automatically resumed.\n * Sandbox must be either running or be paused.\n *\n * With sandbox ID you can connect to the same sandbox from different places or environments (serverless functions, etc).\n *\n * @param sandboxId sandbox ID.\n * @param opts connection options.\n *\n * @returns A running sandbox instance\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * const sandboxId = sandbox.sandboxId\n *\n * // Connect to the same sandbox.\n * const sameSandbox = await Sandbox.connect(sandboxId)\n * ```\n */\n static async connect<S extends typeof Sandbox>(\n this: S,\n sandboxId: string,\n opts?: SandboxConnectOpts\n ): Promise<InstanceType<S>> {\n const info = await SandboxApi.connectSandbox(sandboxId, opts)\n\n const config = new ConnectionConfig(opts)\n\n return new this({\n sandboxId: info.sandboxId,\n sandboxDomain: info.sandboxDomain,\n envdAccessToken: info.envdAccessToken,\n envdVersion: info.envdVersion,\n ...config,\n }) as InstanceType<S>\n }\n\n /**\n * Clone a sandbox to create multiple identical sandboxes.\n *\n * @param sandboxId sandbox ID.\n * @param count number of sandboxes to clone.\n * @param opts clone options.\n *\n * @returns clone response with count and list of cloned sandboxes.\n *\n * @example\n * ```ts\n * const cloneResponse = await Sandbox.clone('sandbox-id', {\n * count: 3,\n * strict: false\n * })\n * console.log(`Cloned ${cloneResponse.count} sandboxes`)\n * ```\n */\n static async clone<S extends typeof Sandbox>(\n this: S,\n sandboxId: string,\n opts: SandboxCloneOpts\n ): Promise<CloneResult<InstanceType<S>>> {\n // Note: timeout behavior is handled by backend when `opts.timeoutMs` is not provided:\n // - If parent sandbox is running: inherit parent sandbox timeout\n // - If parent sandbox is paused: default to 15 seconds\n const res = await SandboxApi.cloneSandboxes(sandboxId, opts)\n\n const instances = res.sandboxes.map((sb) => {\n const config = new ConnectionConfig(opts)\n return new this({\n sandboxId: sb.sandboxId,\n envdVersion: sb.envdVersion,\n envdAccessToken: sb.envdAccessToken,\n ...config,\n }) as InstanceType<S>\n })\n\n return {\n count: res.count,\n snapshotTemplateId: res.snapshotTemplateId,\n sandboxes: instances,\n }\n }\n\n /**\n * Reset sandbox memory and optionally resume the sandbox.\n */\n static async reset(\n sandboxId: string,\n opts?: SandboxResetOpts\n ): Promise<boolean> {\n return await SandboxApi.reset(sandboxId, opts)\n }\n\n /**\n * Connect to a sandbox. If the sandbox is paused, it will be automatically resumed.\n * Sandbox must be either running or be paused.\n *\n * With sandbox ID you can connect to the same sandbox from different places or environments (serverless functions, etc).\n *\n * @param opts connection options.\n *\n * @returns A running sandbox instance\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * await sandbox.betaPause()\n *\n * // Connect to the same sandbox.\n * const sameSandbox = await sandbox.connect()\n * ```\n */\n async connect(opts?: SandboxBetaCreateOpts): Promise<this> {\n await SandboxApi.connectSandbox(this.sandboxId, opts)\n\n return this\n }\n\n /**\n * Get the host address for the specified sandbox port.\n * You can then use this address to connect to the sandbox port from outside the sandbox via HTTP or WebSocket.\n *\n * @param port number of the port in the sandbox.\n *\n * @returns host address of the sandbox port.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * // Start an HTTP server\n * await sandbox.commands.exec('python3 -m http.server 3000')\n * // Get the hostname of the HTTP server\n * const serverURL = sandbox.getHost(3000)\n * ```\n */\n getHost(port: number) {\n if (this.connectionConfig.debug) {\n return `localhost:${port}`\n }\n\n return `${port}-${this.sandboxId}.${this.sandboxDomain}`\n }\n\n /**\n * Check if the sandbox is running.\n *\n * @returns `true` if the sandbox is running, `false` otherwise.\n *\n * @example\n * ```ts\n * const sandbox = await Sandbox.create()\n * await sandbox.isRunning() // Returns true\n *\n * await sandbox.kill()\n * await sandbox.isRunning() // Returns false\n * ```\n */\n async isRunning(\n opts?: Pick<ConnectionOpts, 'requestTimeoutMs'>\n ): Promise<boolean> {\n const signal = this.connectionConfig.getSignal(opts?.requestTimeoutMs)\n\n const res = await this.envdApi.api.GET('/health', {\n signal,\n })\n\n if (res.response.status == 502) {\n return false\n }\n\n const err = await handleEnvdApiError(res)\n if (err) {\n throw err\n }\n\n return true\n }\n\n /**\n * Set the timeout of the sandbox.\n * After the timeout expires the sandbox will be automatically killed.\n *\n * This method can extend or reduce the sandbox timeout set when creating the sandbox or from the last call to `.setTimeout`.\n * Maximum time a sandbox can be kept alive is 24 hours (86_400_000 milliseconds) for Pro users and 1 hour (3_600_000 milliseconds) for Hobby users.\n *\n * @param timeoutMs timeout in **milliseconds**.\n * @param opts connection options.\n */\n async setTimeout(\n timeoutMs: number,\n opts?: Pick<SandboxOpts, 'requestTimeoutMs'>\n ) {\n if (this.connectionConfig.debug) {\n // Skip timeout in debug mode\n return\n }\n\n await SandboxApi.setTimeout(this.sandboxId, timeoutMs, {\n ...this.connectionConfig,\n ...opts,\n })\n }\n\n /**\n * Kill the sandbox.\n *\n * @param opts connection options.\n */\n async kill(opts?: Pick<SandboxOpts, 'requestTimeoutMs'>) {\n if (this.connectionConfig.debug) {\n // Skip killing in debug mode\n return\n }\n\n await SandboxApi.kill(this.sandboxId, { ...this.connectionConfig, ...opts })\n }\n\n /**\n * @beta This feature is in beta and may change in the future.\n *\n * Pause a sandbox by its ID.\n *\n * @param opts connection options.\n *\n * @returns sandbox ID that can be used to resume the sandbox.\n */\n async betaPause(opts?: ConnectionOpts): Promise<boolean> {\n return await SandboxApi.betaPause(this.sandboxId, opts)\n }\n\n /**\n * Reset sandbox memory and optionally resume the sandbox.\n */\n async reset(opts?: SandboxResetOpts): Promise<boolean> {\n return await SandboxApi.reset(this.sandboxId, opts)\n }\n\n /**\n * Commit the sandbox to create a template snapshot.\n *\n * This creates a snapshot of the current sandbox state that can be used as a template to create new sandboxes.\n *\n * @param opts commit options including optional alias for the template.\n *\n * @returns template information.\n *\n * @example\n * ```ts\n * const template = await sandbox.commit({ alias: 'my-custom-template' })\n * console.log('Created template:', template.templateId)\n * ```\n */\n async commit(opts?: SandboxCommitOpts): Promise<Template> {\n return await SandboxApi.commit(this.sandboxId, {\n ...this.connectionConfig,\n ...opts,\n })\n }\n\n\n /**\n * Get the URL to upload a file to the sandbox.\n *\n * You have to send a POST request to this URL with the file as multipart/form-data.\n *\n * @param path path to the file in the sandbox.\n *\n * @param opts download url options.\n *\n * @returns URL for uploading file.\n */\n async uploadUrl(path?: string, opts?: SandboxUrlOpts) {\n opts = opts ?? {}\n\n const useSignature = !!this.envdAccessToken\n\n if (!useSignature && opts.useSignatureExpiration != undefined) {\n throw new Error(\n 'Signature expiration can be used only when sandbox is created as secured.'\n )\n }\n\n const username = opts.user ?? defaultUsername\n const filePath = path ?? ''\n const fileUrl = this.fileUrl(filePath, username)\n\n if (useSignature) {\n const url = new URL(fileUrl)\n const sig = await getSignature({\n path: filePath,\n operation: 'write',\n user: username,\n expirationInSeconds: opts.useSignatureExpiration,\n envdAccessToken: this.envdAccessToken,\n })\n\n url.searchParams.set('signature', sig.signature)\n if (sig.expiration) {\n url.searchParams.set('signature_expiration', sig.expiration.toString())\n }\n\n return url.toString()\n }\n\n return fileUrl\n }\n\n /**\n * Get the URL to download a file from the sandbox.\n *\n * @param path path to the file in the sandbox.\n *\n * @param opts download url options.\n *\n * @returns URL for downloading file.\n */\n async downloadUrl(path: string, opts?: SandboxUrlOpts) {\n opts = opts ?? {}\n\n const useSignature = !!this.envdAccessToken\n\n if (!useSignature && opts.useSignatureExpiration != undefined) {\n throw new Error(\n 'Signature expiration can be used only when sandbox is created as secured.'\n )\n }\n\n const username = opts.user ?? defaultUsername\n const fileUrl = this.fileUrl(path, username)\n\n if (useSignature) {\n const url = new URL(fileUrl)\n const sig = await getSignature({\n path,\n operation: 'read',\n user: username,\n expirationInSeconds: opts.useSignatureExpiration,\n envdAccessToken: this.envdAccessToken,\n })\n\n url.searchParams.set('signature', sig.signature)\n if (sig.expiration) {\n url.searchParams.set('signature_expiration', sig.expiration.toString())\n }\n\n return url.toString()\n }\n\n return fileUrl\n }\n\n /**\n * Get sandbox information like sandbox ID, template, metadata, started at/end at date.\n *\n * @param opts connection options.\n *\n * @returns information about the sandbox\n */\n async getInfo(opts?: Pick<SandboxOpts, 'requestTimeoutMs'>) {\n return await SandboxApi.getInfo(this.sandboxId, {\n ...this.connectionConfig,\n ...opts,\n })\n }\n\n /**\n * Get the metrics of the sandbox.\n *\n * @param opts connection options.\n *\n * @returns List of sandbox metrics containing CPU, memory and disk usage information.\n */\n async getMetrics(opts?: SandboxMetricsOpts) {\n if (this.envdApi.version) {\n if (compareVersions(this.envdApi.version, '0.1.5') < 0) {\n throw new SandboxError(\n 'You need to update the template to use the new SDK. ' +\n 'You can do this by running `ppio-sandbox-cli template build` in the directory with the template.'\n )\n }\n\n if (compareVersions(this.envdApi.version, '0.2.4') < 0) {\n this.connectionConfig.logger?.warn?.(\n 'Disk metrics are not supported in this version of the sandbox, please rebuild the template to get disk metrics.'\n )\n }\n }\n\n return await SandboxApi.getMetrics(this.sandboxId, {\n ...this.connectionConfig,\n ...opts,\n })\n }\n\n private fileUrl(path?: string, username?: string) {\n const url = new URL('/files', this.envdApiUrl)\n\n url.searchParams.set('username', username ?? defaultUsername)\n if (path) {\n url.searchParams.set('path', path)\n }\n\n return url.toString()\n }\n}\n","import {\n Code,\n ConnectError,\n createClient,\n Client,\n Transport,\n} from '@connectrpc/connect'\n\nimport {\n Signal,\n Process as ProcessService,\n} from '../../envd/process/process_pb'\nimport {\n ConnectionConfig,\n Username,\n ConnectionOpts,\n KEEPALIVE_PING_INTERVAL_SEC,\n KEEPALIVE_PING_HEADER,\n} from '../../connectionConfig'\nimport { authenticationHeader, handleRpcError } from '../../envd/rpc'\nimport { CommandResult, CommandHandle } from './commandHandle'\nimport { handleProcessStartEvent } from '../../envd/api'\nexport { Pty } from './pty'\n\n/**\n * Options for sending a command request.\n */\nexport interface CommandRequestOpts\n extends Partial<Pick<ConnectionOpts, 'requestTimeoutMs'>> {}\n\n/**\n * Options for starting a new command.\n */\nexport interface CommandStartOpts extends CommandRequestOpts {\n /**\n * If true, starts command in the background and the method returns immediately.\n * You can use {@link CommandHandle.wait} to wait for the command to finish.\n */\n background?: boolean\n /**\n * Working directory for the command.\n *\n * @default // home directory of the user used to start the command\n */\n cwd?: string\n /**\n * User to run the command as.\n *\n * @default `user`\n */\n user?: Username\n /**\n * Environment variables used for the command.\n *\n * This overrides the default environment variables from `Sandbox` constructor.\n *\n * @default `{}`\n */\n envs?: Record<string, string>\n /**\n * Callback for command stdout output.\n */\n onStdout?: (data: string) => void | Promise<void>\n /**\n * Callback for command stderr output.\n */\n onStderr?: (data: string) => void | Promise<void>\n /**\n * Timeout for the command in **milliseconds**.\n *\n * @default 60_000 // 60 seconds\n */\n timeoutMs?: number\n}\n\n/**\n * Options for connecting to a command.\n */\nexport type CommandConnectOpts = Pick<\n CommandStartOpts,\n 'onStderr' | 'onStdout' | 'timeoutMs'\n> &\n CommandRequestOpts\n\n/**\n * Information about a command, PTY session or start command running in the sandbox as process.\n */\nexport interface ProcessInfo {\n /**\n * Process ID.\n */\n pid: number\n /**\n * Custom tag used for identifying special commands like start command in the custom template.\n */\n tag?: string\n /**\n * Command that was executed.\n */\n cmd: string\n /**\n * Command arguments.\n */\n args: string[]\n /**\n * Environment variables used for the command.\n */\n envs: Record<string, string>\n /**\n * Executed command working directory.\n */\n cwd?: string\n}\n\n/**\n * Module for starting and interacting with commands in the sandbox.\n */\nexport class Commands {\n protected readonly rpc: Client<typeof ProcessService>\n\n private readonly defaultProcessConnectionTimeout = 60_000 // 60 seconds\n\n constructor(\n transport: Transport,\n private readonly connectionConfig: ConnectionConfig\n ) {\n this.rpc = createClient(ProcessService, transport)\n }\n\n /**\n * List all running commands and PTY sessions.\n *\n * @param opts connection options.\n *\n * @returns list of running commands and PTY sessions.\n */\n async list(opts?: CommandRequestOpts): Promise<ProcessInfo[]> {\n try {\n const res = await this.rpc.list(\n {},\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n return res.processes.map((p) => ({\n pid: p.pid,\n ...(p.tag && { tag: p.tag }),\n args: p.config!.args,\n envs: p.config!.envs,\n cmd: p.config!.cmd,\n ...(p.config!.cwd && { cwd: p.config!.cwd }),\n }))\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Send data to command stdin.\n *\n * @param pid process ID of the command. You can get the list of running commands using {@link Commands.list}.\n * @param data data to send to the command.\n * @param opts connection options.\n */\n async sendStdin(\n pid: number,\n data: string,\n opts?: CommandRequestOpts\n ): Promise<void> {\n try {\n await this.rpc.sendInput(\n {\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n input: {\n input: {\n case: 'stdin',\n value: new TextEncoder().encode(data),\n },\n },\n },\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Kill a running command specified by its process ID.\n * It uses `SIGKILL` signal to kill the command.\n *\n * @param pid process ID of the command. You can get the list of running commands using {@link Commands.list}.\n * @param opts connection options.\n *\n * @returns `true` if the command was killed, `false` if the command was not found.\n */\n async kill(pid: number, opts?: CommandRequestOpts): Promise<boolean> {\n try {\n await this.rpc.sendSignal(\n {\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n signal: Signal.SIGKILL,\n },\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n return true\n } catch (err) {\n if (err instanceof ConnectError) {\n if (err.code === Code.NotFound) {\n return false\n }\n }\n\n throw handleRpcError(err)\n }\n }\n\n /**\n * Connect to a running command.\n * You can use {@link CommandHandle.wait} to wait for the command to finish and get execution results.\n *\n * @param pid process ID of the command to connect to. You can get the list of running commands using {@link Commands.list}.\n * @param opts connection options.\n *\n * @returns `CommandHandle` handle to interact with the running command.\n */\n async connect(\n pid: number,\n opts?: CommandConnectOpts\n ): Promise<CommandHandle> {\n const requestTimeoutMs =\n opts?.requestTimeoutMs ?? this.connectionConfig.requestTimeoutMs\n\n const controller = new AbortController()\n\n const reqTimeout = requestTimeoutMs\n ? setTimeout(() => {\n controller.abort()\n }, requestTimeoutMs)\n : undefined\n\n const events = this.rpc.connect(\n {\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n },\n {\n signal: controller.signal,\n headers: {\n [KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString(),\n },\n timeoutMs: opts?.timeoutMs ?? this.defaultProcessConnectionTimeout,\n }\n )\n\n try {\n const pid = await handleProcessStartEvent(events)\n\n clearTimeout(reqTimeout)\n\n return new CommandHandle(\n pid,\n () => controller.abort(),\n () => this.kill(pid),\n events,\n opts?.onStdout,\n opts?.onStderr,\n undefined\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Start a new command and wait until it finishes executing.\n *\n * @param cmd command to execute.\n * @param opts options for starting the command.\n *\n * @returns `CommandResult` result of the command execution.\n */\n async run(\n cmd: string,\n opts?: CommandStartOpts & { background?: false }\n ): Promise<CommandResult>\n\n /**\n * Start a new command in the background.\n * You can use {@link CommandHandle.wait} to wait for the command to finish and get its result.\n *\n * @param cmd command to execute.\n * @param opts options for starting the command\n *\n * @returns `CommandHandle` handle to interact with the running command.\n */\n async run(\n cmd: string,\n opts: CommandStartOpts & { background: true }\n ): Promise<CommandHandle>\n\n // NOTE - The following overload seems redundant, but it's required to make the type inference work correctly.\n\n /**\n * Start a new command.\n *\n * @param cmd command to execute.\n * @param opts options for starting the command.\n * - `opts.background: true` - runs in background, returns `CommandHandle`\n * - `opts.background: false | undefined` - waits for completion, returns `CommandResult`\n *\n * @returns Either a `CommandHandle` or a `CommandResult` (depending on `opts.background`).\n */\n async run(\n cmd: string,\n opts?: CommandStartOpts & { background?: boolean }\n ): Promise<CommandHandle | CommandResult>\n async run(\n cmd: string,\n opts?: CommandStartOpts & { background?: boolean }\n ): Promise<CommandHandle | CommandResult> {\n const proc = await this.start(cmd, opts)\n\n return opts?.background ? proc : proc.wait()\n }\n\n private async start(\n cmd: string,\n opts?: CommandStartOpts\n ): Promise<CommandHandle> {\n const requestTimeoutMs =\n opts?.requestTimeoutMs ?? this.connectionConfig.requestTimeoutMs\n\n const controller = new AbortController()\n\n const reqTimeout = requestTimeoutMs\n ? setTimeout(() => {\n controller.abort()\n }, requestTimeoutMs)\n : undefined\n\n const events = this.rpc.start(\n {\n process: {\n cmd: '/bin/bash',\n cwd: opts?.cwd,\n envs: opts?.envs,\n args: ['-l', '-c', cmd],\n },\n },\n {\n headers: {\n ...authenticationHeader(opts?.user),\n [KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString(),\n },\n signal: controller.signal,\n timeoutMs: opts?.timeoutMs ?? this.defaultProcessConnectionTimeout,\n }\n )\n\n try {\n const pid = await handleProcessStartEvent(events)\n\n clearTimeout(reqTimeout)\n\n return new CommandHandle(\n pid,\n () => controller.abort(),\n () => this.kill(pid),\n events,\n opts?.onStdout,\n opts?.onStderr,\n undefined\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n}\n","// @generated by protoc-gen-es v2.6.2 with parameter \"target=ts\"\n// @generated from file process/process.proto (package process, syntax proto3)\n/* eslint-disable */\n\nimport type { GenEnum, GenFile, GenMessage, GenService } from \"@bufbuild/protobuf/codegenv2\";\nimport { enumDesc, fileDesc, messageDesc, serviceDesc } from \"@bufbuild/protobuf/codegenv2\";\nimport type { Message } from \"@bufbuild/protobuf\";\n\n/**\n * Describes the file process/process.proto.\n */\nexport const file_process_process: GenFile = /*@__PURE__*/\n fileDesc(\"ChVwcm9jZXNzL3Byb2Nlc3MucHJvdG8SB3Byb2Nlc3MiSgoDUFRZEh8KBHNpemUYASABKAsyES5wcm9jZXNzLlBUWS5TaXplGiIKBFNpemUSDAoEY29scxgBIAEoDRIMCgRyb3dzGAIgASgNIqEBCg1Qcm9jZXNzQ29uZmlnEgsKA2NtZBgBIAEoCRIMCgRhcmdzGAIgAygJEi4KBGVudnMYAyADKAsyIC5wcm9jZXNzLlByb2Nlc3NDb25maWcuRW52c0VudHJ5EhAKA2N3ZBgEIAEoCUgAiAEBGisKCUVudnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBQgYKBF9jd2QiDQoLTGlzdFJlcXVlc3QiXAoLUHJvY2Vzc0luZm8SJgoGY29uZmlnGAEgASgLMhYucHJvY2Vzcy5Qcm9jZXNzQ29uZmlnEgsKA3BpZBgCIAEoDRIQCgN0YWcYAyABKAlIAIgBAUIGCgRfdGFnIjcKDExpc3RSZXNwb25zZRInCglwcm9jZXNzZXMYASADKAsyFC5wcm9jZXNzLlByb2Nlc3NJbmZvInkKDFN0YXJ0UmVxdWVzdBInCgdwcm9jZXNzGAEgASgLMhYucHJvY2Vzcy5Qcm9jZXNzQ29uZmlnEh4KA3B0eRgCIAEoCzIMLnByb2Nlc3MuUFRZSACIAQESEAoDdGFnGAMgASgJSAGIAQFCBgoEX3B0eUIGCgRfdGFnImIKDVVwZGF0ZVJlcXVlc3QSKQoHcHJvY2VzcxgBIAEoCzIYLnByb2Nlc3MuUHJvY2Vzc1NlbGVjdG9yEh4KA3B0eRgCIAEoCzIMLnByb2Nlc3MuUFRZSACIAQFCBgoEX3B0eSIQCg5VcGRhdGVSZXNwb25zZSKvAwoMUHJvY2Vzc0V2ZW50EjEKBXN0YXJ0GAEgASgLMiAucHJvY2Vzcy5Qcm9jZXNzRXZlbnQuU3RhcnRFdmVudEgAEi8KBGRhdGEYAiABKAsyHy5wcm9jZXNzLlByb2Nlc3NFdmVudC5EYXRhRXZlbnRIABItCgNlbmQYAyABKAsyHi5wcm9jZXNzLlByb2Nlc3NFdmVudC5FbmRFdmVudEgAEjQKCWtlZXBhbGl2ZRgEIAEoCzIfLnByb2Nlc3MuUHJvY2Vzc0V2ZW50LktlZXBBbGl2ZUgAGhkKClN0YXJ0RXZlbnQSCwoDcGlkGAEgASgNGkgKCURhdGFFdmVudBIQCgZzdGRvdXQYASABKAxIABIQCgZzdGRlcnIYAiABKAxIABINCgNwdHkYAyABKAxIAEIICgZvdXRwdXQaWwoIRW5kRXZlbnQSEQoJZXhpdF9jb2RlGAEgASgREg4KBmV4aXRlZBgCIAEoCBIOCgZzdGF0dXMYAyABKAkSEgoFZXJyb3IYBCABKAlIAIgBAUIICgZfZXJyb3IaCwoJS2VlcEFsaXZlQgcKBWV2ZW50IjUKDVN0YXJ0UmVzcG9uc2USJAoFZXZlbnQYASABKAsyFS5wcm9jZXNzLlByb2Nlc3NFdmVudCI3Cg9Db25uZWN0UmVzcG9uc2USJAoFZXZlbnQYASABKAsyFS5wcm9jZXNzLlByb2Nlc3NFdmVudCJjChBTZW5kSW5wdXRSZXF1ZXN0EikKB3Byb2Nlc3MYASABKAsyGC5wcm9jZXNzLlByb2Nlc3NTZWxlY3RvchIkCgVpbnB1dBgCIAEoCzIVLnByb2Nlc3MuUHJvY2Vzc0lucHV0IhMKEVNlbmRJbnB1dFJlc3BvbnNlIjcKDFByb2Nlc3NJbnB1dBIPCgVzdGRpbhgBIAEoDEgAEg0KA3B0eRgCIAEoDEgAQgcKBWlucHV0IsICChJTdHJlYW1JbnB1dFJlcXVlc3QSNwoFc3RhcnQYASABKAsyJi5wcm9jZXNzLlN0cmVhbUlucHV0UmVxdWVzdC5TdGFydEV2ZW50SAASNQoEZGF0YRgCIAEoCzIlLnByb2Nlc3MuU3RyZWFtSW5wdXRSZXF1ZXN0LkRhdGFFdmVudEgAEjoKCWtlZXBhbGl2ZRgDIAEoCzIlLnByb2Nlc3MuU3RyZWFtSW5wdXRSZXF1ZXN0LktlZXBBbGl2ZUgAGjcKClN0YXJ0RXZlbnQSKQoHcHJvY2VzcxgBIAEoCzIYLnByb2Nlc3MuUHJvY2Vzc1NlbGVjdG9yGjEKCURhdGFFdmVudBIkCgVpbnB1dBgCIAEoCzIVLnByb2Nlc3MuUHJvY2Vzc0lucHV0GgsKCUtlZXBBbGl2ZUIHCgVldmVudCIVChNTdHJlYW1JbnB1dFJlc3BvbnNlIl8KEVNlbmRTaWduYWxSZXF1ZXN0EikKB3Byb2Nlc3MYASABKAsyGC5wcm9jZXNzLlByb2Nlc3NTZWxlY3RvchIfCgZzaWduYWwYAiABKA4yDy5wcm9jZXNzLlNpZ25hbCIUChJTZW5kU2lnbmFsUmVzcG9uc2UiOwoOQ29ubmVjdFJlcXVlc3QSKQoHcHJvY2VzcxgBIAEoCzIYLnByb2Nlc3MuUHJvY2Vzc1NlbGVjdG9yIjsKD1Byb2Nlc3NTZWxlY3RvchINCgNwaWQYASABKA1IABINCgN0YWcYAiABKAlIAEIKCghzZWxlY3RvcipICgZTaWduYWwSFgoSU0lHTkFMX1VOU1BFQ0lGSUVEEAASEgoOU0lHTkFMX1NJR1RFUk0QDxISCg5TSUdOQUxfU0lHS0lMTBAJMsoDCgdQcm9jZXNzEjMKBExpc3QSFC5wcm9jZXNzLkxpc3RSZXF1ZXN0GhUucHJvY2Vzcy5MaXN0UmVzcG9uc2USPgoHQ29ubmVjdBIXLnByb2Nlc3MuQ29ubmVjdFJlcXVlc3QaGC5wcm9jZXNzLkNvbm5lY3RSZXNwb25zZTABEjgKBVN0YXJ0EhUucHJvY2Vzcy5TdGFydFJlcXVlc3QaFi5wcm9jZXNzLlN0YXJ0UmVzcG9uc2UwARI5CgZVcGRhdGUSFi5wcm9jZXNzLlVwZGF0ZVJlcXVlc3QaFy5wcm9jZXNzLlVwZGF0ZVJlc3BvbnNlEkoKC1N0cmVhbUlucHV0EhsucHJvY2Vzcy5TdHJlYW1JbnB1dFJlcXVlc3QaHC5wcm9jZXNzLlN0cmVhbUlucHV0UmVzcG9uc2UoARJCCglTZW5kSW5wdXQSGS5wcm9jZXNzLlNlbmRJbnB1dFJlcXVlc3QaGi5wcm9jZXNzLlNlbmRJbnB1dFJlc3BvbnNlEkUKClNlbmRTaWduYWwSGi5wcm9jZXNzLlNlbmRTaWduYWxSZXF1ZXN0GhsucHJvY2Vzcy5TZW5kU2lnbmFsUmVzcG9uc2VCVwoLY29tLnByb2Nlc3NCDFByb2Nlc3NQcm90b1ABogIDUFhYqgIHUHJvY2Vzc8oCB1Byb2Nlc3PiAhNQcm9jZXNzXEdQQk1ldGFkYXRh6gIHUHJvY2Vzc2IGcHJvdG8z\");\n\n/**\n * @generated from message process.PTY\n */\nexport type PTY = Message<\"process.PTY\"> & {\n /**\n * @generated from field: process.PTY.Size size = 1;\n */\n size?: PTY_Size;\n};\n\n/**\n * Describes the message process.PTY.\n * Use `create(PTYSchema)` to create a new message.\n */\nexport const PTYSchema: GenMessage<PTY> = /*@__PURE__*/\n messageDesc(file_process_process, 0);\n\n/**\n * @generated from message process.PTY.Size\n */\nexport type PTY_Size = Message<\"process.PTY.Size\"> & {\n /**\n * @generated from field: uint32 cols = 1;\n */\n cols: number;\n\n /**\n * @generated from field: uint32 rows = 2;\n */\n rows: number;\n};\n\n/**\n * Describes the message process.PTY.Size.\n * Use `create(PTY_SizeSchema)` to create a new message.\n */\nexport const PTY_SizeSchema: GenMessage<PTY_Size> = /*@__PURE__*/\n messageDesc(file_process_process, 0, 0);\n\n/**\n * @generated from message process.ProcessConfig\n */\nexport type ProcessConfig = Message<\"process.ProcessConfig\"> & {\n /**\n * @generated from field: string cmd = 1;\n */\n cmd: string;\n\n /**\n * @generated from field: repeated string args = 2;\n */\n args: string[];\n\n /**\n * @generated from field: map<string, string> envs = 3;\n */\n envs: { [key: string]: string };\n\n /**\n * @generated from field: optional string cwd = 4;\n */\n cwd?: string;\n};\n\n/**\n * Describes the message process.ProcessConfig.\n * Use `create(ProcessConfigSchema)` to create a new message.\n */\nexport const ProcessConfigSchema: GenMessage<ProcessConfig> = /*@__PURE__*/\n messageDesc(file_process_process, 1);\n\n/**\n * @generated from message process.ListRequest\n */\nexport type ListRequest = Message<\"process.ListRequest\"> & {\n};\n\n/**\n * Describes the message process.ListRequest.\n * Use `create(ListRequestSchema)` to create a new message.\n */\nexport const ListRequestSchema: GenMessage<ListRequest> = /*@__PURE__*/\n messageDesc(file_process_process, 2);\n\n/**\n * @generated from message process.ProcessInfo\n */\nexport type ProcessInfo = Message<\"process.ProcessInfo\"> & {\n /**\n * @generated from field: process.ProcessConfig config = 1;\n */\n config?: ProcessConfig;\n\n /**\n * @generated from field: uint32 pid = 2;\n */\n pid: number;\n\n /**\n * @generated from field: optional string tag = 3;\n */\n tag?: string;\n};\n\n/**\n * Describes the message process.ProcessInfo.\n * Use `create(ProcessInfoSchema)` to create a new message.\n */\nexport const ProcessInfoSchema: GenMessage<ProcessInfo> = /*@__PURE__*/\n messageDesc(file_process_process, 3);\n\n/**\n * @generated from message process.ListResponse\n */\nexport type ListResponse = Message<\"process.ListResponse\"> & {\n /**\n * @generated from field: repeated process.ProcessInfo processes = 1;\n */\n processes: ProcessInfo[];\n};\n\n/**\n * Describes the message process.ListResponse.\n * Use `create(ListResponseSchema)` to create a new message.\n */\nexport const ListResponseSchema: GenMessage<ListResponse> = /*@__PURE__*/\n messageDesc(file_process_process, 4);\n\n/**\n * @generated from message process.StartRequest\n */\nexport type StartRequest = Message<\"process.StartRequest\"> & {\n /**\n * @generated from field: process.ProcessConfig process = 1;\n */\n process?: ProcessConfig;\n\n /**\n * @generated from field: optional process.PTY pty = 2;\n */\n pty?: PTY;\n\n /**\n * @generated from field: optional string tag = 3;\n */\n tag?: string;\n};\n\n/**\n * Describes the message process.StartRequest.\n * Use `create(StartRequestSchema)` to create a new message.\n */\nexport const StartRequestSchema: GenMessage<StartRequest> = /*@__PURE__*/\n messageDesc(file_process_process, 5);\n\n/**\n * @generated from message process.UpdateRequest\n */\nexport type UpdateRequest = Message<\"process.UpdateRequest\"> & {\n /**\n * @generated from field: process.ProcessSelector process = 1;\n */\n process?: ProcessSelector;\n\n /**\n * @generated from field: optional process.PTY pty = 2;\n */\n pty?: PTY;\n};\n\n/**\n * Describes the message process.UpdateRequest.\n * Use `create(UpdateRequestSchema)` to create a new message.\n */\nexport const UpdateRequestSchema: GenMessage<UpdateRequest> = /*@__PURE__*/\n messageDesc(file_process_process, 6);\n\n/**\n * @generated from message process.UpdateResponse\n */\nexport type UpdateResponse = Message<\"process.UpdateResponse\"> & {\n};\n\n/**\n * Describes the message process.UpdateResponse.\n * Use `create(UpdateResponseSchema)` to create a new message.\n */\nexport const UpdateResponseSchema: GenMessage<UpdateResponse> = /*@__PURE__*/\n messageDesc(file_process_process, 7);\n\n/**\n * @generated from message process.ProcessEvent\n */\nexport type ProcessEvent = Message<\"process.ProcessEvent\"> & {\n /**\n * @generated from oneof process.ProcessEvent.event\n */\n event: {\n /**\n * @generated from field: process.ProcessEvent.StartEvent start = 1;\n */\n value: ProcessEvent_StartEvent;\n case: \"start\";\n } | {\n /**\n * @generated from field: process.ProcessEvent.DataEvent data = 2;\n */\n value: ProcessEvent_DataEvent;\n case: \"data\";\n } | {\n /**\n * @generated from field: process.ProcessEvent.EndEvent end = 3;\n */\n value: ProcessEvent_EndEvent;\n case: \"end\";\n } | {\n /**\n * @generated from field: process.ProcessEvent.KeepAlive keepalive = 4;\n */\n value: ProcessEvent_KeepAlive;\n case: \"keepalive\";\n } | { case: undefined; value?: undefined };\n};\n\n/**\n * Describes the message process.ProcessEvent.\n * Use `create(ProcessEventSchema)` to create a new message.\n */\nexport const ProcessEventSchema: GenMessage<ProcessEvent> = /*@__PURE__*/\n messageDesc(file_process_process, 8);\n\n/**\n * @generated from message process.ProcessEvent.StartEvent\n */\nexport type ProcessEvent_StartEvent = Message<\"process.ProcessEvent.StartEvent\"> & {\n /**\n * @generated from field: uint32 pid = 1;\n */\n pid: number;\n};\n\n/**\n * Describes the message process.ProcessEvent.StartEvent.\n * Use `create(ProcessEvent_StartEventSchema)` to create a new message.\n */\nexport const ProcessEvent_StartEventSchema: GenMessage<ProcessEvent_StartEvent> = /*@__PURE__*/\n messageDesc(file_process_process, 8, 0);\n\n/**\n * @generated from message process.ProcessEvent.DataEvent\n */\nexport type ProcessEvent_DataEvent = Message<\"process.ProcessEvent.DataEvent\"> & {\n /**\n * @generated from oneof process.ProcessEvent.DataEvent.output\n */\n output: {\n /**\n * @generated from field: bytes stdout = 1;\n */\n value: Uint8Array;\n case: \"stdout\";\n } | {\n /**\n * @generated from field: bytes stderr = 2;\n */\n value: Uint8Array;\n case: \"stderr\";\n } | {\n /**\n * @generated from field: bytes pty = 3;\n */\n value: Uint8Array;\n case: \"pty\";\n } | { case: undefined; value?: undefined };\n};\n\n/**\n * Describes the message process.ProcessEvent.DataEvent.\n * Use `create(ProcessEvent_DataEventSchema)` to create a new message.\n */\nexport const ProcessEvent_DataEventSchema: GenMessage<ProcessEvent_DataEvent> = /*@__PURE__*/\n messageDesc(file_process_process, 8, 1);\n\n/**\n * @generated from message process.ProcessEvent.EndEvent\n */\nexport type ProcessEvent_EndEvent = Message<\"process.ProcessEvent.EndEvent\"> & {\n /**\n * @generated from field: sint32 exit_code = 1;\n */\n exitCode: number;\n\n /**\n * @generated from field: bool exited = 2;\n */\n exited: boolean;\n\n /**\n * @generated from field: string status = 3;\n */\n status: string;\n\n /**\n * @generated from field: optional string error = 4;\n */\n error?: string;\n};\n\n/**\n * Describes the message process.ProcessEvent.EndEvent.\n * Use `create(ProcessEvent_EndEventSchema)` to create a new message.\n */\nexport const ProcessEvent_EndEventSchema: GenMessage<ProcessEvent_EndEvent> = /*@__PURE__*/\n messageDesc(file_process_process, 8, 2);\n\n/**\n * @generated from message process.ProcessEvent.KeepAlive\n */\nexport type ProcessEvent_KeepAlive = Message<\"process.ProcessEvent.KeepAlive\"> & {\n};\n\n/**\n * Describes the message process.ProcessEvent.KeepAlive.\n * Use `create(ProcessEvent_KeepAliveSchema)` to create a new message.\n */\nexport const ProcessEvent_KeepAliveSchema: GenMessage<ProcessEvent_KeepAlive> = /*@__PURE__*/\n messageDesc(file_process_process, 8, 3);\n\n/**\n * @generated from message process.StartResponse\n */\nexport type StartResponse = Message<\"process.StartResponse\"> & {\n /**\n * @generated from field: process.ProcessEvent event = 1;\n */\n event?: ProcessEvent;\n};\n\n/**\n * Describes the message process.StartResponse.\n * Use `create(StartResponseSchema)` to create a new message.\n */\nexport const StartResponseSchema: GenMessage<StartResponse> = /*@__PURE__*/\n messageDesc(file_process_process, 9);\n\n/**\n * @generated from message process.ConnectResponse\n */\nexport type ConnectResponse = Message<\"process.ConnectResponse\"> & {\n /**\n * @generated from field: process.ProcessEvent event = 1;\n */\n event?: ProcessEvent;\n};\n\n/**\n * Describes the message process.ConnectResponse.\n * Use `create(ConnectResponseSchema)` to create a new message.\n */\nexport const ConnectResponseSchema: GenMessage<ConnectResponse> = /*@__PURE__*/\n messageDesc(file_process_process, 10);\n\n/**\n * @generated from message process.SendInputRequest\n */\nexport type SendInputRequest = Message<\"process.SendInputRequest\"> & {\n /**\n * @generated from field: process.ProcessSelector process = 1;\n */\n process?: ProcessSelector;\n\n /**\n * @generated from field: process.ProcessInput input = 2;\n */\n input?: ProcessInput;\n};\n\n/**\n * Describes the message process.SendInputRequest.\n * Use `create(SendInputRequestSchema)` to create a new message.\n */\nexport const SendInputRequestSchema: GenMessage<SendInputRequest> = /*@__PURE__*/\n messageDesc(file_process_process, 11);\n\n/**\n * @generated from message process.SendInputResponse\n */\nexport type SendInputResponse = Message<\"process.SendInputResponse\"> & {\n};\n\n/**\n * Describes the message process.SendInputResponse.\n * Use `create(SendInputResponseSchema)` to create a new message.\n */\nexport const SendInputResponseSchema: GenMessage<SendInputResponse> = /*@__PURE__*/\n messageDesc(file_process_process, 12);\n\n/**\n * @generated from message process.ProcessInput\n */\nexport type ProcessInput = Message<\"process.ProcessInput\"> & {\n /**\n * @generated from oneof process.ProcessInput.input\n */\n input: {\n /**\n * @generated from field: bytes stdin = 1;\n */\n value: Uint8Array;\n case: \"stdin\";\n } | {\n /**\n * @generated from field: bytes pty = 2;\n */\n value: Uint8Array;\n case: \"pty\";\n } | { case: undefined; value?: undefined };\n};\n\n/**\n * Describes the message process.ProcessInput.\n * Use `create(ProcessInputSchema)` to create a new message.\n */\nexport const ProcessInputSchema: GenMessage<ProcessInput> = /*@__PURE__*/\n messageDesc(file_process_process, 13);\n\n/**\n * @generated from message process.StreamInputRequest\n */\nexport type StreamInputRequest = Message<\"process.StreamInputRequest\"> & {\n /**\n * @generated from oneof process.StreamInputRequest.event\n */\n event: {\n /**\n * @generated from field: process.StreamInputRequest.StartEvent start = 1;\n */\n value: StreamInputRequest_StartEvent;\n case: \"start\";\n } | {\n /**\n * @generated from field: process.StreamInputRequest.DataEvent data = 2;\n */\n value: StreamInputRequest_DataEvent;\n case: \"data\";\n } | {\n /**\n * @generated from field: process.StreamInputRequest.KeepAlive keepalive = 3;\n */\n value: StreamInputRequest_KeepAlive;\n case: \"keepalive\";\n } | { case: undefined; value?: undefined };\n};\n\n/**\n * Describes the message process.StreamInputRequest.\n * Use `create(StreamInputRequestSchema)` to create a new message.\n */\nexport const StreamInputRequestSchema: GenMessage<StreamInputRequest> = /*@__PURE__*/\n messageDesc(file_process_process, 14);\n\n/**\n * @generated from message process.StreamInputRequest.StartEvent\n */\nexport type StreamInputRequest_StartEvent = Message<\"process.StreamInputRequest.StartEvent\"> & {\n /**\n * @generated from field: process.ProcessSelector process = 1;\n */\n process?: ProcessSelector;\n};\n\n/**\n * Describes the message process.StreamInputRequest.StartEvent.\n * Use `create(StreamInputRequest_StartEventSchema)` to create a new message.\n */\nexport const StreamInputRequest_StartEventSchema: GenMessage<StreamInputRequest_StartEvent> = /*@__PURE__*/\n messageDesc(file_process_process, 14, 0);\n\n/**\n * @generated from message process.StreamInputRequest.DataEvent\n */\nexport type StreamInputRequest_DataEvent = Message<\"process.StreamInputRequest.DataEvent\"> & {\n /**\n * @generated from field: process.ProcessInput input = 2;\n */\n input?: ProcessInput;\n};\n\n/**\n * Describes the message process.StreamInputRequest.DataEvent.\n * Use `create(StreamInputRequest_DataEventSchema)` to create a new message.\n */\nexport const StreamInputRequest_DataEventSchema: GenMessage<StreamInputRequest_DataEvent> = /*@__PURE__*/\n messageDesc(file_process_process, 14, 1);\n\n/**\n * @generated from message process.StreamInputRequest.KeepAlive\n */\nexport type StreamInputRequest_KeepAlive = Message<\"process.StreamInputRequest.KeepAlive\"> & {\n};\n\n/**\n * Describes the message process.StreamInputRequest.KeepAlive.\n * Use `create(StreamInputRequest_KeepAliveSchema)` to create a new message.\n */\nexport const StreamInputRequest_KeepAliveSchema: GenMessage<StreamInputRequest_KeepAlive> = /*@__PURE__*/\n messageDesc(file_process_process, 14, 2);\n\n/**\n * @generated from message process.StreamInputResponse\n */\nexport type StreamInputResponse = Message<\"process.StreamInputResponse\"> & {\n};\n\n/**\n * Describes the message process.StreamInputResponse.\n * Use `create(StreamInputResponseSchema)` to create a new message.\n */\nexport const StreamInputResponseSchema: GenMessage<StreamInputResponse> = /*@__PURE__*/\n messageDesc(file_process_process, 15);\n\n/**\n * @generated from message process.SendSignalRequest\n */\nexport type SendSignalRequest = Message<\"process.SendSignalRequest\"> & {\n /**\n * @generated from field: process.ProcessSelector process = 1;\n */\n process?: ProcessSelector;\n\n /**\n * @generated from field: process.Signal signal = 2;\n */\n signal: Signal;\n};\n\n/**\n * Describes the message process.SendSignalRequest.\n * Use `create(SendSignalRequestSchema)` to create a new message.\n */\nexport const SendSignalRequestSchema: GenMessage<SendSignalRequest> = /*@__PURE__*/\n messageDesc(file_process_process, 16);\n\n/**\n * @generated from message process.SendSignalResponse\n */\nexport type SendSignalResponse = Message<\"process.SendSignalResponse\"> & {\n};\n\n/**\n * Describes the message process.SendSignalResponse.\n * Use `create(SendSignalResponseSchema)` to create a new message.\n */\nexport const SendSignalResponseSchema: GenMessage<SendSignalResponse> = /*@__PURE__*/\n messageDesc(file_process_process, 17);\n\n/**\n * @generated from message process.ConnectRequest\n */\nexport type ConnectRequest = Message<\"process.ConnectRequest\"> & {\n /**\n * @generated from field: process.ProcessSelector process = 1;\n */\n process?: ProcessSelector;\n};\n\n/**\n * Describes the message process.ConnectRequest.\n * Use `create(ConnectRequestSchema)` to create a new message.\n */\nexport const ConnectRequestSchema: GenMessage<ConnectRequest> = /*@__PURE__*/\n messageDesc(file_process_process, 18);\n\n/**\n * @generated from message process.ProcessSelector\n */\nexport type ProcessSelector = Message<\"process.ProcessSelector\"> & {\n /**\n * @generated from oneof process.ProcessSelector.selector\n */\n selector: {\n /**\n * @generated from field: uint32 pid = 1;\n */\n value: number;\n case: \"pid\";\n } | {\n /**\n * @generated from field: string tag = 2;\n */\n value: string;\n case: \"tag\";\n } | { case: undefined; value?: undefined };\n};\n\n/**\n * Describes the message process.ProcessSelector.\n * Use `create(ProcessSelectorSchema)` to create a new message.\n */\nexport const ProcessSelectorSchema: GenMessage<ProcessSelector> = /*@__PURE__*/\n messageDesc(file_process_process, 19);\n\n/**\n * @generated from enum process.Signal\n */\nexport enum Signal {\n /**\n * @generated from enum value: SIGNAL_UNSPECIFIED = 0;\n */\n UNSPECIFIED = 0,\n\n /**\n * @generated from enum value: SIGNAL_SIGTERM = 15;\n */\n SIGTERM = 15,\n\n /**\n * @generated from enum value: SIGNAL_SIGKILL = 9;\n */\n SIGKILL = 9,\n}\n\n/**\n * Describes the enum process.Signal.\n */\nexport const SignalSchema: GenEnum<Signal> = /*@__PURE__*/\n enumDesc(file_process_process, 0);\n\n/**\n * @generated from service process.Process\n */\nexport const Process: GenService<{\n /**\n * @generated from rpc process.Process.List\n */\n list: {\n methodKind: \"unary\";\n input: typeof ListRequestSchema;\n output: typeof ListResponseSchema;\n },\n /**\n * @generated from rpc process.Process.Connect\n */\n connect: {\n methodKind: \"server_streaming\";\n input: typeof ConnectRequestSchema;\n output: typeof ConnectResponseSchema;\n },\n /**\n * @generated from rpc process.Process.Start\n */\n start: {\n methodKind: \"server_streaming\";\n input: typeof StartRequestSchema;\n output: typeof StartResponseSchema;\n },\n /**\n * @generated from rpc process.Process.Update\n */\n update: {\n methodKind: \"unary\";\n input: typeof UpdateRequestSchema;\n output: typeof UpdateResponseSchema;\n },\n /**\n * Client input stream ensures ordering of messages\n *\n * @generated from rpc process.Process.StreamInput\n */\n streamInput: {\n methodKind: \"client_streaming\";\n input: typeof StreamInputRequestSchema;\n output: typeof StreamInputResponseSchema;\n },\n /**\n * @generated from rpc process.Process.SendInput\n */\n sendInput: {\n methodKind: \"unary\";\n input: typeof SendInputRequestSchema;\n output: typeof SendInputResponseSchema;\n },\n /**\n * @generated from rpc process.Process.SendSignal\n */\n sendSignal: {\n methodKind: \"unary\";\n input: typeof SendSignalRequestSchema;\n output: typeof SendSignalResponseSchema;\n },\n}> = /*@__PURE__*/\n serviceDesc(file_process_process, 0);\n\n","import {\n Code,\n ConnectError,\n createClient,\n Client,\n Transport,\n} from '@connectrpc/connect'\n\nimport { Signal, Process as ProcessService } from '../../envd/process/process_pb'\nimport {\n ConnectionConfig,\n ConnectionOpts,\n Username,\n KEEPALIVE_PING_HEADER,\n KEEPALIVE_PING_INTERVAL_SEC,\n} from '../../connectionConfig'\nimport { CommandHandle } from './commandHandle'\nimport { authenticationHeader, handleRpcError } from '../../envd/rpc'\nimport { handleProcessStartEvent } from '../../envd/api'\n\nexport interface PtyCreateOpts\n extends Pick<ConnectionOpts, 'requestTimeoutMs'> {\n /**\n * Number of columns for the PTY.\n */\n cols: number\n /**\n * Number of rows for the PTY.\n */\n rows: number\n /**\n * Callback to handle PTY data.\n */\n onData: (data: Uint8Array) => void | Promise<void>\n /**\n * Timeout for the PTY in **milliseconds**.\n * \n * @default 60_000 // 60 seconds\n */\n timeoutMs?: number\n /**\n * User to use for the PTY.\n * \n * @default `user`\n */\n user?: Username\n /**\n * Environment variables for the PTY.\n * \n * @default {}\n */\n envs?: Record<string, string>\n /**\n * Working directory for the PTY.\n * \n * @default // home directory of the user used to start the PTY\n */\n cwd?: string\n}\n\n/**\n * Module for interacting with PTYs (pseudo-terminals) in the sandbox.\n */\nexport class Pty {\n private readonly rpc: Client<typeof ProcessService>\n\n constructor(\n private readonly transport: Transport,\n private readonly connectionConfig: ConnectionConfig\n ) {\n this.rpc = createClient(ProcessService, this.transport)\n }\n\n /**\n * Create a new PTY (pseudo-terminal).\n *\n * @param opts options for creating the PTY.\n * \n * @returns handle to interact with the PTY.\n */\n async create(opts: PtyCreateOpts) {\n const requestTimeoutMs =\n opts?.requestTimeoutMs ?? this.connectionConfig.requestTimeoutMs\n const envs = opts?.envs ?? {}\n envs.TERM = 'xterm-256color'\n const controller = new AbortController()\n\n const reqTimeout = setTimeout(() => {\n controller.abort()\n }, requestTimeoutMs)\n\n const events = this.rpc.start(\n {\n process: {\n cmd: '/bin/bash',\n args: ['-i', '-l'],\n envs: envs,\n cwd: opts?.cwd,\n },\n pty: {\n size: {\n cols: opts.cols,\n rows: opts.rows,\n },\n },\n },\n {\n headers: {\n ...authenticationHeader(opts?.user),\n [KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString(),\n },\n signal: controller.signal,\n timeoutMs: opts?.timeoutMs ?? 60_000,\n }\n )\n\n try {\n const pid = await handleProcessStartEvent(events)\n\n clearTimeout(reqTimeout)\n\n return new CommandHandle(\n pid,\n () => controller.abort(),\n () => this.kill(pid),\n events,\n undefined,\n undefined,\n opts.onData\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Send input to a PTY.\n *\n * @param pid process ID of the PTY.\n * @param data input data to send to the PTY.\n * @param opts connection options.\n */\n async sendInput(\n pid: number,\n data: Uint8Array,\n opts?: Pick<ConnectionOpts, 'requestTimeoutMs'>\n ): Promise<void> {\n try {\n await this.rpc.sendInput(\n {\n input: {\n input: {\n case: 'pty',\n value: data,\n },\n },\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n },\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Resize PTY.\n * Call this when the terminal window is resized and the number of columns and rows has changed.\n *\n * @param pid process ID of the PTY.\n * @param size new size of the PTY.\n * @param opts connection options.\n */\n async resize(\n pid: number,\n size: {\n cols: number\n rows: number\n },\n opts?: Pick<ConnectionOpts, 'requestTimeoutMs'>\n ): Promise<void> {\n try {\n await this.rpc.update(\n {\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n pty: {\n size,\n },\n },\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n } catch (err) {\n throw handleRpcError(err)\n }\n }\n\n /**\n * Kill a running PTY specified by process ID.\n * It uses `SIGKILL` signal to kill the PTY.\n *\n * @param pid process ID of the PTY.\n * @param opts connection options.\n * \n * @returns `true` if the PTY was killed, `false` if the PTY was not found.\n */\n async kill(\n pid: number,\n opts?: Pick<ConnectionOpts, 'requestTimeoutMs'>\n ): Promise<boolean> {\n try {\n await this.rpc.sendSignal(\n {\n process: {\n selector: {\n case: 'pid',\n value: pid,\n },\n },\n signal: Signal.SIGKILL,\n },\n {\n signal: this.connectionConfig.getSignal(opts?.requestTimeoutMs),\n }\n )\n\n return true\n } catch (err) {\n if (err instanceof ConnectError) {\n if (err.code === Code.NotFound) {\n return false\n }\n }\n\n throw handleRpcError(err)\n }\n }\n}\n","import { ApiClient, components, handleApiError } from '../api'\nimport {\n ConnectionConfig,\n ConnectionOpts,\n DEFAULT_SANDBOX_TIMEOUT_MS,\n REQUEST_LONG_TIMEOUT_MS,\n} from '../connectionConfig'\nimport { compareVersions } from 'compare-versions'\nimport { NotFoundError, TemplateError } from '../errors'\nimport { timeoutToSeconds } from '../utils'\n\nasync function createRawApiError(response: Response): Promise<Error> {\n let message = response.statusText\n\n try {\n const body = (await response.json()) as { message?: string }\n message = body.message ?? JSON.stringify(body)\n } catch {\n try {\n message = await response.text()\n } catch {\n // Use statusText.\n }\n }\n\n return new Error(`${response.status}: ${message}`)\n}\n\n/**\n * Options for request to the Sandbox API.\n */\nexport interface SandboxApiOpts\n extends Partial<\n Pick<\n ConnectionOpts,\n 'apiKey' | 'headers' | 'debug' | 'domain' | 'requestTimeoutMs' | 'sync'\n >\n > {}\n\n/**\n * Options for creating a new Sandbox.\n */\nexport interface SandboxOpts extends ConnectionOpts {\n /**\n * Custom metadata for the sandbox.\n *\n * @default {}\n */\n metadata?: Record<string, string>\n\n /**\n * Custom environment variables for the sandbox.\n *\n * Used when executing commands and code in the sandbox.\n * Can be overridden with the `envs` argument when executing commands or code.\n *\n * @default {}\n */\n envs?: Record<string, string>\n\n /**\n * Timeout for the sandbox in **milliseconds**.\n * Maximum time a sandbox can be kept alive is 24 hours (86_400_000 milliseconds) for Pro users and 1 hour (3_600_000 milliseconds) for Hobby users.\n *\n * @default 300_000 // 5 minutes\n */\n timeoutMs?: number\n\n /**\n * Secure all traffic coming to the sandbox controller with auth token\n *\n * @default true\n */\n secure?: boolean\n\n /**\n * Allow sandbox to access the internet\n *\n * @default true\n */\n // allowInternetAccess?: boolean\n}\n\nexport type SandboxBetaCreateOpts = SandboxOpts & {\n /**\n * Automatically pause the sandbox after the timeout expires.\n * @default false\n */\n autoPause?: boolean\n\n /**\n * Create a sandbox on the specified node.\n * @default empty\n */\n nodeID?: string\n}\n\n/**\n * Options for connecting to a Sandbox.\n */\nexport type SandboxConnectOpts = Omit<SandboxOpts, 'metadata' | 'envs'>\n\n/**\n * State of the sandbox.\n */\nexport type SandboxState = 'running' | 'paused' | 'cloning'\n\nexport interface SandboxListOpts extends SandboxApiOpts {\n /**\n * Filter the list of sandboxes, e.g. by metadata `metadata:{\"key\": \"value\"}`, if there are multiple filters they are combined with AND.\n *\n */\n query?: {\n metadata?: Record<string, string>\n /**\n * Filter the list of sandboxes by state.\n * @default ['running', 'paused']\n */\n state?: Array<SandboxState>\n }\n\n /**\n * Number of sandboxes to return per page.\n *\n * @default 100\n */\n limit?: number\n\n /**\n * Token to the next page.\n */\n nextToken?: string\n}\n\nexport interface SandboxMetricsOpts extends SandboxApiOpts {\n /**\n * Start time for the metrics, defaults to the start of the sandbox\n */\n start?: string | Date\n /**\n * End time for the metrics, defaults to the current time\n */\n end?: string | Date\n}\n\nexport interface SandboxEventsOpts extends SandboxApiOpts {\n startTime?: number\n endTime?: number\n sandboxID?: string\n templateID?: string\n events?: string\n state?: string\n orderAsc?: boolean\n offset?: number\n limit?: number\n}\n\nexport interface SandboxEventItem {\n eventID: string\n recordAt: number\n templateID: string\n templateName: string\n sandboxID: string\n eventName: string\n state: string\n errorMsg: string\n statusCode: number\n}\n\nexport interface SandboxEventsResult {\n items: SandboxEventItem[]\n total: number\n hasMore: boolean\n}\n\n/**\n * Options for cloning a sandbox.\n */\nexport interface SandboxCloneOpts extends SandboxApiOpts {\n /**\n * Number of sandboxes to clone.\n * @default 1\n */\n count?: number\n\n /**\n * Timeout for cloned sandboxes in milliseconds.\n *\n * If omitted, backend applies defaults depending on the parent sandbox state:\n * - When parent sandbox is running: inherit parent's timeout\n * - When parent sandbox is paused: use 15 seconds\n */\n timeoutMs?: number\n\n /**\n * Optional identifier of the node where the sandbox should be created.\n */\n nodeID?: string\n\n /**\n * If true, strictly clone the exact count of sandboxes and fail if insufficient resources are available.\n * @default false\n */\n strict?: boolean\n}\n\n/**\n * Response from cloning a sandbox (raw API response).\n */\nexport interface SandboxCloneResponse {\n /**\n * Number of successfully cloned sandboxes.\n */\n count: number\n\n /**\n * Minimal info for constructing SDK instances of cloned sandboxes.\n */\n sandboxes: Array<{\n /** Combined sandbox id: \"{sandboxID}-{clientID}\" */\n sandboxId: string\n /** Envd version */\n envdVersion: string\n /** Access token for envd communication */\n envdAccessToken?: string\n }>\n\n /**\n * Identifier of the snapshot template used for cloning.\n */\n snapshotTemplateId?: string\n}\n\n/**\n * Result of a sandbox clone operation.\n * \n * @example\n * ```ts\n * const result = await Sandbox.clone('sandbox-id', { count: 3 })\n * \n * console.log('Count:', result.count)\n * console.log('Snapshot Template ID:', result.snapshotTemplateId)\n * \n * for (const sandbox of result.sandboxes) {\n * console.log(sandbox.sandboxId)\n * await sandbox.kill()\n * }\n * ```\n */\nexport interface CloneResult<T> {\n /**\n * Number of successfully cloned sandboxes.\n */\n count: number\n\n /**\n * Identifier of the snapshot template used for cloning.\n */\n snapshotTemplateId?: string\n\n /**\n * List of cloned sandbox instances.\n */\n sandboxes: T[]\n}\n\n/**\n * Options for resetting a sandbox.\n */\nexport interface SandboxResetOpts extends SandboxApiOpts {\n /**\n * Whether to resume the sandbox after memory reset.\n * @default true\n */\n resume?: boolean\n\n /**\n * Timeout for the sandbox in milliseconds if resumed.\n * If omitted, backend default is used.\n */\n timeoutMs?: number\n}\n\n/**\n * Options for committing a sandbox to create a template snapshot.\n */\nexport interface SandboxCommitOpts extends SandboxApiOpts {\n /**\n * Optional alias for the created template.\n */\n alias?: string\n}\n\n/**\n * Template information returned from sandbox commit.\n */\nexport interface Template {\n /**\n * Identifier of the template.\n */\n templateId: string\n\n /**\n * Aliases of the template.\n */\n aliases?: string[]\n\n /**\n * Number of times the template was built.\n */\n buildCount: number\n\n /**\n * Identifier of the last successful build for given template.\n */\n buildId: string\n\n /**\n * Sandbox CPU count.\n */\n cpuCount: number\n\n /**\n * Template creation time.\n */\n createdAt: Date\n\n /**\n * User who created the template.\n */\n createdBy: {\n email?: string\n id: string\n name?: string\n } | null\n\n /**\n * Disk size in MB.\n */\n diskSizeMB: number\n\n /**\n * Envd version.\n */\n envdVersion: string\n\n /**\n * Time when the template was last used.\n */\n lastSpawnedAt: Date\n\n /**\n * Memory size in MB.\n */\n memoryMB: number\n\n /**\n * Optional metadata for the template (key-value pairs).\n */\n metadata?: Record<string, string>\n\n /**\n * Whether the template is public or only accessible by the team.\n */\n public: boolean\n\n /**\n * Number of times the template was used.\n */\n spawnCount: number\n\n /**\n * Type of the template, indicates whether the template is built or committed.\n */\n templateType?: 'template_build' | 'snapshot_template'\n\n /**\n * The original sandbox ID from which this template was created (only applicable for snapshot_template type).\n */\n originSandboxID?: string | null\n\n /**\n * Time when the template was last updated.\n */\n updatedAt: Date\n}\n\n/**\n * Information about a sandbox.\n */\nexport interface SandboxInfo {\n /**\n * Sandbox ID.\n */\n sandboxId: string\n\n /**\n * Template ID.\n */\n templateId: string\n\n /**\n * Template name.\n */\n name?: string\n\n /**\n * Saved sandbox metadata.\n */\n metadata: Record<string, string>\n\n /**\n * Sandbox start time.\n */\n startedAt: Date\n\n /**\n * Sandbox expiration date.\n */\n endAt: Date\n\n /**\n * Sandbox state.\n *\n * @string can be `running` or `paused`\n */\n state: SandboxState\n\n /**\n * Sandbox CPU count.\n */\n cpuCount: number\n\n /**\n * Sandbox Memory size in MiB.\n */\n memoryMB: number\n\n /**\n * Envd version.\n */\n envdVersion: string | undefined\n}\n\n/**\n * Sandbox resource usage metrics.\n */\nexport interface SandboxMetrics {\n /**\n * Timestamp of the metrics.\n */\n timestamp: Date\n\n /**\n * CPU usage in percentage.\n */\n cpuUsedPct: number\n\n /**\n * Number of CPU cores.\n */\n cpuCount: number\n\n /**\n * Memory usage in bytes.\n */\n memUsed: number\n\n /**\n * Total memory available in bytes.\n */\n memTotal: number\n\n /**\n * Used disk space in bytes.\n */\n diskUsed: number\n\n /**\n * Total disk space available in bytes.\n */\n diskTotal: number\n}\n\nexport class SandboxApi {\n protected constructor() {}\n\n /**\n * Kill the sandbox specified by sandbox ID.\n *\n * @param sandboxId sandbox ID.\n * @param opts connection options.\n *\n * @returns `true` if the sandbox was found and killed, `false` otherwise.\n */\n static async kill(\n sandboxId: string,\n opts?: SandboxApiOpts\n ): Promise<boolean> {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.DELETE('/sandboxes/{sandboxID}', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n return false\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n return true\n }\n\n /**\n * Get sandbox information like sandbox ID, template, metadata, started at/end at date.\n *\n * @param sandboxId sandbox ID.\n * @param opts connection options.\n *\n * @returns sandbox information.\n */\n static async getInfo(\n sandboxId: string,\n opts?: SandboxApiOpts\n ): Promise<SandboxInfo> {\n const fullInfo = await this.getFullInfo(sandboxId, opts)\n delete fullInfo.envdAccessToken\n delete fullInfo.sandboxDomain\n\n return fullInfo\n }\n\n /**\n * Get the metrics of the sandbox.\n *\n * @param sandboxId sandbox ID.\n * @param opts sandbox metrics options.\n *\n * @returns List of sandbox metrics containing CPU, memory and disk usage information.\n */\n static async getMetrics(\n sandboxId: string,\n opts?: SandboxMetricsOpts\n ): Promise<SandboxMetrics[]> {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.GET('/sandboxes/{sandboxID}/metrics', {\n params: {\n path: {\n sandboxID: sandboxId,\n start: opts?.start,\n end: opts?.end,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n return (\n res.data?.map((metric: components['schemas']['SandboxMetric']) => ({\n timestamp: new Date(metric.timestamp),\n cpuUsedPct: metric.cpuUsedPct,\n cpuCount: metric.cpuCount,\n memUsed: metric.memUsedMiB * 1024 * 1024,\n memTotal: metric.memTotalMiB * 1024 * 1024,\n // diskUsed: metric.diskUsed,\n diskUsed: -1,\n // diskTotal: metric.diskTotal,\n diskTotal: -1,\n })) ?? []\n )\n }\n\n /**\n * Set the timeout of the specified sandbox.\n * After the timeout expires the sandbox will be automatically killed.\n *\n * This method can extend or reduce the sandbox timeout set when creating the sandbox or from the last call to {@link Sandbox.setTimeout}.\n *\n * Maximum time a sandbox can be kept alive is 24 hours (86_400_000 milliseconds) for Pro users and 1 hour (3_600_000 milliseconds) for Hobby users.\n *\n * @param sandboxId sandbox ID.\n * @param timeoutMs timeout in **milliseconds**.\n * @param opts connection options.\n */\n static async setTimeout(\n sandboxId: string,\n timeoutMs: number,\n opts?: SandboxApiOpts\n ): Promise<void> {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.POST('/sandboxes/{sandboxID}/timeout', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n body: {\n timeout: timeoutToSeconds(timeoutMs),\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n }\n\n static async getFullInfo(sandboxId: string, opts?: SandboxApiOpts) {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.GET('/sandboxes/{sandboxID}', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n if (!res.data) {\n throw new Error('Sandbox not found')\n }\n\n return {\n sandboxId: `${res.data.sandboxID}-${res.data.clientID}`,\n templateId: res.data.templateID,\n ...(res.data.alias && { name: res.data.alias }),\n metadata: res.data.metadata ?? {},\n envdVersion: res.data.envdVersion,\n envdAccessToken: res.data.envdAccessToken,\n startedAt: new Date(res.data.startedAt),\n endAt: new Date(res.data.endAt),\n state: res.data.state,\n cpuCount: res.data.cpuCount,\n memoryMB: res.data.memoryMB,\n // sandboxDomain: res.data.domain || undefined,\n sandboxDomain: undefined,\n }\n }\n\n /**\n * Pause the sandbox specified by sandbox ID.\n *\n * @param sandboxId sandbox ID.\n * @param opts connection options.\n *\n * @returns `true` if the sandbox got paused, `false` if the sandbox was already paused.\n */\n static async betaPause(\n sandboxId: string,\n opts?: SandboxApiOpts\n ): Promise<boolean> {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.POST('/sandboxes/{sandboxID}/pause', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n body: {\n sync: opts?.sync ?? false,\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n throw new NotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (res.error?.code === 409) {\n // Sandbox is already paused\n return false\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n return true\n }\n\n /**\n * Clone a sandbox to create multiple identical sandboxes.\n *\n * Note: This low-level API returns raw identifiers required to construct SDK instances.\n *\n * @param sandboxId sandbox ID.\n * @param opts clone options including count.\n *\n * @returns clone response with count and list of cloned sandboxes.\n */\n static async cloneSandboxes(\n sandboxId: string,\n opts: SandboxCloneOpts\n ): Promise<SandboxCloneResponse> {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.POST('/sandboxes/{sandboxID}/clone', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n body: {\n count: opts.count ?? 1,\n nodeID: opts.nodeID,\n strict: opts.strict ?? false,\n ...(typeof opts.timeoutMs === 'number'\n ? { timeout: timeoutToSeconds(opts.timeoutMs) }\n : {}),\n },\n // Use an extended timeout for clone operation by default\n signal: config.getSignal(\n opts?.requestTimeoutMs ?? REQUEST_LONG_TIMEOUT_MS\n ),\n })\n\n if (res.error?.code === 404) {\n throw new NotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n if (!res.data) {\n throw new Error('Clone response data is missing')\n }\n\n // Transform to minimal info for constructing SDK instances\n const sandboxes = (res.data.sandboxes || []).map((sb: any) => ({\n sandboxId: `${sb.sandboxID}-${sb.clientID}`,\n envdVersion: sb.envdVersion,\n envdAccessToken: sb.envdAccessToken,\n }))\n\n return {\n count: res.data.count,\n sandboxes,\n snapshotTemplateId: res.data.snapshotTemplateId,\n }\n }\n\n protected static async createSandbox(\n template: string,\n timeoutMs: number,\n opts?: SandboxBetaCreateOpts\n ): Promise<{\n sandboxId: string\n sandboxDomain?: string\n envdVersion: string\n envdAccessToken?: string\n }> {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.POST('/sandboxes', {\n body: {\n autoPause: opts?.autoPause ?? false,\n templateID: template,\n metadata: opts?.metadata,\n envVars: opts?.envs,\n timeout: timeoutToSeconds(timeoutMs),\n secure: opts?.secure ?? false,\n // allow_internet_access: opts?.allowInternetAccess ?? true,\n allow_internet_access: true,\n nodeID:opts?.nodeID,\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n if (compareVersions(res.data!.envdVersion, '0.1.0') < 0) {\n await this.kill(res.data!.sandboxID, opts)\n throw new TemplateError(\n 'You need to update the template to use the new SDK. ' +\n 'You can do this by running `ppio-sandbox-cli template build` in the directory with the template.'\n )\n }\n\n return {\n sandboxId: `${res.data!.sandboxID}-${res.data!.clientID}`,\n // sandboxDomain: res.data!.domain || undefined,\n sandboxDomain: undefined,\n envdVersion: res.data!.envdVersion,\n envdAccessToken: res.data!.envdAccessToken,\n }\n }\n\n protected static async resumeSandbox(\n sandboxId: string,\n opts?: SandboxConnectOpts\n ): Promise<boolean> {\n const timeoutMs = opts?.timeoutMs ?? DEFAULT_SANDBOX_TIMEOUT_MS\n\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.POST('/sandboxes/{sandboxID}/resume', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n body: {\n autoPause: false,\n timeout: timeoutToSeconds(timeoutMs),\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n throw new NotFoundError(`Paused sandbox ${sandboxId} not found`)\n }\n\n if (res.error?.code === 409) {\n // Sandbox is already running\n return false\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n return true\n }\n\n protected static async connectSandbox(\n sandboxId: string,\n opts?: SandboxConnectOpts\n ) {\n const timeoutMs = opts?.timeoutMs ?? DEFAULT_SANDBOX_TIMEOUT_MS\n\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.POST('/sandboxes/{sandboxID}/connect', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n body: {\n timeout: timeoutToSeconds(timeoutMs),\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n throw new NotFoundError(`Sandbox ${sandboxId} not found`)\n }\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n if (!res.data) {\n throw new Error('Sandbox not found')\n }\n\n return {\n sandboxId: `${res.data.sandboxID}-${res.data.clientID}`,\n envdVersion: res.data.envdVersion,\n envdAccessToken: res.data.envdAccessToken,\n sandboxDomain: undefined,\n }\n }\n\n /**\n * Reset sandbox memory and optionally resume the sandbox.\n *\n * @param sandboxId sandbox ID.\n * @param opts reset options.\n *\n * @returns `true` if reset succeeded; `false` if conflict (no-op).\n */\n static async reset(\n sandboxId: string,\n opts?: SandboxResetOpts\n ): Promise<boolean> {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.POST('/sandboxes/{sandboxID}/reset', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n body: {\n resume: opts?.resume ?? true,\n ...(typeof opts?.timeoutMs === 'number'\n ? { timeout: timeoutToSeconds(opts!.timeoutMs!) }\n : {}),\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n throw new NotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n if (res.error?.code === 409) {\n return false\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n return true\n }\n\n /**\n * Commit the sandbox to create a template snapshot.\n *\n * @param sandboxId sandbox ID.\n * @param opts commit options.\n *\n * @returns template information.\n */\n static async commit(\n sandboxId: string,\n opts?: SandboxCommitOpts\n ): Promise<Template> {\n const config = new ConnectionConfig(opts)\n const client = new ApiClient(config)\n\n const res = await client.api.POST('/sandboxes/{sandboxID}/commit', {\n params: {\n path: {\n sandboxID: sandboxId,\n },\n },\n body: opts?.alias ? { alias: opts.alias } : undefined,\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (res.error?.code === 404) {\n throw new NotFoundError(`Sandbox ${sandboxId} not found`)\n }\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n if (!res.data) {\n throw new Error('Commit response data is missing')\n }\n\n return {\n templateId: res.data.templateID,\n aliases: res.data.aliases,\n buildCount: res.data.buildCount,\n buildId: res.data.buildID,\n cpuCount: res.data.cpuCount,\n createdAt: new Date(res.data.createdAt),\n createdBy: res.data.createdBy,\n diskSizeMB: res.data.diskSizeMB,\n envdVersion: res.data.envdVersion,\n lastSpawnedAt: new Date(res.data.lastSpawnedAt),\n memoryMB: res.data.memoryMB,\n metadata: res.data.metadata,\n public: res.data.public,\n spawnCount: res.data.spawnCount,\n templateType: res.data.templateType,\n originSandboxID: res.data.originSandboxID,\n updatedAt: new Date(res.data.updatedAt),\n }\n }\n\n static async getEvents(\n opts?: SandboxEventsOpts\n ): Promise<SandboxEventsResult> {\n const config = new ConnectionConfig(opts)\n const url = new URL(`${config.apiUrl}/sandboxes/events`)\n if (opts?.startTime !== undefined)\n url.searchParams.set('startTime', String(opts.startTime))\n if (opts?.endTime !== undefined)\n url.searchParams.set('endTime', String(opts.endTime))\n if (opts?.sandboxID) url.searchParams.set('sandboxID', opts.sandboxID)\n if (opts?.templateID) url.searchParams.set('templateID', opts.templateID)\n if (opts?.events) url.searchParams.set('events', opts.events)\n if (opts?.state) url.searchParams.set('state', opts.state)\n if (opts?.orderAsc !== undefined)\n url.searchParams.set('orderAsc', String(opts.orderAsc))\n if (opts?.offset !== undefined)\n url.searchParams.set('offset', String(opts.offset))\n if (opts?.limit !== undefined)\n url.searchParams.set('limit', String(opts.limit))\n\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n ...config.headers,\n ...(config.apiKey ? { 'X-API-KEY': config.apiKey } : {}),\n ...(config.accessToken\n ? { Authorization: `Bearer ${config.accessToken}` }\n : {}),\n },\n signal: config.getSignal(opts?.requestTimeoutMs),\n })\n\n if (!response.ok) {\n throw await createRawApiError(response)\n }\n\n const data = (await response.json()) as {\n items?: SandboxEventItem[]\n total?: number\n hasMore?: boolean\n }\n\n return {\n items: data.items ?? [],\n total: data.total ?? 0,\n hasMore: data.hasMore ?? false,\n }\n }\n}\n\n/**\n * Paginator for listing sandboxes.\n *\n * @example\n * ```ts\n * const paginator = Sandbox.list()\n *\n * while (paginator.hasNext) {\n * const sandboxes = await paginator.nextItems()\n * console.log(sandboxes)\n * }\n * ```\n */\nexport class SandboxPaginator {\n private _hasNext: boolean\n private _nextToken?: string\n\n private readonly config: ConnectionConfig\n private client: ApiClient\n\n private query: SandboxListOpts['query']\n private readonly limit?: number\n\n constructor(opts?: SandboxListOpts) {\n this.config = new ConnectionConfig(opts)\n this.client = new ApiClient(this.config)\n\n this._hasNext = true\n this._nextToken = opts?.nextToken\n\n this.query = opts?.query\n this.limit = opts?.limit\n }\n\n /**\n * Returns True if there are more items to fetch.\n */\n get hasNext(): boolean {\n return this._hasNext\n }\n\n /**\n * Returns the next token to use for pagination.\n */\n get nextToken(): string | undefined {\n return this._nextToken\n }\n\n /**\n * Get the next page of sandboxes.\n *\n * @throws Error if there are no more items to fetch. Call this method only if `hasNext` is `true`.\n *\n * @returns List of sandboxes\n */\n async nextItems(): Promise<SandboxInfo[]> {\n if (!this.hasNext) {\n throw new Error('No more items to fetch')\n }\n\n let metadata = undefined\n if (this.query?.metadata) {\n const encodedPairs: Record<string, string> = Object.fromEntries(\n Object.entries(this.query.metadata).map(([key, value]) => [\n encodeURIComponent(key),\n encodeURIComponent(value),\n ])\n )\n\n metadata = new URLSearchParams(encodedPairs).toString()\n }\n\n const res = await this.client.api.GET('/v2/sandboxes', {\n params: {\n query: {\n metadata,\n state: this.query?.state,\n limit: this.limit,\n nextToken: this.nextToken,\n },\n },\n // requestTimeoutMs is already passed here via the connectionConfig.\n signal: this.config.getSignal(),\n })\n\n const err = handleApiError(res)\n if (err) {\n throw err\n }\n\n this._nextToken = res.response.headers.get('x-next-token') || undefined\n this._hasNext = !!this._nextToken\n\n return (res.data ?? []).map(\n (sandbox: components['schemas']['ListedSandbox']) => ({\n sandboxId: `${sandbox.sandboxID}-${sandbox.clientID}`,\n templateId: sandbox.templateID,\n ...(sandbox.alias && { name: sandbox.alias }),\n metadata: sandbox.metadata ?? {},\n startedAt: new Date(sandbox.startedAt),\n endAt: new Date(sandbox.endAt),\n state: sandbox.state,\n cpuCount: sandbox.cpuCount,\n memoryMB: sandbox.memoryMB,\n // envdVersion: sandbox.envdVersion,\n envdVersion: undefined,\n })\n )\n }\n}\n","export { ApiClient } from './api'\nexport type { components, paths } from './api'\n\nexport { ConnectionConfig } from './connectionConfig'\nexport type { ConnectionOpts, Username } from './connectionConfig'\nexport {\n AuthenticationError,\n InvalidArgumentError,\n NotEnoughSpaceError,\n NotFoundError,\n SandboxError,\n TemplateError,\n TimeoutError,\n RateLimitError,\n} from './errors'\nexport type { Logger } from './logs'\n\nexport { getSignature } from './sandbox/signature'\n\nexport { FileType } from './sandbox/filesystem'\nexport type { WriteInfo, EntryInfo, Filesystem } from './sandbox/filesystem'\nexport { FilesystemEventType } from './sandbox/filesystem/watchHandle'\nexport type {\n FilesystemEvent,\n WatchHandle,\n} from './sandbox/filesystem/watchHandle'\n\nexport { CommandExitError } from './sandbox/commands/commandHandle'\nexport type {\n CommandResult,\n Stdout,\n Stderr,\n PtyOutput,\n CommandHandle,\n} from './sandbox/commands/commandHandle'\nexport type {\n SandboxInfo,\n SandboxMetrics,\n SandboxOpts,\n SandboxApiOpts,\n SandboxConnectOpts,\n SandboxBetaCreateOpts,\n SandboxMetricsOpts,\n SandboxEventsOpts,\n SandboxEventItem,\n SandboxEventsResult,\n SandboxCommitOpts,\n SandboxCloneOpts,\n SandboxCloneResponse,\n CloneResult,\n SandboxState,\n SandboxListOpts,\n SandboxPaginator,\n Template,\n} from './sandbox/sandboxApi'\n\nexport type {\n ProcessInfo,\n CommandRequestOpts,\n CommandConnectOpts,\n CommandStartOpts,\n Commands,\n Pty,\n} from './sandbox/commands'\n\nexport { TemplateApi, TemplatePaginator } from './template'\nexport type {\n TemplateApiOpts,\n TemplateListOpts,\n PaginatedTemplatesResponse,\n} from './template'\n\nexport { Sandbox }\nimport { Sandbox } from './sandbox'\nexport default Sandbox\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,kBAAqC;;;ACA5C,OAAO,cAAc;;;ACEnB,cAAW;;;ADQb,SAAS,aAAoD;AAV7D,MAAAA,KAAA;AAYE,MAAK,WAAmB,KAAK;AAE3B,WAAO,EAAE,SAAS,OAAO,SAAS,WAAW,IAAI,QAAQ;AAAA,EAC3D;AAGA,MAAK,WAAmB,MAAM;AAE5B,WAAO,EAAE,SAAS,QAAQ,SAAS,WAAW,KAAK,QAAQ,KAAK;AAAA,EAClE;AAEA,QAAK,MAAAA,MAAA,WAAmB,YAAnB,gBAAAA,IAA4B,YAA5B,mBAAqC,UAAS,QAAQ;AACzD,WAAO,EAAE,SAAS,QAAQ,SAAS,SAAS,WAAW,UAAU;AAAA,EACnE;AAGA,MAAI,OAAO,gBAAgB,UAAU;AACnC,WAAO,EAAE,SAAS,eAAe,SAAS,UAAU;AAAA,EACtD;AAEA,QAAK,gBAAmB,cAAnB,mBAA8B,eAAc,sBAAsB;AACrE,WAAO,EAAE,SAAS,qBAAqB,SAAS,UAAU;AAAA,EAC5D;AAEA,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,EAAE,SAAS,WAAW,SAAS,SAAS,WAAW,UAAU;AAAA,EACtE;AAEA,SAAO,EAAE,SAAS,WAAW,SAAS,UAAU;AAClD;AAEO,IAAM,EAAE,SAAS,SAAS,eAAe,IAAI,WAAW;AA3C/D;AA6CO,IAAM,iBAAiB;AAAA,EAC5B,SAAU,OAAO,WAAW,eAAe,SAAS,QAAS;AAAA,EAC7D,MAAM;AAAA,EACN,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,WAAW;AAAA,EACX,aAAa;AAAA,EACb,UAAQ,cAAS,OAAT,mBAAa,WAAU;AACjC;AAEO,SAAS,UAAU,MAAc;AACtC,MAAI,YAAY,QAAQ;AAEtB,WAAO,KAAK,IAAI,IAAI,IAAI;AAAA,EAC1B;AAEA,MAAI,OAAO,YAAY,aAAa;AAClC,WAAO;AAAA,EACT;AAEA,SAAO,QAAQ,IAAI,IAAI;AACzB;;;AEjEO,SAAS,0BAA0B,SAAiB;AACzD,SAAO,IAAI;AAAA,IACT,GAAG,OAAO;AAAA,EACZ;AACF;AAOO,IAAM,eAAN,cAA2B,MAAM;AAAA,EACtC,YAAY,SAAc;AACxB,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAaO,IAAM,eAAN,cAA2B,aAAa;AAAA,EAC7C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,uBAAN,cAAmC,aAAa;AAAA,EACrD,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,sBAAN,cAAkC,aAAa;AAAA,EACpD,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,gBAAN,cAA4B,aAAa;AAAA,EAC9C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,sBAAN,cAAkC,aAAa;AAAA,EACpD,YAAY,SAAc;AACxB,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,gBAAN,cAA4B,aAAa;AAAA,EAC9C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,iBAAN,cAA6B,aAAa;AAAA,EAC/C,YAAY,SAAc;AACxB,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;;;ACtEA,SAAS,UAAU,KAAU;AAC3B,SAAO,KAAK,MAAM,KAAK,UAAU,GAAG,CAAC;AACvC;AAEO,SAAS,gBAAgB,QAA6B;AAC3D,WAAgB,QAAQ,QAA4B;AAAA;AA9BtD,UAAAC;AA+BI;AAAA,mCAAsB,SAAtB,uFAA8B;AAAnB,gBAAM,IAAjB;AACE,WAAAA,MAAA,OAAO,UAAP,gBAAAA,IAAA,aAAe,oBAAoB,UAAU,CAAC;AAC9C,gBAAM;AAAA,QACR;AAAA,eAHA,MA/BJ;AA+BI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAIF;AAAA;AAEA,SAAO,CAAC,SAAS,OAAO,QAAQ;AArClC,QAAAA,KAAA;AAsCI,KAAAA,MAAA,OAAO,SAAP,gBAAAA,IAAA,aAAc,iBAAiB,IAAI,GAAG;AAEtC,UAAM,MAAM,MAAM,KAAK,GAAG;AAC1B,QAAI,IAAI,QAAQ;AACd,aAAO,iCACF,MADE;AAAA,QAEL,SAAS,QAAQ,IAAI,OAAO;AAAA,MAC9B;AAAA,IACF,OAAO;AACL,mBAAO,SAAP,gCAAc,aAAa,UAAU,IAAI,OAAO;AAAA,IAClD;AAEA,WAAO;AAAA,EACT;AACF;AAEO,SAAS,gBAAgB,QAA4B;AAC1D,SAAO;AAAA,IACL,MAAM,UAAU,KAAK;AAxDzB,UAAAA;AAyDM,OAAAA,MAAA,OAAO,SAAP,gBAAAA,IAAA,aAAc,WAAW,IAAI,MAAM,IAAI,IAAI,GAAG;AAE9C,aAAO;AAAA,IACT;AAAA,IACA,MAAM,WAAW,KAAK;AA7D1B,UAAAA,KAAA;AA8DM,UAAI,IAAI,UAAU,KAAK;AACrB,SAAAA,MAAA,OAAO,UAAP,gBAAAA,IAAA,aAAe,aAAa,IAAI,QAAQ,IAAI;AAAA,MAC9C,OAAO;AACL,qBAAO,SAAP,gCAAc,aAAa,IAAI,QAAQ,IAAI;AAAA,MAC7C;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AJ/DO,SAAS,eACd,UACmB;AAVrB,MAAAC,KAAA;AAWE,MAAI,CAAC,SAAS,OAAO;AACnB;AAAA,EACF;AAEA,MAAI,SAAS,SAAS,WAAW,KAAK;AACpC,UAAMC,WAAU;AAChB,UAAM,WAAU,MAAAD,MAAA,SAAS,UAAT,gBAAAA,IAAgB,YAAhB,YAA2B,SAAS;AAEpD,QAAI,SAAS;AACX,aAAO,IAAI,eAAe,GAAGC,QAAO,MAAM,OAAO,EAAE;AAAA,IACrD;AACA,WAAO,IAAI,eAAeA,QAAO;AAAA,EACnC;AAEA,QAAM,WAAU,oBAAS,UAAT,mBAAgB,YAAhB,YAA2B,SAAS;AACpD,SAAO,IAAI,aAAa,GAAG,SAAS,SAAS,MAAM,KAAK,OAAO,EAAE;AACnE;AAKA,IAAM,YAAN,MAAgB;AAAA,EAGd,YACE,QACA,OAGI,EAAE,oBAAoB,OAAO,eAAe,MAAM,GACtD;AACA,SAAI,6BAAM,kBAAiB,CAAC,OAAO,QAAQ;AACzC,YAAM,IAAI;AAAA,QACR;AAAA,MAGF;AAAA,IACF;AAEA,SAAI,6BAAM,uBAAsB,CAAC,OAAO,aAAa;AACnD,YAAM,IAAI;AAAA,QACR;AAAA,MAEF;AAAA,IACF;AAEA,SAAK,MAAM,aAAoB;AAAA,MAC7B,SAAS,OAAO;AAAA;AAAA,MAEhB,SAAS,gEACJ,iBACC,OAAO,UAAU,EAAE,aAAa,OAAO,OAAO,IAC9C,OAAO,eAAe;AAAA,QACxB,eAAe,UAAU,OAAO,WAAW;AAAA,MAC7C,IACG,OAAO;AAAA,MAEZ,iBAAiB;AAAA,QACf,OAAO;AAAA,UACL,OAAO;AAAA,UACP,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF,CAAC;AAED,QAAI,OAAO,QAAQ;AACjB,WAAK,IAAI,IAAI,gBAAgB,OAAO,MAAM,CAAC;AAAA,IAC7C;AAAA,EACF;AACF;;;AK7EO,IAAM,qBAAqB;AAC3B,IAAM,0BAA0B;AAChC,IAAM,6BAA6B;AACnC,IAAM,8BAA8B;AAEpC,IAAM,wBAAwB;AAwD9B,IAAM,mBAAN,MAAM,kBAAiB;AAAA,EAa5B,YAAY,MAAuB;AA7ErC,QAAAC;AA8EI,SAAK,UAAS,6BAAM,WAAU,kBAAiB;AAC/C,SAAK,SAAQ,6BAAM,UAAS,kBAAiB;AAC7C,SAAK,UAAS,6BAAM,WAAU,kBAAiB;AAC/C,SAAK,eAAc,6BAAM,gBAAe,kBAAiB;AACzD,SAAK,oBAAmBA,MAAA,6BAAM,qBAAN,OAAAA,MAA0B;AAClD,SAAK,SAAS,6BAAM;AACpB,SAAK,WAAU,6BAAM,YAAW,CAAC;AACjC,SAAK,QAAQ,YAAY,IAAI,uBAAuB,OAAO;AAE3D,SAAK,SAAS,KAAK,QACf,0BACA,eAAe,KAAK,MAAM;AAAA,EAChC;AAAA,EAEA,WAAmB,SAAS;AAC1B,WAAO,UAAU,aAAa,KAAK;AAAA,EACrC;AAAA,EAEA,WAAmB,QAAQ;AACzB,YAAQ,UAAU,YAAY,KAAK,SAAS,YAAY,MAAM;AAAA,EAChE;AAAA,EAEA,WAAmB,SAAS;AAC1B,WAAO,UAAU,cAAc;AAAA,EACjC;AAAA,EAEA,WAAmB,cAAc;AAC/B,WAAO,UAAU,mBAAmB;AAAA,EACtC;AAAA,EAEA,UAAU,kBAA2B;AACnC,UAAM,UAAU,8CAAoB,KAAK;AAEzC,WAAO,UAAU,YAAY,QAAQ,OAAO,IAAI;AAAA,EAClD;AACF;AAOO,IAAM,kBAA4B;;;ACxHzC,eAAsB,OAAO,MAA+B;AAE1D,MAAI,OAAO,WAAW,aAAa;AACjC,UAAM,UAAU,IAAI,YAAY;AAChC,UAAM,aAAa,QAAQ,OAAO,IAAI;AACtC,UAAM,aAAa,MAAM,OAAO,OAAO,OAAO,WAAW,UAAU;AACnE,UAAM,YAAY,IAAI,WAAW,UAAU;AAC3C,WAAO,KAAK,OAAO,aAAa,GAAG,SAAS,CAAC;AAAA,EAC/C;AAIA,QAAM,EAAE,WAAW,IAAI,UAAQ,QAAa;AAC5C,QAAM,OAAO,WAAW,QAAQ,EAAE,OAAO,MAAM,MAAM,EAAE,OAAO;AAC9D,SAAO,KAAK,SAAS,QAAQ;AAC/B;AAEO,SAAS,iBAAiB,SAAyB;AACxD,SAAO,KAAK,KAAK,UAAU,GAAI;AACjC;;;ACGA,eAAsB,aAAa;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA6E;AAC3E,MAAI,CAAC,iBAAiB;AACpB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,QAAM,sBAAsB,sBACxB,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAI,sBAChC;AACJ,MAAI;AAEJ,MAAI,wBAAwB,MAAM;AAChC,mBAAe,GAAG,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,eAAe;AAAA,EAChE,OAAO;AACL,mBAAe,GAAG,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,eAAe,IAAI,oBAAoB,SAAS,CAAC;AAAA,EAClG;AAEA,QAAM,aAAa,MAAM,OAAO,YAAY;AAC5C,QAAM,YAAY,QAAQ,WAAW,QAAQ,OAAO,EAAE;AAEtD,SAAO;AAAA,IACL;AAAA,IACA,YAAY;AAAA,EACd;AACF;;;ACtDA;AAAA,EACE,gBAAAC;AAAA,EAGA,gBAAAC;AAAA,EACA,QAAAC;AAAA,OACK;;;ACNP,OAAOC,mBAAqC;AAc5C,SAAS,MAAM,oBAAoB;AAGnC,eAAsB,mBACpB,KACA;AAnBF,MAAAC;AAoBE,MAAI,CAAC,IAAI,OAAO;AACd;AAAA,EACF;AAEA,QAAM,UACJ,OAAO,IAAI,SAAS,WAChB,IAAI,UACJA,MAAA,IAAI,UAAJ,gBAAAA,IAAW,YAAY,MAAM,IAAI,SAAS,KAAK;AAErD,UAAQ,IAAI,SAAS,QAAQ;AAAA,IAC3B,KAAK;AACH,aAAO,IAAI,qBAAqB,OAAO;AAAA,IACzC,KAAK;AACH,aAAO,IAAI,oBAAoB,OAAO;AAAA,IACxC,KAAK;AACH,aAAO,IAAI,cAAc,OAAO;AAAA,IAClC,KAAK;AACH,aAAO,IAAI;AAAA,QACT,GAAG,IAAI,SAAS,MAAM,KAAK,OAAO;AAAA,MACpC;AAAA,IACF,KAAK;AACH,aAAO,0BAA0B,OAAO;AAAA,IAC1C,KAAK;AACH,aAAO,IAAI,oBAAoB,OAAO;AAAA,IACxC;AACE,aAAO,IAAI,aAAa,GAAG,IAAI,SAAS,MAAM,KAAK,OAAO,EAAE;AAAA,EAChE;AACF;AAEA,eAAsB,wBACpB,QACA;AAnDF,MAAAA;AAoDE,MAAI;AAEJ,MAAI;AACF,kBAAc,MAAM,OAAO,OAAO,aAAa,EAAE,EAAE,KAAK,GAAG;AAAA,EAC7D,SAAS,KAAK;AACZ,QAAI,eAAe,cAAc;AAC/B,UAAI,IAAI,SAAS,KAAK,aAAa;AACjC,cAAM,IAAI,cAAc,yCAAyC;AAAA,MACnE;AAAA,IACF;AAEA,UAAM;AAAA,EACR;AACA,QAAIA,MAAA,WAAW,UAAX,gBAAAA,IAAkB,MAAM,UAAS,SAAS;AAC5C,UAAM,IAAI,MAAM,sBAAsB;AAAA,EACxC;AAEA,SAAO,WAAW,MAAM,MAAM,MAAM;AACtC;AAEA,eAAsB,yBACpB,QACA;AA1EF,MAAAA;AA2EE,MAAI;AAEJ,MAAI;AACF,kBAAc,MAAM,OAAO,OAAO,aAAa,EAAE,EAAE,KAAK,GAAG;AAAA,EAC7D,SAAS,KAAK;AACZ,QAAI,eAAe,cAAc;AAC/B,UAAI,IAAI,SAAS,KAAK,aAAa;AACjC,cAAM,IAAI,cAAc,yCAAyC;AAAA,MACnE;AAAA,IACF;AAEA,UAAM;AAAA,EACR;AACA,QAAIA,MAAA,WAAW,UAAX,gBAAAA,IAAkB,UAAS,SAAS;AACtC,UAAM,IAAI,MAAM,sBAAsB;AAAA,EACxC;AAEA,SAAO,WAAW,MAAM;AAC1B;AAEA,IAAM,gBAAN,MAAoB;AAAA,EAIlB,YACE,QACA,UAGA;AACA,SAAK,MAAMC,cAAa;AAAA,MACtB,SAAS,OAAO;AAAA,MAChB,OAAO,iCAAQ;AAAA,MACf,SAAS,iCAAQ;AAAA;AAAA,IAEnB,CAAC;AACD,SAAK,UAAU,SAAS;AAExB,QAAI,OAAO,QAAQ;AACjB,WAAK,IAAI,IAAI,gBAAgB,OAAO,MAAM,CAAC;AAAA,IAC7C;AAAA,EACF;AACF;;;ACrHA,SAAS,QAAAC,OAAM,gBAAAC,qBAAoB;AAO5B,SAAS,eAAe,KAAqB;AAClD,MAAI,eAAeC,eAAc;AAC/B,YAAQ,IAAI,MAAM;AAAA,MAChB,KAAKC,MAAK;AACR,eAAO,IAAI,qBAAqB,IAAI,OAAO;AAAA,MAC7C,KAAKA,MAAK;AACR,eAAO,IAAI,oBAAoB,IAAI,OAAO;AAAA,MAC5C,KAAKA,MAAK;AACR,eAAO,IAAI,cAAc,IAAI,OAAO;AAAA,MACtC,KAAKA,MAAK;AACR,eAAO,0BAA0B,IAAI,OAAO;AAAA,MAC9C,KAAKA,MAAK;AACR,eAAO,IAAI;AAAA,UACT,GAAG,IAAI,OAAO;AAAA,QAChB;AAAA,MACF,KAAKA,MAAK;AACR,eAAO,IAAI;AAAA,UACT,GAAG,IAAI,OAAO;AAAA,QAChB;AAAA,MACF;AACE,eAAO,IAAI,aAAa,GAAG,IAAI,IAAI,KAAK,IAAI,OAAO,EAAE;AAAA,IACzD;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,SAAS,OAAuB;AACvC,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO,KAAK,KAAK;AAAA,IACnB,KAAK;AACH,aAAO,OAAO,KAAK,KAAK,EAAE,SAAS,QAAQ;AAAA,IAC7C,KAAK;AACH,aAAO,OAAO,KAAK,KAAK,EAAE,SAAS,QAAQ;AAAA,IAC7C;AACE,aAAO,KAAK,KAAK;AAAA,EACrB;AACF;AAEO,SAAS,qBAAqB,UAA2C;AAC9E,QAAM,QAAQ,GAAG,YAAY,eAAe;AAE5C,QAAM,UAAU,SAAS,KAAK;AAE9B,SAAO,EAAE,iBAAiB,SAAS,OAAO,GAAG;AAC/C;;;AChDA,SAAS,UAAU,UAAU,aAAa,mBAAmB;AAE7D,SAAS,sCAAsC;AAMxC,IAAM,6BACX,yBAAS,koGAAkoG,CAAC,8BAA8B,CAAC;AAwgBtqG,IAAM,aA4EX,4BAAY,4BAA4B,CAAC;;;ACzlBpC,IAAK,sBAAL,kBAAKC,yBAAL;AAIL,EAAAA,qBAAA,WAAQ;AAIR,EAAAA,qBAAA,YAAS;AAIT,EAAAA,qBAAA,YAAS;AAIT,EAAAA,qBAAA,YAAS;AAIT,EAAAA,qBAAA,WAAQ;AApBE,SAAAA;AAAA,GAAA;AAuBZ,SAAS,aAAa,MAAiB;AACrC,UAAQ,MAAM;AAAA,IACZ;AACE,aAAO;AAAA,IACT;AACE,aAAO;AAAA,IACT;AACE,aAAO;AAAA,IACT;AACE,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAqBO,IAAM,cAAN,MAAkB;AAAA,EACvB,YACmB,YACA,QACA,SACA,QACjB;AAJiB;AACA;AACA;AACA;AAEjB,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAO;AACX,SAAK,WAAW;AAAA,EAClB;AAAA,EAEe,gBAAgB;AAAA;AAC7B,UAAI;AACF;AAAA,qCAA0B,KAAK,SAA/B,uFAAuC;AAA5B,kBAAM,QAAjB;AACE,oBAAQ,MAAM,MAAM,MAAM;AAAA,cACxB,KAAK;AACH,sBAAM,MAAM;AACZ;AAAA,YACJ;AAAA,UACF;AAAA,iBANA,MArFN;AAqFM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOF,SAAS,KAAK;AACZ,cAAM,eAAe,GAAG;AAAA,MAC1B;AAAA,IACF;AAAA;AAAA,EAEA,MAAc,eAAe;AAjG/B,QAAAC,KAAA;AAkGI,QAAI;AACF;AAAA,mCAA0B,KAAK,cAAc,IAA7C,0EAAgD;AAArC,gBAAM,QAAjB;AACE,gBAAM,YAAY,aAAa,MAAM,MAAM,IAAI;AAC/C,cAAI,cAAc,QAAW;AAC3B;AAAA,UACF;AAEA,WAAAA,MAAA,KAAK,YAAL,gBAAAA,IAAA,WAAe;AAAA,YACb,MAAM,MAAM,MAAM;AAAA,YAClB,MAAM;AAAA,UACR;AAAA,QACF;AAAA,eAVA,MAnGN;AAmGM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWA,iBAAK,WAAL;AAAA,IACF,SAAS,KAAK;AACZ,iBAAK,WAAL,8BAAc;AAAA,IAChB;AAAA,EACF;AACF;;;AJxFA,SAAS,uBAAuB;;;AK3BzB,IAAM,+BAA+B;;;AL0FrC,IAAKC,YAAL,kBAAKA,cAAL;AAIL,EAAAA,UAAA,UAAO;AAIP,EAAAA,UAAA,SAAM;AARI,SAAAA;AAAA,gBAAA;AAgBZ,SAAS,YAAY,UAAsB;AACzC,UAAQ,UAAU;AAAA,IAChB;AACE,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,gBAAgB,cAAqC;AAC5D,MAAI,CAAC,aAAc,QAAO;AAE1B,SAAO,IAAI;AAAA,IACT,OAAO,aAAa,OAAO,IAAI,MAC7B,KAAK,MAAM,aAAa,QAAQ,GAAS;AAAA,EAC7C;AACF;AA6CO,IAAMC,cAAN,MAAiB;AAAA,EAMtB,YACE,WACiB,SACA,kBACjB;AAFiB;AACA;AANnB,SAAiB,sBAAsB;AACvC;AAAA,SAAiB,wBAAwB;AAOvC,SAAK,MAAMC,cAAa,YAAmB,SAAS;AAAA,EACtD;AAAA,EA8DA,MAAM,KACJ,MACA,MAGkB;AAtPtB,QAAAC;AAuPI,UAAM,UAASA,MAAA,6BAAM,WAAN,OAAAA,MAAgB;AAE/B,UAAM,MAAM,MAAM,KAAK,QAAQ,IAAI,IAAI,UAAU;AAAA,MAC/C,QAAQ;AAAA,QACN,OAAO;AAAA,UACL;AAAA,UACA,WAAU,6BAAM,SAAQ;AAAA,QAC1B;AAAA,MACF;AAAA,MACA,SAAS,WAAW,UAAU,gBAAgB;AAAA,MAC9C,QAAQ,KAAK,iBAAiB,UAAU,6BAAM,gBAAgB;AAAA,IAChE,CAAC;AAED,UAAM,MAAM,MAAM,mBAAmB,GAAG;AACxC,QAAI,KAAK;AACP,YAAM;AAAA,IACR;AAEA,QAAI,WAAW,SAAS;AACtB,aAAO,IAAI,WAAW,IAAI,IAAmB;AAAA,IAC/C;AAGA,QAAI,IAAI,SAAS,QAAQ,IAAI,gBAAgB,MAAM,KAAK;AACtD,UAAI,WAAW,QAAQ;AACrB,eAAO,IAAI,KAAK,CAAC,CAAC;AAAA,MACpB;AAEA,aAAO;AAAA,IACT;AAEA,WAAO,IAAI;AAAA,EACb;AAAA,EA2BA,MAAM,MACJ,aACA,YAMA,MACkC;AAClC,QAAI,OAAO,gBAAgB,YAAY,CAAC,MAAM,QAAQ,WAAW,GAAG;AAClE,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AAEA,QAAI,OAAO,gBAAgB,YAAY,MAAM,QAAQ,UAAU,GAAG;AAChE,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,EAAE,MAAM,WAAW,WAAW,IAClC,OAAO,gBAAgB,WACnB;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,YAAY;AAAA,QACV;AAAA,UACE,MAAM;AAAA,QAKR;AAAA,MACF;AAAA,IACF,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,YAAY;AAAA,IACd;AAEN,QAAI,WAAW,WAAW,EAAG,QAAO,CAAC;AAErC,UAAM,QAAQ,MAAM,QAAQ;AAAA,MAC1B,WAAW,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC;AAAA,IACnD;AAEA,UAAM,MAAM,MAAM,KAAK,QAAQ,IAAI,KAAK,UAAU;AAAA,MAChD,QAAQ;AAAA,QACN,OAAO;AAAA,UACL;AAAA,UACA,WAAU,uCAAW,SAAQ;AAAA,QAC/B;AAAA,MACF;AAAA,MACA,iBAAiB;AACf,eAAO,MAAM,OAAO,CAAC,IAAI,MAAM,MAAM;AAKnC,aAAG,OAAO,QAAQ,MAAM,WAAW,CAAC,EAAE,IAAI;AAE1C,iBAAO;AAAA,QACT,GAAG,IAAI,SAAS,CAAC;AAAA,MACnB;AAAA,MACA,MAAM,CAAC;AAAA,MACP,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,oBAAoB;AAAA;AAAA,MACtB;AAAA,IACF,CAAC;AAED,UAAM,MAAM,MAAM,mBAAmB,GAAG;AACxC,QAAI,KAAK;AACP,YAAM;AAAA,IACR;AAEA,UAAM,QAAQ,IAAI;AAClB,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,MAAM,oDAAoD;AAAA,IACtE;AAEA,WAAO,MAAM,WAAW,KAAK,OAAO,MAAM,CAAC,IAAI;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,KAAK,MAAc,MAAiD;AA/Y5E,QAAAA;AAgZI,QAAI,QAAO,6BAAM,WAAU,YAAY,KAAK,QAAQ,GAAG;AACrD,YAAM,IAAI,qBAAqB,8BAA8B;AAAA,IAC/D;AAEA,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,IAAI;AAAA,QACzB;AAAA,UACE;AAAA,UACA,QAAOA,MAAA,6BAAM,UAAN,OAAAA,MAAe;AAAA,QACxB;AAAA,QACA;AAAA,UACE,SAAS,qBAAqB,6BAAM,IAAI;AAAA,UACxC,QAAQ,KAAK,iBAAiB,UAAU,6BAAM,gBAAgB;AAAA,QAChE;AAAA,MACF;AAEA,YAAM,UAAuB,CAAC;AAE9B,iBAAW,KAAK,IAAI,SAAS;AAC3B,cAAM,OAAO,YAAY,EAAE,IAAI;AAE/B,YAAI,MAAM;AACR,kBAAQ,KAAK;AAAA,YACX,MAAM,EAAE;AAAA,YACR;AAAA,YACA,MAAM,EAAE;AAAA,YACR,MAAM,OAAO,EAAE,IAAI;AAAA,YACnB,MAAM,EAAE;AAAA,YACR,aAAa,EAAE;AAAA,YACf,OAAO,EAAE;AAAA,YACT,OAAO,EAAE;AAAA,YACT,cAAc,gBAAgB,EAAE,YAAY;AAAA,YAC5C,eAAe,EAAE;AAAA,UACnB,CAAC;AAAA,QACH;AAAA,MACF;AAEA,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,YAAM,eAAe,GAAG;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,QAAQ,MAAc,MAAgD;AAC1E,QAAI;AACF,YAAM,KAAK,IAAI;AAAA,QACb,EAAE,KAAK;AAAA,QACP;AAAA,UACE,SAAS,qBAAqB,6BAAM,IAAI;AAAA,UACxC,QAAQ,KAAK,iBAAiB,UAAU,6BAAM,gBAAgB;AAAA,QAChE;AAAA,MACF;AAEA,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,UAAI,eAAeC,eAAc;AAC/B,YAAI,IAAI,SAASC,MAAK,eAAe;AACnC,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,YAAM,eAAe,GAAG;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,OACJ,SACA,SACA,MACoB;AACpB,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,IAAI;AAAA,QACzB;AAAA,UACE,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA;AAAA,UACE,SAAS,qBAAqB,6BAAM,IAAI;AAAA,UACxC,QAAQ,KAAK,iBAAiB,UAAU,6BAAM,gBAAgB;AAAA,QAChE;AAAA,MACF;AAEA,YAAM,QAAQ,IAAI;AAClB,UAAI,CAAC,OAAO;AACV,cAAM,IAAI,MAAM,oDAAoD;AAAA,MACtE;AAEA,aAAO;AAAA,QACL,MAAM,MAAM;AAAA,QACZ,MAAM,YAAY,MAAM,IAAI;AAAA,QAC5B,MAAM,MAAM;AAAA,QACZ,MAAM,OAAO,MAAM,IAAI;AAAA,QACvB,MAAM,MAAM;AAAA,QACZ,aAAa,MAAM;AAAA,QACnB,OAAO,MAAM;AAAA,QACb,OAAO,MAAM;AAAA,QACb,cAAc,gBAAgB,MAAM,YAAY;AAAA,QAChD,eAAe,MAAM;AAAA,MACvB;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,eAAe,GAAG;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OAAO,MAAc,MAA6C;AACtE,QAAI;AACF,YAAM,KAAK,IAAI;AAAA,QACb,EAAE,KAAK;AAAA,QACP;AAAA,UACE,SAAS,qBAAqB,6BAAM,IAAI;AAAA,UACxC,QAAQ,KAAK,iBAAiB,UAAU,6BAAM,gBAAgB;AAAA,QAChE;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,eAAe,GAAG;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,OAAO,MAAc,MAAgD;AACzE,QAAI;AACF,YAAM,KAAK,IAAI;AAAA,QACb,EAAE,KAAK;AAAA,QACP;AAAA,UACE,SAAS,qBAAqB,6BAAM,IAAI;AAAA,UACxC,QAAQ,KAAK,iBAAiB,UAAU,6BAAM,gBAAgB;AAAA,QAChE;AAAA,MACF;AAEA,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,UAAI,eAAeD,eAAc;AAC/B,YAAI,IAAI,SAASC,MAAK,UAAU;AAC9B,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,YAAM,eAAe,GAAG;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,QACJ,MACA,MACoB;AACpB,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,IAAI;AAAA,QACzB,EAAE,KAAK;AAAA,QACP,EAAE,SAAS,qBAAqB,6BAAM,IAAI,EAAE;AAAA,MAC9C;AAEA,UAAI,CAAC,IAAI,OAAO;AACd,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL,MAAM,IAAI,MAAM;AAAA,QAChB,MAAM,YAAY,IAAI,MAAM,IAAI;AAAA,QAChC,MAAM,IAAI,MAAM;AAAA,QAChB,MAAM,OAAO,IAAI,MAAM,IAAI;AAAA,QAC3B,MAAM,IAAI,MAAM;AAAA,QAChB,aAAa,IAAI,MAAM;AAAA,QACvB,OAAO,IAAI,MAAM;AAAA,QACjB,OAAO,IAAI,MAAM;AAAA,QACjB,cAAc,gBAAgB,IAAI,MAAM,YAAY;AAAA,QACpD,eAAe,IAAI,MAAM;AAAA,MAC3B;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,eAAe,GAAG;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,SACJ,MACA,SACA,MAGsB;AAnnB1B,QAAAF,KAAA;AAonBI,SACE,6BAAM,cACN,KAAK,QAAQ,WACb,gBAAgB,KAAK,QAAQ,SAAS,4BAA4B,IAAI,GACtE;AACA,YAAM,IAAI;AAAA,QACR;AAAA,MAEF;AAAA,IACF;AAEA,UAAM,oBACJA,MAAA,6BAAM,qBAAN,OAAAA,MAA0B,KAAK,iBAAiB;AAElD,UAAM,aAAa,IAAI,gBAAgB;AAEvC,UAAM,aAAa,mBACf,WAAW,MAAM;AACf,iBAAW,MAAM;AAAA,IACnB,GAAG,gBAAgB,IACnB;AAEJ,UAAM,SAAS,KAAK,IAAI;AAAA,MACtB;AAAA,QACE;AAAA,QACA,YAAW,kCAAM,cAAN,YAAmB,KAAK;AAAA,MACrC;AAAA,MACA;AAAA,QACE,SAAS,iCACJ,qBAAqB,6BAAM,IAAI,IAD3B;AAAA,UAEP,CAAC,qBAAqB,GAAG,4BAA4B,SAAS;AAAA,QAChE;AAAA,QACA,QAAQ,WAAW;AAAA,QACnB,YAAW,kCAAM,cAAN,YAAmB,KAAK;AAAA,MACrC;AAAA,IACF;AAEA,QAAI;AACF,YAAM,yBAAyB,MAAM;AAErC,mBAAa,UAAU;AAEvB,aAAO,IAAI;AAAA,QACT,MAAM,WAAW,MAAM;AAAA,QACvB;AAAA,QACA;AAAA,QACA,6BAAM;AAAA,MACR;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,eAAe,GAAG;AAAA,IAC1B;AAAA,EACF;AACF;;;AMloBO,IAAM,mBAAN,cAA+B,aAAsC;AAAA,EAC1E,YAA6B,QAAuB;AAClD,UAAM,OAAO,KAAK;AADS;AAE3B,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,WAAW;AACb,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,QAAQ;AACV,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAAS;AACX,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAAS;AACX,WAAO,KAAK,OAAO;AAAA,EACrB;AACF;AASO,IAAM,gBAAN,MAIP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcE,YACW,KACQ,kBACA,YACA,QACA,UACA,UACA,OACjB;AAPS;AACQ;AACA;AACA;AACA;AACA;AACA;AApBnB,SAAQ,UAAU;AAClB,SAAQ,UAAU;AAqBhB,SAAK,QAAQ,KAAK,aAAa;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,WAAW;AArHjB,QAAAG;AAsHI,YAAOA,MAAA,KAAK,WAAL,gBAAAA,IAAa;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,QAAQ;AA5Hd,QAAAA;AA6HI,YAAOA,MAAA,KAAK,WAAL,gBAAAA,IAAa;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAAS;AACX,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAAS;AACX,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OAAO;AACX,UAAM,KAAK;AAEX,QAAI,KAAK,gBAAgB;AACvB,YAAM,KAAK;AAAA,IACb;AAEA,QAAI,CAAC,KAAK,QAAQ;AAChB,YAAM,IAAI,aAAa,iCAAiC;AAAA,IAC1D;AAEA,QAAI,KAAK,OAAO,aAAa,GAAG;AAC9B,YAAM,IAAI,iBAAiB,KAAK,MAAM;AAAA,IACxC;AAEA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa;AACjB,SAAK,iBAAiB;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OAAO;AACX,WAAO,MAAM,KAAK,WAAW;AAAA,EAC/B;AAAA,EAEe,gBAEb;AAAA;AA5LJ,UAAAA;AA6LI;AAAA,mCAA0B,KAAK,SAA/B,uFAAuC;AAA5B,gBAAM,QAAjB;AACE,gBAAM,KAAIA,MAAA,+BAAO,UAAP,gBAAAA,IAAc;AACxB,cAAI;AAEJ,kBAAQ,uBAAG,MAAM;AAAA,YACf,KAAK;AACH,sBAAQ,EAAE,MAAM,OAAO,MAAM;AAAA,gBAC3B,KAAK;AACH,wBAAM,IAAI,YAAY,EAAE,OAAO,EAAE,MAAM,OAAO,KAAK;AACnD,uBAAK,WAAW;AAChB,wBAAM,CAAC,KAAe,MAAM,IAAI;AAChC;AAAA,gBACF,KAAK;AACH,wBAAM,IAAI,YAAY,EAAE,OAAO,EAAE,MAAM,OAAO,KAAK;AACnD,uBAAK,WAAW;AAChB,wBAAM,CAAC,MAAM,KAAe,IAAI;AAChC;AAAA,gBACF,KAAK;AACH,wBAAM,CAAC,MAAM,MAAM,EAAE,MAAM,OAAO,KAAkB;AACpD;AAAA,cACJ;AACA;AAAA,YACF,KAAK;AACH,mBAAK,SAAS;AAAA,gBACZ,UAAU,EAAE,MAAM;AAAA,gBAClB,OAAO,EAAE,MAAM;AAAA,gBACf,QAAQ,KAAK;AAAA,gBACb,QAAQ,KAAK;AAAA,cACf;AACA;AAAA,UACJ;AAAA,QAEF;AAAA,eAhCA,MA7LJ;AA6LI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAiCF;AAAA;AAAA,EAEA,MAAc,eAAe;AAhO/B,QAAAA,KAAA;AAiOI,QAAI;AACF;AAAA,mCAA0C,KAAK,cAAc,IAA7D,0EAAgE;AAArD,gBAAM,CAAC,QAAQ,QAAQ,GAAG,IAArC;AACE,cAAI,WAAW,MAAM;AACnB,aAAAA,MAAA,KAAK,aAAL,gBAAAA,IAAA,WAAgB;AAAA,UAClB,WAAW,WAAW,MAAM;AAC1B,uBAAK,aAAL,8BAAgB;AAAA,UAClB,WAAW,KAAK;AACd,uBAAK,UAAL,8BAAa;AAAA,UACf;AAAA,QACF;AAAA,eARA,MAlON;AAkOM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASF,SAAS,GAAG;AACV,WAAK,iBAAiB,eAAe,CAAC;AAAA,IACxC;AAAA,EACF;AACF;;;AChJO,IAAM,cAAN,MAAkB;AAAA,EACb,cAAc;AAAA,EAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBzB,aAAa,cACX,MACqC;AACrC,UAAM,SAAS,IAAI,iBAAiB,IAAI;AACxC,UAAM,SAAS,IAAI,UAAU,MAAM;AAEnC,UAAM,MAAM,MAAM,OAAO,IAAI,IAAI,iBAAiB;AAAA,MAChD,QAAQ;AAAA,QACN,OAAO;AAAA,UACL,eAAe,6BAAM;AAAA,UACrB,MAAM,6BAAM;AAAA,UACZ,OAAO,6BAAM;AAAA,QACf;AAAA,MACF;AAAA,MACA,QAAQ,OAAO,UAAU,6BAAM,gBAAgB;AAAA,IACjD,CAAC;AAED,UAAM,MAAM,eAAe,GAAG;AAC9B,QAAI,KAAK;AACP,YAAM;AAAA,IACR;AAEA,QAAI,CAAC,IAAI,MAAM;AACb,YAAM,IAAI,MAAM,wCAAwC;AAAA,IAC1D;AAGA,UAAM,aAAa,IAAI,KAAK,aAAa,CAAC,GAAG;AAAA,MAC3C,CAAC,OAA0C;AAAA,QACzC,YAAY,EAAE;AAAA,QACd,SAAS,EAAE;AAAA,QACX,YAAY,EAAE;AAAA,QACd,SAAS,EAAE;AAAA,QACX,UAAU,EAAE;AAAA,QACZ,WAAW,IAAI,KAAK,EAAE,SAAS;AAAA,QAC/B,WAAW,EAAE;AAAA,QACb,YAAY,EAAE;AAAA,QACd,aAAa,EAAE;AAAA,QACf,eAAe,IAAI,KAAK,EAAE,aAAa;AAAA,QACvC,UAAU,EAAE;AAAA,QACZ,UAAU,EAAE;AAAA,QACZ,QAAQ,EAAE;AAAA,QACV,YAAY,EAAE;AAAA,QACd,cAAc,EAAE;AAAA,QAChB,iBAAiB,EAAE;AAAA,QACnB,WAAW,IAAI,KAAK,EAAE,SAAS;AAAA,MACjC;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA,MAAM,IAAI,KAAK;AAAA,MACf,OAAO,IAAI,KAAK;AAAA,MAChB,OAAO,IAAI,KAAK;AAAA,MAChB,YAAY,IAAI,KAAK;AAAA,IACvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,aAAa,eACX,YACA,MACkB;AAClB,UAAM,SAAS,IAAI,iBAAiB,IAAI;AACxC,UAAM,SAAS,IAAI,UAAU,MAAM;AAEnC,UAAM,MAAM,MAAM,OAAO,IAAI,OAAO,2BAA2B;AAAA,MAC7D,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ,YAAY;AAAA,QACd;AAAA,MACF;AAAA,MACA,QAAQ,OAAO,UAAU,6BAAM,gBAAgB;AAAA,IACjD,CAAC;AAED,UAAM,MAAM,eAAe,GAAG;AAC9B,QAAI,KAAK;AACP,YAAM;AAAA,IACR;AAGA,WAAO,IAAI,SAAS,WAAW;AAAA,EACjC;AACF;AAgBO,IAAM,oBAAN,MAAwB;AAAA,EAW7B,YAAY,MAAyB;AA/OvC,QAAAC,KAAA;AAgPI,SAAK,SAAS,IAAI,iBAAiB,IAAI;AACvC,SAAK,SAAS,IAAI,UAAU,KAAK,MAAM;AAEvC,SAAK,WAAW;AAChB,SAAK,iBAAgBA,MAAA,6BAAM,SAAN,OAAAA,MAAc,KAAK;AACxC,SAAK,cAAc;AAEnB,SAAK,eAAe,6BAAM;AAC1B,SAAK,SAAQ,kCAAM,UAAN,YAAe;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,UAAmB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,cAAsB;AACxB,WAAO,KAAK,eAAe;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,aAAiC;AACnC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,WAAgD;AACpD,QAAI,CAAC,KAAK,SAAS;AACjB,YAAM,IAAI,MAAM,wBAAwB;AAAA,IAC1C;AAEA,SAAK;AAEL,UAAM,MAAM,MAAM,KAAK,OAAO,IAAI,IAAI,iBAAiB;AAAA,MACrD,QAAQ;AAAA,QACN,OAAO;AAAA,UACL,eAAe,KAAK;AAAA,UACpB,MAAM,KAAK,eAAe;AAAA;AAAA,UAC1B,OAAO,KAAK;AAAA,QACd;AAAA,MACF;AAAA,MACA,QAAQ,KAAK,OAAO,UAAU;AAAA,IAChC,CAAC;AAED,UAAM,MAAM,eAAe,GAAG;AAC9B,QAAI,KAAK;AACP,YAAM;AAAA,IACR;AAEA,QAAI,CAAC,IAAI,MAAM;AACb,YAAM,IAAI,MAAM,wCAAwC;AAAA,IAC1D;AAEA,SAAK,cAAc,IAAI,KAAK;AAC5B,SAAK,WAAW,KAAK,eAAe,IAAI,IAAI,KAAK;AAGjD,UAAM,aAAa,IAAI,KAAK,aAAa,CAAC,GAAG;AAAA,MAC3C,CAAC,OAA0C;AAAA,QACzC,YAAY,EAAE;AAAA,QACd,SAAS,EAAE;AAAA,QACX,YAAY,EAAE;AAAA,QACd,SAAS,EAAE;AAAA,QACX,UAAU,EAAE;AAAA,QACZ,WAAW,IAAI,KAAK,EAAE,SAAS;AAAA,QAC/B,WAAW,EAAE;AAAA,QACb,YAAY,EAAE;AAAA,QACd,aAAa,EAAE;AAAA,QACf,eAAe,IAAI,KAAK,EAAE,aAAa;AAAA,QACvC,UAAU,EAAE;AAAA,QACZ,UAAU,EAAE;AAAA,QACZ,QAAQ,EAAE;AAAA,QACV,YAAY,EAAE;AAAA,QACd,cAAc,EAAE;AAAA,QAChB,iBAAiB,EAAE;AAAA,QACnB,WAAW,IAAI,KAAK,EAAE,SAAS;AAAA,MACjC;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA,MAAM,IAAI,KAAK;AAAA,MACf,OAAO,IAAI,KAAK;AAAA,MAChB,OAAO,IAAI,KAAK;AAAA,MAChB,YAAY,IAAI,KAAK;AAAA,IACvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,eAAe;AACpB,SAAK,WAAW;AAChB,SAAK,cAAc;AAAA,EACrB;AACF;;;AC7VA,SAAS,8BAA8B;;;ACAvC;AAAA,EACE,QAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,gBAAAC;AAAA,OAGK;;;ACDP,SAAS,YAAAC,WAAU,YAAAC,WAAU,eAAAC,cAAa,eAAAC,oBAAmB;AAMtD,IAAM,uBACX,gBAAAF,UAAS,86GAA86G;AAynBl7G,IAAM,UA4DX,gBAAAG,aAAY,sBAAsB,CAAC;;;ACjsBrC;AAAA,EACE,QAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,gBAAAC;AAAA,OAGK;AAyDA,IAAM,MAAN,MAAU;AAAA,EAGf,YACmB,WACA,kBACjB;AAFiB;AACA;AAEjB,SAAK,MAAMC,cAAa,SAAgB,KAAK,SAAS;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OAAO,MAAqB;AAhFpC,QAAAC,KAAA;AAiFI,UAAM,oBACJA,MAAA,6BAAM,qBAAN,OAAAA,MAA0B,KAAK,iBAAiB;AAClD,UAAM,QAAO,kCAAM,SAAN,YAAc,CAAC;AAC5B,SAAK,OAAO;AACZ,UAAM,aAAa,IAAI,gBAAgB;AAEvC,UAAM,aAAa,WAAW,MAAM;AAClC,iBAAW,MAAM;AAAA,IACnB,GAAG,gBAAgB;AAEnB,UAAM,SAAS,KAAK,IAAI;AAAA,MACtB;AAAA,QACE,SAAS;AAAA,UACP,KAAK;AAAA,UACL,MAAM,CAAC,MAAM,IAAI;AAAA,UACjB;AAAA,UACA,KAAK,6BAAM;AAAA,QACb;AAAA,QACA,KAAK;AAAA,UACH,MAAM;AAAA,YACJ,MAAM,KAAK;AAAA,YACX,MAAM,KAAK;AAAA,UACb;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,QACE,SAAS,iCACJ,qBAAqB,6BAAM,IAAI,IAD3B;AAAA,UAEP,CAAC,qBAAqB,GAAG,4BAA4B,SAAS;AAAA,QAChE;AAAA,QACA,QAAQ,WAAW;AAAA,QACnB,YAAW,kCAAM,cAAN,YAAmB;AAAA,MAChC;AAAA,IACF;AAEA,QAAI;AACF,YAAM,MAAM,MAAM,wBAAwB,MAAM;AAEhD,mBAAa,UAAU;AAEvB,aAAO,IAAI;AAAA,QACT;AAAA,QACA,MAAM,WAAW,MAAM;AAAA,QACvB,MAAM,KAAK,KAAK,GAAG;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK;AAAA,MACP;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,eAAe,GAAG;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,UACJ,KACA,MACA,MACe;AACf,QAAI;AACF,YAAM,KAAK,IAAI;AAAA,QACb;AAAA,UACE,OAAO;AAAA,YACL,OAAO;AAAA,cACL,MAAM;AAAA,cACN,OAAO;AAAA,YACT;AAAA,UACF;AAAA,UACA,SAAS;AAAA,YACP,UAAU;AAAA,cACR,MAAM;AAAA,cACN,OAAO;AAAA,YACT;AAAA,UACF;AAAA,QACF;AAAA,QACA;AAAA,UACE,QAAQ,KAAK,iBAAiB,UAAU,6BAAM,gBAAgB;AAAA,QAChE;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,eAAe,GAAG;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,OACJ,KACA,MAIA,MACe;AACf,QAAI;AACF,YAAM,KAAK,IAAI;AAAA,QACb;AAAA,UACE,SAAS;AAAA,YACP,UAAU;AAAA,cACR,MAAM;AAAA,cACN,OAAO;AAAA,YACT;AAAA,UACF;AAAA,UACA,KAAK;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAAA,QACA;AAAA,UACE,QAAQ,KAAK,iBAAiB,UAAU,6BAAM,gBAAgB;AAAA,QAChE;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,eAAe,GAAG;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,KACJ,KACA,MACkB;AAClB,QAAI;AACF,YAAM,KAAK,IAAI;AAAA,QACb;AAAA,UACE,SAAS;AAAA,YACP,UAAU;AAAA,cACR,MAAM;AAAA,cACN,OAAO;AAAA,YACT;AAAA,UACF;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,UACE,QAAQ,KAAK,iBAAiB,UAAU,6BAAM,gBAAgB;AAAA,QAChE;AAAA,MACF;AAEA,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,UAAI,eAAeC,eAAc;AAC/B,YAAI,IAAI,SAASC,MAAK,UAAU;AAC9B,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,YAAM,eAAe,GAAG;AAAA,IAC1B;AAAA,EACF;AACF;;;AFrIO,IAAM,WAAN,MAAe;AAAA;AAAA,EAKpB,YACE,WACiB,kBACjB;AADiB;AAJnB,SAAiB,kCAAkC;AAMjD,SAAK,MAAMC,cAAa,SAAgB,SAAS;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,KAAK,MAAmD;AAC5D,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,IAAI;AAAA,QACzB,CAAC;AAAA,QACD;AAAA,UACE,QAAQ,KAAK,iBAAiB,UAAU,6BAAM,gBAAgB;AAAA,QAChE;AAAA,MACF;AAEA,aAAO,IAAI,UAAU,IAAI,CAAC,MAAO;AAAA,QAC/B,KAAK,EAAE;AAAA,SACH,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,IAFK;AAAA,QAG/B,MAAM,EAAE,OAAQ;AAAA,QAChB,MAAM,EAAE,OAAQ;AAAA,QAChB,KAAK,EAAE,OAAQ;AAAA,UACX,EAAE,OAAQ,OAAO,EAAE,KAAK,EAAE,OAAQ,IAAI,EAC1C;AAAA,IACJ,SAAS,KAAK;AACZ,YAAM,eAAe,GAAG;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,UACJ,KACA,MACA,MACe;AACf,QAAI;AACF,YAAM,KAAK,IAAI;AAAA,QACb;AAAA,UACE,SAAS;AAAA,YACP,UAAU;AAAA,cACR,MAAM;AAAA,cACN,OAAO;AAAA,YACT;AAAA,UACF;AAAA,UACA,OAAO;AAAA,YACL,OAAO;AAAA,cACL,MAAM;AAAA,cACN,OAAO,IAAI,YAAY,EAAE,OAAO,IAAI;AAAA,YACtC;AAAA,UACF;AAAA,QACF;AAAA,QACA;AAAA,UACE,QAAQ,KAAK,iBAAiB,UAAU,6BAAM,gBAAgB;AAAA,QAChE;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,eAAe,GAAG;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,KAAK,KAAa,MAA6C;AACnE,QAAI;AACF,YAAM,KAAK,IAAI;AAAA,QACb;AAAA,UACE,SAAS;AAAA,YACP,UAAU;AAAA,cACR,MAAM;AAAA,cACN,OAAO;AAAA,YACT;AAAA,UACF;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,UACE,QAAQ,KAAK,iBAAiB,UAAU,6BAAM,gBAAgB;AAAA,QAChE;AAAA,MACF;AAEA,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,UAAI,eAAeC,eAAc;AAC/B,YAAI,IAAI,SAASC,MAAK,UAAU;AAC9B,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,YAAM,eAAe,GAAG;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,QACJ,KACA,MACwB;AArP5B,QAAAC,KAAA;AAsPI,UAAM,oBACJA,MAAA,6BAAM,qBAAN,OAAAA,MAA0B,KAAK,iBAAiB;AAElD,UAAM,aAAa,IAAI,gBAAgB;AAEvC,UAAM,aAAa,mBACf,WAAW,MAAM;AACf,iBAAW,MAAM;AAAA,IACnB,GAAG,gBAAgB,IACnB;AAEJ,UAAM,SAAS,KAAK,IAAI;AAAA,MACtB;AAAA,QACE,SAAS;AAAA,UACP,UAAU;AAAA,YACR,MAAM;AAAA,YACN,OAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,QACE,QAAQ,WAAW;AAAA,QACnB,SAAS;AAAA,UACP,CAAC,qBAAqB,GAAG,4BAA4B,SAAS;AAAA,QAChE;AAAA,QACA,YAAW,kCAAM,cAAN,YAAmB,KAAK;AAAA,MACrC;AAAA,IACF;AAEA,QAAI;AACF,YAAMC,OAAM,MAAM,wBAAwB,MAAM;AAEhD,mBAAa,UAAU;AAEvB,aAAO,IAAI;AAAA,QACTA;AAAA,QACA,MAAM,WAAW,MAAM;AAAA,QACvB,MAAM,KAAK,KAAKA,IAAG;AAAA,QACnB;AAAA,QACA,6BAAM;AAAA,QACN,6BAAM;AAAA,QACN;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,eAAe,GAAG;AAAA,IAC1B;AAAA,EACF;AAAA,EA6CA,MAAM,IACJ,KACA,MACwC;AACxC,UAAM,OAAO,MAAM,KAAK,MAAM,KAAK,IAAI;AAEvC,YAAO,6BAAM,cAAa,OAAO,KAAK,KAAK;AAAA,EAC7C;AAAA,EAEA,MAAc,MACZ,KACA,MACwB;AA7V5B,QAAAD,KAAA;AA8VI,UAAM,oBACJA,MAAA,6BAAM,qBAAN,OAAAA,MAA0B,KAAK,iBAAiB;AAElD,UAAM,aAAa,IAAI,gBAAgB;AAEvC,UAAM,aAAa,mBACf,WAAW,MAAM;AACf,iBAAW,MAAM;AAAA,IACnB,GAAG,gBAAgB,IACnB;AAEJ,UAAM,SAAS,KAAK,IAAI;AAAA,MACtB;AAAA,QACE,SAAS;AAAA,UACP,KAAK;AAAA,UACL,KAAK,6BAAM;AAAA,UACX,MAAM,6BAAM;AAAA,UACZ,MAAM,CAAC,MAAM,MAAM,GAAG;AAAA,QACxB;AAAA,MACF;AAAA,MACA;AAAA,QACE,SAAS,iCACJ,qBAAqB,6BAAM,IAAI,IAD3B;AAAA,UAEP,CAAC,qBAAqB,GAAG,4BAA4B,SAAS;AAAA,QAChE;AAAA,QACA,QAAQ,WAAW;AAAA,QACnB,YAAW,kCAAM,cAAN,YAAmB,KAAK;AAAA,MACrC;AAAA,IACF;AAEA,QAAI;AACF,YAAM,MAAM,MAAM,wBAAwB,MAAM;AAEhD,mBAAa,UAAU;AAEvB,aAAO,IAAI;AAAA,QACT;AAAA,QACA,MAAM,WAAW,MAAM;AAAA,QACvB,MAAM,KAAK,KAAK,GAAG;AAAA,QACnB;AAAA,QACA,6BAAM;AAAA,QACN,6BAAM;AAAA,QACN;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,eAAe,GAAG;AAAA,IAC1B;AAAA,EACF;AACF;;;AGvYA,SAAS,mBAAAE,wBAAuB;AAIhC,eAAe,kBAAkB,UAAoC;AAXrE,MAAAC;AAYE,MAAI,UAAU,SAAS;AAEvB,MAAI;AACF,UAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,eAAUA,MAAA,KAAK,YAAL,OAAAA,MAAgB,KAAK,UAAU,IAAI;AAAA,EAC/C,SAAQ;AACN,QAAI;AACF,gBAAU,MAAM,SAAS,KAAK;AAAA,IAChC,SAAQC,IAAA;AAAA,IAER;AAAA,EACF;AAEA,SAAO,IAAI,MAAM,GAAG,SAAS,MAAM,KAAK,OAAO,EAAE;AACnD;AA0cO,IAAM,aAAN,MAAiB;AAAA,EACZ,cAAc;AAAA,EAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUzB,aAAa,KACX,WACA,MACkB;AAlftB,QAAAD;AAmfI,UAAM,SAAS,IAAI,iBAAiB,IAAI;AACxC,UAAM,SAAS,IAAI,UAAU,MAAM;AAEnC,UAAM,MAAM,MAAM,OAAO,IAAI,OAAO,0BAA0B;AAAA,MAC5D,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ,WAAW;AAAA,QACb;AAAA,MACF;AAAA,MACA,QAAQ,OAAO,UAAU,6BAAM,gBAAgB;AAAA,IACjD,CAAC;AAED,UAAIA,MAAA,IAAI,UAAJ,gBAAAA,IAAW,UAAS,KAAK;AAC3B,aAAO;AAAA,IACT;AAEA,UAAM,MAAM,eAAe,GAAG;AAC9B,QAAI,KAAK;AACP,YAAM;AAAA,IACR;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,aAAa,QACX,WACA,MACsB;AACtB,UAAM,WAAW,MAAM,KAAK,YAAY,WAAW,IAAI;AACvD,WAAO,SAAS;AAChB,WAAO,SAAS;AAEhB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,aAAa,WACX,WACA,MAC2B;AAziB/B,QAAAA,KAAA;AA0iBI,UAAM,SAAS,IAAI,iBAAiB,IAAI;AACxC,UAAM,SAAS,IAAI,UAAU,MAAM;AAEnC,UAAM,MAAM,MAAM,OAAO,IAAI,IAAI,kCAAkC;AAAA,MACjE,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ,WAAW;AAAA,UACX,OAAO,6BAAM;AAAA,UACb,KAAK,6BAAM;AAAA,QACb;AAAA,MACF;AAAA,MACA,QAAQ,OAAO,UAAU,6BAAM,gBAAgB;AAAA,IACjD,CAAC;AAED,UAAM,MAAM,eAAe,GAAG;AAC9B,QAAI,KAAK;AACP,YAAM;AAAA,IACR;AAEA,YACE,MAAAA,MAAA,IAAI,SAAJ,gBAAAA,IAAU,IAAI,CAAC,YAAoD;AAAA,MACjE,WAAW,IAAI,KAAK,OAAO,SAAS;AAAA,MACpC,YAAY,OAAO;AAAA,MACnB,UAAU,OAAO;AAAA,MACjB,SAAS,OAAO,aAAa,OAAO;AAAA,MACpC,UAAU,OAAO,cAAc,OAAO;AAAA;AAAA,MAEtC,UAAU;AAAA;AAAA,MAEV,WAAW;AAAA,IACb,QAVA,YAUO,CAAC;AAAA,EAEZ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,aAAa,WACX,WACA,WACA,MACe;AACf,UAAM,SAAS,IAAI,iBAAiB,IAAI;AACxC,UAAM,SAAS,IAAI,UAAU,MAAM;AAEnC,UAAM,MAAM,MAAM,OAAO,IAAI,KAAK,kCAAkC;AAAA,MAClE,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ,WAAW;AAAA,QACb;AAAA,MACF;AAAA,MACA,MAAM;AAAA,QACJ,SAAS,iBAAiB,SAAS;AAAA,MACrC;AAAA,MACA,QAAQ,OAAO,UAAU,6BAAM,gBAAgB;AAAA,IACjD,CAAC;AAED,UAAM,MAAM,eAAe,GAAG;AAC9B,QAAI,KAAK;AACP,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,aAAa,YAAY,WAAmB,MAAuB;AAlnBrE,QAAAA;AAmnBI,UAAM,SAAS,IAAI,iBAAiB,IAAI;AACxC,UAAM,SAAS,IAAI,UAAU,MAAM;AAEnC,UAAM,MAAM,MAAM,OAAO,IAAI,IAAI,0BAA0B;AAAA,MACzD,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ,WAAW;AAAA,QACb;AAAA,MACF;AAAA,MACA,QAAQ,OAAO,UAAU,6BAAM,gBAAgB;AAAA,IACjD,CAAC;AAED,UAAM,MAAM,eAAe,GAAG;AAC9B,QAAI,KAAK;AACP,YAAM;AAAA,IACR;AAEA,QAAI,CAAC,IAAI,MAAM;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACrC;AAEA,WAAO;AAAA,MACL,WAAW,GAAG,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,QAAQ;AAAA,MACrD,YAAY,IAAI,KAAK;AAAA,OACjB,IAAI,KAAK,SAAS,EAAE,MAAM,IAAI,KAAK,MAAM,IAHxC;AAAA,MAIL,WAAUA,MAAA,IAAI,KAAK,aAAT,OAAAA,MAAqB,CAAC;AAAA,MAChC,aAAa,IAAI,KAAK;AAAA,MACtB,iBAAiB,IAAI,KAAK;AAAA,MAC1B,WAAW,IAAI,KAAK,IAAI,KAAK,SAAS;AAAA,MACtC,OAAO,IAAI,KAAK,IAAI,KAAK,KAAK;AAAA,MAC9B,OAAO,IAAI,KAAK;AAAA,MAChB,UAAU,IAAI,KAAK;AAAA,MACnB,UAAU,IAAI,KAAK;AAAA;AAAA,MAEnB,eAAe;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,aAAa,UACX,WACA,MACkB;AApqBtB,QAAAA,KAAA;AAqqBI,UAAM,SAAS,IAAI,iBAAiB,IAAI;AACxC,UAAM,SAAS,IAAI,UAAU,MAAM;AAEnC,UAAM,MAAM,MAAM,OAAO,IAAI,KAAK,gCAAgC;AAAA,MAChE,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ,WAAW;AAAA,QACb;AAAA,MACF;AAAA,MACA,MAAM;AAAA,QACJ,OAAMA,MAAA,6BAAM,SAAN,OAAAA,MAAc;AAAA,MACtB;AAAA,MACA,QAAQ,OAAO,UAAU,6BAAM,gBAAgB;AAAA,IACjD,CAAC;AAED,UAAI,SAAI,UAAJ,mBAAW,UAAS,KAAK;AAC3B,YAAM,IAAI,cAAc,WAAW,SAAS,YAAY;AAAA,IAC1D;AAEA,UAAI,SAAI,UAAJ,mBAAW,UAAS,KAAK;AAE3B,aAAO;AAAA,IACT;AAEA,UAAM,MAAM,eAAe,GAAG;AAC9B,QAAI,KAAK;AACP,YAAM;AAAA,IACR;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,aAAa,eACX,WACA,MAC+B;AAltBnC,QAAAA,KAAA;AAmtBI,UAAM,SAAS,IAAI,iBAAiB,IAAI;AACxC,UAAM,SAAS,IAAI,UAAU,MAAM;AAEnC,UAAM,MAAM,MAAM,OAAO,IAAI,KAAK,gCAAgC;AAAA,MAChE,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ,WAAW;AAAA,QACb;AAAA,MACF;AAAA,MACA,MAAM;AAAA,QACJ,QAAOA,MAAA,KAAK,UAAL,OAAAA,MAAc;AAAA,QACrB,QAAQ,KAAK;AAAA,QACb,SAAQ,UAAK,WAAL,YAAe;AAAA,SACnB,OAAO,KAAK,cAAc,WAC1B,EAAE,SAAS,iBAAiB,KAAK,SAAS,EAAE,IAC5C,CAAC;AAAA;AAAA,MAGP,QAAQ,OAAO;AAAA,SACb,kCAAM,qBAAN,YAA0B;AAAA,MAC5B;AAAA,IACF,CAAC;AAED,UAAI,SAAI,UAAJ,mBAAW,UAAS,KAAK;AAC3B,YAAM,IAAI,cAAc,WAAW,SAAS,YAAY;AAAA,IAC1D;AAEA,UAAM,MAAM,eAAe,GAAG;AAC9B,QAAI,KAAK;AACP,YAAM;AAAA,IACR;AAEA,QAAI,CAAC,IAAI,MAAM;AACb,YAAM,IAAI,MAAM,gCAAgC;AAAA,IAClD;AAGA,UAAM,aAAa,IAAI,KAAK,aAAa,CAAC,GAAG,IAAI,CAAC,QAAa;AAAA,MAC7D,WAAW,GAAG,GAAG,SAAS,IAAI,GAAG,QAAQ;AAAA,MACzC,aAAa,GAAG;AAAA,MAChB,iBAAiB,GAAG;AAAA,IACtB,EAAE;AAEF,WAAO;AAAA,MACL,OAAO,IAAI,KAAK;AAAA,MAChB;AAAA,MACA,oBAAoB,IAAI,KAAK;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,aAAuB,cACrB,UACA,WACA,MAMC;AA9wBL,QAAAA,KAAA;AA+wBI,UAAM,SAAS,IAAI,iBAAiB,IAAI;AACxC,UAAM,SAAS,IAAI,UAAU,MAAM;AAEnC,UAAM,MAAM,MAAM,OAAO,IAAI,KAAK,cAAc;AAAA,MAC9C,MAAM;AAAA,QACJ,YAAWA,MAAA,6BAAM,cAAN,OAAAA,MAAmB;AAAA,QAC9B,YAAY;AAAA,QACZ,UAAU,6BAAM;AAAA,QAChB,SAAS,6BAAM;AAAA,QACf,SAAS,iBAAiB,SAAS;AAAA,QACnC,SAAQ,kCAAM,WAAN,YAAgB;AAAA;AAAA,QAExB,uBAAuB;AAAA,QACvB,QAAO,6BAAM;AAAA,MACf;AAAA,MACA,QAAQ,OAAO,UAAU,6BAAM,gBAAgB;AAAA,IACjD,CAAC;AAED,UAAM,MAAM,eAAe,GAAG;AAC9B,QAAI,KAAK;AACP,YAAM;AAAA,IACR;AAEA,QAAIE,iBAAgB,IAAI,KAAM,aAAa,OAAO,IAAI,GAAG;AACvD,YAAM,KAAK,KAAK,IAAI,KAAM,WAAW,IAAI;AACzC,YAAM,IAAI;AAAA,QACR;AAAA,MAEF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,WAAW,GAAG,IAAI,KAAM,SAAS,IAAI,IAAI,KAAM,QAAQ;AAAA;AAAA,MAEvD,eAAe;AAAA,MACf,aAAa,IAAI,KAAM;AAAA,MACvB,iBAAiB,IAAI,KAAM;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,aAAuB,cACrB,WACA,MACkB;AA1zBtB,QAAAF,KAAA;AA2zBI,UAAM,aAAYA,MAAA,6BAAM,cAAN,OAAAA,MAAmB;AAErC,UAAM,SAAS,IAAI,iBAAiB,IAAI;AACxC,UAAM,SAAS,IAAI,UAAU,MAAM;AAEnC,UAAM,MAAM,MAAM,OAAO,IAAI,KAAK,iCAAiC;AAAA,MACjE,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ,WAAW;AAAA,QACb;AAAA,MACF;AAAA,MACA,MAAM;AAAA,QACJ,WAAW;AAAA,QACX,SAAS,iBAAiB,SAAS;AAAA,MACrC;AAAA,MACA,QAAQ,OAAO,UAAU,6BAAM,gBAAgB;AAAA,IACjD,CAAC;AAED,UAAI,SAAI,UAAJ,mBAAW,UAAS,KAAK;AAC3B,YAAM,IAAI,cAAc,kBAAkB,SAAS,YAAY;AAAA,IACjE;AAEA,UAAI,SAAI,UAAJ,mBAAW,UAAS,KAAK;AAE3B,aAAO;AAAA,IACT;AAEA,UAAM,MAAM,eAAe,GAAG;AAC9B,QAAI,KAAK;AACP,YAAM;AAAA,IACR;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,aAAuB,eACrB,WACA,MACA;AAj2BJ,QAAAA,KAAA;AAk2BI,UAAM,aAAYA,MAAA,6BAAM,cAAN,OAAAA,MAAmB;AAErC,UAAM,SAAS,IAAI,iBAAiB,IAAI;AACxC,UAAM,SAAS,IAAI,UAAU,MAAM;AAEnC,UAAM,MAAM,MAAM,OAAO,IAAI,KAAK,kCAAkC;AAAA,MAClE,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ,WAAW;AAAA,QACb;AAAA,MACF;AAAA,MACA,MAAM;AAAA,QACJ,SAAS,iBAAiB,SAAS;AAAA,MACrC;AAAA,MACA,QAAQ,OAAO,UAAU,6BAAM,gBAAgB;AAAA,IACjD,CAAC;AAED,UAAI,SAAI,UAAJ,mBAAW,UAAS,KAAK;AAC3B,YAAM,IAAI,cAAc,WAAW,SAAS,YAAY;AAAA,IAC1D;AACA,UAAM,MAAM,eAAe,GAAG;AAC9B,QAAI,KAAK;AACP,YAAM;AAAA,IACR;AAEA,QAAI,CAAC,IAAI,MAAM;AACb,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACrC;AAEA,WAAO;AAAA,MACL,WAAW,GAAG,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,QAAQ;AAAA,MACrD,aAAa,IAAI,KAAK;AAAA,MACtB,iBAAiB,IAAI,KAAK;AAAA,MAC1B,eAAe;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,aAAa,MACX,WACA,MACkB;AAl5BtB,QAAAA,KAAA;AAm5BI,UAAM,SAAS,IAAI,iBAAiB,IAAI;AACxC,UAAM,SAAS,IAAI,UAAU,MAAM;AAEnC,UAAM,MAAM,MAAM,OAAO,IAAI,KAAK,gCAAgC;AAAA,MAChE,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ,WAAW;AAAA,QACb;AAAA,MACF;AAAA,MACA,MAAM;AAAA,QACJ,SAAQA,MAAA,6BAAM,WAAN,OAAAA,MAAgB;AAAA,SACpB,QAAO,6BAAM,eAAc,WAC3B,EAAE,SAAS,iBAAiB,KAAM,SAAU,EAAE,IAC9C,CAAC;AAAA,MAEP,QAAQ,OAAO,UAAU,6BAAM,gBAAgB;AAAA,IACjD,CAAC;AAED,UAAI,SAAI,UAAJ,mBAAW,UAAS,KAAK;AAC3B,YAAM,IAAI,cAAc,WAAW,SAAS,YAAY;AAAA,IAC1D;AAEA,UAAI,SAAI,UAAJ,mBAAW,UAAS,KAAK;AAC3B,aAAO;AAAA,IACT;AAEA,UAAM,MAAM,eAAe,GAAG;AAC9B,QAAI,KAAK;AACP,YAAM;AAAA,IACR;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,aAAa,OACX,WACA,MACmB;AAh8BvB,QAAAA;AAi8BI,UAAM,SAAS,IAAI,iBAAiB,IAAI;AACxC,UAAM,SAAS,IAAI,UAAU,MAAM;AAEnC,UAAM,MAAM,MAAM,OAAO,IAAI,KAAK,iCAAiC;AAAA,MACjE,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ,WAAW;AAAA,QACb;AAAA,MACF;AAAA,MACA,OAAM,6BAAM,SAAQ,EAAE,OAAO,KAAK,MAAM,IAAI;AAAA,MAC5C,QAAQ,OAAO,UAAU,6BAAM,gBAAgB;AAAA,IACjD,CAAC;AAED,UAAIA,MAAA,IAAI,UAAJ,gBAAAA,IAAW,UAAS,KAAK;AAC3B,YAAM,IAAI,cAAc,WAAW,SAAS,YAAY;AAAA,IAC1D;AAEA,UAAM,MAAM,eAAe,GAAG;AAC9B,QAAI,KAAK;AACP,YAAM;AAAA,IACR;AAEA,QAAI,CAAC,IAAI,MAAM;AACb,YAAM,IAAI,MAAM,iCAAiC;AAAA,IACnD;AAEA,WAAO;AAAA,MACL,YAAY,IAAI,KAAK;AAAA,MACrB,SAAS,IAAI,KAAK;AAAA,MAClB,YAAY,IAAI,KAAK;AAAA,MACrB,SAAS,IAAI,KAAK;AAAA,MAClB,UAAU,IAAI,KAAK;AAAA,MACnB,WAAW,IAAI,KAAK,IAAI,KAAK,SAAS;AAAA,MACtC,WAAW,IAAI,KAAK;AAAA,MACpB,YAAY,IAAI,KAAK;AAAA,MACrB,aAAa,IAAI,KAAK;AAAA,MACtB,eAAe,IAAI,KAAK,IAAI,KAAK,aAAa;AAAA,MAC9C,UAAU,IAAI,KAAK;AAAA,MACnB,UAAU,IAAI,KAAK;AAAA,MACnB,QAAQ,IAAI,KAAK;AAAA,MACjB,YAAY,IAAI,KAAK;AAAA,MACrB,cAAc,IAAI,KAAK;AAAA,MACvB,iBAAiB,IAAI,KAAK;AAAA,MAC1B,WAAW,IAAI,KAAK,IAAI,KAAK,SAAS;AAAA,IACxC;AAAA,EACF;AAAA,EAEA,aAAa,UACX,MAC8B;AAl/BlC,QAAAA,KAAA;AAm/BI,UAAM,SAAS,IAAI,iBAAiB,IAAI;AACxC,UAAM,MAAM,IAAI,IAAI,GAAG,OAAO,MAAM,mBAAmB;AACvD,SAAI,6BAAM,eAAc;AACtB,UAAI,aAAa,IAAI,aAAa,OAAO,KAAK,SAAS,CAAC;AAC1D,SAAI,6BAAM,aAAY;AACpB,UAAI,aAAa,IAAI,WAAW,OAAO,KAAK,OAAO,CAAC;AACtD,QAAI,6BAAM,UAAW,KAAI,aAAa,IAAI,aAAa,KAAK,SAAS;AACrE,QAAI,6BAAM,WAAY,KAAI,aAAa,IAAI,cAAc,KAAK,UAAU;AACxE,QAAI,6BAAM,OAAQ,KAAI,aAAa,IAAI,UAAU,KAAK,MAAM;AAC5D,QAAI,6BAAM,MAAO,KAAI,aAAa,IAAI,SAAS,KAAK,KAAK;AACzD,SAAI,6BAAM,cAAa;AACrB,UAAI,aAAa,IAAI,YAAY,OAAO,KAAK,QAAQ,CAAC;AACxD,SAAI,6BAAM,YAAW;AACnB,UAAI,aAAa,IAAI,UAAU,OAAO,KAAK,MAAM,CAAC;AACpD,SAAI,6BAAM,WAAU;AAClB,UAAI,aAAa,IAAI,SAAS,OAAO,KAAK,KAAK,CAAC;AAElD,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR,SAAS,iDACJ,OAAO,UACN,OAAO,SAAS,EAAE,aAAa,OAAO,OAAO,IAAI,CAAC,IAClD,OAAO,cACP,EAAE,eAAe,UAAU,OAAO,WAAW,GAAG,IAChD,CAAC;AAAA,MAEP,QAAQ,OAAO,UAAU,6BAAM,gBAAgB;AAAA,IACjD,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,MAAM,kBAAkB,QAAQ;AAAA,IACxC;AAEA,UAAM,OAAQ,MAAM,SAAS,KAAK;AAMlC,WAAO;AAAA,MACL,QAAOA,MAAA,KAAK,UAAL,OAAAA,MAAc,CAAC;AAAA,MACtB,QAAO,UAAK,UAAL,YAAc;AAAA,MACrB,UAAS,UAAK,YAAL,YAAgB;AAAA,IAC3B;AAAA,EACF;AACF;AAeO,IAAM,mBAAN,MAAuB;AAAA,EAU5B,YAAY,MAAwB;AAClC,SAAK,SAAS,IAAI,iBAAiB,IAAI;AACvC,SAAK,SAAS,IAAI,UAAU,KAAK,MAAM;AAEvC,SAAK,WAAW;AAChB,SAAK,aAAa,6BAAM;AAExB,SAAK,QAAQ,6BAAM;AACnB,SAAK,QAAQ,6BAAM;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,UAAmB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,YAAgC;AAClC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,YAAoC;AAzlC5C,QAAAA,KAAA;AA0lCI,QAAI,CAAC,KAAK,SAAS;AACjB,YAAM,IAAI,MAAM,wBAAwB;AAAA,IAC1C;AAEA,QAAI,WAAW;AACf,SAAIA,MAAA,KAAK,UAAL,gBAAAA,IAAY,UAAU;AACxB,YAAM,eAAuC,OAAO;AAAA,QAClD,OAAO,QAAQ,KAAK,MAAM,QAAQ,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM;AAAA,UACxD,mBAAmB,GAAG;AAAA,UACtB,mBAAmB,KAAK;AAAA,QAC1B,CAAC;AAAA,MACH;AAEA,iBAAW,IAAI,gBAAgB,YAAY,EAAE,SAAS;AAAA,IACxD;AAEA,UAAM,MAAM,MAAM,KAAK,OAAO,IAAI,IAAI,iBAAiB;AAAA,MACrD,QAAQ;AAAA,QACN,OAAO;AAAA,UACL;AAAA,UACA,QAAO,UAAK,UAAL,mBAAY;AAAA,UACnB,OAAO,KAAK;AAAA,UACZ,WAAW,KAAK;AAAA,QAClB;AAAA,MACF;AAAA;AAAA,MAEA,QAAQ,KAAK,OAAO,UAAU;AAAA,IAChC,CAAC;AAED,UAAM,MAAM,eAAe,GAAG;AAC9B,QAAI,KAAK;AACP,YAAM;AAAA,IACR;AAEA,SAAK,aAAa,IAAI,SAAS,QAAQ,IAAI,cAAc,KAAK;AAC9D,SAAK,WAAW,CAAC,CAAC,KAAK;AAEvB,aAAQ,SAAI,SAAJ,YAAY,CAAC,GAAG;AAAA,MACtB,CAAC,YAAiD;AAhoCxD,YAAAA;AAgoC4D;AAAA,UACpD,WAAW,GAAG,QAAQ,SAAS,IAAI,QAAQ,QAAQ;AAAA,UACnD,YAAY,QAAQ;AAAA,WAChB,QAAQ,SAAS,EAAE,MAAM,QAAQ,MAAM,IAHS;AAAA,UAIpD,WAAUA,MAAA,QAAQ,aAAR,OAAAA,MAAoB,CAAC;AAAA,UAC/B,WAAW,IAAI,KAAK,QAAQ,SAAS;AAAA,UACrC,OAAO,IAAI,KAAK,QAAQ,KAAK;AAAA,UAC7B,OAAO,QAAQ;AAAA,UACf,UAAU,QAAQ;AAAA,UAClB,UAAU,QAAQ;AAAA;AAAA,UAElB,aAAa;AAAA,QACf;AAAA;AAAA,IACF;AAAA,EACF;AACF;;;AJnnCA,SAAS,mBAAAG,wBAAuB;AAwCzB,IAAM,UAAN,cAAsB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0CtC,YACE,MAMA;AArHJ,QAAAC;AAsHI,UAAM;AAvBR,SAAmB,WAAW;AAyB5B,SAAK,mBAAmB,IAAI,iBAAiB,IAAI;AAEjD,SAAK,YAAY,KAAK;AACtB,SAAK,iBAAgBA,MAAA,KAAK,kBAAL,OAAAA,MAAsB,KAAK,iBAAiB;AAEjE,SAAK,kBAAkB,KAAK;AAC5B,SAAK,aAAa,GAChB,KAAK,iBAAiB,QAAQ,SAAS,OACzC,MAAM,KAAK,QAAQ,KAAK,QAAQ,CAAC;AAEjC,UAAM,eAAe,uBAAuB;AAAA,MAC1C,SAAS,KAAK;AAAA,MACd,iBAAiB;AAAA,MACjB,eAAc,6BAAM,UAAS,CAAC,gBAAgB,KAAK,MAAM,CAAC,IAAI;AAAA,MAC9D,OAAO,CAAC,KAAK,YAAY;AAKvB,cAAM,UAAU,IAAI,QAAQ,KAAK,iBAAiB,OAAO;AACzD,YAAI,QAAQ,mCAAS,OAAO,EAAE;AAAA,UAAQ,CAAC,OAAO,QAC5C,QAAQ,OAAO,KAAK,KAAK;AAAA,QAC3B;AAEA,YAAI,KAAK,iBAAiB;AACxB,kBAAQ,OAAO,kBAAkB,KAAK,eAAe;AAAA,QACvD;AAEA,kBAAU,iCACJ,4BAAW,CAAC,IADR;AAAA,UAER;AAAA,UACA,UAAU;AAAA,QACZ;AAEA,eAAO,MAAM,KAAK,OAAO;AAAA,MAC3B;AAAA,IACF,CAAC;AAED,SAAK,UAAU,IAAI;AAAA,MACjB;AAAA,QACE,QAAQ,KAAK;AAAA,QACb,QAAQ,6BAAM;AAAA,QACd,aAAa,KAAK;AAAA,QAClB,SAAS,KAAK,kBACV,EAAE,kBAAkB,KAAK,gBAAgB,IACzC,CAAC;AAAA,MACP;AAAA,MACA;AAAA,QACE,SAAS,6BAAM;AAAA,MACjB;AAAA,IACF;AACA,SAAK,QAAQ,IAAIC;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,SAAK,WAAW,IAAI,SAAS,cAAc,KAAK,gBAAgB;AAChE,SAAK,MAAM,IAAI,IAAI,cAAc,KAAK,gBAAgB;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,KAAK,MAA0C;AACpD,WAAO,IAAI,iBAAiB,IAAI;AAAA,EAClC;AAAA,EAuCA,aAAa,OAEX,gBACA,MAC0B;AAxO9B,QAAAD;AAyOI,UAAM,EAAE,UAAU,YAAY,IAC5B,OAAO,mBAAmB,WACtB,EAAE,UAAU,gBAAgB,aAAa,KAAK,IAC9C,EAAE,UAAU,KAAK,iBAAiB,aAAa,eAAe;AAEpE,UAAM,SAAS,IAAI,iBAAiB,WAAW;AAC/C,QAAI,OAAO,OAAO;AAChB,aAAO,IAAI,KAAK;AAAA,QACd,WAAW;AAAA,SACR,OACJ;AAAA,IACH;AAEA,UAAM,UAAU,MAAM,WAAW;AAAA,MAC/B;AAAA,OACAA,MAAA,2CAAa,cAAb,OAAAA,MAA0B,KAAK;AAAA,MAC/B;AAAA,IACF;AAEA,WAAO,IAAI,KAAK,kCAAK,UAAY,OAAQ;AAAA,EAC3C;AAAA,EA2CA,aAAa,WAEX,gBACA,MAC0B;AA5S9B,QAAAA;AA6SI,UAAM,EAAE,UAAU,YAAY,IAC5B,OAAO,mBAAmB,WACtB,EAAE,UAAU,gBAAgB,aAAa,KAAK,IAC9C,EAAE,UAAU,KAAK,iBAAiB,aAAa,eAAe;AAEpE,UAAM,SAAS,IAAI,iBAAiB,WAAW;AAC/C,QAAI,OAAO,OAAO;AAChB,aAAO,IAAI,KAAK;AAAA,QACd,WAAW;AAAA,SACR,OACJ;AAAA,IACH;AAEA,UAAM,UAAU,MAAM,WAAW;AAAA,MAC/B;AAAA,OACAA,MAAA,2CAAa,cAAb,OAAAA,MAA0B,KAAK;AAAA,MAC/B;AAAA,IACF;AAEA,WAAO,IAAI,KAAK,kCAAK,UAAY,OAAQ;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,aAAa,QAEX,WACA,MAC0B;AAC1B,UAAM,OAAO,MAAM,WAAW,eAAe,WAAW,IAAI;AAE5D,UAAM,SAAS,IAAI,iBAAiB,IAAI;AAExC,WAAO,IAAI,KAAK;AAAA,MACd,WAAW,KAAK;AAAA,MAChB,eAAe,KAAK;AAAA,MACpB,iBAAiB,KAAK;AAAA,MACtB,aAAa,KAAK;AAAA,OACf,OACJ;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,aAAa,MAEX,WACA,MACuC;AAIvC,UAAM,MAAM,MAAM,WAAW,eAAe,WAAW,IAAI;AAE3D,UAAM,YAAY,IAAI,UAAU,IAAI,CAAC,OAAO;AAC1C,YAAM,SAAS,IAAI,iBAAiB,IAAI;AACxC,aAAO,IAAI,KAAK;AAAA,QACd,WAAW,GAAG;AAAA,QACd,aAAa,GAAG;AAAA,QAChB,iBAAiB,GAAG;AAAA,SACjB,OACJ;AAAA,IACH,CAAC;AAED,WAAO;AAAA,MACL,OAAO,IAAI;AAAA,MACX,oBAAoB,IAAI;AAAA,MACxB,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,MACX,WACA,MACkB;AAClB,WAAO,MAAM,WAAW,MAAM,WAAW,IAAI;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBA,MAAM,QAAQ,MAA6C;AACzD,UAAM,WAAW,eAAe,KAAK,WAAW,IAAI;AAEpD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,QAAQ,MAAc;AACpB,QAAI,KAAK,iBAAiB,OAAO;AAC/B,aAAO,aAAa,IAAI;AAAA,IAC1B;AAEA,WAAO,GAAG,IAAI,IAAI,KAAK,SAAS,IAAI,KAAK,aAAa;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,UACJ,MACkB;AAClB,UAAM,SAAS,KAAK,iBAAiB,UAAU,6BAAM,gBAAgB;AAErE,UAAM,MAAM,MAAM,KAAK,QAAQ,IAAI,IAAI,WAAW;AAAA,MAChD;AAAA,IACF,CAAC;AAED,QAAI,IAAI,SAAS,UAAU,KAAK;AAC9B,aAAO;AAAA,IACT;AAEA,UAAM,MAAM,MAAM,mBAAmB,GAAG;AACxC,QAAI,KAAK;AACP,YAAM;AAAA,IACR;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,WACJ,WACA,MACA;AACA,QAAI,KAAK,iBAAiB,OAAO;AAE/B;AAAA,IACF;AAEA,UAAM,WAAW,WAAW,KAAK,WAAW,WAAW,kCAClD,KAAK,mBACL,KACJ;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,KAAK,MAA8C;AACvD,QAAI,KAAK,iBAAiB,OAAO;AAE/B;AAAA,IACF;AAEA,UAAM,WAAW,KAAK,KAAK,WAAW,kCAAK,KAAK,mBAAqB,KAAM;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,UAAU,MAAyC;AACvD,WAAO,MAAM,WAAW,UAAU,KAAK,WAAW,IAAI;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAM,MAA2C;AACrD,WAAO,MAAM,WAAW,MAAM,KAAK,WAAW,IAAI;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAM,OAAO,MAA6C;AACxD,WAAO,MAAM,WAAW,OAAO,KAAK,WAAW,kCAC1C,KAAK,mBACL,KACJ;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,UAAU,MAAe,MAAuB;AAllBxD,QAAAA;AAmlBI,WAAO,sBAAQ,CAAC;AAEhB,UAAM,eAAe,CAAC,CAAC,KAAK;AAE5B,QAAI,CAAC,gBAAgB,KAAK,0BAA0B,QAAW;AAC7D,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,YAAWA,MAAA,KAAK,SAAL,OAAAA,MAAa;AAC9B,UAAM,WAAW,sBAAQ;AACzB,UAAM,UAAU,KAAK,QAAQ,UAAU,QAAQ;AAE/C,QAAI,cAAc;AAChB,YAAM,MAAM,IAAI,IAAI,OAAO;AAC3B,YAAM,MAAM,MAAM,aAAa;AAAA,QAC7B,MAAM;AAAA,QACN,WAAW;AAAA,QACX,MAAM;AAAA,QACN,qBAAqB,KAAK;AAAA,QAC1B,iBAAiB,KAAK;AAAA,MACxB,CAAC;AAED,UAAI,aAAa,IAAI,aAAa,IAAI,SAAS;AAC/C,UAAI,IAAI,YAAY;AAClB,YAAI,aAAa,IAAI,wBAAwB,IAAI,WAAW,SAAS,CAAC;AAAA,MACxE;AAEA,aAAO,IAAI,SAAS;AAAA,IACtB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,YAAY,MAAc,MAAuB;AA/nBzD,QAAAA;AAgoBI,WAAO,sBAAQ,CAAC;AAEhB,UAAM,eAAe,CAAC,CAAC,KAAK;AAE5B,QAAI,CAAC,gBAAgB,KAAK,0BAA0B,QAAW;AAC7D,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,YAAWA,MAAA,KAAK,SAAL,OAAAA,MAAa;AAC9B,UAAM,UAAU,KAAK,QAAQ,MAAM,QAAQ;AAE3C,QAAI,cAAc;AAChB,YAAM,MAAM,IAAI,IAAI,OAAO;AAC3B,YAAM,MAAM,MAAM,aAAa;AAAA,QAC7B;AAAA,QACA,WAAW;AAAA,QACX,MAAM;AAAA,QACN,qBAAqB,KAAK;AAAA,QAC1B,iBAAiB,KAAK;AAAA,MACxB,CAAC;AAED,UAAI,aAAa,IAAI,aAAa,IAAI,SAAS;AAC/C,UAAI,IAAI,YAAY;AAClB,YAAI,aAAa,IAAI,wBAAwB,IAAI,WAAW,SAAS,CAAC;AAAA,MACxE;AAEA,aAAO,IAAI,SAAS;AAAA,IACtB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAQ,MAA8C;AAC1D,WAAO,MAAM,WAAW,QAAQ,KAAK,WAAW,kCAC3C,KAAK,mBACL,KACJ;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,WAAW,MAA2B;AAvrB9C,QAAAA,KAAA;AAwrBI,QAAI,KAAK,QAAQ,SAAS;AACxB,UAAIE,iBAAgB,KAAK,QAAQ,SAAS,OAAO,IAAI,GAAG;AACtD,cAAM,IAAI;AAAA,UACR;AAAA,QAEF;AAAA,MACF;AAEA,UAAIA,iBAAgB,KAAK,QAAQ,SAAS,OAAO,IAAI,GAAG;AACtD,eAAAF,MAAA,KAAK,iBAAiB,WAAtB,gBAAAA,IAA8B,SAA9B;AAAA,UAAAA;AAAA,UACE;AAAA;AAAA,MAEJ;AAAA,IACF;AAEA,WAAO,MAAM,WAAW,WAAW,KAAK,WAAW,kCAC9C,KAAK,mBACL,KACJ;AAAA,EACH;AAAA,EAEQ,QAAQ,MAAe,UAAmB;AAChD,UAAM,MAAM,IAAI,IAAI,UAAU,KAAK,UAAU;AAE7C,QAAI,aAAa,IAAI,YAAY,8BAAY,eAAe;AAC5D,QAAI,MAAM;AACR,UAAI,aAAa,IAAI,QAAQ,IAAI;AAAA,IACnC;AAEA,WAAO,IAAI,SAAS;AAAA,EACtB;AACF;AAnpBa,QACe,kBAA0B;AADzC,QAEe,0BAA0B;;;AKItD,IAAO,eAAQ;","names":["_a","_a","_a","message","_a","createClient","ConnectError","Code","createClient","_a","createClient","Code","ConnectError","ConnectError","Code","FilesystemEventType","_a","FileType","Filesystem","createClient","_a","ConnectError","Code","_a","_a","Code","ConnectError","createClient","enumDesc","fileDesc","messageDesc","serviceDesc","serviceDesc","Code","ConnectError","createClient","createClient","_a","ConnectError","Code","createClient","ConnectError","Code","_a","pid","compareVersions","_a","e","compareVersions","compareVersions","_a","Filesystem","compareVersions"]}
@@ -92,7 +92,7 @@ var import_openapi_fetch = __toESM(require("openapi-fetch"));
92
92
  var import_platform = __toESM(require("platform"));
93
93
 
94
94
  // package.json
95
- var version = "1.1.3-b3";
95
+ var version = "1.1.3";
96
96
 
97
97
  // src/core/api/metadata.ts
98
98
  function getRuntime() {