@rivetkit/engine-runner 2.0.29 → 2.0.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mod.cjs +7 -5
- package/dist/mod.cjs.map +1 -1
- package/dist/mod.js +7 -5
- package/dist/mod.js.map +1 -1
- package/package.json +2 -2
- package/src/actor.ts +4 -4
- package/src/mod.ts +5 -4
- package/src/stringify.ts +3 -3
- package/src/tunnel.ts +1 -1
package/dist/mod.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mod.ts","../src/log.ts","../src/utils.ts","../src/actor.ts","../src/stringify.ts","../src/websocket-tunnel-adapter.ts","../src/tunnel.ts","../src/websocket.ts"],"sourcesContent":["import * as protocol from \"@rivetkit/engine-runner-protocol\";\nimport type { Logger } from \"pino\";\nimport type WebSocket from \"ws\";\nimport { type ActorConfig, RunnerActor } from \"./actor\";\nimport { logger, setLogger } from \"./log.js\";\nimport { stringifyToClient, stringifyToServer } from \"./stringify\";\nimport { type HibernatingWebSocketMetadata, Tunnel } from \"./tunnel\";\nimport {\n\tcalculateBackoff,\n\tparseWebSocketCloseReason,\n\tstringifyError,\n\tunreachable,\n} from \"./utils\";\nimport { importWebSocket } from \"./websocket.js\";\n\nexport type { HibernatingWebSocketMetadata };\nexport { RunnerActor, type ActorConfig };\nexport { idToStr } from \"./utils\";\n\nconst KV_EXPIRE: number = 30_000;\nconst PROTOCOL_VERSION: number = 5;\n\n/** Warn once the backlog significantly exceeds the server's ack batch size. */\nconst EVENT_BACKLOG_WARN_THRESHOLD = 10_000;\nconst SIGNAL_HANDLERS: (() => void | Promise<void>)[] = [];\n\nexport class RunnerShutdownError extends Error {\n\tconstructor() {\n\t\tsuper(\"Runner shut down\");\n\t}\n}\n\nexport interface RunnerConfig {\n\tlogger?: Logger;\n\tversion: number;\n\tendpoint: string;\n\ttoken?: string;\n\tpegboardEndpoint?: string;\n\tpegboardRelayEndpoint?: string;\n\tnamespace: string;\n\ttotalSlots: number;\n\trunnerName: string;\n\trunnerKey: string;\n\tprepopulateActorNames: Record<string, { metadata: Record<string, any> }>;\n\tmetadata?: Record<string, any>;\n\tonConnected: () => void;\n\tonDisconnected: (code: number, reason: string) => void;\n\tonShutdown: () => void;\n\n\t/** Called when receiving a network request. */\n\tfetch: (\n\t\trunner: Runner,\n\t\tactorId: string,\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t\trequest: Request,\n\t) => Promise<Response>;\n\n\t/**\n\t * Called when receiving a WebSocket connection.\n\t *\n\t * All event listeners must be added synchronously inside this function or\n\t * else events may be missed. The open event will fire immediately after\n\t * this function finishes.\n\t *\n\t * Any errors thrown here will disconnect the WebSocket immediately.\n\t *\n\t * While `path` and `headers` are partially redundant to the data in the\n\t * `Request`, they may vary slightly from the actual content of `Request`.\n\t * Prefer to persist the `path` and `headers` properties instead of the\n\t * `Request` itself.\n\t *\n\t * ## Hibernating Web Sockets\n\t *\n\t * ### Implementation Requirements\n\t *\n\t * **Requirement 1: Persist HWS Immediately**\n\t *\n\t * This is responsible for persisting hibernatable WebSockets immediately\n\t * (do not wait for open event). It is not time sensitive to flush the\n\t * connection state. If this fails to persist the HWS, the client's\n\t * WebSocket will be disconnected on next wake in the call to\n\t * `Tunnel::restoreHibernatingRequests` since the connection entry will not\n\t * exist.\n\t *\n\t * **Requirement 2: Persist Message Index On `message`**\n\t *\n\t * In the `message` event listener, this handler must persist the message\n\t * index from the event. The request ID is available at\n\t * `event.rivetRequestId` and message index at `event.rivetMessageIndex`.\n\t *\n\t * The message index should not be flushed immediately. Instead, this\n\t * should:\n\t *\n\t * - Debounce calls to persist the message index\n\t * - After each persist, call\n\t * `Runner::sendHibernatableWebSocketMessageAck` to acknowledge the\n\t * message\n\t *\n\t * This mechanism allows us to buffer messages on the gateway so we can\n\t * batch-persist events on our end on a given interval.\n\t *\n\t * If this fails to persist, then the gateway will replay unacked\n\t * messages when the actor starts again.\n\t *\n\t * **Requirement 3: Remove HWS From Storage On `close`**\n\t *\n\t * This handler should add an event listener for `close` to remove the\n\t * connection from storage.\n\t *\n\t * If the connection remove fails to persist, the close event will be\n\t * called again on the next actor start in\n\t * `Tunnel::restoreHibernatingRequests` since there will be no request for\n\t * the given connection.\n\t *\n\t * ### Restoring Connections\n\t *\n\t * The user of this library is responsible for:\n\t * 1. Loading all persisted hibernatable WebSocket metadata for an actor\n\t * 2. Calling `Runner::restoreHibernatingRequests` with this metadata at\n\t * the end of `onActorStart`\n\t *\n\t * `restoreHibernatingRequests` will restore all connections and attach\n\t * the appropriate event listeners.\n\t *\n\t * ### No Open Event On Restoration\n\t *\n\t * When restoring a HWS, the open event will not be called again. It will\n\t * go straight to the message or close event.\n\t */\n\twebsocket: (\n\t\trunner: Runner,\n\t\tactorId: string,\n\t\tws: any,\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t\trequest: Request,\n\t\tpath: string,\n\t\theaders: Record<string, string>,\n\t\tisHibernatable: boolean,\n\t\tisRestoringHibernatable: boolean,\n\t) => Promise<void>;\n\n\thibernatableWebSocket: {\n\t\t/**\n\t\t * Determines if a WebSocket can continue to live while an actor goes to\n\t\t * sleep.\n\t\t */\n\t\tcanHibernate: (\n\t\t\tactorId: string,\n\t\t\tgatewayId: ArrayBuffer,\n\t\t\trequestId: ArrayBuffer,\n\t\t\trequest: Request,\n\t\t) => boolean;\n\t};\n\n\t/**\n\t * Called when an actor starts.\n\t *\n\t * This callback is responsible for:\n\t * 1. Initializing the actor instance\n\t * 2. Loading all persisted hibernatable WebSocket metadata for this actor\n\t * 3. Calling `Runner::restoreHibernatingRequests` with the loaded metadata\n\t * to restore hibernatable WebSocket connections\n\t *\n\t * The actor should not be marked as \"ready\" until after\n\t * `restoreHibernatingRequests` completes to ensure all hibernatable\n\t * connections are fully restored before the actor processes new requests.\n\t */\n\tonActorStart: (\n\t\tactorId: string,\n\t\tgeneration: number,\n\t\tconfig: ActorConfig,\n\t) => Promise<void>;\n\n\tonActorStop: (actorId: string, generation: number) => Promise<void>;\n\tnoAutoShutdown?: boolean;\n}\n\nexport interface KvListOptions {\n\treverse?: boolean;\n\tlimit?: number;\n}\n\ninterface KvRequestEntry {\n\tactorId: string;\n\tdata: protocol.KvRequestData;\n\tresolve: (value: any) => void;\n\treject: (error: unknown) => void;\n\tsent: boolean;\n\ttimestamp: number;\n}\n\nexport class Runner {\n\t#config: RunnerConfig;\n\n\tget config(): RunnerConfig {\n\t\treturn this.#config;\n\t}\n\n\t#actors: Map<string, RunnerActor> = new Map();\n\n\t// WebSocket\n\t__pegboardWebSocket?: WebSocket;\n\trunnerId?: string;\n\t#started: boolean = false;\n\t#shutdown: boolean = false;\n\t#shuttingDown: boolean = false;\n\t#reconnectAttempt: number = 0;\n\t#reconnectTimeout?: NodeJS.Timeout;\n\n\t// Runner lost threshold management\n\t#runnerLostThreshold?: number;\n\t#runnerLostTimeout?: NodeJS.Timeout;\n\n\t// Event storage for resending\n\t#eventBacklogWarned: boolean = false;\n\n\t// Command acknowledgment\n\t#ackInterval?: NodeJS.Timeout;\n\n\t// KV operations\n\t#nextKvRequestId: number = 0;\n\t#kvRequests: Map<number, KvRequestEntry> = new Map();\n\t#kvCleanupInterval?: NodeJS.Timeout;\n\n\t// Tunnel for HTTP/WebSocket forwarding\n\t#tunnel: Tunnel | undefined;\n\n\t// Cached child logger with runner-specific attributes\n\t#logCached?: Logger;\n\n\tget log(): Logger | undefined {\n\t\tif (this.#logCached) return this.#logCached;\n\n\t\tconst l = logger();\n\t\tif (l) {\n\t\t\t// If has connected, create child logger with relevant metadata\n\t\t\t//\n\t\t\t// Otherwise, return default logger\n\t\t\tif (this.runnerId) {\n\t\t\t\tthis.#logCached = l.child({\n\t\t\t\t\trunnerId: this.runnerId,\n\t\t\t\t});\n\t\t\t\treturn this.#logCached;\n\t\t\t} else {\n\t\t\t\treturn l;\n\t\t\t}\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\tconstructor(config: RunnerConfig) {\n\t\tthis.#config = config;\n\t\tif (this.#config.logger) setLogger(this.#config.logger);\n\n\t\t// Start cleaning up old unsent KV requests every 15 seconds\n\t\tthis.#kvCleanupInterval = setInterval(() => {\n\t\t\ttry {\n\t\t\t\tthis.#cleanupOldKvRequests();\n\t\t\t} catch (err) {\n\t\t\t\tthis.log?.error({\n\t\t\t\t\tmsg: \"error cleaning up kv requests\",\n\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t});\n\t\t\t}\n\t\t}, 15000); // Run every 15 seconds\n\t}\n\n\t// MARK: Manage actors\n\tsleepActor(actorId: string, generation?: number) {\n\t\tconst actor = this.getActor(actorId, generation);\n\t\tif (!actor) return;\n\n\t\t// Keep the actor instance in memory during sleep\n\t\tthis.#sendActorIntent(actorId, actor.generation, \"sleep\");\n\n\t\t// NOTE: We do NOT remove the actor from this.#actors here\n\t\t// The server will send a StopActor command if it wants to fully stop\n\t}\n\n\tasync stopActor(actorId: string, generation?: number) {\n\t\tconst actor = this.getActor(actorId, generation);\n\t\tif (!actor) return;\n\n\t\tthis.#sendActorIntent(actorId, actor.generation, \"stop\");\n\n\t\t// NOTE: We do NOT remove the actor from this.#actors here\n\t\t// The server will send a StopActor command if it wants to fully stop\n\t}\n\n\tasync forceStopActor(actorId: string, generation?: number) {\n\t\tthis.log?.debug({\n\t\t\tmsg: \"force stopping actor\",\n\t\t\tactorId,\n\t\t});\n\n\t\tconst actor = this.getActor(actorId, generation);\n\t\tif (!actor) return;\n\n\t\t// If onActorStop times out, Pegboard will handle this timeout with ACTOR_STOP_THRESHOLD_DURATION_MS\n\t\t//\n\t\t// If we receive a request while onActorStop is running, a Service\n\t\t// Unavailable error will be returned to Guard and the request will be\n\t\t// retried\n\t\ttry {\n\t\t\tawait this.#config.onActorStop(actorId, actor.generation);\n\t\t} catch (err) {\n\t\t\tconsole.error(`Error in onActorStop for actor ${actorId}:`, err);\n\t\t}\n\n\t\t// Close requests after onActorStop so you can send messages over the tunnel\n\t\tthis.#tunnel?.closeActiveRequests(actor);\n\n\t\tthis.#sendActorStateUpdate(actorId, actor.generation, \"stopped\");\n\n\t\t// Remove actor after stopping in order to ensure that we can still\n\t\t// call actions on the runner\n\t\tthis.#removeActor(actorId, generation);\n\t}\n\n\t#handleLost() {\n\t\tthis.log?.info({\n\t\t\tmsg: \"stopping all actors due to runner lost threshold\",\n\t\t});\n\n\t\t// Remove all remaining kv requests\n\t\tfor (const [_, request] of this.#kvRequests.entries()) {\n\t\t\trequest.reject(new RunnerShutdownError());\n\t\t}\n\n\t\tthis.#kvRequests.clear();\n\n\t\tthis.#stopAllActors();\n\t}\n\n\t#stopAllActors() {\n\t\tconst actorIds = Array.from(this.#actors.keys());\n\t\tfor (const actorId of actorIds) {\n\t\t\tthis.forceStopActor(actorId).catch((err) => {\n\t\t\t\tthis.log?.error({\n\t\t\t\t\tmsg: \"error stopping actor\",\n\t\t\t\t\tactorId,\n\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t}\n\n\tgetActor(actorId: string, generation?: number): RunnerActor | undefined {\n\t\tconst actor = this.#actors.get(actorId);\n\t\tif (!actor) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"actor not found\",\n\t\t\t\tactorId,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\t\tif (generation !== undefined && actor.generation !== generation) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"actor generation mismatch\",\n\t\t\t\tactorId,\n\t\t\t\tgeneration,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn actor;\n\t}\n\n\tasync getAndWaitForActor(\n\t\tactorId: string,\n\t\tgeneration?: number,\n\t): Promise<RunnerActor | undefined> {\n\t\tconst actor = this.getActor(actorId, generation);\n\t\tif (!actor) return;\n\t\tawait actor.actorStartPromise.promise;\n\t\treturn actor;\n\t}\n\n\thasActor(actorId: string, generation?: number): boolean {\n\t\tconst actor = this.#actors.get(actorId);\n\n\t\treturn (\n\t\t\t!!actor &&\n\t\t\t(generation === undefined || actor.generation === generation)\n\t\t);\n\t}\n\n\tget actors() {\n\t\treturn this.#actors;\n\t}\n\n\t// IMPORTANT: Make sure to call stopActiveRequests if calling #removeActor\n\t#removeActor(\n\t\tactorId: string,\n\t\tgeneration?: number,\n\t): RunnerActor | undefined {\n\t\tconst actor = this.#actors.get(actorId);\n\t\tif (!actor) {\n\t\t\tthis.log?.error({\n\t\t\t\tmsg: \"actor not found for removal\",\n\t\t\t\tactorId,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\t\tif (generation !== undefined && actor.generation !== generation) {\n\t\t\tthis.log?.error({\n\t\t\t\tmsg: \"actor generation mismatch\",\n\t\t\t\tactorId,\n\t\t\t\tgeneration,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\tthis.#actors.delete(actorId);\n\n\t\tthis.log?.info({\n\t\t\tmsg: \"removed actor\",\n\t\t\tactorId,\n\t\t\tactors: this.#actors.size,\n\t\t});\n\n\t\treturn actor;\n\t}\n\n\t// MARK: Start\n\tasync start() {\n\t\tif (this.#started) throw new Error(\"Cannot call runner.start twice\");\n\t\tthis.#started = true;\n\n\t\tthis.log?.info({ msg: \"starting runner\" });\n\n\t\tthis.#tunnel = new Tunnel(this);\n\t\tthis.#tunnel.start();\n\n\t\ttry {\n\t\t\tawait this.#openPegboardWebSocket();\n\t\t} catch (error) {\n\t\t\tthis.#started = false;\n\t\t\tthrow error;\n\t\t}\n\n\t\tif (!this.#config.noAutoShutdown) {\n\t\t\tif (!SIGNAL_HANDLERS.length) {\n\t\t\t\tprocess.on(\"SIGTERM\", async () => {\n\t\t\t\t\tthis.log?.debug(\"received SIGTERM\");\n\n\t\t\t\t\tfor (const handler of SIGNAL_HANDLERS) {\n\t\t\t\t\t\tawait handler();\n\t\t\t\t\t}\n\n\t\t\t\t\t// TODO: Add back\n\t\t\t\t\t// process.exit(0);\n\t\t\t\t});\n\t\t\t\tprocess.on(\"SIGINT\", async () => {\n\t\t\t\t\tthis.log?.debug(\"received SIGINT\");\n\n\t\t\t\t\tfor (const handler of SIGNAL_HANDLERS) {\n\t\t\t\t\t\tawait handler();\n\t\t\t\t\t}\n\n\t\t\t\t\t// TODO: Add back\n\t\t\t\t\t// process.exit(0);\n\t\t\t\t});\n\n\t\t\t\tthis.log?.debug({\n\t\t\t\t\tmsg: \"added SIGTERM listeners\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tSIGNAL_HANDLERS.push(async () => {\n\t\t\t\tconst weak = new WeakRef(this);\n\t\t\t\tawait weak.deref()?.shutdown(false, false);\n\t\t\t});\n\t\t}\n\t}\n\n\t// MARK: Shutdown\n\tasync shutdown(immediate: boolean, exit: boolean = false) {\n\t\t// Prevent concurrent shutdowns\n\t\tif (this.#shuttingDown) {\n\t\t\tthis.log?.debug({\n\t\t\t\tmsg: \"shutdown already in progress, ignoring\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tthis.#shuttingDown = true;\n\n\t\tthis.log?.info({\n\t\t\tmsg: \"starting shutdown\",\n\t\t\timmediate,\n\t\t\texit,\n\t\t});\n\t\tthis.#shutdown = true;\n\n\t\t// Clear reconnect timeout\n\t\tif (this.#reconnectTimeout) {\n\t\t\tclearTimeout(this.#reconnectTimeout);\n\t\t\tthis.#reconnectTimeout = undefined;\n\t\t}\n\n\t\t// Clear runner lost timeout\n\t\tif (this.#runnerLostTimeout) {\n\t\t\tclearTimeout(this.#runnerLostTimeout);\n\t\t\tthis.#runnerLostTimeout = undefined;\n\t\t}\n\n\t\t// Clear ack interval\n\t\tif (this.#ackInterval) {\n\t\t\tclearInterval(this.#ackInterval);\n\t\t\tthis.#ackInterval = undefined;\n\t\t}\n\n\t\t// Clear KV cleanup interval\n\t\tif (this.#kvCleanupInterval) {\n\t\t\tclearInterval(this.#kvCleanupInterval);\n\t\t\tthis.#kvCleanupInterval = undefined;\n\t\t}\n\n\t\t// Reject all KV requests\n\t\tfor (const request of this.#kvRequests.values()) {\n\t\t\trequest.reject(\n\t\t\t\tnew Error(\"WebSocket connection closed during shutdown\"),\n\t\t\t);\n\t\t}\n\t\tthis.#kvRequests.clear();\n\n\t\t// Close WebSocket\n\t\tif (this.__webSocketReady()) {\n\t\t\tconst pegboardWebSocket = this.__pegboardWebSocket;\n\t\t\tif (immediate) {\n\t\t\t\t// Stop immediately\n\t\t\t\tpegboardWebSocket.close(1000, \"pegboard.runner_shutdown\");\n\t\t\t} else {\n\t\t\t\t// Wait for actors to shut down before stopping\n\t\t\t\ttry {\n\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\tmsg: \"sending stopping message\",\n\t\t\t\t\t\treadyState: pegboardWebSocket.readyState,\n\t\t\t\t\t});\n\n\t\t\t\t\t// Start stopping\n\t\t\t\t\t//\n\t\t\t\t\t// The runner workflow will send StopActor commands for all\n\t\t\t\t\t// actors\n\t\t\t\t\tthis.__sendToServer({\n\t\t\t\t\t\ttag: \"ToServerStopping\",\n\t\t\t\t\t\tval: null,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst closePromise = new Promise<void>((resolve) => {\n\t\t\t\t\t\tif (!pegboardWebSocket)\n\t\t\t\t\t\t\tthrow new Error(\"missing pegboardWebSocket\");\n\n\t\t\t\t\t\tpegboardWebSocket.addEventListener(\"close\", (ev) => {\n\t\t\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\t\t\tmsg: \"connection closed\",\n\t\t\t\t\t\t\t\tcode: ev.code,\n\t\t\t\t\t\t\t\treason: ev.reason.toString(),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\t\t// Wait for all actors to stop before closing ws\n\t\t\t\t\tawait this.#waitForActorsToStop(pegboardWebSocket);\n\n\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\tmsg: \"closing WebSocket\",\n\t\t\t\t\t});\n\t\t\t\t\tpegboardWebSocket.close(1000, \"pegboard.runner_shutdown\");\n\n\t\t\t\t\tawait closePromise;\n\n\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\tmsg: \"websocket shutdown completed\",\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\tmsg: \"error during websocket shutdown:\",\n\t\t\t\t\t\terror,\n\t\t\t\t\t});\n\t\t\t\t\tpegboardWebSocket.close();\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// This is often logged when the serverless SSE stream closes after\n\t\t\t// the runner has already shut down\n\t\t\tthis.log?.debug({\n\t\t\t\tmsg: \"no runner WebSocket to shutdown or already closed\",\n\t\t\t\treadyState: this.__pegboardWebSocket?.readyState,\n\t\t\t});\n\t\t}\n\n\t\t// Close tunnel\n\t\tif (this.#tunnel) {\n\t\t\tthis.#tunnel.shutdown();\n\t\t\tthis.#tunnel = undefined;\n\t\t}\n\n\t\tthis.#config.onShutdown();\n\n\t\tif (exit) process.exit(0);\n\t}\n\n\t/**\n\t * Wait for all actors to stop before proceeding with shutdown.\n\t *\n\t * This method polls every 100ms to check if all actors have been stopped.\n\t *\n\t * It will resolve early if:\n\t * - All actors are stopped\n\t * - The WebSocket connection is closed\n\t * - The shutdown timeout is reached (120 seconds)\n\t */\n\tasync #waitForActorsToStop(ws: WebSocket): Promise<void> {\n\t\tconst shutdownTimeout = 120_000; // 120 seconds\n\t\tconst shutdownCheckInterval = 100; // Check every 100ms\n\t\tconst progressLogInterval = 5_000; // Log progress every 5 seconds\n\t\tconst shutdownStartTs = Date.now();\n\t\tlet lastProgressLogTs = 0; // Ensure first log happens immediately\n\n\t\treturn new Promise<void>((resolve) => {\n\t\t\tconst checkActors = () => {\n\t\t\t\tconst now = Date.now();\n\t\t\t\tconst elapsed = now - shutdownStartTs;\n\t\t\t\tconst wsIsClosed = ws.readyState === 2 || ws.readyState === 3;\n\n\t\t\t\tif (this.#actors.size === 0) {\n\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\tmsg: \"all actors stopped\",\n\t\t\t\t\t\telapsed,\n\t\t\t\t\t});\n\t\t\t\t\treturn true;\n\t\t\t\t} else if (wsIsClosed) {\n\t\t\t\t\tthis.log?.warn({\n\t\t\t\t\t\tmsg: \"websocket closed before all actors stopped\",\n\t\t\t\t\t\tremainingActors: this.#actors.size,\n\t\t\t\t\t\telapsed,\n\t\t\t\t\t});\n\t\t\t\t\treturn true;\n\t\t\t\t} else if (elapsed >= shutdownTimeout) {\n\t\t\t\t\tthis.log?.warn({\n\t\t\t\t\t\tmsg: \"shutdown timeout reached, forcing close\",\n\t\t\t\t\t\tremainingActors: this.#actors.size,\n\t\t\t\t\t\telapsed,\n\t\t\t\t\t});\n\t\t\t\t\treturn true;\n\t\t\t\t} else {\n\t\t\t\t\t// Log progress every 5 seconds\n\t\t\t\t\tif (now - lastProgressLogTs >= progressLogInterval) {\n\t\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\t\tmsg: \"waiting for actors to stop\",\n\t\t\t\t\t\t\tremainingActors: this.#actors.size,\n\t\t\t\t\t\t\telapsed,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tlastProgressLogTs = now;\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// Check immediately first\n\t\t\tif (checkActors()) {\n\t\t\t\tthis.log?.debug({\n\t\t\t\t\tmsg: \"actors check completed immediately\",\n\t\t\t\t});\n\t\t\t\tresolve();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.log?.debug({\n\t\t\t\tmsg: \"starting actor wait interval\",\n\t\t\t\tcheckInterval: shutdownCheckInterval,\n\t\t\t});\n\n\t\t\tconst interval = setInterval(() => {\n\t\t\t\tthis.log?.debug({\n\t\t\t\t\tmsg: \"actor wait interval tick\",\n\t\t\t\t\tactorCount: this.#actors.size,\n\t\t\t\t});\n\t\t\t\tif (checkActors()) {\n\t\t\t\t\tthis.log?.debug({\n\t\t\t\t\t\tmsg: \"actors check completed, clearing interval\",\n\t\t\t\t\t});\n\t\t\t\t\tclearInterval(interval);\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t}, shutdownCheckInterval);\n\t\t});\n\t}\n\n\t// MARK: Networking\n\tget pegboardEndpoint() {\n\t\treturn this.#config.pegboardEndpoint || this.#config.endpoint;\n\t}\n\tget pegboardUrl() {\n\t\tconst wsEndpoint = this.pegboardEndpoint\n\t\t\t.replace(\"http://\", \"ws://\")\n\t\t\t.replace(\"https://\", \"wss://\");\n\n\t\t// Ensure the endpoint ends with /runners/connect\n\t\tconst baseUrl = wsEndpoint.endsWith(\"/\")\n\t\t\t? wsEndpoint.slice(0, -1)\n\t\t\t: wsEndpoint;\n\t\treturn `${baseUrl}/runners/connect?protocol_version=${PROTOCOL_VERSION}&namespace=${encodeURIComponent(this.#config.namespace)}&runner_key=${encodeURIComponent(this.#config.runnerKey)}`;\n\t}\n\n\t// MARK: Runner protocol\n\tasync #openPegboardWebSocket() {\n\t\tconst protocols = [\"rivet\"];\n\t\tif (this.config.token)\n\t\t\tprotocols.push(`rivet_token.${this.config.token}`);\n\n\t\tconst WS = await importWebSocket();\n\t\tconst ws = new WS(this.pegboardUrl, protocols) as any as WebSocket;\n\t\tthis.__pegboardWebSocket = ws;\n\n\t\tthis.log?.info({\n\t\t\tmsg: \"connecting\",\n\t\t\tendpoint: this.pegboardEndpoint,\n\t\t\tnamespace: this.#config.namespace,\n\t\t\trunnerKey: this.#config.runnerKey,\n\t\t\thasToken: !!this.config.token,\n\t\t});\n\n\t\tws.addEventListener(\"open\", () => {\n\t\t\tif (this.#reconnectAttempt > 0) {\n\t\t\t\tthis.log?.info({\n\t\t\t\t\tmsg: \"runner reconnected\",\n\t\t\t\t\tnamespace: this.#config.namespace,\n\t\t\t\t\trunnerName: this.#config.runnerName,\n\t\t\t\t\treconnectAttempt: this.#reconnectAttempt,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tthis.log?.debug({\n\t\t\t\t\tmsg: \"runner connected\",\n\t\t\t\t\tnamespace: this.#config.namespace,\n\t\t\t\t\trunnerName: this.#config.runnerName,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Reset reconnect attempt counter on successful connection\n\t\t\tthis.#reconnectAttempt = 0;\n\n\t\t\t// Clear any pending reconnect timeout\n\t\t\tif (this.#reconnectTimeout) {\n\t\t\t\tclearTimeout(this.#reconnectTimeout);\n\t\t\t\tthis.#reconnectTimeout = undefined;\n\t\t\t}\n\n\t\t\t// Clear any pending runner lost timeout since we're reconnecting\n\t\t\tif (this.#runnerLostTimeout) {\n\t\t\t\tclearTimeout(this.#runnerLostTimeout);\n\t\t\t\tthis.#runnerLostTimeout = undefined;\n\t\t\t}\n\n\t\t\t// Send init message\n\t\t\tconst init: protocol.ToServerInit = {\n\t\t\t\tname: this.#config.runnerName,\n\t\t\t\tversion: this.#config.version,\n\t\t\t\ttotalSlots: this.#config.totalSlots,\n\t\t\t\tprepopulateActorNames: new Map(\n\t\t\t\t\tObject.entries(this.#config.prepopulateActorNames).map(\n\t\t\t\t\t\t([name, data]) => [\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t{ metadata: JSON.stringify(data.metadata) },\n\t\t\t\t\t\t],\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t\tmetadata: JSON.stringify(this.#config.metadata),\n\t\t\t};\n\n\t\t\tthis.__sendToServer({\n\t\t\t\ttag: \"ToServerInit\",\n\t\t\t\tval: init,\n\t\t\t});\n\n\t\t\t// Start command acknowledgment interval (5 minutes)\n\t\t\tconst ackInterval = 5 * 60 * 1000; // 5 minutes in milliseconds\n\t\t\tconst ackLoop = setInterval(() => {\n\t\t\t\ttry {\n\t\t\t\t\tif (ws.readyState === 1) {\n\t\t\t\t\t\tthis.#sendCommandAcknowledgment();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclearInterval(ackLoop);\n\t\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\t\tmsg: \"WebSocket not open, stopping ack loop\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\tmsg: \"error in command acknowledgment loop\",\n\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}, ackInterval);\n\t\t\tthis.#ackInterval = ackLoop;\n\t\t});\n\n\t\tws.addEventListener(\"message\", async (ev) => {\n\t\t\tlet buf: Uint8Array;\n\t\t\tif (ev.data instanceof Blob) {\n\t\t\t\tbuf = new Uint8Array(await ev.data.arrayBuffer());\n\t\t\t} else if (Buffer.isBuffer(ev.data)) {\n\t\t\t\tbuf = new Uint8Array(ev.data);\n\t\t\t} else {\n\t\t\t\tthrow new Error(`expected binary data, got ${typeof ev.data}`);\n\t\t\t}\n\n\t\t\t// Parse message\n\t\t\tconst message = protocol.decodeToClient(buf);\n\t\t\tthis.log?.debug({\n\t\t\t\tmsg: \"received runner message\",\n\t\t\t\tdata: stringifyToClient(message),\n\t\t\t});\n\n\t\t\t// Handle message\n\t\t\tif (message.tag === \"ToClientInit\") {\n\t\t\t\tconst init = message.val;\n\n\t\t\t\tif (this.runnerId !== init.runnerId) {\n\t\t\t\t\tthis.runnerId = init.runnerId;\n\n\t\t\t\t\t// Clear actors if runner id changed\n\t\t\t\t\tthis.#stopAllActors();\n\t\t\t\t}\n\n\t\t\t\t// Store the runner lost threshold from metadata\n\t\t\t\tthis.#runnerLostThreshold = init.metadata?.runnerLostThreshold\n\t\t\t\t\t? Number(init.metadata.runnerLostThreshold)\n\t\t\t\t\t: undefined;\n\n\t\t\t\tthis.log?.info({\n\t\t\t\t\tmsg: \"received init\",\n\t\t\t\t\trunnerLostThreshold: this.#runnerLostThreshold,\n\t\t\t\t});\n\n\t\t\t\t// Resend pending events\n\t\t\t\tthis.#processUnsentKvRequests();\n\t\t\t\tthis.#resendUnacknowledgedEvents();\n\t\t\t\tthis.#tunnel?.resendBufferedEvents();\n\n\t\t\t\tthis.#config.onConnected();\n\t\t\t} else if (message.tag === \"ToClientCommands\") {\n\t\t\t\tconst commands = message.val;\n\t\t\t\tthis.#handleCommands(commands);\n\t\t\t} else if (message.tag === \"ToClientAckEvents\") {\n\t\t\t\tthis.#handleAckEvents(message.val);\n\t\t\t} else if (message.tag === \"ToClientKvResponse\") {\n\t\t\t\tconst kvResponse = message.val;\n\t\t\t\tthis.#handleKvResponse(kvResponse);\n\t\t\t} else if (message.tag === \"ToClientTunnelMessage\") {\n\t\t\t\tthis.#tunnel?.handleTunnelMessage(message.val).catch((err) => {\n\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\tmsg: \"error handling tunnel message\",\n\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t} else if (message.tag === \"ToClientPing\") {\n\t\t\t\tthis.__sendToServer({\n\t\t\t\t\ttag: \"ToServerPong\",\n\t\t\t\t\tval: {\n\t\t\t\t\t\tts: message.val.ts,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tunreachable(message);\n\t\t\t}\n\t\t});\n\n\t\tws.addEventListener(\"error\", (ev) => {\n\t\t\tthis.log?.error({\n\t\t\t\tmsg: `WebSocket error: ${ev.error}`,\n\t\t\t});\n\n\t\t\tif (!this.#shutdown) {\n\t\t\t\t// Start runner lost timeout if we have a threshold and are not shutting down\n\t\t\t\tif (\n\t\t\t\t\t!this.#runnerLostTimeout &&\n\t\t\t\t\tthis.#runnerLostThreshold &&\n\t\t\t\t\tthis.#runnerLostThreshold > 0\n\t\t\t\t) {\n\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\tmsg: \"starting runner lost timeout\",\n\t\t\t\t\t\tseconds: this.#runnerLostThreshold / 1000,\n\t\t\t\t\t});\n\t\t\t\t\tthis.#runnerLostTimeout = setTimeout(() => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tthis.#handleLost();\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\t\t\tmsg: \"error handling runner lost\",\n\t\t\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this.#runnerLostThreshold);\n\t\t\t\t}\n\n\t\t\t\t// Attempt to reconnect if not stopped\n\t\t\t\tthis.#scheduleReconnect();\n\t\t\t}\n\t\t});\n\n\t\tws.addEventListener(\"close\", async (ev) => {\n\t\t\tconst closeError = parseWebSocketCloseReason(ev.reason);\n\t\t\tif (\n\t\t\t\tcloseError?.group === \"ws\" &&\n\t\t\t\tcloseError?.error === \"eviction\"\n\t\t\t) {\n\t\t\t\tthis.log?.info(\"runner websocket evicted\");\n\n\t\t\t\tthis.#config.onDisconnected(ev.code, ev.reason);\n\n\t\t\t\tawait this.shutdown(true);\n\t\t\t} else {\n\t\t\t\tif (\n\t\t\t\t\tcloseError?.group === \"pegboard\" &&\n\t\t\t\t\tcloseError?.error === \"runner_shutdown\"\n\t\t\t\t) {\n\t\t\t\t\tthis.log?.info(\"runner shutdown\");\n\t\t\t\t} else {\n\t\t\t\t\tthis.log?.warn({\n\t\t\t\t\t\tmsg: \"runner disconnected\",\n\t\t\t\t\t\tcode: ev.code,\n\t\t\t\t\t\treason: ev.reason.toString(),\n\t\t\t\t\t\tcloseError,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tthis.#config.onDisconnected(ev.code, ev.reason);\n\t\t\t}\n\n\t\t\t// Clear ack interval on close\n\t\t\tif (this.#ackInterval) {\n\t\t\t\tclearInterval(this.#ackInterval);\n\t\t\t\tthis.#ackInterval = undefined;\n\t\t\t}\n\n\t\t\tif (!this.#shutdown) {\n\t\t\t\t// Start runner lost timeout if we have a threshold and are not shutting down\n\t\t\t\tif (\n\t\t\t\t\t!this.#runnerLostTimeout &&\n\t\t\t\t\tthis.#runnerLostThreshold &&\n\t\t\t\t\tthis.#runnerLostThreshold > 0\n\t\t\t\t) {\n\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\tmsg: \"starting runner lost timeout\",\n\t\t\t\t\t\tseconds: this.#runnerLostThreshold / 1000,\n\t\t\t\t\t});\n\t\t\t\t\tthis.#runnerLostTimeout = setTimeout(() => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tthis.#handleLost();\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\t\t\tmsg: \"error handling runner lost\",\n\t\t\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this.#runnerLostThreshold);\n\t\t\t\t}\n\n\t\t\t\t// Attempt to reconnect if not stopped\n\t\t\t\tthis.#scheduleReconnect();\n\t\t\t}\n\t\t});\n\t}\n\n\t#handleCommands(commands: protocol.ToClientCommands) {\n\t\tthis.log?.info({\n\t\t\tmsg: \"received commands\",\n\t\t\tcommandCount: commands.length,\n\t\t});\n\n\t\tfor (const commandWrapper of commands) {\n\t\t\tif (commandWrapper.inner.tag === \"CommandStartActor\") {\n\t\t\t\t// Spawn background promise\n\t\t\t\tthis.#handleCommandStartActor(commandWrapper).catch((err) => {\n\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\tmsg: \"error handling start actor command\",\n\t\t\t\t\t\tactorId: commandWrapper.checkpoint.actorId,\n\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\t// NOTE: We don't do this for CommandStopActor because the actor will be removed by that call\n\t\t\t\t// so we cant update the checkpoint\n\t\t\t\tconst actor = this.getActor(\n\t\t\t\t\tcommandWrapper.checkpoint.actorId,\n\t\t\t\t\tcommandWrapper.checkpoint.generation,\n\t\t\t\t);\n\t\t\t\tif (actor) actor.lastCommandIdx = commandWrapper.checkpoint.index;\n\t\t\t} else if (commandWrapper.inner.tag === \"CommandStopActor\") {\n\t\t\t\t// Spawn background promise\n\t\t\t\tthis.#handleCommandStopActor(commandWrapper).catch((err) => {\n\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\tmsg: \"error handling stop actor command\",\n\t\t\t\t\t\tactorId: commandWrapper.checkpoint.actorId,\n\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tunreachable(commandWrapper.inner);\n\t\t\t}\n\t\t}\n\t}\n\n\t#handleAckEvents(ack: protocol.ToClientAckEvents) {\n\t\tlet originalTotalEvents = Array.from(this.#actors).reduce(\n\t\t\t(s, [_, actor]) => s + actor.eventHistory.length,\n\t\t\t0,\n\t\t);\n\n\t\tfor (const [_, actor] of this.#actors) {\n\t\t\tlet checkpoint = ack.lastEventCheckpoints.find(\n\t\t\t\t(x) => x.actorId == actor.actorId,\n\t\t\t);\n\n\t\t\tif (checkpoint) actor.handleAckEvents(checkpoint.index);\n\t\t}\n\n\t\tconst totalEvents = Array.from(this.#actors).reduce(\n\t\t\t(s, [_, actor]) => s + actor.eventHistory.length,\n\t\t\t0,\n\t\t);\n\t\tconst prunedCount = originalTotalEvents - totalEvents;\n\n\t\tif (prunedCount > 0) {\n\t\t\tthis.log?.info({\n\t\t\t\tmsg: \"pruned acknowledged events\",\n\t\t\t\tprunedCount,\n\t\t\t});\n\t\t}\n\n\t\tif (totalEvents <= EVENT_BACKLOG_WARN_THRESHOLD) {\n\t\t\tthis.#eventBacklogWarned = false;\n\t\t}\n\t}\n\n\t/** Track events to send to the server in case we need to resend it on disconnect. */\n\t#recordEvent(eventWrapper: protocol.EventWrapper) {\n\t\tconst actor = this.getActor(eventWrapper.checkpoint.actorId);\n\t\tif (!actor) return;\n\n\t\tactor.recordEvent(eventWrapper);\n\n\t\tlet totalEvents = Array.from(this.#actors).reduce(\n\t\t\t(s, [_, actor]) => s + actor.eventHistory.length,\n\t\t\t0,\n\t\t);\n\n\t\tif (\n\t\t\ttotalEvents > EVENT_BACKLOG_WARN_THRESHOLD &&\n\t\t\t!this.#eventBacklogWarned\n\t\t) {\n\t\t\tthis.#eventBacklogWarned = true;\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"unacknowledged event backlog exceeds threshold\",\n\t\t\t\tbacklogSize: totalEvents,\n\t\t\t\tthreshold: EVENT_BACKLOG_WARN_THRESHOLD,\n\t\t\t});\n\t\t}\n\t}\n\n\tasync #handleCommandStartActor(commandWrapper: protocol.CommandWrapper) {\n\t\t// IMPORTANT: Make sure no async code runs before inserting #actors and\n\t\t// calling addRequestToActor in order to prevent race conditions with\n\t\t// subsequence commands\n\n\t\tif (!this.#tunnel) throw new Error(\"missing tunnel on actor start\");\n\n\t\tconst startCommand = commandWrapper.inner\n\t\t\t.val as protocol.CommandStartActor;\n\n\t\tconst actorId = commandWrapper.checkpoint.actorId;\n\t\tconst generation = commandWrapper.checkpoint.generation;\n\t\tconst config = startCommand.config;\n\n\t\tconst actorConfig: ActorConfig = {\n\t\t\tname: config.name,\n\t\t\tkey: config.key,\n\t\t\tcreateTs: config.createTs,\n\t\t\tinput: config.input ? new Uint8Array(config.input) : null,\n\t\t};\n\n\t\tconst instance = new RunnerActor(\n\t\t\tactorId,\n\t\t\tgeneration,\n\t\t\tactorConfig,\n\t\t\tstartCommand.hibernatingRequests,\n\t\t);\n\n\t\tconst existingActor = this.#actors.get(actorId);\n\t\tif (existingActor) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"replacing existing actor in actors map\",\n\t\t\t\tactorId,\n\t\t\t\texistingGeneration: existingActor.generation,\n\t\t\t\tnewGeneration: generation,\n\t\t\t\texistingPendingRequests: existingActor.pendingRequests.length,\n\t\t\t});\n\t\t}\n\n\t\tthis.#actors.set(actorId, instance);\n\n\t\t// NOTE: We have to populate the requestToActor map BEFORE running any\n\t\t// async code in order for incoming tunnel messages to wait for\n\t\t// instance.actorStartPromise before processing messages\n\t\t// TODO: Where is this GC'd if something fails?\n\t\tfor (const hr of startCommand.hibernatingRequests) {\n\t\t\tthis.#tunnel.addRequestToActor(hr.gatewayId, hr.requestId, actorId);\n\t\t}\n\n\t\tthis.log?.info({\n\t\t\tmsg: \"created actor\",\n\t\t\tactors: this.#actors.size,\n\t\t\tactorId,\n\t\t\tname: config.name,\n\t\t\tkey: config.key,\n\t\t\tgeneration,\n\t\t\thibernatingRequests: startCommand.hibernatingRequests.length,\n\t\t});\n\n\t\tthis.#sendActorStateUpdate(actorId, generation, \"running\");\n\n\t\ttry {\n\t\t\t// TODO: Add timeout to onActorStart\n\t\t\t// Call onActorStart asynchronously and handle errors\n\t\t\tthis.log?.debug({\n\t\t\t\tmsg: \"calling onActorStart\",\n\t\t\t\tactorId,\n\t\t\t\tgeneration,\n\t\t\t});\n\t\t\tawait this.#config.onActorStart(actorId, generation, actorConfig);\n\n\t\t\tinstance.actorStartPromise.resolve();\n\t\t} catch (err) {\n\t\t\tthis.log?.error({\n\t\t\t\tmsg: \"error starting runner actor\",\n\t\t\t\tactorId,\n\t\t\t\terr,\n\t\t\t});\n\n\t\t\tinstance.actorStartPromise.reject(err);\n\n\t\t\t// TODO: Mark as crashed\n\t\t\t// Send stopped state update if start failed\n\t\t\tawait this.forceStopActor(actorId, generation);\n\t\t}\n\t}\n\n\tasync #handleCommandStopActor(commandWrapper: protocol.CommandWrapper) {\n\t\tconst stopCommand = commandWrapper.inner\n\t\t\t.val as protocol.CommandStopActor;\n\n\t\tconst actorId = commandWrapper.checkpoint.actorId;\n\t\tconst generation = commandWrapper.checkpoint.generation;\n\n\t\tawait this.forceStopActor(actorId, generation);\n\t}\n\n\t#sendActorIntent(\n\t\tactorId: string,\n\t\tgeneration: number,\n\t\tintentType: \"sleep\" | \"stop\",\n\t) {\n\t\tconst actor = this.getActor(actorId, generation);\n\t\tif (!actor) return;\n\n\t\tlet actorIntent: protocol.ActorIntent;\n\n\t\tif (intentType === \"sleep\") {\n\t\t\tactorIntent = { tag: \"ActorIntentSleep\", val: null };\n\t\t} else if (intentType === \"stop\") {\n\t\t\tactorIntent = {\n\t\t\t\ttag: \"ActorIntentStop\",\n\t\t\t\tval: null,\n\t\t\t};\n\t\t} else {\n\t\t\tunreachable(intentType);\n\t\t}\n\n\t\tconst intentEvent: protocol.EventActorIntent = {\n\t\t\tintent: actorIntent,\n\t\t};\n\n\t\tconst eventWrapper: protocol.EventWrapper = {\n\t\t\tcheckpoint: {\n\t\t\t\tactorId,\n\t\t\t\tgeneration,\n\t\t\t\tindex: actor.nextEventIdx++,\n\t\t\t},\n\t\t\tinner: {\n\t\t\t\ttag: \"EventActorIntent\",\n\t\t\t\tval: intentEvent,\n\t\t\t},\n\t\t};\n\n\t\tthis.#recordEvent(eventWrapper);\n\n\t\tthis.__sendToServer({\n\t\t\ttag: \"ToServerEvents\",\n\t\t\tval: [eventWrapper],\n\t\t});\n\t}\n\n\t#sendActorStateUpdate(\n\t\tactorId: string,\n\t\tgeneration: number,\n\t\tstateType: \"running\" | \"stopped\",\n\t) {\n\t\tconst actor = this.getActor(actorId, generation);\n\t\tif (!actor) return;\n\n\t\tlet actorState: protocol.ActorState;\n\n\t\tif (stateType === \"running\") {\n\t\t\tactorState = { tag: \"ActorStateRunning\", val: null };\n\t\t} else if (stateType === \"stopped\") {\n\t\t\tactorState = {\n\t\t\t\ttag: \"ActorStateStopped\",\n\t\t\t\tval: {\n\t\t\t\t\tcode: protocol.StopCode.Ok,\n\t\t\t\t\tmessage: null,\n\t\t\t\t},\n\t\t\t};\n\t\t} else {\n\t\t\tunreachable(stateType);\n\t\t}\n\n\t\tconst stateUpdateEvent: protocol.EventActorStateUpdate = {\n\t\t\tstate: actorState,\n\t\t};\n\n\t\tconst eventWrapper: protocol.EventWrapper = {\n\t\t\tcheckpoint: {\n\t\t\t\tactorId,\n\t\t\t\tgeneration,\n\t\t\t\tindex: actor.nextEventIdx++,\n\t\t\t},\n\t\t\tinner: {\n\t\t\t\ttag: \"EventActorStateUpdate\",\n\t\t\t\tval: stateUpdateEvent,\n\t\t\t},\n\t\t};\n\n\t\tthis.#recordEvent(eventWrapper);\n\n\t\tthis.__sendToServer({\n\t\t\ttag: \"ToServerEvents\",\n\t\t\tval: [eventWrapper],\n\t\t});\n\t}\n\n\t#sendCommandAcknowledgment() {\n\t\tconst lastCommandCheckpoints = [];\n\n\t\tfor (const [_, actor] of this.#actors) {\n\t\t\tif (actor.lastCommandIdx < 0) {\n\t\t\t\t// No commands received yet, nothing to acknowledge\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlastCommandCheckpoints.push({\n\t\t\t\tactorId: actor.actorId,\n\t\t\t\tgeneration: actor.generation,\n\t\t\t\tindex: actor.lastCommandIdx,\n\t\t\t});\n\t\t}\n\n\t\t//this.#log?.log(\"Sending command acknowledgment\", this.#lastCommandIdx);\n\n\t\tthis.__sendToServer({\n\t\t\ttag: \"ToServerAckCommands\",\n\t\t\tval: {\n\t\t\t\tlastCommandCheckpoints,\n\t\t\t},\n\t\t});\n\t}\n\n\t#handleKvResponse(response: protocol.ToClientKvResponse) {\n\t\tconst requestId = response.requestId;\n\t\tconst request = this.#kvRequests.get(requestId);\n\n\t\tif (!request) {\n\t\t\tthis.log?.error({\n\t\t\t\tmsg: \"received kv response for unknown request id\",\n\t\t\t\trequestId,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#kvRequests.delete(requestId);\n\n\t\tif (response.data.tag === \"KvErrorResponse\") {\n\t\t\trequest.reject(\n\t\t\t\tnew Error(response.data.val.message || \"Unknown KV error\"),\n\t\t\t);\n\t\t} else {\n\t\t\trequest.resolve(response.data.val);\n\t\t}\n\t}\n\n\t#parseGetResponseSimple(\n\t\tresponse: protocol.KvGetResponse,\n\t\trequestedKeys: Uint8Array[],\n\t): (Uint8Array | null)[] {\n\t\t// Parse the response keys and values\n\t\tconst responseKeys: Uint8Array[] = [];\n\t\tconst responseValues: Uint8Array[] = [];\n\n\t\tfor (const key of response.keys) {\n\t\t\tresponseKeys.push(new Uint8Array(key));\n\t\t}\n\n\t\tfor (const value of response.values) {\n\t\t\tresponseValues.push(new Uint8Array(value));\n\t\t}\n\n\t\t// Map response back to requested key order\n\t\tconst result: (Uint8Array | null)[] = [];\n\t\tfor (const requestedKey of requestedKeys) {\n\t\t\tlet found = false;\n\t\t\tfor (let i = 0; i < responseKeys.length; i++) {\n\t\t\t\tif (this.#keysEqual(requestedKey, responseKeys[i])) {\n\t\t\t\t\tresult.push(responseValues[i]);\n\t\t\t\t\tfound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!found) {\n\t\t\t\tresult.push(null);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t#keysEqual(key1: Uint8Array, key2: Uint8Array): boolean {\n\t\tif (key1.length !== key2.length) return false;\n\t\tfor (let i = 0; i < key1.length; i++) {\n\t\t\tif (key1[i] !== key2[i]) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t//#parseGetResponse(response: protocol.KvGetResponse) {\n\t//\tconst keys: string[] = [];\n\t//\tconst values: Uint8Array[] = [];\n\t//\tconst metadata: { version: Uint8Array; createTs: bigint }[] = [];\n\t//\n\t//\tfor (const key of response.keys) {\n\t//\t\tkeys.push(new TextDecoder().decode(key));\n\t//\t}\n\t//\n\t//\tfor (const value of response.values) {\n\t//\t\tvalues.push(new Uint8Array(value));\n\t//\t}\n\t//\n\t//\tfor (const meta of response.metadata) {\n\t//\t\tmetadata.push({\n\t//\t\t\tversion: new Uint8Array(meta.version),\n\t//\t\t\tcreateTs: meta.createTs,\n\t//\t\t});\n\t//\t}\n\t//\n\t//\treturn { keys, values, metadata };\n\t//}\n\n\t#parseListResponseSimple(\n\t\tresponse: protocol.KvListResponse,\n\t): [Uint8Array, Uint8Array][] {\n\t\tconst result: [Uint8Array, Uint8Array][] = [];\n\n\t\tfor (let i = 0; i < response.keys.length; i++) {\n\t\t\tconst key = response.keys[i];\n\t\t\tconst value = response.values[i];\n\n\t\t\tif (key && value) {\n\t\t\t\tconst keyBytes = new Uint8Array(key);\n\t\t\t\tconst valueBytes = new Uint8Array(value);\n\t\t\t\tresult.push([keyBytes, valueBytes]);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t//#parseListResponse(response: protocol.KvListResponse) {\n\t//\tconst keys: string[] = [];\n\t//\tconst values: Uint8Array[] = [];\n\t//\tconst metadata: { version: Uint8Array; createTs: bigint }[] = [];\n\t//\n\t//\tfor (const key of response.keys) {\n\t//\t\tkeys.push(new TextDecoder().decode(key));\n\t//\t}\n\t//\n\t//\tfor (const value of response.values) {\n\t//\t\tvalues.push(new Uint8Array(value));\n\t//\t}\n\t//\n\t//\tfor (const meta of response.metadata) {\n\t//\t\tmetadata.push({\n\t//\t\t\tversion: new Uint8Array(meta.version),\n\t//\t\t\tcreateTs: meta.createTs,\n\t//\t\t});\n\t//\t}\n\t//\n\t//\treturn { keys, values, metadata };\n\t//}\n\n\t// MARK: KV Operations\n\tasync kvGet(\n\t\tactorId: string,\n\t\tkeys: Uint8Array[],\n\t): Promise<(Uint8Array | null)[]> {\n\t\tconst kvKeys: protocol.KvKey[] = keys.map(\n\t\t\t(key) =>\n\t\t\t\tkey.buffer.slice(\n\t\t\t\t\tkey.byteOffset,\n\t\t\t\t\tkey.byteOffset + key.byteLength,\n\t\t\t\t) as ArrayBuffer,\n\t\t);\n\n\t\tconst requestData: protocol.KvRequestData = {\n\t\t\ttag: \"KvGetRequest\",\n\t\t\tval: { keys: kvKeys },\n\t\t};\n\n\t\tconst response = await this.#sendKvRequest(actorId, requestData);\n\t\treturn this.#parseGetResponseSimple(response, keys);\n\t}\n\n\tasync kvListAll(\n\t\tactorId: string,\n\t\toptions?: KvListOptions,\n\t): Promise<[Uint8Array, Uint8Array][]> {\n\t\tconst requestData: protocol.KvRequestData = {\n\t\t\ttag: \"KvListRequest\",\n\t\t\tval: {\n\t\t\t\tquery: { tag: \"KvListAllQuery\", val: null },\n\t\t\t\treverse: options?.reverse || null,\n\t\t\t\tlimit:\n\t\t\t\t\toptions?.limit !== undefined ? BigInt(options.limit) : null,\n\t\t\t},\n\t\t};\n\n\t\tconst response = await this.#sendKvRequest(actorId, requestData);\n\t\treturn this.#parseListResponseSimple(response);\n\t}\n\n\tasync kvListRange(\n\t\tactorId: string,\n\t\tstart: Uint8Array,\n\t\tend: Uint8Array,\n\t\texclusive?: boolean,\n\t\toptions?: KvListOptions,\n\t): Promise<[Uint8Array, Uint8Array][]> {\n\t\tconst startKey: protocol.KvKey = start.buffer.slice(\n\t\t\tstart.byteOffset,\n\t\t\tstart.byteOffset + start.byteLength,\n\t\t) as ArrayBuffer;\n\t\tconst endKey: protocol.KvKey = end.buffer.slice(\n\t\t\tend.byteOffset,\n\t\t\tend.byteOffset + end.byteLength,\n\t\t) as ArrayBuffer;\n\n\t\tconst requestData: protocol.KvRequestData = {\n\t\t\ttag: \"KvListRequest\",\n\t\t\tval: {\n\t\t\t\tquery: {\n\t\t\t\t\ttag: \"KvListRangeQuery\",\n\t\t\t\t\tval: {\n\t\t\t\t\t\tstart: startKey,\n\t\t\t\t\t\tend: endKey,\n\t\t\t\t\t\texclusive: exclusive || false,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\treverse: options?.reverse || null,\n\t\t\t\tlimit:\n\t\t\t\t\toptions?.limit !== undefined ? BigInt(options.limit) : null,\n\t\t\t},\n\t\t};\n\n\t\tconst response = await this.#sendKvRequest(actorId, requestData);\n\t\treturn this.#parseListResponseSimple(response);\n\t}\n\n\tasync kvListPrefix(\n\t\tactorId: string,\n\t\tprefix: Uint8Array,\n\t\toptions?: KvListOptions,\n\t): Promise<[Uint8Array, Uint8Array][]> {\n\t\tconst prefixKey: protocol.KvKey = prefix.buffer.slice(\n\t\t\tprefix.byteOffset,\n\t\t\tprefix.byteOffset + prefix.byteLength,\n\t\t) as ArrayBuffer;\n\n\t\tconst requestData: protocol.KvRequestData = {\n\t\t\ttag: \"KvListRequest\",\n\t\t\tval: {\n\t\t\t\tquery: {\n\t\t\t\t\ttag: \"KvListPrefixQuery\",\n\t\t\t\t\tval: { key: prefixKey },\n\t\t\t\t},\n\t\t\t\treverse: options?.reverse || null,\n\t\t\t\tlimit:\n\t\t\t\t\toptions?.limit !== undefined ? BigInt(options.limit) : null,\n\t\t\t},\n\t\t};\n\n\t\tconst response = await this.#sendKvRequest(actorId, requestData);\n\t\treturn this.#parseListResponseSimple(response);\n\t}\n\n\tasync kvPut(\n\t\tactorId: string,\n\t\tentries: [Uint8Array, Uint8Array][],\n\t): Promise<void> {\n\t\tconst keys: protocol.KvKey[] = entries.map(\n\t\t\t([key, _value]) =>\n\t\t\t\tkey.buffer.slice(\n\t\t\t\t\tkey.byteOffset,\n\t\t\t\t\tkey.byteOffset + key.byteLength,\n\t\t\t\t) as ArrayBuffer,\n\t\t);\n\t\tconst values: protocol.KvValue[] = entries.map(\n\t\t\t([_key, value]) =>\n\t\t\t\tvalue.buffer.slice(\n\t\t\t\t\tvalue.byteOffset,\n\t\t\t\t\tvalue.byteOffset + value.byteLength,\n\t\t\t\t) as ArrayBuffer,\n\t\t);\n\n\t\tconst requestData: protocol.KvRequestData = {\n\t\t\ttag: \"KvPutRequest\",\n\t\t\tval: { keys, values },\n\t\t};\n\n\t\tawait this.#sendKvRequest(actorId, requestData);\n\t}\n\n\tasync kvDelete(actorId: string, keys: Uint8Array[]): Promise<void> {\n\t\tconst kvKeys: protocol.KvKey[] = keys.map(\n\t\t\t(key) =>\n\t\t\t\tkey.buffer.slice(\n\t\t\t\t\tkey.byteOffset,\n\t\t\t\t\tkey.byteOffset + key.byteLength,\n\t\t\t\t) as ArrayBuffer,\n\t\t);\n\n\t\tconst requestData: protocol.KvRequestData = {\n\t\t\ttag: \"KvDeleteRequest\",\n\t\t\tval: { keys: kvKeys },\n\t\t};\n\n\t\tawait this.#sendKvRequest(actorId, requestData);\n\t}\n\n\tasync kvDrop(actorId: string): Promise<void> {\n\t\tconst requestData: protocol.KvRequestData = {\n\t\t\ttag: \"KvDropRequest\",\n\t\t\tval: null,\n\t\t};\n\n\t\tawait this.#sendKvRequest(actorId, requestData);\n\t}\n\n\t// MARK: Alarm Operations\n\tsetAlarm(actorId: string, alarmTs: number | null, generation?: number) {\n\t\tconst actor = this.getActor(actorId, generation);\n\t\tif (!actor) return;\n\n\t\tconst alarmEvent: protocol.EventActorSetAlarm = {\n\t\t\talarmTs: alarmTs !== null ? BigInt(alarmTs) : null,\n\t\t};\n\n\t\tconst eventWrapper: protocol.EventWrapper = {\n\t\t\tcheckpoint: {\n\t\t\t\tactorId,\n\t\t\t\tgeneration: actor.generation,\n\t\t\t\tindex: actor.nextEventIdx++,\n\t\t\t},\n\t\t\tinner: {\n\t\t\t\ttag: \"EventActorSetAlarm\",\n\t\t\t\tval: alarmEvent,\n\t\t\t},\n\t\t};\n\n\t\tthis.#recordEvent(eventWrapper);\n\n\t\tthis.__sendToServer({\n\t\t\ttag: \"ToServerEvents\",\n\t\t\tval: [eventWrapper],\n\t\t});\n\t}\n\n\tclearAlarm(actorId: string, generation?: number) {\n\t\tthis.setAlarm(actorId, null, generation);\n\t}\n\n\t#sendKvRequest(\n\t\tactorId: string,\n\t\trequestData: protocol.KvRequestData,\n\t): Promise<any> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst requestId = this.#nextKvRequestId++;\n\n\t\t\t// Store the request\n\t\t\tconst requestEntry = {\n\t\t\t\tactorId,\n\t\t\t\tdata: requestData,\n\t\t\t\tresolve,\n\t\t\t\treject,\n\t\t\t\tsent: false,\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t};\n\n\t\t\tthis.#kvRequests.set(requestId, requestEntry);\n\n\t\t\tif (this.__webSocketReady()) {\n\t\t\t\t// Send immediately\n\t\t\t\tthis.#sendSingleKvRequest(requestId);\n\t\t\t}\n\t\t});\n\t}\n\n\t#sendSingleKvRequest(requestId: number) {\n\t\tconst request = this.#kvRequests.get(requestId);\n\t\tif (!request || request.sent) return;\n\n\t\ttry {\n\t\t\tconst kvRequest: protocol.ToServerKvRequest = {\n\t\t\t\tactorId: request.actorId,\n\t\t\t\trequestId,\n\t\t\t\tdata: request.data,\n\t\t\t};\n\n\t\t\tthis.__sendToServer({\n\t\t\t\ttag: \"ToServerKvRequest\",\n\t\t\t\tval: kvRequest,\n\t\t\t});\n\n\t\t\t// Mark as sent and update timestamp\n\t\t\trequest.sent = true;\n\t\t\trequest.timestamp = Date.now();\n\t\t} catch (error) {\n\t\t\tthis.#kvRequests.delete(requestId);\n\t\t\trequest.reject(error);\n\t\t}\n\t}\n\n\t#processUnsentKvRequests() {\n\t\tif (!this.__webSocketReady()) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet processedCount = 0;\n\t\tfor (const [requestId, request] of this.#kvRequests.entries()) {\n\t\t\tif (!request.sent) {\n\t\t\t\tthis.#sendSingleKvRequest(requestId);\n\t\t\t\tprocessedCount++;\n\t\t\t}\n\t\t}\n\n\t\tif (processedCount > 0) {\n\t\t\t//this.#log?.log(`Processed ${processedCount} queued KV requests`);\n\t\t}\n\t}\n\n\t/** Asserts WebSocket exists and is ready. */\n\t__webSocketReady(): this is this & {\n\t\t__pegboardWebSocket: NonNullable<Runner[\"__pegboardWebSocket\"]>;\n\t} {\n\t\treturn (\n\t\t\t!!this.__pegboardWebSocket &&\n\t\t\tthis.__pegboardWebSocket.readyState === 1\n\t\t);\n\t}\n\n\t__sendToServer(message: protocol.ToServer) {\n\t\tthis.log?.debug({\n\t\t\tmsg: \"sending runner message\",\n\t\t\tdata: stringifyToServer(message),\n\t\t});\n\n\t\tconst encoded = protocol.encodeToServer(message);\n\t\tif (this.__webSocketReady()) {\n\t\t\tthis.__pegboardWebSocket.send(encoded);\n\t\t} else {\n\t\t\tthis.log?.error({\n\t\t\t\tmsg: \"WebSocket not available or not open for sending data\",\n\t\t\t});\n\t\t}\n\t}\n\n\tsendHibernatableWebSocketMessageAck(\n\t\tgatewayId: ArrayBuffer,\n\t\trequestId: ArrayBuffer,\n\t\tindex: number,\n\t) {\n\t\tif (!this.#tunnel)\n\t\t\tthrow new Error(\"missing tunnel to send message ack\");\n\t\tthis.#tunnel.sendHibernatableWebSocketMessageAck(\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t\tindex,\n\t\t);\n\t}\n\n\t/**\n\t * Restores hibernatable WebSocket connections for an actor.\n\t *\n\t * This method should be called at the end of `onActorStart` after the\n\t * actor instance is fully initialized.\n\t *\n\t * This method will:\n\t * - Restore all provided hibernatable WebSocket connections\n\t * - Attach event listeners to the restored WebSockets\n\t * - Close any WebSocket connections that failed to restore\n\t *\n\t * The provided metadata list should include all hibernatable WebSockets\n\t * that were persisted for this actor. The gateway will automatically\n\t * close any connections that are not restored (i.e., not included in\n\t * this list).\n\t *\n\t * **Important:** This method must be called after `onActorStart` completes\n\t * and before marking the actor as \"ready\" to ensure all hibernatable\n\t * connections are fully restored.\n\t *\n\t * @param actorId - The ID of the actor to restore connections for\n\t * @param metaEntries - Array of hibernatable WebSocket metadata to restore\n\t */\n\tasync restoreHibernatingRequests(\n\t\tactorId: string,\n\t\tmetaEntries: HibernatingWebSocketMetadata[],\n\t) {\n\t\tif (!this.#tunnel)\n\t\t\tthrow new Error(\"missing tunnel to restore hibernating requests\");\n\t\tawait this.#tunnel.restoreHibernatingRequests(actorId, metaEntries);\n\t}\n\n\tgetServerlessInitPacket(): string | undefined {\n\t\tif (!this.runnerId) return undefined;\n\n\t\tconst data = protocol.encodeToServerlessServer({\n\t\t\ttag: \"ToServerlessServerInit\",\n\t\t\tval: {\n\t\t\t\trunnerId: this.runnerId,\n\t\t\t\trunnerProtocolVersion: PROTOCOL_VERSION,\n\t\t\t},\n\t\t});\n\n\t\t// Embed version\n\t\tconst buffer = Buffer.alloc(data.length + 2);\n\t\tbuffer.writeUInt16LE(PROTOCOL_VERSION, 0);\n\t\tBuffer.from(data).copy(buffer, 2);\n\n\t\treturn buffer.toString(\"base64\");\n\t}\n\n\t#scheduleReconnect() {\n\t\tif (this.#shutdown) {\n\t\t\tthis.log?.debug({\n\t\t\t\tmsg: \"Runner is shut down, not attempting reconnect\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconst delay = calculateBackoff(this.#reconnectAttempt, {\n\t\t\tinitialDelay: 1000,\n\t\t\tmaxDelay: 30000,\n\t\t\tmultiplier: 2,\n\t\t\tjitter: true,\n\t\t});\n\n\t\tthis.log?.debug({\n\t\t\tmsg: `Scheduling reconnect attempt ${this.#reconnectAttempt + 1} in ${delay}ms`,\n\t\t});\n\n\t\tthis.#reconnectTimeout = setTimeout(() => {\n\t\t\tif (!this.#shutdown) {\n\t\t\t\tthis.#reconnectAttempt++;\n\t\t\t\tthis.log?.debug({\n\t\t\t\t\tmsg: `Attempting to reconnect (attempt ${this.#reconnectAttempt})...`,\n\t\t\t\t});\n\t\t\t\tthis.#openPegboardWebSocket().catch((err) => {\n\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\tmsg: \"error during websocket reconnection\",\n\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\t\t}, delay);\n\t}\n\n\t#resendUnacknowledgedEvents() {\n\t\tconst eventsToResend = [];\n\n\t\tfor (const [_, actor] of this.#actors) {\n\t\t\teventsToResend.push(...actor.eventHistory);\n\t\t}\n\n\t\tif (eventsToResend.length === 0) return;\n\n\t\tthis.log?.info({\n\t\t\tmsg: \"resending unacknowledged events\",\n\t\t\tcount: eventsToResend.length,\n\t\t});\n\n\t\t// Resend events in batches\n\t\tthis.__sendToServer({\n\t\t\ttag: \"ToServerEvents\",\n\t\t\tval: eventsToResend,\n\t\t});\n\t}\n\n\t#cleanupOldKvRequests() {\n\t\tconst thirtySecondsAgo = Date.now() - KV_EXPIRE;\n\t\tconst toDelete: number[] = [];\n\n\t\tfor (const [requestId, request] of this.#kvRequests.entries()) {\n\t\t\tif (request.timestamp < thirtySecondsAgo) {\n\t\t\t\trequest.reject(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\"KV request timed out waiting for WebSocket connection\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\ttoDelete.push(requestId);\n\t\t\t}\n\t\t}\n\n\t\tfor (const requestId of toDelete) {\n\t\t\tthis.#kvRequests.delete(requestId);\n\t\t}\n\n\t\tif (toDelete.length > 0) {\n\t\t\t//this.#log?.log(`Cleaned up ${toDelete.length} expired KV requests`);\n\t\t}\n\t}\n}\n","import type { Logger } from \"pino\";\n\nlet LOGGER: Logger | undefined;\n\nexport function setLogger(logger: Logger) {\n\tLOGGER = logger;\n}\n\nexport function logger(): Logger | undefined {\n\treturn LOGGER;\n}\n","import { logger } from \"./log\";\n\nexport function unreachable(x: never): never {\n\tthrow `Unreachable: ${x}`;\n}\n\nexport interface BackoffOptions {\n\tinitialDelay?: number;\n\tmaxDelay?: number;\n\tmultiplier?: number;\n\tjitter?: boolean;\n}\n\nexport function calculateBackoff(\n\tattempt: number,\n\toptions: BackoffOptions = {},\n): number {\n\tconst {\n\t\tinitialDelay = 1000,\n\t\tmaxDelay = 30000,\n\t\tmultiplier = 2,\n\t\tjitter = true,\n\t} = options;\n\n\tlet delay = Math.min(initialDelay * multiplier ** attempt, maxDelay);\n\n\tif (jitter) {\n\t\t// Add random jitter between 0% and 25% of the delay\n\t\tdelay = delay * (1 + Math.random() * 0.25);\n\t}\n\n\treturn Math.floor(delay);\n}\n\nexport interface ParsedCloseReason {\n\tgroup: string;\n\terror: string;\n\trayId?: string;\n}\n\n/**\n * Parses a WebSocket close reason in the format: {group}.{error} or {group}.{error}#{ray_id}\n *\n * Examples:\n * - \"ws.eviction#t1s80so6h3irenp8ymzltfoittcl00\"\n * - \"ws.client_closed\"\n *\n * Returns undefined if the format is invalid\n */\nexport function parseWebSocketCloseReason(\n\treason: string,\n): ParsedCloseReason | undefined {\n\tconst [mainPart, rayId] = reason.split(\"#\");\n\tconst [group, error] = mainPart.split(\".\");\n\n\tif (!group || !error) {\n\t\tlogger()?.warn({ msg: \"failed to parse close reason\", reason });\n\t\treturn undefined;\n\t}\n\n\treturn {\n\t\tgroup,\n\t\terror,\n\t\trayId,\n\t};\n}\n\nconst U16_MAX = 65535;\n\n/**\n * Wrapping greater than comparison for u16 values.\n * Based on shared_state.rs wrapping_gt implementation.\n */\nexport function wrappingGtU16(a: number, b: number): boolean {\n\treturn a !== b && wrappingSub(a, b, U16_MAX) < U16_MAX / 2;\n}\n\n/**\n * Wrapping less than comparison for u16 values.\n * Based on shared_state.rs wrapping_lt implementation.\n */\nexport function wrappingLtU16(a: number, b: number): boolean {\n\treturn a !== b && wrappingSub(b, a, U16_MAX) < U16_MAX / 2;\n}\n\n/**\n * Wrapping greater than or equal comparison for u16 values.\n */\nexport function wrappingGteU16(a: number, b: number): boolean {\n\treturn a === b || wrappingGtU16(a, b);\n}\n\n/**\n * Wrapping less than or equal comparison for u16 values.\n */\nexport function wrappingLteU16(a: number, b: number): boolean {\n\treturn a === b || wrappingLtU16(a, b);\n}\n\n/**\n * Performs wrapping addition for u16 values.\n */\nexport function wrappingAddU16(a: number, b: number): number {\n\treturn (a + b) % (U16_MAX + 1);\n}\n\n/**\n * Performs wrapping subtraction for u16 values.\n */\nexport function wrappingSubU16(a: number, b: number): number {\n\treturn wrappingSub(a, b, U16_MAX);\n}\n\n/**\n * Performs wrapping subtraction for unsigned integers.\n */\nfunction wrappingSub(a: number, b: number, max: number): number {\n\tconst result = a - b;\n\tif (result < 0) {\n\t\treturn result + max + 1;\n\t}\n\treturn result;\n}\n\nexport function arraysEqual(a: ArrayBuffer, b: ArrayBuffer): boolean {\n\tconst ua = new Uint8Array(a);\n\tconst ub = new Uint8Array(b);\n\tif (ua.length !== ub.length) return false;\n\tfor (let i = 0; i < ua.length; i++) {\n\t\tif (ua[i] !== ub[i]) return false;\n\t}\n\treturn true;\n}\n\n/**\n * Polyfill for Promise.withResolvers().\n *\n * This is specifically for Cloudflare Workers. Their implementation of Promise.withResolvers does not work correctly.\n */\nexport function promiseWithResolvers<T>(): {\n\tpromise: Promise<T>;\n\tresolve: (value: T | PromiseLike<T>) => void;\n\treject: (reason?: any) => void;\n} {\n\tlet resolve!: (value: T | PromiseLike<T>) => void;\n\tlet reject!: (reason?: any) => void;\n\tconst promise = new Promise<T>((res, rej) => {\n\t\tresolve = res;\n\t\treject = rej;\n\t});\n\treturn { promise, resolve, reject };\n}\n\nexport function idToStr(id: ArrayBuffer): string {\n\tconst bytes = new Uint8Array(id);\n\treturn Array.from(bytes)\n\t\t.map((byte) => byte.toString(16).padStart(2, \"0\"))\n\t\t.join(\"\");\n}\n\nexport function stringifyError(error: unknown): string {\n\tif (error instanceof Error) {\n\t\treturn `${error.name}: ${error.message}${error.stack ? `\\n${error.stack}` : \"\"}`;\n\t} else if (typeof error === \"string\") {\n\t\treturn error;\n\t} else if (typeof error === \"object\" && error !== null) {\n\t\ttry {\n\t\t\treturn `${JSON.stringify(error)}`;\n\t\t} catch {\n\t\t\treturn `[object ${error.constructor?.name || \"Object\"}]`;\n\t\t}\n\t} else {\n\t\treturn String(error);\n\t}\n}\n","import type * as protocol from \"@rivetkit/engine-runner-protocol\";\nimport { logger } from \"./log\";\nimport type { PendingRequest } from \"./tunnel\";\nimport { arraysEqual, idToStr, promiseWithResolvers } from \"./utils\";\nimport type { WebSocketTunnelAdapter } from \"./websocket-tunnel-adapter\";\n\nexport interface ActorConfig {\n\tname: string;\n\tkey: string | null;\n\tcreateTs: bigint;\n\tinput: Uint8Array | null;\n}\n\nexport class RunnerActor {\n\tactorId: string;\n\tgeneration: number;\n\tconfig: ActorConfig;\n\tpendingRequests: Array<{\n\t\tgatewayId: protocol.GatewayId;\n\t\trequestId: protocol.RequestId;\n\t\trequest: PendingRequest;\n\t}> = [];\n\twebSockets: Array<{\n\t\tgatewayId: protocol.GatewayId;\n\t\trequestId: protocol.RequestId;\n\t\tws: WebSocketTunnelAdapter;\n\t}> = [];\n\tactorStartPromise: ReturnType<typeof promiseWithResolvers<void>>;\n\n\tlastCommandIdx: bigint = -1n;\n\tnextEventIdx: bigint = 0n;\n\teventHistory: protocol.EventWrapper[] = [];\n\n\t/**\n\t * If restoreHibernatingRequests has been called. This is used to assert\n\t * that the caller is implemented correctly.\n\t **/\n\thibernationRestored: boolean = false;\n\n\tconstructor(\n\t\tactorId: string,\n\t\tgeneration: number,\n\t\tconfig: ActorConfig,\n\t\t/**\n\t\t * List of hibernating requests provided by the gateway on actor start.\n\t\t * This represents the WebSocket connections that the gateway knows about.\n\t\t **/\n\t\tpublic hibernatingRequests: readonly protocol.HibernatingRequest[],\n\t) {\n\t\tthis.actorId = actorId;\n\t\tthis.generation = generation;\n\t\tthis.config = config;\n\t\tthis.actorStartPromise = promiseWithResolvers();\n\t}\n\n\t// Pending request methods\n\tgetPendingRequest(\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t): PendingRequest | undefined {\n\t\treturn this.pendingRequests.find(\n\t\t\t(entry) =>\n\t\t\t\tarraysEqual(entry.gatewayId, gatewayId) &&\n\t\t\t\tarraysEqual(entry.requestId, requestId),\n\t\t)?.request;\n\t}\n\n\tcreatePendingRequest(\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t\tclientMessageIndex: number,\n\t) {\n\t\tconst exists =\n\t\t\tthis.getPendingRequest(gatewayId, requestId) !== undefined;\n\t\tif (exists) {\n\t\t\tlogger()?.warn({\n\t\t\t\tmsg: \"attempting to set pending request twice, replacing existing\",\n\t\t\t\tgatewayId: idToStr(gatewayId),\n\t\t\t\trequestId: idToStr(requestId),\n\t\t\t});\n\t\t\t// Delete existing pending request before adding the new one\n\t\t\tthis.deletePendingRequest(gatewayId, requestId);\n\t\t}\n\t\tthis.pendingRequests.push({\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t\trequest: {\n\t\t\t\tresolve: () => { },\n\t\t\t\treject: () => { },\n\t\t\t\tactorId: this.actorId,\n\t\t\t\tgatewayId: gatewayId,\n\t\t\t\trequestId: requestId,\n\t\t\t\tclientMessageIndex,\n\t\t\t},\n\t\t});\n\t\tlogger()?.debug({\n\t\t\tmsg: \"added pending request\",\n\t\t\tgatewayId: idToStr(gatewayId),\n\t\t\trequestId: idToStr(requestId),\n\t\t\tlength: this.pendingRequests.length,\n\t\t});\n\t}\n\n\tcreatePendingRequestWithStreamController(\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t\tclientMessageIndex: number,\n\t\tstreamController: ReadableStreamDefaultController<Uint8Array>,\n\t) {\n\t\tconst exists =\n\t\t\tthis.getPendingRequest(gatewayId, requestId) !== undefined;\n\t\tif (exists) {\n\t\t\tlogger()?.warn({\n\t\t\t\tmsg: \"attempting to set pending request twice, replacing existing\",\n\t\t\t\tgatewayId: idToStr(gatewayId),\n\t\t\t\trequestId: idToStr(requestId),\n\t\t\t});\n\t\t\t// Delete existing pending request before adding the new one\n\t\t\tthis.deletePendingRequest(gatewayId, requestId);\n\t\t}\n\t\tthis.pendingRequests.push({\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t\trequest: {\n\t\t\t\tresolve: () => { },\n\t\t\t\treject: () => { },\n\t\t\t\tactorId: this.actorId,\n\t\t\t\tgatewayId: gatewayId,\n\t\t\t\trequestId: requestId,\n\t\t\t\tclientMessageIndex,\n\t\t\t\tstreamController,\n\t\t\t},\n\t\t});\n\t\tlogger()?.debug({\n\t\t\tmsg: \"added pending request with stream controller\",\n\t\t\tgatewayId: idToStr(gatewayId),\n\t\t\trequestId: idToStr(requestId),\n\t\t\tlength: this.pendingRequests.length,\n\t\t});\n\t}\n\n\tdeletePendingRequest(\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t) {\n\t\tconst index = this.pendingRequests.findIndex(\n\t\t\t(entry) =>\n\t\t\t\tarraysEqual(entry.gatewayId, gatewayId) &&\n\t\t\t\tarraysEqual(entry.requestId, requestId),\n\t\t);\n\t\tif (index !== -1) {\n\t\t\tthis.pendingRequests.splice(index, 1);\n\t\t\tlogger()?.debug({\n\t\t\t\tmsg: \"removed pending request\",\n\t\t\t\tgatewayId: idToStr(gatewayId),\n\t\t\t\trequestId: idToStr(requestId),\n\t\t\t\tlength: this.pendingRequests.length,\n\t\t\t});\n\t\t}\n\t}\n\n\t// WebSocket methods\n\tgetWebSocket(\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t): WebSocketTunnelAdapter | undefined {\n\t\treturn this.webSockets.find(\n\t\t\t(entry) =>\n\t\t\t\tarraysEqual(entry.gatewayId, gatewayId) &&\n\t\t\t\tarraysEqual(entry.requestId, requestId),\n\t\t)?.ws;\n\t}\n\n\tsetWebSocket(\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t\tws: WebSocketTunnelAdapter,\n\t) {\n\t\tconst exists = this.getWebSocket(gatewayId, requestId) !== undefined;\n\t\tif (exists) {\n\t\t\tlogger()?.warn({ msg: \"attempting to set websocket twice\" });\n\t\t\treturn;\n\t\t}\n\t\tthis.webSockets.push({ gatewayId, requestId, ws });\n\t}\n\n\tdeleteWebSocket(\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t) {\n\t\tconst index = this.webSockets.findIndex(\n\t\t\t(entry) =>\n\t\t\t\tarraysEqual(entry.gatewayId, gatewayId) &&\n\t\t\t\tarraysEqual(entry.requestId, requestId),\n\t\t);\n\t\tif (index !== -1) {\n\t\t\tthis.webSockets.splice(index, 1);\n\t\t}\n\t}\n\n\thandleAckEvents(lastEventIdx: bigint) {\n\t\tthis.eventHistory = this.eventHistory.filter(\n\t\t\t(event) => event.checkpoint.index > lastEventIdx,\n\t\t);\n\t}\n\n\trecordEvent(eventWrapper: protocol.EventWrapper) {\n\t\tthis.eventHistory.push(eventWrapper);\n\t}\n}\n","import type * as protocol from \"@rivetkit/engine-runner-protocol\";\nimport { idToStr } from \"./utils\";\n\n/**\n * Helper function to stringify ArrayBuffer for logging\n */\nfunction stringifyArrayBuffer(buffer: ArrayBuffer): string {\n\treturn `ArrayBuffer(${buffer.byteLength})`;\n}\n\n/**\n * Helper function to stringify bigint for logging\n */\nfunction stringifyBigInt(value: bigint): string {\n\treturn `${value}n`;\n}\n\n/**\n * Helper function to stringify Map for logging\n */\nfunction stringifyMap(map: ReadonlyMap<string, string>): string {\n\tconst entries = Array.from(map.entries())\n\t\t.map(([k, v]) => `\"${k}\": \"${v}\"`)\n\t\t.join(\", \");\n\treturn `Map(${map.size}){${entries}}`;\n}\n\n/**\n * Helper function to stringify MessageId for logging\n */\nfunction stringifyMessageId(messageId: protocol.MessageId): string {\n\treturn `MessageId{gatewayId: ${idToStr(messageId.gatewayId)}, requestId: ${idToStr(messageId.requestId)}, messageIndex: ${messageId.messageIndex}}`;\n}\n\n/**\n * Stringify ToServerTunnelMessageKind for logging\n * Handles ArrayBuffers, BigInts, and Maps that can't be JSON.stringified\n */\nexport function stringifyToServerTunnelMessageKind(\n\tkind: protocol.ToServerTunnelMessageKind,\n): string {\n\tswitch (kind.tag) {\n\t\tcase \"ToServerResponseStart\": {\n\t\t\tconst { status, headers, body, stream } = kind.val;\n\t\t\tconst bodyStr = body === null ? \"null\" : stringifyArrayBuffer(body);\n\t\t\treturn `ToServerResponseStart{status: ${status}, headers: ${stringifyMap(headers)}, body: ${bodyStr}, stream: ${stream}}`;\n\t\t}\n\t\tcase \"ToServerResponseChunk\": {\n\t\t\tconst { body, finish } = kind.val;\n\t\t\treturn `ToServerResponseChunk{body: ${stringifyArrayBuffer(body)}, finish: ${finish}}`;\n\t\t}\n\t\tcase \"ToServerResponseAbort\":\n\t\t\treturn \"ToServerResponseAbort\";\n\t\tcase \"ToServerWebSocketOpen\": {\n\t\t\tconst { canHibernate } = kind.val;\n\t\t\treturn `ToServerWebSocketOpen{canHibernate: ${canHibernate}}`;\n\t\t}\n\t\tcase \"ToServerWebSocketMessage\": {\n\t\t\tconst { data, binary } = kind.val;\n\t\t\treturn `ToServerWebSocketMessage{data: ${stringifyArrayBuffer(data)}, binary: ${binary}}`;\n\t\t}\n\t\tcase \"ToServerWebSocketMessageAck\": {\n\t\t\tconst { index } = kind.val;\n\t\t\treturn `ToServerWebSocketMessageAck{index: ${index}}`;\n\t\t}\n\t\tcase \"ToServerWebSocketClose\": {\n\t\t\tconst { code, reason, hibernate } = kind.val;\n\t\t\tconst codeStr = code === null ? \"null\" : code.toString();\n\t\t\tconst reasonStr = reason === null ? \"null\" : `\"${reason}\"`;\n\t\t\treturn `ToServerWebSocketClose{code: ${codeStr}, reason: ${reasonStr}, hibernate: ${hibernate}}`;\n\t\t}\n\t}\n}\n\n/**\n * Stringify ToClientTunnelMessageKind for logging\n * Handles ArrayBuffers, BigInts, and Maps that can't be JSON.stringified\n */\nexport function stringifyToClientTunnelMessageKind(\n\tkind: protocol.ToClientTunnelMessageKind,\n): string {\n\tswitch (kind.tag) {\n\t\tcase \"ToClientRequestStart\": {\n\t\t\tconst { actorId, method, path, headers, body, stream } = kind.val;\n\t\t\tconst bodyStr = body === null ? \"null\" : stringifyArrayBuffer(body);\n\t\t\treturn `ToClientRequestStart{actorId: \"${actorId}\", method: \"${method}\", path: \"${path}\", headers: ${stringifyMap(headers)}, body: ${bodyStr}, stream: ${stream}}`;\n\t\t}\n\t\tcase \"ToClientRequestChunk\": {\n\t\t\tconst { body, finish } = kind.val;\n\t\t\treturn `ToClientRequestChunk{body: ${stringifyArrayBuffer(body)}, finish: ${finish}}`;\n\t\t}\n\t\tcase \"ToClientRequestAbort\":\n\t\t\treturn \"ToClientRequestAbort\";\n\t\tcase \"ToClientWebSocketOpen\": {\n\t\t\tconst { actorId, path, headers } = kind.val;\n\t\t\treturn `ToClientWebSocketOpen{actorId: \"${actorId}\", path: \"${path}\", headers: ${stringifyMap(headers)}}`;\n\t\t}\n\t\tcase \"ToClientWebSocketMessage\": {\n\t\t\tconst { data, binary } = kind.val;\n\t\t\treturn `ToClientWebSocketMessage{data: ${stringifyArrayBuffer(data)}, binary: ${binary}}`;\n\t\t}\n\t\tcase \"ToClientWebSocketClose\": {\n\t\t\tconst { code, reason } = kind.val;\n\t\t\tconst codeStr = code === null ? \"null\" : code.toString();\n\t\t\tconst reasonStr = reason === null ? \"null\" : `\"${reason}\"`;\n\t\t\treturn `ToClientWebSocketClose{code: ${codeStr}, reason: ${reasonStr}}`;\n\t\t}\n\t}\n}\n\n/**\n * Stringify Command for logging\n * Handles ArrayBuffers, BigInts, and Maps that can't be JSON.stringified\n */\nexport function stringifyCommand(command: protocol.Command): string {\n\tswitch (command.tag) {\n\t\tcase \"CommandStartActor\": {\n\t\t\tconst { config, hibernatingRequests } =\n\t\t\t\tcommand.val;\n\t\t\tconst keyStr = config.key === null ? \"null\" : `\"${config.key}\"`;\n\t\t\tconst inputStr =\n\t\t\t\tconfig.input === null\n\t\t\t\t\t? \"null\"\n\t\t\t\t\t: stringifyArrayBuffer(config.input);\n\t\t\tconst hibernatingRequestsStr =\n\t\t\t\thibernatingRequests.length > 0\n\t\t\t\t\t? `[${hibernatingRequests.map((hr) => `{gatewayId: ${idToStr(hr.gatewayId)}, requestId: ${idToStr(hr.requestId)}}`).join(\", \")}]`\n\t\t\t\t\t: \"[]\";\n\t\t\treturn `CommandStartActor{config: {name: \"${config.name}\", key: ${keyStr}, createTs: ${stringifyBigInt(config.createTs)}, input: ${inputStr}}, hibernatingRequests: ${hibernatingRequestsStr}}`;\n\t\t}\n\t\tcase \"CommandStopActor\": {\n\t\t\treturn `CommandStopActor`;\n\t\t}\n\t}\n}\n\n/**\n * Stringify CommandWrapper for logging\n * Handles ArrayBuffers, BigInts, and Maps that can't be JSON.stringified\n */\nexport function stringifyCommandWrapper(\n\twrapper: protocol.CommandWrapper,\n): string {\n\treturn `CommandWrapper{actorId: \"${wrapper.checkpoint.actorId}\", generation: \"${wrapper.checkpoint.generation}\", index: ${stringifyBigInt(wrapper.checkpoint.index)}, inner: ${stringifyCommand(wrapper.inner)}}`;\n}\n\n/**\n * Stringify Event for logging\n * Handles ArrayBuffers, BigInts, and Maps that can't be JSON.stringified\n */\nexport function stringifyEvent(event: protocol.Event): string {\n\tswitch (event.tag) {\n\t\tcase \"EventActorIntent\": {\n\t\t\tconst { intent } = event.val;\n\t\t\tconst intentStr =\n\t\t\t\tintent.tag === \"ActorIntentSleep\"\n\t\t\t\t\t? \"Sleep\"\n\t\t\t\t\t: intent.tag === \"ActorIntentStop\"\n\t\t\t\t\t\t? \"Stop\"\n\t\t\t\t\t\t: \"Unknown\";\n\t\t\treturn `EventActorIntent{intent: ${intentStr}}`;\n\t\t}\n\t\tcase \"EventActorStateUpdate\": {\n\t\t\tconst { state } = event.val;\n\t\t\tlet stateStr: string;\n\t\t\tif (state.tag === \"ActorStateRunning\") {\n\t\t\t\tstateStr = \"Running\";\n\t\t\t} else if (state.tag === \"ActorStateStopped\") {\n\t\t\t\tconst { code, message } = state.val;\n\t\t\t\tconst messageStr = message === null ? \"null\" : `\"${message}\"`;\n\t\t\t\tstateStr = `Stopped{code: ${code}, message: ${messageStr}}`;\n\t\t\t} else {\n\t\t\t\tstateStr = \"Unknown\";\n\t\t\t}\n\t\t\treturn `EventActorStateUpdate{state: ${stateStr}}`;\n\t\t}\n\t\tcase \"EventActorSetAlarm\": {\n\t\t\tconst { alarmTs } = event.val;\n\t\t\tconst alarmTsStr =\n\t\t\t\talarmTs === null ? \"null\" : stringifyBigInt(alarmTs);\n\t\t\treturn `EventActorSetAlarm{alarmTs: ${alarmTsStr}}`;\n\t\t}\n\t}\n}\n\n/**\n * Stringify EventWrapper for logging\n * Handles ArrayBuffers, BigInts, and Maps that can't be JSON.stringified\n */\nexport function stringifyEventWrapper(wrapper: protocol.EventWrapper): string {\n\treturn `EventWrapper{actorId: ${wrapper.checkpoint.actorId}, generation: \"${wrapper.checkpoint.generation}\", index: ${stringifyBigInt(wrapper.checkpoint.index)}, inner: ${stringifyEvent(wrapper.inner)}}`;\n}\n\n/**\n * Stringify ToServer for logging\n * Handles ArrayBuffers, BigInts, and Maps that can't be JSON.stringified\n */\nexport function stringifyToServer(message: protocol.ToServer): string {\n\tswitch (message.tag) {\n\t\tcase \"ToServerInit\": {\n\t\t\tconst {\n\t\t\t\tname,\n\t\t\t\tversion,\n\t\t\t\ttotalSlots,\n\t\t\t\tprepopulateActorNames,\n\t\t\t\tmetadata,\n\t\t\t} = message.val;\n\t\t\tconst prepopulateActorNamesStr =\n\t\t\t\tprepopulateActorNames === null\n\t\t\t\t\t? \"null\"\n\t\t\t\t\t: `Map(${prepopulateActorNames.size})`;\n\t\t\tconst metadataStr = metadata === null ? \"null\" : `\"${metadata}\"`;\n\t\t\treturn `ToServerInit{name: \"${name}\", version: ${version}, totalSlots: ${totalSlots}, prepopulateActorNames: ${prepopulateActorNamesStr}, metadata: ${metadataStr}}`;\n\t\t}\n\t\tcase \"ToServerEvents\": {\n\t\t\tconst events = message.val;\n\t\t\treturn `ToServerEvents{count: ${events.length}, events: [${events.map((e) => stringifyEventWrapper(e)).join(\", \")}]}`;\n\t\t}\n\t\tcase \"ToServerAckCommands\": {\n\t\t\tconst { lastCommandCheckpoints } = message.val;\n\t\t\tconst checkpointsStr =\n\t\t\t\tlastCommandCheckpoints.length > 0\n\t\t\t\t\t? `[${lastCommandCheckpoints.map((cp) => `{actorId: \"${cp.actorId}\", index: ${stringifyBigInt(cp.index)}}`).join(\", \")}]`\n\t\t\t\t\t: \"[]\";\n\t\t\treturn `ToServerAckCommands{lastCommandCheckpoints: ${checkpointsStr}}`;\n\t\t}\n\t\tcase \"ToServerStopping\":\n\t\t\treturn \"ToServerStopping\";\n\t\tcase \"ToServerPong\": {\n\t\t\tconst { ts } = message.val;\n\t\t\treturn `ToServerPong{ts: ${stringifyBigInt(ts)}}`;\n\t\t}\n\t\tcase \"ToServerKvRequest\": {\n\t\t\tconst { actorId, requestId, data } = message.val;\n\t\t\tconst dataStr = stringifyKvRequestData(data);\n\t\t\treturn `ToServerKvRequest{actorId: \"${actorId}\", requestId: ${requestId}, data: ${dataStr}}`;\n\t\t}\n\t\tcase \"ToServerTunnelMessage\": {\n\t\t\tconst { messageId, messageKind } = message.val;\n\t\t\treturn `ToServerTunnelMessage{messageId: ${stringifyMessageId(messageId)}, messageKind: ${stringifyToServerTunnelMessageKind(messageKind)}}`;\n\t\t}\n\t}\n}\n\n/**\n * Stringify ToClient for logging\n * Handles ArrayBuffers, BigInts, and Maps that can't be JSON.stringified\n */\nexport function stringifyToClient(message: protocol.ToClient): string {\n\tswitch (message.tag) {\n\t\tcase \"ToClientInit\": {\n\t\t\tconst { runnerId, metadata } = message.val;\n\t\t\tconst metadataStr = `{runnerLostThreshold: ${stringifyBigInt(metadata.runnerLostThreshold)}}`;\n\t\t\treturn `ToClientInit{runnerId: \"${runnerId}\", metadata: ${metadataStr}}`;\n\t\t}\n\t\tcase \"ToClientPing\":\n\t\t\tconst { ts } = message.val;\n\t\t\treturn `ToClientPing{ts: ${stringifyBigInt(ts)}}`;\n\t\tcase \"ToClientCommands\": {\n\t\t\tconst commands = message.val;\n\t\t\treturn `ToClientCommands{count: ${commands.length}, commands: [${commands.map((c) => stringifyCommandWrapper(c)).join(\", \")}]}`;\n\t\t}\n\t\tcase \"ToClientAckEvents\": {\n\t\t\tconst { lastEventCheckpoints } = message.val;\n\t\t\tconst checkpointsStr =\n\t\t\t\tlastEventCheckpoints.length > 0\n\t\t\t\t\t? `[${lastEventCheckpoints.map((cp) => `{actorId: \"${cp.actorId}\", index: ${stringifyBigInt(cp.index)}}`).join(\", \")}]`\n\t\t\t\t\t: \"[]\";\n\t\t\treturn `ToClientAckEvents{lastEventCheckpoints: ${checkpointsStr}}`;\n\t\t}\n\t\tcase \"ToClientKvResponse\": {\n\t\t\tconst { requestId, data } = message.val;\n\t\t\tconst dataStr = stringifyKvResponseData(data);\n\t\t\treturn `ToClientKvResponse{requestId: ${requestId}, data: ${dataStr}}`;\n\t\t}\n\t\tcase \"ToClientTunnelMessage\": {\n\t\t\tconst { messageId, messageKind } = message.val;\n\t\t\treturn `ToClientTunnelMessage{messageId: ${stringifyMessageId(messageId)}, messageKind: ${stringifyToClientTunnelMessageKind(messageKind)}}`;\n\t\t}\n\t}\n}\n\n/**\n * Stringify KvRequestData for logging\n */\nfunction stringifyKvRequestData(data: protocol.KvRequestData): string {\n\tswitch (data.tag) {\n\t\tcase \"KvGetRequest\": {\n\t\t\tconst { keys } = data.val;\n\t\t\treturn `KvGetRequest{keys: ${keys.length}}`;\n\t\t}\n\t\tcase \"KvListRequest\": {\n\t\t\tconst { query, reverse, limit } = data.val;\n\t\t\tconst reverseStr = reverse === null ? \"null\" : reverse.toString();\n\t\t\tconst limitStr = limit === null ? \"null\" : stringifyBigInt(limit);\n\t\t\treturn `KvListRequest{query: ${stringifyKvListQuery(query)}, reverse: ${reverseStr}, limit: ${limitStr}}`;\n\t\t}\n\t\tcase \"KvPutRequest\": {\n\t\t\tconst { keys, values } = data.val;\n\t\t\treturn `KvPutRequest{keys: ${keys.length}, values: ${values.length}}`;\n\t\t}\n\t\tcase \"KvDeleteRequest\": {\n\t\t\tconst { keys } = data.val;\n\t\t\treturn `KvDeleteRequest{keys: ${keys.length}}`;\n\t\t}\n\t\tcase \"KvDropRequest\":\n\t\t\treturn \"KvDropRequest\";\n\t}\n}\n\n/**\n * Stringify KvListQuery for logging\n */\nfunction stringifyKvListQuery(query: protocol.KvListQuery): string {\n\tswitch (query.tag) {\n\t\tcase \"KvListAllQuery\":\n\t\t\treturn \"KvListAllQuery\";\n\t\tcase \"KvListRangeQuery\": {\n\t\t\tconst { start, end, exclusive } = query.val;\n\t\t\treturn `KvListRangeQuery{start: ${stringifyArrayBuffer(start)}, end: ${stringifyArrayBuffer(end)}, exclusive: ${exclusive}}`;\n\t\t}\n\t\tcase \"KvListPrefixQuery\": {\n\t\t\tconst { key } = query.val;\n\t\t\treturn `KvListPrefixQuery{key: ${stringifyArrayBuffer(key)}}`;\n\t\t}\n\t}\n}\n\n/**\n * Stringify KvResponseData for logging\n */\nfunction stringifyKvResponseData(data: protocol.KvResponseData): string {\n\tswitch (data.tag) {\n\t\tcase \"KvErrorResponse\": {\n\t\t\tconst { message } = data.val;\n\t\t\treturn `KvErrorResponse{message: \"${message}\"}`;\n\t\t}\n\t\tcase \"KvGetResponse\": {\n\t\t\tconst { keys, values, metadata } = data.val;\n\t\t\treturn `KvGetResponse{keys: ${keys.length}, values: ${values.length}, metadata: ${metadata.length}}`;\n\t\t}\n\t\tcase \"KvListResponse\": {\n\t\t\tconst { keys, values, metadata } = data.val;\n\t\t\treturn `KvListResponse{keys: ${keys.length}, values: ${values.length}, metadata: ${metadata.length}}`;\n\t\t}\n\t\tcase \"KvPutResponse\":\n\t\t\treturn \"KvPutResponse\";\n\t\tcase \"KvDeleteResponse\":\n\t\t\treturn \"KvDeleteResponse\";\n\t\tcase \"KvDropResponse\":\n\t\t\treturn \"KvDropResponse\";\n\t}\n}\n","// WebSocket-like adapter for tunneled connections\n// Implements a subset of the WebSocket interface for compatibility with runner code\n\nimport type { Logger } from \"pino\";\nimport { logger } from \"./log\";\nimport type { Tunnel } from \"./tunnel\";\nimport { wrappingAddU16, wrappingLteU16, wrappingSubU16 } from \"./utils\";\n\nexport const HIBERNATABLE_SYMBOL = Symbol(\"hibernatable\");\n\nexport class WebSocketTunnelAdapter {\n\t// MARK: - WebSocket Compat Variables\n\t#readyState: number = 0; // CONNECTING\n\t#eventListeners: Map<string, Set<(event: any) => void>> = new Map();\n\t#onopen: ((this: any, ev: any) => any) | null = null;\n\t#onclose: ((this: any, ev: any) => any) | null = null;\n\t#onerror: ((this: any, ev: any) => any) | null = null;\n\t#onmessage: ((this: any, ev: any) => any) | null = null;\n\t#bufferedAmount = 0;\n\t#binaryType: \"nodebuffer\" | \"arraybuffer\" | \"blob\" = \"nodebuffer\";\n\t#extensions = \"\";\n\t#protocol = \"\";\n\t#url = \"\";\n\n\t// mARK: - Internal State\n\t#tunnel: Tunnel;\n\t#actorId: string;\n\t#requestId: string;\n\t#hibernatable: boolean;\n\t#serverMessageIndex: number;\n\n\tget [HIBERNATABLE_SYMBOL](): boolean {\n\t\treturn this.#hibernatable;\n\t}\n\n\t/**\n\t * Called when sending a message from this WebSocket.\n\t *\n\t * Used to send a tunnel message from Tunnel.\n\t */\n\t#sendCallback: (data: ArrayBuffer | string, isBinary: boolean) => void;\n\n\t/**\n\t * Called when closing this WebSocket.\n\t *\n\t * Used to send a tunnel message from Tunnel\n\t */\n\t#closeCallback: (\n\t\tcode?: number,\n\t\treason?: string,\n\t\thibernate?: boolean,\n\t) => void;\n\n\tget #log(): Logger | undefined {\n\t\treturn this.#tunnel.log;\n\t}\n\n\tconstructor(\n\t\ttunnel: Tunnel,\n\t\tactorId: string,\n\t\trequestId: string,\n\t\tserverMessageIndex: number,\n\t\thibernatable: boolean,\n\t\tisRestoringHibernatable: boolean,\n\t\t/** @experimental */\n\t\tpublic readonly request: Request,\n\t\tsendCallback: (data: ArrayBuffer | string, isBinary: boolean) => void,\n\t\tcloseCallback: (code?: number, reason?: string) => void,\n\t) {\n\t\tthis.#tunnel = tunnel;\n\t\tthis.#actorId = actorId;\n\t\tthis.#requestId = requestId;\n\t\tthis.#hibernatable = hibernatable;\n\t\tthis.#serverMessageIndex = serverMessageIndex;\n\t\tthis.#sendCallback = sendCallback;\n\t\tthis.#closeCallback = closeCallback;\n\n\t\t// For restored WebSockets, immediately set to OPEN state\n\t\tif (isRestoringHibernatable) {\n\t\t\tthis.#log?.debug({\n\t\t\t\tmsg: \"setting WebSocket to OPEN state for restored connection\",\n\t\t\t\tactorId: this.#actorId,\n\t\t\t\trequestId: this.#requestId,\n\t\t\t\thibernatable: this.#hibernatable,\n\t\t\t});\n\t\t\tthis.#readyState = 1; // OPEN\n\t\t}\n\t}\n\n\t// MARK: - Lifecycle\n\tget bufferedAmount(): number {\n\t\treturn this.#bufferedAmount;\n\t}\n\n\t_handleOpen(requestId: ArrayBuffer): void {\n\t\tif (this.#readyState !== 0) {\n\t\t\t// CONNECTING\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#readyState = 1; // OPEN\n\n\t\tconst event = {\n\t\t\ttype: \"open\",\n\t\t\trivetRequestId: requestId,\n\t\t\ttarget: this,\n\t\t};\n\n\t\tthis.#fireEvent(\"open\", event);\n\t}\n\n\t_handleMessage(\n\t\trequestId: ArrayBuffer,\n\t\tdata: string | Uint8Array,\n\t\tserverMessageIndex: number,\n\t\tisBinary: boolean,\n\t): boolean {\n\t\tif (this.#readyState !== 1) {\n\t\t\tthis.#log?.warn({\n\t\t\t\tmsg: \"WebSocket message ignored - not in OPEN state\",\n\t\t\t\trequestId: this.#requestId,\n\t\t\t\tactorId: this.#actorId,\n\t\t\t\tcurrentReadyState: this.#readyState,\n\t\t\t\texpectedReadyState: 1,\n\t\t\t\tserverMessageIndex: serverMessageIndex,\n\t\t\t\thibernatable: this.#hibernatable,\n\t\t\t});\n\t\t\treturn true;\n\t\t}\n\n\t\t// Validate message index\n\t\tif (this.#hibernatable) {\n\t\t\tconst previousIndex = this.#serverMessageIndex;\n\n\t\t\t// Ignore duplicate old messages\n\t\t\t//\n\t\t\t// This should only happen if something goes wrong\n\t\t\t// between persisting the previous index and acking the\n\t\t\t// message index to the gateway. If the ack is never\n\t\t\t// received by the gateway (due to a crash or network\n\t\t\t// issue), the gateway will resend all messages from\n\t\t\t// the last ack on reconnect.\n\t\t\tif (wrappingLteU16(serverMessageIndex, previousIndex)) {\n\t\t\t\tthis.#log?.info({\n\t\t\t\t\tmsg: \"received duplicate hibernating websocket message, this indicates the actor failed to ack the message index before restarting\",\n\t\t\t\t\trequestId,\n\t\t\t\t\tactorId: this.#actorId,\n\t\t\t\t\tpreviousIndex,\n\t\t\t\t\texpectedIndex: wrappingAddU16(previousIndex, 1),\n\t\t\t\t\treceivedIndex: serverMessageIndex,\n\t\t\t\t});\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Close message if skipped message in sequence\n\t\t\t//\n\t\t\t// There is no scenario where this should ever happen\n\t\t\tconst expectedIndex = wrappingAddU16(previousIndex, 1);\n\t\t\tif (serverMessageIndex !== expectedIndex) {\n\t\t\t\tconst closeReason = \"ws.message_index_skip\";\n\n\t\t\t\tthis.#log?.warn({\n\t\t\t\t\tmsg: \"hibernatable websocket message index out of sequence, closing connection\",\n\t\t\t\t\trequestId,\n\t\t\t\t\tactorId: this.#actorId,\n\t\t\t\t\tpreviousIndex,\n\t\t\t\t\texpectedIndex,\n\t\t\t\t\treceivedIndex: serverMessageIndex,\n\t\t\t\t\tcloseReason,\n\t\t\t\t\tgap: wrappingSubU16(\n\t\t\t\t\t\twrappingSubU16(serverMessageIndex, previousIndex),\n\t\t\t\t\t\t1,\n\t\t\t\t\t),\n\t\t\t\t});\n\n\t\t\t\t// Close the WebSocket and skip processing\n\t\t\t\tthis.close(1008, closeReason);\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Update to the next index\n\t\t\tthis.#serverMessageIndex = serverMessageIndex;\n\t\t}\n\n\t\t// Dispatch event\n\t\tlet messageData: any;\n\t\tif (isBinary) {\n\t\t\t// Handle binary data based on binaryType\n\t\t\tif (this.#binaryType === \"nodebuffer\") {\n\t\t\t\t// Convert to Buffer for Node.js compatibility\n\t\t\t\tmessageData = Buffer.from(data as Uint8Array);\n\t\t\t} else if (this.#binaryType === \"arraybuffer\") {\n\t\t\t\t// Convert to ArrayBuffer\n\t\t\t\tif (data instanceof Uint8Array) {\n\t\t\t\t\tmessageData = data.buffer.slice(\n\t\t\t\t\t\tdata.byteOffset,\n\t\t\t\t\t\tdata.byteOffset + data.byteLength,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tmessageData = data;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Blob type - not commonly used in Node.js\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Blob binaryType not supported in tunnel adapter\",\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\tmessageData = data;\n\t\t}\n\n\t\tconst event = {\n\t\t\ttype: \"message\",\n\t\t\tdata: messageData,\n\t\t\trivetRequestId: requestId,\n\t\t\trivetMessageIndex: serverMessageIndex,\n\t\t\ttarget: this,\n\t\t};\n\n\t\tthis.#fireEvent(\"message\", event);\n\n\t\treturn false;\n\t}\n\n\t_handleClose(\n\t\t_requestId: ArrayBuffer,\n\t\tcode?: number,\n\t\treason?: string,\n\t): void {\n\t\tthis.#closeInner(code, reason, true);\n\t}\n\n\t_handleError(error: Error): void {\n\t\tconst event = {\n\t\t\ttype: \"error\",\n\t\t\ttarget: this,\n\t\t\terror,\n\t\t};\n\n\t\tthis.#fireEvent(\"error\", event);\n\t}\n\n\t_closeWithoutCallback(code?: number, reason?: string): void {\n\t\tthis.#closeInner(code, reason, false);\n\t}\n\n\t#fireEvent(type: string, event: any): void {\n\t\t// Call all registered event listeners\n\t\tconst listeners = this.#eventListeners.get(type);\n\n\t\tif (listeners && listeners.size > 0) {\n\t\t\tfor (const listener of listeners) {\n\t\t\t\ttry {\n\t\t\t\t\tlistener.call(this, event);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlogger()?.error({\n\t\t\t\t\t\tmsg: \"error in websocket event listener\",\n\t\t\t\t\t\terror,\n\t\t\t\t\t\ttype,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the onX property if set\n\t\tswitch (type) {\n\t\t\tcase \"open\":\n\t\t\t\tif (this.#onopen) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.#onopen.call(this, event);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tlogger()?.error({\n\t\t\t\t\t\t\tmsg: \"error in onopen handler\",\n\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"close\":\n\t\t\t\tif (this.#onclose) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.#onclose.call(this, event);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tlogger()?.error({\n\t\t\t\t\t\t\tmsg: \"error in onclose handler\",\n\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"error\":\n\t\t\t\tif (this.#onerror) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.#onerror.call(this, event);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tlogger()?.error({\n\t\t\t\t\t\t\tmsg: \"error in onerror handler\",\n\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"message\":\n\t\t\t\tif (this.#onmessage) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.#onmessage.call(this, event);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tlogger()?.error({\n\t\t\t\t\t\t\tmsg: \"error in onmessage handler\",\n\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t#closeInner(\n\t\tcode: number | undefined,\n\t\treason: string | undefined,\n\t\tcallback: boolean,\n\t): void {\n\t\tif (\n\t\t\tthis.#readyState === 2 || // CLOSING\n\t\t\tthis.#readyState === 3 // CLOSED\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#readyState = 2; // CLOSING\n\n\t\t// Send close through tunnel\n\t\tif (callback) {\n\t\t\tthis.#closeCallback(code, reason);\n\t\t}\n\n\t\t// Update state and fire event\n\t\tthis.#readyState = 3; // CLOSED\n\n\t\tconst closeEvent = {\n\t\t\twasClean: true,\n\t\t\tcode: code || 1000,\n\t\t\treason: reason || \"\",\n\t\t\ttype: \"close\",\n\t\t\ttarget: this,\n\t\t};\n\n\t\tthis.#fireEvent(\"close\", closeEvent);\n\t}\n\n\t// MARK: - WebSocket Compatible API\n\tget readyState(): number {\n\t\treturn this.#readyState;\n\t}\n\n\tget binaryType(): string {\n\t\treturn this.#binaryType;\n\t}\n\n\tset binaryType(value: string) {\n\t\tif (\n\t\t\tvalue === \"nodebuffer\" ||\n\t\t\tvalue === \"arraybuffer\" ||\n\t\t\tvalue === \"blob\"\n\t\t) {\n\t\t\tthis.#binaryType = value;\n\t\t}\n\t}\n\n\tget extensions(): string {\n\t\treturn this.#extensions;\n\t}\n\n\tget protocol(): string {\n\t\treturn this.#protocol;\n\t}\n\n\tget url(): string {\n\t\treturn this.#url;\n\t}\n\n\tget onopen(): ((this: any, ev: any) => any) | null {\n\t\treturn this.#onopen;\n\t}\n\n\tset onopen(value: ((this: any, ev: any) => any) | null) {\n\t\tthis.#onopen = value;\n\t}\n\n\tget onclose(): ((this: any, ev: any) => any) | null {\n\t\treturn this.#onclose;\n\t}\n\n\tset onclose(value: ((this: any, ev: any) => any) | null) {\n\t\tthis.#onclose = value;\n\t}\n\n\tget onerror(): ((this: any, ev: any) => any) | null {\n\t\treturn this.#onerror;\n\t}\n\n\tset onerror(value: ((this: any, ev: any) => any) | null) {\n\t\tthis.#onerror = value;\n\t}\n\n\tget onmessage(): ((this: any, ev: any) => any) | null {\n\t\treturn this.#onmessage;\n\t}\n\n\tset onmessage(value: ((this: any, ev: any) => any) | null) {\n\t\tthis.#onmessage = value;\n\t}\n\n\tsend(data: string | ArrayBuffer | ArrayBufferView | Blob | Buffer): void {\n\t\t// Handle different ready states\n\t\tif (this.#readyState === 0) {\n\t\t\t// CONNECTING\n\t\t\tthrow new DOMException(\n\t\t\t\t\"WebSocket is still in CONNECTING state\",\n\t\t\t\t\"InvalidStateError\",\n\t\t\t);\n\t\t}\n\n\t\tif (this.#readyState === 2 || this.#readyState === 3) {\n\t\t\t// CLOSING or CLOSED - silently ignore\n\t\t\treturn;\n\t\t}\n\n\t\tlet isBinary = false;\n\t\tlet messageData: string | ArrayBuffer;\n\n\t\tif (typeof data === \"string\") {\n\t\t\tmessageData = data;\n\t\t} else if (data instanceof ArrayBuffer) {\n\t\t\tisBinary = true;\n\t\t\tmessageData = data;\n\t\t} else if (ArrayBuffer.isView(data)) {\n\t\t\tisBinary = true;\n\t\t\t// Convert ArrayBufferView to ArrayBuffer\n\t\t\tconst view = data as ArrayBufferView;\n\t\t\t// Check if it's a SharedArrayBuffer\n\t\t\tif (view.buffer instanceof SharedArrayBuffer) {\n\t\t\t\t// Copy SharedArrayBuffer to regular ArrayBuffer\n\t\t\t\tconst bytes = new Uint8Array(\n\t\t\t\t\tview.buffer,\n\t\t\t\t\tview.byteOffset,\n\t\t\t\t\tview.byteLength,\n\t\t\t\t);\n\t\t\t\tmessageData = bytes.buffer.slice(\n\t\t\t\t\tbytes.byteOffset,\n\t\t\t\t\tbytes.byteOffset + bytes.byteLength,\n\t\t\t\t) as unknown as ArrayBuffer;\n\t\t\t} else {\n\t\t\t\tmessageData = view.buffer.slice(\n\t\t\t\t\tview.byteOffset,\n\t\t\t\t\tview.byteOffset + view.byteLength,\n\t\t\t\t) as ArrayBuffer;\n\t\t\t}\n\t\t} else if (data instanceof Blob) {\n\t\t\tthrow new Error(\"Blob sending not implemented in tunnel adapter\");\n\t\t} else if (typeof Buffer !== \"undefined\" && Buffer.isBuffer(data)) {\n\t\t\tisBinary = true;\n\t\t\t// Convert Buffer to ArrayBuffer\n\t\t\tconst buf = data as Buffer;\n\t\t\t// Check if it's a SharedArrayBuffer\n\t\t\tif (buf.buffer instanceof SharedArrayBuffer) {\n\t\t\t\t// Copy SharedArrayBuffer to regular ArrayBuffer\n\t\t\t\tconst bytes = new Uint8Array(\n\t\t\t\t\tbuf.buffer,\n\t\t\t\t\tbuf.byteOffset,\n\t\t\t\t\tbuf.byteLength,\n\t\t\t\t);\n\t\t\t\tmessageData = bytes.buffer.slice(\n\t\t\t\t\tbytes.byteOffset,\n\t\t\t\t\tbytes.byteOffset + bytes.byteLength,\n\t\t\t\t) as unknown as ArrayBuffer;\n\t\t\t} else {\n\t\t\t\tmessageData = buf.buffer.slice(\n\t\t\t\t\tbuf.byteOffset,\n\t\t\t\t\tbuf.byteOffset + buf.byteLength,\n\t\t\t\t) as ArrayBuffer;\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new Error(\"Invalid data type\");\n\t\t}\n\n\t\t// Send through tunnel\n\t\tthis.#sendCallback(messageData, isBinary);\n\t}\n\n\tclose(code?: number, reason?: string): void {\n\t\tthis.#closeInner(code, reason, true);\n\t}\n\n\taddEventListener(\n\t\ttype: string,\n\t\tlistener: (event: any) => void,\n\t\toptions?: boolean | any,\n\t): void {\n\t\tif (typeof listener === \"function\") {\n\t\t\tlet listeners = this.#eventListeners.get(type);\n\t\t\tif (!listeners) {\n\t\t\t\tlisteners = new Set();\n\t\t\t\tthis.#eventListeners.set(type, listeners);\n\t\t\t}\n\t\t\tlisteners.add(listener);\n\t\t}\n\t}\n\n\tremoveEventListener(\n\t\ttype: string,\n\t\tlistener: (event: any) => void,\n\t\toptions?: boolean | any,\n\t): void {\n\t\tif (typeof listener === \"function\") {\n\t\t\tconst listeners = this.#eventListeners.get(type);\n\t\t\tif (listeners) {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t}\n\t\t}\n\t}\n\n\tdispatchEvent(event: any): boolean {\n\t\t// TODO:\n\t\treturn true;\n\t}\n\n\tstatic readonly CONNECTING = 0;\n\tstatic readonly OPEN = 1;\n\tstatic readonly CLOSING = 2;\n\tstatic readonly CLOSED = 3;\n\n\treadonly CONNECTING = 0;\n\treadonly OPEN = 1;\n\treadonly CLOSING = 2;\n\treadonly CLOSED = 3;\n\n\t// Additional methods for compatibility\n\tping(data?: any, mask?: boolean, cb?: (err: Error) => void): void {\n\t\t// Not implemented for tunnel - could be added if needed\n\t\tif (cb) cb(new Error(\"Ping not supported in tunnel adapter\"));\n\t}\n\n\tpong(data?: any, mask?: boolean, cb?: (err: Error) => void): void {\n\t\t// Not implemented for tunnel - could be added if needed\n\t\tif (cb) cb(new Error(\"Pong not supported in tunnel adapter\"));\n\t}\n\n\t/** @experimental */\n\tterminate(): void {\n\t\t// Immediate close without close frame\n\t\tthis.#readyState = 3; // CLOSED\n\t\tthis.#closeCallback(1006, \"Abnormal Closure\");\n\n\t\tconst event = {\n\t\t\twasClean: false,\n\t\t\tcode: 1006,\n\t\t\treason: \"Abnormal Closure\",\n\t\t\ttype: \"close\",\n\t\t\ttarget: this,\n\t\t};\n\n\t\tthis.#fireEvent(\"close\", event);\n\t}\n}\n","import type * as protocol from \"@rivetkit/engine-runner-protocol\";\nimport type {\n\tGatewayId,\n\tMessageId,\n\tRequestId,\n} from \"@rivetkit/engine-runner-protocol\";\nimport type { Logger } from \"pino\";\nimport {\n\tparse as uuidparse,\n\tstringify as uuidstringify,\n\tv4 as uuidv4,\n} from \"uuid\";\nimport { RunnerShutdownError, type Runner, type RunnerActor } from \"./mod\";\nimport {\n\tstringifyToClientTunnelMessageKind,\n\tstringifyToServerTunnelMessageKind,\n} from \"./stringify\";\nimport { arraysEqual, idToStr, stringifyError, unreachable } from \"./utils\";\nimport {\n\tHIBERNATABLE_SYMBOL,\n\tWebSocketTunnelAdapter,\n} from \"./websocket-tunnel-adapter\";\n\nexport interface PendingRequest {\n\tresolve: (response: Response) => void;\n\treject: (error: Error) => void;\n\tstreamController?: ReadableStreamDefaultController<Uint8Array>;\n\tactorId?: string;\n\tgatewayId?: GatewayId;\n\trequestId?: RequestId;\n\tclientMessageIndex: number;\n}\n\nexport interface HibernatingWebSocketMetadata {\n\tgatewayId: GatewayId;\n\trequestId: RequestId;\n\tclientMessageIndex: number;\n\tserverMessageIndex: number;\n\n\tpath: string;\n\theaders: Record<string, string>;\n}\n\nexport class Tunnel {\n\t#runner: Runner;\n\n\t/** Maps request IDs to actor IDs for lookup */\n\t#requestToActor: Array<{\n\t\tgatewayId: GatewayId;\n\t\trequestId: RequestId;\n\t\tactorId: string;\n\t}> = [];\n\n\t/** Buffer for messages when not connected */\n\t#bufferedMessages: Array<{\n\t\tgatewayId: GatewayId;\n\t\trequestId: RequestId;\n\t\tmessageKind: protocol.ToServerTunnelMessageKind;\n\t}> = [];\n\n\tget log(): Logger | undefined {\n\t\treturn this.#runner.log;\n\t}\n\n\tconstructor(runner: Runner) {\n\t\tthis.#runner = runner;\n\t}\n\n\tstart(): void {\n\t\t// No-op - kept for compatibility\n\t}\n\n\tresendBufferedEvents(): void {\n\t\tif (this.#bufferedMessages.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.log?.info({\n\t\t\tmsg: \"resending buffered tunnel messages\",\n\t\t\tcount: this.#bufferedMessages.length,\n\t\t});\n\n\t\tconst messages = this.#bufferedMessages;\n\t\tthis.#bufferedMessages = [];\n\n\t\tfor (const { gatewayId, requestId, messageKind } of messages) {\n\t\t\tthis.#sendMessage(gatewayId, requestId, messageKind);\n\t\t}\n\t}\n\n\tshutdown() {\n\t\t// NOTE: Pegboard WS already closed at this point, cannot send\n\t\t// anything. All teardown logic is handled by pegboard-runner.\n\n\t\t// Reject all pending requests and close all WebSockets for all actors\n\t\t// RunnerShutdownError will be explicitly ignored\n\t\tfor (const [_actorId, actor] of this.#runner.actors) {\n\t\t\t// Reject all pending requests for this actor\n\t\t\tfor (const entry of actor.pendingRequests) {\n\t\t\t\tentry.request.reject(new RunnerShutdownError());\n\t\t\t}\n\t\t\tactor.pendingRequests = [];\n\n\t\t\t// Close all WebSockets for this actor\n\t\t\t// The WebSocket close event with retry is automatically sent when the\n\t\t\t// runner WS closes, so we only need to notify the client that the WS\n\t\t\t// closed:\n\t\t\t// https://github.com/rivet-dev/rivet/blob/00d4f6a22da178a6f8115e5db50d96c6f8387c2e/engine/packages/pegboard-runner/src/lib.rs#L157\n\t\t\tfor (const entry of actor.webSockets) {\n\t\t\t\t// Only close non-hibernatable websockets to prevent sending\n\t\t\t\t// unnecessary close messages for websockets that will be hibernated\n\t\t\t\tif (!entry.ws[HIBERNATABLE_SYMBOL]) {\n\t\t\t\t\tentry.ws._closeWithoutCallback(1000, \"ws.tunnel_shutdown\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tactor.webSockets = [];\n\t\t}\n\n\t\t// Clear the request-to-actor mapping\n\t\tthis.#requestToActor = [];\n\t}\n\n\tasync restoreHibernatingRequests(\n\t\tactorId: string,\n\t\tmetaEntries: HibernatingWebSocketMetadata[],\n\t) {\n\t\tconst actor = this.#runner.getActor(actorId);\n\t\tif (!actor) {\n\t\t\tthrow new Error(\n\t\t\t\t`Actor ${actorId} not found for restoring hibernating requests`,\n\t\t\t);\n\t\t}\n\n\t\tif (actor.hibernationRestored) {\n\t\t\tthrow new Error(\n\t\t\t\t`Actor ${actorId} already restored hibernating requests`,\n\t\t\t);\n\t\t}\n\n\t\tthis.log?.debug({\n\t\t\tmsg: \"restoring hibernating requests\",\n\t\t\tactorId,\n\t\t\trequests: actor.hibernatingRequests.length,\n\t\t});\n\n\t\t// Track all background operations\n\t\tconst backgroundOperations: Promise<void>[] = [];\n\n\t\t// Process connected WebSockets\n\t\tlet connectedButNotLoadedCount = 0;\n\t\tlet restoredCount = 0;\n\t\tfor (const { gatewayId, requestId } of actor.hibernatingRequests) {\n\t\t\tconst requestIdStr = idToStr(requestId);\n\t\t\tconst meta = metaEntries.find(\n\t\t\t\t(entry) =>\n\t\t\t\t\tarraysEqual(entry.gatewayId, gatewayId) &&\n\t\t\t\t\tarraysEqual(entry.requestId, requestId),\n\t\t\t);\n\n\t\t\tif (!meta) {\n\t\t\t\t// Connected but not loaded (not persisted) - close it\n\t\t\t\t//\n\t\t\t\t// This may happen if the metadata was not successfully persisted\n\t\t\t\tthis.log?.warn({\n\t\t\t\t\tmsg: \"closing websocket that is not persisted\",\n\t\t\t\t\trequestId: requestIdStr,\n\t\t\t\t});\n\n\t\t\t\tthis.#sendMessage(gatewayId, requestId, {\n\t\t\t\t\ttag: \"ToServerWebSocketClose\",\n\t\t\t\t\tval: {\n\t\t\t\t\t\tcode: 1000,\n\t\t\t\t\t\treason: \"ws.meta_not_found_during_restore\",\n\t\t\t\t\t\thibernate: false,\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\tconnectedButNotLoadedCount++;\n\t\t\t} else {\n\t\t\t\t// Both connected and persisted - restore it\n\t\t\t\tconst request = buildRequestForWebSocket(\n\t\t\t\t\tmeta.path,\n\t\t\t\t\tmeta.headers,\n\t\t\t\t);\n\n\t\t\t\t// This will call `runner.config.websocket` under the hood to\n\t\t\t\t// attach the event listeners to the WebSocket.\n\t\t\t\t// Track this operation to ensure it completes\n\t\t\t\tconst restoreOperation = this.#createWebSocket(\n\t\t\t\t\tactorId,\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\trequestIdStr,\n\t\t\t\t\tmeta.serverMessageIndex,\n\t\t\t\t\ttrue,\n\t\t\t\t\ttrue,\n\t\t\t\t\trequest,\n\t\t\t\t\tmeta.path,\n\t\t\t\t\tmeta.headers,\n\t\t\t\t\tfalse,\n\t\t\t\t)\n\t\t\t\t\t.then(() => {\n\t\t\t\t\t\t// Create a PendingRequest entry to track the message index\n\t\t\t\t\t\tconst actor = this.#runner.getActor(actorId);\n\t\t\t\t\t\tif (actor) {\n\t\t\t\t\t\t\tactor.createPendingRequest(\n\t\t\t\t\t\t\t\tgatewayId,\n\t\t\t\t\t\t\t\trequestId,\n\t\t\t\t\t\t\t\tmeta.clientMessageIndex,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\t\tmsg: \"connection successfully restored\",\n\t\t\t\t\t\t\tactorId,\n\t\t\t\t\t\t\trequestId: requestIdStr,\n\t\t\t\t\t\t});\n\t\t\t\t\t})\n\t\t\t\t\t.catch((err) => {\n\t\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\t\tmsg: \"error creating websocket during restore\",\n\t\t\t\t\t\t\trequestId: requestIdStr,\n\t\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t// Close the WebSocket on error\n\t\t\t\t\t\tthis.#sendMessage(gatewayId, requestId, {\n\t\t\t\t\t\t\ttag: \"ToServerWebSocketClose\",\n\t\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\t\tcode: 1011,\n\t\t\t\t\t\t\t\treason: \"ws.restore_error\",\n\t\t\t\t\t\t\t\thibernate: false,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\tbackgroundOperations.push(restoreOperation);\n\t\t\t\trestoredCount++;\n\t\t\t}\n\t\t}\n\n\t\t// Process loaded but not connected (stale) - remove them\n\t\tlet loadedButNotConnectedCount = 0;\n\t\tfor (const meta of metaEntries) {\n\t\t\tconst requestIdStr = idToStr(meta.requestId);\n\t\t\tconst isConnected = actor.hibernatingRequests.some(\n\t\t\t\t(req) =>\n\t\t\t\t\tarraysEqual(req.gatewayId, meta.gatewayId) &&\n\t\t\t\t\tarraysEqual(req.requestId, meta.requestId),\n\t\t\t);\n\t\t\tif (!isConnected) {\n\t\t\t\tthis.log?.warn({\n\t\t\t\t\tmsg: \"removing stale persisted websocket\",\n\t\t\t\t\trequestId: requestIdStr,\n\t\t\t\t});\n\n\t\t\t\tconst request = buildRequestForWebSocket(\n\t\t\t\t\tmeta.path,\n\t\t\t\t\tmeta.headers,\n\t\t\t\t);\n\n\t\t\t\t// Create adapter to register user's event listeners.\n\t\t\t\t// Pass engineAlreadyClosed=true so close callback won't send tunnel message.\n\t\t\t\t// Track this operation to ensure it completes\n\t\t\t\tconst cleanupOperation = this.#createWebSocket(\n\t\t\t\t\tactorId,\n\t\t\t\t\tmeta.gatewayId,\n\t\t\t\t\tmeta.requestId,\n\t\t\t\t\trequestIdStr,\n\t\t\t\t\tmeta.serverMessageIndex,\n\t\t\t\t\ttrue,\n\t\t\t\t\ttrue,\n\t\t\t\t\trequest,\n\t\t\t\t\tmeta.path,\n\t\t\t\t\tmeta.headers,\n\t\t\t\t\ttrue,\n\t\t\t\t)\n\t\t\t\t\t.then((adapter) => {\n\t\t\t\t\t\t// Close the adapter normally - this will fire user's close event handler\n\t\t\t\t\t\t// (which should clean up persistence) and trigger the close callback\n\t\t\t\t\t\t// (which will clean up maps but skip sending tunnel message)\n\t\t\t\t\t\tadapter.close(1000, \"ws.stale_metadata\");\n\t\t\t\t\t})\n\t\t\t\t\t.catch((err) => {\n\t\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\t\tmsg: \"error creating stale websocket during restore\",\n\t\t\t\t\t\t\trequestId: requestIdStr,\n\t\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\tbackgroundOperations.push(cleanupOperation);\n\t\t\t\tloadedButNotConnectedCount++;\n\t\t\t}\n\t\t}\n\n\t\t// Wait for all background operations to complete before finishing\n\t\tawait Promise.allSettled(backgroundOperations);\n\n\t\t// Mark restoration as complete\n\t\tactor.hibernationRestored = true;\n\n\t\tthis.log?.info({\n\t\t\tmsg: \"restored hibernatable websockets\",\n\t\t\tactorId,\n\t\t\trestoredCount,\n\t\t\tconnectedButNotLoadedCount,\n\t\t\tloadedButNotConnectedCount,\n\t\t});\n\t}\n\n\t/**\n\t * Called from WebSocketOpen message and when restoring hibernatable WebSockets.\n\t *\n\t * engineAlreadyClosed will be true if this is only being called to trigger\n\t * the close callback and not to send a close message to the server. This\n\t * is used specifically to clean up zombie WebSocket connections.\n\t */\n\tasync #createWebSocket(\n\t\tactorId: string,\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t\trequestIdStr: string,\n\t\tserverMessageIndex: number,\n\t\tisHibernatable: boolean,\n\t\tisRestoringHibernatable: boolean,\n\t\trequest: Request,\n\t\tpath: string,\n\t\theaders: Record<string, string>,\n\t\tengineAlreadyClosed: boolean,\n\t): Promise<WebSocketTunnelAdapter> {\n\t\tthis.log?.debug({\n\t\t\tmsg: \"createWebSocket creating adapter\",\n\t\t\tactorId,\n\t\t\trequestIdStr,\n\t\t\tisHibernatable,\n\t\t\tpath,\n\t\t});\n\t\t// Create WebSocket adapter\n\t\tconst adapter = new WebSocketTunnelAdapter(\n\t\t\tthis,\n\t\t\tactorId,\n\t\t\trequestIdStr,\n\t\t\tserverMessageIndex,\n\t\t\tisHibernatable,\n\t\t\tisRestoringHibernatable,\n\t\t\trequest,\n\t\t\t(data: ArrayBuffer | string, isBinary: boolean) => {\n\t\t\t\t// Send message through tunnel\n\t\t\t\tconst dataBuffer =\n\t\t\t\t\ttypeof data === \"string\"\n\t\t\t\t\t\t? (new TextEncoder().encode(data).buffer as ArrayBuffer)\n\t\t\t\t\t\t: data;\n\n\t\t\t\tthis.#sendMessage(gatewayId, requestId, {\n\t\t\t\t\ttag: \"ToServerWebSocketMessage\",\n\t\t\t\t\tval: {\n\t\t\t\t\t\tdata: dataBuffer,\n\t\t\t\t\t\tbinary: isBinary,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t},\n\t\t\t(code?: number, reason?: string) => {\n\t\t\t\t// Send close through tunnel if engine doesn't already know it's closed\n\t\t\t\tif (!engineAlreadyClosed) {\n\t\t\t\t\tthis.#sendMessage(gatewayId, requestId, {\n\t\t\t\t\t\ttag: \"ToServerWebSocketClose\",\n\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\tcode: code || null,\n\t\t\t\t\t\t\treason: reason || null,\n\t\t\t\t\t\t\thibernate: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Clean up actor tracking\n\t\t\t\tconst actor = this.#runner.getActor(actorId);\n\t\t\t\tif (actor) {\n\t\t\t\t\tactor.deleteWebSocket(gatewayId, requestId);\n\t\t\t\t\tactor.deletePendingRequest(gatewayId, requestId);\n\t\t\t\t}\n\n\t\t\t\t// Clean up request-to-actor mapping\n\t\t\t\tthis.#removeRequestToActor(gatewayId, requestId);\n\t\t\t},\n\t\t);\n\n\t\t// Get actor and add websocket to it\n\t\tconst actor = this.#runner.getActor(actorId);\n\t\tif (!actor) {\n\t\t\tthrow new Error(`Actor ${actorId} not found`);\n\t\t}\n\n\t\tactor.setWebSocket(gatewayId, requestId, adapter);\n\t\tthis.addRequestToActor(gatewayId, requestId, actorId);\n\n\t\t// Call WebSocket handler. This handler will add event listeners\n\t\t// for `open`, etc.\n\t\tawait this.#runner.config.websocket(\n\t\t\tthis.#runner,\n\t\t\tactorId,\n\t\t\tadapter,\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t\trequest,\n\t\t\tpath,\n\t\t\theaders,\n\t\t\tisHibernatable,\n\t\t\tisRestoringHibernatable,\n\t\t);\n\n\t\treturn adapter;\n\t}\n\n\taddRequestToActor(\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t\tactorId: string,\n\t) {\n\t\tthis.#requestToActor.push({ gatewayId, requestId, actorId });\n\t}\n\n\t#removeRequestToActor(gatewayId: GatewayId, requestId: RequestId) {\n\t\tconst index = this.#requestToActor.findIndex(\n\t\t\t(entry) =>\n\t\t\t\tarraysEqual(entry.gatewayId, gatewayId) &&\n\t\t\t\tarraysEqual(entry.requestId, requestId),\n\t\t);\n\t\tif (index !== -1) {\n\t\t\tthis.#requestToActor.splice(index, 1);\n\t\t}\n\t}\n\n\tgetRequestActor(\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t): RunnerActor | undefined {\n\t\tconst entry = this.#requestToActor.find(\n\t\t\t(entry) =>\n\t\t\t\tarraysEqual(entry.gatewayId, gatewayId) &&\n\t\t\t\tarraysEqual(entry.requestId, requestId),\n\t\t);\n\n\t\tif (!entry) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"missing requestToActor entry\",\n\t\t\t\trequestId: idToStr(requestId),\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst actor = this.#runner.getActor(entry.actorId);\n\t\tif (!actor) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"missing actor for requestToActor lookup\",\n\t\t\t\trequestId: idToStr(requestId),\n\t\t\t\tactorId: entry.actorId,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn actor;\n\t}\n\n\tasync getAndWaitForRequestActor(\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t): Promise<RunnerActor | undefined> {\n\t\tconst actor = this.getRequestActor(gatewayId, requestId);\n\t\tif (!actor) return;\n\t\tawait actor.actorStartPromise.promise;\n\t\treturn actor;\n\t}\n\n\t#sendMessage(\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t\tmessageKind: protocol.ToServerTunnelMessageKind,\n\t) {\n\t\t// Buffer message if not connected\n\t\tif (!this.#runner.__webSocketReady()) {\n\t\t\tthis.log?.debug({\n\t\t\t\tmsg: \"buffering tunnel message, socket not connected to engine\",\n\t\t\t\trequestId: idToStr(requestId),\n\t\t\t\tmessage: stringifyToServerTunnelMessageKind(messageKind),\n\t\t\t});\n\t\t\tthis.#bufferedMessages.push({ gatewayId, requestId, messageKind });\n\t\t\treturn;\n\t\t}\n\n\t\t// Get or initialize message index for this request\n\t\t//\n\t\t// We don't have to wait for the actor to start since we're not calling\n\t\t// any callbacks on the actor\n\t\tconst gatewayIdStr = idToStr(gatewayId);\n\t\tconst requestIdStr = idToStr(requestId);\n\t\tconst actor = this.getRequestActor(gatewayId, requestId);\n\t\tif (!actor) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"cannot send tunnel message, actor not found\",\n\t\t\t\tgatewayId: gatewayIdStr,\n\t\t\t\trequestId: requestIdStr,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Get message index from pending request\n\t\tlet clientMessageIndex: number;\n\t\tconst pending = actor.getPendingRequest(gatewayId, requestId);\n\t\tif (pending) {\n\t\t\tclientMessageIndex = pending.clientMessageIndex;\n\t\t\tpending.clientMessageIndex++;\n\t\t} else {\n\t\t\t// No pending request\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"missing pending request for send message, defaulting to message index 0\",\n\t\t\t\tgatewayId: gatewayIdStr,\n\t\t\t\trequestId: requestIdStr,\n\t\t\t});\n\t\t\tclientMessageIndex = 0;\n\t\t}\n\n\t\t// Build message ID from gatewayId + requestId + messageIndex\n\t\tconst messageId: protocol.MessageId = {\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t\tmessageIndex: clientMessageIndex,\n\t\t};\n\t\tconst messageIdStr = `${idToStr(messageId.gatewayId)}-${idToStr(messageId.requestId)}-${messageId.messageIndex}`;\n\n\t\tthis.log?.debug({\n\t\t\tmsg: \"sending tunnel msg\",\n\t\t\tmessageId: messageIdStr,\n\t\t\tgatewayId: gatewayIdStr,\n\t\t\trequestId: requestIdStr,\n\t\t\tmessageIndex: clientMessageIndex,\n\t\t\tmessage: stringifyToServerTunnelMessageKind(messageKind),\n\t\t});\n\n\t\t// Send message\n\t\tconst message: protocol.ToServer = {\n\t\t\ttag: \"ToServerTunnelMessage\",\n\t\t\tval: {\n\t\t\t\tmessageId,\n\t\t\t\tmessageKind,\n\t\t\t},\n\t\t};\n\t\tthis.#runner.__sendToServer(message);\n\t}\n\n\tcloseActiveRequests(actor: RunnerActor) {\n\t\tconst actorId = actor.actorId;\n\n\t\t// Terminate all requests for this actor. This will no send a\n\t\t// ToServerResponse* message since the actor will no longer be loaded.\n\t\t// The gateway is responsible for closing the request.\n\t\tfor (const entry of actor.pendingRequests) {\n\t\t\tentry.request.reject(new Error(`Actor ${actorId} stopped`));\n\t\t\tif (entry.gatewayId && entry.requestId) {\n\t\t\t\tthis.#removeRequestToActor(entry.gatewayId, entry.requestId);\n\t\t\t}\n\t\t}\n\n\t\t// Close all WebSockets. Only send close event to non-HWS. The gateway is\n\t\t// responsible for hibernating HWS and closing regular WS.\n\t\tfor (const entry of actor.webSockets) {\n\t\t\tconst isHibernatable = entry.ws[HIBERNATABLE_SYMBOL];\n\t\t\tif (!isHibernatable) {\n\t\t\t\tentry.ws._closeWithoutCallback(1000, \"actor.stopped\");\n\t\t\t}\n\t\t\t// Note: request-to-actor mapping is cleaned up in the close callback\n\t\t}\n\t}\n\n\tasync #fetch(\n\t\tactorId: string,\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t\trequest: Request,\n\t): Promise<Response> {\n\t\t// Validate actor exists\n\t\tif (!this.#runner.hasActor(actorId)) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"ignoring request for unknown actor\",\n\t\t\t\tactorId,\n\t\t\t});\n\n\t\t\t// NOTE: This is a special response that will cause Guard to retry the request\n\t\t\t//\n\t\t\t// See should_retry_request_inner\n\t\t\t// https://github.com/rivet-dev/rivet/blob/222dae87e3efccaffa2b503de40ecf8afd4e31eb/engine/packages/guard-core/src/proxy_service.rs#L2458\n\t\t\treturn new Response(\"Actor not found\", {\n\t\t\t\tstatus: 503,\n\t\t\t\theaders: { \"x-rivet-error\": \"runner.actor_not_found\" },\n\t\t\t});\n\t\t}\n\n\t\tconst fetchHandler = this.#runner.config.fetch(\n\t\t\tthis.#runner,\n\t\t\tactorId,\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t\trequest,\n\t\t);\n\n\t\tif (!fetchHandler) {\n\t\t\treturn new Response(\"Not Implemented\", { status: 501 });\n\t\t}\n\n\t\treturn fetchHandler;\n\t}\n\n\tasync handleTunnelMessage(message: protocol.ToClientTunnelMessage) {\n\t\t// Parse the gateway ID, request ID, and message index from the messageId\n\t\tconst { gatewayId, requestId, messageIndex } = message.messageId;\n\n\t\tconst gatewayIdStr = idToStr(gatewayId);\n\t\tconst requestIdStr = idToStr(requestId);\n\t\tthis.log?.debug({\n\t\t\tmsg: \"receive tunnel msg\",\n\t\t\tgatewayId: gatewayIdStr,\n\t\t\trequestId: requestIdStr,\n\t\t\tmessageIndex: message.messageId.messageIndex,\n\t\t\tmessage: stringifyToClientTunnelMessageKind(message.messageKind),\n\t\t});\n\n\t\tswitch (message.messageKind.tag) {\n\t\t\tcase \"ToClientRequestStart\":\n\t\t\t\tawait this.#handleRequestStart(\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\tmessage.messageKind.val,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"ToClientRequestChunk\":\n\t\t\t\tawait this.#handleRequestChunk(\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\tmessage.messageKind.val,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"ToClientRequestAbort\":\n\t\t\t\tawait this.#handleRequestAbort(gatewayId, requestId);\n\t\t\t\tbreak;\n\t\t\tcase \"ToClientWebSocketOpen\":\n\t\t\t\tawait this.#handleWebSocketOpen(\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\tmessage.messageKind.val,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"ToClientWebSocketMessage\": {\n\t\t\t\tawait this.#handleWebSocketMessage(\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\tmessageIndex,\n\t\t\t\t\tmessage.messageKind.val,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"ToClientWebSocketClose\":\n\t\t\t\tawait this.#handleWebSocketClose(\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\tmessage.messageKind.val,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tunreachable(message.messageKind);\n\t\t}\n\t}\n\n\tasync #handleRequestStart(\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t\treq: protocol.ToClientRequestStart,\n\t) {\n\t\t// Track this request for the actor\n\t\tconst requestIdStr = idToStr(requestId);\n\t\tconst actor = await this.#runner.getAndWaitForActor(req.actorId);\n\t\tif (!actor) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"actor does not exist in handleRequestStart, request will leak\",\n\t\t\t\tactorId: req.actorId,\n\t\t\t\trequestId: requestIdStr,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Add to request-to-actor mapping\n\t\tthis.addRequestToActor(gatewayId, requestId, req.actorId);\n\n\t\ttry {\n\t\t\t// Convert headers map to Headers object\n\t\t\tconst headers = new Headers();\n\t\t\tfor (const [key, value] of req.headers) {\n\t\t\t\theaders.append(key, value);\n\t\t\t}\n\n\t\t\t// Create Request object\n\t\t\tconst request = new Request(`http://localhost${req.path}`, {\n\t\t\t\tmethod: req.method,\n\t\t\t\theaders,\n\t\t\t\tbody: req.body ? new Uint8Array(req.body) : undefined,\n\t\t\t});\n\n\t\t\t// Handle streaming request\n\t\t\tif (req.stream) {\n\t\t\t\t// Create a stream for the request body\n\t\t\t\tconst stream = new ReadableStream<Uint8Array>({\n\t\t\t\t\tstart: (controller) => {\n\t\t\t\t\t\t// Store controller for chunks\n\t\t\t\t\t\tconst existing = actor.getPendingRequest(\n\t\t\t\t\t\t\tgatewayId,\n\t\t\t\t\t\t\trequestId,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (existing) {\n\t\t\t\t\t\t\texisting.streamController = controller;\n\t\t\t\t\t\t\texisting.actorId = req.actorId;\n\t\t\t\t\t\t\texisting.gatewayId = gatewayId;\n\t\t\t\t\t\t\texisting.requestId = requestId;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tactor.createPendingRequestWithStreamController(\n\t\t\t\t\t\t\t\tgatewayId,\n\t\t\t\t\t\t\t\trequestId,\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tcontroller,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\t// Create request with streaming body\n\t\t\t\tconst streamingRequest = new Request(request, {\n\t\t\t\t\tbody: stream,\n\t\t\t\t\tduplex: \"half\",\n\t\t\t\t} as any);\n\n\t\t\t\t// Call fetch handler with validation\n\t\t\t\tconst response = await this.#fetch(\n\t\t\t\t\treq.actorId,\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\tstreamingRequest,\n\t\t\t\t);\n\t\t\t\tawait this.#sendResponse(\n\t\t\t\t\tactor.actorId,\n\t\t\t\t\tactor.generation,\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\tresponse,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// Non-streaming request\n\t\t\t\t// Create a pending request entry to track messageIndex for the response\n\t\t\t\tactor.createPendingRequest(gatewayId, requestId, 0);\n\n\t\t\t\tconst response = await this.#fetch(\n\t\t\t\t\treq.actorId,\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\trequest,\n\t\t\t\t);\n\t\t\t\tawait this.#sendResponse(\n\t\t\t\t\tactor.actorId,\n\t\t\t\t\tactor.generation,\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\tresponse,\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (error instanceof RunnerShutdownError) {\n\t\t\t\tthis.log?.debug({ msg: \"catught runner shutdown error\" });\n\t\t\t} else {\n\t\t\t\tthis.log?.error({ msg: \"error handling request\", error });\n\t\t\t\tthis.#sendResponseError(\n\t\t\t\t\tactor.actorId,\n\t\t\t\t\tactor.generation,\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\t500,\n\t\t\t\t\t\"Internal Server Error\",\n\t\t\t\t);\n\t\t\t}\n\t\t} finally {\n\t\t\t// Clean up request tracking\n\t\t\tif (this.#runner.hasActor(req.actorId, actor.generation)) {\n\t\t\t\tactor.deletePendingRequest(gatewayId, requestId);\n\t\t\t\tthis.#removeRequestToActor(gatewayId, requestId);\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #handleRequestChunk(\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t\tchunk: protocol.ToClientRequestChunk,\n\t) {\n\t\tconst actor = await this.getAndWaitForRequestActor(\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t);\n\t\tif (actor) {\n\t\t\tconst pending = actor.getPendingRequest(gatewayId, requestId);\n\t\t\tif (pending?.streamController) {\n\t\t\t\tpending.streamController.enqueue(new Uint8Array(chunk.body));\n\t\t\t\tif (chunk.finish) {\n\t\t\t\t\tpending.streamController.close();\n\t\t\t\t\tactor.deletePendingRequest(gatewayId, requestId);\n\t\t\t\t\tthis.#removeRequestToActor(gatewayId, requestId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #handleRequestAbort(gatewayId: GatewayId, requestId: RequestId) {\n\t\tconst actor = await this.getAndWaitForRequestActor(\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t);\n\t\tif (actor) {\n\t\t\tconst pending = actor.getPendingRequest(gatewayId, requestId);\n\t\t\tif (pending?.streamController) {\n\t\t\t\tpending.streamController.error(new Error(\"Request aborted\"));\n\t\t\t}\n\t\t\tactor.deletePendingRequest(gatewayId, requestId);\n\t\t\tthis.#removeRequestToActor(gatewayId, requestId);\n\t\t}\n\t}\n\n\tasync #sendResponse(\n\t\tactorId: string,\n\t\tgeneration: number,\n\t\tgatewayId: GatewayId,\n\t\trequestId: ArrayBuffer,\n\t\tresponse: Response,\n\t) {\n\t\tif (!this.#runner.hasActor(actorId, generation)) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"actor not loaded to send response, assuming gateway has closed request\",\n\t\t\t\tactorId,\n\t\t\t\tgeneration,\n\t\t\t\trequestId,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Always treat responses as non-streaming for now\n\t\t// In the future, we could detect streaming responses based on:\n\t\t// - Transfer-Encoding: chunked\n\t\t// - Content-Type: text/event-stream\n\t\t// - Explicit stream flag from the handler\n\n\t\t// Read the body first to get the actual content\n\t\tconst body = response.body ? await response.arrayBuffer() : null;\n\n\t\t// Convert headers to map and add Content-Length if not present\n\t\tconst headers = new Map<string, string>();\n\t\tresponse.headers.forEach((value, key) => {\n\t\t\theaders.set(key, value);\n\t\t});\n\n\t\t// Add Content-Length header if we have a body and it's not already set\n\t\tif (body && !headers.has(\"content-length\")) {\n\t\t\theaders.set(\"content-length\", String(body.byteLength));\n\t\t}\n\n\t\t// Send as non-streaming response if actor has not stopped\n\t\tthis.#sendMessage(gatewayId, requestId, {\n\t\t\ttag: \"ToServerResponseStart\",\n\t\t\tval: {\n\t\t\t\tstatus: response.status as protocol.u16,\n\t\t\t\theaders,\n\t\t\t\tbody: body || null,\n\t\t\t\tstream: false,\n\t\t\t},\n\t\t});\n\t}\n\n\t#sendResponseError(\n\t\tactorId: string,\n\t\tgeneration: number,\n\t\tgatewayId: GatewayId,\n\t\trequestId: ArrayBuffer,\n\t\tstatus: number,\n\t\tmessage: string,\n\t) {\n\t\tif (!this.#runner.hasActor(actorId, generation)) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"actor not loaded to send response, assuming gateway has closed request\",\n\t\t\t\tactorId,\n\t\t\t\tgeneration,\n\t\t\t\trequestId,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconst headers = new Map<string, string>();\n\t\theaders.set(\"content-type\", \"text/plain\");\n\n\t\tthis.#sendMessage(gatewayId, requestId, {\n\t\t\ttag: \"ToServerResponseStart\",\n\t\t\tval: {\n\t\t\t\tstatus: status as protocol.u16,\n\t\t\t\theaders,\n\t\t\t\tbody: new TextEncoder().encode(message).buffer as ArrayBuffer,\n\t\t\t\tstream: false,\n\t\t\t},\n\t\t});\n\t}\n\n\tasync #handleWebSocketOpen(\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t\topen: protocol.ToClientWebSocketOpen,\n\t) {\n\t\t// NOTE: This method is safe to be async since we will not receive any\n\t\t// further WebSocket events until we send a ToServerWebSocketOpen\n\t\t// tunnel message. We can do any async logic we need to between thoes two events.\n\t\t//\n\t\t// Sending a ToServerWebSocketClose will terminate the WebSocket early.\n\n\t\tconst requestIdStr = idToStr(requestId);\n\n\t\t// Validate actor exists\n\t\tconst actor = await this.#runner.getAndWaitForActor(open.actorId);\n\t\tif (!actor) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"ignoring websocket for unknown actor\",\n\t\t\t\tactorId: open.actorId,\n\t\t\t});\n\n\t\t\t// NOTE: Closing a WebSocket before open is equivalent to a Service\n\t\t\t// Unavailable error and will cause Guard to retry the request\n\t\t\t//\n\t\t\t// See\n\t\t\t// https://github.com/rivet-dev/rivet/blob/222dae87e3efccaffa2b503de40ecf8afd4e31eb/engine/packages/pegboard-gateway/src/lib.rs#L238\n\t\t\tthis.#sendMessage(gatewayId, requestId, {\n\t\t\t\ttag: \"ToServerWebSocketClose\",\n\t\t\t\tval: {\n\t\t\t\t\tcode: 1011,\n\t\t\t\t\treason: \"Actor not found\",\n\t\t\t\t\thibernate: false,\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Close existing WebSocket if one already exists for this request ID.\n\t\t// This should never happen, but prevents any potential duplicate\n\t\t// WebSockets from retransmits.\n\t\tconst existingAdapter = actor.getWebSocket(gatewayId, requestId);\n\t\tif (existingAdapter) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"closing existing websocket for duplicate open event for the same request id\",\n\t\t\t\trequestId: requestIdStr,\n\t\t\t});\n\t\t\t// Close without sending a message through the tunnel since the server\n\t\t\t// already knows about the new connection\n\t\t\texistingAdapter._closeWithoutCallback(1000, \"ws.duplicate_open\");\n\t\t}\n\n\t\t// Create WebSocket\n\t\ttry {\n\t\t\tconst request = buildRequestForWebSocket(\n\t\t\t\topen.path,\n\t\t\t\tObject.fromEntries(open.headers),\n\t\t\t);\n\n\t\t\tconst canHibernate =\n\t\t\t\tthis.#runner.config.hibernatableWebSocket.canHibernate(\n\t\t\t\t\tactor.actorId,\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\trequest,\n\t\t\t\t);\n\n\t\t\t// #createWebSocket will call `runner.config.websocket` under the\n\t\t\t// hood to add the event listeners for open, etc. If this handler\n\t\t\t// throws, then the WebSocket will be closed before sending the\n\t\t\t// open event.\n\t\t\tconst adapter = await this.#createWebSocket(\n\t\t\t\tactor.actorId,\n\t\t\t\tgatewayId,\n\t\t\t\trequestId,\n\t\t\t\trequestIdStr,\n\t\t\t\t0,\n\t\t\t\tcanHibernate,\n\t\t\t\tfalse,\n\t\t\t\trequest,\n\t\t\t\topen.path,\n\t\t\t\tObject.fromEntries(open.headers),\n\t\t\t\tfalse,\n\t\t\t);\n\n\t\t\t// Create a PendingRequest entry to track the message index\n\t\t\tactor.createPendingRequest(gatewayId, requestId, 0);\n\n\t\t\t// Open the WebSocket after `config.socket` so (a) the event\n\t\t\t// handlers can be added and (b) any errors in `config.websocket`\n\t\t\t// will cause the WebSocket to terminate before the open event.\n\t\t\tthis.#sendMessage(gatewayId, requestId, {\n\t\t\t\ttag: \"ToServerWebSocketOpen\",\n\t\t\t\tval: {\n\t\t\t\t\tcanHibernate,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// Dispatch open event\n\t\t\tadapter._handleOpen(requestId);\n\t\t} catch (error) {\n\t\t\tthis.log?.error({ msg: \"error handling websocket open\", error });\n\n\t\t\t// TODO: Call close event on adapter if needed\n\n\t\t\t// Send close on error\n\t\t\tthis.#sendMessage(gatewayId, requestId, {\n\t\t\t\ttag: \"ToServerWebSocketClose\",\n\t\t\t\tval: {\n\t\t\t\t\tcode: 1011,\n\t\t\t\t\treason: \"Server Error\",\n\t\t\t\t\thibernate: false,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// Clean up actor tracking\n\t\t\tactor.deleteWebSocket(gatewayId, requestId);\n\t\t\tactor.deletePendingRequest(gatewayId, requestId);\n\t\t\tthis.#removeRequestToActor(gatewayId, requestId);\n\t\t}\n\t}\n\n\tasync #handleWebSocketMessage(\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t\tserverMessageIndex: number,\n\t\tmsg: protocol.ToClientWebSocketMessage,\n\t) {\n\t\tconst actor = await this.getAndWaitForRequestActor(\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t);\n\t\tif (actor) {\n\t\t\tconst adapter = actor.getWebSocket(gatewayId, requestId);\n\t\t\tif (adapter) {\n\t\t\t\tconst data = msg.binary\n\t\t\t\t\t? new Uint8Array(msg.data)\n\t\t\t\t\t: new TextDecoder().decode(new Uint8Array(msg.data));\n\n\t\t\t\tadapter._handleMessage(\n\t\t\t\t\trequestId,\n\t\t\t\t\tdata,\n\t\t\t\t\tserverMessageIndex,\n\t\t\t\t\tmsg.binary,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// TODO: This will never retransmit the socket and the socket will close\n\t\tthis.log?.warn({\n\t\t\tmsg: \"missing websocket for incoming websocket message, this may indicate the actor stopped before processing a message\",\n\t\t\trequestId,\n\t\t});\n\t}\n\n\tsendHibernatableWebSocketMessageAck(\n\t\tgatewayId: ArrayBuffer,\n\t\trequestId: ArrayBuffer,\n\t\tclientMessageIndex: number,\n\t) {\n\t\tconst requestIdStr = idToStr(requestId);\n\n\t\tthis.log?.debug({\n\t\t\tmsg: \"ack ws msg\",\n\t\t\trequestId: requestIdStr,\n\t\t\tindex: clientMessageIndex,\n\t\t});\n\n\t\tif (clientMessageIndex < 0 || clientMessageIndex > 65535)\n\t\t\tthrow new Error(\"invalid websocket ack index\");\n\n\t\t// Get the actor to find the gatewayId\n\t\t//\n\t\t// We don't have to wait for the actor to start since we're not calling\n\t\t// any callbacks on the actor\n\t\tconst actor = this.getRequestActor(gatewayId, requestId);\n\t\tif (!actor) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"cannot send websocket ack, actor not found\",\n\t\t\t\trequestId: requestIdStr,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Get gatewayId from the pending request\n\t\tconst pending = actor.getPendingRequest(gatewayId, requestId);\n\t\tif (!pending?.gatewayId) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"cannot send websocket ack, gatewayId not found in pending request\",\n\t\t\t\trequestId: requestIdStr,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Send the ack message\n\t\tthis.#sendMessage(pending.gatewayId, requestId, {\n\t\t\ttag: \"ToServerWebSocketMessageAck\",\n\t\t\tval: {\n\t\t\t\tindex: clientMessageIndex,\n\t\t\t},\n\t\t});\n\t}\n\n\tasync #handleWebSocketClose(\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t\tclose: protocol.ToClientWebSocketClose,\n\t) {\n\t\tconst actor = await this.getAndWaitForRequestActor(\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t);\n\t\tif (actor) {\n\t\t\tconst adapter = actor.getWebSocket(gatewayId, requestId);\n\t\t\tif (adapter) {\n\t\t\t\t// We don't need to send a close response\n\t\t\t\tadapter._handleClose(\n\t\t\t\t\trequestId,\n\t\t\t\t\tclose.code || undefined,\n\t\t\t\t\tclose.reason || undefined,\n\t\t\t\t);\n\t\t\t\tactor.deleteWebSocket(gatewayId, requestId);\n\t\t\t\tactor.deletePendingRequest(gatewayId, requestId);\n\t\t\t\tthis.#removeRequestToActor(gatewayId, requestId);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Builds a request that represents the incoming request for a given WebSocket.\n *\n * This request is not a real request and will never be sent. It's used to be passed to the actor to behave like a real incoming request.\n */\nfunction buildRequestForWebSocket(\n\tpath: string,\n\theaders: Record<string, string>,\n): Request {\n\t// We need to manually ensure the original Upgrade/Connection WS\n\t// headers are present\n\tconst fullHeaders = {\n\t\t...headers,\n\t\tUpgrade: \"websocket\",\n\t\tConnection: \"Upgrade\",\n\t};\n\n\tif (!path.startsWith(\"/\")) {\n\t\tthrow new Error(\"path must start with leading slash\");\n\t}\n\n\tconst request = new Request(`http://actor${path}`, {\n\t\tmethod: \"GET\",\n\t\theaders: fullHeaders,\n\t});\n\n\treturn request;\n}\n","import { logger } from \"./log\";\n\n// Global singleton promise that will be reused for subsequent calls\nlet webSocketPromise: Promise<typeof WebSocket> | null = null;\n\nexport async function importWebSocket(): Promise<typeof WebSocket> {\n\t// Return existing promise if we already started loading\n\tif (webSocketPromise !== null) {\n\t\treturn webSocketPromise;\n\t}\n\n\t// Create and store the promise\n\twebSocketPromise = (async () => {\n\t\tlet _WebSocket: typeof WebSocket;\n\n\t\tif (typeof WebSocket !== \"undefined\") {\n\t\t\t// Native\n\t\t\t_WebSocket = WebSocket as unknown as typeof WebSocket;\n\t\t\tlogger()?.debug({ msg: \"using native websocket\" });\n\t\t} else {\n\t\t\t// Node.js package\n\t\t\ttry {\n\t\t\t\tconst ws = await import(\"ws\");\n\t\t\t\t_WebSocket = ws.default as unknown as typeof WebSocket;\n\t\t\t\tlogger()?.debug({ msg: \"using websocket from npm\" });\n\t\t\t} catch {\n\t\t\t\t// WS not available\n\t\t\t\t_WebSocket = class MockWebSocket {\n\t\t\t\t\tconstructor() {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t'WebSocket support requires installing the \"ws\" peer dependency.',\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} as unknown as typeof WebSocket;\n\t\t\t\tlogger()?.debug({ msg: \"using mock websocket\" });\n\t\t\t}\n\t\t}\n\n\t\treturn _WebSocket;\n\t})();\n\n\treturn webSocketPromise;\n}\n"],"mappings":";AAAA,YAAY,cAAc;;;ACE1B,IAAI;AAEG,SAAS,UAAUA,SAAgB;AACzC,WAASA;AACV;AAEO,SAAS,SAA6B;AAC5C,SAAO;AACR;;;ACRO,SAAS,YAAY,GAAiB;AAC5C,QAAM,gBAAgB,CAAC;AACxB;AASO,SAAS,iBACf,SACA,UAA0B,CAAC,GAClB;AACT,QAAM;AAAA,IACL,eAAe;AAAA,IACf,WAAW;AAAA,IACX,aAAa;AAAA,IACb,SAAS;AAAA,EACV,IAAI;AAEJ,MAAI,QAAQ,KAAK,IAAI,eAAe,cAAc,SAAS,QAAQ;AAEnE,MAAI,QAAQ;AAEX,YAAQ,SAAS,IAAI,KAAK,OAAO,IAAI;AAAA,EACtC;AAEA,SAAO,KAAK,MAAM,KAAK;AACxB;AAiBO,SAAS,0BACf,QACgC;AAnDjC;AAoDC,QAAM,CAAC,UAAU,KAAK,IAAI,OAAO,MAAM,GAAG;AAC1C,QAAM,CAAC,OAAO,KAAK,IAAI,SAAS,MAAM,GAAG;AAEzC,MAAI,CAAC,SAAS,CAAC,OAAO;AACrB,iBAAO,MAAP,mBAAU,KAAK,EAAE,KAAK,gCAAgC,OAAO;AAC7D,WAAO;AAAA,EACR;AAEA,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;AAEA,IAAM,UAAU;AAcT,SAAS,cAAc,GAAW,GAAoB;AAC5D,SAAO,MAAM,KAAK,YAAY,GAAG,GAAG,OAAO,IAAI,UAAU;AAC1D;AAYO,SAAS,eAAe,GAAW,GAAoB;AAC7D,SAAO,MAAM,KAAK,cAAc,GAAG,CAAC;AACrC;AAKO,SAAS,eAAe,GAAW,GAAmB;AAC5D,UAAQ,IAAI,MAAM,UAAU;AAC7B;AAKO,SAAS,eAAe,GAAW,GAAmB;AAC5D,SAAO,YAAY,GAAG,GAAG,OAAO;AACjC;AAKA,SAAS,YAAY,GAAW,GAAW,KAAqB;AAC/D,QAAM,SAAS,IAAI;AACnB,MAAI,SAAS,GAAG;AACf,WAAO,SAAS,MAAM;AAAA,EACvB;AACA,SAAO;AACR;AAEO,SAAS,YAAY,GAAgB,GAAyB;AACpE,QAAM,KAAK,IAAI,WAAW,CAAC;AAC3B,QAAM,KAAK,IAAI,WAAW,CAAC;AAC3B,MAAI,GAAG,WAAW,GAAG,OAAQ,QAAO;AACpC,WAAS,IAAI,GAAG,IAAI,GAAG,QAAQ,KAAK;AACnC,QAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAG,QAAO;AAAA,EAC7B;AACA,SAAO;AACR;AAOO,SAAS,uBAId;AACD,MAAI;AACJ,MAAI;AACJ,QAAM,UAAU,IAAI,QAAW,CAAC,KAAK,QAAQ;AAC5C,cAAU;AACV,aAAS;AAAA,EACV,CAAC;AACD,SAAO,EAAE,SAAS,SAAS,OAAO;AACnC;AAEO,SAAS,QAAQ,IAAyB;AAChD,QAAM,QAAQ,IAAI,WAAW,EAAE;AAC/B,SAAO,MAAM,KAAK,KAAK,EACrB,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAChD,KAAK,EAAE;AACV;AAEO,SAAS,eAAe,OAAwB;AAhKvD;AAiKC,MAAI,iBAAiB,OAAO;AAC3B,WAAO,GAAG,MAAM,IAAI,KAAK,MAAM,OAAO,GAAG,MAAM,QAAQ;AAAA,EAAK,MAAM,KAAK,KAAK,EAAE;AAAA,EAC/E,WAAW,OAAO,UAAU,UAAU;AACrC,WAAO;AAAA,EACR,WAAW,OAAO,UAAU,YAAY,UAAU,MAAM;AACvD,QAAI;AACH,aAAO,GAAG,KAAK,UAAU,KAAK,CAAC;AAAA,IAChC,QAAQ;AACP,aAAO,aAAW,WAAM,gBAAN,mBAAmB,SAAQ,QAAQ;AAAA,IACtD;AAAA,EACD,OAAO;AACN,WAAO,OAAO,KAAK;AAAA,EACpB;AACD;;;ACjKO,IAAM,cAAN,MAAkB;AAAA,EA0BxB,YACC,SACA,YACA,QAKO,qBACN;AADM;AAEP,SAAK,UAAU;AACf,SAAK,aAAa;AAClB,SAAK,SAAS;AACd,SAAK,oBAAoB,qBAAqB;AAAA,EAC/C;AAAA,EAvCA;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAIK,CAAC;AAAA,EACN,aAIK,CAAC;AAAA,EACN;AAAA,EAEA,iBAAyB,CAAC;AAAA,EAC1B,eAAuB;AAAA,EACvB,eAAwC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMzC,sBAA+B;AAAA;AAAA,EAmB/B,kBACC,WACA,WAC6B;AA3D/B;AA4DE,YAAO,UAAK,gBAAgB;AAAA,MAC3B,CAAC,UACA,YAAY,MAAM,WAAW,SAAS,KACtC,YAAY,MAAM,WAAW,SAAS;AAAA,IACxC,MAJO,mBAIJ;AAAA,EACJ;AAAA,EAEA,qBACC,WACA,WACA,oBACC;AAvEH;AAwEE,UAAM,SACL,KAAK,kBAAkB,WAAW,SAAS,MAAM;AAClD,QAAI,QAAQ;AACX,mBAAO,MAAP,mBAAU,KAAK;AAAA,QACd,KAAK;AAAA,QACL,WAAW,QAAQ,SAAS;AAAA,QAC5B,WAAW,QAAQ,SAAS;AAAA,MAC7B;AAEA,WAAK,qBAAqB,WAAW,SAAS;AAAA,IAC/C;AACA,SAAK,gBAAgB,KAAK;AAAA,MACzB;AAAA,MACA;AAAA,MACA,SAAS;AAAA,QACR,SAAS,MAAM;AAAA,QAAE;AAAA,QACjB,QAAQ,MAAM;AAAA,QAAE;AAAA,QAChB,SAAS,KAAK;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,IACD,CAAC;AACD,iBAAO,MAAP,mBAAU,MAAM;AAAA,MACf,KAAK;AAAA,MACL,WAAW,QAAQ,SAAS;AAAA,MAC5B,WAAW,QAAQ,SAAS;AAAA,MAC5B,QAAQ,KAAK,gBAAgB;AAAA,IAC9B;AAAA,EACD;AAAA,EAEA,yCACC,WACA,WACA,oBACA,kBACC;AA5GH;AA6GE,UAAM,SACL,KAAK,kBAAkB,WAAW,SAAS,MAAM;AAClD,QAAI,QAAQ;AACX,mBAAO,MAAP,mBAAU,KAAK;AAAA,QACd,KAAK;AAAA,QACL,WAAW,QAAQ,SAAS;AAAA,QAC5B,WAAW,QAAQ,SAAS;AAAA,MAC7B;AAEA,WAAK,qBAAqB,WAAW,SAAS;AAAA,IAC/C;AACA,SAAK,gBAAgB,KAAK;AAAA,MACzB;AAAA,MACA;AAAA,MACA,SAAS;AAAA,QACR,SAAS,MAAM;AAAA,QAAE;AAAA,QACjB,QAAQ,MAAM;AAAA,QAAE;AAAA,QAChB,SAAS,KAAK;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,IACD,CAAC;AACD,iBAAO,MAAP,mBAAU,MAAM;AAAA,MACf,KAAK;AAAA,MACL,WAAW,QAAQ,SAAS;AAAA,MAC5B,WAAW,QAAQ,SAAS;AAAA,MAC5B,QAAQ,KAAK,gBAAgB;AAAA,IAC9B;AAAA,EACD;AAAA,EAEA,qBACC,WACA,WACC;AAhJH;AAiJE,UAAM,QAAQ,KAAK,gBAAgB;AAAA,MAClC,CAAC,UACA,YAAY,MAAM,WAAW,SAAS,KACtC,YAAY,MAAM,WAAW,SAAS;AAAA,IACxC;AACA,QAAI,UAAU,IAAI;AACjB,WAAK,gBAAgB,OAAO,OAAO,CAAC;AACpC,mBAAO,MAAP,mBAAU,MAAM;AAAA,QACf,KAAK;AAAA,QACL,WAAW,QAAQ,SAAS;AAAA,QAC5B,WAAW,QAAQ,SAAS;AAAA,QAC5B,QAAQ,KAAK,gBAAgB;AAAA,MAC9B;AAAA,IACD;AAAA,EACD;AAAA;AAAA,EAGA,aACC,WACA,WACqC;AArKvC;AAsKE,YAAO,UAAK,WAAW;AAAA,MACtB,CAAC,UACA,YAAY,MAAM,WAAW,SAAS,KACtC,YAAY,MAAM,WAAW,SAAS;AAAA,IACxC,MAJO,mBAIJ;AAAA,EACJ;AAAA,EAEA,aACC,WACA,WACA,IACC;AAjLH;AAkLE,UAAM,SAAS,KAAK,aAAa,WAAW,SAAS,MAAM;AAC3D,QAAI,QAAQ;AACX,mBAAO,MAAP,mBAAU,KAAK,EAAE,KAAK,oCAAoC;AAC1D;AAAA,IACD;AACA,SAAK,WAAW,KAAK,EAAE,WAAW,WAAW,GAAG,CAAC;AAAA,EAClD;AAAA,EAEA,gBACC,WACA,WACC;AACD,UAAM,QAAQ,KAAK,WAAW;AAAA,MAC7B,CAAC,UACA,YAAY,MAAM,WAAW,SAAS,KACtC,YAAY,MAAM,WAAW,SAAS;AAAA,IACxC;AACA,QAAI,UAAU,IAAI;AACjB,WAAK,WAAW,OAAO,OAAO,CAAC;AAAA,IAChC;AAAA,EACD;AAAA,EAEA,gBAAgB,cAAsB;AACrC,SAAK,eAAe,KAAK,aAAa;AAAA,MACrC,CAAC,UAAU,MAAM,WAAW,QAAQ;AAAA,IACrC;AAAA,EACD;AAAA,EAEA,YAAY,cAAqC;AAChD,SAAK,aAAa,KAAK,YAAY;AAAA,EACpC;AACD;;;AC3MA,SAAS,qBAAqB,QAA6B;AAC1D,SAAO,eAAe,OAAO,UAAU;AACxC;AAKA,SAAS,gBAAgB,OAAuB;AAC/C,SAAO,GAAG,KAAK;AAChB;AAKA,SAAS,aAAa,KAA0C;AAC/D,QAAM,UAAU,MAAM,KAAK,IAAI,QAAQ,CAAC,EACtC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,EAChC,KAAK,IAAI;AACX,SAAO,OAAO,IAAI,IAAI,KAAK,OAAO;AACnC;AAKA,SAAS,mBAAmB,WAAuC;AAClE,SAAO,wBAAwB,QAAQ,UAAU,SAAS,CAAC,gBAAgB,QAAQ,UAAU,SAAS,CAAC,mBAAmB,UAAU,YAAY;AACjJ;AAMO,SAAS,mCACf,MACS;AACT,UAAQ,KAAK,KAAK;AAAA,IACjB,KAAK,yBAAyB;AAC7B,YAAM,EAAE,QAAQ,SAAS,MAAM,OAAO,IAAI,KAAK;AAC/C,YAAM,UAAU,SAAS,OAAO,SAAS,qBAAqB,IAAI;AAClE,aAAO,iCAAiC,MAAM,cAAc,aAAa,OAAO,CAAC,WAAW,OAAO,aAAa,MAAM;AAAA,IACvH;AAAA,IACA,KAAK,yBAAyB;AAC7B,YAAM,EAAE,MAAM,OAAO,IAAI,KAAK;AAC9B,aAAO,+BAA+B,qBAAqB,IAAI,CAAC,aAAa,MAAM;AAAA,IACpF;AAAA,IACA,KAAK;AACJ,aAAO;AAAA,IACR,KAAK,yBAAyB;AAC7B,YAAM,EAAE,aAAa,IAAI,KAAK;AAC9B,aAAO,uCAAuC,YAAY;AAAA,IAC3D;AAAA,IACA,KAAK,4BAA4B;AAChC,YAAM,EAAE,MAAM,OAAO,IAAI,KAAK;AAC9B,aAAO,kCAAkC,qBAAqB,IAAI,CAAC,aAAa,MAAM;AAAA,IACvF;AAAA,IACA,KAAK,+BAA+B;AACnC,YAAM,EAAE,MAAM,IAAI,KAAK;AACvB,aAAO,sCAAsC,KAAK;AAAA,IACnD;AAAA,IACA,KAAK,0BAA0B;AAC9B,YAAM,EAAE,MAAM,QAAQ,UAAU,IAAI,KAAK;AACzC,YAAM,UAAU,SAAS,OAAO,SAAS,KAAK,SAAS;AACvD,YAAM,YAAY,WAAW,OAAO,SAAS,IAAI,MAAM;AACvD,aAAO,gCAAgC,OAAO,aAAa,SAAS,gBAAgB,SAAS;AAAA,IAC9F;AAAA,EACD;AACD;AAMO,SAAS,mCACf,MACS;AACT,UAAQ,KAAK,KAAK;AAAA,IACjB,KAAK,wBAAwB;AAC5B,YAAM,EAAE,SAAS,QAAQ,MAAM,SAAS,MAAM,OAAO,IAAI,KAAK;AAC9D,YAAM,UAAU,SAAS,OAAO,SAAS,qBAAqB,IAAI;AAClE,aAAO,kCAAkC,OAAO,eAAe,MAAM,aAAa,IAAI,eAAe,aAAa,OAAO,CAAC,WAAW,OAAO,aAAa,MAAM;AAAA,IAChK;AAAA,IACA,KAAK,wBAAwB;AAC5B,YAAM,EAAE,MAAM,OAAO,IAAI,KAAK;AAC9B,aAAO,8BAA8B,qBAAqB,IAAI,CAAC,aAAa,MAAM;AAAA,IACnF;AAAA,IACA,KAAK;AACJ,aAAO;AAAA,IACR,KAAK,yBAAyB;AAC7B,YAAM,EAAE,SAAS,MAAM,QAAQ,IAAI,KAAK;AACxC,aAAO,mCAAmC,OAAO,aAAa,IAAI,eAAe,aAAa,OAAO,CAAC;AAAA,IACvG;AAAA,IACA,KAAK,4BAA4B;AAChC,YAAM,EAAE,MAAM,OAAO,IAAI,KAAK;AAC9B,aAAO,kCAAkC,qBAAqB,IAAI,CAAC,aAAa,MAAM;AAAA,IACvF;AAAA,IACA,KAAK,0BAA0B;AAC9B,YAAM,EAAE,MAAM,OAAO,IAAI,KAAK;AAC9B,YAAM,UAAU,SAAS,OAAO,SAAS,KAAK,SAAS;AACvD,YAAM,YAAY,WAAW,OAAO,SAAS,IAAI,MAAM;AACvD,aAAO,gCAAgC,OAAO,aAAa,SAAS;AAAA,IACrE;AAAA,EACD;AACD;AAMO,SAAS,iBAAiB,SAAmC;AACnE,UAAQ,QAAQ,KAAK;AAAA,IACpB,KAAK,qBAAqB;AACzB,YAAM,EAAE,QAAQ,oBAAoB,IACnC,QAAQ;AACT,YAAM,SAAS,OAAO,QAAQ,OAAO,SAAS,IAAI,OAAO,GAAG;AAC5D,YAAM,WACL,OAAO,UAAU,OACd,SACA,qBAAqB,OAAO,KAAK;AACrC,YAAM,yBACL,oBAAoB,SAAS,IAC1B,IAAI,oBAAoB,IAAI,CAAC,OAAO,eAAe,QAAQ,GAAG,SAAS,CAAC,gBAAgB,QAAQ,GAAG,SAAS,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC,MAC5H;AACJ,aAAO,qCAAqC,OAAO,IAAI,WAAW,MAAM,eAAe,gBAAgB,OAAO,QAAQ,CAAC,YAAY,QAAQ,2BAA2B,sBAAsB;AAAA,IAC7L;AAAA,IACA,KAAK,oBAAoB;AACxB,aAAO;AAAA,IACR;AAAA,EACD;AACD;AAMO,SAAS,wBACf,SACS;AACT,SAAO,4BAA4B,QAAQ,WAAW,OAAO,mBAAmB,QAAQ,WAAW,UAAU,aAAa,gBAAgB,QAAQ,WAAW,KAAK,CAAC,YAAY,iBAAiB,QAAQ,KAAK,CAAC;AAC/M;AAMO,SAAS,eAAe,OAA+B;AAC7D,UAAQ,MAAM,KAAK;AAAA,IAClB,KAAK,oBAAoB;AACxB,YAAM,EAAE,OAAO,IAAI,MAAM;AACzB,YAAM,YACL,OAAO,QAAQ,qBACZ,UACA,OAAO,QAAQ,oBACd,SACA;AACL,aAAO,4BAA4B,SAAS;AAAA,IAC7C;AAAA,IACA,KAAK,yBAAyB;AAC7B,YAAM,EAAE,MAAM,IAAI,MAAM;AACxB,UAAI;AACJ,UAAI,MAAM,QAAQ,qBAAqB;AACtC,mBAAW;AAAA,MACZ,WAAW,MAAM,QAAQ,qBAAqB;AAC7C,cAAM,EAAE,MAAM,QAAQ,IAAI,MAAM;AAChC,cAAM,aAAa,YAAY,OAAO,SAAS,IAAI,OAAO;AAC1D,mBAAW,iBAAiB,IAAI,cAAc,UAAU;AAAA,MACzD,OAAO;AACN,mBAAW;AAAA,MACZ;AACA,aAAO,gCAAgC,QAAQ;AAAA,IAChD;AAAA,IACA,KAAK,sBAAsB;AAC1B,YAAM,EAAE,QAAQ,IAAI,MAAM;AAC1B,YAAM,aACL,YAAY,OAAO,SAAS,gBAAgB,OAAO;AACpD,aAAO,+BAA+B,UAAU;AAAA,IACjD;AAAA,EACD;AACD;AAMO,SAAS,sBAAsB,SAAwC;AAC7E,SAAO,yBAAyB,QAAQ,WAAW,OAAO,kBAAkB,QAAQ,WAAW,UAAU,aAAa,gBAAgB,QAAQ,WAAW,KAAK,CAAC,YAAY,eAAe,QAAQ,KAAK,CAAC;AACzM;AAMO,SAAS,kBAAkB,SAAoC;AACrE,UAAQ,QAAQ,KAAK;AAAA,IACpB,KAAK,gBAAgB;AACpB,YAAM;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD,IAAI,QAAQ;AACZ,YAAM,2BACL,0BAA0B,OACvB,SACA,OAAO,sBAAsB,IAAI;AACrC,YAAM,cAAc,aAAa,OAAO,SAAS,IAAI,QAAQ;AAC7D,aAAO,uBAAuB,IAAI,eAAe,OAAO,iBAAiB,UAAU,4BAA4B,wBAAwB,eAAe,WAAW;AAAA,IAClK;AAAA,IACA,KAAK,kBAAkB;AACtB,YAAM,SAAS,QAAQ;AACvB,aAAO,yBAAyB,OAAO,MAAM,cAAc,OAAO,IAAI,CAAC,MAAM,sBAAsB,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,IAClH;AAAA,IACA,KAAK,uBAAuB;AAC3B,YAAM,EAAE,uBAAuB,IAAI,QAAQ;AAC3C,YAAM,iBACL,uBAAuB,SAAS,IAC7B,IAAI,uBAAuB,IAAI,CAAC,OAAO,cAAc,GAAG,OAAO,aAAa,gBAAgB,GAAG,KAAK,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC,MACpH;AACJ,aAAO,+CAA+C,cAAc;AAAA,IACrE;AAAA,IACA,KAAK;AACJ,aAAO;AAAA,IACR,KAAK,gBAAgB;AACpB,YAAM,EAAE,GAAG,IAAI,QAAQ;AACvB,aAAO,oBAAoB,gBAAgB,EAAE,CAAC;AAAA,IAC/C;AAAA,IACA,KAAK,qBAAqB;AACzB,YAAM,EAAE,SAAS,WAAW,KAAK,IAAI,QAAQ;AAC7C,YAAM,UAAU,uBAAuB,IAAI;AAC3C,aAAO,+BAA+B,OAAO,iBAAiB,SAAS,WAAW,OAAO;AAAA,IAC1F;AAAA,IACA,KAAK,yBAAyB;AAC7B,YAAM,EAAE,WAAW,YAAY,IAAI,QAAQ;AAC3C,aAAO,oCAAoC,mBAAmB,SAAS,CAAC,kBAAkB,mCAAmC,WAAW,CAAC;AAAA,IAC1I;AAAA,EACD;AACD;AAMO,SAAS,kBAAkB,SAAoC;AACrE,UAAQ,QAAQ,KAAK;AAAA,IACpB,KAAK,gBAAgB;AACpB,YAAM,EAAE,UAAU,SAAS,IAAI,QAAQ;AACvC,YAAM,cAAc,yBAAyB,gBAAgB,SAAS,mBAAmB,CAAC;AAC1F,aAAO,2BAA2B,QAAQ,gBAAgB,WAAW;AAAA,IACtE;AAAA,IACA,KAAK;AACJ,YAAM,EAAE,GAAG,IAAI,QAAQ;AACvB,aAAO,oBAAoB,gBAAgB,EAAE,CAAC;AAAA,IAC/C,KAAK,oBAAoB;AACxB,YAAM,WAAW,QAAQ;AACzB,aAAO,2BAA2B,SAAS,MAAM,gBAAgB,SAAS,IAAI,CAAC,MAAM,wBAAwB,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,IAC5H;AAAA,IACA,KAAK,qBAAqB;AACzB,YAAM,EAAE,qBAAqB,IAAI,QAAQ;AACzC,YAAM,iBACL,qBAAqB,SAAS,IAC3B,IAAI,qBAAqB,IAAI,CAAC,OAAO,cAAc,GAAG,OAAO,aAAa,gBAAgB,GAAG,KAAK,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC,MAClH;AACJ,aAAO,2CAA2C,cAAc;AAAA,IACjE;AAAA,IACA,KAAK,sBAAsB;AAC1B,YAAM,EAAE,WAAW,KAAK,IAAI,QAAQ;AACpC,YAAM,UAAU,wBAAwB,IAAI;AAC5C,aAAO,iCAAiC,SAAS,WAAW,OAAO;AAAA,IACpE;AAAA,IACA,KAAK,yBAAyB;AAC7B,YAAM,EAAE,WAAW,YAAY,IAAI,QAAQ;AAC3C,aAAO,oCAAoC,mBAAmB,SAAS,CAAC,kBAAkB,mCAAmC,WAAW,CAAC;AAAA,IAC1I;AAAA,EACD;AACD;AAKA,SAAS,uBAAuB,MAAsC;AACrE,UAAQ,KAAK,KAAK;AAAA,IACjB,KAAK,gBAAgB;AACpB,YAAM,EAAE,KAAK,IAAI,KAAK;AACtB,aAAO,sBAAsB,KAAK,MAAM;AAAA,IACzC;AAAA,IACA,KAAK,iBAAiB;AACrB,YAAM,EAAE,OAAO,SAAS,MAAM,IAAI,KAAK;AACvC,YAAM,aAAa,YAAY,OAAO,SAAS,QAAQ,SAAS;AAChE,YAAM,WAAW,UAAU,OAAO,SAAS,gBAAgB,KAAK;AAChE,aAAO,wBAAwB,qBAAqB,KAAK,CAAC,cAAc,UAAU,YAAY,QAAQ;AAAA,IACvG;AAAA,IACA,KAAK,gBAAgB;AACpB,YAAM,EAAE,MAAM,OAAO,IAAI,KAAK;AAC9B,aAAO,sBAAsB,KAAK,MAAM,aAAa,OAAO,MAAM;AAAA,IACnE;AAAA,IACA,KAAK,mBAAmB;AACvB,YAAM,EAAE,KAAK,IAAI,KAAK;AACtB,aAAO,yBAAyB,KAAK,MAAM;AAAA,IAC5C;AAAA,IACA,KAAK;AACJ,aAAO;AAAA,EACT;AACD;AAKA,SAAS,qBAAqB,OAAqC;AAClE,UAAQ,MAAM,KAAK;AAAA,IAClB,KAAK;AACJ,aAAO;AAAA,IACR,KAAK,oBAAoB;AACxB,YAAM,EAAE,OAAO,KAAK,UAAU,IAAI,MAAM;AACxC,aAAO,2BAA2B,qBAAqB,KAAK,CAAC,UAAU,qBAAqB,GAAG,CAAC,gBAAgB,SAAS;AAAA,IAC1H;AAAA,IACA,KAAK,qBAAqB;AACzB,YAAM,EAAE,IAAI,IAAI,MAAM;AACtB,aAAO,0BAA0B,qBAAqB,GAAG,CAAC;AAAA,IAC3D;AAAA,EACD;AACD;AAKA,SAAS,wBAAwB,MAAuC;AACvE,UAAQ,KAAK,KAAK;AAAA,IACjB,KAAK,mBAAmB;AACvB,YAAM,EAAE,QAAQ,IAAI,KAAK;AACzB,aAAO,6BAA6B,OAAO;AAAA,IAC5C;AAAA,IACA,KAAK,iBAAiB;AACrB,YAAM,EAAE,MAAM,QAAQ,SAAS,IAAI,KAAK;AACxC,aAAO,uBAAuB,KAAK,MAAM,aAAa,OAAO,MAAM,eAAe,SAAS,MAAM;AAAA,IAClG;AAAA,IACA,KAAK,kBAAkB;AACtB,YAAM,EAAE,MAAM,QAAQ,SAAS,IAAI,KAAK;AACxC,aAAO,wBAAwB,KAAK,MAAM,aAAa,OAAO,MAAM,eAAe,SAAS,MAAM;AAAA,IACnG;AAAA,IACA,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,EACT;AACD;;;ACxVO,IAAM,sBAAsB,OAAO,cAAc;AAEjD,IAAM,yBAAN,MAA6B;AAAA,EA+CnC,YACC,QACA,SACA,WACA,oBACA,cACA,yBAEgB,SAChB,cACA,eACC;AAHe;AAjElB;AAqEE,SAAK,UAAU;AACf,SAAK,WAAW;AAChB,SAAK,aAAa;AAClB,SAAK,gBAAgB;AACrB,SAAK,sBAAsB;AAC3B,SAAK,gBAAgB;AACrB,SAAK,iBAAiB;AAGtB,QAAI,yBAAyB;AAC5B,iBAAK,SAAL,mBAAW,MAAM;AAAA,QAChB,KAAK;AAAA,QACL,SAAS,KAAK;AAAA,QACd,WAAW,KAAK;AAAA,QAChB,cAAc,KAAK;AAAA,MACpB;AACA,WAAK,cAAc;AAAA,IACpB;AAAA,EACD;AAAA;AAAA,EA3EA,cAAsB;AAAA;AAAA,EACtB,kBAA0D,oBAAI,IAAI;AAAA,EAClE,UAAgD;AAAA,EAChD,WAAiD;AAAA,EACjD,WAAiD;AAAA,EACjD,aAAmD;AAAA,EACnD,kBAAkB;AAAA,EAClB,cAAqD;AAAA,EACrD,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,OAAO;AAAA;AAAA,EAGP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,KAAK,mBAAmB,IAAa;AACpC,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA;AAAA,EAMA,IAAI,OAA2B;AAC9B,WAAO,KAAK,QAAQ;AAAA,EACrB;AAAA;AAAA,EAmCA,IAAI,iBAAyB;AAC5B,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,YAAY,WAA8B;AACzC,QAAI,KAAK,gBAAgB,GAAG;AAE3B;AAAA,IACD;AAEA,SAAK,cAAc;AAEnB,UAAM,QAAQ;AAAA,MACb,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,QAAQ;AAAA,IACT;AAEA,SAAK,WAAW,QAAQ,KAAK;AAAA,EAC9B;AAAA,EAEA,eACC,WACA,MACA,oBACA,UACU;AApHZ;AAqHE,QAAI,KAAK,gBAAgB,GAAG;AAC3B,iBAAK,SAAL,mBAAW,KAAK;AAAA,QACf,KAAK;AAAA,QACL,WAAW,KAAK;AAAA,QAChB,SAAS,KAAK;AAAA,QACd,mBAAmB,KAAK;AAAA,QACxB,oBAAoB;AAAA,QACpB;AAAA,QACA,cAAc,KAAK;AAAA,MACpB;AACA,aAAO;AAAA,IACR;AAGA,QAAI,KAAK,eAAe;AACvB,YAAM,gBAAgB,KAAK;AAU3B,UAAI,eAAe,oBAAoB,aAAa,GAAG;AACtD,mBAAK,SAAL,mBAAW,KAAK;AAAA,UACf,KAAK;AAAA,UACL;AAAA,UACA,SAAS,KAAK;AAAA,UACd;AAAA,UACA,eAAe,eAAe,eAAe,CAAC;AAAA,UAC9C,eAAe;AAAA,QAChB;AAEA,eAAO;AAAA,MACR;AAKA,YAAM,gBAAgB,eAAe,eAAe,CAAC;AACrD,UAAI,uBAAuB,eAAe;AACzC,cAAM,cAAc;AAEpB,mBAAK,SAAL,mBAAW,KAAK;AAAA,UACf,KAAK;AAAA,UACL;AAAA,UACA,SAAS,KAAK;AAAA,UACd;AAAA,UACA;AAAA,UACA,eAAe;AAAA,UACf;AAAA,UACA,KAAK;AAAA,YACJ,eAAe,oBAAoB,aAAa;AAAA,YAChD;AAAA,UACD;AAAA,QACD;AAGA,aAAK,MAAM,MAAM,WAAW;AAE5B,eAAO;AAAA,MACR;AAGA,WAAK,sBAAsB;AAAA,IAC5B;AAGA,QAAI;AACJ,QAAI,UAAU;AAEb,UAAI,KAAK,gBAAgB,cAAc;AAEtC,sBAAc,OAAO,KAAK,IAAkB;AAAA,MAC7C,WAAW,KAAK,gBAAgB,eAAe;AAE9C,YAAI,gBAAgB,YAAY;AAC/B,wBAAc,KAAK,OAAO;AAAA,YACzB,KAAK;AAAA,YACL,KAAK,aAAa,KAAK;AAAA,UACxB;AAAA,QACD,OAAO;AACN,wBAAc;AAAA,QACf;AAAA,MACD,OAAO;AAEN,cAAM,IAAI;AAAA,UACT;AAAA,QACD;AAAA,MACD;AAAA,IACD,OAAO;AACN,oBAAc;AAAA,IACf;AAEA,UAAM,QAAQ;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,mBAAmB;AAAA,MACnB,QAAQ;AAAA,IACT;AAEA,SAAK,WAAW,WAAW,KAAK;AAEhC,WAAO;AAAA,EACR;AAAA,EAEA,aACC,YACA,MACA,QACO;AACP,SAAK,YAAY,MAAM,QAAQ,IAAI;AAAA,EACpC;AAAA,EAEA,aAAa,OAAoB;AAChC,UAAM,QAAQ;AAAA,MACb,MAAM;AAAA,MACN,QAAQ;AAAA,MACR;AAAA,IACD;AAEA,SAAK,WAAW,SAAS,KAAK;AAAA,EAC/B;AAAA,EAEA,sBAAsB,MAAe,QAAuB;AAC3D,SAAK,YAAY,MAAM,QAAQ,KAAK;AAAA,EACrC;AAAA,EAEA,WAAW,MAAc,OAAkB;AAxP5C;AA0PE,UAAM,YAAY,KAAK,gBAAgB,IAAI,IAAI;AAE/C,QAAI,aAAa,UAAU,OAAO,GAAG;AACpC,iBAAW,YAAY,WAAW;AACjC,YAAI;AACH,mBAAS,KAAK,MAAM,KAAK;AAAA,QAC1B,SAAS,OAAO;AACf,uBAAO,MAAP,mBAAU,MAAM;AAAA,YACf,KAAK;AAAA,YACL;AAAA,YACA;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAGA,YAAQ,MAAM;AAAA,MACb,KAAK;AACJ,YAAI,KAAK,SAAS;AACjB,cAAI;AACH,iBAAK,QAAQ,KAAK,MAAM,KAAK;AAAA,UAC9B,SAAS,OAAO;AACf,yBAAO,MAAP,mBAAU,MAAM;AAAA,cACf,KAAK;AAAA,cACL;AAAA,YACD;AAAA,UACD;AAAA,QACD;AACA;AAAA,MACD,KAAK;AACJ,YAAI,KAAK,UAAU;AAClB,cAAI;AACH,iBAAK,SAAS,KAAK,MAAM,KAAK;AAAA,UAC/B,SAAS,OAAO;AACf,yBAAO,MAAP,mBAAU,MAAM;AAAA,cACf,KAAK;AAAA,cACL;AAAA,YACD;AAAA,UACD;AAAA,QACD;AACA;AAAA,MACD,KAAK;AACJ,YAAI,KAAK,UAAU;AAClB,cAAI;AACH,iBAAK,SAAS,KAAK,MAAM,KAAK;AAAA,UAC/B,SAAS,OAAO;AACf,yBAAO,MAAP,mBAAU,MAAM;AAAA,cACf,KAAK;AAAA,cACL;AAAA,YACD;AAAA,UACD;AAAA,QACD;AACA;AAAA,MACD,KAAK;AACJ,YAAI,KAAK,YAAY;AACpB,cAAI;AACH,iBAAK,WAAW,KAAK,MAAM,KAAK;AAAA,UACjC,SAAS,OAAO;AACf,yBAAO,MAAP,mBAAU,MAAM;AAAA,cACf,KAAK;AAAA,cACL;AAAA,YACD;AAAA,UACD;AAAA,QACD;AACA;AAAA,IACF;AAAA,EACD;AAAA,EAEA,YACC,MACA,QACA,UACO;AACP,QACC,KAAK,gBAAgB;AAAA,IACrB,KAAK,gBAAgB,GACpB;AACD;AAAA,IACD;AAEA,SAAK,cAAc;AAGnB,QAAI,UAAU;AACb,WAAK,eAAe,MAAM,MAAM;AAAA,IACjC;AAGA,SAAK,cAAc;AAEnB,UAAM,aAAa;AAAA,MAClB,UAAU;AAAA,MACV,MAAM,QAAQ;AAAA,MACd,QAAQ,UAAU;AAAA,MAClB,MAAM;AAAA,MACN,QAAQ;AAAA,IACT;AAEA,SAAK,WAAW,SAAS,UAAU;AAAA,EACpC;AAAA;AAAA,EAGA,IAAI,aAAqB;AACxB,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,IAAI,aAAqB;AACxB,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,IAAI,WAAW,OAAe;AAC7B,QACC,UAAU,gBACV,UAAU,iBACV,UAAU,QACT;AACD,WAAK,cAAc;AAAA,IACpB;AAAA,EACD;AAAA,EAEA,IAAI,aAAqB;AACxB,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,IAAI,WAAmB;AACtB,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,IAAI,MAAc;AACjB,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,IAAI,SAA+C;AAClD,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,IAAI,OAAO,OAA6C;AACvD,SAAK,UAAU;AAAA,EAChB;AAAA,EAEA,IAAI,UAAgD;AACnD,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,IAAI,QAAQ,OAA6C;AACxD,SAAK,WAAW;AAAA,EACjB;AAAA,EAEA,IAAI,UAAgD;AACnD,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,IAAI,QAAQ,OAA6C;AACxD,SAAK,WAAW;AAAA,EACjB;AAAA,EAEA,IAAI,YAAkD;AACrD,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,IAAI,UAAU,OAA6C;AAC1D,SAAK,aAAa;AAAA,EACnB;AAAA,EAEA,KAAK,MAAoE;AAExE,QAAI,KAAK,gBAAgB,GAAG;AAE3B,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,QAAI,KAAK,gBAAgB,KAAK,KAAK,gBAAgB,GAAG;AAErD;AAAA,IACD;AAEA,QAAI,WAAW;AACf,QAAI;AAEJ,QAAI,OAAO,SAAS,UAAU;AAC7B,oBAAc;AAAA,IACf,WAAW,gBAAgB,aAAa;AACvC,iBAAW;AACX,oBAAc;AAAA,IACf,WAAW,YAAY,OAAO,IAAI,GAAG;AACpC,iBAAW;AAEX,YAAM,OAAO;AAEb,UAAI,KAAK,kBAAkB,mBAAmB;AAE7C,cAAM,QAAQ,IAAI;AAAA,UACjB,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,QACN;AACA,sBAAc,MAAM,OAAO;AAAA,UAC1B,MAAM;AAAA,UACN,MAAM,aAAa,MAAM;AAAA,QAC1B;AAAA,MACD,OAAO;AACN,sBAAc,KAAK,OAAO;AAAA,UACzB,KAAK;AAAA,UACL,KAAK,aAAa,KAAK;AAAA,QACxB;AAAA,MACD;AAAA,IACD,WAAW,gBAAgB,MAAM;AAChC,YAAM,IAAI,MAAM,gDAAgD;AAAA,IACjE,WAAW,OAAO,WAAW,eAAe,OAAO,SAAS,IAAI,GAAG;AAClE,iBAAW;AAEX,YAAM,MAAM;AAEZ,UAAI,IAAI,kBAAkB,mBAAmB;AAE5C,cAAM,QAAQ,IAAI;AAAA,UACjB,IAAI;AAAA,UACJ,IAAI;AAAA,UACJ,IAAI;AAAA,QACL;AACA,sBAAc,MAAM,OAAO;AAAA,UAC1B,MAAM;AAAA,UACN,MAAM,aAAa,MAAM;AAAA,QAC1B;AAAA,MACD,OAAO;AACN,sBAAc,IAAI,OAAO;AAAA,UACxB,IAAI;AAAA,UACJ,IAAI,aAAa,IAAI;AAAA,QACtB;AAAA,MACD;AAAA,IACD,OAAO;AACN,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACpC;AAGA,SAAK,cAAc,aAAa,QAAQ;AAAA,EACzC;AAAA,EAEA,MAAM,MAAe,QAAuB;AAC3C,SAAK,YAAY,MAAM,QAAQ,IAAI;AAAA,EACpC;AAAA,EAEA,iBACC,MACA,UACA,SACO;AACP,QAAI,OAAO,aAAa,YAAY;AACnC,UAAI,YAAY,KAAK,gBAAgB,IAAI,IAAI;AAC7C,UAAI,CAAC,WAAW;AACf,oBAAY,oBAAI,IAAI;AACpB,aAAK,gBAAgB,IAAI,MAAM,SAAS;AAAA,MACzC;AACA,gBAAU,IAAI,QAAQ;AAAA,IACvB;AAAA,EACD;AAAA,EAEA,oBACC,MACA,UACA,SACO;AACP,QAAI,OAAO,aAAa,YAAY;AACnC,YAAM,YAAY,KAAK,gBAAgB,IAAI,IAAI;AAC/C,UAAI,WAAW;AACd,kBAAU,OAAO,QAAQ;AAAA,MAC1B;AAAA,IACD;AAAA,EACD;AAAA,EAEA,cAAc,OAAqB;AAElC,WAAO;AAAA,EACR;AAAA,EAEA,OAAgB,aAAa;AAAA,EAC7B,OAAgB,OAAO;AAAA,EACvB,OAAgB,UAAU;AAAA,EAC1B,OAAgB,SAAS;AAAA,EAEhB,aAAa;AAAA,EACb,OAAO;AAAA,EACP,UAAU;AAAA,EACV,SAAS;AAAA;AAAA,EAGlB,KAAK,MAAY,MAAgB,IAAiC;AAEjE,QAAI,GAAI,IAAG,IAAI,MAAM,sCAAsC,CAAC;AAAA,EAC7D;AAAA,EAEA,KAAK,MAAY,MAAgB,IAAiC;AAEjE,QAAI,GAAI,IAAG,IAAI,MAAM,sCAAsC,CAAC;AAAA,EAC7D;AAAA;AAAA,EAGA,YAAkB;AAEjB,SAAK,cAAc;AACnB,SAAK,eAAe,MAAM,kBAAkB;AAE5C,UAAM,QAAQ;AAAA,MACb,UAAU;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,QAAQ;AAAA,IACT;AAEA,SAAK,WAAW,SAAS,KAAK;AAAA,EAC/B;AACD;;;AC3gBO,IAAM,SAAN,MAAa;AAAA,EACnB;AAAA;AAAA,EAGA,kBAIK,CAAC;AAAA;AAAA,EAGN,oBAIK,CAAC;AAAA,EAEN,IAAI,MAA0B;AAC7B,WAAO,KAAK,QAAQ;AAAA,EACrB;AAAA,EAEA,YAAY,QAAgB;AAC3B,SAAK,UAAU;AAAA,EAChB;AAAA,EAEA,QAAc;AAAA,EAEd;AAAA,EAEA,uBAA6B;AAxE9B;AAyEE,QAAI,KAAK,kBAAkB,WAAW,GAAG;AACxC;AAAA,IACD;AAEA,eAAK,QAAL,mBAAU,KAAK;AAAA,MACd,KAAK;AAAA,MACL,OAAO,KAAK,kBAAkB;AAAA,IAC/B;AAEA,UAAM,WAAW,KAAK;AACtB,SAAK,oBAAoB,CAAC;AAE1B,eAAW,EAAE,WAAW,WAAW,YAAY,KAAK,UAAU;AAC7D,WAAK,aAAa,WAAW,WAAW,WAAW;AAAA,IACpD;AAAA,EACD;AAAA,EAEA,WAAW;AAMV,eAAW,CAAC,UAAU,KAAK,KAAK,KAAK,QAAQ,QAAQ;AAEpD,iBAAW,SAAS,MAAM,iBAAiB;AAC1C,cAAM,QAAQ,OAAO,IAAI,oBAAoB,CAAC;AAAA,MAC/C;AACA,YAAM,kBAAkB,CAAC;AAOzB,iBAAW,SAAS,MAAM,YAAY;AAGrC,YAAI,CAAC,MAAM,GAAG,mBAAmB,GAAG;AACnC,gBAAM,GAAG,sBAAsB,KAAM,oBAAoB;AAAA,QAC1D;AAAA,MACD;AACA,YAAM,aAAa,CAAC;AAAA,IACrB;AAGA,SAAK,kBAAkB,CAAC;AAAA,EACzB;AAAA,EAEA,MAAM,2BACL,SACA,aACC;AA7HH;AA8HE,UAAM,QAAQ,KAAK,QAAQ,SAAS,OAAO;AAC3C,QAAI,CAAC,OAAO;AACX,YAAM,IAAI;AAAA,QACT,SAAS,OAAO;AAAA,MACjB;AAAA,IACD;AAEA,QAAI,MAAM,qBAAqB;AAC9B,YAAM,IAAI;AAAA,QACT,SAAS,OAAO;AAAA,MACjB;AAAA,IACD;AAEA,eAAK,QAAL,mBAAU,MAAM;AAAA,MACf,KAAK;AAAA,MACL;AAAA,MACA,UAAU,MAAM,oBAAoB;AAAA,IACrC;AAGA,UAAM,uBAAwC,CAAC;AAG/C,QAAI,6BAA6B;AACjC,QAAI,gBAAgB;AACpB,eAAW,EAAE,WAAW,UAAU,KAAK,MAAM,qBAAqB;AACjE,YAAM,eAAe,QAAQ,SAAS;AACtC,YAAM,OAAO,YAAY;AAAA,QACxB,CAAC,UACA,YAAY,MAAM,WAAW,SAAS,KACtC,YAAY,MAAM,WAAW,SAAS;AAAA,MACxC;AAEA,UAAI,CAAC,MAAM;AAIV,mBAAK,QAAL,mBAAU,KAAK;AAAA,UACd,KAAK;AAAA,UACL,WAAW;AAAA,QACZ;AAEA,aAAK,aAAa,WAAW,WAAW;AAAA,UACvC,KAAK;AAAA,UACL,KAAK;AAAA,YACJ,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,WAAW;AAAA,UACZ;AAAA,QACD,CAAC;AAED;AAAA,MACD,OAAO;AAEN,cAAM,UAAU;AAAA,UACf,KAAK;AAAA,UACL,KAAK;AAAA,QACN;AAKA,cAAM,mBAAmB,KAAK;AAAA,UAC7B;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,KAAK;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,UACA,KAAK;AAAA,UACL,KAAK;AAAA,UACL;AAAA,QACD,EACE,KAAK,MAAM;AAzMjB,cAAAC;AA2MM,gBAAMC,SAAQ,KAAK,QAAQ,SAAS,OAAO;AAC3C,cAAIA,QAAO;AACV,YAAAA,OAAM;AAAA,cACL;AAAA,cACA;AAAA,cACA,KAAK;AAAA,YACN;AAAA,UACD;AAEA,WAAAD,MAAA,KAAK,QAAL,gBAAAA,IAAU,KAAK;AAAA,YACd,KAAK;AAAA,YACL;AAAA,YACA,WAAW;AAAA,UACZ;AAAA,QACD,CAAC,EACA,MAAM,CAAC,QAAQ;AA1NrB,cAAAA;AA2NM,WAAAA,MAAA,KAAK,QAAL,gBAAAA,IAAU,MAAM;AAAA,YACf,KAAK;AAAA,YACL,WAAW;AAAA,YACX,OAAO,eAAe,GAAG;AAAA,UAC1B;AAGA,eAAK,aAAa,WAAW,WAAW;AAAA,YACvC,KAAK;AAAA,YACL,KAAK;AAAA,cACJ,MAAM;AAAA,cACN,QAAQ;AAAA,cACR,WAAW;AAAA,YACZ;AAAA,UACD,CAAC;AAAA,QACF,CAAC;AAEF,6BAAqB,KAAK,gBAAgB;AAC1C;AAAA,MACD;AAAA,IACD;AAGA,QAAI,6BAA6B;AACjC,eAAW,QAAQ,aAAa;AAC/B,YAAM,eAAe,QAAQ,KAAK,SAAS;AAC3C,YAAM,cAAc,MAAM,oBAAoB;AAAA,QAC7C,CAAC,QACA,YAAY,IAAI,WAAW,KAAK,SAAS,KACzC,YAAY,IAAI,WAAW,KAAK,SAAS;AAAA,MAC3C;AACA,UAAI,CAAC,aAAa;AACjB,mBAAK,QAAL,mBAAU,KAAK;AAAA,UACd,KAAK;AAAA,UACL,WAAW;AAAA,QACZ;AAEA,cAAM,UAAU;AAAA,UACf,KAAK;AAAA,UACL,KAAK;AAAA,QACN;AAKA,cAAM,mBAAmB,KAAK;AAAA,UAC7B;AAAA,UACA,KAAK;AAAA,UACL,KAAK;AAAA,UACL;AAAA,UACA,KAAK;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,UACA,KAAK;AAAA,UACL,KAAK;AAAA,UACL;AAAA,QACD,EACE,KAAK,CAAC,YAAY;AAIlB,kBAAQ,MAAM,KAAM,mBAAmB;AAAA,QACxC,CAAC,EACA,MAAM,CAAC,QAAQ;AA3RrB,cAAAA;AA4RM,WAAAA,MAAA,KAAK,QAAL,gBAAAA,IAAU,MAAM;AAAA,YACf,KAAK;AAAA,YACL,WAAW;AAAA,YACX,OAAO,eAAe,GAAG;AAAA,UAC1B;AAAA,QACD,CAAC;AAEF,6BAAqB,KAAK,gBAAgB;AAC1C;AAAA,MACD;AAAA,IACD;AAGA,UAAM,QAAQ,WAAW,oBAAoB;AAG7C,UAAM,sBAAsB;AAE5B,eAAK,QAAL,mBAAU,KAAK;AAAA,MACd,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,iBACL,SACA,WACA,WACA,cACA,oBACA,gBACA,yBACA,SACA,MACA,SACA,qBACkC;AA1UpC;AA2UE,eAAK,QAAL,mBAAU,MAAM;AAAA,MACf,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAEA,UAAM,UAAU,IAAI;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,CAAC,MAA4B,aAAsB;AAElD,cAAM,aACL,OAAO,SAAS,WACZ,IAAI,YAAY,EAAE,OAAO,IAAI,EAAE,SAChC;AAEJ,aAAK,aAAa,WAAW,WAAW;AAAA,UACvC,KAAK;AAAA,UACL,KAAK;AAAA,YACJ,MAAM;AAAA,YACN,QAAQ;AAAA,UACT;AAAA,QACD,CAAC;AAAA,MACF;AAAA,MACA,CAAC,MAAe,WAAoB;AAEnC,YAAI,CAAC,qBAAqB;AACzB,eAAK,aAAa,WAAW,WAAW;AAAA,YACvC,KAAK;AAAA,YACL,KAAK;AAAA,cACJ,MAAM,QAAQ;AAAA,cACd,QAAQ,UAAU;AAAA,cAClB,WAAW;AAAA,YACZ;AAAA,UACD,CAAC;AAAA,QACF;AAGA,cAAMC,SAAQ,KAAK,QAAQ,SAAS,OAAO;AAC3C,YAAIA,QAAO;AACV,UAAAA,OAAM,gBAAgB,WAAW,SAAS;AAC1C,UAAAA,OAAM,qBAAqB,WAAW,SAAS;AAAA,QAChD;AAGA,aAAK,sBAAsB,WAAW,SAAS;AAAA,MAChD;AAAA,IACD;AAGA,UAAM,QAAQ,KAAK,QAAQ,SAAS,OAAO;AAC3C,QAAI,CAAC,OAAO;AACX,YAAM,IAAI,MAAM,SAAS,OAAO,YAAY;AAAA,IAC7C;AAEA,UAAM,aAAa,WAAW,WAAW,OAAO;AAChD,SAAK,kBAAkB,WAAW,WAAW,OAAO;AAIpD,UAAM,KAAK,QAAQ,OAAO;AAAA,MACzB,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA,EAEA,kBACC,WACA,WACA,SACC;AACD,SAAK,gBAAgB,KAAK,EAAE,WAAW,WAAW,QAAQ,CAAC;AAAA,EAC5D;AAAA,EAEA,sBAAsB,WAAsB,WAAsB;AACjE,UAAM,QAAQ,KAAK,gBAAgB;AAAA,MAClC,CAAC,UACA,YAAY,MAAM,WAAW,SAAS,KACtC,YAAY,MAAM,WAAW,SAAS;AAAA,IACxC;AACA,QAAI,UAAU,IAAI;AACjB,WAAK,gBAAgB,OAAO,OAAO,CAAC;AAAA,IACrC;AAAA,EACD;AAAA,EAEA,gBACC,WACA,WAC0B;AApb5B;AAqbE,UAAM,QAAQ,KAAK,gBAAgB;AAAA,MAClC,CAACC,WACA,YAAYA,OAAM,WAAW,SAAS,KACtC,YAAYA,OAAM,WAAW,SAAS;AAAA,IACxC;AAEA,QAAI,CAAC,OAAO;AACX,iBAAK,QAAL,mBAAU,KAAK;AAAA,QACd,KAAK;AAAA,QACL,WAAW,QAAQ,SAAS;AAAA,MAC7B;AACA,aAAO;AAAA,IACR;AAEA,UAAM,QAAQ,KAAK,QAAQ,SAAS,MAAM,OAAO;AACjD,QAAI,CAAC,OAAO;AACX,iBAAK,QAAL,mBAAU,KAAK;AAAA,QACd,KAAK;AAAA,QACL,WAAW,QAAQ,SAAS;AAAA,QAC5B,SAAS,MAAM;AAAA,MAChB;AACA,aAAO;AAAA,IACR;AAEA,WAAO;AAAA,EACR;AAAA,EAEA,MAAM,0BACL,WACA,WACmC;AACnC,UAAM,QAAQ,KAAK,gBAAgB,WAAW,SAAS;AACvD,QAAI,CAAC,MAAO;AACZ,UAAM,MAAM,kBAAkB;AAC9B,WAAO;AAAA,EACR;AAAA,EAEA,aACC,WACA,WACA,aACC;AA9dH;AAgeE,QAAI,CAAC,KAAK,QAAQ,iBAAiB,GAAG;AACrC,iBAAK,QAAL,mBAAU,MAAM;AAAA,QACf,KAAK;AAAA,QACL,WAAW,QAAQ,SAAS;AAAA,QAC5B,SAAS,mCAAmC,WAAW;AAAA,MACxD;AACA,WAAK,kBAAkB,KAAK,EAAE,WAAW,WAAW,YAAY,CAAC;AACjE;AAAA,IACD;AAMA,UAAM,eAAe,QAAQ,SAAS;AACtC,UAAM,eAAe,QAAQ,SAAS;AACtC,UAAM,QAAQ,KAAK,gBAAgB,WAAW,SAAS;AACvD,QAAI,CAAC,OAAO;AACX,iBAAK,QAAL,mBAAU,KAAK;AAAA,QACd,KAAK;AAAA,QACL,WAAW;AAAA,QACX,WAAW;AAAA,MACZ;AACA;AAAA,IACD;AAGA,QAAI;AACJ,UAAM,UAAU,MAAM,kBAAkB,WAAW,SAAS;AAC5D,QAAI,SAAS;AACZ,2BAAqB,QAAQ;AAC7B,cAAQ;AAAA,IACT,OAAO;AAEN,iBAAK,QAAL,mBAAU,KAAK;AAAA,QACd,KAAK;AAAA,QACL,WAAW;AAAA,QACX,WAAW;AAAA,MACZ;AACA,2BAAqB;AAAA,IACtB;AAGA,UAAM,YAAgC;AAAA,MACrC;AAAA,MACA;AAAA,MACA,cAAc;AAAA,IACf;AACA,UAAM,eAAe,GAAG,QAAQ,UAAU,SAAS,CAAC,IAAI,QAAQ,UAAU,SAAS,CAAC,IAAI,UAAU,YAAY;AAE9G,eAAK,QAAL,mBAAU,MAAM;AAAA,MACf,KAAK;AAAA,MACL,WAAW;AAAA,MACX,WAAW;AAAA,MACX,WAAW;AAAA,MACX,cAAc;AAAA,MACd,SAAS,mCAAmC,WAAW;AAAA,IACxD;AAGA,UAAM,UAA6B;AAAA,MAClC,KAAK;AAAA,MACL,KAAK;AAAA,QACJ;AAAA,QACA;AAAA,MACD;AAAA,IACD;AACA,SAAK,QAAQ,eAAe,OAAO;AAAA,EACpC;AAAA,EAEA,oBAAoB,OAAoB;AACvC,UAAM,UAAU,MAAM;AAKtB,eAAW,SAAS,MAAM,iBAAiB;AAC1C,YAAM,QAAQ,OAAO,IAAI,MAAM,SAAS,OAAO,UAAU,CAAC;AAC1D,UAAI,MAAM,aAAa,MAAM,WAAW;AACvC,aAAK,sBAAsB,MAAM,WAAW,MAAM,SAAS;AAAA,MAC5D;AAAA,IACD;AAIA,eAAW,SAAS,MAAM,YAAY;AACrC,YAAM,iBAAiB,MAAM,GAAG,mBAAmB;AACnD,UAAI,CAAC,gBAAgB;AACpB,cAAM,GAAG,sBAAsB,KAAM,eAAe;AAAA,MACrD;AAAA,IAED;AAAA,EACD;AAAA,EAEA,MAAM,OACL,SACA,WACA,WACA,SACoB;AAnkBtB;AAqkBE,QAAI,CAAC,KAAK,QAAQ,SAAS,OAAO,GAAG;AACpC,iBAAK,QAAL,mBAAU,KAAK;AAAA,QACd,KAAK;AAAA,QACL;AAAA,MACD;AAMA,aAAO,IAAI,SAAS,mBAAmB;AAAA,QACtC,QAAQ;AAAA,QACR,SAAS,EAAE,iBAAiB,yBAAyB;AAAA,MACtD,CAAC;AAAA,IACF;AAEA,UAAM,eAAe,KAAK,QAAQ,OAAO;AAAA,MACxC,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAEA,QAAI,CAAC,cAAc;AAClB,aAAO,IAAI,SAAS,mBAAmB,EAAE,QAAQ,IAAI,CAAC;AAAA,IACvD;AAEA,WAAO;AAAA,EACR;AAAA,EAEA,MAAM,oBAAoB,SAAyC;AApmBpE;AAsmBE,UAAM,EAAE,WAAW,WAAW,aAAa,IAAI,QAAQ;AAEvD,UAAM,eAAe,QAAQ,SAAS;AACtC,UAAM,eAAe,QAAQ,SAAS;AACtC,eAAK,QAAL,mBAAU,MAAM;AAAA,MACf,KAAK;AAAA,MACL,WAAW;AAAA,MACX,WAAW;AAAA,MACX,cAAc,QAAQ,UAAU;AAAA,MAChC,SAAS,mCAAmC,QAAQ,WAAW;AAAA,IAChE;AAEA,YAAQ,QAAQ,YAAY,KAAK;AAAA,MAChC,KAAK;AACJ,cAAM,KAAK;AAAA,UACV;AAAA,UACA;AAAA,UACA,QAAQ,YAAY;AAAA,QACrB;AACA;AAAA,MACD,KAAK;AACJ,cAAM,KAAK;AAAA,UACV;AAAA,UACA;AAAA,UACA,QAAQ,YAAY;AAAA,QACrB;AACA;AAAA,MACD,KAAK;AACJ,cAAM,KAAK,oBAAoB,WAAW,SAAS;AACnD;AAAA,MACD,KAAK;AACJ,cAAM,KAAK;AAAA,UACV;AAAA,UACA;AAAA,UACA,QAAQ,YAAY;AAAA,QACrB;AACA;AAAA,MACD,KAAK,4BAA4B;AAChC,cAAM,KAAK;AAAA,UACV;AAAA,UACA;AAAA,UACA;AAAA,UACA,QAAQ,YAAY;AAAA,QACrB;AACA;AAAA,MACD;AAAA,MACA,KAAK;AACJ,cAAM,KAAK;AAAA,UACV;AAAA,UACA;AAAA,UACA,QAAQ,YAAY;AAAA,QACrB;AACA;AAAA,MACD;AACC,oBAAY,QAAQ,WAAW;AAAA,IACjC;AAAA,EACD;AAAA,EAEA,MAAM,oBACL,WACA,WACA,KACC;AApqBH;AAsqBE,UAAM,eAAe,QAAQ,SAAS;AACtC,UAAM,QAAQ,MAAM,KAAK,QAAQ,mBAAmB,IAAI,OAAO;AAC/D,QAAI,CAAC,OAAO;AACX,iBAAK,QAAL,mBAAU,KAAK;AAAA,QACd,KAAK;AAAA,QACL,SAAS,IAAI;AAAA,QACb,WAAW;AAAA,MACZ;AACA;AAAA,IACD;AAGA,SAAK,kBAAkB,WAAW,WAAW,IAAI,OAAO;AAExD,QAAI;AAEH,YAAM,UAAU,IAAI,QAAQ;AAC5B,iBAAW,CAAC,KAAK,KAAK,KAAK,IAAI,SAAS;AACvC,gBAAQ,OAAO,KAAK,KAAK;AAAA,MAC1B;AAGA,YAAM,UAAU,IAAI,QAAQ,mBAAmB,IAAI,IAAI,IAAI;AAAA,QAC1D,QAAQ,IAAI;AAAA,QACZ;AAAA,QACA,MAAM,IAAI,OAAO,IAAI,WAAW,IAAI,IAAI,IAAI;AAAA,MAC7C,CAAC;AAGD,UAAI,IAAI,QAAQ;AAEf,cAAM,SAAS,IAAI,eAA2B;AAAA,UAC7C,OAAO,CAAC,eAAe;AAEtB,kBAAM,WAAW,MAAM;AAAA,cACtB;AAAA,cACA;AAAA,YACD;AACA,gBAAI,UAAU;AACb,uBAAS,mBAAmB;AAC5B,uBAAS,UAAU,IAAI;AACvB,uBAAS,YAAY;AACrB,uBAAS,YAAY;AAAA,YACtB,OAAO;AACN,oBAAM;AAAA,gBACL;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,cACD;AAAA,YACD;AAAA,UACD;AAAA,QACD,CAAC;AAGD,cAAM,mBAAmB,IAAI,QAAQ,SAAS;AAAA,UAC7C,MAAM;AAAA,UACN,QAAQ;AAAA,QACT,CAAQ;AAGR,cAAM,WAAW,MAAM,KAAK;AAAA,UAC3B,IAAI;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,QACD;AACA,cAAM,KAAK;AAAA,UACV,MAAM;AAAA,UACN,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA;AAAA,QACD;AAAA,MACD,OAAO;AAGN,cAAM,qBAAqB,WAAW,WAAW,CAAC;AAElD,cAAM,WAAW,MAAM,KAAK;AAAA,UAC3B,IAAI;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,QACD;AACA,cAAM,KAAK;AAAA,UACV,MAAM;AAAA,UACN,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA;AAAA,QACD;AAAA,MACD;AAAA,IACD,SAAS,OAAO;AACf,UAAI,iBAAiB,qBAAqB;AACzC,mBAAK,QAAL,mBAAU,MAAM,EAAE,KAAK,gCAAgC;AAAA,MACxD,OAAO;AACN,mBAAK,QAAL,mBAAU,MAAM,EAAE,KAAK,0BAA0B,MAAM;AACvD,aAAK;AAAA,UACJ,MAAM;AAAA,UACN,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACD;AAAA,MACD;AAAA,IACD,UAAE;AAED,UAAI,KAAK,QAAQ,SAAS,IAAI,SAAS,MAAM,UAAU,GAAG;AACzD,cAAM,qBAAqB,WAAW,SAAS;AAC/C,aAAK,sBAAsB,WAAW,SAAS;AAAA,MAChD;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM,oBACL,WACA,WACA,OACC;AACD,UAAM,QAAQ,MAAM,KAAK;AAAA,MACxB;AAAA,MACA;AAAA,IACD;AACA,QAAI,OAAO;AACV,YAAM,UAAU,MAAM,kBAAkB,WAAW,SAAS;AAC5D,UAAI,mCAAS,kBAAkB;AAC9B,gBAAQ,iBAAiB,QAAQ,IAAI,WAAW,MAAM,IAAI,CAAC;AAC3D,YAAI,MAAM,QAAQ;AACjB,kBAAQ,iBAAiB,MAAM;AAC/B,gBAAM,qBAAqB,WAAW,SAAS;AAC/C,eAAK,sBAAsB,WAAW,SAAS;AAAA,QAChD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM,oBAAoB,WAAsB,WAAsB;AACrE,UAAM,QAAQ,MAAM,KAAK;AAAA,MACxB;AAAA,MACA;AAAA,IACD;AACA,QAAI,OAAO;AACV,YAAM,UAAU,MAAM,kBAAkB,WAAW,SAAS;AAC5D,UAAI,mCAAS,kBAAkB;AAC9B,gBAAQ,iBAAiB,MAAM,IAAI,MAAM,iBAAiB,CAAC;AAAA,MAC5D;AACA,YAAM,qBAAqB,WAAW,SAAS;AAC/C,WAAK,sBAAsB,WAAW,SAAS;AAAA,IAChD;AAAA,EACD;AAAA,EAEA,MAAM,cACL,SACA,YACA,WACA,WACA,UACC;AAr0BH;AAs0BE,QAAI,CAAC,KAAK,QAAQ,SAAS,SAAS,UAAU,GAAG;AAChD,iBAAK,QAAL,mBAAU,KAAK;AAAA,QACd,KAAK;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,MACD;AACA;AAAA,IACD;AASA,UAAM,OAAO,SAAS,OAAO,MAAM,SAAS,YAAY,IAAI;AAG5D,UAAM,UAAU,oBAAI,IAAoB;AACxC,aAAS,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AACxC,cAAQ,IAAI,KAAK,KAAK;AAAA,IACvB,CAAC;AAGD,QAAI,QAAQ,CAAC,QAAQ,IAAI,gBAAgB,GAAG;AAC3C,cAAQ,IAAI,kBAAkB,OAAO,KAAK,UAAU,CAAC;AAAA,IACtD;AAGA,SAAK,aAAa,WAAW,WAAW;AAAA,MACvC,KAAK;AAAA,MACL,KAAK;AAAA,QACJ,QAAQ,SAAS;AAAA,QACjB;AAAA,QACA,MAAM,QAAQ;AAAA,QACd,QAAQ;AAAA,MACT;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EAEA,mBACC,SACA,YACA,WACA,WACA,QACA,SACC;AAv3BH;AAw3BE,QAAI,CAAC,KAAK,QAAQ,SAAS,SAAS,UAAU,GAAG;AAChD,iBAAK,QAAL,mBAAU,KAAK;AAAA,QACd,KAAK;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,MACD;AACA;AAAA,IACD;AAEA,UAAM,UAAU,oBAAI,IAAoB;AACxC,YAAQ,IAAI,gBAAgB,YAAY;AAExC,SAAK,aAAa,WAAW,WAAW;AAAA,MACvC,KAAK;AAAA,MACL,KAAK;AAAA,QACJ;AAAA,QACA;AAAA,QACA,MAAM,IAAI,YAAY,EAAE,OAAO,OAAO,EAAE;AAAA,QACxC,QAAQ;AAAA,MACT;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EAEA,MAAM,qBACL,WACA,WACA,MACC;AAp5BH;AA25BE,UAAM,eAAe,QAAQ,SAAS;AAGtC,UAAM,QAAQ,MAAM,KAAK,QAAQ,mBAAmB,KAAK,OAAO;AAChE,QAAI,CAAC,OAAO;AACX,iBAAK,QAAL,mBAAU,KAAK;AAAA,QACd,KAAK;AAAA,QACL,SAAS,KAAK;AAAA,MACf;AAOA,WAAK,aAAa,WAAW,WAAW;AAAA,QACvC,KAAK;AAAA,QACL,KAAK;AAAA,UACJ,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,WAAW;AAAA,QACZ;AAAA,MACD,CAAC;AACD;AAAA,IACD;AAKA,UAAM,kBAAkB,MAAM,aAAa,WAAW,SAAS;AAC/D,QAAI,iBAAiB;AACpB,iBAAK,QAAL,mBAAU,KAAK;AAAA,QACd,KAAK;AAAA,QACL,WAAW;AAAA,MACZ;AAGA,sBAAgB,sBAAsB,KAAM,mBAAmB;AAAA,IAChE;AAGA,QAAI;AACH,YAAM,UAAU;AAAA,QACf,KAAK;AAAA,QACL,OAAO,YAAY,KAAK,OAAO;AAAA,MAChC;AAEA,YAAM,eACL,KAAK,QAAQ,OAAO,sBAAsB;AAAA,QACzC,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAMD,YAAM,UAAU,MAAM,KAAK;AAAA,QAC1B,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK;AAAA,QACL,OAAO,YAAY,KAAK,OAAO;AAAA,QAC/B;AAAA,MACD;AAGA,YAAM,qBAAqB,WAAW,WAAW,CAAC;AAKlD,WAAK,aAAa,WAAW,WAAW;AAAA,QACvC,KAAK;AAAA,QACL,KAAK;AAAA,UACJ;AAAA,QACD;AAAA,MACD,CAAC;AAGD,cAAQ,YAAY,SAAS;AAAA,IAC9B,SAAS,OAAO;AACf,iBAAK,QAAL,mBAAU,MAAM,EAAE,KAAK,iCAAiC,MAAM;AAK9D,WAAK,aAAa,WAAW,WAAW;AAAA,QACvC,KAAK;AAAA,QACL,KAAK;AAAA,UACJ,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,WAAW;AAAA,QACZ;AAAA,MACD,CAAC;AAGD,YAAM,gBAAgB,WAAW,SAAS;AAC1C,YAAM,qBAAqB,WAAW,SAAS;AAC/C,WAAK,sBAAsB,WAAW,SAAS;AAAA,IAChD;AAAA,EACD;AAAA,EAEA,MAAM,wBACL,WACA,WACA,oBACA,KACC;AA9gCH;AA+gCE,UAAM,QAAQ,MAAM,KAAK;AAAA,MACxB;AAAA,MACA;AAAA,IACD;AACA,QAAI,OAAO;AACV,YAAM,UAAU,MAAM,aAAa,WAAW,SAAS;AACvD,UAAI,SAAS;AACZ,cAAM,OAAO,IAAI,SACd,IAAI,WAAW,IAAI,IAAI,IACvB,IAAI,YAAY,EAAE,OAAO,IAAI,WAAW,IAAI,IAAI,CAAC;AAEpD,gBAAQ;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA,IAAI;AAAA,QACL;AACA;AAAA,MACD;AAAA,IACD;AAGA,eAAK,QAAL,mBAAU,KAAK;AAAA,MACd,KAAK;AAAA,MACL;AAAA,IACD;AAAA,EACD;AAAA,EAEA,oCACC,WACA,WACA,oBACC;AA/iCH;AAgjCE,UAAM,eAAe,QAAQ,SAAS;AAEtC,eAAK,QAAL,mBAAU,MAAM;AAAA,MACf,KAAK;AAAA,MACL,WAAW;AAAA,MACX,OAAO;AAAA,IACR;AAEA,QAAI,qBAAqB,KAAK,qBAAqB;AAClD,YAAM,IAAI,MAAM,6BAA6B;AAM9C,UAAM,QAAQ,KAAK,gBAAgB,WAAW,SAAS;AACvD,QAAI,CAAC,OAAO;AACX,iBAAK,QAAL,mBAAU,KAAK;AAAA,QACd,KAAK;AAAA,QACL,WAAW;AAAA,MACZ;AACA;AAAA,IACD;AAGA,UAAM,UAAU,MAAM,kBAAkB,WAAW,SAAS;AAC5D,QAAI,EAAC,mCAAS,YAAW;AACxB,iBAAK,QAAL,mBAAU,KAAK;AAAA,QACd,KAAK;AAAA,QACL,WAAW;AAAA,MACZ;AACA;AAAA,IACD;AAGA,SAAK,aAAa,QAAQ,WAAW,WAAW;AAAA,MAC/C,KAAK;AAAA,MACL,KAAK;AAAA,QACJ,OAAO;AAAA,MACR;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EAEA,MAAM,sBACL,WACA,WACA,OACC;AACD,UAAM,QAAQ,MAAM,KAAK;AAAA,MACxB;AAAA,MACA;AAAA,IACD;AACA,QAAI,OAAO;AACV,YAAM,UAAU,MAAM,aAAa,WAAW,SAAS;AACvD,UAAI,SAAS;AAEZ,gBAAQ;AAAA,UACP;AAAA,UACA,MAAM,QAAQ;AAAA,UACd,MAAM,UAAU;AAAA,QACjB;AACA,cAAM,gBAAgB,WAAW,SAAS;AAC1C,cAAM,qBAAqB,WAAW,SAAS;AAC/C,aAAK,sBAAsB,WAAW,SAAS;AAAA,MAChD;AAAA,IACD;AAAA,EACD;AACD;AAOA,SAAS,yBACR,MACA,SACU;AAGV,QAAM,cAAc;AAAA,IACnB,GAAG;AAAA,IACH,SAAS;AAAA,IACT,YAAY;AAAA,EACb;AAEA,MAAI,CAAC,KAAK,WAAW,GAAG,GAAG;AAC1B,UAAM,IAAI,MAAM,oCAAoC;AAAA,EACrD;AAEA,QAAM,UAAU,IAAI,QAAQ,eAAe,IAAI,IAAI;AAAA,IAClD,QAAQ;AAAA,IACR,SAAS;AAAA,EACV,CAAC;AAED,SAAO;AACR;;;AC7oCA,IAAI,mBAAqD;AAEzD,eAAsB,kBAA6C;AAElE,MAAI,qBAAqB,MAAM;AAC9B,WAAO;AAAA,EACR;AAGA,sBAAoB,YAAY;AAZjC;AAaE,QAAI;AAEJ,QAAI,OAAO,cAAc,aAAa;AAErC,mBAAa;AACb,mBAAO,MAAP,mBAAU,MAAM,EAAE,KAAK,yBAAyB;AAAA,IACjD,OAAO;AAEN,UAAI;AACH,cAAM,KAAK,MAAM,OAAO,IAAI;AAC5B,qBAAa,GAAG;AAChB,qBAAO,MAAP,mBAAU,MAAM,EAAE,KAAK,2BAA2B;AAAA,MACnD,QAAQ;AAEP,qBAAa,MAAM,cAAc;AAAA,UAChC,cAAc;AACb,kBAAM,IAAI;AAAA,cACT;AAAA,YACD;AAAA,UACD;AAAA,QACD;AACA,qBAAO,MAAP,mBAAU,MAAM,EAAE,KAAK,uBAAuB;AAAA,MAC/C;AAAA,IACD;AAEA,WAAO;AAAA,EACR,GAAG;AAEH,SAAO;AACR;;;APvBA,IAAM,YAAoB;AAC1B,IAAM,mBAA2B;AAGjC,IAAM,+BAA+B;AACrC,IAAM,kBAAkD,CAAC;AAElD,IAAM,sBAAN,cAAkC,MAAM;AAAA,EAC9C,cAAc;AACb,UAAM,kBAAkB;AAAA,EACzB;AACD;AAmKO,IAAM,SAAN,MAAa;AAAA,EACnB;AAAA,EAEA,IAAI,SAAuB;AAC1B,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,UAAoC,oBAAI,IAAI;AAAA;AAAA,EAG5C;AAAA,EACA;AAAA,EACA,WAAoB;AAAA,EACpB,YAAqB;AAAA,EACrB,gBAAyB;AAAA,EACzB,oBAA4B;AAAA,EAC5B;AAAA;AAAA,EAGA;AAAA,EACA;AAAA;AAAA,EAGA,sBAA+B;AAAA;AAAA,EAG/B;AAAA;AAAA,EAGA,mBAA2B;AAAA,EAC3B,cAA2C,oBAAI,IAAI;AAAA,EACnD;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA,EAEA,IAAI,MAA0B;AAC7B,QAAI,KAAK,WAAY,QAAO,KAAK;AAEjC,UAAM,IAAI,OAAO;AACjB,QAAI,GAAG;AAIN,UAAI,KAAK,UAAU;AAClB,aAAK,aAAa,EAAE,MAAM;AAAA,UACzB,UAAU,KAAK;AAAA,QAChB,CAAC;AACD,eAAO,KAAK;AAAA,MACb,OAAO;AACN,eAAO;AAAA,MACR;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA,EAEA,YAAY,QAAsB;AACjC,SAAK,UAAU;AACf,QAAI,KAAK,QAAQ,OAAQ,WAAU,KAAK,QAAQ,MAAM;AAGtD,SAAK,qBAAqB,YAAY,MAAM;AAlQ9C;AAmQG,UAAI;AACH,aAAK,sBAAsB;AAAA,MAC5B,SAAS,KAAK;AACb,mBAAK,QAAL,mBAAU,MAAM;AAAA,UACf,KAAK;AAAA,UACL,OAAO,eAAe,GAAG;AAAA,QAC1B;AAAA,MACD;AAAA,IACD,GAAG,IAAK;AAAA,EACT;AAAA;AAAA,EAGA,WAAW,SAAiB,YAAqB;AAChD,UAAM,QAAQ,KAAK,SAAS,SAAS,UAAU;AAC/C,QAAI,CAAC,MAAO;AAGZ,SAAK,iBAAiB,SAAS,MAAM,YAAY,OAAO;AAAA,EAIzD;AAAA,EAEA,MAAM,UAAU,SAAiB,YAAqB;AACrD,UAAM,QAAQ,KAAK,SAAS,SAAS,UAAU;AAC/C,QAAI,CAAC,MAAO;AAEZ,SAAK,iBAAiB,SAAS,MAAM,YAAY,MAAM;AAAA,EAIxD;AAAA,EAEA,MAAM,eAAe,SAAiB,YAAqB;AApS5D;AAqSE,eAAK,QAAL,mBAAU,MAAM;AAAA,MACf,KAAK;AAAA,MACL;AAAA,IACD;AAEA,UAAM,QAAQ,KAAK,SAAS,SAAS,UAAU;AAC/C,QAAI,CAAC,MAAO;AAOZ,QAAI;AACH,YAAM,KAAK,QAAQ,YAAY,SAAS,MAAM,UAAU;AAAA,IACzD,SAAS,KAAK;AACb,cAAQ,MAAM,kCAAkC,OAAO,KAAK,GAAG;AAAA,IAChE;AAGA,eAAK,YAAL,mBAAc,oBAAoB;AAElC,SAAK,sBAAsB,SAAS,MAAM,YAAY,SAAS;AAI/D,SAAK,aAAa,SAAS,UAAU;AAAA,EACtC;AAAA,EAEA,cAAc;AAlUf;AAmUE,eAAK,QAAL,mBAAU,KAAK;AAAA,MACd,KAAK;AAAA,IACN;AAGA,eAAW,CAAC,GAAG,OAAO,KAAK,KAAK,YAAY,QAAQ,GAAG;AACtD,cAAQ,OAAO,IAAI,oBAAoB,CAAC;AAAA,IACzC;AAEA,SAAK,YAAY,MAAM;AAEvB,SAAK,eAAe;AAAA,EACrB;AAAA,EAEA,iBAAiB;AAChB,UAAM,WAAW,MAAM,KAAK,KAAK,QAAQ,KAAK,CAAC;AAC/C,eAAW,WAAW,UAAU;AAC/B,WAAK,eAAe,OAAO,EAAE,MAAM,CAAC,QAAQ;AApV/C;AAqVI,mBAAK,QAAL,mBAAU,MAAM;AAAA,UACf,KAAK;AAAA,UACL;AAAA,UACA,OAAO,eAAe,GAAG;AAAA,QAC1B;AAAA,MACD,CAAC;AAAA,IACF;AAAA,EACD;AAAA,EAEA,SAAS,SAAiB,YAA8C;AA9VzE;AA+VE,UAAM,QAAQ,KAAK,QAAQ,IAAI,OAAO;AACtC,QAAI,CAAC,OAAO;AACX,iBAAK,QAAL,mBAAU,KAAK;AAAA,QACd,KAAK;AAAA,QACL;AAAA,MACD;AACA,aAAO;AAAA,IACR;AACA,QAAI,eAAe,UAAa,MAAM,eAAe,YAAY;AAChE,iBAAK,QAAL,mBAAU,KAAK;AAAA,QACd,KAAK;AAAA,QACL;AAAA,QACA;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAEA,WAAO;AAAA,EACR;AAAA,EAEA,MAAM,mBACL,SACA,YACmC;AACnC,UAAM,QAAQ,KAAK,SAAS,SAAS,UAAU;AAC/C,QAAI,CAAC,MAAO;AACZ,UAAM,MAAM,kBAAkB;AAC9B,WAAO;AAAA,EACR;AAAA,EAEA,SAAS,SAAiB,YAA8B;AACvD,UAAM,QAAQ,KAAK,QAAQ,IAAI,OAAO;AAEtC,WACC,CAAC,CAAC,UACD,eAAe,UAAa,MAAM,eAAe;AAAA,EAEpD;AAAA,EAEA,IAAI,SAAS;AACZ,WAAO,KAAK;AAAA,EACb;AAAA;AAAA,EAGA,aACC,SACA,YAC0B;AA9Y5B;AA+YE,UAAM,QAAQ,KAAK,QAAQ,IAAI,OAAO;AACtC,QAAI,CAAC,OAAO;AACX,iBAAK,QAAL,mBAAU,MAAM;AAAA,QACf,KAAK;AAAA,QACL;AAAA,MACD;AACA,aAAO;AAAA,IACR;AACA,QAAI,eAAe,UAAa,MAAM,eAAe,YAAY;AAChE,iBAAK,QAAL,mBAAU,MAAM;AAAA,QACf,KAAK;AAAA,QACL;AAAA,QACA;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAEA,SAAK,QAAQ,OAAO,OAAO;AAE3B,eAAK,QAAL,mBAAU,KAAK;AAAA,MACd,KAAK;AAAA,MACL;AAAA,MACA,QAAQ,KAAK,QAAQ;AAAA,IACtB;AAEA,WAAO;AAAA,EACR;AAAA;AAAA,EAGA,MAAM,QAAQ;AA5af;AA6aE,QAAI,KAAK,SAAU,OAAM,IAAI,MAAM,gCAAgC;AACnE,SAAK,WAAW;AAEhB,eAAK,QAAL,mBAAU,KAAK,EAAE,KAAK,kBAAkB;AAExC,SAAK,UAAU,IAAI,OAAO,IAAI;AAC9B,SAAK,QAAQ,MAAM;AAEnB,QAAI;AACH,YAAM,KAAK,uBAAuB;AAAA,IACnC,SAAS,OAAO;AACf,WAAK,WAAW;AAChB,YAAM;AAAA,IACP;AAEA,QAAI,CAAC,KAAK,QAAQ,gBAAgB;AACjC,UAAI,CAAC,gBAAgB,QAAQ;AAC5B,gBAAQ,GAAG,WAAW,YAAY;AA9btC,cAAAC;AA+bK,WAAAA,MAAA,KAAK,QAAL,gBAAAA,IAAU,MAAM;AAEhB,qBAAW,WAAW,iBAAiB;AACtC,kBAAM,QAAQ;AAAA,UACf;AAAA,QAID,CAAC;AACD,gBAAQ,GAAG,UAAU,YAAY;AAxcrC,cAAAA;AAycK,WAAAA,MAAA,KAAK,QAAL,gBAAAA,IAAU,MAAM;AAEhB,qBAAW,WAAW,iBAAiB;AACtC,kBAAM,QAAQ;AAAA,UACf;AAAA,QAID,CAAC;AAED,mBAAK,QAAL,mBAAU,MAAM;AAAA,UACf,KAAK;AAAA,QACN;AAAA,MACD;AAEA,sBAAgB,KAAK,YAAY;AAxdpC,YAAAA;AAydI,cAAM,OAAO,IAAI,QAAQ,IAAI;AAC7B,gBAAMA,MAAA,KAAK,MAAM,MAAX,gBAAAA,IAAc,SAAS,OAAO;AAAA,MACrC,CAAC;AAAA,IACF;AAAA,EACD;AAAA;AAAA,EAGA,MAAM,SAAS,WAAoB,OAAgB,OAAO;AAhe3D;AAkeE,QAAI,KAAK,eAAe;AACvB,iBAAK,QAAL,mBAAU,MAAM;AAAA,QACf,KAAK;AAAA,MACN;AACA;AAAA,IACD;AACA,SAAK,gBAAgB;AAErB,eAAK,QAAL,mBAAU,KAAK;AAAA,MACd,KAAK;AAAA,MACL;AAAA,MACA;AAAA,IACD;AACA,SAAK,YAAY;AAGjB,QAAI,KAAK,mBAAmB;AAC3B,mBAAa,KAAK,iBAAiB;AACnC,WAAK,oBAAoB;AAAA,IAC1B;AAGA,QAAI,KAAK,oBAAoB;AAC5B,mBAAa,KAAK,kBAAkB;AACpC,WAAK,qBAAqB;AAAA,IAC3B;AAGA,QAAI,KAAK,cAAc;AACtB,oBAAc,KAAK,YAAY;AAC/B,WAAK,eAAe;AAAA,IACrB;AAGA,QAAI,KAAK,oBAAoB;AAC5B,oBAAc,KAAK,kBAAkB;AACrC,WAAK,qBAAqB;AAAA,IAC3B;AAGA,eAAW,WAAW,KAAK,YAAY,OAAO,GAAG;AAChD,cAAQ;AAAA,QACP,IAAI,MAAM,6CAA6C;AAAA,MACxD;AAAA,IACD;AACA,SAAK,YAAY,MAAM;AAGvB,QAAI,KAAK,iBAAiB,GAAG;AAC5B,YAAM,oBAAoB,KAAK;AAC/B,UAAI,WAAW;AAEd,0BAAkB,MAAM,KAAM,0BAA0B;AAAA,MACzD,OAAO;AAEN,YAAI;AACH,qBAAK,QAAL,mBAAU,KAAK;AAAA,YACd,KAAK;AAAA,YACL,YAAY,kBAAkB;AAAA,UAC/B;AAMA,eAAK,eAAe;AAAA,YACnB,KAAK;AAAA,YACL,KAAK;AAAA,UACN,CAAC;AAED,gBAAM,eAAe,IAAI,QAAc,CAAC,YAAY;AACnD,gBAAI,CAAC;AACJ,oBAAM,IAAI,MAAM,2BAA2B;AAE5C,8BAAkB,iBAAiB,SAAS,CAAC,OAAO;AA5iB1D,kBAAAA;AA6iBO,eAAAA,MAAA,KAAK,QAAL,gBAAAA,IAAU,KAAK;AAAA,gBACd,KAAK;AAAA,gBACL,MAAM,GAAG;AAAA,gBACT,QAAQ,GAAG,OAAO,SAAS;AAAA,cAC5B;AACA,sBAAQ;AAAA,YACT,CAAC;AAAA,UACF,CAAC;AAGD,gBAAM,KAAK,qBAAqB,iBAAiB;AAEjD,qBAAK,QAAL,mBAAU,KAAK;AAAA,YACd,KAAK;AAAA,UACN;AACA,4BAAkB,MAAM,KAAM,0BAA0B;AAExD,gBAAM;AAEN,qBAAK,QAAL,mBAAU,KAAK;AAAA,YACd,KAAK;AAAA,UACN;AAAA,QACD,SAAS,OAAO;AACf,qBAAK,QAAL,mBAAU,MAAM;AAAA,YACf,KAAK;AAAA,YACL;AAAA,UACD;AACA,4BAAkB,MAAM;AAAA,QACzB;AAAA,MACD;AAAA,IACD,OAAO;AAGN,iBAAK,QAAL,mBAAU,MAAM;AAAA,QACf,KAAK;AAAA,QACL,aAAY,UAAK,wBAAL,mBAA0B;AAAA,MACvC;AAAA,IACD;AAGA,QAAI,KAAK,SAAS;AACjB,WAAK,QAAQ,SAAS;AACtB,WAAK,UAAU;AAAA,IAChB;AAEA,SAAK,QAAQ,WAAW;AAExB,QAAI,KAAM,SAAQ,KAAK,CAAC;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,qBAAqB,IAA8B;AACxD,UAAM,kBAAkB;AACxB,UAAM,wBAAwB;AAC9B,UAAM,sBAAsB;AAC5B,UAAM,kBAAkB,KAAK,IAAI;AACjC,QAAI,oBAAoB;AAExB,WAAO,IAAI,QAAc,CAAC,YAAY;AAhnBxC;AAinBG,YAAM,cAAc,MAAM;AAjnB7B,YAAAA,KAAAC,KAAA;AAknBI,cAAM,MAAM,KAAK,IAAI;AACrB,cAAM,UAAU,MAAM;AACtB,cAAM,aAAa,GAAG,eAAe,KAAK,GAAG,eAAe;AAE5D,YAAI,KAAK,QAAQ,SAAS,GAAG;AAC5B,WAAAD,MAAA,KAAK,QAAL,gBAAAA,IAAU,KAAK;AAAA,YACd,KAAK;AAAA,YACL;AAAA,UACD;AACA,iBAAO;AAAA,QACR,WAAW,YAAY;AACtB,WAAAC,MAAA,KAAK,QAAL,gBAAAA,IAAU,KAAK;AAAA,YACd,KAAK;AAAA,YACL,iBAAiB,KAAK,QAAQ;AAAA,YAC9B;AAAA,UACD;AACA,iBAAO;AAAA,QACR,WAAW,WAAW,iBAAiB;AACtC,qBAAK,QAAL,mBAAU,KAAK;AAAA,YACd,KAAK;AAAA,YACL,iBAAiB,KAAK,QAAQ;AAAA,YAC9B;AAAA,UACD;AACA,iBAAO;AAAA,QACR,OAAO;AAEN,cAAI,MAAM,qBAAqB,qBAAqB;AACnD,uBAAK,QAAL,mBAAU,KAAK;AAAA,cACd,KAAK;AAAA,cACL,iBAAiB,KAAK,QAAQ;AAAA,cAC9B;AAAA,YACD;AACA,gCAAoB;AAAA,UACrB;AACA,iBAAO;AAAA,QACR;AAAA,MACD;AAGA,UAAI,YAAY,GAAG;AAClB,mBAAK,QAAL,mBAAU,MAAM;AAAA,UACf,KAAK;AAAA,QACN;AACA,gBAAQ;AACR;AAAA,MACD;AAEA,iBAAK,QAAL,mBAAU,MAAM;AAAA,QACf,KAAK;AAAA,QACL,eAAe;AAAA,MAChB;AAEA,YAAM,WAAW,YAAY,MAAM;AAtqBtC,YAAAD,KAAAC;AAuqBI,SAAAD,MAAA,KAAK,QAAL,gBAAAA,IAAU,MAAM;AAAA,UACf,KAAK;AAAA,UACL,YAAY,KAAK,QAAQ;AAAA,QAC1B;AACA,YAAI,YAAY,GAAG;AAClB,WAAAC,MAAA,KAAK,QAAL,gBAAAA,IAAU,MAAM;AAAA,YACf,KAAK;AAAA,UACN;AACA,wBAAc,QAAQ;AACtB,kBAAQ;AAAA,QACT;AAAA,MACD,GAAG,qBAAqB;AAAA,IACzB,CAAC;AAAA,EACF;AAAA;AAAA,EAGA,IAAI,mBAAmB;AACtB,WAAO,KAAK,QAAQ,oBAAoB,KAAK,QAAQ;AAAA,EACtD;AAAA,EACA,IAAI,cAAc;AACjB,UAAM,aAAa,KAAK,iBACtB,QAAQ,WAAW,OAAO,EAC1B,QAAQ,YAAY,QAAQ;AAG9B,UAAM,UAAU,WAAW,SAAS,GAAG,IACpC,WAAW,MAAM,GAAG,EAAE,IACtB;AACH,WAAO,GAAG,OAAO,qCAAqC,gBAAgB,cAAc,mBAAmB,KAAK,QAAQ,SAAS,CAAC,eAAe,mBAAmB,KAAK,QAAQ,SAAS,CAAC;AAAA,EACxL;AAAA;AAAA,EAGA,MAAM,yBAAyB;AAvsBhC;AAwsBE,UAAM,YAAY,CAAC,OAAO;AAC1B,QAAI,KAAK,OAAO;AACf,gBAAU,KAAK,eAAe,KAAK,OAAO,KAAK,EAAE;AAElD,UAAM,KAAK,MAAM,gBAAgB;AACjC,UAAM,KAAK,IAAI,GAAG,KAAK,aAAa,SAAS;AAC7C,SAAK,sBAAsB;AAE3B,eAAK,QAAL,mBAAU,KAAK;AAAA,MACd,KAAK;AAAA,MACL,UAAU,KAAK;AAAA,MACf,WAAW,KAAK,QAAQ;AAAA,MACxB,WAAW,KAAK,QAAQ;AAAA,MACxB,UAAU,CAAC,CAAC,KAAK,OAAO;AAAA,IACzB;AAEA,OAAG,iBAAiB,QAAQ,MAAM;AAxtBpC,UAAAD,KAAA;AAytBG,UAAI,KAAK,oBAAoB,GAAG;AAC/B,SAAAA,MAAA,KAAK,QAAL,gBAAAA,IAAU,KAAK;AAAA,UACd,KAAK;AAAA,UACL,WAAW,KAAK,QAAQ;AAAA,UACxB,YAAY,KAAK,QAAQ;AAAA,UACzB,kBAAkB,KAAK;AAAA,QACxB;AAAA,MACD,OAAO;AACN,mBAAK,QAAL,mBAAU,MAAM;AAAA,UACf,KAAK;AAAA,UACL,WAAW,KAAK,QAAQ;AAAA,UACxB,YAAY,KAAK,QAAQ;AAAA,QAC1B;AAAA,MACD;AAGA,WAAK,oBAAoB;AAGzB,UAAI,KAAK,mBAAmB;AAC3B,qBAAa,KAAK,iBAAiB;AACnC,aAAK,oBAAoB;AAAA,MAC1B;AAGA,UAAI,KAAK,oBAAoB;AAC5B,qBAAa,KAAK,kBAAkB;AACpC,aAAK,qBAAqB;AAAA,MAC3B;AAGA,YAAM,OAA8B;AAAA,QACnC,MAAM,KAAK,QAAQ;AAAA,QACnB,SAAS,KAAK,QAAQ;AAAA,QACtB,YAAY,KAAK,QAAQ;AAAA,QACzB,uBAAuB,IAAI;AAAA,UAC1B,OAAO,QAAQ,KAAK,QAAQ,qBAAqB,EAAE;AAAA,YAClD,CAAC,CAAC,MAAM,IAAI,MAAM;AAAA,cACjB;AAAA,cACA,EAAE,UAAU,KAAK,UAAU,KAAK,QAAQ,EAAE;AAAA,YAC3C;AAAA,UACD;AAAA,QACD;AAAA,QACA,UAAU,KAAK,UAAU,KAAK,QAAQ,QAAQ;AAAA,MAC/C;AAEA,WAAK,eAAe;AAAA,QACnB,KAAK;AAAA,QACL,KAAK;AAAA,MACN,CAAC;AAGD,YAAM,cAAc,IAAI,KAAK;AAC7B,YAAM,UAAU,YAAY,MAAM;AA9wBrC,YAAAA,KAAAC;AA+wBI,YAAI;AACH,cAAI,GAAG,eAAe,GAAG;AACxB,iBAAK,2BAA2B;AAAA,UACjC,OAAO;AACN,0BAAc,OAAO;AACrB,aAAAD,MAAA,KAAK,QAAL,gBAAAA,IAAU,KAAK;AAAA,cACd,KAAK;AAAA,YACN;AAAA,UACD;AAAA,QACD,SAAS,KAAK;AACb,WAAAC,MAAA,KAAK,QAAL,gBAAAA,IAAU,MAAM;AAAA,YACf,KAAK;AAAA,YACL,OAAO,eAAe,GAAG;AAAA,UAC1B;AAAA,QACD;AAAA,MACD,GAAG,WAAW;AACd,WAAK,eAAe;AAAA,IACrB,CAAC;AAED,OAAG,iBAAiB,WAAW,OAAO,OAAO;AAlyB/C,UAAAD,KAAA;AAmyBG,UAAI;AACJ,UAAI,GAAG,gBAAgB,MAAM;AAC5B,cAAM,IAAI,WAAW,MAAM,GAAG,KAAK,YAAY,CAAC;AAAA,MACjD,WAAW,OAAO,SAAS,GAAG,IAAI,GAAG;AACpC,cAAM,IAAI,WAAW,GAAG,IAAI;AAAA,MAC7B,OAAO;AACN,cAAM,IAAI,MAAM,6BAA6B,OAAO,GAAG,IAAI,EAAE;AAAA,MAC9D;AAGA,YAAM,UAAmB,wBAAe,GAAG;AAC3C,OAAAA,MAAA,KAAK,QAAL,gBAAAA,IAAU,MAAM;AAAA,QACf,KAAK;AAAA,QACL,MAAM,kBAAkB,OAAO;AAAA,MAChC;AAGA,UAAI,QAAQ,QAAQ,gBAAgB;AACnC,cAAM,OAAO,QAAQ;AAErB,YAAI,KAAK,aAAa,KAAK,UAAU;AACpC,eAAK,WAAW,KAAK;AAGrB,eAAK,eAAe;AAAA,QACrB;AAGA,aAAK,yBAAuB,UAAK,aAAL,mBAAe,uBACxC,OAAO,KAAK,SAAS,mBAAmB,IACxC;AAEH,mBAAK,QAAL,mBAAU,KAAK;AAAA,UACd,KAAK;AAAA,UACL,qBAAqB,KAAK;AAAA,QAC3B;AAGA,aAAK,yBAAyB;AAC9B,aAAK,4BAA4B;AACjC,mBAAK,YAAL,mBAAc;AAEd,aAAK,QAAQ,YAAY;AAAA,MAC1B,WAAW,QAAQ,QAAQ,oBAAoB;AAC9C,cAAM,WAAW,QAAQ;AACzB,aAAK,gBAAgB,QAAQ;AAAA,MAC9B,WAAW,QAAQ,QAAQ,qBAAqB;AAC/C,aAAK,iBAAiB,QAAQ,GAAG;AAAA,MAClC,WAAW,QAAQ,QAAQ,sBAAsB;AAChD,cAAM,aAAa,QAAQ;AAC3B,aAAK,kBAAkB,UAAU;AAAA,MAClC,WAAW,QAAQ,QAAQ,yBAAyB;AACnD,mBAAK,YAAL,mBAAc,oBAAoB,QAAQ,KAAK,MAAM,CAAC,QAAQ;AAv1BlE,cAAAA;AAw1BK,WAAAA,MAAA,KAAK,QAAL,gBAAAA,IAAU,MAAM;AAAA,YACf,KAAK;AAAA,YACL,OAAO,eAAe,GAAG;AAAA,UAC1B;AAAA,QACD;AAAA,MACD,WAAW,QAAQ,QAAQ,gBAAgB;AAC1C,aAAK,eAAe;AAAA,UACnB,KAAK;AAAA,UACL,KAAK;AAAA,YACJ,IAAI,QAAQ,IAAI;AAAA,UACjB;AAAA,QACD,CAAC;AAAA,MACF,OAAO;AACN,oBAAY,OAAO;AAAA,MACpB;AAAA,IACD,CAAC;AAED,OAAG,iBAAiB,SAAS,CAAC,OAAO;AAz2BvC,UAAAA,KAAA;AA02BG,OAAAA,MAAA,KAAK,QAAL,gBAAAA,IAAU,MAAM;AAAA,QACf,KAAK,oBAAoB,GAAG,KAAK;AAAA,MAClC;AAEA,UAAI,CAAC,KAAK,WAAW;AAEpB,YACC,CAAC,KAAK,sBACN,KAAK,wBACL,KAAK,uBAAuB,GAC3B;AACD,qBAAK,QAAL,mBAAU,KAAK;AAAA,YACd,KAAK;AAAA,YACL,SAAS,KAAK,uBAAuB;AAAA,UACtC;AACA,eAAK,qBAAqB,WAAW,MAAM;AAz3BhD,gBAAAA;AA03BM,gBAAI;AACH,mBAAK,YAAY;AAAA,YAClB,SAAS,KAAK;AACb,eAAAA,MAAA,KAAK,QAAL,gBAAAA,IAAU,MAAM;AAAA,gBACf,KAAK;AAAA,gBACL,OAAO,eAAe,GAAG;AAAA,cAC1B;AAAA,YACD;AAAA,UACD,GAAG,KAAK,oBAAoB;AAAA,QAC7B;AAGA,aAAK,mBAAmB;AAAA,MACzB;AAAA,IACD,CAAC;AAED,OAAG,iBAAiB,SAAS,OAAO,OAAO;AA14B7C,UAAAA,KAAA;AA24BG,YAAM,aAAa,0BAA0B,GAAG,MAAM;AACtD,WACC,yCAAY,WAAU,SACtB,yCAAY,WAAU,YACrB;AACD,SAAAA,MAAA,KAAK,QAAL,gBAAAA,IAAU,KAAK;AAEf,aAAK,QAAQ,eAAe,GAAG,MAAM,GAAG,MAAM;AAE9C,cAAM,KAAK,SAAS,IAAI;AAAA,MACzB,OAAO;AACN,aACC,yCAAY,WAAU,eACtB,yCAAY,WAAU,mBACrB;AACD,qBAAK,QAAL,mBAAU,KAAK;AAAA,QAChB,OAAO;AACN,qBAAK,QAAL,mBAAU,KAAK;AAAA,YACd,KAAK;AAAA,YACL,MAAM,GAAG;AAAA,YACT,QAAQ,GAAG,OAAO,SAAS;AAAA,YAC3B;AAAA,UACD;AAAA,QACD;AAEA,aAAK,QAAQ,eAAe,GAAG,MAAM,GAAG,MAAM;AAAA,MAC/C;AAGA,UAAI,KAAK,cAAc;AACtB,sBAAc,KAAK,YAAY;AAC/B,aAAK,eAAe;AAAA,MACrB;AAEA,UAAI,CAAC,KAAK,WAAW;AAEpB,YACC,CAAC,KAAK,sBACN,KAAK,wBACL,KAAK,uBAAuB,GAC3B;AACD,qBAAK,QAAL,mBAAU,KAAK;AAAA,YACd,KAAK;AAAA,YACL,SAAS,KAAK,uBAAuB;AAAA,UACtC;AACA,eAAK,qBAAqB,WAAW,MAAM;AAx7BhD,gBAAAA;AAy7BM,gBAAI;AACH,mBAAK,YAAY;AAAA,YAClB,SAAS,KAAK;AACb,eAAAA,MAAA,KAAK,QAAL,gBAAAA,IAAU,MAAM;AAAA,gBACf,KAAK;AAAA,gBACL,OAAO,eAAe,GAAG;AAAA,cAC1B;AAAA,YACD;AAAA,UACD,GAAG,KAAK,oBAAoB;AAAA,QAC7B;AAGA,aAAK,mBAAmB;AAAA,MACzB;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EAEA,gBAAgB,UAAqC;AA18BtD;AA28BE,eAAK,QAAL,mBAAU,KAAK;AAAA,MACd,KAAK;AAAA,MACL,cAAc,SAAS;AAAA,IACxB;AAEA,eAAW,kBAAkB,UAAU;AACtC,UAAI,eAAe,MAAM,QAAQ,qBAAqB;AAErD,aAAK,yBAAyB,cAAc,EAAE,MAAM,CAAC,QAAQ;AAn9BjE,cAAAA;AAo9BK,WAAAA,MAAA,KAAK,QAAL,gBAAAA,IAAU,MAAM;AAAA,YACf,KAAK;AAAA,YACL,SAAS,eAAe,WAAW;AAAA,YACnC,OAAO,eAAe,GAAG;AAAA,UAC1B;AAAA,QACD,CAAC;AAID,cAAM,QAAQ,KAAK;AAAA,UAClB,eAAe,WAAW;AAAA,UAC1B,eAAe,WAAW;AAAA,QAC3B;AACA,YAAI,MAAO,OAAM,iBAAiB,eAAe,WAAW;AAAA,MAC7D,WAAW,eAAe,MAAM,QAAQ,oBAAoB;AAE3D,aAAK,wBAAwB,cAAc,EAAE,MAAM,CAAC,QAAQ;AAp+BhE,cAAAA;AAq+BK,WAAAA,MAAA,KAAK,QAAL,gBAAAA,IAAU,MAAM;AAAA,YACf,KAAK;AAAA,YACL,SAAS,eAAe,WAAW;AAAA,YACnC,OAAO,eAAe,GAAG;AAAA,UAC1B;AAAA,QACD,CAAC;AAAA,MACF,OAAO;AACN,oBAAY,eAAe,KAAK;AAAA,MACjC;AAAA,IACD;AAAA,EACD;AAAA,EAEA,iBAAiB,KAAiC;AAj/BnD;AAk/BE,QAAI,sBAAsB,MAAM,KAAK,KAAK,OAAO,EAAE;AAAA,MAClD,CAAC,GAAG,CAAC,GAAG,KAAK,MAAM,IAAI,MAAM,aAAa;AAAA,MAC1C;AAAA,IACD;AAEA,eAAW,CAAC,GAAG,KAAK,KAAK,KAAK,SAAS;AACtC,UAAI,aAAa,IAAI,qBAAqB;AAAA,QACzC,CAAC,MAAM,EAAE,WAAW,MAAM;AAAA,MAC3B;AAEA,UAAI,WAAY,OAAM,gBAAgB,WAAW,KAAK;AAAA,IACvD;AAEA,UAAM,cAAc,MAAM,KAAK,KAAK,OAAO,EAAE;AAAA,MAC5C,CAAC,GAAG,CAAC,GAAG,KAAK,MAAM,IAAI,MAAM,aAAa;AAAA,MAC1C;AAAA,IACD;AACA,UAAM,cAAc,sBAAsB;AAE1C,QAAI,cAAc,GAAG;AACpB,iBAAK,QAAL,mBAAU,KAAK;AAAA,QACd,KAAK;AAAA,QACL;AAAA,MACD;AAAA,IACD;AAEA,QAAI,eAAe,8BAA8B;AAChD,WAAK,sBAAsB;AAAA,IAC5B;AAAA,EACD;AAAA;AAAA,EAGA,aAAa,cAAqC;AAlhCnD;AAmhCE,UAAM,QAAQ,KAAK,SAAS,aAAa,WAAW,OAAO;AAC3D,QAAI,CAAC,MAAO;AAEZ,UAAM,YAAY,YAAY;AAE9B,QAAI,cAAc,MAAM,KAAK,KAAK,OAAO,EAAE;AAAA,MAC1C,CAAC,GAAG,CAAC,GAAGE,MAAK,MAAM,IAAIA,OAAM,aAAa;AAAA,MAC1C;AAAA,IACD;AAEA,QACC,cAAc,gCACd,CAAC,KAAK,qBACL;AACD,WAAK,sBAAsB;AAC3B,iBAAK,QAAL,mBAAU,KAAK;AAAA,QACd,KAAK;AAAA,QACL,aAAa;AAAA,QACb,WAAW;AAAA,MACZ;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM,yBAAyB,gBAAyC;AA1iCzE;AA+iCE,QAAI,CAAC,KAAK,QAAS,OAAM,IAAI,MAAM,+BAA+B;AAElE,UAAM,eAAe,eAAe,MAClC;AAEF,UAAM,UAAU,eAAe,WAAW;AAC1C,UAAM,aAAa,eAAe,WAAW;AAC7C,UAAM,SAAS,aAAa;AAE5B,UAAM,cAA2B;AAAA,MAChC,MAAM,OAAO;AAAA,MACb,KAAK,OAAO;AAAA,MACZ,UAAU,OAAO;AAAA,MACjB,OAAO,OAAO,QAAQ,IAAI,WAAW,OAAO,KAAK,IAAI;AAAA,IACtD;AAEA,UAAM,WAAW,IAAI;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa;AAAA,IACd;AAEA,UAAM,gBAAgB,KAAK,QAAQ,IAAI,OAAO;AAC9C,QAAI,eAAe;AAClB,iBAAK,QAAL,mBAAU,KAAK;AAAA,QACd,KAAK;AAAA,QACL;AAAA,QACA,oBAAoB,cAAc;AAAA,QAClC,eAAe;AAAA,QACf,yBAAyB,cAAc,gBAAgB;AAAA,MACxD;AAAA,IACD;AAEA,SAAK,QAAQ,IAAI,SAAS,QAAQ;AAMlC,eAAW,MAAM,aAAa,qBAAqB;AAClD,WAAK,QAAQ,kBAAkB,GAAG,WAAW,GAAG,WAAW,OAAO;AAAA,IACnE;AAEA,eAAK,QAAL,mBAAU,KAAK;AAAA,MACd,KAAK;AAAA,MACL,QAAQ,KAAK,QAAQ;AAAA,MACrB;AAAA,MACA,MAAM,OAAO;AAAA,MACb,KAAK,OAAO;AAAA,MACZ;AAAA,MACA,qBAAqB,aAAa,oBAAoB;AAAA,IACvD;AAEA,SAAK,sBAAsB,SAAS,YAAY,SAAS;AAEzD,QAAI;AAGH,iBAAK,QAAL,mBAAU,MAAM;AAAA,QACf,KAAK;AAAA,QACL;AAAA,QACA;AAAA,MACD;AACA,YAAM,KAAK,QAAQ,aAAa,SAAS,YAAY,WAAW;AAEhE,eAAS,kBAAkB,QAAQ;AAAA,IACpC,SAAS,KAAK;AACb,iBAAK,QAAL,mBAAU,MAAM;AAAA,QACf,KAAK;AAAA,QACL;AAAA,QACA;AAAA,MACD;AAEA,eAAS,kBAAkB,OAAO,GAAG;AAIrC,YAAM,KAAK,eAAe,SAAS,UAAU;AAAA,IAC9C;AAAA,EACD;AAAA,EAEA,MAAM,wBAAwB,gBAAyC;AACtE,UAAM,cAAc,eAAe,MACjC;AAEF,UAAM,UAAU,eAAe,WAAW;AAC1C,UAAM,aAAa,eAAe,WAAW;AAE7C,UAAM,KAAK,eAAe,SAAS,UAAU;AAAA,EAC9C;AAAA,EAEA,iBACC,SACA,YACA,YACC;AACD,UAAM,QAAQ,KAAK,SAAS,SAAS,UAAU;AAC/C,QAAI,CAAC,MAAO;AAEZ,QAAI;AAEJ,QAAI,eAAe,SAAS;AAC3B,oBAAc,EAAE,KAAK,oBAAoB,KAAK,KAAK;AAAA,IACpD,WAAW,eAAe,QAAQ;AACjC,oBAAc;AAAA,QACb,KAAK;AAAA,QACL,KAAK;AAAA,MACN;AAAA,IACD,OAAO;AACN,kBAAY,UAAU;AAAA,IACvB;AAEA,UAAM,cAAyC;AAAA,MAC9C,QAAQ;AAAA,IACT;AAEA,UAAM,eAAsC;AAAA,MAC3C,YAAY;AAAA,QACX;AAAA,QACA;AAAA,QACA,OAAO,MAAM;AAAA,MACd;AAAA,MACA,OAAO;AAAA,QACN,KAAK;AAAA,QACL,KAAK;AAAA,MACN;AAAA,IACD;AAEA,SAAK,aAAa,YAAY;AAE9B,SAAK,eAAe;AAAA,MACnB,KAAK;AAAA,MACL,KAAK,CAAC,YAAY;AAAA,IACnB,CAAC;AAAA,EACF;AAAA,EAEA,sBACC,SACA,YACA,WACC;AACD,UAAM,QAAQ,KAAK,SAAS,SAAS,UAAU;AAC/C,QAAI,CAAC,MAAO;AAEZ,QAAI;AAEJ,QAAI,cAAc,WAAW;AAC5B,mBAAa,EAAE,KAAK,qBAAqB,KAAK,KAAK;AAAA,IACpD,WAAW,cAAc,WAAW;AACnC,mBAAa;AAAA,QACZ,KAAK;AAAA,QACL,KAAK;AAAA,UACJ,MAAe,kBAAS;AAAA,UACxB,SAAS;AAAA,QACV;AAAA,MACD;AAAA,IACD,OAAO;AACN,kBAAY,SAAS;AAAA,IACtB;AAEA,UAAM,mBAAmD;AAAA,MACxD,OAAO;AAAA,IACR;AAEA,UAAM,eAAsC;AAAA,MAC3C,YAAY;AAAA,QACX;AAAA,QACA;AAAA,QACA,OAAO,MAAM;AAAA,MACd;AAAA,MACA,OAAO;AAAA,QACN,KAAK;AAAA,QACL,KAAK;AAAA,MACN;AAAA,IACD;AAEA,SAAK,aAAa,YAAY;AAE9B,SAAK,eAAe;AAAA,MACnB,KAAK;AAAA,MACL,KAAK,CAAC,YAAY;AAAA,IACnB,CAAC;AAAA,EACF;AAAA,EAEA,6BAA6B;AAC5B,UAAM,yBAAyB,CAAC;AAEhC,eAAW,CAAC,GAAG,KAAK,KAAK,KAAK,SAAS;AACtC,UAAI,MAAM,iBAAiB,GAAG;AAE7B;AAAA,MACD;AAEA,6BAAuB,KAAK;AAAA,QAC3B,SAAS,MAAM;AAAA,QACf,YAAY,MAAM;AAAA,QAClB,OAAO,MAAM;AAAA,MACd,CAAC;AAAA,IACF;AAIA,SAAK,eAAe;AAAA,MACnB,KAAK;AAAA,MACL,KAAK;AAAA,QACJ;AAAA,MACD;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EAEA,kBAAkB,UAAuC;AAlwC1D;AAmwCE,UAAM,YAAY,SAAS;AAC3B,UAAM,UAAU,KAAK,YAAY,IAAI,SAAS;AAE9C,QAAI,CAAC,SAAS;AACb,iBAAK,QAAL,mBAAU,MAAM;AAAA,QACf,KAAK;AAAA,QACL;AAAA,MACD;AACA;AAAA,IACD;AAEA,SAAK,YAAY,OAAO,SAAS;AAEjC,QAAI,SAAS,KAAK,QAAQ,mBAAmB;AAC5C,cAAQ;AAAA,QACP,IAAI,MAAM,SAAS,KAAK,IAAI,WAAW,kBAAkB;AAAA,MAC1D;AAAA,IACD,OAAO;AACN,cAAQ,QAAQ,SAAS,KAAK,GAAG;AAAA,IAClC;AAAA,EACD;AAAA,EAEA,wBACC,UACA,eACwB;AAExB,UAAM,eAA6B,CAAC;AACpC,UAAM,iBAA+B,CAAC;AAEtC,eAAW,OAAO,SAAS,MAAM;AAChC,mBAAa,KAAK,IAAI,WAAW,GAAG,CAAC;AAAA,IACtC;AAEA,eAAW,SAAS,SAAS,QAAQ;AACpC,qBAAe,KAAK,IAAI,WAAW,KAAK,CAAC;AAAA,IAC1C;AAGA,UAAM,SAAgC,CAAC;AACvC,eAAW,gBAAgB,eAAe;AACzC,UAAI,QAAQ;AACZ,eAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC7C,YAAI,KAAK,WAAW,cAAc,aAAa,CAAC,CAAC,GAAG;AACnD,iBAAO,KAAK,eAAe,CAAC,CAAC;AAC7B,kBAAQ;AACR;AAAA,QACD;AAAA,MACD;AACA,UAAI,CAAC,OAAO;AACX,eAAO,KAAK,IAAI;AAAA,MACjB;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA,EAEA,WAAW,MAAkB,MAA2B;AACvD,QAAI,KAAK,WAAW,KAAK,OAAQ,QAAO;AACxC,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACrC,UAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAG,QAAO;AAAA,IACjC;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyBA,yBACC,UAC6B;AAC7B,UAAM,SAAqC,CAAC;AAE5C,aAAS,IAAI,GAAG,IAAI,SAAS,KAAK,QAAQ,KAAK;AAC9C,YAAM,MAAM,SAAS,KAAK,CAAC;AAC3B,YAAM,QAAQ,SAAS,OAAO,CAAC;AAE/B,UAAI,OAAO,OAAO;AACjB,cAAM,WAAW,IAAI,WAAW,GAAG;AACnC,cAAM,aAAa,IAAI,WAAW,KAAK;AACvC,eAAO,KAAK,CAAC,UAAU,UAAU,CAAC;AAAA,MACnC;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0BA,MAAM,MACL,SACA,MACiC;AACjC,UAAM,SAA2B,KAAK;AAAA,MACrC,CAAC,QACA,IAAI,OAAO;AAAA,QACV,IAAI;AAAA,QACJ,IAAI,aAAa,IAAI;AAAA,MACtB;AAAA,IACF;AAEA,UAAM,cAAsC;AAAA,MAC3C,KAAK;AAAA,MACL,KAAK,EAAE,MAAM,OAAO;AAAA,IACrB;AAEA,UAAM,WAAW,MAAM,KAAK,eAAe,SAAS,WAAW;AAC/D,WAAO,KAAK,wBAAwB,UAAU,IAAI;AAAA,EACnD;AAAA,EAEA,MAAM,UACL,SACA,SACsC;AACtC,UAAM,cAAsC;AAAA,MAC3C,KAAK;AAAA,MACL,KAAK;AAAA,QACJ,OAAO,EAAE,KAAK,kBAAkB,KAAK,KAAK;AAAA,QAC1C,UAAS,mCAAS,YAAW;AAAA,QAC7B,QACC,mCAAS,WAAU,SAAY,OAAO,QAAQ,KAAK,IAAI;AAAA,MACzD;AAAA,IACD;AAEA,UAAM,WAAW,MAAM,KAAK,eAAe,SAAS,WAAW;AAC/D,WAAO,KAAK,yBAAyB,QAAQ;AAAA,EAC9C;AAAA,EAEA,MAAM,YACL,SACA,OACA,KACA,WACA,SACsC;AACtC,UAAM,WAA2B,MAAM,OAAO;AAAA,MAC7C,MAAM;AAAA,MACN,MAAM,aAAa,MAAM;AAAA,IAC1B;AACA,UAAM,SAAyB,IAAI,OAAO;AAAA,MACzC,IAAI;AAAA,MACJ,IAAI,aAAa,IAAI;AAAA,IACtB;AAEA,UAAM,cAAsC;AAAA,MAC3C,KAAK;AAAA,MACL,KAAK;AAAA,QACJ,OAAO;AAAA,UACN,KAAK;AAAA,UACL,KAAK;AAAA,YACJ,OAAO;AAAA,YACP,KAAK;AAAA,YACL,WAAW,aAAa;AAAA,UACzB;AAAA,QACD;AAAA,QACA,UAAS,mCAAS,YAAW;AAAA,QAC7B,QACC,mCAAS,WAAU,SAAY,OAAO,QAAQ,KAAK,IAAI;AAAA,MACzD;AAAA,IACD;AAEA,UAAM,WAAW,MAAM,KAAK,eAAe,SAAS,WAAW;AAC/D,WAAO,KAAK,yBAAyB,QAAQ;AAAA,EAC9C;AAAA,EAEA,MAAM,aACL,SACA,QACA,SACsC;AACtC,UAAM,YAA4B,OAAO,OAAO;AAAA,MAC/C,OAAO;AAAA,MACP,OAAO,aAAa,OAAO;AAAA,IAC5B;AAEA,UAAM,cAAsC;AAAA,MAC3C,KAAK;AAAA,MACL,KAAK;AAAA,QACJ,OAAO;AAAA,UACN,KAAK;AAAA,UACL,KAAK,EAAE,KAAK,UAAU;AAAA,QACvB;AAAA,QACA,UAAS,mCAAS,YAAW;AAAA,QAC7B,QACC,mCAAS,WAAU,SAAY,OAAO,QAAQ,KAAK,IAAI;AAAA,MACzD;AAAA,IACD;AAEA,UAAM,WAAW,MAAM,KAAK,eAAe,SAAS,WAAW;AAC/D,WAAO,KAAK,yBAAyB,QAAQ;AAAA,EAC9C;AAAA,EAEA,MAAM,MACL,SACA,SACgB;AAChB,UAAM,OAAyB,QAAQ;AAAA,MACtC,CAAC,CAAC,KAAK,MAAM,MACZ,IAAI,OAAO;AAAA,QACV,IAAI;AAAA,QACJ,IAAI,aAAa,IAAI;AAAA,MACtB;AAAA,IACF;AACA,UAAM,SAA6B,QAAQ;AAAA,MAC1C,CAAC,CAAC,MAAM,KAAK,MACZ,MAAM,OAAO;AAAA,QACZ,MAAM;AAAA,QACN,MAAM,aAAa,MAAM;AAAA,MAC1B;AAAA,IACF;AAEA,UAAM,cAAsC;AAAA,MAC3C,KAAK;AAAA,MACL,KAAK,EAAE,MAAM,OAAO;AAAA,IACrB;AAEA,UAAM,KAAK,eAAe,SAAS,WAAW;AAAA,EAC/C;AAAA,EAEA,MAAM,SAAS,SAAiB,MAAmC;AAClE,UAAM,SAA2B,KAAK;AAAA,MACrC,CAAC,QACA,IAAI,OAAO;AAAA,QACV,IAAI;AAAA,QACJ,IAAI,aAAa,IAAI;AAAA,MACtB;AAAA,IACF;AAEA,UAAM,cAAsC;AAAA,MAC3C,KAAK;AAAA,MACL,KAAK,EAAE,MAAM,OAAO;AAAA,IACrB;AAEA,UAAM,KAAK,eAAe,SAAS,WAAW;AAAA,EAC/C;AAAA,EAEA,MAAM,OAAO,SAAgC;AAC5C,UAAM,cAAsC;AAAA,MAC3C,KAAK;AAAA,MACL,KAAK;AAAA,IACN;AAEA,UAAM,KAAK,eAAe,SAAS,WAAW;AAAA,EAC/C;AAAA;AAAA,EAGA,SAAS,SAAiB,SAAwB,YAAqB;AACtE,UAAM,QAAQ,KAAK,SAAS,SAAS,UAAU;AAC/C,QAAI,CAAC,MAAO;AAEZ,UAAM,aAA0C;AAAA,MAC/C,SAAS,YAAY,OAAO,OAAO,OAAO,IAAI;AAAA,IAC/C;AAEA,UAAM,eAAsC;AAAA,MAC3C,YAAY;AAAA,QACX;AAAA,QACA,YAAY,MAAM;AAAA,QAClB,OAAO,MAAM;AAAA,MACd;AAAA,MACA,OAAO;AAAA,QACN,KAAK;AAAA,QACL,KAAK;AAAA,MACN;AAAA,IACD;AAEA,SAAK,aAAa,YAAY;AAE9B,SAAK,eAAe;AAAA,MACnB,KAAK;AAAA,MACL,KAAK,CAAC,YAAY;AAAA,IACnB,CAAC;AAAA,EACF;AAAA,EAEA,WAAW,SAAiB,YAAqB;AAChD,SAAK,SAAS,SAAS,MAAM,UAAU;AAAA,EACxC;AAAA,EAEA,eACC,SACA,aACe;AACf,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACvC,YAAM,YAAY,KAAK;AAGvB,YAAM,eAAe;AAAA,QACpB;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,MAAM;AAAA,QACN,WAAW,KAAK,IAAI;AAAA,MACrB;AAEA,WAAK,YAAY,IAAI,WAAW,YAAY;AAE5C,UAAI,KAAK,iBAAiB,GAAG;AAE5B,aAAK,qBAAqB,SAAS;AAAA,MACpC;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EAEA,qBAAqB,WAAmB;AACvC,UAAM,UAAU,KAAK,YAAY,IAAI,SAAS;AAC9C,QAAI,CAAC,WAAW,QAAQ,KAAM;AAE9B,QAAI;AACH,YAAM,YAAwC;AAAA,QAC7C,SAAS,QAAQ;AAAA,QACjB;AAAA,QACA,MAAM,QAAQ;AAAA,MACf;AAEA,WAAK,eAAe;AAAA,QACnB,KAAK;AAAA,QACL,KAAK;AAAA,MACN,CAAC;AAGD,cAAQ,OAAO;AACf,cAAQ,YAAY,KAAK,IAAI;AAAA,IAC9B,SAAS,OAAO;AACf,WAAK,YAAY,OAAO,SAAS;AACjC,cAAQ,OAAO,KAAK;AAAA,IACrB;AAAA,EACD;AAAA,EAEA,2BAA2B;AAC1B,QAAI,CAAC,KAAK,iBAAiB,GAAG;AAC7B;AAAA,IACD;AAEA,QAAI,iBAAiB;AACrB,eAAW,CAAC,WAAW,OAAO,KAAK,KAAK,YAAY,QAAQ,GAAG;AAC9D,UAAI,CAAC,QAAQ,MAAM;AAClB,aAAK,qBAAqB,SAAS;AACnC;AAAA,MACD;AAAA,IACD;AAEA,QAAI,iBAAiB,GAAG;AAAA,IAExB;AAAA,EACD;AAAA;AAAA,EAGA,mBAEE;AACD,WACC,CAAC,CAAC,KAAK,uBACP,KAAK,oBAAoB,eAAe;AAAA,EAE1C;AAAA,EAEA,eAAe,SAA4B;AAlpD5C;AAmpDE,eAAK,QAAL,mBAAU,MAAM;AAAA,MACf,KAAK;AAAA,MACL,MAAM,kBAAkB,OAAO;AAAA,IAChC;AAEA,UAAM,UAAmB,wBAAe,OAAO;AAC/C,QAAI,KAAK,iBAAiB,GAAG;AAC5B,WAAK,oBAAoB,KAAK,OAAO;AAAA,IACtC,OAAO;AACN,iBAAK,QAAL,mBAAU,MAAM;AAAA,QACf,KAAK;AAAA,MACN;AAAA,IACD;AAAA,EACD;AAAA,EAEA,oCACC,WACA,WACA,OACC;AACD,QAAI,CAAC,KAAK;AACT,YAAM,IAAI,MAAM,oCAAoC;AACrD,SAAK,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyBA,MAAM,2BACL,SACA,aACC;AACD,QAAI,CAAC,KAAK;AACT,YAAM,IAAI,MAAM,gDAAgD;AACjE,UAAM,KAAK,QAAQ,2BAA2B,SAAS,WAAW;AAAA,EACnE;AAAA,EAEA,0BAA8C;AAC7C,QAAI,CAAC,KAAK,SAAU,QAAO;AAE3B,UAAM,OAAgB,kCAAyB;AAAA,MAC9C,KAAK;AAAA,MACL,KAAK;AAAA,QACJ,UAAU,KAAK;AAAA,QACf,uBAAuB;AAAA,MACxB;AAAA,IACD,CAAC;AAGD,UAAM,SAAS,OAAO,MAAM,KAAK,SAAS,CAAC;AAC3C,WAAO,cAAc,kBAAkB,CAAC;AACxC,WAAO,KAAK,IAAI,EAAE,KAAK,QAAQ,CAAC;AAEhC,WAAO,OAAO,SAAS,QAAQ;AAAA,EAChC;AAAA,EAEA,qBAAqB;AAnuDtB;AAouDE,QAAI,KAAK,WAAW;AACnB,iBAAK,QAAL,mBAAU,MAAM;AAAA,QACf,KAAK;AAAA,MACN;AACA;AAAA,IACD;AAEA,UAAM,QAAQ,iBAAiB,KAAK,mBAAmB;AAAA,MACtD,cAAc;AAAA,MACd,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,QAAQ;AAAA,IACT,CAAC;AAED,eAAK,QAAL,mBAAU,MAAM;AAAA,MACf,KAAK,gCAAgC,KAAK,oBAAoB,CAAC,OAAO,KAAK;AAAA,IAC5E;AAEA,SAAK,oBAAoB,WAAW,MAAM;AAtvD5C,UAAAF;AAuvDG,UAAI,CAAC,KAAK,WAAW;AACpB,aAAK;AACL,SAAAA,MAAA,KAAK,QAAL,gBAAAA,IAAU,MAAM;AAAA,UACf,KAAK,oCAAoC,KAAK,iBAAiB;AAAA,QAChE;AACA,aAAK,uBAAuB,EAAE,MAAM,CAAC,QAAQ;AA5vDjD,cAAAA;AA6vDK,WAAAA,MAAA,KAAK,QAAL,gBAAAA,IAAU,MAAM;AAAA,YACf,KAAK;AAAA,YACL,OAAO,eAAe,GAAG;AAAA,UAC1B;AAAA,QACD,CAAC;AAAA,MACF;AAAA,IACD,GAAG,KAAK;AAAA,EACT;AAAA,EAEA,8BAA8B;AAtwD/B;AAuwDE,UAAM,iBAAiB,CAAC;AAExB,eAAW,CAAC,GAAG,KAAK,KAAK,KAAK,SAAS;AACtC,qBAAe,KAAK,GAAG,MAAM,YAAY;AAAA,IAC1C;AAEA,QAAI,eAAe,WAAW,EAAG;AAEjC,eAAK,QAAL,mBAAU,KAAK;AAAA,MACd,KAAK;AAAA,MACL,OAAO,eAAe;AAAA,IACvB;AAGA,SAAK,eAAe;AAAA,MACnB,KAAK;AAAA,MACL,KAAK;AAAA,IACN,CAAC;AAAA,EACF;AAAA,EAEA,wBAAwB;AACvB,UAAM,mBAAmB,KAAK,IAAI,IAAI;AACtC,UAAM,WAAqB,CAAC;AAE5B,eAAW,CAAC,WAAW,OAAO,KAAK,KAAK,YAAY,QAAQ,GAAG;AAC9D,UAAI,QAAQ,YAAY,kBAAkB;AACzC,gBAAQ;AAAA,UACP,IAAI;AAAA,YACH;AAAA,UACD;AAAA,QACD;AACA,iBAAS,KAAK,SAAS;AAAA,MACxB;AAAA,IACD;AAEA,eAAW,aAAa,UAAU;AACjC,WAAK,YAAY,OAAO,SAAS;AAAA,IAClC;AAEA,QAAI,SAAS,SAAS,GAAG;AAAA,IAEzB;AAAA,EACD;AACD;","names":["logger","_a","actor","entry","_a","_b","actor"]}
|
|
1
|
+
{"version":3,"sources":["../src/mod.ts","../src/log.ts","../src/utils.ts","../src/actor.ts","../src/stringify.ts","../src/websocket-tunnel-adapter.ts","../src/tunnel.ts","../src/websocket.ts"],"sourcesContent":["import * as protocol from \"@rivetkit/engine-runner-protocol\";\nimport type { Logger } from \"pino\";\nimport type WebSocket from \"ws\";\nimport { type ActorConfig, RunnerActor } from \"./actor\";\nimport { logger, setLogger } from \"./log.js\";\nimport { stringifyToClient, stringifyToServer } from \"./stringify\";\nimport { type HibernatingWebSocketMetadata, Tunnel } from \"./tunnel\";\nimport {\n\tcalculateBackoff,\n\tparseWebSocketCloseReason,\n\tstringifyError,\n\tunreachable,\n} from \"./utils\";\nimport { importWebSocket } from \"./websocket.js\";\n\nexport type { HibernatingWebSocketMetadata };\nexport { RunnerActor, type ActorConfig };\nexport { idToStr } from \"./utils\";\n\nconst KV_EXPIRE: number = 30_000;\nconst PROTOCOL_VERSION: number = 5;\n\n/** Warn once the backlog significantly exceeds the server's ack batch size. */\nconst EVENT_BACKLOG_WARN_THRESHOLD = 10_000;\nconst SIGNAL_HANDLERS: (() => void | Promise<void>)[] = [];\n\nexport class RunnerShutdownError extends Error {\n\tconstructor() {\n\t\tsuper(\"Runner shut down\");\n\t}\n}\n\nexport interface RunnerConfig {\n\tlogger?: Logger;\n\tversion: number;\n\tendpoint: string;\n\ttoken?: string;\n\tpegboardEndpoint?: string;\n\tpegboardRelayEndpoint?: string;\n\tnamespace: string;\n\ttotalSlots: number;\n\trunnerName: string;\n\trunnerKey: string;\n\tprepopulateActorNames: Record<string, { metadata: Record<string, any> }>;\n\tmetadata?: Record<string, any>;\n\tonConnected: () => void;\n\tonDisconnected: (code: number, reason: string) => void;\n\tonShutdown: () => void;\n\n\t/** Called when receiving a network request. */\n\tfetch: (\n\t\trunner: Runner,\n\t\tactorId: string,\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t\trequest: Request,\n\t) => Promise<Response>;\n\n\t/**\n\t * Called when receiving a WebSocket connection.\n\t *\n\t * All event listeners must be added synchronously inside this function or\n\t * else events may be missed. The open event will fire immediately after\n\t * this function finishes.\n\t *\n\t * Any errors thrown here will disconnect the WebSocket immediately.\n\t *\n\t * While `path` and `headers` are partially redundant to the data in the\n\t * `Request`, they may vary slightly from the actual content of `Request`.\n\t * Prefer to persist the `path` and `headers` properties instead of the\n\t * `Request` itself.\n\t *\n\t * ## Hibernating Web Sockets\n\t *\n\t * ### Implementation Requirements\n\t *\n\t * **Requirement 1: Persist HWS Immediately**\n\t *\n\t * This is responsible for persisting hibernatable WebSockets immediately\n\t * (do not wait for open event). It is not time sensitive to flush the\n\t * connection state. If this fails to persist the HWS, the client's\n\t * WebSocket will be disconnected on next wake in the call to\n\t * `Tunnel::restoreHibernatingRequests` since the connection entry will not\n\t * exist.\n\t *\n\t * **Requirement 2: Persist Message Index On `message`**\n\t *\n\t * In the `message` event listener, this handler must persist the message\n\t * index from the event. The request ID is available at\n\t * `event.rivetRequestId` and message index at `event.rivetMessageIndex`.\n\t *\n\t * The message index should not be flushed immediately. Instead, this\n\t * should:\n\t *\n\t * - Debounce calls to persist the message index\n\t * - After each persist, call\n\t * `Runner::sendHibernatableWebSocketMessageAck` to acknowledge the\n\t * message\n\t *\n\t * This mechanism allows us to buffer messages on the gateway so we can\n\t * batch-persist events on our end on a given interval.\n\t *\n\t * If this fails to persist, then the gateway will replay unacked\n\t * messages when the actor starts again.\n\t *\n\t * **Requirement 3: Remove HWS From Storage On `close`**\n\t *\n\t * This handler should add an event listener for `close` to remove the\n\t * connection from storage.\n\t *\n\t * If the connection remove fails to persist, the close event will be\n\t * called again on the next actor start in\n\t * `Tunnel::restoreHibernatingRequests` since there will be no request for\n\t * the given connection.\n\t *\n\t * ### Restoring Connections\n\t *\n\t * The user of this library is responsible for:\n\t * 1. Loading all persisted hibernatable WebSocket metadata for an actor\n\t * 2. Calling `Runner::restoreHibernatingRequests` with this metadata at\n\t * the end of `onActorStart`\n\t *\n\t * `restoreHibernatingRequests` will restore all connections and attach\n\t * the appropriate event listeners.\n\t *\n\t * ### No Open Event On Restoration\n\t *\n\t * When restoring a HWS, the open event will not be called again. It will\n\t * go straight to the message or close event.\n\t */\n\twebsocket: (\n\t\trunner: Runner,\n\t\tactorId: string,\n\t\tws: any,\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t\trequest: Request,\n\t\tpath: string,\n\t\theaders: Record<string, string>,\n\t\tisHibernatable: boolean,\n\t\tisRestoringHibernatable: boolean,\n\t) => Promise<void>;\n\n\thibernatableWebSocket: {\n\t\t/**\n\t\t * Determines if a WebSocket can continue to live while an actor goes to\n\t\t * sleep.\n\t\t */\n\t\tcanHibernate: (\n\t\t\tactorId: string,\n\t\t\tgatewayId: ArrayBuffer,\n\t\t\trequestId: ArrayBuffer,\n\t\t\trequest: Request,\n\t\t) => boolean;\n\t};\n\n\t/**\n\t * Called when an actor starts.\n\t *\n\t * This callback is responsible for:\n\t * 1. Initializing the actor instance\n\t * 2. Loading all persisted hibernatable WebSocket metadata for this actor\n\t * 3. Calling `Runner::restoreHibernatingRequests` with the loaded metadata\n\t * to restore hibernatable WebSocket connections\n\t *\n\t * The actor should not be marked as \"ready\" until after\n\t * `restoreHibernatingRequests` completes to ensure all hibernatable\n\t * connections are fully restored before the actor processes new requests.\n\t */\n\tonActorStart: (\n\t\tactorId: string,\n\t\tgeneration: number,\n\t\tconfig: ActorConfig,\n\t) => Promise<void>;\n\n\tonActorStop: (actorId: string, generation: number) => Promise<void>;\n\tnoAutoShutdown?: boolean;\n}\n\nexport interface KvListOptions {\n\treverse?: boolean;\n\tlimit?: number;\n}\n\ninterface KvRequestEntry {\n\tactorId: string;\n\tdata: protocol.KvRequestData;\n\tresolve: (value: any) => void;\n\treject: (error: unknown) => void;\n\tsent: boolean;\n\ttimestamp: number;\n}\n\nexport class Runner {\n\t#config: RunnerConfig;\n\n\tget config(): RunnerConfig {\n\t\treturn this.#config;\n\t}\n\n\t#actors: Map<string, RunnerActor> = new Map();\n\n\t// WebSocket\n\t__pegboardWebSocket?: WebSocket;\n\trunnerId?: string;\n\t#started: boolean = false;\n\t#shutdown: boolean = false;\n\t#shuttingDown: boolean = false;\n\t#reconnectAttempt: number = 0;\n\t#reconnectTimeout?: NodeJS.Timeout;\n\n\t// Runner lost threshold management\n\t#runnerLostThreshold?: number;\n\t#runnerLostTimeout?: NodeJS.Timeout;\n\n\t// Event storage for resending\n\t#eventBacklogWarned: boolean = false;\n\n\t// Command acknowledgment\n\t#ackInterval?: NodeJS.Timeout;\n\n\t// KV operations\n\t#nextKvRequestId: number = 0;\n\t#kvRequests: Map<number, KvRequestEntry> = new Map();\n\t#kvCleanupInterval?: NodeJS.Timeout;\n\n\t// Tunnel for HTTP/WebSocket forwarding\n\t#tunnel: Tunnel | undefined;\n\n\t// Cached child logger with runner-specific attributes\n\t#logCached?: Logger;\n\n\tget log(): Logger | undefined {\n\t\tif (this.#logCached) return this.#logCached;\n\n\t\tconst l = logger();\n\t\tif (l) {\n\t\t\t// If has connected, create child logger with relevant metadata\n\t\t\t//\n\t\t\t// Otherwise, return default logger\n\t\t\tif (this.runnerId) {\n\t\t\t\tthis.#logCached = l.child({\n\t\t\t\t\trunnerId: this.runnerId,\n\t\t\t\t});\n\t\t\t\treturn this.#logCached;\n\t\t\t} else {\n\t\t\t\treturn l;\n\t\t\t}\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\tconstructor(config: RunnerConfig) {\n\t\tthis.#config = config;\n\t\tif (this.#config.logger) setLogger(this.#config.logger);\n\n\t\t// Start cleaning up old unsent KV requests every 15 seconds\n\t\tthis.#kvCleanupInterval = setInterval(() => {\n\t\t\ttry {\n\t\t\t\tthis.#cleanupOldKvRequests();\n\t\t\t} catch (err) {\n\t\t\t\tthis.log?.error({\n\t\t\t\t\tmsg: \"error cleaning up kv requests\",\n\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t});\n\t\t\t}\n\t\t}, 15000); // Run every 15 seconds\n\t}\n\n\t// MARK: Manage actors\n\tsleepActor(actorId: string, generation?: number) {\n\t\tconst actor = this.getActor(actorId, generation);\n\t\tif (!actor) return;\n\n\t\t// Keep the actor instance in memory during sleep\n\t\tthis.#sendActorIntent(actorId, actor.generation, \"sleep\");\n\n\t\t// NOTE: We do NOT remove the actor from this.#actors here\n\t\t// The server will send a StopActor command if it wants to fully stop\n\t}\n\n\tasync stopActor(actorId: string, generation?: number) {\n\t\tconst actor = this.getActor(actorId, generation);\n\t\tif (!actor) return;\n\n\t\tthis.#sendActorIntent(actorId, actor.generation, \"stop\");\n\n\t\t// NOTE: We do NOT remove the actor from this.#actors here\n\t\t// The server will send a StopActor command if it wants to fully stop\n\t}\n\n\tasync forceStopActor(actorId: string, generation?: number) {\n\t\tthis.log?.debug({\n\t\t\tmsg: \"force stopping actor\",\n\t\t\tactorId,\n\t\t});\n\n\t\tconst actor = this.getActor(actorId, generation);\n\t\tif (!actor) return;\n\n\t\t// If onActorStop times out, Pegboard will handle this timeout with ACTOR_STOP_THRESHOLD_DURATION_MS\n\t\t//\n\t\t// If we receive a request while onActorStop is running, a Service\n\t\t// Unavailable error will be returned to Guard and the request will be\n\t\t// retried\n\t\ttry {\n\t\t\tawait this.#config.onActorStop(actorId, actor.generation);\n\t\t} catch (err) {\n\t\t\tconsole.error(`Error in onActorStop for actor ${actorId}:`, err);\n\t\t}\n\n\t\t// Close requests after onActorStop so you can send messages over the tunnel\n\t\tthis.#tunnel?.closeActiveRequests(actor);\n\n\t\tthis.#sendActorStateUpdate(actorId, actor.generation, \"stopped\");\n\n\t\t// Remove actor after stopping in order to ensure that we can still\n\t\t// call actions on the runner\n\t\tthis.#removeActor(actorId, generation);\n\t}\n\n\t#handleLost() {\n\t\tthis.log?.info({\n\t\t\tmsg: \"stopping all actors due to runner lost threshold\",\n\t\t});\n\n\t\t// Remove all remaining kv requests\n\t\tfor (const [_, request] of this.#kvRequests.entries()) {\n\t\t\trequest.reject(new RunnerShutdownError());\n\t\t}\n\n\t\tthis.#kvRequests.clear();\n\n\t\tthis.#stopAllActors();\n\t}\n\n\t#stopAllActors() {\n\t\tconst actorIds = Array.from(this.#actors.keys());\n\t\tfor (const actorId of actorIds) {\n\t\t\tthis.forceStopActor(actorId).catch((err) => {\n\t\t\t\tthis.log?.error({\n\t\t\t\t\tmsg: \"error stopping actor\",\n\t\t\t\t\tactorId,\n\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t}\n\n\tgetActor(actorId: string, generation?: number): RunnerActor | undefined {\n\t\tconst actor = this.#actors.get(actorId);\n\t\tif (!actor) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"actor not found\",\n\t\t\t\tactorId,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\t\tif (generation !== undefined && actor.generation !== generation) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"actor generation mismatch\",\n\t\t\t\tactorId,\n\t\t\t\tgeneration,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn actor;\n\t}\n\n\tasync getAndWaitForActor(\n\t\tactorId: string,\n\t\tgeneration?: number,\n\t): Promise<RunnerActor | undefined> {\n\t\tconst actor = this.getActor(actorId, generation);\n\t\tif (!actor) return;\n\t\tawait actor.actorStartPromise.promise;\n\t\treturn actor;\n\t}\n\n\thasActor(actorId: string, generation?: number): boolean {\n\t\tconst actor = this.#actors.get(actorId);\n\n\t\treturn (\n\t\t\t!!actor &&\n\t\t\t(generation === undefined || actor.generation === generation)\n\t\t);\n\t}\n\n\tget actors() {\n\t\treturn this.#actors;\n\t}\n\n\t// IMPORTANT: Make sure to call stopActiveRequests if calling #removeActor\n\t#removeActor(\n\t\tactorId: string,\n\t\tgeneration?: number,\n\t): RunnerActor | undefined {\n\t\tconst actor = this.#actors.get(actorId);\n\t\tif (!actor) {\n\t\t\tthis.log?.error({\n\t\t\t\tmsg: \"actor not found for removal\",\n\t\t\t\tactorId,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\t\tif (generation !== undefined && actor.generation !== generation) {\n\t\t\tthis.log?.error({\n\t\t\t\tmsg: \"actor generation mismatch\",\n\t\t\t\tactorId,\n\t\t\t\tgeneration,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\tthis.#actors.delete(actorId);\n\n\t\tthis.log?.info({\n\t\t\tmsg: \"removed actor\",\n\t\t\tactorId,\n\t\t\tactors: this.#actors.size,\n\t\t});\n\n\t\treturn actor;\n\t}\n\n\t// MARK: Start\n\tasync start() {\n\t\tif (this.#started) throw new Error(\"Cannot call runner.start twice\");\n\t\tthis.#started = true;\n\n\t\tthis.log?.info({ msg: \"starting runner\" });\n\n\t\tthis.#tunnel = new Tunnel(this);\n\t\tthis.#tunnel.start();\n\n\t\ttry {\n\t\t\tawait this.#openPegboardWebSocket();\n\t\t} catch (error) {\n\t\t\tthis.#started = false;\n\t\t\tthrow error;\n\t\t}\n\n\t\tif (!this.#config.noAutoShutdown) {\n\t\t\tif (!SIGNAL_HANDLERS.length) {\n\t\t\t\tprocess.on(\"SIGTERM\", async () => {\n\t\t\t\t\tthis.log?.debug(\"received SIGTERM\");\n\n\t\t\t\t\tfor (const handler of SIGNAL_HANDLERS) {\n\t\t\t\t\t\tawait handler();\n\t\t\t\t\t}\n\n\t\t\t\t\t// TODO: Add back\n\t\t\t\t\t// process.exit(0);\n\t\t\t\t});\n\t\t\t\tprocess.on(\"SIGINT\", async () => {\n\t\t\t\t\tthis.log?.debug(\"received SIGINT\");\n\n\t\t\t\t\tfor (const handler of SIGNAL_HANDLERS) {\n\t\t\t\t\t\tawait handler();\n\t\t\t\t\t}\n\n\t\t\t\t\t// TODO: Add back\n\t\t\t\t\t// process.exit(0);\n\t\t\t\t});\n\n\t\t\t\tthis.log?.debug({\n\t\t\t\t\tmsg: \"added SIGTERM listeners\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tSIGNAL_HANDLERS.push(async () => {\n\t\t\t\tconst weak = new WeakRef(this);\n\t\t\t\tawait weak.deref()?.shutdown(false, false);\n\t\t\t});\n\t\t}\n\t}\n\n\t// MARK: Shutdown\n\tasync shutdown(immediate: boolean, exit: boolean = false) {\n\t\t// Prevent concurrent shutdowns\n\t\tif (this.#shuttingDown) {\n\t\t\tthis.log?.debug({\n\t\t\t\tmsg: \"shutdown already in progress, ignoring\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tthis.#shuttingDown = true;\n\n\t\tthis.log?.info({\n\t\t\tmsg: \"starting shutdown\",\n\t\t\timmediate,\n\t\t\texit,\n\t\t});\n\t\tthis.#shutdown = true;\n\n\t\t// Clear reconnect timeout\n\t\tif (this.#reconnectTimeout) {\n\t\t\tclearTimeout(this.#reconnectTimeout);\n\t\t\tthis.#reconnectTimeout = undefined;\n\t\t}\n\n\t\t// Clear runner lost timeout\n\t\tif (this.#runnerLostTimeout) {\n\t\t\tclearTimeout(this.#runnerLostTimeout);\n\t\t\tthis.#runnerLostTimeout = undefined;\n\t\t}\n\n\t\t// Clear ack interval\n\t\tif (this.#ackInterval) {\n\t\t\tclearInterval(this.#ackInterval);\n\t\t\tthis.#ackInterval = undefined;\n\t\t}\n\n\t\t// Clear KV cleanup interval\n\t\tif (this.#kvCleanupInterval) {\n\t\t\tclearInterval(this.#kvCleanupInterval);\n\t\t\tthis.#kvCleanupInterval = undefined;\n\t\t}\n\n\t\t// Reject all KV requests\n\t\tfor (const request of this.#kvRequests.values()) {\n\t\t\trequest.reject(\n\t\t\t\tnew Error(\"WebSocket connection closed during shutdown\"),\n\t\t\t);\n\t\t}\n\t\tthis.#kvRequests.clear();\n\n\t\t// Close WebSocket\n\t\tif (this.__webSocketReady()) {\n\t\t\tconst pegboardWebSocket = this.__pegboardWebSocket;\n\t\t\tif (immediate) {\n\t\t\t\t// Stop immediately\n\t\t\t\tpegboardWebSocket.close(1000, \"pegboard.runner_shutdown\");\n\t\t\t} else {\n\t\t\t\t// Wait for actors to shut down before stopping\n\t\t\t\ttry {\n\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\tmsg: \"sending stopping message\",\n\t\t\t\t\t\treadyState: pegboardWebSocket.readyState,\n\t\t\t\t\t});\n\n\t\t\t\t\t// Start stopping\n\t\t\t\t\t//\n\t\t\t\t\t// The runner workflow will send StopActor commands for all\n\t\t\t\t\t// actors\n\t\t\t\t\tthis.__sendToServer({\n\t\t\t\t\t\ttag: \"ToServerStopping\",\n\t\t\t\t\t\tval: null,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst closePromise = new Promise<void>((resolve) => {\n\t\t\t\t\t\tif (!pegboardWebSocket)\n\t\t\t\t\t\t\tthrow new Error(\"missing pegboardWebSocket\");\n\n\t\t\t\t\t\tpegboardWebSocket.addEventListener(\"close\", (ev) => {\n\t\t\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\t\t\tmsg: \"connection closed\",\n\t\t\t\t\t\t\t\tcode: ev.code,\n\t\t\t\t\t\t\t\treason: ev.reason.toString(),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\t\t// Wait for all actors to stop before closing ws\n\t\t\t\t\tawait this.#waitForActorsToStop(pegboardWebSocket);\n\n\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\tmsg: \"closing WebSocket\",\n\t\t\t\t\t});\n\t\t\t\t\tpegboardWebSocket.close(1000, \"pegboard.runner_shutdown\");\n\n\t\t\t\t\tawait closePromise;\n\n\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\tmsg: \"websocket shutdown completed\",\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\tmsg: \"error during websocket shutdown:\",\n\t\t\t\t\t\terror,\n\t\t\t\t\t});\n\t\t\t\t\tpegboardWebSocket.close();\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// This is often logged when the serverless SSE stream closes after\n\t\t\t// the runner has already shut down\n\t\t\tthis.log?.debug({\n\t\t\t\tmsg: \"no runner WebSocket to shutdown or already closed\",\n\t\t\t\treadyState: this.__pegboardWebSocket?.readyState,\n\t\t\t});\n\t\t}\n\n\t\t// Close tunnel\n\t\tif (this.#tunnel) {\n\t\t\tthis.#tunnel.shutdown();\n\t\t\tthis.#tunnel = undefined;\n\t\t}\n\n\t\tthis.#config.onShutdown();\n\n\t\tif (exit) process.exit(0);\n\t}\n\n\t/**\n\t * Wait for all actors to stop before proceeding with shutdown.\n\t *\n\t * This method polls every 100ms to check if all actors have been stopped.\n\t *\n\t * It will resolve early if:\n\t * - All actors are stopped\n\t * - The WebSocket connection is closed\n\t * - The shutdown timeout is reached (120 seconds)\n\t */\n\tasync #waitForActorsToStop(ws: WebSocket): Promise<void> {\n\t\tconst shutdownTimeout = 120_000; // 120 seconds\n\t\tconst shutdownCheckInterval = 100; // Check every 100ms\n\t\tconst progressLogInterval = 5_000; // Log progress every 5 seconds\n\t\tconst shutdownStartTs = Date.now();\n\t\tlet lastProgressLogTs = 0; // Ensure first log happens immediately\n\n\t\treturn new Promise<void>((resolve) => {\n\t\t\tconst checkActors = () => {\n\t\t\t\tconst now = Date.now();\n\t\t\t\tconst elapsed = now - shutdownStartTs;\n\t\t\t\tconst wsIsClosed = ws.readyState === 2 || ws.readyState === 3;\n\n\t\t\t\tif (this.#actors.size === 0) {\n\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\tmsg: \"all actors stopped\",\n\t\t\t\t\t\telapsed,\n\t\t\t\t\t});\n\t\t\t\t\treturn true;\n\t\t\t\t} else if (wsIsClosed) {\n\t\t\t\t\tthis.log?.warn({\n\t\t\t\t\t\tmsg: \"websocket closed before all actors stopped\",\n\t\t\t\t\t\tremainingActors: this.#actors.size,\n\t\t\t\t\t\telapsed,\n\t\t\t\t\t});\n\t\t\t\t\treturn true;\n\t\t\t\t} else if (elapsed >= shutdownTimeout) {\n\t\t\t\t\tthis.log?.warn({\n\t\t\t\t\t\tmsg: \"shutdown timeout reached, forcing close\",\n\t\t\t\t\t\tremainingActors: this.#actors.size,\n\t\t\t\t\t\telapsed,\n\t\t\t\t\t});\n\t\t\t\t\treturn true;\n\t\t\t\t} else {\n\t\t\t\t\t// Log progress every 5 seconds\n\t\t\t\t\tif (now - lastProgressLogTs >= progressLogInterval) {\n\t\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\t\tmsg: \"waiting for actors to stop\",\n\t\t\t\t\t\t\tremainingActors: this.#actors.size,\n\t\t\t\t\t\t\telapsed,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tlastProgressLogTs = now;\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// Check immediately first\n\t\t\tif (checkActors()) {\n\t\t\t\tthis.log?.debug({\n\t\t\t\t\tmsg: \"actors check completed immediately\",\n\t\t\t\t});\n\t\t\t\tresolve();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.log?.debug({\n\t\t\t\tmsg: \"starting actor wait interval\",\n\t\t\t\tcheckInterval: shutdownCheckInterval,\n\t\t\t});\n\n\t\t\tconst interval = setInterval(() => {\n\t\t\t\tthis.log?.debug({\n\t\t\t\t\tmsg: \"actor wait interval tick\",\n\t\t\t\t\tactorCount: this.#actors.size,\n\t\t\t\t});\n\t\t\t\tif (checkActors()) {\n\t\t\t\t\tthis.log?.debug({\n\t\t\t\t\t\tmsg: \"actors check completed, clearing interval\",\n\t\t\t\t\t});\n\t\t\t\t\tclearInterval(interval);\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t}, shutdownCheckInterval);\n\t\t});\n\t}\n\n\t// MARK: Networking\n\tget pegboardEndpoint() {\n\t\treturn this.#config.pegboardEndpoint || this.#config.endpoint;\n\t}\n\tget pegboardUrl() {\n\t\tconst wsEndpoint = this.pegboardEndpoint\n\t\t\t.replace(\"http://\", \"ws://\")\n\t\t\t.replace(\"https://\", \"wss://\");\n\n\t\t// Ensure the endpoint ends with /runners/connect\n\t\tconst baseUrl = wsEndpoint.endsWith(\"/\")\n\t\t\t? wsEndpoint.slice(0, -1)\n\t\t\t: wsEndpoint;\n\t\treturn `${baseUrl}/runners/connect?protocol_version=${PROTOCOL_VERSION}&namespace=${encodeURIComponent(this.#config.namespace)}&runner_key=${encodeURIComponent(this.#config.runnerKey)}`;\n\t}\n\n\t// MARK: Runner protocol\n\tasync #openPegboardWebSocket() {\n\t\tconst protocols = [\"rivet\"];\n\t\tif (this.config.token)\n\t\t\tprotocols.push(`rivet_token.${this.config.token}`);\n\n\t\tconst WS = await importWebSocket();\n\t\tconst ws = new WS(this.pegboardUrl, protocols) as any as WebSocket;\n\t\tthis.__pegboardWebSocket = ws;\n\n\t\tthis.log?.info({\n\t\t\tmsg: \"connecting\",\n\t\t\tendpoint: this.pegboardEndpoint,\n\t\t\tnamespace: this.#config.namespace,\n\t\t\trunnerKey: this.#config.runnerKey,\n\t\t\thasToken: !!this.config.token,\n\t\t});\n\n\t\tws.addEventListener(\"open\", () => {\n\t\t\tif (this.#reconnectAttempt > 0) {\n\t\t\t\tthis.log?.info({\n\t\t\t\t\tmsg: \"runner reconnected\",\n\t\t\t\t\tnamespace: this.#config.namespace,\n\t\t\t\t\trunnerName: this.#config.runnerName,\n\t\t\t\t\treconnectAttempt: this.#reconnectAttempt,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tthis.log?.debug({\n\t\t\t\t\tmsg: \"runner connected\",\n\t\t\t\t\tnamespace: this.#config.namespace,\n\t\t\t\t\trunnerName: this.#config.runnerName,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Reset reconnect attempt counter on successful connection\n\t\t\tthis.#reconnectAttempt = 0;\n\n\t\t\t// Clear any pending reconnect timeout\n\t\t\tif (this.#reconnectTimeout) {\n\t\t\t\tclearTimeout(this.#reconnectTimeout);\n\t\t\t\tthis.#reconnectTimeout = undefined;\n\t\t\t}\n\n\t\t\t// Clear any pending runner lost timeout since we're reconnecting\n\t\t\tif (this.#runnerLostTimeout) {\n\t\t\t\tclearTimeout(this.#runnerLostTimeout);\n\t\t\t\tthis.#runnerLostTimeout = undefined;\n\t\t\t}\n\n\t\t\t// Send init message\n\t\t\tconst init: protocol.ToServerInit = {\n\t\t\t\tname: this.#config.runnerName,\n\t\t\t\tversion: this.#config.version,\n\t\t\t\ttotalSlots: this.#config.totalSlots,\n\t\t\t\tprepopulateActorNames: new Map(\n\t\t\t\t\tObject.entries(this.#config.prepopulateActorNames).map(\n\t\t\t\t\t\t([name, data]) => [\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t{ metadata: JSON.stringify(data.metadata) },\n\t\t\t\t\t\t],\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t\tmetadata: JSON.stringify(this.#config.metadata),\n\t\t\t};\n\n\t\t\tthis.__sendToServer({\n\t\t\t\ttag: \"ToServerInit\",\n\t\t\t\tval: init,\n\t\t\t});\n\n\t\t\t// Start command acknowledgment interval (5 minutes)\n\t\t\tconst ackInterval = 5 * 60 * 1000; // 5 minutes in milliseconds\n\t\t\tconst ackLoop = setInterval(() => {\n\t\t\t\ttry {\n\t\t\t\t\tif (ws.readyState === 1) {\n\t\t\t\t\t\tthis.#sendCommandAcknowledgment();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclearInterval(ackLoop);\n\t\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\t\tmsg: \"WebSocket not open, stopping ack loop\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\tmsg: \"error in command acknowledgment loop\",\n\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}, ackInterval);\n\t\t\tthis.#ackInterval = ackLoop;\n\t\t});\n\n\t\tws.addEventListener(\"message\", async (ev) => {\n\t\t\tlet buf: Uint8Array;\n\t\t\tif (ev.data instanceof Blob) {\n\t\t\t\tbuf = new Uint8Array(await ev.data.arrayBuffer());\n\t\t\t} else if (Buffer.isBuffer(ev.data)) {\n\t\t\t\tbuf = new Uint8Array(ev.data);\n\t\t\t} else {\n\t\t\t\tthrow new Error(`expected binary data, got ${typeof ev.data}`);\n\t\t\t}\n\n\t\t\t// Parse message\n\t\t\tconst message = protocol.decodeToClient(buf);\n\t\t\tthis.log?.debug({\n\t\t\t\tmsg: \"received runner message\",\n\t\t\t\tdata: stringifyToClient(message),\n\t\t\t});\n\n\t\t\t// Handle message\n\t\t\tif (message.tag === \"ToClientInit\") {\n\t\t\t\tconst init = message.val;\n\n\t\t\t\tif (this.runnerId !== init.runnerId) {\n\t\t\t\t\tthis.runnerId = init.runnerId;\n\n\t\t\t\t\t// Clear actors if runner id changed\n\t\t\t\t\tthis.#stopAllActors();\n\t\t\t\t}\n\n\t\t\t\t// Store the runner lost threshold from metadata\n\t\t\t\tthis.#runnerLostThreshold = init.metadata?.runnerLostThreshold\n\t\t\t\t\t? Number(init.metadata.runnerLostThreshold)\n\t\t\t\t\t: undefined;\n\n\t\t\t\tthis.log?.info({\n\t\t\t\t\tmsg: \"received init\",\n\t\t\t\t\trunnerLostThreshold: this.#runnerLostThreshold,\n\t\t\t\t});\n\n\t\t\t\t// Resend pending events\n\t\t\t\tthis.#processUnsentKvRequests();\n\t\t\t\tthis.#resendUnacknowledgedEvents();\n\t\t\t\tthis.#tunnel?.resendBufferedEvents();\n\n\t\t\t\tthis.#config.onConnected();\n\t\t\t} else if (message.tag === \"ToClientCommands\") {\n\t\t\t\tconst commands = message.val;\n\t\t\t\tthis.#handleCommands(commands);\n\t\t\t} else if (message.tag === \"ToClientAckEvents\") {\n\t\t\t\tthis.#handleAckEvents(message.val);\n\t\t\t} else if (message.tag === \"ToClientKvResponse\") {\n\t\t\t\tconst kvResponse = message.val;\n\t\t\t\tthis.#handleKvResponse(kvResponse);\n\t\t\t} else if (message.tag === \"ToClientTunnelMessage\") {\n\t\t\t\tthis.#tunnel?.handleTunnelMessage(message.val).catch((err) => {\n\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\tmsg: \"error handling tunnel message\",\n\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t} else if (message.tag === \"ToClientPing\") {\n\t\t\t\tthis.__sendToServer({\n\t\t\t\t\ttag: \"ToServerPong\",\n\t\t\t\t\tval: {\n\t\t\t\t\t\tts: message.val.ts,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tunreachable(message);\n\t\t\t}\n\t\t});\n\n\t\tws.addEventListener(\"error\", (ev) => {\n\t\t\tthis.log?.error({\n\t\t\t\tmsg: `WebSocket error: ${ev.error}`,\n\t\t\t});\n\n\t\t\tif (!this.#shutdown) {\n\t\t\t\t// Start runner lost timeout if we have a threshold and are not shutting down\n\t\t\t\tif (\n\t\t\t\t\t!this.#runnerLostTimeout &&\n\t\t\t\t\tthis.#runnerLostThreshold &&\n\t\t\t\t\tthis.#runnerLostThreshold > 0\n\t\t\t\t) {\n\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\tmsg: \"starting runner lost timeout\",\n\t\t\t\t\t\tseconds: this.#runnerLostThreshold / 1000,\n\t\t\t\t\t});\n\t\t\t\t\tthis.#runnerLostTimeout = setTimeout(() => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tthis.#handleLost();\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\t\t\tmsg: \"error handling runner lost\",\n\t\t\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this.#runnerLostThreshold);\n\t\t\t\t}\n\n\t\t\t\t// Attempt to reconnect if not stopped\n\t\t\t\tthis.#scheduleReconnect();\n\t\t\t}\n\t\t});\n\n\t\tws.addEventListener(\"close\", async (ev) => {\n\t\t\tconst closeError = parseWebSocketCloseReason(ev.reason);\n\t\t\tif (\n\t\t\t\tcloseError?.group === \"ws\" &&\n\t\t\t\tcloseError?.error === \"eviction\"\n\t\t\t) {\n\t\t\t\tthis.log?.info(\"runner websocket evicted\");\n\n\t\t\t\tthis.#config.onDisconnected(ev.code, ev.reason);\n\n\t\t\t\tawait this.shutdown(true);\n\t\t\t} else {\n\t\t\t\tif (\n\t\t\t\t\tcloseError?.group === \"pegboard\" &&\n\t\t\t\t\tcloseError?.error === \"runner_shutdown\"\n\t\t\t\t) {\n\t\t\t\t\tthis.log?.info(\"runner shutdown\");\n\t\t\t\t} else {\n\t\t\t\t\tthis.log?.warn({\n\t\t\t\t\t\tmsg: \"runner disconnected\",\n\t\t\t\t\t\tcode: ev.code,\n\t\t\t\t\t\treason: ev.reason.toString(),\n\t\t\t\t\t\tcloseError,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tthis.#config.onDisconnected(ev.code, ev.reason);\n\t\t\t}\n\n\t\t\t// Clear ack interval on close\n\t\t\tif (this.#ackInterval) {\n\t\t\t\tclearInterval(this.#ackInterval);\n\t\t\t\tthis.#ackInterval = undefined;\n\t\t\t}\n\n\t\t\tif (!this.#shutdown) {\n\t\t\t\t// Start runner lost timeout if we have a threshold and are not shutting down\n\t\t\t\tif (\n\t\t\t\t\t!this.#runnerLostTimeout &&\n\t\t\t\t\tthis.#runnerLostThreshold &&\n\t\t\t\t\tthis.#runnerLostThreshold > 0\n\t\t\t\t) {\n\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\tmsg: \"starting runner lost timeout\",\n\t\t\t\t\t\tseconds: this.#runnerLostThreshold / 1000,\n\t\t\t\t\t});\n\t\t\t\t\tthis.#runnerLostTimeout = setTimeout(() => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tthis.#handleLost();\n\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\t\t\tmsg: \"error handling runner lost\",\n\t\t\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this.#runnerLostThreshold);\n\t\t\t\t}\n\n\t\t\t\t// Attempt to reconnect if not stopped\n\t\t\t\tthis.#scheduleReconnect();\n\t\t\t}\n\t\t});\n\t}\n\n\t#handleCommands(commands: protocol.ToClientCommands) {\n\t\tthis.log?.info({\n\t\t\tmsg: \"received commands\",\n\t\t\tcommandCount: commands.length,\n\t\t});\n\n\t\tfor (const commandWrapper of commands) {\n\t\t\tif (commandWrapper.inner.tag === \"CommandStartActor\") {\n\t\t\t\t// Spawn background promise\n\t\t\t\tthis.#handleCommandStartActor(commandWrapper).catch((err) => {\n\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\tmsg: \"error handling start actor command\",\n\t\t\t\t\t\tactorId: commandWrapper.checkpoint.actorId,\n\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\t// NOTE: We don't do this for CommandStopActor because the actor will be removed by that call\n\t\t\t\t// so we cant update the checkpoint\n\t\t\t\tconst actor = this.getActor(\n\t\t\t\t\tcommandWrapper.checkpoint.actorId,\n\t\t\t\t\tcommandWrapper.checkpoint.generation,\n\t\t\t\t);\n\t\t\t\tif (actor)\n\t\t\t\t\tactor.lastCommandIdx = commandWrapper.checkpoint.index;\n\t\t\t} else if (commandWrapper.inner.tag === \"CommandStopActor\") {\n\t\t\t\t// Spawn background promise\n\t\t\t\tthis.#handleCommandStopActor(commandWrapper).catch((err) => {\n\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\tmsg: \"error handling stop actor command\",\n\t\t\t\t\t\tactorId: commandWrapper.checkpoint.actorId,\n\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tunreachable(commandWrapper.inner);\n\t\t\t}\n\t\t}\n\t}\n\n\t#handleAckEvents(ack: protocol.ToClientAckEvents) {\n\t\tconst originalTotalEvents = Array.from(this.#actors).reduce(\n\t\t\t(s, [_, actor]) => s + actor.eventHistory.length,\n\t\t\t0,\n\t\t);\n\n\t\tfor (const [_, actor] of this.#actors) {\n\t\t\tconst checkpoint = ack.lastEventCheckpoints.find(\n\t\t\t\t(x) => x.actorId == actor.actorId,\n\t\t\t);\n\n\t\t\tif (checkpoint) actor.handleAckEvents(checkpoint.index);\n\t\t}\n\n\t\tconst totalEvents = Array.from(this.#actors).reduce(\n\t\t\t(s, [_, actor]) => s + actor.eventHistory.length,\n\t\t\t0,\n\t\t);\n\t\tconst prunedCount = originalTotalEvents - totalEvents;\n\n\t\tif (prunedCount > 0) {\n\t\t\tthis.log?.info({\n\t\t\t\tmsg: \"pruned acknowledged events\",\n\t\t\t\tprunedCount,\n\t\t\t});\n\t\t}\n\n\t\tif (totalEvents <= EVENT_BACKLOG_WARN_THRESHOLD) {\n\t\t\tthis.#eventBacklogWarned = false;\n\t\t}\n\t}\n\n\t/** Track events to send to the server in case we need to resend it on disconnect. */\n\t#recordEvent(eventWrapper: protocol.EventWrapper) {\n\t\tconst actor = this.getActor(eventWrapper.checkpoint.actorId);\n\t\tif (!actor) return;\n\n\t\tactor.recordEvent(eventWrapper);\n\n\t\tconst totalEvents = Array.from(this.#actors).reduce(\n\t\t\t(s, [_, actor]) => s + actor.eventHistory.length,\n\t\t\t0,\n\t\t);\n\n\t\tif (\n\t\t\ttotalEvents > EVENT_BACKLOG_WARN_THRESHOLD &&\n\t\t\t!this.#eventBacklogWarned\n\t\t) {\n\t\t\tthis.#eventBacklogWarned = true;\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"unacknowledged event backlog exceeds threshold\",\n\t\t\t\tbacklogSize: totalEvents,\n\t\t\t\tthreshold: EVENT_BACKLOG_WARN_THRESHOLD,\n\t\t\t});\n\t\t}\n\t}\n\n\tasync #handleCommandStartActor(commandWrapper: protocol.CommandWrapper) {\n\t\t// IMPORTANT: Make sure no async code runs before inserting #actors and\n\t\t// calling addRequestToActor in order to prevent race conditions with\n\t\t// subsequence commands\n\n\t\tif (!this.#tunnel) throw new Error(\"missing tunnel on actor start\");\n\n\t\tconst startCommand = commandWrapper.inner\n\t\t\t.val as protocol.CommandStartActor;\n\n\t\tconst actorId = commandWrapper.checkpoint.actorId;\n\t\tconst generation = commandWrapper.checkpoint.generation;\n\t\tconst config = startCommand.config;\n\n\t\tconst actorConfig: ActorConfig = {\n\t\t\tname: config.name,\n\t\t\tkey: config.key,\n\t\t\tcreateTs: config.createTs,\n\t\t\tinput: config.input ? new Uint8Array(config.input) : null,\n\t\t};\n\n\t\tconst instance = new RunnerActor(\n\t\t\tactorId,\n\t\t\tgeneration,\n\t\t\tactorConfig,\n\t\t\tstartCommand.hibernatingRequests,\n\t\t);\n\n\t\tconst existingActor = this.#actors.get(actorId);\n\t\tif (existingActor) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"replacing existing actor in actors map\",\n\t\t\t\tactorId,\n\t\t\t\texistingGeneration: existingActor.generation,\n\t\t\t\tnewGeneration: generation,\n\t\t\t\texistingPendingRequests: existingActor.pendingRequests.length,\n\t\t\t});\n\t\t}\n\n\t\tthis.#actors.set(actorId, instance);\n\n\t\t// NOTE: We have to populate the requestToActor map BEFORE running any\n\t\t// async code in order for incoming tunnel messages to wait for\n\t\t// instance.actorStartPromise before processing messages\n\t\t// TODO: Where is this GC'd if something fails?\n\t\tfor (const hr of startCommand.hibernatingRequests) {\n\t\t\tthis.#tunnel.addRequestToActor(hr.gatewayId, hr.requestId, actorId);\n\t\t}\n\n\t\tthis.log?.info({\n\t\t\tmsg: \"created actor\",\n\t\t\tactors: this.#actors.size,\n\t\t\tactorId,\n\t\t\tname: config.name,\n\t\t\tkey: config.key,\n\t\t\tgeneration,\n\t\t\thibernatingRequests: startCommand.hibernatingRequests.length,\n\t\t});\n\n\t\tthis.#sendActorStateUpdate(actorId, generation, \"running\");\n\n\t\ttry {\n\t\t\t// TODO: Add timeout to onActorStart\n\t\t\t// Call onActorStart asynchronously and handle errors\n\t\t\tthis.log?.debug({\n\t\t\t\tmsg: \"calling onActorStart\",\n\t\t\t\tactorId,\n\t\t\t\tgeneration,\n\t\t\t});\n\t\t\tawait this.#config.onActorStart(actorId, generation, actorConfig);\n\n\t\t\tinstance.actorStartPromise.resolve();\n\t\t} catch (err) {\n\t\t\tthis.log?.error({\n\t\t\t\tmsg: \"error starting runner actor\",\n\t\t\t\tactorId,\n\t\t\t\terr,\n\t\t\t});\n\n\t\t\tinstance.actorStartPromise.reject(err);\n\n\t\t\t// TODO: Mark as crashed\n\t\t\t// Send stopped state update if start failed\n\t\t\tawait this.forceStopActor(actorId, generation);\n\t\t}\n\t}\n\n\tasync #handleCommandStopActor(commandWrapper: protocol.CommandWrapper) {\n\t\tconst stopCommand = commandWrapper.inner\n\t\t\t.val as protocol.CommandStopActor;\n\n\t\tconst actorId = commandWrapper.checkpoint.actorId;\n\t\tconst generation = commandWrapper.checkpoint.generation;\n\n\t\tawait this.forceStopActor(actorId, generation);\n\t}\n\n\t#sendActorIntent(\n\t\tactorId: string,\n\t\tgeneration: number,\n\t\tintentType: \"sleep\" | \"stop\",\n\t) {\n\t\tconst actor = this.getActor(actorId, generation);\n\t\tif (!actor) return;\n\n\t\tlet actorIntent: protocol.ActorIntent;\n\n\t\tif (intentType === \"sleep\") {\n\t\t\tactorIntent = { tag: \"ActorIntentSleep\", val: null };\n\t\t} else if (intentType === \"stop\") {\n\t\t\tactorIntent = {\n\t\t\t\ttag: \"ActorIntentStop\",\n\t\t\t\tval: null,\n\t\t\t};\n\t\t} else {\n\t\t\tunreachable(intentType);\n\t\t}\n\n\t\tconst intentEvent: protocol.EventActorIntent = {\n\t\t\tintent: actorIntent,\n\t\t};\n\n\t\tconst eventWrapper: protocol.EventWrapper = {\n\t\t\tcheckpoint: {\n\t\t\t\tactorId,\n\t\t\t\tgeneration,\n\t\t\t\tindex: actor.nextEventIdx++,\n\t\t\t},\n\t\t\tinner: {\n\t\t\t\ttag: \"EventActorIntent\",\n\t\t\t\tval: intentEvent,\n\t\t\t},\n\t\t};\n\n\t\tthis.#recordEvent(eventWrapper);\n\n\t\tthis.__sendToServer({\n\t\t\ttag: \"ToServerEvents\",\n\t\t\tval: [eventWrapper],\n\t\t});\n\t}\n\n\t#sendActorStateUpdate(\n\t\tactorId: string,\n\t\tgeneration: number,\n\t\tstateType: \"running\" | \"stopped\",\n\t) {\n\t\tconst actor = this.getActor(actorId, generation);\n\t\tif (!actor) return;\n\n\t\tlet actorState: protocol.ActorState;\n\n\t\tif (stateType === \"running\") {\n\t\t\tactorState = { tag: \"ActorStateRunning\", val: null };\n\t\t} else if (stateType === \"stopped\") {\n\t\t\tactorState = {\n\t\t\t\ttag: \"ActorStateStopped\",\n\t\t\t\tval: {\n\t\t\t\t\tcode: protocol.StopCode.Ok,\n\t\t\t\t\tmessage: null,\n\t\t\t\t},\n\t\t\t};\n\t\t} else {\n\t\t\tunreachable(stateType);\n\t\t}\n\n\t\tconst stateUpdateEvent: protocol.EventActorStateUpdate = {\n\t\t\tstate: actorState,\n\t\t};\n\n\t\tconst eventWrapper: protocol.EventWrapper = {\n\t\t\tcheckpoint: {\n\t\t\t\tactorId,\n\t\t\t\tgeneration,\n\t\t\t\tindex: actor.nextEventIdx++,\n\t\t\t},\n\t\t\tinner: {\n\t\t\t\ttag: \"EventActorStateUpdate\",\n\t\t\t\tval: stateUpdateEvent,\n\t\t\t},\n\t\t};\n\n\t\tthis.#recordEvent(eventWrapper);\n\n\t\tthis.__sendToServer({\n\t\t\ttag: \"ToServerEvents\",\n\t\t\tval: [eventWrapper],\n\t\t});\n\t}\n\n\t#sendCommandAcknowledgment() {\n\t\tconst lastCommandCheckpoints = [];\n\n\t\tfor (const [_, actor] of this.#actors) {\n\t\t\tif (actor.lastCommandIdx < 0) {\n\t\t\t\t// No commands received yet, nothing to acknowledge\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlastCommandCheckpoints.push({\n\t\t\t\tactorId: actor.actorId,\n\t\t\t\tgeneration: actor.generation,\n\t\t\t\tindex: actor.lastCommandIdx,\n\t\t\t});\n\t\t}\n\n\t\t//this.#log?.log(\"Sending command acknowledgment\", this.#lastCommandIdx);\n\n\t\tthis.__sendToServer({\n\t\t\ttag: \"ToServerAckCommands\",\n\t\t\tval: {\n\t\t\t\tlastCommandCheckpoints,\n\t\t\t},\n\t\t});\n\t}\n\n\t#handleKvResponse(response: protocol.ToClientKvResponse) {\n\t\tconst requestId = response.requestId;\n\t\tconst request = this.#kvRequests.get(requestId);\n\n\t\tif (!request) {\n\t\t\tthis.log?.error({\n\t\t\t\tmsg: \"received kv response for unknown request id\",\n\t\t\t\trequestId,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#kvRequests.delete(requestId);\n\n\t\tif (response.data.tag === \"KvErrorResponse\") {\n\t\t\trequest.reject(\n\t\t\t\tnew Error(response.data.val.message || \"Unknown KV error\"),\n\t\t\t);\n\t\t} else {\n\t\t\trequest.resolve(response.data.val);\n\t\t}\n\t}\n\n\t#parseGetResponseSimple(\n\t\tresponse: protocol.KvGetResponse,\n\t\trequestedKeys: Uint8Array[],\n\t): (Uint8Array | null)[] {\n\t\t// Parse the response keys and values\n\t\tconst responseKeys: Uint8Array[] = [];\n\t\tconst responseValues: Uint8Array[] = [];\n\n\t\tfor (const key of response.keys) {\n\t\t\tresponseKeys.push(new Uint8Array(key));\n\t\t}\n\n\t\tfor (const value of response.values) {\n\t\t\tresponseValues.push(new Uint8Array(value));\n\t\t}\n\n\t\t// Map response back to requested key order\n\t\tconst result: (Uint8Array | null)[] = [];\n\t\tfor (const requestedKey of requestedKeys) {\n\t\t\tlet found = false;\n\t\t\tfor (let i = 0; i < responseKeys.length; i++) {\n\t\t\t\tif (this.#keysEqual(requestedKey, responseKeys[i])) {\n\t\t\t\t\tresult.push(responseValues[i]);\n\t\t\t\t\tfound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!found) {\n\t\t\t\tresult.push(null);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t#keysEqual(key1: Uint8Array, key2: Uint8Array): boolean {\n\t\tif (key1.length !== key2.length) return false;\n\t\tfor (let i = 0; i < key1.length; i++) {\n\t\t\tif (key1[i] !== key2[i]) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t//#parseGetResponse(response: protocol.KvGetResponse) {\n\t//\tconst keys: string[] = [];\n\t//\tconst values: Uint8Array[] = [];\n\t//\tconst metadata: { version: Uint8Array; createTs: bigint }[] = [];\n\t//\n\t//\tfor (const key of response.keys) {\n\t//\t\tkeys.push(new TextDecoder().decode(key));\n\t//\t}\n\t//\n\t//\tfor (const value of response.values) {\n\t//\t\tvalues.push(new Uint8Array(value));\n\t//\t}\n\t//\n\t//\tfor (const meta of response.metadata) {\n\t//\t\tmetadata.push({\n\t//\t\t\tversion: new Uint8Array(meta.version),\n\t//\t\t\tcreateTs: meta.createTs,\n\t//\t\t});\n\t//\t}\n\t//\n\t//\treturn { keys, values, metadata };\n\t//}\n\n\t#parseListResponseSimple(\n\t\tresponse: protocol.KvListResponse,\n\t): [Uint8Array, Uint8Array][] {\n\t\tconst result: [Uint8Array, Uint8Array][] = [];\n\n\t\tfor (let i = 0; i < response.keys.length; i++) {\n\t\t\tconst key = response.keys[i];\n\t\t\tconst value = response.values[i];\n\n\t\t\tif (key && value) {\n\t\t\t\tconst keyBytes = new Uint8Array(key);\n\t\t\t\tconst valueBytes = new Uint8Array(value);\n\t\t\t\tresult.push([keyBytes, valueBytes]);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t//#parseListResponse(response: protocol.KvListResponse) {\n\t//\tconst keys: string[] = [];\n\t//\tconst values: Uint8Array[] = [];\n\t//\tconst metadata: { version: Uint8Array; createTs: bigint }[] = [];\n\t//\n\t//\tfor (const key of response.keys) {\n\t//\t\tkeys.push(new TextDecoder().decode(key));\n\t//\t}\n\t//\n\t//\tfor (const value of response.values) {\n\t//\t\tvalues.push(new Uint8Array(value));\n\t//\t}\n\t//\n\t//\tfor (const meta of response.metadata) {\n\t//\t\tmetadata.push({\n\t//\t\t\tversion: new Uint8Array(meta.version),\n\t//\t\t\tcreateTs: meta.createTs,\n\t//\t\t});\n\t//\t}\n\t//\n\t//\treturn { keys, values, metadata };\n\t//}\n\n\t// MARK: KV Operations\n\tasync kvGet(\n\t\tactorId: string,\n\t\tkeys: Uint8Array[],\n\t): Promise<(Uint8Array | null)[]> {\n\t\tconst kvKeys: protocol.KvKey[] = keys.map(\n\t\t\t(key) =>\n\t\t\t\tkey.buffer.slice(\n\t\t\t\t\tkey.byteOffset,\n\t\t\t\t\tkey.byteOffset + key.byteLength,\n\t\t\t\t) as ArrayBuffer,\n\t\t);\n\n\t\tconst requestData: protocol.KvRequestData = {\n\t\t\ttag: \"KvGetRequest\",\n\t\t\tval: { keys: kvKeys },\n\t\t};\n\n\t\tconst response = await this.#sendKvRequest(actorId, requestData);\n\t\treturn this.#parseGetResponseSimple(response, keys);\n\t}\n\n\tasync kvListAll(\n\t\tactorId: string,\n\t\toptions?: KvListOptions,\n\t): Promise<[Uint8Array, Uint8Array][]> {\n\t\tconst requestData: protocol.KvRequestData = {\n\t\t\ttag: \"KvListRequest\",\n\t\t\tval: {\n\t\t\t\tquery: { tag: \"KvListAllQuery\", val: null },\n\t\t\t\treverse: options?.reverse || null,\n\t\t\t\tlimit:\n\t\t\t\t\toptions?.limit !== undefined ? BigInt(options.limit) : null,\n\t\t\t},\n\t\t};\n\n\t\tconst response = await this.#sendKvRequest(actorId, requestData);\n\t\treturn this.#parseListResponseSimple(response);\n\t}\n\n\tasync kvListRange(\n\t\tactorId: string,\n\t\tstart: Uint8Array,\n\t\tend: Uint8Array,\n\t\texclusive?: boolean,\n\t\toptions?: KvListOptions,\n\t): Promise<[Uint8Array, Uint8Array][]> {\n\t\tconst startKey: protocol.KvKey = start.buffer.slice(\n\t\t\tstart.byteOffset,\n\t\t\tstart.byteOffset + start.byteLength,\n\t\t) as ArrayBuffer;\n\t\tconst endKey: protocol.KvKey = end.buffer.slice(\n\t\t\tend.byteOffset,\n\t\t\tend.byteOffset + end.byteLength,\n\t\t) as ArrayBuffer;\n\n\t\tconst requestData: protocol.KvRequestData = {\n\t\t\ttag: \"KvListRequest\",\n\t\t\tval: {\n\t\t\t\tquery: {\n\t\t\t\t\ttag: \"KvListRangeQuery\",\n\t\t\t\t\tval: {\n\t\t\t\t\t\tstart: startKey,\n\t\t\t\t\t\tend: endKey,\n\t\t\t\t\t\texclusive: exclusive || false,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\treverse: options?.reverse || null,\n\t\t\t\tlimit:\n\t\t\t\t\toptions?.limit !== undefined ? BigInt(options.limit) : null,\n\t\t\t},\n\t\t};\n\n\t\tconst response = await this.#sendKvRequest(actorId, requestData);\n\t\treturn this.#parseListResponseSimple(response);\n\t}\n\n\tasync kvListPrefix(\n\t\tactorId: string,\n\t\tprefix: Uint8Array,\n\t\toptions?: KvListOptions,\n\t): Promise<[Uint8Array, Uint8Array][]> {\n\t\tconst prefixKey: protocol.KvKey = prefix.buffer.slice(\n\t\t\tprefix.byteOffset,\n\t\t\tprefix.byteOffset + prefix.byteLength,\n\t\t) as ArrayBuffer;\n\n\t\tconst requestData: protocol.KvRequestData = {\n\t\t\ttag: \"KvListRequest\",\n\t\t\tval: {\n\t\t\t\tquery: {\n\t\t\t\t\ttag: \"KvListPrefixQuery\",\n\t\t\t\t\tval: { key: prefixKey },\n\t\t\t\t},\n\t\t\t\treverse: options?.reverse || null,\n\t\t\t\tlimit:\n\t\t\t\t\toptions?.limit !== undefined ? BigInt(options.limit) : null,\n\t\t\t},\n\t\t};\n\n\t\tconst response = await this.#sendKvRequest(actorId, requestData);\n\t\treturn this.#parseListResponseSimple(response);\n\t}\n\n\tasync kvPut(\n\t\tactorId: string,\n\t\tentries: [Uint8Array, Uint8Array][],\n\t): Promise<void> {\n\t\tconst keys: protocol.KvKey[] = entries.map(\n\t\t\t([key, _value]) =>\n\t\t\t\tkey.buffer.slice(\n\t\t\t\t\tkey.byteOffset,\n\t\t\t\t\tkey.byteOffset + key.byteLength,\n\t\t\t\t) as ArrayBuffer,\n\t\t);\n\t\tconst values: protocol.KvValue[] = entries.map(\n\t\t\t([_key, value]) =>\n\t\t\t\tvalue.buffer.slice(\n\t\t\t\t\tvalue.byteOffset,\n\t\t\t\t\tvalue.byteOffset + value.byteLength,\n\t\t\t\t) as ArrayBuffer,\n\t\t);\n\n\t\tconst requestData: protocol.KvRequestData = {\n\t\t\ttag: \"KvPutRequest\",\n\t\t\tval: { keys, values },\n\t\t};\n\n\t\tawait this.#sendKvRequest(actorId, requestData);\n\t}\n\n\tasync kvDelete(actorId: string, keys: Uint8Array[]): Promise<void> {\n\t\tconst kvKeys: protocol.KvKey[] = keys.map(\n\t\t\t(key) =>\n\t\t\t\tkey.buffer.slice(\n\t\t\t\t\tkey.byteOffset,\n\t\t\t\t\tkey.byteOffset + key.byteLength,\n\t\t\t\t) as ArrayBuffer,\n\t\t);\n\n\t\tconst requestData: protocol.KvRequestData = {\n\t\t\ttag: \"KvDeleteRequest\",\n\t\t\tval: { keys: kvKeys },\n\t\t};\n\n\t\tawait this.#sendKvRequest(actorId, requestData);\n\t}\n\n\tasync kvDrop(actorId: string): Promise<void> {\n\t\tconst requestData: protocol.KvRequestData = {\n\t\t\ttag: \"KvDropRequest\",\n\t\t\tval: null,\n\t\t};\n\n\t\tawait this.#sendKvRequest(actorId, requestData);\n\t}\n\n\t// MARK: Alarm Operations\n\tsetAlarm(actorId: string, alarmTs: number | null, generation?: number) {\n\t\tconst actor = this.getActor(actorId, generation);\n\t\tif (!actor) return;\n\n\t\tconst alarmEvent: protocol.EventActorSetAlarm = {\n\t\t\talarmTs: alarmTs !== null ? BigInt(alarmTs) : null,\n\t\t};\n\n\t\tconst eventWrapper: protocol.EventWrapper = {\n\t\t\tcheckpoint: {\n\t\t\t\tactorId,\n\t\t\t\tgeneration: actor.generation,\n\t\t\t\tindex: actor.nextEventIdx++,\n\t\t\t},\n\t\t\tinner: {\n\t\t\t\ttag: \"EventActorSetAlarm\",\n\t\t\t\tval: alarmEvent,\n\t\t\t},\n\t\t};\n\n\t\tthis.#recordEvent(eventWrapper);\n\n\t\tthis.__sendToServer({\n\t\t\ttag: \"ToServerEvents\",\n\t\t\tval: [eventWrapper],\n\t\t});\n\t}\n\n\tclearAlarm(actorId: string, generation?: number) {\n\t\tthis.setAlarm(actorId, null, generation);\n\t}\n\n\t#sendKvRequest(\n\t\tactorId: string,\n\t\trequestData: protocol.KvRequestData,\n\t): Promise<any> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst requestId = this.#nextKvRequestId++;\n\n\t\t\t// Store the request\n\t\t\tconst requestEntry = {\n\t\t\t\tactorId,\n\t\t\t\tdata: requestData,\n\t\t\t\tresolve,\n\t\t\t\treject,\n\t\t\t\tsent: false,\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t};\n\n\t\t\tthis.#kvRequests.set(requestId, requestEntry);\n\n\t\t\tif (this.__webSocketReady()) {\n\t\t\t\t// Send immediately\n\t\t\t\tthis.#sendSingleKvRequest(requestId);\n\t\t\t}\n\t\t});\n\t}\n\n\t#sendSingleKvRequest(requestId: number) {\n\t\tconst request = this.#kvRequests.get(requestId);\n\t\tif (!request || request.sent) return;\n\n\t\ttry {\n\t\t\tconst kvRequest: protocol.ToServerKvRequest = {\n\t\t\t\tactorId: request.actorId,\n\t\t\t\trequestId,\n\t\t\t\tdata: request.data,\n\t\t\t};\n\n\t\t\tthis.__sendToServer({\n\t\t\t\ttag: \"ToServerKvRequest\",\n\t\t\t\tval: kvRequest,\n\t\t\t});\n\n\t\t\t// Mark as sent and update timestamp\n\t\t\trequest.sent = true;\n\t\t\trequest.timestamp = Date.now();\n\t\t} catch (error) {\n\t\t\tthis.#kvRequests.delete(requestId);\n\t\t\trequest.reject(error);\n\t\t}\n\t}\n\n\t#processUnsentKvRequests() {\n\t\tif (!this.__webSocketReady()) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet processedCount = 0;\n\t\tfor (const [requestId, request] of this.#kvRequests.entries()) {\n\t\t\tif (!request.sent) {\n\t\t\t\tthis.#sendSingleKvRequest(requestId);\n\t\t\t\tprocessedCount++;\n\t\t\t}\n\t\t}\n\n\t\tif (processedCount > 0) {\n\t\t\t//this.#log?.log(`Processed ${processedCount} queued KV requests`);\n\t\t}\n\t}\n\n\t/** Asserts WebSocket exists and is ready. */\n\t__webSocketReady(): this is this & {\n\t\t__pegboardWebSocket: NonNullable<Runner[\"__pegboardWebSocket\"]>;\n\t} {\n\t\treturn (\n\t\t\t!!this.__pegboardWebSocket &&\n\t\t\tthis.__pegboardWebSocket.readyState === 1\n\t\t);\n\t}\n\n\t__sendToServer(message: protocol.ToServer) {\n\t\tthis.log?.debug({\n\t\t\tmsg: \"sending runner message\",\n\t\t\tdata: stringifyToServer(message),\n\t\t});\n\n\t\tconst encoded = protocol.encodeToServer(message);\n\t\tif (this.__webSocketReady()) {\n\t\t\tthis.__pegboardWebSocket.send(encoded);\n\t\t} else {\n\t\t\tthis.log?.error({\n\t\t\t\tmsg: \"WebSocket not available or not open for sending data\",\n\t\t\t});\n\t\t}\n\t}\n\n\tsendHibernatableWebSocketMessageAck(\n\t\tgatewayId: ArrayBuffer,\n\t\trequestId: ArrayBuffer,\n\t\tindex: number,\n\t) {\n\t\tif (!this.#tunnel)\n\t\t\tthrow new Error(\"missing tunnel to send message ack\");\n\t\tthis.#tunnel.sendHibernatableWebSocketMessageAck(\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t\tindex,\n\t\t);\n\t}\n\n\t/**\n\t * Restores hibernatable WebSocket connections for an actor.\n\t *\n\t * This method should be called at the end of `onActorStart` after the\n\t * actor instance is fully initialized.\n\t *\n\t * This method will:\n\t * - Restore all provided hibernatable WebSocket connections\n\t * - Attach event listeners to the restored WebSockets\n\t * - Close any WebSocket connections that failed to restore\n\t *\n\t * The provided metadata list should include all hibernatable WebSockets\n\t * that were persisted for this actor. The gateway will automatically\n\t * close any connections that are not restored (i.e., not included in\n\t * this list).\n\t *\n\t * **Important:** This method must be called after `onActorStart` completes\n\t * and before marking the actor as \"ready\" to ensure all hibernatable\n\t * connections are fully restored.\n\t *\n\t * @param actorId - The ID of the actor to restore connections for\n\t * @param metaEntries - Array of hibernatable WebSocket metadata to restore\n\t */\n\tasync restoreHibernatingRequests(\n\t\tactorId: string,\n\t\tmetaEntries: HibernatingWebSocketMetadata[],\n\t) {\n\t\tif (!this.#tunnel)\n\t\t\tthrow new Error(\"missing tunnel to restore hibernating requests\");\n\t\tawait this.#tunnel.restoreHibernatingRequests(actorId, metaEntries);\n\t}\n\n\tgetServerlessInitPacket(): string | undefined {\n\t\tif (!this.runnerId) return undefined;\n\n\t\tconst data = protocol.encodeToServerlessServer({\n\t\t\ttag: \"ToServerlessServerInit\",\n\t\t\tval: {\n\t\t\t\trunnerId: this.runnerId,\n\t\t\t\trunnerProtocolVersion: PROTOCOL_VERSION,\n\t\t\t},\n\t\t});\n\n\t\t// Embed version\n\t\tconst buffer = Buffer.alloc(data.length + 2);\n\t\tbuffer.writeUInt16LE(PROTOCOL_VERSION, 0);\n\t\tBuffer.from(data).copy(buffer, 2);\n\n\t\treturn buffer.toString(\"base64\");\n\t}\n\n\t#scheduleReconnect() {\n\t\tif (this.#shutdown) {\n\t\t\tthis.log?.debug({\n\t\t\t\tmsg: \"Runner is shut down, not attempting reconnect\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconst delay = calculateBackoff(this.#reconnectAttempt, {\n\t\t\tinitialDelay: 1000,\n\t\t\tmaxDelay: 30000,\n\t\t\tmultiplier: 2,\n\t\t\tjitter: true,\n\t\t});\n\n\t\tthis.log?.debug({\n\t\t\tmsg: `Scheduling reconnect attempt ${this.#reconnectAttempt + 1} in ${delay}ms`,\n\t\t});\n\n\t\tthis.#reconnectTimeout = setTimeout(() => {\n\t\t\tif (!this.#shutdown) {\n\t\t\t\tthis.#reconnectAttempt++;\n\t\t\t\tthis.log?.debug({\n\t\t\t\t\tmsg: `Attempting to reconnect (attempt ${this.#reconnectAttempt})...`,\n\t\t\t\t});\n\t\t\t\tthis.#openPegboardWebSocket().catch((err) => {\n\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\tmsg: \"error during websocket reconnection\",\n\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\t\t}, delay);\n\t}\n\n\t#resendUnacknowledgedEvents() {\n\t\tconst eventsToResend = [];\n\n\t\tfor (const [_, actor] of this.#actors) {\n\t\t\teventsToResend.push(...actor.eventHistory);\n\t\t}\n\n\t\tif (eventsToResend.length === 0) return;\n\n\t\tthis.log?.info({\n\t\t\tmsg: \"resending unacknowledged events\",\n\t\t\tcount: eventsToResend.length,\n\t\t});\n\n\t\t// Resend events in batches\n\t\tthis.__sendToServer({\n\t\t\ttag: \"ToServerEvents\",\n\t\t\tval: eventsToResend,\n\t\t});\n\t}\n\n\t#cleanupOldKvRequests() {\n\t\tconst thirtySecondsAgo = Date.now() - KV_EXPIRE;\n\t\tconst toDelete: number[] = [];\n\n\t\tfor (const [requestId, request] of this.#kvRequests.entries()) {\n\t\t\tif (request.timestamp < thirtySecondsAgo) {\n\t\t\t\trequest.reject(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\"KV request timed out waiting for WebSocket connection\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\ttoDelete.push(requestId);\n\t\t\t}\n\t\t}\n\n\t\tfor (const requestId of toDelete) {\n\t\t\tthis.#kvRequests.delete(requestId);\n\t\t}\n\n\t\tif (toDelete.length > 0) {\n\t\t\t//this.#log?.log(`Cleaned up ${toDelete.length} expired KV requests`);\n\t\t}\n\t}\n}\n","import type { Logger } from \"pino\";\n\nlet LOGGER: Logger | undefined;\n\nexport function setLogger(logger: Logger) {\n\tLOGGER = logger;\n}\n\nexport function logger(): Logger | undefined {\n\treturn LOGGER;\n}\n","import { logger } from \"./log\";\n\nexport function unreachable(x: never): never {\n\tthrow `Unreachable: ${x}`;\n}\n\nexport interface BackoffOptions {\n\tinitialDelay?: number;\n\tmaxDelay?: number;\n\tmultiplier?: number;\n\tjitter?: boolean;\n}\n\nexport function calculateBackoff(\n\tattempt: number,\n\toptions: BackoffOptions = {},\n): number {\n\tconst {\n\t\tinitialDelay = 1000,\n\t\tmaxDelay = 30000,\n\t\tmultiplier = 2,\n\t\tjitter = true,\n\t} = options;\n\n\tlet delay = Math.min(initialDelay * multiplier ** attempt, maxDelay);\n\n\tif (jitter) {\n\t\t// Add random jitter between 0% and 25% of the delay\n\t\tdelay = delay * (1 + Math.random() * 0.25);\n\t}\n\n\treturn Math.floor(delay);\n}\n\nexport interface ParsedCloseReason {\n\tgroup: string;\n\terror: string;\n\trayId?: string;\n}\n\n/**\n * Parses a WebSocket close reason in the format: {group}.{error} or {group}.{error}#{ray_id}\n *\n * Examples:\n * - \"ws.eviction#t1s80so6h3irenp8ymzltfoittcl00\"\n * - \"ws.client_closed\"\n *\n * Returns undefined if the format is invalid\n */\nexport function parseWebSocketCloseReason(\n\treason: string,\n): ParsedCloseReason | undefined {\n\tconst [mainPart, rayId] = reason.split(\"#\");\n\tconst [group, error] = mainPart.split(\".\");\n\n\tif (!group || !error) {\n\t\tlogger()?.warn({ msg: \"failed to parse close reason\", reason });\n\t\treturn undefined;\n\t}\n\n\treturn {\n\t\tgroup,\n\t\terror,\n\t\trayId,\n\t};\n}\n\nconst U16_MAX = 65535;\n\n/**\n * Wrapping greater than comparison for u16 values.\n * Based on shared_state.rs wrapping_gt implementation.\n */\nexport function wrappingGtU16(a: number, b: number): boolean {\n\treturn a !== b && wrappingSub(a, b, U16_MAX) < U16_MAX / 2;\n}\n\n/**\n * Wrapping less than comparison for u16 values.\n * Based on shared_state.rs wrapping_lt implementation.\n */\nexport function wrappingLtU16(a: number, b: number): boolean {\n\treturn a !== b && wrappingSub(b, a, U16_MAX) < U16_MAX / 2;\n}\n\n/**\n * Wrapping greater than or equal comparison for u16 values.\n */\nexport function wrappingGteU16(a: number, b: number): boolean {\n\treturn a === b || wrappingGtU16(a, b);\n}\n\n/**\n * Wrapping less than or equal comparison for u16 values.\n */\nexport function wrappingLteU16(a: number, b: number): boolean {\n\treturn a === b || wrappingLtU16(a, b);\n}\n\n/**\n * Performs wrapping addition for u16 values.\n */\nexport function wrappingAddU16(a: number, b: number): number {\n\treturn (a + b) % (U16_MAX + 1);\n}\n\n/**\n * Performs wrapping subtraction for u16 values.\n */\nexport function wrappingSubU16(a: number, b: number): number {\n\treturn wrappingSub(a, b, U16_MAX);\n}\n\n/**\n * Performs wrapping subtraction for unsigned integers.\n */\nfunction wrappingSub(a: number, b: number, max: number): number {\n\tconst result = a - b;\n\tif (result < 0) {\n\t\treturn result + max + 1;\n\t}\n\treturn result;\n}\n\nexport function arraysEqual(a: ArrayBuffer, b: ArrayBuffer): boolean {\n\tconst ua = new Uint8Array(a);\n\tconst ub = new Uint8Array(b);\n\tif (ua.length !== ub.length) return false;\n\tfor (let i = 0; i < ua.length; i++) {\n\t\tif (ua[i] !== ub[i]) return false;\n\t}\n\treturn true;\n}\n\n/**\n * Polyfill for Promise.withResolvers().\n *\n * This is specifically for Cloudflare Workers. Their implementation of Promise.withResolvers does not work correctly.\n */\nexport function promiseWithResolvers<T>(): {\n\tpromise: Promise<T>;\n\tresolve: (value: T | PromiseLike<T>) => void;\n\treject: (reason?: any) => void;\n} {\n\tlet resolve!: (value: T | PromiseLike<T>) => void;\n\tlet reject!: (reason?: any) => void;\n\tconst promise = new Promise<T>((res, rej) => {\n\t\tresolve = res;\n\t\treject = rej;\n\t});\n\treturn { promise, resolve, reject };\n}\n\nexport function idToStr(id: ArrayBuffer): string {\n\tconst bytes = new Uint8Array(id);\n\treturn Array.from(bytes)\n\t\t.map((byte) => byte.toString(16).padStart(2, \"0\"))\n\t\t.join(\"\");\n}\n\nexport function stringifyError(error: unknown): string {\n\tif (error instanceof Error) {\n\t\treturn `${error.name}: ${error.message}${error.stack ? `\\n${error.stack}` : \"\"}`;\n\t} else if (typeof error === \"string\") {\n\t\treturn error;\n\t} else if (typeof error === \"object\" && error !== null) {\n\t\ttry {\n\t\t\treturn `${JSON.stringify(error)}`;\n\t\t} catch {\n\t\t\treturn `[object ${error.constructor?.name || \"Object\"}]`;\n\t\t}\n\t} else {\n\t\treturn String(error);\n\t}\n}\n","import type * as protocol from \"@rivetkit/engine-runner-protocol\";\nimport { logger } from \"./log\";\nimport type { PendingRequest } from \"./tunnel\";\nimport { arraysEqual, idToStr, promiseWithResolvers } from \"./utils\";\nimport type { WebSocketTunnelAdapter } from \"./websocket-tunnel-adapter\";\n\nexport interface ActorConfig {\n\tname: string;\n\tkey: string | null;\n\tcreateTs: bigint;\n\tinput: Uint8Array | null;\n}\n\nexport class RunnerActor {\n\tactorId: string;\n\tgeneration: number;\n\tconfig: ActorConfig;\n\tpendingRequests: Array<{\n\t\tgatewayId: protocol.GatewayId;\n\t\trequestId: protocol.RequestId;\n\t\trequest: PendingRequest;\n\t}> = [];\n\twebSockets: Array<{\n\t\tgatewayId: protocol.GatewayId;\n\t\trequestId: protocol.RequestId;\n\t\tws: WebSocketTunnelAdapter;\n\t}> = [];\n\tactorStartPromise: ReturnType<typeof promiseWithResolvers<void>>;\n\n\tlastCommandIdx: bigint = -1n;\n\tnextEventIdx: bigint = 0n;\n\teventHistory: protocol.EventWrapper[] = [];\n\n\t/**\n\t * If restoreHibernatingRequests has been called. This is used to assert\n\t * that the caller is implemented correctly.\n\t **/\n\thibernationRestored: boolean = false;\n\n\tconstructor(\n\t\tactorId: string,\n\t\tgeneration: number,\n\t\tconfig: ActorConfig,\n\t\t/**\n\t\t * List of hibernating requests provided by the gateway on actor start.\n\t\t * This represents the WebSocket connections that the gateway knows about.\n\t\t **/\n\t\tpublic hibernatingRequests: readonly protocol.HibernatingRequest[],\n\t) {\n\t\tthis.actorId = actorId;\n\t\tthis.generation = generation;\n\t\tthis.config = config;\n\t\tthis.actorStartPromise = promiseWithResolvers();\n\t}\n\n\t// Pending request methods\n\tgetPendingRequest(\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t): PendingRequest | undefined {\n\t\treturn this.pendingRequests.find(\n\t\t\t(entry) =>\n\t\t\t\tarraysEqual(entry.gatewayId, gatewayId) &&\n\t\t\t\tarraysEqual(entry.requestId, requestId),\n\t\t)?.request;\n\t}\n\n\tcreatePendingRequest(\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t\tclientMessageIndex: number,\n\t) {\n\t\tconst exists =\n\t\t\tthis.getPendingRequest(gatewayId, requestId) !== undefined;\n\t\tif (exists) {\n\t\t\tlogger()?.warn({\n\t\t\t\tmsg: \"attempting to set pending request twice, replacing existing\",\n\t\t\t\tgatewayId: idToStr(gatewayId),\n\t\t\t\trequestId: idToStr(requestId),\n\t\t\t});\n\t\t\t// Delete existing pending request before adding the new one\n\t\t\tthis.deletePendingRequest(gatewayId, requestId);\n\t\t}\n\t\tthis.pendingRequests.push({\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t\trequest: {\n\t\t\t\tresolve: () => {},\n\t\t\t\treject: () => {},\n\t\t\t\tactorId: this.actorId,\n\t\t\t\tgatewayId: gatewayId,\n\t\t\t\trequestId: requestId,\n\t\t\t\tclientMessageIndex,\n\t\t\t},\n\t\t});\n\t\tlogger()?.debug({\n\t\t\tmsg: \"added pending request\",\n\t\t\tgatewayId: idToStr(gatewayId),\n\t\t\trequestId: idToStr(requestId),\n\t\t\tlength: this.pendingRequests.length,\n\t\t});\n\t}\n\n\tcreatePendingRequestWithStreamController(\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t\tclientMessageIndex: number,\n\t\tstreamController: ReadableStreamDefaultController<Uint8Array>,\n\t) {\n\t\tconst exists =\n\t\t\tthis.getPendingRequest(gatewayId, requestId) !== undefined;\n\t\tif (exists) {\n\t\t\tlogger()?.warn({\n\t\t\t\tmsg: \"attempting to set pending request twice, replacing existing\",\n\t\t\t\tgatewayId: idToStr(gatewayId),\n\t\t\t\trequestId: idToStr(requestId),\n\t\t\t});\n\t\t\t// Delete existing pending request before adding the new one\n\t\t\tthis.deletePendingRequest(gatewayId, requestId);\n\t\t}\n\t\tthis.pendingRequests.push({\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t\trequest: {\n\t\t\t\tresolve: () => {},\n\t\t\t\treject: () => {},\n\t\t\t\tactorId: this.actorId,\n\t\t\t\tgatewayId: gatewayId,\n\t\t\t\trequestId: requestId,\n\t\t\t\tclientMessageIndex,\n\t\t\t\tstreamController,\n\t\t\t},\n\t\t});\n\t\tlogger()?.debug({\n\t\t\tmsg: \"added pending request with stream controller\",\n\t\t\tgatewayId: idToStr(gatewayId),\n\t\t\trequestId: idToStr(requestId),\n\t\t\tlength: this.pendingRequests.length,\n\t\t});\n\t}\n\n\tdeletePendingRequest(\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t) {\n\t\tconst index = this.pendingRequests.findIndex(\n\t\t\t(entry) =>\n\t\t\t\tarraysEqual(entry.gatewayId, gatewayId) &&\n\t\t\t\tarraysEqual(entry.requestId, requestId),\n\t\t);\n\t\tif (index !== -1) {\n\t\t\tthis.pendingRequests.splice(index, 1);\n\t\t\tlogger()?.debug({\n\t\t\t\tmsg: \"removed pending request\",\n\t\t\t\tgatewayId: idToStr(gatewayId),\n\t\t\t\trequestId: idToStr(requestId),\n\t\t\t\tlength: this.pendingRequests.length,\n\t\t\t});\n\t\t}\n\t}\n\n\t// WebSocket methods\n\tgetWebSocket(\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t): WebSocketTunnelAdapter | undefined {\n\t\treturn this.webSockets.find(\n\t\t\t(entry) =>\n\t\t\t\tarraysEqual(entry.gatewayId, gatewayId) &&\n\t\t\t\tarraysEqual(entry.requestId, requestId),\n\t\t)?.ws;\n\t}\n\n\tsetWebSocket(\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t\tws: WebSocketTunnelAdapter,\n\t) {\n\t\tconst exists = this.getWebSocket(gatewayId, requestId) !== undefined;\n\t\tif (exists) {\n\t\t\tlogger()?.warn({ msg: \"attempting to set websocket twice\" });\n\t\t\treturn;\n\t\t}\n\t\tthis.webSockets.push({ gatewayId, requestId, ws });\n\t}\n\n\tdeleteWebSocket(\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t) {\n\t\tconst index = this.webSockets.findIndex(\n\t\t\t(entry) =>\n\t\t\t\tarraysEqual(entry.gatewayId, gatewayId) &&\n\t\t\t\tarraysEqual(entry.requestId, requestId),\n\t\t);\n\t\tif (index !== -1) {\n\t\t\tthis.webSockets.splice(index, 1);\n\t\t}\n\t}\n\n\thandleAckEvents(lastEventIdx: bigint) {\n\t\tthis.eventHistory = this.eventHistory.filter(\n\t\t\t(event) => event.checkpoint.index > lastEventIdx,\n\t\t);\n\t}\n\n\trecordEvent(eventWrapper: protocol.EventWrapper) {\n\t\tthis.eventHistory.push(eventWrapper);\n\t}\n}\n","import type * as protocol from \"@rivetkit/engine-runner-protocol\";\nimport { idToStr } from \"./utils\";\n\n/**\n * Helper function to stringify ArrayBuffer for logging\n */\nfunction stringifyArrayBuffer(buffer: ArrayBuffer): string {\n\treturn `ArrayBuffer(${buffer.byteLength})`;\n}\n\n/**\n * Helper function to stringify bigint for logging\n */\nfunction stringifyBigInt(value: bigint): string {\n\treturn `${value}n`;\n}\n\n/**\n * Helper function to stringify Map for logging\n */\nfunction stringifyMap(map: ReadonlyMap<string, string>): string {\n\tconst entries = Array.from(map.entries())\n\t\t.map(([k, v]) => `\"${k}\": \"${v}\"`)\n\t\t.join(\", \");\n\treturn `Map(${map.size}){${entries}}`;\n}\n\n/**\n * Helper function to stringify MessageId for logging\n */\nfunction stringifyMessageId(messageId: protocol.MessageId): string {\n\treturn `MessageId{gatewayId: ${idToStr(messageId.gatewayId)}, requestId: ${idToStr(messageId.requestId)}, messageIndex: ${messageId.messageIndex}}`;\n}\n\n/**\n * Stringify ToServerTunnelMessageKind for logging\n * Handles ArrayBuffers, BigInts, and Maps that can't be JSON.stringified\n */\nexport function stringifyToServerTunnelMessageKind(\n\tkind: protocol.ToServerTunnelMessageKind,\n): string {\n\tswitch (kind.tag) {\n\t\tcase \"ToServerResponseStart\": {\n\t\t\tconst { status, headers, body, stream } = kind.val;\n\t\t\tconst bodyStr = body === null ? \"null\" : stringifyArrayBuffer(body);\n\t\t\treturn `ToServerResponseStart{status: ${status}, headers: ${stringifyMap(headers)}, body: ${bodyStr}, stream: ${stream}}`;\n\t\t}\n\t\tcase \"ToServerResponseChunk\": {\n\t\t\tconst { body, finish } = kind.val;\n\t\t\treturn `ToServerResponseChunk{body: ${stringifyArrayBuffer(body)}, finish: ${finish}}`;\n\t\t}\n\t\tcase \"ToServerResponseAbort\":\n\t\t\treturn \"ToServerResponseAbort\";\n\t\tcase \"ToServerWebSocketOpen\": {\n\t\t\tconst { canHibernate } = kind.val;\n\t\t\treturn `ToServerWebSocketOpen{canHibernate: ${canHibernate}}`;\n\t\t}\n\t\tcase \"ToServerWebSocketMessage\": {\n\t\t\tconst { data, binary } = kind.val;\n\t\t\treturn `ToServerWebSocketMessage{data: ${stringifyArrayBuffer(data)}, binary: ${binary}}`;\n\t\t}\n\t\tcase \"ToServerWebSocketMessageAck\": {\n\t\t\tconst { index } = kind.val;\n\t\t\treturn `ToServerWebSocketMessageAck{index: ${index}}`;\n\t\t}\n\t\tcase \"ToServerWebSocketClose\": {\n\t\t\tconst { code, reason, hibernate } = kind.val;\n\t\t\tconst codeStr = code === null ? \"null\" : code.toString();\n\t\t\tconst reasonStr = reason === null ? \"null\" : `\"${reason}\"`;\n\t\t\treturn `ToServerWebSocketClose{code: ${codeStr}, reason: ${reasonStr}, hibernate: ${hibernate}}`;\n\t\t}\n\t}\n}\n\n/**\n * Stringify ToClientTunnelMessageKind for logging\n * Handles ArrayBuffers, BigInts, and Maps that can't be JSON.stringified\n */\nexport function stringifyToClientTunnelMessageKind(\n\tkind: protocol.ToClientTunnelMessageKind,\n): string {\n\tswitch (kind.tag) {\n\t\tcase \"ToClientRequestStart\": {\n\t\t\tconst { actorId, method, path, headers, body, stream } = kind.val;\n\t\t\tconst bodyStr = body === null ? \"null\" : stringifyArrayBuffer(body);\n\t\t\treturn `ToClientRequestStart{actorId: \"${actorId}\", method: \"${method}\", path: \"${path}\", headers: ${stringifyMap(headers)}, body: ${bodyStr}, stream: ${stream}}`;\n\t\t}\n\t\tcase \"ToClientRequestChunk\": {\n\t\t\tconst { body, finish } = kind.val;\n\t\t\treturn `ToClientRequestChunk{body: ${stringifyArrayBuffer(body)}, finish: ${finish}}`;\n\t\t}\n\t\tcase \"ToClientRequestAbort\":\n\t\t\treturn \"ToClientRequestAbort\";\n\t\tcase \"ToClientWebSocketOpen\": {\n\t\t\tconst { actorId, path, headers } = kind.val;\n\t\t\treturn `ToClientWebSocketOpen{actorId: \"${actorId}\", path: \"${path}\", headers: ${stringifyMap(headers)}}`;\n\t\t}\n\t\tcase \"ToClientWebSocketMessage\": {\n\t\t\tconst { data, binary } = kind.val;\n\t\t\treturn `ToClientWebSocketMessage{data: ${stringifyArrayBuffer(data)}, binary: ${binary}}`;\n\t\t}\n\t\tcase \"ToClientWebSocketClose\": {\n\t\t\tconst { code, reason } = kind.val;\n\t\t\tconst codeStr = code === null ? \"null\" : code.toString();\n\t\t\tconst reasonStr = reason === null ? \"null\" : `\"${reason}\"`;\n\t\t\treturn `ToClientWebSocketClose{code: ${codeStr}, reason: ${reasonStr}}`;\n\t\t}\n\t}\n}\n\n/**\n * Stringify Command for logging\n * Handles ArrayBuffers, BigInts, and Maps that can't be JSON.stringified\n */\nexport function stringifyCommand(command: protocol.Command): string {\n\tswitch (command.tag) {\n\t\tcase \"CommandStartActor\": {\n\t\t\tconst { config, hibernatingRequests } = command.val;\n\t\t\tconst keyStr = config.key === null ? \"null\" : `\"${config.key}\"`;\n\t\t\tconst inputStr =\n\t\t\t\tconfig.input === null\n\t\t\t\t\t? \"null\"\n\t\t\t\t\t: stringifyArrayBuffer(config.input);\n\t\t\tconst hibernatingRequestsStr =\n\t\t\t\thibernatingRequests.length > 0\n\t\t\t\t\t? `[${hibernatingRequests.map((hr) => `{gatewayId: ${idToStr(hr.gatewayId)}, requestId: ${idToStr(hr.requestId)}}`).join(\", \")}]`\n\t\t\t\t\t: \"[]\";\n\t\t\treturn `CommandStartActor{config: {name: \"${config.name}\", key: ${keyStr}, createTs: ${stringifyBigInt(config.createTs)}, input: ${inputStr}}, hibernatingRequests: ${hibernatingRequestsStr}}`;\n\t\t}\n\t\tcase \"CommandStopActor\": {\n\t\t\treturn `CommandStopActor`;\n\t\t}\n\t}\n}\n\n/**\n * Stringify CommandWrapper for logging\n * Handles ArrayBuffers, BigInts, and Maps that can't be JSON.stringified\n */\nexport function stringifyCommandWrapper(\n\twrapper: protocol.CommandWrapper,\n): string {\n\treturn `CommandWrapper{actorId: \"${wrapper.checkpoint.actorId}\", generation: \"${wrapper.checkpoint.generation}\", index: ${stringifyBigInt(wrapper.checkpoint.index)}, inner: ${stringifyCommand(wrapper.inner)}}`;\n}\n\n/**\n * Stringify Event for logging\n * Handles ArrayBuffers, BigInts, and Maps that can't be JSON.stringified\n */\nexport function stringifyEvent(event: protocol.Event): string {\n\tswitch (event.tag) {\n\t\tcase \"EventActorIntent\": {\n\t\t\tconst { intent } = event.val;\n\t\t\tconst intentStr =\n\t\t\t\tintent.tag === \"ActorIntentSleep\"\n\t\t\t\t\t? \"Sleep\"\n\t\t\t\t\t: intent.tag === \"ActorIntentStop\"\n\t\t\t\t\t\t? \"Stop\"\n\t\t\t\t\t\t: \"Unknown\";\n\t\t\treturn `EventActorIntent{intent: ${intentStr}}`;\n\t\t}\n\t\tcase \"EventActorStateUpdate\": {\n\t\t\tconst { state } = event.val;\n\t\t\tlet stateStr: string;\n\t\t\tif (state.tag === \"ActorStateRunning\") {\n\t\t\t\tstateStr = \"Running\";\n\t\t\t} else if (state.tag === \"ActorStateStopped\") {\n\t\t\t\tconst { code, message } = state.val;\n\t\t\t\tconst messageStr = message === null ? \"null\" : `\"${message}\"`;\n\t\t\t\tstateStr = `Stopped{code: ${code}, message: ${messageStr}}`;\n\t\t\t} else {\n\t\t\t\tstateStr = \"Unknown\";\n\t\t\t}\n\t\t\treturn `EventActorStateUpdate{state: ${stateStr}}`;\n\t\t}\n\t\tcase \"EventActorSetAlarm\": {\n\t\t\tconst { alarmTs } = event.val;\n\t\t\tconst alarmTsStr =\n\t\t\t\talarmTs === null ? \"null\" : stringifyBigInt(alarmTs);\n\t\t\treturn `EventActorSetAlarm{alarmTs: ${alarmTsStr}}`;\n\t\t}\n\t}\n}\n\n/**\n * Stringify EventWrapper for logging\n * Handles ArrayBuffers, BigInts, and Maps that can't be JSON.stringified\n */\nexport function stringifyEventWrapper(wrapper: protocol.EventWrapper): string {\n\treturn `EventWrapper{actorId: ${wrapper.checkpoint.actorId}, generation: \"${wrapper.checkpoint.generation}\", index: ${stringifyBigInt(wrapper.checkpoint.index)}, inner: ${stringifyEvent(wrapper.inner)}}`;\n}\n\n/**\n * Stringify ToServer for logging\n * Handles ArrayBuffers, BigInts, and Maps that can't be JSON.stringified\n */\nexport function stringifyToServer(message: protocol.ToServer): string {\n\tswitch (message.tag) {\n\t\tcase \"ToServerInit\": {\n\t\t\tconst {\n\t\t\t\tname,\n\t\t\t\tversion,\n\t\t\t\ttotalSlots,\n\t\t\t\tprepopulateActorNames,\n\t\t\t\tmetadata,\n\t\t\t} = message.val;\n\t\t\tconst prepopulateActorNamesStr =\n\t\t\t\tprepopulateActorNames === null\n\t\t\t\t\t? \"null\"\n\t\t\t\t\t: `Map(${prepopulateActorNames.size})`;\n\t\t\tconst metadataStr = metadata === null ? \"null\" : `\"${metadata}\"`;\n\t\t\treturn `ToServerInit{name: \"${name}\", version: ${version}, totalSlots: ${totalSlots}, prepopulateActorNames: ${prepopulateActorNamesStr}, metadata: ${metadataStr}}`;\n\t\t}\n\t\tcase \"ToServerEvents\": {\n\t\t\tconst events = message.val;\n\t\t\treturn `ToServerEvents{count: ${events.length}, events: [${events.map((e) => stringifyEventWrapper(e)).join(\", \")}]}`;\n\t\t}\n\t\tcase \"ToServerAckCommands\": {\n\t\t\tconst { lastCommandCheckpoints } = message.val;\n\t\t\tconst checkpointsStr =\n\t\t\t\tlastCommandCheckpoints.length > 0\n\t\t\t\t\t? `[${lastCommandCheckpoints.map((cp) => `{actorId: \"${cp.actorId}\", index: ${stringifyBigInt(cp.index)}}`).join(\", \")}]`\n\t\t\t\t\t: \"[]\";\n\t\t\treturn `ToServerAckCommands{lastCommandCheckpoints: ${checkpointsStr}}`;\n\t\t}\n\t\tcase \"ToServerStopping\":\n\t\t\treturn \"ToServerStopping\";\n\t\tcase \"ToServerPong\": {\n\t\t\tconst { ts } = message.val;\n\t\t\treturn `ToServerPong{ts: ${stringifyBigInt(ts)}}`;\n\t\t}\n\t\tcase \"ToServerKvRequest\": {\n\t\t\tconst { actorId, requestId, data } = message.val;\n\t\t\tconst dataStr = stringifyKvRequestData(data);\n\t\t\treturn `ToServerKvRequest{actorId: \"${actorId}\", requestId: ${requestId}, data: ${dataStr}}`;\n\t\t}\n\t\tcase \"ToServerTunnelMessage\": {\n\t\t\tconst { messageId, messageKind } = message.val;\n\t\t\treturn `ToServerTunnelMessage{messageId: ${stringifyMessageId(messageId)}, messageKind: ${stringifyToServerTunnelMessageKind(messageKind)}}`;\n\t\t}\n\t}\n}\n\n/**\n * Stringify ToClient for logging\n * Handles ArrayBuffers, BigInts, and Maps that can't be JSON.stringified\n */\nexport function stringifyToClient(message: protocol.ToClient): string {\n\tswitch (message.tag) {\n\t\tcase \"ToClientInit\": {\n\t\t\tconst { runnerId, metadata } = message.val;\n\t\t\tconst metadataStr = `{runnerLostThreshold: ${stringifyBigInt(metadata.runnerLostThreshold)}}`;\n\t\t\treturn `ToClientInit{runnerId: \"${runnerId}\", metadata: ${metadataStr}}`;\n\t\t}\n\t\tcase \"ToClientPing\": {\n\t\t\tconst { ts } = message.val;\n\t\t\treturn `ToClientPing{ts: ${stringifyBigInt(ts)}}`;\n\t\t}\n\t\tcase \"ToClientCommands\": {\n\t\t\tconst commands = message.val;\n\t\t\treturn `ToClientCommands{count: ${commands.length}, commands: [${commands.map((c) => stringifyCommandWrapper(c)).join(\", \")}]}`;\n\t\t}\n\t\tcase \"ToClientAckEvents\": {\n\t\t\tconst { lastEventCheckpoints } = message.val;\n\t\t\tconst checkpointsStr =\n\t\t\t\tlastEventCheckpoints.length > 0\n\t\t\t\t\t? `[${lastEventCheckpoints.map((cp) => `{actorId: \"${cp.actorId}\", index: ${stringifyBigInt(cp.index)}}`).join(\", \")}]`\n\t\t\t\t\t: \"[]\";\n\t\t\treturn `ToClientAckEvents{lastEventCheckpoints: ${checkpointsStr}}`;\n\t\t}\n\t\tcase \"ToClientKvResponse\": {\n\t\t\tconst { requestId, data } = message.val;\n\t\t\tconst dataStr = stringifyKvResponseData(data);\n\t\t\treturn `ToClientKvResponse{requestId: ${requestId}, data: ${dataStr}}`;\n\t\t}\n\t\tcase \"ToClientTunnelMessage\": {\n\t\t\tconst { messageId, messageKind } = message.val;\n\t\t\treturn `ToClientTunnelMessage{messageId: ${stringifyMessageId(messageId)}, messageKind: ${stringifyToClientTunnelMessageKind(messageKind)}}`;\n\t\t}\n\t}\n}\n\n/**\n * Stringify KvRequestData for logging\n */\nfunction stringifyKvRequestData(data: protocol.KvRequestData): string {\n\tswitch (data.tag) {\n\t\tcase \"KvGetRequest\": {\n\t\t\tconst { keys } = data.val;\n\t\t\treturn `KvGetRequest{keys: ${keys.length}}`;\n\t\t}\n\t\tcase \"KvListRequest\": {\n\t\t\tconst { query, reverse, limit } = data.val;\n\t\t\tconst reverseStr = reverse === null ? \"null\" : reverse.toString();\n\t\t\tconst limitStr = limit === null ? \"null\" : stringifyBigInt(limit);\n\t\t\treturn `KvListRequest{query: ${stringifyKvListQuery(query)}, reverse: ${reverseStr}, limit: ${limitStr}}`;\n\t\t}\n\t\tcase \"KvPutRequest\": {\n\t\t\tconst { keys, values } = data.val;\n\t\t\treturn `KvPutRequest{keys: ${keys.length}, values: ${values.length}}`;\n\t\t}\n\t\tcase \"KvDeleteRequest\": {\n\t\t\tconst { keys } = data.val;\n\t\t\treturn `KvDeleteRequest{keys: ${keys.length}}`;\n\t\t}\n\t\tcase \"KvDropRequest\":\n\t\t\treturn \"KvDropRequest\";\n\t}\n}\n\n/**\n * Stringify KvListQuery for logging\n */\nfunction stringifyKvListQuery(query: protocol.KvListQuery): string {\n\tswitch (query.tag) {\n\t\tcase \"KvListAllQuery\":\n\t\t\treturn \"KvListAllQuery\";\n\t\tcase \"KvListRangeQuery\": {\n\t\t\tconst { start, end, exclusive } = query.val;\n\t\t\treturn `KvListRangeQuery{start: ${stringifyArrayBuffer(start)}, end: ${stringifyArrayBuffer(end)}, exclusive: ${exclusive}}`;\n\t\t}\n\t\tcase \"KvListPrefixQuery\": {\n\t\t\tconst { key } = query.val;\n\t\t\treturn `KvListPrefixQuery{key: ${stringifyArrayBuffer(key)}}`;\n\t\t}\n\t}\n}\n\n/**\n * Stringify KvResponseData for logging\n */\nfunction stringifyKvResponseData(data: protocol.KvResponseData): string {\n\tswitch (data.tag) {\n\t\tcase \"KvErrorResponse\": {\n\t\t\tconst { message } = data.val;\n\t\t\treturn `KvErrorResponse{message: \"${message}\"}`;\n\t\t}\n\t\tcase \"KvGetResponse\": {\n\t\t\tconst { keys, values, metadata } = data.val;\n\t\t\treturn `KvGetResponse{keys: ${keys.length}, values: ${values.length}, metadata: ${metadata.length}}`;\n\t\t}\n\t\tcase \"KvListResponse\": {\n\t\t\tconst { keys, values, metadata } = data.val;\n\t\t\treturn `KvListResponse{keys: ${keys.length}, values: ${values.length}, metadata: ${metadata.length}}`;\n\t\t}\n\t\tcase \"KvPutResponse\":\n\t\t\treturn \"KvPutResponse\";\n\t\tcase \"KvDeleteResponse\":\n\t\t\treturn \"KvDeleteResponse\";\n\t\tcase \"KvDropResponse\":\n\t\t\treturn \"KvDropResponse\";\n\t}\n}\n","// WebSocket-like adapter for tunneled connections\n// Implements a subset of the WebSocket interface for compatibility with runner code\n\nimport type { Logger } from \"pino\";\nimport { logger } from \"./log\";\nimport type { Tunnel } from \"./tunnel\";\nimport { wrappingAddU16, wrappingLteU16, wrappingSubU16 } from \"./utils\";\n\nexport const HIBERNATABLE_SYMBOL = Symbol(\"hibernatable\");\n\nexport class WebSocketTunnelAdapter {\n\t// MARK: - WebSocket Compat Variables\n\t#readyState: number = 0; // CONNECTING\n\t#eventListeners: Map<string, Set<(event: any) => void>> = new Map();\n\t#onopen: ((this: any, ev: any) => any) | null = null;\n\t#onclose: ((this: any, ev: any) => any) | null = null;\n\t#onerror: ((this: any, ev: any) => any) | null = null;\n\t#onmessage: ((this: any, ev: any) => any) | null = null;\n\t#bufferedAmount = 0;\n\t#binaryType: \"nodebuffer\" | \"arraybuffer\" | \"blob\" = \"nodebuffer\";\n\t#extensions = \"\";\n\t#protocol = \"\";\n\t#url = \"\";\n\n\t// mARK: - Internal State\n\t#tunnel: Tunnel;\n\t#actorId: string;\n\t#requestId: string;\n\t#hibernatable: boolean;\n\t#serverMessageIndex: number;\n\n\tget [HIBERNATABLE_SYMBOL](): boolean {\n\t\treturn this.#hibernatable;\n\t}\n\n\t/**\n\t * Called when sending a message from this WebSocket.\n\t *\n\t * Used to send a tunnel message from Tunnel.\n\t */\n\t#sendCallback: (data: ArrayBuffer | string, isBinary: boolean) => void;\n\n\t/**\n\t * Called when closing this WebSocket.\n\t *\n\t * Used to send a tunnel message from Tunnel\n\t */\n\t#closeCallback: (\n\t\tcode?: number,\n\t\treason?: string,\n\t\thibernate?: boolean,\n\t) => void;\n\n\tget #log(): Logger | undefined {\n\t\treturn this.#tunnel.log;\n\t}\n\n\tconstructor(\n\t\ttunnel: Tunnel,\n\t\tactorId: string,\n\t\trequestId: string,\n\t\tserverMessageIndex: number,\n\t\thibernatable: boolean,\n\t\tisRestoringHibernatable: boolean,\n\t\t/** @experimental */\n\t\tpublic readonly request: Request,\n\t\tsendCallback: (data: ArrayBuffer | string, isBinary: boolean) => void,\n\t\tcloseCallback: (code?: number, reason?: string) => void,\n\t) {\n\t\tthis.#tunnel = tunnel;\n\t\tthis.#actorId = actorId;\n\t\tthis.#requestId = requestId;\n\t\tthis.#hibernatable = hibernatable;\n\t\tthis.#serverMessageIndex = serverMessageIndex;\n\t\tthis.#sendCallback = sendCallback;\n\t\tthis.#closeCallback = closeCallback;\n\n\t\t// For restored WebSockets, immediately set to OPEN state\n\t\tif (isRestoringHibernatable) {\n\t\t\tthis.#log?.debug({\n\t\t\t\tmsg: \"setting WebSocket to OPEN state for restored connection\",\n\t\t\t\tactorId: this.#actorId,\n\t\t\t\trequestId: this.#requestId,\n\t\t\t\thibernatable: this.#hibernatable,\n\t\t\t});\n\t\t\tthis.#readyState = 1; // OPEN\n\t\t}\n\t}\n\n\t// MARK: - Lifecycle\n\tget bufferedAmount(): number {\n\t\treturn this.#bufferedAmount;\n\t}\n\n\t_handleOpen(requestId: ArrayBuffer): void {\n\t\tif (this.#readyState !== 0) {\n\t\t\t// CONNECTING\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#readyState = 1; // OPEN\n\n\t\tconst event = {\n\t\t\ttype: \"open\",\n\t\t\trivetRequestId: requestId,\n\t\t\ttarget: this,\n\t\t};\n\n\t\tthis.#fireEvent(\"open\", event);\n\t}\n\n\t_handleMessage(\n\t\trequestId: ArrayBuffer,\n\t\tdata: string | Uint8Array,\n\t\tserverMessageIndex: number,\n\t\tisBinary: boolean,\n\t): boolean {\n\t\tif (this.#readyState !== 1) {\n\t\t\tthis.#log?.warn({\n\t\t\t\tmsg: \"WebSocket message ignored - not in OPEN state\",\n\t\t\t\trequestId: this.#requestId,\n\t\t\t\tactorId: this.#actorId,\n\t\t\t\tcurrentReadyState: this.#readyState,\n\t\t\t\texpectedReadyState: 1,\n\t\t\t\tserverMessageIndex: serverMessageIndex,\n\t\t\t\thibernatable: this.#hibernatable,\n\t\t\t});\n\t\t\treturn true;\n\t\t}\n\n\t\t// Validate message index\n\t\tif (this.#hibernatable) {\n\t\t\tconst previousIndex = this.#serverMessageIndex;\n\n\t\t\t// Ignore duplicate old messages\n\t\t\t//\n\t\t\t// This should only happen if something goes wrong\n\t\t\t// between persisting the previous index and acking the\n\t\t\t// message index to the gateway. If the ack is never\n\t\t\t// received by the gateway (due to a crash or network\n\t\t\t// issue), the gateway will resend all messages from\n\t\t\t// the last ack on reconnect.\n\t\t\tif (wrappingLteU16(serverMessageIndex, previousIndex)) {\n\t\t\t\tthis.#log?.info({\n\t\t\t\t\tmsg: \"received duplicate hibernating websocket message, this indicates the actor failed to ack the message index before restarting\",\n\t\t\t\t\trequestId,\n\t\t\t\t\tactorId: this.#actorId,\n\t\t\t\t\tpreviousIndex,\n\t\t\t\t\texpectedIndex: wrappingAddU16(previousIndex, 1),\n\t\t\t\t\treceivedIndex: serverMessageIndex,\n\t\t\t\t});\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Close message if skipped message in sequence\n\t\t\t//\n\t\t\t// There is no scenario where this should ever happen\n\t\t\tconst expectedIndex = wrappingAddU16(previousIndex, 1);\n\t\t\tif (serverMessageIndex !== expectedIndex) {\n\t\t\t\tconst closeReason = \"ws.message_index_skip\";\n\n\t\t\t\tthis.#log?.warn({\n\t\t\t\t\tmsg: \"hibernatable websocket message index out of sequence, closing connection\",\n\t\t\t\t\trequestId,\n\t\t\t\t\tactorId: this.#actorId,\n\t\t\t\t\tpreviousIndex,\n\t\t\t\t\texpectedIndex,\n\t\t\t\t\treceivedIndex: serverMessageIndex,\n\t\t\t\t\tcloseReason,\n\t\t\t\t\tgap: wrappingSubU16(\n\t\t\t\t\t\twrappingSubU16(serverMessageIndex, previousIndex),\n\t\t\t\t\t\t1,\n\t\t\t\t\t),\n\t\t\t\t});\n\n\t\t\t\t// Close the WebSocket and skip processing\n\t\t\t\tthis.close(1008, closeReason);\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Update to the next index\n\t\t\tthis.#serverMessageIndex = serverMessageIndex;\n\t\t}\n\n\t\t// Dispatch event\n\t\tlet messageData: any;\n\t\tif (isBinary) {\n\t\t\t// Handle binary data based on binaryType\n\t\t\tif (this.#binaryType === \"nodebuffer\") {\n\t\t\t\t// Convert to Buffer for Node.js compatibility\n\t\t\t\tmessageData = Buffer.from(data as Uint8Array);\n\t\t\t} else if (this.#binaryType === \"arraybuffer\") {\n\t\t\t\t// Convert to ArrayBuffer\n\t\t\t\tif (data instanceof Uint8Array) {\n\t\t\t\t\tmessageData = data.buffer.slice(\n\t\t\t\t\t\tdata.byteOffset,\n\t\t\t\t\t\tdata.byteOffset + data.byteLength,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tmessageData = data;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Blob type - not commonly used in Node.js\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Blob binaryType not supported in tunnel adapter\",\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\tmessageData = data;\n\t\t}\n\n\t\tconst event = {\n\t\t\ttype: \"message\",\n\t\t\tdata: messageData,\n\t\t\trivetRequestId: requestId,\n\t\t\trivetMessageIndex: serverMessageIndex,\n\t\t\ttarget: this,\n\t\t};\n\n\t\tthis.#fireEvent(\"message\", event);\n\n\t\treturn false;\n\t}\n\n\t_handleClose(\n\t\t_requestId: ArrayBuffer,\n\t\tcode?: number,\n\t\treason?: string,\n\t): void {\n\t\tthis.#closeInner(code, reason, true);\n\t}\n\n\t_handleError(error: Error): void {\n\t\tconst event = {\n\t\t\ttype: \"error\",\n\t\t\ttarget: this,\n\t\t\terror,\n\t\t};\n\n\t\tthis.#fireEvent(\"error\", event);\n\t}\n\n\t_closeWithoutCallback(code?: number, reason?: string): void {\n\t\tthis.#closeInner(code, reason, false);\n\t}\n\n\t#fireEvent(type: string, event: any): void {\n\t\t// Call all registered event listeners\n\t\tconst listeners = this.#eventListeners.get(type);\n\n\t\tif (listeners && listeners.size > 0) {\n\t\t\tfor (const listener of listeners) {\n\t\t\t\ttry {\n\t\t\t\t\tlistener.call(this, event);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlogger()?.error({\n\t\t\t\t\t\tmsg: \"error in websocket event listener\",\n\t\t\t\t\t\terror,\n\t\t\t\t\t\ttype,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the onX property if set\n\t\tswitch (type) {\n\t\t\tcase \"open\":\n\t\t\t\tif (this.#onopen) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.#onopen.call(this, event);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tlogger()?.error({\n\t\t\t\t\t\t\tmsg: \"error in onopen handler\",\n\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"close\":\n\t\t\t\tif (this.#onclose) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.#onclose.call(this, event);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tlogger()?.error({\n\t\t\t\t\t\t\tmsg: \"error in onclose handler\",\n\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"error\":\n\t\t\t\tif (this.#onerror) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.#onerror.call(this, event);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tlogger()?.error({\n\t\t\t\t\t\t\tmsg: \"error in onerror handler\",\n\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"message\":\n\t\t\t\tif (this.#onmessage) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.#onmessage.call(this, event);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tlogger()?.error({\n\t\t\t\t\t\t\tmsg: \"error in onmessage handler\",\n\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t#closeInner(\n\t\tcode: number | undefined,\n\t\treason: string | undefined,\n\t\tcallback: boolean,\n\t): void {\n\t\tif (\n\t\t\tthis.#readyState === 2 || // CLOSING\n\t\t\tthis.#readyState === 3 // CLOSED\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#readyState = 2; // CLOSING\n\n\t\t// Send close through tunnel\n\t\tif (callback) {\n\t\t\tthis.#closeCallback(code, reason);\n\t\t}\n\n\t\t// Update state and fire event\n\t\tthis.#readyState = 3; // CLOSED\n\n\t\tconst closeEvent = {\n\t\t\twasClean: true,\n\t\t\tcode: code || 1000,\n\t\t\treason: reason || \"\",\n\t\t\ttype: \"close\",\n\t\t\ttarget: this,\n\t\t};\n\n\t\tthis.#fireEvent(\"close\", closeEvent);\n\t}\n\n\t// MARK: - WebSocket Compatible API\n\tget readyState(): number {\n\t\treturn this.#readyState;\n\t}\n\n\tget binaryType(): string {\n\t\treturn this.#binaryType;\n\t}\n\n\tset binaryType(value: string) {\n\t\tif (\n\t\t\tvalue === \"nodebuffer\" ||\n\t\t\tvalue === \"arraybuffer\" ||\n\t\t\tvalue === \"blob\"\n\t\t) {\n\t\t\tthis.#binaryType = value;\n\t\t}\n\t}\n\n\tget extensions(): string {\n\t\treturn this.#extensions;\n\t}\n\n\tget protocol(): string {\n\t\treturn this.#protocol;\n\t}\n\n\tget url(): string {\n\t\treturn this.#url;\n\t}\n\n\tget onopen(): ((this: any, ev: any) => any) | null {\n\t\treturn this.#onopen;\n\t}\n\n\tset onopen(value: ((this: any, ev: any) => any) | null) {\n\t\tthis.#onopen = value;\n\t}\n\n\tget onclose(): ((this: any, ev: any) => any) | null {\n\t\treturn this.#onclose;\n\t}\n\n\tset onclose(value: ((this: any, ev: any) => any) | null) {\n\t\tthis.#onclose = value;\n\t}\n\n\tget onerror(): ((this: any, ev: any) => any) | null {\n\t\treturn this.#onerror;\n\t}\n\n\tset onerror(value: ((this: any, ev: any) => any) | null) {\n\t\tthis.#onerror = value;\n\t}\n\n\tget onmessage(): ((this: any, ev: any) => any) | null {\n\t\treturn this.#onmessage;\n\t}\n\n\tset onmessage(value: ((this: any, ev: any) => any) | null) {\n\t\tthis.#onmessage = value;\n\t}\n\n\tsend(data: string | ArrayBuffer | ArrayBufferView | Blob | Buffer): void {\n\t\t// Handle different ready states\n\t\tif (this.#readyState === 0) {\n\t\t\t// CONNECTING\n\t\t\tthrow new DOMException(\n\t\t\t\t\"WebSocket is still in CONNECTING state\",\n\t\t\t\t\"InvalidStateError\",\n\t\t\t);\n\t\t}\n\n\t\tif (this.#readyState === 2 || this.#readyState === 3) {\n\t\t\t// CLOSING or CLOSED - silently ignore\n\t\t\treturn;\n\t\t}\n\n\t\tlet isBinary = false;\n\t\tlet messageData: string | ArrayBuffer;\n\n\t\tif (typeof data === \"string\") {\n\t\t\tmessageData = data;\n\t\t} else if (data instanceof ArrayBuffer) {\n\t\t\tisBinary = true;\n\t\t\tmessageData = data;\n\t\t} else if (ArrayBuffer.isView(data)) {\n\t\t\tisBinary = true;\n\t\t\t// Convert ArrayBufferView to ArrayBuffer\n\t\t\tconst view = data as ArrayBufferView;\n\t\t\t// Check if it's a SharedArrayBuffer\n\t\t\tif (view.buffer instanceof SharedArrayBuffer) {\n\t\t\t\t// Copy SharedArrayBuffer to regular ArrayBuffer\n\t\t\t\tconst bytes = new Uint8Array(\n\t\t\t\t\tview.buffer,\n\t\t\t\t\tview.byteOffset,\n\t\t\t\t\tview.byteLength,\n\t\t\t\t);\n\t\t\t\tmessageData = bytes.buffer.slice(\n\t\t\t\t\tbytes.byteOffset,\n\t\t\t\t\tbytes.byteOffset + bytes.byteLength,\n\t\t\t\t) as unknown as ArrayBuffer;\n\t\t\t} else {\n\t\t\t\tmessageData = view.buffer.slice(\n\t\t\t\t\tview.byteOffset,\n\t\t\t\t\tview.byteOffset + view.byteLength,\n\t\t\t\t) as ArrayBuffer;\n\t\t\t}\n\t\t} else if (data instanceof Blob) {\n\t\t\tthrow new Error(\"Blob sending not implemented in tunnel adapter\");\n\t\t} else if (typeof Buffer !== \"undefined\" && Buffer.isBuffer(data)) {\n\t\t\tisBinary = true;\n\t\t\t// Convert Buffer to ArrayBuffer\n\t\t\tconst buf = data as Buffer;\n\t\t\t// Check if it's a SharedArrayBuffer\n\t\t\tif (buf.buffer instanceof SharedArrayBuffer) {\n\t\t\t\t// Copy SharedArrayBuffer to regular ArrayBuffer\n\t\t\t\tconst bytes = new Uint8Array(\n\t\t\t\t\tbuf.buffer,\n\t\t\t\t\tbuf.byteOffset,\n\t\t\t\t\tbuf.byteLength,\n\t\t\t\t);\n\t\t\t\tmessageData = bytes.buffer.slice(\n\t\t\t\t\tbytes.byteOffset,\n\t\t\t\t\tbytes.byteOffset + bytes.byteLength,\n\t\t\t\t) as unknown as ArrayBuffer;\n\t\t\t} else {\n\t\t\t\tmessageData = buf.buffer.slice(\n\t\t\t\t\tbuf.byteOffset,\n\t\t\t\t\tbuf.byteOffset + buf.byteLength,\n\t\t\t\t) as ArrayBuffer;\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new Error(\"Invalid data type\");\n\t\t}\n\n\t\t// Send through tunnel\n\t\tthis.#sendCallback(messageData, isBinary);\n\t}\n\n\tclose(code?: number, reason?: string): void {\n\t\tthis.#closeInner(code, reason, true);\n\t}\n\n\taddEventListener(\n\t\ttype: string,\n\t\tlistener: (event: any) => void,\n\t\toptions?: boolean | any,\n\t): void {\n\t\tif (typeof listener === \"function\") {\n\t\t\tlet listeners = this.#eventListeners.get(type);\n\t\t\tif (!listeners) {\n\t\t\t\tlisteners = new Set();\n\t\t\t\tthis.#eventListeners.set(type, listeners);\n\t\t\t}\n\t\t\tlisteners.add(listener);\n\t\t}\n\t}\n\n\tremoveEventListener(\n\t\ttype: string,\n\t\tlistener: (event: any) => void,\n\t\toptions?: boolean | any,\n\t): void {\n\t\tif (typeof listener === \"function\") {\n\t\t\tconst listeners = this.#eventListeners.get(type);\n\t\t\tif (listeners) {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t}\n\t\t}\n\t}\n\n\tdispatchEvent(event: any): boolean {\n\t\t// TODO:\n\t\treturn true;\n\t}\n\n\tstatic readonly CONNECTING = 0;\n\tstatic readonly OPEN = 1;\n\tstatic readonly CLOSING = 2;\n\tstatic readonly CLOSED = 3;\n\n\treadonly CONNECTING = 0;\n\treadonly OPEN = 1;\n\treadonly CLOSING = 2;\n\treadonly CLOSED = 3;\n\n\t// Additional methods for compatibility\n\tping(data?: any, mask?: boolean, cb?: (err: Error) => void): void {\n\t\t// Not implemented for tunnel - could be added if needed\n\t\tif (cb) cb(new Error(\"Ping not supported in tunnel adapter\"));\n\t}\n\n\tpong(data?: any, mask?: boolean, cb?: (err: Error) => void): void {\n\t\t// Not implemented for tunnel - could be added if needed\n\t\tif (cb) cb(new Error(\"Pong not supported in tunnel adapter\"));\n\t}\n\n\t/** @experimental */\n\tterminate(): void {\n\t\t// Immediate close without close frame\n\t\tthis.#readyState = 3; // CLOSED\n\t\tthis.#closeCallback(1006, \"Abnormal Closure\");\n\n\t\tconst event = {\n\t\t\twasClean: false,\n\t\t\tcode: 1006,\n\t\t\treason: \"Abnormal Closure\",\n\t\t\ttype: \"close\",\n\t\t\ttarget: this,\n\t\t};\n\n\t\tthis.#fireEvent(\"close\", event);\n\t}\n}\n","import type * as protocol from \"@rivetkit/engine-runner-protocol\";\nimport type {\n\tGatewayId,\n\tMessageId,\n\tRequestId,\n} from \"@rivetkit/engine-runner-protocol\";\nimport type { Logger } from \"pino\";\nimport {\n\tparse as uuidparse,\n\tstringify as uuidstringify,\n\tv4 as uuidv4,\n} from \"uuid\";\nimport { type Runner, type RunnerActor, RunnerShutdownError } from \"./mod\";\nimport {\n\tstringifyToClientTunnelMessageKind,\n\tstringifyToServerTunnelMessageKind,\n} from \"./stringify\";\nimport { arraysEqual, idToStr, stringifyError, unreachable } from \"./utils\";\nimport {\n\tHIBERNATABLE_SYMBOL,\n\tWebSocketTunnelAdapter,\n} from \"./websocket-tunnel-adapter\";\n\nexport interface PendingRequest {\n\tresolve: (response: Response) => void;\n\treject: (error: Error) => void;\n\tstreamController?: ReadableStreamDefaultController<Uint8Array>;\n\tactorId?: string;\n\tgatewayId?: GatewayId;\n\trequestId?: RequestId;\n\tclientMessageIndex: number;\n}\n\nexport interface HibernatingWebSocketMetadata {\n\tgatewayId: GatewayId;\n\trequestId: RequestId;\n\tclientMessageIndex: number;\n\tserverMessageIndex: number;\n\n\tpath: string;\n\theaders: Record<string, string>;\n}\n\nexport class Tunnel {\n\t#runner: Runner;\n\n\t/** Maps request IDs to actor IDs for lookup */\n\t#requestToActor: Array<{\n\t\tgatewayId: GatewayId;\n\t\trequestId: RequestId;\n\t\tactorId: string;\n\t}> = [];\n\n\t/** Buffer for messages when not connected */\n\t#bufferedMessages: Array<{\n\t\tgatewayId: GatewayId;\n\t\trequestId: RequestId;\n\t\tmessageKind: protocol.ToServerTunnelMessageKind;\n\t}> = [];\n\n\tget log(): Logger | undefined {\n\t\treturn this.#runner.log;\n\t}\n\n\tconstructor(runner: Runner) {\n\t\tthis.#runner = runner;\n\t}\n\n\tstart(): void {\n\t\t// No-op - kept for compatibility\n\t}\n\n\tresendBufferedEvents(): void {\n\t\tif (this.#bufferedMessages.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.log?.info({\n\t\t\tmsg: \"resending buffered tunnel messages\",\n\t\t\tcount: this.#bufferedMessages.length,\n\t\t});\n\n\t\tconst messages = this.#bufferedMessages;\n\t\tthis.#bufferedMessages = [];\n\n\t\tfor (const { gatewayId, requestId, messageKind } of messages) {\n\t\t\tthis.#sendMessage(gatewayId, requestId, messageKind);\n\t\t}\n\t}\n\n\tshutdown() {\n\t\t// NOTE: Pegboard WS already closed at this point, cannot send\n\t\t// anything. All teardown logic is handled by pegboard-runner.\n\n\t\t// Reject all pending requests and close all WebSockets for all actors\n\t\t// RunnerShutdownError will be explicitly ignored\n\t\tfor (const [_actorId, actor] of this.#runner.actors) {\n\t\t\t// Reject all pending requests for this actor\n\t\t\tfor (const entry of actor.pendingRequests) {\n\t\t\t\tentry.request.reject(new RunnerShutdownError());\n\t\t\t}\n\t\t\tactor.pendingRequests = [];\n\n\t\t\t// Close all WebSockets for this actor\n\t\t\t// The WebSocket close event with retry is automatically sent when the\n\t\t\t// runner WS closes, so we only need to notify the client that the WS\n\t\t\t// closed:\n\t\t\t// https://github.com/rivet-dev/rivet/blob/00d4f6a22da178a6f8115e5db50d96c6f8387c2e/engine/packages/pegboard-runner/src/lib.rs#L157\n\t\t\tfor (const entry of actor.webSockets) {\n\t\t\t\t// Only close non-hibernatable websockets to prevent sending\n\t\t\t\t// unnecessary close messages for websockets that will be hibernated\n\t\t\t\tif (!entry.ws[HIBERNATABLE_SYMBOL]) {\n\t\t\t\t\tentry.ws._closeWithoutCallback(1000, \"ws.tunnel_shutdown\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tactor.webSockets = [];\n\t\t}\n\n\t\t// Clear the request-to-actor mapping\n\t\tthis.#requestToActor = [];\n\t}\n\n\tasync restoreHibernatingRequests(\n\t\tactorId: string,\n\t\tmetaEntries: HibernatingWebSocketMetadata[],\n\t) {\n\t\tconst actor = this.#runner.getActor(actorId);\n\t\tif (!actor) {\n\t\t\tthrow new Error(\n\t\t\t\t`Actor ${actorId} not found for restoring hibernating requests`,\n\t\t\t);\n\t\t}\n\n\t\tif (actor.hibernationRestored) {\n\t\t\tthrow new Error(\n\t\t\t\t`Actor ${actorId} already restored hibernating requests`,\n\t\t\t);\n\t\t}\n\n\t\tthis.log?.debug({\n\t\t\tmsg: \"restoring hibernating requests\",\n\t\t\tactorId,\n\t\t\trequests: actor.hibernatingRequests.length,\n\t\t});\n\n\t\t// Track all background operations\n\t\tconst backgroundOperations: Promise<void>[] = [];\n\n\t\t// Process connected WebSockets\n\t\tlet connectedButNotLoadedCount = 0;\n\t\tlet restoredCount = 0;\n\t\tfor (const { gatewayId, requestId } of actor.hibernatingRequests) {\n\t\t\tconst requestIdStr = idToStr(requestId);\n\t\t\tconst meta = metaEntries.find(\n\t\t\t\t(entry) =>\n\t\t\t\t\tarraysEqual(entry.gatewayId, gatewayId) &&\n\t\t\t\t\tarraysEqual(entry.requestId, requestId),\n\t\t\t);\n\n\t\t\tif (!meta) {\n\t\t\t\t// Connected but not loaded (not persisted) - close it\n\t\t\t\t//\n\t\t\t\t// This may happen if the metadata was not successfully persisted\n\t\t\t\tthis.log?.warn({\n\t\t\t\t\tmsg: \"closing websocket that is not persisted\",\n\t\t\t\t\trequestId: requestIdStr,\n\t\t\t\t});\n\n\t\t\t\tthis.#sendMessage(gatewayId, requestId, {\n\t\t\t\t\ttag: \"ToServerWebSocketClose\",\n\t\t\t\t\tval: {\n\t\t\t\t\t\tcode: 1000,\n\t\t\t\t\t\treason: \"ws.meta_not_found_during_restore\",\n\t\t\t\t\t\thibernate: false,\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\tconnectedButNotLoadedCount++;\n\t\t\t} else {\n\t\t\t\t// Both connected and persisted - restore it\n\t\t\t\tconst request = buildRequestForWebSocket(\n\t\t\t\t\tmeta.path,\n\t\t\t\t\tmeta.headers,\n\t\t\t\t);\n\n\t\t\t\t// This will call `runner.config.websocket` under the hood to\n\t\t\t\t// attach the event listeners to the WebSocket.\n\t\t\t\t// Track this operation to ensure it completes\n\t\t\t\tconst restoreOperation = this.#createWebSocket(\n\t\t\t\t\tactorId,\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\trequestIdStr,\n\t\t\t\t\tmeta.serverMessageIndex,\n\t\t\t\t\ttrue,\n\t\t\t\t\ttrue,\n\t\t\t\t\trequest,\n\t\t\t\t\tmeta.path,\n\t\t\t\t\tmeta.headers,\n\t\t\t\t\tfalse,\n\t\t\t\t)\n\t\t\t\t\t.then(() => {\n\t\t\t\t\t\t// Create a PendingRequest entry to track the message index\n\t\t\t\t\t\tconst actor = this.#runner.getActor(actorId);\n\t\t\t\t\t\tif (actor) {\n\t\t\t\t\t\t\tactor.createPendingRequest(\n\t\t\t\t\t\t\t\tgatewayId,\n\t\t\t\t\t\t\t\trequestId,\n\t\t\t\t\t\t\t\tmeta.clientMessageIndex,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthis.log?.info({\n\t\t\t\t\t\t\tmsg: \"connection successfully restored\",\n\t\t\t\t\t\t\tactorId,\n\t\t\t\t\t\t\trequestId: requestIdStr,\n\t\t\t\t\t\t});\n\t\t\t\t\t})\n\t\t\t\t\t.catch((err) => {\n\t\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\t\tmsg: \"error creating websocket during restore\",\n\t\t\t\t\t\t\trequestId: requestIdStr,\n\t\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t// Close the WebSocket on error\n\t\t\t\t\t\tthis.#sendMessage(gatewayId, requestId, {\n\t\t\t\t\t\t\ttag: \"ToServerWebSocketClose\",\n\t\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\t\tcode: 1011,\n\t\t\t\t\t\t\t\treason: \"ws.restore_error\",\n\t\t\t\t\t\t\t\thibernate: false,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\tbackgroundOperations.push(restoreOperation);\n\t\t\t\trestoredCount++;\n\t\t\t}\n\t\t}\n\n\t\t// Process loaded but not connected (stale) - remove them\n\t\tlet loadedButNotConnectedCount = 0;\n\t\tfor (const meta of metaEntries) {\n\t\t\tconst requestIdStr = idToStr(meta.requestId);\n\t\t\tconst isConnected = actor.hibernatingRequests.some(\n\t\t\t\t(req) =>\n\t\t\t\t\tarraysEqual(req.gatewayId, meta.gatewayId) &&\n\t\t\t\t\tarraysEqual(req.requestId, meta.requestId),\n\t\t\t);\n\t\t\tif (!isConnected) {\n\t\t\t\tthis.log?.warn({\n\t\t\t\t\tmsg: \"removing stale persisted websocket\",\n\t\t\t\t\trequestId: requestIdStr,\n\t\t\t\t});\n\n\t\t\t\tconst request = buildRequestForWebSocket(\n\t\t\t\t\tmeta.path,\n\t\t\t\t\tmeta.headers,\n\t\t\t\t);\n\n\t\t\t\t// Create adapter to register user's event listeners.\n\t\t\t\t// Pass engineAlreadyClosed=true so close callback won't send tunnel message.\n\t\t\t\t// Track this operation to ensure it completes\n\t\t\t\tconst cleanupOperation = this.#createWebSocket(\n\t\t\t\t\tactorId,\n\t\t\t\t\tmeta.gatewayId,\n\t\t\t\t\tmeta.requestId,\n\t\t\t\t\trequestIdStr,\n\t\t\t\t\tmeta.serverMessageIndex,\n\t\t\t\t\ttrue,\n\t\t\t\t\ttrue,\n\t\t\t\t\trequest,\n\t\t\t\t\tmeta.path,\n\t\t\t\t\tmeta.headers,\n\t\t\t\t\ttrue,\n\t\t\t\t)\n\t\t\t\t\t.then((adapter) => {\n\t\t\t\t\t\t// Close the adapter normally - this will fire user's close event handler\n\t\t\t\t\t\t// (which should clean up persistence) and trigger the close callback\n\t\t\t\t\t\t// (which will clean up maps but skip sending tunnel message)\n\t\t\t\t\t\tadapter.close(1000, \"ws.stale_metadata\");\n\t\t\t\t\t})\n\t\t\t\t\t.catch((err) => {\n\t\t\t\t\t\tthis.log?.error({\n\t\t\t\t\t\t\tmsg: \"error creating stale websocket during restore\",\n\t\t\t\t\t\t\trequestId: requestIdStr,\n\t\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\tbackgroundOperations.push(cleanupOperation);\n\t\t\t\tloadedButNotConnectedCount++;\n\t\t\t}\n\t\t}\n\n\t\t// Wait for all background operations to complete before finishing\n\t\tawait Promise.allSettled(backgroundOperations);\n\n\t\t// Mark restoration as complete\n\t\tactor.hibernationRestored = true;\n\n\t\tthis.log?.info({\n\t\t\tmsg: \"restored hibernatable websockets\",\n\t\t\tactorId,\n\t\t\trestoredCount,\n\t\t\tconnectedButNotLoadedCount,\n\t\t\tloadedButNotConnectedCount,\n\t\t});\n\t}\n\n\t/**\n\t * Called from WebSocketOpen message and when restoring hibernatable WebSockets.\n\t *\n\t * engineAlreadyClosed will be true if this is only being called to trigger\n\t * the close callback and not to send a close message to the server. This\n\t * is used specifically to clean up zombie WebSocket connections.\n\t */\n\tasync #createWebSocket(\n\t\tactorId: string,\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t\trequestIdStr: string,\n\t\tserverMessageIndex: number,\n\t\tisHibernatable: boolean,\n\t\tisRestoringHibernatable: boolean,\n\t\trequest: Request,\n\t\tpath: string,\n\t\theaders: Record<string, string>,\n\t\tengineAlreadyClosed: boolean,\n\t): Promise<WebSocketTunnelAdapter> {\n\t\tthis.log?.debug({\n\t\t\tmsg: \"createWebSocket creating adapter\",\n\t\t\tactorId,\n\t\t\trequestIdStr,\n\t\t\tisHibernatable,\n\t\t\tpath,\n\t\t});\n\t\t// Create WebSocket adapter\n\t\tconst adapter = new WebSocketTunnelAdapter(\n\t\t\tthis,\n\t\t\tactorId,\n\t\t\trequestIdStr,\n\t\t\tserverMessageIndex,\n\t\t\tisHibernatable,\n\t\t\tisRestoringHibernatable,\n\t\t\trequest,\n\t\t\t(data: ArrayBuffer | string, isBinary: boolean) => {\n\t\t\t\t// Send message through tunnel\n\t\t\t\tconst dataBuffer =\n\t\t\t\t\ttypeof data === \"string\"\n\t\t\t\t\t\t? (new TextEncoder().encode(data).buffer as ArrayBuffer)\n\t\t\t\t\t\t: data;\n\n\t\t\t\tthis.#sendMessage(gatewayId, requestId, {\n\t\t\t\t\ttag: \"ToServerWebSocketMessage\",\n\t\t\t\t\tval: {\n\t\t\t\t\t\tdata: dataBuffer,\n\t\t\t\t\t\tbinary: isBinary,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t},\n\t\t\t(code?: number, reason?: string) => {\n\t\t\t\t// Send close through tunnel if engine doesn't already know it's closed\n\t\t\t\tif (!engineAlreadyClosed) {\n\t\t\t\t\tthis.#sendMessage(gatewayId, requestId, {\n\t\t\t\t\t\ttag: \"ToServerWebSocketClose\",\n\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\tcode: code || null,\n\t\t\t\t\t\t\treason: reason || null,\n\t\t\t\t\t\t\thibernate: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Clean up actor tracking\n\t\t\t\tconst actor = this.#runner.getActor(actorId);\n\t\t\t\tif (actor) {\n\t\t\t\t\tactor.deleteWebSocket(gatewayId, requestId);\n\t\t\t\t\tactor.deletePendingRequest(gatewayId, requestId);\n\t\t\t\t}\n\n\t\t\t\t// Clean up request-to-actor mapping\n\t\t\t\tthis.#removeRequestToActor(gatewayId, requestId);\n\t\t\t},\n\t\t);\n\n\t\t// Get actor and add websocket to it\n\t\tconst actor = this.#runner.getActor(actorId);\n\t\tif (!actor) {\n\t\t\tthrow new Error(`Actor ${actorId} not found`);\n\t\t}\n\n\t\tactor.setWebSocket(gatewayId, requestId, adapter);\n\t\tthis.addRequestToActor(gatewayId, requestId, actorId);\n\n\t\t// Call WebSocket handler. This handler will add event listeners\n\t\t// for `open`, etc.\n\t\tawait this.#runner.config.websocket(\n\t\t\tthis.#runner,\n\t\t\tactorId,\n\t\t\tadapter,\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t\trequest,\n\t\t\tpath,\n\t\t\theaders,\n\t\t\tisHibernatable,\n\t\t\tisRestoringHibernatable,\n\t\t);\n\n\t\treturn adapter;\n\t}\n\n\taddRequestToActor(\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t\tactorId: string,\n\t) {\n\t\tthis.#requestToActor.push({ gatewayId, requestId, actorId });\n\t}\n\n\t#removeRequestToActor(gatewayId: GatewayId, requestId: RequestId) {\n\t\tconst index = this.#requestToActor.findIndex(\n\t\t\t(entry) =>\n\t\t\t\tarraysEqual(entry.gatewayId, gatewayId) &&\n\t\t\t\tarraysEqual(entry.requestId, requestId),\n\t\t);\n\t\tif (index !== -1) {\n\t\t\tthis.#requestToActor.splice(index, 1);\n\t\t}\n\t}\n\n\tgetRequestActor(\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t): RunnerActor | undefined {\n\t\tconst entry = this.#requestToActor.find(\n\t\t\t(entry) =>\n\t\t\t\tarraysEqual(entry.gatewayId, gatewayId) &&\n\t\t\t\tarraysEqual(entry.requestId, requestId),\n\t\t);\n\n\t\tif (!entry) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"missing requestToActor entry\",\n\t\t\t\trequestId: idToStr(requestId),\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst actor = this.#runner.getActor(entry.actorId);\n\t\tif (!actor) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"missing actor for requestToActor lookup\",\n\t\t\t\trequestId: idToStr(requestId),\n\t\t\t\tactorId: entry.actorId,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn actor;\n\t}\n\n\tasync getAndWaitForRequestActor(\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t): Promise<RunnerActor | undefined> {\n\t\tconst actor = this.getRequestActor(gatewayId, requestId);\n\t\tif (!actor) return;\n\t\tawait actor.actorStartPromise.promise;\n\t\treturn actor;\n\t}\n\n\t#sendMessage(\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t\tmessageKind: protocol.ToServerTunnelMessageKind,\n\t) {\n\t\t// Buffer message if not connected\n\t\tif (!this.#runner.__webSocketReady()) {\n\t\t\tthis.log?.debug({\n\t\t\t\tmsg: \"buffering tunnel message, socket not connected to engine\",\n\t\t\t\trequestId: idToStr(requestId),\n\t\t\t\tmessage: stringifyToServerTunnelMessageKind(messageKind),\n\t\t\t});\n\t\t\tthis.#bufferedMessages.push({ gatewayId, requestId, messageKind });\n\t\t\treturn;\n\t\t}\n\n\t\t// Get or initialize message index for this request\n\t\t//\n\t\t// We don't have to wait for the actor to start since we're not calling\n\t\t// any callbacks on the actor\n\t\tconst gatewayIdStr = idToStr(gatewayId);\n\t\tconst requestIdStr = idToStr(requestId);\n\t\tconst actor = this.getRequestActor(gatewayId, requestId);\n\t\tif (!actor) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"cannot send tunnel message, actor not found\",\n\t\t\t\tgatewayId: gatewayIdStr,\n\t\t\t\trequestId: requestIdStr,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Get message index from pending request\n\t\tlet clientMessageIndex: number;\n\t\tconst pending = actor.getPendingRequest(gatewayId, requestId);\n\t\tif (pending) {\n\t\t\tclientMessageIndex = pending.clientMessageIndex;\n\t\t\tpending.clientMessageIndex++;\n\t\t} else {\n\t\t\t// No pending request\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"missing pending request for send message, defaulting to message index 0\",\n\t\t\t\tgatewayId: gatewayIdStr,\n\t\t\t\trequestId: requestIdStr,\n\t\t\t});\n\t\t\tclientMessageIndex = 0;\n\t\t}\n\n\t\t// Build message ID from gatewayId + requestId + messageIndex\n\t\tconst messageId: protocol.MessageId = {\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t\tmessageIndex: clientMessageIndex,\n\t\t};\n\t\tconst messageIdStr = `${idToStr(messageId.gatewayId)}-${idToStr(messageId.requestId)}-${messageId.messageIndex}`;\n\n\t\tthis.log?.debug({\n\t\t\tmsg: \"sending tunnel msg\",\n\t\t\tmessageId: messageIdStr,\n\t\t\tgatewayId: gatewayIdStr,\n\t\t\trequestId: requestIdStr,\n\t\t\tmessageIndex: clientMessageIndex,\n\t\t\tmessage: stringifyToServerTunnelMessageKind(messageKind),\n\t\t});\n\n\t\t// Send message\n\t\tconst message: protocol.ToServer = {\n\t\t\ttag: \"ToServerTunnelMessage\",\n\t\t\tval: {\n\t\t\t\tmessageId,\n\t\t\t\tmessageKind,\n\t\t\t},\n\t\t};\n\t\tthis.#runner.__sendToServer(message);\n\t}\n\n\tcloseActiveRequests(actor: RunnerActor) {\n\t\tconst actorId = actor.actorId;\n\n\t\t// Terminate all requests for this actor. This will no send a\n\t\t// ToServerResponse* message since the actor will no longer be loaded.\n\t\t// The gateway is responsible for closing the request.\n\t\tfor (const entry of actor.pendingRequests) {\n\t\t\tentry.request.reject(new Error(`Actor ${actorId} stopped`));\n\t\t\tif (entry.gatewayId && entry.requestId) {\n\t\t\t\tthis.#removeRequestToActor(entry.gatewayId, entry.requestId);\n\t\t\t}\n\t\t}\n\n\t\t// Close all WebSockets. Only send close event to non-HWS. The gateway is\n\t\t// responsible for hibernating HWS and closing regular WS.\n\t\tfor (const entry of actor.webSockets) {\n\t\t\tconst isHibernatable = entry.ws[HIBERNATABLE_SYMBOL];\n\t\t\tif (!isHibernatable) {\n\t\t\t\tentry.ws._closeWithoutCallback(1000, \"actor.stopped\");\n\t\t\t}\n\t\t\t// Note: request-to-actor mapping is cleaned up in the close callback\n\t\t}\n\t}\n\n\tasync #fetch(\n\t\tactorId: string,\n\t\tgatewayId: protocol.GatewayId,\n\t\trequestId: protocol.RequestId,\n\t\trequest: Request,\n\t): Promise<Response> {\n\t\t// Validate actor exists\n\t\tif (!this.#runner.hasActor(actorId)) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"ignoring request for unknown actor\",\n\t\t\t\tactorId,\n\t\t\t});\n\n\t\t\t// NOTE: This is a special response that will cause Guard to retry the request\n\t\t\t//\n\t\t\t// See should_retry_request_inner\n\t\t\t// https://github.com/rivet-dev/rivet/blob/222dae87e3efccaffa2b503de40ecf8afd4e31eb/engine/packages/guard-core/src/proxy_service.rs#L2458\n\t\t\treturn new Response(\"Actor not found\", {\n\t\t\t\tstatus: 503,\n\t\t\t\theaders: { \"x-rivet-error\": \"runner.actor_not_found\" },\n\t\t\t});\n\t\t}\n\n\t\tconst fetchHandler = this.#runner.config.fetch(\n\t\t\tthis.#runner,\n\t\t\tactorId,\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t\trequest,\n\t\t);\n\n\t\tif (!fetchHandler) {\n\t\t\treturn new Response(\"Not Implemented\", { status: 501 });\n\t\t}\n\n\t\treturn fetchHandler;\n\t}\n\n\tasync handleTunnelMessage(message: protocol.ToClientTunnelMessage) {\n\t\t// Parse the gateway ID, request ID, and message index from the messageId\n\t\tconst { gatewayId, requestId, messageIndex } = message.messageId;\n\n\t\tconst gatewayIdStr = idToStr(gatewayId);\n\t\tconst requestIdStr = idToStr(requestId);\n\t\tthis.log?.debug({\n\t\t\tmsg: \"receive tunnel msg\",\n\t\t\tgatewayId: gatewayIdStr,\n\t\t\trequestId: requestIdStr,\n\t\t\tmessageIndex: message.messageId.messageIndex,\n\t\t\tmessage: stringifyToClientTunnelMessageKind(message.messageKind),\n\t\t});\n\n\t\tswitch (message.messageKind.tag) {\n\t\t\tcase \"ToClientRequestStart\":\n\t\t\t\tawait this.#handleRequestStart(\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\tmessage.messageKind.val,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"ToClientRequestChunk\":\n\t\t\t\tawait this.#handleRequestChunk(\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\tmessage.messageKind.val,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"ToClientRequestAbort\":\n\t\t\t\tawait this.#handleRequestAbort(gatewayId, requestId);\n\t\t\t\tbreak;\n\t\t\tcase \"ToClientWebSocketOpen\":\n\t\t\t\tawait this.#handleWebSocketOpen(\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\tmessage.messageKind.val,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"ToClientWebSocketMessage\": {\n\t\t\t\tawait this.#handleWebSocketMessage(\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\tmessageIndex,\n\t\t\t\t\tmessage.messageKind.val,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"ToClientWebSocketClose\":\n\t\t\t\tawait this.#handleWebSocketClose(\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\tmessage.messageKind.val,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tunreachable(message.messageKind);\n\t\t}\n\t}\n\n\tasync #handleRequestStart(\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t\treq: protocol.ToClientRequestStart,\n\t) {\n\t\t// Track this request for the actor\n\t\tconst requestIdStr = idToStr(requestId);\n\t\tconst actor = await this.#runner.getAndWaitForActor(req.actorId);\n\t\tif (!actor) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"actor does not exist in handleRequestStart, request will leak\",\n\t\t\t\tactorId: req.actorId,\n\t\t\t\trequestId: requestIdStr,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Add to request-to-actor mapping\n\t\tthis.addRequestToActor(gatewayId, requestId, req.actorId);\n\n\t\ttry {\n\t\t\t// Convert headers map to Headers object\n\t\t\tconst headers = new Headers();\n\t\t\tfor (const [key, value] of req.headers) {\n\t\t\t\theaders.append(key, value);\n\t\t\t}\n\n\t\t\t// Create Request object\n\t\t\tconst request = new Request(`http://localhost${req.path}`, {\n\t\t\t\tmethod: req.method,\n\t\t\t\theaders,\n\t\t\t\tbody: req.body ? new Uint8Array(req.body) : undefined,\n\t\t\t});\n\n\t\t\t// Handle streaming request\n\t\t\tif (req.stream) {\n\t\t\t\t// Create a stream for the request body\n\t\t\t\tconst stream = new ReadableStream<Uint8Array>({\n\t\t\t\t\tstart: (controller) => {\n\t\t\t\t\t\t// Store controller for chunks\n\t\t\t\t\t\tconst existing = actor.getPendingRequest(\n\t\t\t\t\t\t\tgatewayId,\n\t\t\t\t\t\t\trequestId,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (existing) {\n\t\t\t\t\t\t\texisting.streamController = controller;\n\t\t\t\t\t\t\texisting.actorId = req.actorId;\n\t\t\t\t\t\t\texisting.gatewayId = gatewayId;\n\t\t\t\t\t\t\texisting.requestId = requestId;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tactor.createPendingRequestWithStreamController(\n\t\t\t\t\t\t\t\tgatewayId,\n\t\t\t\t\t\t\t\trequestId,\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tcontroller,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\t// Create request with streaming body\n\t\t\t\tconst streamingRequest = new Request(request, {\n\t\t\t\t\tbody: stream,\n\t\t\t\t\tduplex: \"half\",\n\t\t\t\t} as any);\n\n\t\t\t\t// Call fetch handler with validation\n\t\t\t\tconst response = await this.#fetch(\n\t\t\t\t\treq.actorId,\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\tstreamingRequest,\n\t\t\t\t);\n\t\t\t\tawait this.#sendResponse(\n\t\t\t\t\tactor.actorId,\n\t\t\t\t\tactor.generation,\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\tresponse,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// Non-streaming request\n\t\t\t\t// Create a pending request entry to track messageIndex for the response\n\t\t\t\tactor.createPendingRequest(gatewayId, requestId, 0);\n\n\t\t\t\tconst response = await this.#fetch(\n\t\t\t\t\treq.actorId,\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\trequest,\n\t\t\t\t);\n\t\t\t\tawait this.#sendResponse(\n\t\t\t\t\tactor.actorId,\n\t\t\t\t\tactor.generation,\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\tresponse,\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (error instanceof RunnerShutdownError) {\n\t\t\t\tthis.log?.debug({ msg: \"catught runner shutdown error\" });\n\t\t\t} else {\n\t\t\t\tthis.log?.error({ msg: \"error handling request\", error });\n\t\t\t\tthis.#sendResponseError(\n\t\t\t\t\tactor.actorId,\n\t\t\t\t\tactor.generation,\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\t500,\n\t\t\t\t\t\"Internal Server Error\",\n\t\t\t\t);\n\t\t\t}\n\t\t} finally {\n\t\t\t// Clean up request tracking\n\t\t\tif (this.#runner.hasActor(req.actorId, actor.generation)) {\n\t\t\t\tactor.deletePendingRequest(gatewayId, requestId);\n\t\t\t\tthis.#removeRequestToActor(gatewayId, requestId);\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #handleRequestChunk(\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t\tchunk: protocol.ToClientRequestChunk,\n\t) {\n\t\tconst actor = await this.getAndWaitForRequestActor(\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t);\n\t\tif (actor) {\n\t\t\tconst pending = actor.getPendingRequest(gatewayId, requestId);\n\t\t\tif (pending?.streamController) {\n\t\t\t\tpending.streamController.enqueue(new Uint8Array(chunk.body));\n\t\t\t\tif (chunk.finish) {\n\t\t\t\t\tpending.streamController.close();\n\t\t\t\t\tactor.deletePendingRequest(gatewayId, requestId);\n\t\t\t\t\tthis.#removeRequestToActor(gatewayId, requestId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #handleRequestAbort(gatewayId: GatewayId, requestId: RequestId) {\n\t\tconst actor = await this.getAndWaitForRequestActor(\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t);\n\t\tif (actor) {\n\t\t\tconst pending = actor.getPendingRequest(gatewayId, requestId);\n\t\t\tif (pending?.streamController) {\n\t\t\t\tpending.streamController.error(new Error(\"Request aborted\"));\n\t\t\t}\n\t\t\tactor.deletePendingRequest(gatewayId, requestId);\n\t\t\tthis.#removeRequestToActor(gatewayId, requestId);\n\t\t}\n\t}\n\n\tasync #sendResponse(\n\t\tactorId: string,\n\t\tgeneration: number,\n\t\tgatewayId: GatewayId,\n\t\trequestId: ArrayBuffer,\n\t\tresponse: Response,\n\t) {\n\t\tif (!this.#runner.hasActor(actorId, generation)) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"actor not loaded to send response, assuming gateway has closed request\",\n\t\t\t\tactorId,\n\t\t\t\tgeneration,\n\t\t\t\trequestId,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Always treat responses as non-streaming for now\n\t\t// In the future, we could detect streaming responses based on:\n\t\t// - Transfer-Encoding: chunked\n\t\t// - Content-Type: text/event-stream\n\t\t// - Explicit stream flag from the handler\n\n\t\t// Read the body first to get the actual content\n\t\tconst body = response.body ? await response.arrayBuffer() : null;\n\n\t\t// Convert headers to map and add Content-Length if not present\n\t\tconst headers = new Map<string, string>();\n\t\tresponse.headers.forEach((value, key) => {\n\t\t\theaders.set(key, value);\n\t\t});\n\n\t\t// Add Content-Length header if we have a body and it's not already set\n\t\tif (body && !headers.has(\"content-length\")) {\n\t\t\theaders.set(\"content-length\", String(body.byteLength));\n\t\t}\n\n\t\t// Send as non-streaming response if actor has not stopped\n\t\tthis.#sendMessage(gatewayId, requestId, {\n\t\t\ttag: \"ToServerResponseStart\",\n\t\t\tval: {\n\t\t\t\tstatus: response.status as protocol.u16,\n\t\t\t\theaders,\n\t\t\t\tbody: body || null,\n\t\t\t\tstream: false,\n\t\t\t},\n\t\t});\n\t}\n\n\t#sendResponseError(\n\t\tactorId: string,\n\t\tgeneration: number,\n\t\tgatewayId: GatewayId,\n\t\trequestId: ArrayBuffer,\n\t\tstatus: number,\n\t\tmessage: string,\n\t) {\n\t\tif (!this.#runner.hasActor(actorId, generation)) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"actor not loaded to send response, assuming gateway has closed request\",\n\t\t\t\tactorId,\n\t\t\t\tgeneration,\n\t\t\t\trequestId,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconst headers = new Map<string, string>();\n\t\theaders.set(\"content-type\", \"text/plain\");\n\n\t\tthis.#sendMessage(gatewayId, requestId, {\n\t\t\ttag: \"ToServerResponseStart\",\n\t\t\tval: {\n\t\t\t\tstatus: status as protocol.u16,\n\t\t\t\theaders,\n\t\t\t\tbody: new TextEncoder().encode(message).buffer as ArrayBuffer,\n\t\t\t\tstream: false,\n\t\t\t},\n\t\t});\n\t}\n\n\tasync #handleWebSocketOpen(\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t\topen: protocol.ToClientWebSocketOpen,\n\t) {\n\t\t// NOTE: This method is safe to be async since we will not receive any\n\t\t// further WebSocket events until we send a ToServerWebSocketOpen\n\t\t// tunnel message. We can do any async logic we need to between thoes two events.\n\t\t//\n\t\t// Sending a ToServerWebSocketClose will terminate the WebSocket early.\n\n\t\tconst requestIdStr = idToStr(requestId);\n\n\t\t// Validate actor exists\n\t\tconst actor = await this.#runner.getAndWaitForActor(open.actorId);\n\t\tif (!actor) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"ignoring websocket for unknown actor\",\n\t\t\t\tactorId: open.actorId,\n\t\t\t});\n\n\t\t\t// NOTE: Closing a WebSocket before open is equivalent to a Service\n\t\t\t// Unavailable error and will cause Guard to retry the request\n\t\t\t//\n\t\t\t// See\n\t\t\t// https://github.com/rivet-dev/rivet/blob/222dae87e3efccaffa2b503de40ecf8afd4e31eb/engine/packages/pegboard-gateway/src/lib.rs#L238\n\t\t\tthis.#sendMessage(gatewayId, requestId, {\n\t\t\t\ttag: \"ToServerWebSocketClose\",\n\t\t\t\tval: {\n\t\t\t\t\tcode: 1011,\n\t\t\t\t\treason: \"Actor not found\",\n\t\t\t\t\thibernate: false,\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Close existing WebSocket if one already exists for this request ID.\n\t\t// This should never happen, but prevents any potential duplicate\n\t\t// WebSockets from retransmits.\n\t\tconst existingAdapter = actor.getWebSocket(gatewayId, requestId);\n\t\tif (existingAdapter) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"closing existing websocket for duplicate open event for the same request id\",\n\t\t\t\trequestId: requestIdStr,\n\t\t\t});\n\t\t\t// Close without sending a message through the tunnel since the server\n\t\t\t// already knows about the new connection\n\t\t\texistingAdapter._closeWithoutCallback(1000, \"ws.duplicate_open\");\n\t\t}\n\n\t\t// Create WebSocket\n\t\ttry {\n\t\t\tconst request = buildRequestForWebSocket(\n\t\t\t\topen.path,\n\t\t\t\tObject.fromEntries(open.headers),\n\t\t\t);\n\n\t\t\tconst canHibernate =\n\t\t\t\tthis.#runner.config.hibernatableWebSocket.canHibernate(\n\t\t\t\t\tactor.actorId,\n\t\t\t\t\tgatewayId,\n\t\t\t\t\trequestId,\n\t\t\t\t\trequest,\n\t\t\t\t);\n\n\t\t\t// #createWebSocket will call `runner.config.websocket` under the\n\t\t\t// hood to add the event listeners for open, etc. If this handler\n\t\t\t// throws, then the WebSocket will be closed before sending the\n\t\t\t// open event.\n\t\t\tconst adapter = await this.#createWebSocket(\n\t\t\t\tactor.actorId,\n\t\t\t\tgatewayId,\n\t\t\t\trequestId,\n\t\t\t\trequestIdStr,\n\t\t\t\t0,\n\t\t\t\tcanHibernate,\n\t\t\t\tfalse,\n\t\t\t\trequest,\n\t\t\t\topen.path,\n\t\t\t\tObject.fromEntries(open.headers),\n\t\t\t\tfalse,\n\t\t\t);\n\n\t\t\t// Create a PendingRequest entry to track the message index\n\t\t\tactor.createPendingRequest(gatewayId, requestId, 0);\n\n\t\t\t// Open the WebSocket after `config.socket` so (a) the event\n\t\t\t// handlers can be added and (b) any errors in `config.websocket`\n\t\t\t// will cause the WebSocket to terminate before the open event.\n\t\t\tthis.#sendMessage(gatewayId, requestId, {\n\t\t\t\ttag: \"ToServerWebSocketOpen\",\n\t\t\t\tval: {\n\t\t\t\t\tcanHibernate,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// Dispatch open event\n\t\t\tadapter._handleOpen(requestId);\n\t\t} catch (error) {\n\t\t\tthis.log?.error({ msg: \"error handling websocket open\", error });\n\n\t\t\t// TODO: Call close event on adapter if needed\n\n\t\t\t// Send close on error\n\t\t\tthis.#sendMessage(gatewayId, requestId, {\n\t\t\t\ttag: \"ToServerWebSocketClose\",\n\t\t\t\tval: {\n\t\t\t\t\tcode: 1011,\n\t\t\t\t\treason: \"Server Error\",\n\t\t\t\t\thibernate: false,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// Clean up actor tracking\n\t\t\tactor.deleteWebSocket(gatewayId, requestId);\n\t\t\tactor.deletePendingRequest(gatewayId, requestId);\n\t\t\tthis.#removeRequestToActor(gatewayId, requestId);\n\t\t}\n\t}\n\n\tasync #handleWebSocketMessage(\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t\tserverMessageIndex: number,\n\t\tmsg: protocol.ToClientWebSocketMessage,\n\t) {\n\t\tconst actor = await this.getAndWaitForRequestActor(\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t);\n\t\tif (actor) {\n\t\t\tconst adapter = actor.getWebSocket(gatewayId, requestId);\n\t\t\tif (adapter) {\n\t\t\t\tconst data = msg.binary\n\t\t\t\t\t? new Uint8Array(msg.data)\n\t\t\t\t\t: new TextDecoder().decode(new Uint8Array(msg.data));\n\n\t\t\t\tadapter._handleMessage(\n\t\t\t\t\trequestId,\n\t\t\t\t\tdata,\n\t\t\t\t\tserverMessageIndex,\n\t\t\t\t\tmsg.binary,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// TODO: This will never retransmit the socket and the socket will close\n\t\tthis.log?.warn({\n\t\t\tmsg: \"missing websocket for incoming websocket message, this may indicate the actor stopped before processing a message\",\n\t\t\trequestId,\n\t\t});\n\t}\n\n\tsendHibernatableWebSocketMessageAck(\n\t\tgatewayId: ArrayBuffer,\n\t\trequestId: ArrayBuffer,\n\t\tclientMessageIndex: number,\n\t) {\n\t\tconst requestIdStr = idToStr(requestId);\n\n\t\tthis.log?.debug({\n\t\t\tmsg: \"ack ws msg\",\n\t\t\trequestId: requestIdStr,\n\t\t\tindex: clientMessageIndex,\n\t\t});\n\n\t\tif (clientMessageIndex < 0 || clientMessageIndex > 65535)\n\t\t\tthrow new Error(\"invalid websocket ack index\");\n\n\t\t// Get the actor to find the gatewayId\n\t\t//\n\t\t// We don't have to wait for the actor to start since we're not calling\n\t\t// any callbacks on the actor\n\t\tconst actor = this.getRequestActor(gatewayId, requestId);\n\t\tif (!actor) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"cannot send websocket ack, actor not found\",\n\t\t\t\trequestId: requestIdStr,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Get gatewayId from the pending request\n\t\tconst pending = actor.getPendingRequest(gatewayId, requestId);\n\t\tif (!pending?.gatewayId) {\n\t\t\tthis.log?.warn({\n\t\t\t\tmsg: \"cannot send websocket ack, gatewayId not found in pending request\",\n\t\t\t\trequestId: requestIdStr,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Send the ack message\n\t\tthis.#sendMessage(pending.gatewayId, requestId, {\n\t\t\ttag: \"ToServerWebSocketMessageAck\",\n\t\t\tval: {\n\t\t\t\tindex: clientMessageIndex,\n\t\t\t},\n\t\t});\n\t}\n\n\tasync #handleWebSocketClose(\n\t\tgatewayId: GatewayId,\n\t\trequestId: RequestId,\n\t\tclose: protocol.ToClientWebSocketClose,\n\t) {\n\t\tconst actor = await this.getAndWaitForRequestActor(\n\t\t\tgatewayId,\n\t\t\trequestId,\n\t\t);\n\t\tif (actor) {\n\t\t\tconst adapter = actor.getWebSocket(gatewayId, requestId);\n\t\t\tif (adapter) {\n\t\t\t\t// We don't need to send a close response\n\t\t\t\tadapter._handleClose(\n\t\t\t\t\trequestId,\n\t\t\t\t\tclose.code || undefined,\n\t\t\t\t\tclose.reason || undefined,\n\t\t\t\t);\n\t\t\t\tactor.deleteWebSocket(gatewayId, requestId);\n\t\t\t\tactor.deletePendingRequest(gatewayId, requestId);\n\t\t\t\tthis.#removeRequestToActor(gatewayId, requestId);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Builds a request that represents the incoming request for a given WebSocket.\n *\n * This request is not a real request and will never be sent. It's used to be passed to the actor to behave like a real incoming request.\n */\nfunction buildRequestForWebSocket(\n\tpath: string,\n\theaders: Record<string, string>,\n): Request {\n\t// We need to manually ensure the original Upgrade/Connection WS\n\t// headers are present\n\tconst fullHeaders = {\n\t\t...headers,\n\t\tUpgrade: \"websocket\",\n\t\tConnection: \"Upgrade\",\n\t};\n\n\tif (!path.startsWith(\"/\")) {\n\t\tthrow new Error(\"path must start with leading slash\");\n\t}\n\n\tconst request = new Request(`http://actor${path}`, {\n\t\tmethod: \"GET\",\n\t\theaders: fullHeaders,\n\t});\n\n\treturn request;\n}\n","import { logger } from \"./log\";\n\n// Global singleton promise that will be reused for subsequent calls\nlet webSocketPromise: Promise<typeof WebSocket> | null = null;\n\nexport async function importWebSocket(): Promise<typeof WebSocket> {\n\t// Return existing promise if we already started loading\n\tif (webSocketPromise !== null) {\n\t\treturn webSocketPromise;\n\t}\n\n\t// Create and store the promise\n\twebSocketPromise = (async () => {\n\t\tlet _WebSocket: typeof WebSocket;\n\n\t\tif (typeof WebSocket !== \"undefined\") {\n\t\t\t// Native\n\t\t\t_WebSocket = WebSocket as unknown as typeof WebSocket;\n\t\t\tlogger()?.debug({ msg: \"using native websocket\" });\n\t\t} else {\n\t\t\t// Node.js package\n\t\t\ttry {\n\t\t\t\tconst ws = await import(\"ws\");\n\t\t\t\t_WebSocket = ws.default as unknown as typeof WebSocket;\n\t\t\t\tlogger()?.debug({ msg: \"using websocket from npm\" });\n\t\t\t} catch {\n\t\t\t\t// WS not available\n\t\t\t\t_WebSocket = class MockWebSocket {\n\t\t\t\t\tconstructor() {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t'WebSocket support requires installing the \"ws\" peer dependency.',\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} as unknown as typeof WebSocket;\n\t\t\t\tlogger()?.debug({ msg: \"using mock websocket\" });\n\t\t\t}\n\t\t}\n\n\t\treturn _WebSocket;\n\t})();\n\n\treturn webSocketPromise;\n}\n"],"mappings":"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","names":["logger","_a","actor","entry","_a","_b","actor"]}
|