rivetkit 2.1.2 → 2.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/client.js +1 -1
- package/dist/browser/client.js.map +1 -1
- package/dist/browser/inspector/client.js +1 -1
- package/dist/browser/inspector/client.js.map +1 -1
- package/dist/inspector.tar.gz +0 -0
- package/dist/tsup/{chunk-NXEHFUDB.cjs → chunk-5AZ6UPEF.cjs} +24 -21
- package/dist/tsup/chunk-5AZ6UPEF.cjs.map +1 -0
- package/dist/tsup/{chunk-YQ5P6KMN.js → chunk-6LHZQSWJ.js} +8 -5
- package/dist/tsup/{chunk-YQ5P6KMN.js.map → chunk-6LHZQSWJ.js.map} +1 -1
- package/dist/tsup/{chunk-BFI4LYS2.js → chunk-6T3WSP5M.js} +4 -4
- package/dist/tsup/{chunk-772NPMTY.cjs → chunk-BMNB6YRQ.cjs} +160 -103
- package/dist/tsup/chunk-BMNB6YRQ.cjs.map +1 -0
- package/dist/tsup/{chunk-GVQAVU7R.cjs → chunk-DADGS67O.cjs} +4 -4
- package/dist/tsup/{chunk-GVQAVU7R.cjs.map → chunk-DADGS67O.cjs.map} +1 -1
- package/dist/tsup/{chunk-RHUII57M.js → chunk-GNGRMP5E.js} +10 -6
- package/dist/tsup/chunk-GNGRMP5E.js.map +1 -0
- package/dist/tsup/{chunk-PZAV6PP2.cjs → chunk-HPAX7L72.cjs} +152 -152
- package/dist/tsup/{chunk-PZAV6PP2.cjs.map → chunk-HPAX7L72.cjs.map} +1 -1
- package/dist/tsup/{chunk-UZV7NXC6.cjs → chunk-IJAGZS57.cjs} +30 -30
- package/dist/tsup/{chunk-UZV7NXC6.cjs.map → chunk-IJAGZS57.cjs.map} +1 -1
- package/dist/tsup/{chunk-HFWRHT5T.cjs → chunk-KSZZRTOD.cjs} +3 -3
- package/dist/tsup/{chunk-HFWRHT5T.cjs.map → chunk-KSZZRTOD.cjs.map} +1 -1
- package/dist/tsup/{chunk-PSUVV4HM.js → chunk-MAXIXG56.js} +2 -2
- package/dist/tsup/{chunk-HB4RGGMC.js → chunk-N7ASEZ2Y.js} +5 -5
- package/dist/tsup/{chunk-PW3YONDJ.js → chunk-OAOF23ZY.js} +2 -2
- package/dist/tsup/{chunk-TDFDR7AO.js → chunk-POUBQA6Z.js} +2 -2
- package/dist/tsup/{chunk-VMX4I4MP.js → chunk-QUDLEWGD.js} +3 -3
- package/dist/tsup/{chunk-MNS5LY6M.cjs → chunk-R64EFI6F.cjs} +74 -74
- package/dist/tsup/{chunk-MNS5LY6M.cjs.map → chunk-R64EFI6F.cjs.map} +1 -1
- package/dist/tsup/{chunk-QABDKI3W.cjs → chunk-T6MM5RTW.cjs} +248 -244
- package/dist/tsup/chunk-T6MM5RTW.cjs.map +1 -0
- package/dist/tsup/{chunk-ZHQDRRMY.cjs → chunk-U6VWVHVW.cjs} +3 -3
- package/dist/tsup/{chunk-ZHQDRRMY.cjs.map → chunk-U6VWVHVW.cjs.map} +1 -1
- package/dist/tsup/{chunk-WUXR722E.js → chunk-YET3IZD6.js} +2 -2
- package/dist/tsup/{chunk-WUXR722E.js.map → chunk-YET3IZD6.js.map} +1 -1
- package/dist/tsup/{chunk-BSIJG3LG.js → chunk-YLDDENCZ.js} +69 -12
- package/dist/tsup/chunk-YLDDENCZ.js.map +1 -0
- package/dist/tsup/{chunk-RMJJE43B.cjs → chunk-ZSJ2OTY4.cjs} +2 -2
- package/dist/tsup/{chunk-RMJJE43B.cjs.map → chunk-ZSJ2OTY4.cjs.map} +1 -1
- package/dist/tsup/client/mod.cjs +6 -6
- package/dist/tsup/client/mod.js +5 -5
- package/dist/tsup/common/log.cjs +2 -2
- package/dist/tsup/common/log.js +1 -1
- package/dist/tsup/common/websocket.cjs +3 -3
- package/dist/tsup/common/websocket.js +2 -2
- package/dist/tsup/driver-helpers/mod.cjs +4 -4
- package/dist/tsup/driver-helpers/mod.js +3 -3
- package/dist/tsup/driver-test-suite/mod.cjs +425 -338
- package/dist/tsup/driver-test-suite/mod.cjs.map +1 -1
- package/dist/tsup/driver-test-suite/mod.js +376 -289
- package/dist/tsup/driver-test-suite/mod.js.map +1 -1
- package/dist/tsup/inspector/mod.cjs +3 -3
- package/dist/tsup/inspector/mod.js +2 -2
- package/dist/tsup/mod.cjs +8 -8
- package/dist/tsup/mod.js +7 -7
- package/dist/tsup/serve-test-suite/mod.cjs +111 -99
- package/dist/tsup/serve-test-suite/mod.cjs.map +1 -1
- package/dist/tsup/serve-test-suite/mod.js +22 -10
- package/dist/tsup/serve-test-suite/mod.js.map +1 -1
- package/dist/tsup/test/mod.cjs +10 -10
- package/dist/tsup/test/mod.js +6 -6
- package/dist/tsup/utils.cjs +2 -2
- package/dist/tsup/utils.js +1 -1
- package/dist/tsup/workflow/mod.cjs +5 -5
- package/dist/tsup/workflow/mod.js +4 -4
- package/package.json +5 -5
- package/src/actor/instance/mod.ts +13 -2
- package/src/driver-test-suite/tests/actor-db.ts +299 -216
- package/src/driver-test-suite/tests/actor-queue.ts +10 -9
- package/src/driver-test-suite/tests/actor-workflow.ts +12 -2
- package/src/driver-test-suite/utils.ts +8 -8
- package/src/drivers/engine/actor-driver.ts +77 -7
- package/src/workflow/driver.ts +4 -1
- package/dist/tsup/chunk-772NPMTY.cjs.map +0 -1
- package/dist/tsup/chunk-BSIJG3LG.js.map +0 -1
- package/dist/tsup/chunk-NXEHFUDB.cjs.map +0 -1
- package/dist/tsup/chunk-QABDKI3W.cjs.map +0 -1
- package/dist/tsup/chunk-RHUII57M.js.map +0 -1
- /package/dist/tsup/{chunk-BFI4LYS2.js.map → chunk-6T3WSP5M.js.map} +0 -0
- /package/dist/tsup/{chunk-PSUVV4HM.js.map → chunk-MAXIXG56.js.map} +0 -0
- /package/dist/tsup/{chunk-HB4RGGMC.js.map → chunk-N7ASEZ2Y.js.map} +0 -0
- /package/dist/tsup/{chunk-PW3YONDJ.js.map → chunk-OAOF23ZY.js.map} +0 -0
- /package/dist/tsup/{chunk-TDFDR7AO.js.map → chunk-POUBQA6Z.js.map} +0 -0
- /package/dist/tsup/{chunk-VMX4I4MP.js.map → chunk-QUDLEWGD.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/rivet/rivet/rivetkit-typescript/packages/rivetkit/dist/tsup/chunk-PZAV6PP2.cjs","../../src/devtools-loader/log.ts","../../src/devtools-loader/index.ts","../../src/remote-manager-driver/mod.ts","../../src/remote-manager-driver/api-utils.ts","../../src/client/utils.ts","../../src/client/errors.ts","../../src/remote-manager-driver/log.ts","../../src/remote-manager-driver/actor-websocket-client.ts","../../src/remote-manager-driver/actor-http-client.ts","../../src/remote-manager-driver/api-endpoints.ts","../../src/remote-manager-driver/metadata.ts","../../src/remote-manager-driver/ws-proxy.ts","../../src/client/actor-conn.ts","../../src/client/actor-query.ts","../../src/client/queue.ts","../../src/client/actor-handle.ts","../../src/client/raw-utils.ts","../../src/client/client.ts","../../src/client/config.ts","../../src/client/mod.ts"],"names":["logger","WebSocket","id"],"mappings":"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","file":"/home/runner/work/rivet/rivet/rivetkit-typescript/packages/rivetkit/dist/tsup/chunk-PZAV6PP2.cjs","sourcesContent":[null,"import { getLogger } from \"@/common/log\";\n\nexport function logger() {\n\treturn getLogger(\"devtools\");\n}\n","import type { ClientConfigInput } from \"@/client/client\";\nimport { VERSION } from \"@/utils\";\nimport { logger } from \"./log\";\n\ndeclare global {\n\t// Injected via tsup config\n\t// biome-ignore lint/style/noVar: required for global declaration\n\tvar CUSTOM_RIVETKIT_DEVTOOLS_URL: string | undefined;\n}\n\nconst DEFAULT_DEVTOOLS_URL = (version = VERSION) =>\n\t`https://releases.rivet.dev/rivet/latest/devtools/mod.js?v=${version}`;\n\nconst scriptId = \"rivetkit-devtools-script\";\n\nexport function injectDevtools(config: ClientConfigInput) {\n\tif (!window) {\n\t\tlogger().warn(\"devtools not available outside browser environment\");\n\t\treturn;\n\t}\n\n\tif (!document.getElementById(scriptId)) {\n\t\tconst script = document.createElement(\"script\");\n\t\tscript.id = scriptId;\n\t\tscript.src =\n\t\t\tglobalThis.CUSTOM_RIVETKIT_DEVTOOLS_URL || DEFAULT_DEVTOOLS_URL();\n\t\tscript.async = true;\n\t\tdocument.head.appendChild(script);\n\t}\n\n\twindow.__rivetkit = window.__rivetkit || [];\n\twindow.__rivetkit.push(config);\n}\n","import * as cbor from \"cbor-x\";\nimport type { Context as HonoContext } from \"hono\";\nimport invariant from \"invariant\";\nimport { deserializeActorKey, serializeActorKey } from \"@/actor/keys\";\nimport type { ClientConfig } from \"@/client/client\";\nimport { noopNext } from \"@/common/utils\";\nimport type {\n\tActorOutput,\n\tCreateInput,\n\tGetForIdInput,\n\tGetOrCreateWithKeyInput,\n\tGetWithKeyInput,\n\tListActorsInput,\n\tManagerDisplayInformation,\n\tManagerDriver,\n} from \"@/driver-helpers/mod\";\nimport type { Actor as ApiActor } from \"@/manager-api/actors\";\nimport type { Encoding, UniversalWebSocket } from \"@/mod\";\nimport { uint8ArrayToBase64 } from \"@/serde\";\nimport { combineUrlPath, type GetUpgradeWebSocket } from \"@/utils\";\nimport { getNextPhase } from \"@/utils/env-vars\";\nimport { sendHttpRequestToActor } from \"./actor-http-client\";\nimport {\n\tbuildActorGatewayUrl,\n\tbuildWebSocketProtocols,\n\topenWebSocketToActor,\n} from \"./actor-websocket-client\";\nimport {\n\tcreateActor,\n\tdestroyActor,\n\tgetActor,\n\tgetActorByKey,\n\tgetOrCreateActor,\n\tkvGet,\n\tlistActorsByName,\n} from \"./api-endpoints\";\nimport { EngineApiError, getEndpoint } from \"./api-utils\";\nimport { logger } from \"./log\";\nimport { lookupMetadataCached } from \"./metadata\";\nimport { createWebSocketProxy } from \"./ws-proxy\";\n\n// TODO:\n// // Lazily import the dynamic imports so we don't have to turn `createClient` in to an async fn\n// const dynamicImports = (async () => {\n// \t// Import dynamic dependencies\n// \tconst [WebSocket, EventSource] = await Promise.all([\n// \t\timportWebSocket(),\n// \t\timportEventSource(),\n// \t]);\n// \treturn {\n// \t\tWebSocket,\n// \t\tEventSource,\n// \t};\n// })();\n\nexport class RemoteManagerDriver implements ManagerDriver {\n\t#config: ClientConfig;\n\t#metadataPromise: Promise<void> | undefined;\n\n\tconstructor(runConfig: ClientConfig) {\n\t\t// Disable health check if in Next.js build phase since there is no `/metadata` endpoint\n\t\t//\n\t\t// See https://github.com/vercel/next.js/blob/5e6b008b561caf2710ab7be63320a3d549474a5b/packages/next/shared/lib/constants.ts#L19-L23\n\t\tif (getNextPhase() === \"phase-production-build\") {\n\t\t\tlogger().info(\n\t\t\t\t\"detected next.js build phase, disabling health check\",\n\t\t\t);\n\t\t\trunConfig.disableMetadataLookup = true;\n\t\t}\n\n\t\t// Clone config so we can mutate the endpoint in #metadataPromise\n\t\t// NOTE: This is a shallow clone, so mutating nested properties will not do anything\n\t\tthis.#config = { ...runConfig };\n\n\t\t// Perform metadata check if enabled\n\t\tif (!runConfig.disableMetadataLookup) {\n\t\t\t// This should never error, since it uses pRetry. If it does for\n\t\t\t// any reason, we'll surface the error anywhere #metadataPromise is\n\t\t\t// awaited.\n\t\t\tthis.#metadataPromise = lookupMetadataCached(this.#config).then(\n\t\t\t\t(metadataData) => {\n\t\t\t\t\t// Override endpoint for all future requests\n\t\t\t\t\tif (metadataData.clientEndpoint) {\n\t\t\t\t\t\tthis.#config.endpoint = metadataData.clientEndpoint;\n\t\t\t\t\t\tif (metadataData.clientNamespace) {\n\t\t\t\t\t\t\tthis.#config.namespace =\n\t\t\t\t\t\t\t\tmetadataData.clientNamespace;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (metadataData.clientToken) {\n\t\t\t\t\t\t\tthis.#config.token = metadataData.clientToken;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlogger().info({\n\t\t\t\t\t\t\tmsg: \"overriding client endpoint\",\n\t\t\t\t\t\t\tendpoint: metadataData.clientEndpoint,\n\t\t\t\t\t\t\tnamespace: metadataData.clientNamespace,\n\t\t\t\t\t\t\ttoken: metadataData.clientToken,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tlogger().info({\n\t\t\t\t\t\tmsg: \"connected to rivetkit manager\",\n\t\t\t\t\t\truntime: metadataData.runtime,\n\t\t\t\t\t\tversion: metadataData.version,\n\t\t\t\t\t\trunner: metadataData.runner,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\n\tasync getForId({\n\t\tc,\n\t\tname,\n\t\tactorId,\n\t}: GetForIdInput): Promise<ActorOutput | undefined> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\t// Fetch from API if not in cache\n\t\tconst response = await getActor(this.#config, name, actorId);\n\t\tconst actor = response.actors[0];\n\t\tif (!actor) return undefined;\n\n\t\t// Validate name matches\n\t\tif (actor.name !== name) {\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"actor name mismatch from api\",\n\t\t\t\tactorId,\n\t\t\t\tapiName: actor.name,\n\t\t\t\trequestedName: name,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn apiActorToOutput(actor);\n\t}\n\n\tasync getWithKey({\n\t\tc,\n\t\tname,\n\t\tkey,\n\t}: GetWithKeyInput): Promise<ActorOutput | undefined> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\tlogger().debug({ msg: \"getWithKey: searching for actor\", name, key });\n\n\t\t// If not in local cache, fetch by key from API\n\t\ttry {\n\t\t\tconst response = await getActorByKey(this.#config, name, key);\n\t\t\tconst actor = response.actors[0];\n\t\t\tif (!actor) return undefined;\n\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"getWithKey: found actor via api\",\n\t\t\t\tactorId: actor.actor_id,\n\t\t\t\tname,\n\t\t\t\tkey,\n\t\t\t});\n\n\t\t\treturn apiActorToOutput(actor);\n\t\t} catch (error) {\n\t\t\tif (\n\t\t\t\terror instanceof EngineApiError &&\n\t\t\t\t(error as EngineApiError).group === \"actor\" &&\n\t\t\t\t(error as EngineApiError).code === \"not_found\"\n\t\t\t) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync getOrCreateWithKey(\n\t\tinput: GetOrCreateWithKeyInput,\n\t): Promise<ActorOutput> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\tconst { c, name, key, input: actorInput, region } = input;\n\n\t\tlogger().info({\n\t\t\tmsg: \"getOrCreateWithKey: getting or creating actor via engine api\",\n\t\t\tname,\n\t\t\tkey,\n\t\t});\n\n\t\tconst { actor, created } = await getOrCreateActor(this.#config, {\n\t\t\tdatacenter: region,\n\t\t\tname,\n\t\t\tkey: serializeActorKey(key),\n\t\t\trunner_name_selector: this.#config.runnerName,\n\t\t\tinput: actorInput\n\t\t\t\t? uint8ArrayToBase64(cbor.encode(actorInput))\n\t\t\t\t: undefined,\n\t\t\tcrash_policy: \"sleep\",\n\t\t});\n\n\t\tlogger().info({\n\t\t\tmsg: \"getOrCreateWithKey: actor ready\",\n\t\t\tactorId: actor.actor_id,\n\t\t\tname,\n\t\t\tkey,\n\t\t\tcreated,\n\t\t});\n\n\t\treturn apiActorToOutput(actor);\n\t}\n\n\tasync createActor({\n\t\tc,\n\t\tname,\n\t\tkey,\n\t\tinput,\n\t\tregion,\n\t}: CreateInput): Promise<ActorOutput> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\tlogger().info({ msg: \"creating actor via engine api\", name, key });\n\n\t\t// Create actor via engine API\n\t\tconst result = await createActor(this.#config, {\n\t\t\tdatacenter: region,\n\t\t\tname,\n\t\t\trunner_name_selector: this.#config.runnerName,\n\t\t\tkey: serializeActorKey(key),\n\t\t\tinput: input ? uint8ArrayToBase64(cbor.encode(input)) : undefined,\n\t\t\tcrash_policy: \"sleep\",\n\t\t});\n\n\t\tlogger().info({\n\t\t\tmsg: \"actor created\",\n\t\t\tactorId: result.actor.actor_id,\n\t\t\tname,\n\t\t\tkey,\n\t\t});\n\n\t\treturn apiActorToOutput(result.actor);\n\t}\n\n\tasync listActors({ c, name }: ListActorsInput): Promise<ActorOutput[]> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\tlogger().debug({ msg: \"listing actors via engine api\", name });\n\n\t\tconst response = await listActorsByName(this.#config, name);\n\n\t\treturn response.actors.map(apiActorToOutput);\n\t}\n\n\tasync destroyActor(actorId: string): Promise<void> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\tlogger().info({ msg: \"destroying actor via engine api\", actorId });\n\n\t\tawait destroyActor(this.#config, actorId);\n\n\t\tlogger().info({ msg: \"actor destroyed\", actorId });\n\t}\n\n\tasync sendRequest(\n\t\tactorId: string,\n\t\tactorRequest: Request,\n\t): Promise<Response> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\treturn await sendHttpRequestToActor(\n\t\t\tthis.#config,\n\t\t\tactorId,\n\t\t\tactorRequest,\n\t\t);\n\t}\n\n\tasync openWebSocket(\n\t\tpath: string,\n\t\tactorId: string,\n\t\tencoding: Encoding,\n\t\tparams: unknown,\n\t): Promise<UniversalWebSocket> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\treturn await openWebSocketToActor(\n\t\t\tthis.#config,\n\t\t\tpath,\n\t\t\tactorId,\n\t\t\tencoding,\n\t\t\tparams,\n\t\t);\n\t}\n\n\tasync buildGatewayUrl(actorId: string): Promise<string> {\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\tconst endpoint = getEndpoint(this.#config);\n\t\treturn buildActorGatewayUrl(endpoint, actorId, this.#config.token);\n\t}\n\n\tasync proxyRequest(\n\t\t_c: HonoContext,\n\t\tactorRequest: Request,\n\t\tactorId: string,\n\t): Promise<Response> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\treturn await sendHttpRequestToActor(\n\t\t\tthis.#config,\n\t\t\tactorId,\n\t\t\tactorRequest,\n\t\t);\n\t}\n\n\tasync proxyWebSocket(\n\t\tc: HonoContext,\n\t\tpath: string,\n\t\tactorId: string,\n\t\tencoding: Encoding,\n\t\tparams: unknown,\n\t): Promise<Response> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\tconst upgradeWebSocket = this.#config.getUpgradeWebSocket?.();\n\t\tinvariant(upgradeWebSocket, \"missing getUpgradeWebSocket\");\n\n\t\tconst endpoint = getEndpoint(this.#config);\n\t\tconst guardUrl = combineUrlPath(endpoint, path);\n\t\tconst wsGuardUrl = guardUrl.replace(\"http://\", \"ws://\");\n\n\t\tlogger().debug({\n\t\t\tmsg: \"forwarding websocket to actor via guard\",\n\t\t\tactorId,\n\t\t\tpath,\n\t\t\tguardUrl,\n\t\t});\n\n\t\t// Build protocols\n\t\tconst protocols = buildWebSocketProtocols(\n\t\t\tthis.#config,\n\t\t\tencoding,\n\t\t\tparams,\n\t\t);\n\t\tconst args = await createWebSocketProxy(c, wsGuardUrl, protocols);\n\n\t\treturn await upgradeWebSocket(() => args)(c, noopNext());\n\t}\n\n\tasync kvGet(actorId: string, key: Uint8Array): Promise<string | null> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\tlogger().debug({ msg: \"getting kv value via engine api\", key });\n\n\t\tconst response = await kvGet(\n\t\t\tthis.#config,\n\t\t\tactorId,\n\t\t\tnew TextDecoder(\"utf8\").decode(key),\n\t\t);\n\n\t\treturn response.value;\n\t}\n\n\tdisplayInformation(): ManagerDisplayInformation {\n\t\treturn { properties: {} };\n\t}\n\n\tsetGetUpgradeWebSocket(getUpgradeWebSocket: GetUpgradeWebSocket): void {\n\t\tthis.#config.getUpgradeWebSocket = getUpgradeWebSocket;\n\t}\n}\n\nfunction apiActorToOutput(actor: ApiActor): ActorOutput {\n\treturn {\n\t\tactorId: actor.actor_id,\n\t\tname: actor.name,\n\t\tkey: deserializeActorKey(actor.key),\n\t\tcreateTs: actor.create_ts,\n\t\tstartTs: actor.start_ts ?? null,\n\t\tconnectableTs: actor.connectable_ts ?? null,\n\t\tsleepTs: actor.sleep_ts ?? null,\n\t\tdestroyTs: actor.destroy_ts ?? null,\n\t\terror: actor.error ?? undefined,\n\t};\n}\n","import { z } from \"zod/v4\";\nimport type { ClientConfig } from \"@/client/config\";\nimport { sendHttpRequest } from \"@/client/utils\";\nimport { combineUrlPath } from \"@/utils\";\nimport { logger } from \"./log\";\nimport { RegistryConfig } from \"@/registry/config\";\n\n// Error class for Engine API errors\nexport class EngineApiError extends Error {\n\tconstructor(\n\t\tpublic readonly group: string,\n\t\tpublic readonly code: string,\n\t\tmessage?: string,\n\t) {\n\t\tsuper(message || `Engine API error: ${group}/${code}`);\n\t\tthis.name = \"EngineApiError\";\n\t}\n}\n\n// TODO: Remove getEndpoint, but it's used in a lot of places\nexport function getEndpoint(config: ClientConfig | RegistryConfig) {\n\t// Endpoint is always defined for ClientConfig (has default in schema).\n\t// RegistryConfig may not have endpoint if using local manager.\n\treturn config.endpoint ?? \"http://127.0.0.1:6420\";\n}\n\n// Helper function for making API calls\nexport async function apiCall<TInput = unknown, TOutput = unknown>(\n\tconfig: ClientConfig,\n\tmethod: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\",\n\tpath: string,\n\tbody?: TInput,\n): Promise<TOutput> {\n\tconst endpoint = getEndpoint(config);\n\tconst url = combineUrlPath(endpoint, path, {\n\t\tnamespace: config.namespace,\n\t});\n\n\tlogger().debug({ msg: \"making api call\", method, url });\n\n\tconst headers: Record<string, string> = {\n\t\t...config.headers,\n\t};\n\n\t// Add Authorization header if token is provided\n\tif (config.token) {\n\t\theaders.Authorization = `Bearer ${config.token}`;\n\t}\n\n\treturn await sendHttpRequest<TInput, TOutput>({\n\t\tmethod,\n\t\turl,\n\t\theaders,\n\t\tbody,\n\t\tencoding: \"json\",\n\t\tskipParseResponse: false,\n\t\trequestVersionedDataHandler: undefined,\n\t\trequestVersion: undefined,\n\t\tresponseVersionedDataHandler: undefined,\n\t\tresponseVersion: undefined,\n\t\trequestZodSchema: z.any() as z.ZodType<TInput>,\n\t\tresponseZodSchema: z.any() as z.ZodType<TOutput>,\n\t\t// Identity conversions (passthrough for generic API calls)\n\t\trequestToJson: (value) => value,\n\t\trequestToBare: (value) => value,\n\t\tresponseFromJson: (value) => value,\n\t\tresponseFromBare: (value) => value,\n\t});\n}\n","import * as cbor from \"cbor-x\";\nimport invariant from \"invariant\";\nimport type { VersionedDataHandler } from \"vbare\";\nimport type { z } from \"zod/v4\";\nimport type { Encoding } from \"@/actor/protocol/serde\";\nimport { assertUnreachable } from \"@/common/utils\";\nimport type { HttpResponseError } from \"@/schemas/client-protocol/mod\";\nimport { HTTP_RESPONSE_ERROR_VERSIONED } from \"@/schemas/client-protocol/versioned\";\nimport {\n\ttype HttpResponseError as HttpResponseErrorJson,\n\tHttpResponseErrorSchema,\n} from \"@/schemas/client-protocol-zod/mod\";\nimport {\n\tcontentTypeForEncoding,\n\tdeserializeWithEncoding,\n\tencodingIsBinary,\n\tserializeWithEncoding,\n} from \"@/serde\";\nimport { httpUserAgent } from \"@/utils\";\nimport { ActorError, HttpRequestError } from \"./errors\";\nimport { logger } from \"./log\";\n\nexport interface ParsedCloseReason {\n\tgroup: string;\n\tcode: string;\n\trayId?: string;\n}\n\n/**\n * Parses WebSocket close reason string into structured data.\n *\n * Expected format examples:\n * - \"guard.actor_runner_failed#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, code] = mainPart.split(\".\");\n\n\tif (!group || !code) {\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\tcode,\n\t\trayId,\n\t};\n}\n\nexport type WebSocketMessage = string | Blob | ArrayBuffer | Uint8Array;\n\nexport function messageLength(message: WebSocketMessage): number {\n\tif (message instanceof Blob) {\n\t\treturn message.size;\n\t}\n\tif (message instanceof ArrayBuffer) {\n\t\treturn message.byteLength;\n\t}\n\tif (message instanceof Uint8Array) {\n\t\treturn message.byteLength;\n\t}\n\tif (typeof message === \"string\") {\n\t\treturn message.length;\n\t}\n\tassertUnreachable(message);\n}\n\nexport interface HttpRequestOpts<\n\tRequestBare,\n\tResponseBare,\n\tRequestJson = RequestBare,\n\tResponseJson = ResponseBare,\n\tRequest = RequestBare,\n\tResponse = ResponseBare,\n> {\n\tmethod: string;\n\turl: string;\n\theaders: Record<string, string>;\n\tbody?: Request;\n\tencoding: Encoding;\n\tskipParseResponse?: boolean;\n\tsignal?: AbortSignal;\n\tcustomFetch?: (req: globalThis.Request) => Promise<globalThis.Response>;\n\trequestVersionedDataHandler: VersionedDataHandler<RequestBare> | undefined;\n\trequestVersion: number | undefined;\n\tresponseVersionedDataHandler:\n\t\t| VersionedDataHandler<ResponseBare>\n\t\t| undefined;\n\tresponseVersion: number | undefined;\n\trequestZodSchema: z.ZodType<RequestJson>;\n\tresponseZodSchema: z.ZodType<ResponseJson>;\n\trequestToJson: (value: Request) => RequestJson;\n\trequestToBare: (value: Request) => RequestBare;\n\tresponseFromJson: (value: ResponseJson) => Response;\n\tresponseFromBare: (value: ResponseBare) => Response;\n}\n\nexport async function sendHttpRequest<\n\tRequestBare = unknown,\n\tResponseBare = unknown,\n\tRequestJson = RequestBare,\n\tResponseJson = ResponseBare,\n\tRequest = RequestBare,\n\tResponse = ResponseBare,\n>(\n\topts: HttpRequestOpts<\n\t\tRequestBare,\n\t\tResponseBare,\n\t\tRequestJson,\n\t\tResponseJson,\n\t\tRequest,\n\t\tResponse\n\t>,\n): Promise<Response> {\n\tlogger().debug({\n\t\tmsg: \"sending http request\",\n\t\turl: opts.url,\n\t\tencoding: opts.encoding,\n\t});\n\n\t// Serialize body\n\tlet contentType: string | undefined;\n\tlet bodyData: string | Uint8Array | undefined;\n\tif (opts.method === \"POST\" || opts.method === \"PUT\") {\n\t\tinvariant(opts.body !== undefined, \"missing body\");\n\t\tcontentType = contentTypeForEncoding(opts.encoding);\n\t\tbodyData = serializeWithEncoding<RequestBare, RequestJson, Request>(\n\t\t\topts.encoding,\n\t\t\topts.body,\n\t\t\topts.requestVersionedDataHandler,\n\t\t\topts.requestVersion,\n\t\t\topts.requestZodSchema,\n\t\t\topts.requestToJson,\n\t\t\topts.requestToBare,\n\t\t);\n\t}\n\n\t// Send request\n\tlet response: globalThis.Response;\n\ttry {\n\t\t// Make the HTTP request\n\t\tresponse = await (opts.customFetch ?? fetch)(\n\t\t\tnew globalThis.Request(opts.url, {\n\t\t\t\tmethod: opts.method,\n\t\t\t\theaders: {\n\t\t\t\t\t...opts.headers,\n\t\t\t\t\t...(contentType\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\"Content-Type\": contentType,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {}),\n\t\t\t\t\t\"User-Agent\": httpUserAgent(),\n\t\t\t\t},\n\t\t\t\tbody: bodyData,\n\t\t\t\tcredentials: \"include\",\n\t\t\t\tsignal: opts.signal,\n\t\t\t}),\n\t\t);\n\t} catch (error) {\n\t\tthrow new HttpRequestError(`Request failed: ${error}`, {\n\t\t\tcause: error,\n\t\t});\n\t}\n\n\t// Parse response error\n\tif (!response.ok) {\n\t\tconst bufferResponse = await response.arrayBuffer();\n\t\tconst contentType = response.headers.get(\"content-type\");\n\t\tconst rayId = response.headers.get(\"x-rivet-ray-id\");\n\n\t\t// Determine encoding from Content-Type header, defaulting to provided encoding\n\t\tconst encoding: Encoding = contentType?.includes(\"application/json\")\n\t\t\t? \"json\"\n\t\t\t: opts.encoding;\n\n\t\t// Attempt to parse structured error data\n\t\ttry {\n\t\t\tconst responseData = deserializeWithEncoding(\n\t\t\t\tencoding,\n\t\t\t\tnew Uint8Array(bufferResponse),\n\t\t\t\tHTTP_RESPONSE_ERROR_VERSIONED,\n\t\t\t\tHttpResponseErrorSchema,\n\t\t\t\t// JSON: metadata is already unknown\n\t\t\t\t(json): HttpResponseErrorJson => json as HttpResponseErrorJson,\n\t\t\t\t// BARE: decode ArrayBuffer metadata to unknown\n\t\t\t\t(bare): any => ({\n\t\t\t\t\tgroup: bare.group,\n\t\t\t\t\tcode: bare.code,\n\t\t\t\t\tmessage: bare.message,\n\t\t\t\t\tmetadata: bare.metadata\n\t\t\t\t\t\t? cbor.decode(new Uint8Array(bare.metadata))\n\t\t\t\t\t\t: undefined,\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\tthrow new ActorError(\n\t\t\t\tresponseData.group,\n\t\t\t\tresponseData.code,\n\t\t\t\tresponseData.message,\n\t\t\t\tresponseData.metadata,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\t// If it's already an ActorError, re-throw it\n\t\t\tif (error instanceof ActorError) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\t// Otherwise, fall back to generic error with text response\n\t\t\tconst textResponse = new TextDecoder(\"utf-8\", {\n\t\t\t\tfatal: false,\n\t\t\t}).decode(bufferResponse);\n\n\t\t\tif (rayId) {\n\t\t\t\tthrow new HttpRequestError(\n\t\t\t\t\t`${response.statusText} (${response.status}) (Ray ID: ${rayId}):\\n${textResponse}`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthrow new HttpRequestError(\n\t\t\t\t\t`${response.statusText} (${response.status}):\\n${textResponse}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Some requests don't need the success response to be parsed, so this can speed things up\n\tif (opts.skipParseResponse) {\n\t\treturn undefined as Response;\n\t}\n\n\t// Parse the response based on encoding\n\ttry {\n\t\tconst buffer = new Uint8Array(await response.arrayBuffer());\n\t\treturn deserializeWithEncoding<ResponseBare, ResponseJson, Response>(\n\t\t\topts.encoding,\n\t\t\tbuffer,\n\t\t\topts.responseVersionedDataHandler,\n\t\t\topts.responseZodSchema,\n\t\t\topts.responseFromJson,\n\t\t\topts.responseFromBare,\n\t\t);\n\t} catch (error) {\n\t\tthrow new HttpRequestError(`Failed to parse response: ${error}`, {\n\t\t\tcause: error,\n\t\t});\n\t}\n}\n","export class ActorClientError extends Error {}\n\nexport class InternalError extends ActorClientError {}\n\nexport class ManagerError extends ActorClientError {\n\tconstructor(error: string, opts?: ErrorOptions) {\n\t\tsuper(`Manager error: ${error}`, opts);\n\t}\n}\n\nexport class MalformedResponseMessage extends ActorClientError {\n\tconstructor(cause?: unknown) {\n\t\tsuper(`Malformed response message: ${cause}`, { cause });\n\t}\n}\n\nexport class ActorError extends ActorClientError {\n\t__type = \"ActorError\";\n\n\tconstructor(\n\t\tpublic readonly group: string,\n\t\tpublic readonly code: string,\n\t\tmessage: string,\n\t\tpublic readonly metadata?: unknown,\n\t) {\n\t\tsuper(message);\n\t}\n}\n\nexport class HttpRequestError extends ActorClientError {\n\tconstructor(message: string, opts?: { cause?: unknown }) {\n\t\tsuper(`HTTP request error: ${message}`, { cause: opts?.cause });\n\t}\n}\n\nexport class ActorConnDisposed extends ActorClientError {\n\tconstructor() {\n\t\tsuper(\"Attempting to interact with a disposed actor connection.\");\n\t}\n}\n\n/**\n * Checks if an error code indicates a scheduling error that may have more details.\n */\nexport function isSchedulingError(group: string, code: string): boolean {\n\treturn (\n\t\tgroup === \"guard\" &&\n\t\t(code === \"actor_ready_timeout\" || code === \"actor_runner_failed\")\n\t);\n}\n\n/**\n * Error thrown when actor scheduling fails.\n * Provides detailed information about why the actor failed to start.\n */\nexport class ActorSchedulingError extends ActorError {\n\tpublic readonly actorId: string;\n\tpublic readonly details: unknown;\n\n\tconstructor(\n\t\tgroup: string,\n\t\tcode: string,\n\t\tactorId: string,\n\t\tdetails: unknown,\n\t) {\n\t\tsuper(\n\t\t\tgroup,\n\t\t\tcode,\n\t\t\t`Actor failed to start (${actorId}): ${JSON.stringify(details)}`,\n\t\t\t{ actorId, details },\n\t\t);\n\t\tthis.name = \"ActorSchedulingError\";\n\t\tthis.actorId = actorId;\n\t\tthis.details = details;\n\t}\n}\n","import { getLogger } from \"@/common//log\";\n\nexport function logger() {\n\treturn getLogger(\"remote-manager-driver\");\n}\n","import type { ClientConfig } from \"@/client/config\";\nimport {\n\tHEADER_CONN_PARAMS,\n\tHEADER_ENCODING,\n\tWS_PROTOCOL_CONN_PARAMS,\n\tWS_PROTOCOL_ENCODING,\n\tWS_PROTOCOL_STANDARD as WS_PROTOCOL_RIVETKIT,\n\tWS_PROTOCOL_TOKEN,\n} from \"@/common/actor-router-consts\";\nimport { importWebSocket } from \"@/common/websocket\";\nimport type { Encoding, UniversalWebSocket } from \"@/mod\";\nimport { combineUrlPath } from \"@/utils\";\nimport { getEndpoint } from \"./api-utils\";\nimport { logger } from \"./log\";\n\nexport function buildActorGatewayUrl(\n\tendpoint: string,\n\tactorId: string,\n\ttoken: string | undefined,\n\tpath = \"\",\n): string {\n\tconst tokenSegment =\n\t\ttoken !== undefined ? `@${encodeURIComponent(token)}` : \"\";\n\tconst gatewayPath = `/gateway/${encodeURIComponent(actorId)}${tokenSegment}${path}`;\n\treturn combineUrlPath(endpoint, gatewayPath);\n}\n\nexport async function openWebSocketToActor(\n\trunConfig: ClientConfig,\n\tpath: string,\n\tactorId: string,\n\tencoding: Encoding,\n\tparams: unknown,\n): Promise<UniversalWebSocket> {\n\tconst WebSocket = await importWebSocket();\n\n\t// WebSocket connections go through guard\n\tconst endpoint = getEndpoint(runConfig);\n\tconst guardUrl = buildActorGatewayUrl(\n\t\tendpoint,\n\t\tactorId,\n\t\trunConfig.token,\n\t\tpath,\n\t);\n\n\tlogger().debug({\n\t\tmsg: \"opening websocket to actor via guard\",\n\t\tactorId,\n\t\tpath,\n\t\tguardUrl,\n\t});\n\n\t// Create WebSocket connection\n\tconst ws = new WebSocket(\n\t\tguardUrl,\n\t\tbuildWebSocketProtocols(runConfig, encoding, params),\n\t);\n\n\t// Set binary type to arraybuffer for proper encoding support\n\tws.binaryType = \"arraybuffer\";\n\n\tlogger().debug({ msg: \"websocket connection opened\", actorId });\n\n\treturn ws as UniversalWebSocket;\n}\n\nexport function buildWebSocketProtocols(\n\trunConfig: ClientConfig,\n\tencoding: Encoding,\n\tparams?: unknown,\n): string[] {\n\tconst protocols: string[] = [];\n\tprotocols.push(WS_PROTOCOL_RIVETKIT);\n\tprotocols.push(`${WS_PROTOCOL_ENCODING}${encoding}`);\n\tif (params) {\n\t\tprotocols.push(\n\t\t\t`${WS_PROTOCOL_CONN_PARAMS}${encodeURIComponent(JSON.stringify(params))}`,\n\t\t);\n\t}\n\treturn protocols;\n}\n","import type { ClientConfig } from \"@/client/config\";\nimport { HEADER_RIVET_TOKEN } from \"@/common/actor-router-consts\";\nimport { buildActorGatewayUrl } from \"./actor-websocket-client\";\nimport { getEndpoint } from \"./api-utils\";\n\nexport async function sendHttpRequestToActor(\n\trunConfig: ClientConfig,\n\tactorId: string,\n\tactorRequest: Request,\n): Promise<Response> {\n\t// Route through guard port\n\tconst url = new URL(actorRequest.url);\n\tconst endpoint = getEndpoint(runConfig);\n\tconst guardUrl = buildActorGatewayUrl(\n\t\tendpoint,\n\t\tactorId,\n\t\trunConfig.token,\n\t\t`${url.pathname}${url.search}`,\n\t);\n\n\t// Handle body properly based on method and presence\n\tlet bodyToSend: ArrayBuffer | null = null;\n\tconst guardHeaders = buildGuardHeadersForHttp(\n\t\trunConfig,\n\t\tactorRequest,\n\t\tactorId,\n\t);\n\n\tif (actorRequest.method !== \"GET\" && actorRequest.method !== \"HEAD\") {\n\t\tif (actorRequest.bodyUsed) {\n\t\t\tthrow new Error(\"Request body has already been consumed\");\n\t\t}\n\n\t\t// TODO: This buffers the entire request in memory every time. We\n\t\t// need to properly implement streaming bodies.\n\t\tconst reqBody = await actorRequest.arrayBuffer();\n\n\t\tif (reqBody.byteLength !== 0) {\n\t\t\tbodyToSend = reqBody;\n\n\t\t\t// If this is a streaming request, we need to convert the headers\n\t\t\t// for the basic array buffer\n\t\t\tguardHeaders.delete(\"transfer-encoding\");\n\t\t\tguardHeaders.set(\"content-length\", String(bodyToSend.byteLength));\n\t\t}\n\t}\n\n\tconst guardRequest = new Request(guardUrl, {\n\t\tmethod: actorRequest.method,\n\t\theaders: guardHeaders,\n\t\tbody: bodyToSend,\n\t\tsignal: actorRequest.signal,\n\t});\n\n\treturn mutableResponse(await fetch(guardRequest));\n}\n\nfunction mutableResponse(fetchRes: Response): Response {\n\t// We cannot return the raw response from `fetch` since the response type is not mutable.\n\t//\n\t// In order for middleware to be able to mutate the response, we need to build a new Response object that is mutable.\n\treturn new Response(fetchRes.body, fetchRes);\n}\n\nfunction buildGuardHeadersForHttp(\n\trunConfig: ClientConfig,\n\tactorRequest: Request,\n\tactorId: string,\n): Headers {\n\tconst headers = new Headers();\n\t// Copy all headers from the original request\n\tactorRequest.headers.forEach((value, key) => {\n\t\theaders.set(key, value);\n\t});\n\t// Add extra headers from config\n\tfor (const [key, value] of Object.entries(runConfig.headers)) {\n\t\theaders.set(key, value as string);\n\t}\n\t// Add guard-specific headers\n\tif (runConfig.token) {\n\t\theaders.set(HEADER_RIVET_TOKEN, runConfig.token);\n\t}\n\treturn headers;\n}\n","import { serializeActorKey } from \"@/actor/keys\";\nimport type { ClientConfig } from \"@/client/client\";\nimport type { MetadataResponse } from \"@/common/router\";\nimport type {\n\tActorsCreateRequest,\n\tActorsCreateResponse,\n\tActorsDeleteResponse,\n\tActorsGetOrCreateRequest,\n\tActorsGetOrCreateResponse,\n\tActorsListResponse,\n} from \"@/manager-api/actors\";\nimport type { RivetId } from \"@/manager-api/common\";\nimport { apiCall } from \"./api-utils\";\n\n// MARK: Get actor\nexport async function getActor(\n\tconfig: ClientConfig,\n\t_: string,\n\tactorId: RivetId,\n): Promise<ActorsListResponse> {\n\treturn apiCall<never, ActorsListResponse>(\n\t\tconfig,\n\t\t\"GET\",\n\t\t`/actors?actor_ids=${encodeURIComponent(actorId)}`,\n\t);\n}\n\n// MARK: Get actor by key\nexport async function getActorByKey(\n\tconfig: ClientConfig,\n\tname: string,\n\tkey: string[],\n): Promise<ActorsListResponse> {\n\tconst serializedKey = serializeActorKey(key);\n\treturn apiCall<never, ActorsListResponse>(\n\t\tconfig,\n\t\t\"GET\",\n\t\t`/actors?name=${encodeURIComponent(name)}&key=${encodeURIComponent(serializedKey)}`,\n\t);\n}\n\n// MARK: List actors by name\nexport async function listActorsByName(\n\tconfig: ClientConfig,\n\tname: string,\n): Promise<ActorsListResponse> {\n\treturn apiCall<never, ActorsListResponse>(\n\t\tconfig,\n\t\t\"GET\",\n\t\t`/actors?name=${encodeURIComponent(name)}`,\n\t);\n}\n\n// MARK: Get or create actor by id\nexport async function getOrCreateActor(\n\tconfig: ClientConfig,\n\trequest: ActorsGetOrCreateRequest,\n): Promise<ActorsGetOrCreateResponse> {\n\treturn apiCall<ActorsGetOrCreateRequest, ActorsGetOrCreateResponse>(\n\t\tconfig,\n\t\t\"PUT\",\n\t\t`/actors`,\n\t\trequest,\n\t);\n}\n\n// MARK: Create actor\nexport async function createActor(\n\tconfig: ClientConfig,\n\trequest: ActorsCreateRequest,\n): Promise<ActorsCreateResponse> {\n\treturn apiCall<ActorsCreateRequest, ActorsCreateResponse>(\n\t\tconfig,\n\t\t\"POST\",\n\t\t`/actors`,\n\t\trequest,\n\t);\n}\n\n// MARK: Destroy actor\nexport async function destroyActor(\n\tconfig: ClientConfig,\n\tactorId: RivetId,\n): Promise<ActorsDeleteResponse> {\n\treturn apiCall<never, ActorsDeleteResponse>(\n\t\tconfig,\n\t\t\"DELETE\",\n\t\t`/actors/${encodeURIComponent(actorId)}`,\n\t);\n}\n\n// MARK: Get metadata\nexport async function getMetadata(\n\tconfig: ClientConfig,\n): Promise<MetadataResponse> {\n\treturn apiCall<never, MetadataResponse>(config, \"GET\", `/metadata`);\n}\n\n// MARK: Get datacenters\nexport interface DatacentersResponse {\n\tdatacenters: { name: string }[];\n}\n\nexport async function getDatacenters(\n\tconfig: ClientConfig,\n): Promise<DatacentersResponse> {\n\treturn apiCall<never, DatacentersResponse>(config, \"GET\", `/datacenters`);\n}\n\n// MARK: Update runner config\nexport interface RegistryConfigRequest {\n\tdatacenters: Record<\n\t\tstring,\n\t\t{\n\t\t\tserverless: {\n\t\t\t\turl: string;\n\t\t\t\theaders: Record<string, string>;\n\t\t\t\tmax_runners: number;\n\t\t\t\tmin_runners: number;\n\t\t\t\trequest_lifespan: number;\n\t\t\t\trunners_margin: number;\n\t\t\t\tslots_per_runner: number;\n\t\t\t\tmetadata_poll_interval?: number;\n\t\t\t};\n\t\t\tmetadata?: Record<string, unknown>;\n\t\t}\n\t>;\n}\n\nexport async function updateRunnerConfig(\n\tconfig: ClientConfig,\n\trunnerName: string,\n\trequest: RegistryConfigRequest,\n): Promise<void> {\n\treturn apiCall<RegistryConfigRequest, void>(\n\t\tconfig,\n\t\t\"PUT\",\n\t\t`/runner-configs/${runnerName}`,\n\t\trequest,\n\t);\n}\n\n// MARK: KV Get\ninterface KvGetResponse {\n\tupdate_ts: string;\n\tvalue: string | null;\n}\n\nexport async function kvGet(\n\tconfig: ClientConfig,\n\tactorId: RivetId,\n\tkey: string,\n): Promise<KvGetResponse> {\n\treturn apiCall<{}, KvGetResponse>(\n\t\tconfig,\n\t\t\"GET\",\n\t\t`/actors/${encodeURIComponent(actorId)}/kv/keys/${encodeURIComponent(key)}`,\n\t);\n}\n","import pRetry from \"p-retry\";\nimport type { ClientConfig } from \"@/client/client\";\nimport type { MetadataResponse } from \"@/common/router\";\nimport { stringifyError } from \"@/common/utils\";\nimport { getMetadata } from \"./api-endpoints\";\nimport { getEndpoint } from \"./api-utils\";\nimport { logger } from \"./log\";\n\n// Global cache to store metadata check promises for each endpoint\nconst metadataLookupCache = new Map<string, Promise<MetadataResponse>>();\n\nexport async function lookupMetadataCached(\n\tconfig: ClientConfig,\n): Promise<MetadataResponse> {\n\tconst endpoint = getEndpoint(config);\n\n\t// Check if metadata lookup is already in progress or completed for this endpoint\n\tconst existingPromise = metadataLookupCache.get(endpoint);\n\tif (existingPromise) {\n\t\treturn existingPromise;\n\t}\n\n\t// Create and store the promise immediately to prevent racing requests\n\tconst metadataLookupPromise = pRetry(\n\t\tasync () => {\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"fetching metadata\",\n\t\t\t\tendpoint,\n\t\t\t});\n\n\t\t\tconst metadataData = await getMetadata(config);\n\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"received metadata\",\n\t\t\t\tendpoint,\n\t\t\t\tclientEndpoint: metadataData.clientEndpoint,\n\t\t\t});\n\n\t\t\treturn metadataData;\n\t\t},\n\t\t{\n\t\t\tforever: true,\n\t\t\tminTimeout: 500,\n\t\t\tmaxTimeout: 15_000,\n\t\t\tonFailedAttempt: (error) => {\n\t\t\t\t// Skip logging warning on first attempt since this attempt\n\t\t\t\t// fails if called immediately on startup. This is because the\n\t\t\t\t// runtime startup is an async operation that will not be\n\t\t\t\t// available on the first tick.\n\t\t\t\tif (error.attemptNumber > 1) {\n\t\t\t\t\tlogger().warn({\n\t\t\t\t\t\tmsg: \"failed to fetch metadata, retrying\",\n\t\t\t\t\t\tendpoint,\n\t\t\t\t\t\tattempt: error.attemptNumber,\n\t\t\t\t\t\terror: stringifyError(error),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t);\n\n\tmetadataLookupCache.set(endpoint, metadataLookupPromise);\n\treturn metadataLookupPromise;\n}\n","import type { Context as HonoContext } from \"hono\";\nimport type { WSContext } from \"hono/ws\";\nimport type { UpgradeWebSocketArgs } from \"@/actor/router-websocket-endpoints\";\nimport { stringifyError } from \"@/common/utils\";\nimport { importWebSocket } from \"@/common/websocket\";\nimport { logger } from \"./log\";\n\n/**\n * Returns Hono `upgradeWebSocket` args that will proxy requests from the client to a destination address.\n */\nexport async function createWebSocketProxy(\n\tc: HonoContext,\n\ttargetUrl: string,\n\tprotocols: string[],\n): Promise<UpgradeWebSocketArgs> {\n\tconst WebSocket = await importWebSocket();\n\n\t// WebSocket state\n\tinterface WsState {\n\t\ttargetWs?: WebSocket;\n\t\tconnectPromise?: Promise<void>;\n\t}\n\tconst state: WsState = {};\n\n\treturn {\n\t\tonOpen: async (event: any, clientWs: WSContext) => {\n\t\t\tlogger().debug({ msg: \"client websocket connected\", targetUrl });\n\n\t\t\tif (clientWs.readyState !== 1) {\n\t\t\t\tlogger().warn({\n\t\t\t\t\tmsg: \"client websocket not open on connection\",\n\t\t\t\t\ttargetUrl,\n\t\t\t\t\treadyState: clientWs.readyState,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Create WebSocket\n\t\t\tconst targetWs = new WebSocket(targetUrl, protocols);\n\t\t\tstate.targetWs = targetWs;\n\n\t\t\t// Setup connection promise\n\t\t\tstate.connectPromise = new Promise<void>((resolve, reject) => {\n\t\t\t\ttargetWs.addEventListener(\"open\", () => {\n\t\t\t\t\tlogger().debug({\n\t\t\t\t\t\tmsg: \"target websocket connected\",\n\t\t\t\t\t\ttargetUrl,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (clientWs.readyState !== 1) {\n\t\t\t\t\t\tlogger().warn({\n\t\t\t\t\t\t\tmsg: \"client websocket closed before target connected\",\n\t\t\t\t\t\t\ttargetUrl,\n\t\t\t\t\t\t\tclientReadyState: clientWs.readyState,\n\t\t\t\t\t\t});\n\t\t\t\t\t\ttargetWs.close(1001, \"Client disconnected\");\n\t\t\t\t\t\treject(new Error(\"Client disconnected\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tresolve();\n\t\t\t\t});\n\n\t\t\t\ttargetWs.addEventListener(\"error\", (error) => {\n\t\t\t\t\tlogger().warn({\n\t\t\t\t\t\tmsg: \"target websocket error during connection\",\n\t\t\t\t\t\ttargetUrl,\n\t\t\t\t\t});\n\t\t\t\t\treject(error);\n\t\t\t\t});\n\t\t\t});\n\n\t\t\t// Setup bidirectional forwarding\n\t\t\tstate.targetWs.addEventListener(\"message\", (event) => {\n\t\t\t\tif (\n\t\t\t\t\ttypeof event.data === \"string\" ||\n\t\t\t\t\tevent.data instanceof ArrayBuffer\n\t\t\t\t) {\n\t\t\t\t\tclientWs.send(event.data);\n\t\t\t\t} else if (event.data instanceof Blob) {\n\t\t\t\t\tevent.data.arrayBuffer().then((buffer) => {\n\t\t\t\t\t\tclientWs.send(buffer);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tstate.targetWs.addEventListener(\"close\", (event) => {\n\t\t\t\tlogger().debug({\n\t\t\t\t\tmsg: \"target websocket closed\",\n\t\t\t\t\ttargetUrl,\n\t\t\t\t\tcode: event.code,\n\t\t\t\t\treason: event.reason,\n\t\t\t\t});\n\t\t\t\tcloseWebSocketIfOpen(clientWs, event.code, event.reason);\n\t\t\t});\n\n\t\t\tstate.targetWs.addEventListener(\"error\", (error) => {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"target websocket error\",\n\t\t\t\t\ttargetUrl,\n\t\t\t\t\terror: stringifyError(error),\n\t\t\t\t});\n\t\t\t\tcloseWebSocketIfOpen(clientWs, 1011, \"Target WebSocket error\");\n\t\t\t});\n\t\t},\n\n\t\tonMessage: async (event: any, clientWs: WSContext) => {\n\t\t\tif (!state.targetWs || !state.connectPromise) {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"websocket state not initialized\",\n\t\t\t\t\ttargetUrl,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tawait state.connectPromise;\n\t\t\t\tif (state.targetWs.readyState === WebSocket.OPEN) {\n\t\t\t\t\tstate.targetWs.send(event.data);\n\t\t\t\t} else {\n\t\t\t\t\tlogger().warn({\n\t\t\t\t\t\tmsg: \"target websocket not open\",\n\t\t\t\t\t\ttargetUrl,\n\t\t\t\t\t\treadyState: state.targetWs.readyState,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"failed to connect to target websocket\",\n\t\t\t\t\ttargetUrl,\n\t\t\t\t\terror,\n\t\t\t\t});\n\t\t\t\tcloseWebSocketIfOpen(\n\t\t\t\t\tclientWs,\n\t\t\t\t\t1011,\n\t\t\t\t\t\"Failed to connect to target\",\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\n\t\tonClose: (event: any, clientWs: WSContext) => {\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"client websocket closed\",\n\t\t\t\ttargetUrl,\n\t\t\t\tcode: event.code,\n\t\t\t\treason: event.reason,\n\t\t\t\twasClean: event.wasClean,\n\t\t\t});\n\n\t\t\tif (state.targetWs) {\n\t\t\t\tif (\n\t\t\t\t\tstate.targetWs.readyState === WebSocket.OPEN ||\n\t\t\t\t\tstate.targetWs.readyState === WebSocket.CONNECTING\n\t\t\t\t) {\n\t\t\t\t\tstate.targetWs.close(\n\t\t\t\t\t\t1000,\n\t\t\t\t\t\tevent.reason || \"Client disconnected\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tonError: (event: any, clientWs: WSContext) => {\n\t\t\tlogger().error({ msg: \"client websocket error\", targetUrl, event });\n\n\t\t\tif (state.targetWs) {\n\t\t\t\tif (state.targetWs.readyState === WebSocket.OPEN) {\n\t\t\t\t\tstate.targetWs.close(1011, \"Client WebSocket error\");\n\t\t\t\t} else if (state.targetWs.readyState === WebSocket.CONNECTING) {\n\t\t\t\t\tstate.targetWs.close();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n}\n\nfunction closeWebSocketIfOpen(\n\tws: WebSocket | WSContext,\n\tcode: number,\n\treason: string,\n): void {\n\tif (ws.readyState === 1) {\n\t\tws.close(code, reason);\n\t} else if (\n\t\t\"close\" in ws &&\n\t\t(ws as WebSocket).readyState === WebSocket.OPEN\n\t) {\n\t\tws.close(code, reason);\n\t}\n}\n","import * as cbor from \"cbor-x\";\nimport invariant from \"invariant\";\nimport pRetry from \"p-retry\";\nimport type { CloseEvent } from \"ws\";\nimport type { AnyActorDefinition } from \"@/actor/definition\";\nimport { inputDataToBuffer } from \"@/actor/protocol/old\";\nimport { type Encoding, jsonStringifyCompat } from \"@/actor/protocol/serde\";\nimport { PATH_CONNECT } from \"@/common/actor-router-consts\";\nimport { assertUnreachable, stringifyError } from \"@/common/utils\";\nimport type { UniversalWebSocket } from \"@/common/websocket-interface\";\nimport type { ManagerDriver } from \"@/driver-helpers/mod\";\nimport type { ActorQuery } from \"@/manager/protocol/query\";\nimport type * as protocol from \"@/schemas/client-protocol/mod\";\nimport {\n\tCURRENT_VERSION as CLIENT_PROTOCOL_CURRENT_VERSION,\n\tTO_CLIENT_VERSIONED,\n\tTO_SERVER_VERSIONED,\n} from \"@/schemas/client-protocol/versioned\";\nimport {\n\ttype ToClient as ToClientJson,\n\tToClientSchema,\n\ttype ToServer as ToServerJson,\n\tToServerSchema,\n} from \"@/schemas/client-protocol-zod/mod\";\nimport { deserializeWithEncoding, serializeWithEncoding } from \"@/serde\";\nimport { bufferToArrayBuffer, promiseWithResolvers } from \"@/utils\";\nimport { getLogMessage } from \"@/utils/env-vars\";\nimport type { ActorDefinitionActions } from \"./actor-common\";\nimport { checkForSchedulingError, queryActor } from \"./actor-query\";\nimport { ACTOR_CONNS_SYMBOL, type ClientRaw } from \"./client\";\nimport * as errors from \"./errors\";\nimport { logger } from \"./log\";\nimport {\n\tcreateQueueSender,\n\ttype QueueSendNoWaitOptions,\n\ttype QueueSendOptions,\n\ttype QueueSendResult,\n\ttype QueueSendWaitOptions,\n} from \"./queue\";\nimport {\n\ttype WebSocketMessage as ConnMessage,\n\tmessageLength,\n\tparseWebSocketCloseReason,\n\tsendHttpRequest,\n} from \"./utils\";\n\n/**\n * Connection status for an actor connection.\n *\n * - `\"idle\"`: Not connected, no auto-reconnect (initial state, after dispose, or disabled)\n * - `\"connecting\"`: Attempting to establish connection\n * - `\"connected\"`: Connection is active\n * - `\"disconnected\"`: Connection was lost, will auto-reconnect\n */\nexport type ActorConnStatus =\n\t| \"idle\"\n\t| \"connecting\"\n\t| \"connected\"\n\t| \"disconnected\";\n\ninterface ActionInFlight {\n\tname: string;\n\tresolve: (response: { id: bigint; output: unknown }) => void;\n\treject: (error: Error) => void;\n}\n\ninterface EventSubscriptions<Args extends Array<unknown>> {\n\tcallback: (...args: Args) => void;\n\tonce: boolean;\n}\n\n/**\n * A function that unsubscribes from an event.\n *\n * @typedef {Function} EventUnsubscribe\n */\nexport type EventUnsubscribe = () => void;\n\n/**\n * A function that handles connection errors.\n *\n * @typedef {Function} ActorErrorCallback\n */\nexport type ActorErrorCallback = (error: errors.ActorError) => void;\n\n/**\n * A callback for connection state changes.\n *\n * @typedef {Function} ConnectionStateCallback\n */\nexport type ConnectionStateCallback = () => void;\n\n/**\n * A callback for connection status changes.\n *\n * @typedef {Function} StatusChangeCallback\n */\nexport type StatusChangeCallback = (status: ActorConnStatus) => void;\n\nexport interface SendHttpMessageOpts {\n\tephemeral: boolean;\n\tsignal?: AbortSignal;\n}\n\nexport const CONNECT_SYMBOL = Symbol(\"connect\");\n\n/**\n * Provides underlying functions for {@link ActorConn}. See {@link ActorConn} for using type-safe remote procedure calls.\n *\n * @see {@link ActorConn}\n */\nexport class ActorConnRaw {\n\t#disposed = false;\n\n\t/* Will be aborted on dispose. */\n\t#abortController = new AbortController();\n\n\t#connStatus: ActorConnStatus = \"idle\";\n\n\t#actorId?: string;\n\t#connId?: string;\n\n\t#messageQueue: Array<{\n\t\tbody:\n\t\t\t| {\n\t\t\t\t\ttag: \"ActionRequest\";\n\t\t\t\t\tval: { id: bigint; name: string; args: unknown };\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\ttag: \"SubscriptionRequest\";\n\t\t\t\t\tval: { eventName: string; subscribe: boolean };\n\t\t\t };\n\t}> = [];\n\t#actionsInFlight = new Map<number, ActionInFlight>();\n\n\t// biome-ignore lint/suspicious/noExplicitAny: Unknown subscription type\n\t#eventSubscriptions = new Map<string, Set<EventSubscriptions<any[]>>>();\n\n\t#errorHandlers = new Set<ActorErrorCallback>();\n\t#openHandlers = new Set<ConnectionStateCallback>();\n\t#openScheduled = false;\n\t#closeHandlers = new Set<ConnectionStateCallback>();\n\t#statusChangeHandlers = new Set<StatusChangeCallback>();\n\n\t#actionIdCounter = 0;\n\t#queueSender: ReturnType<typeof createQueueSender>;\n\n\t/**\n\t * Interval that keeps the NodeJS process alive if this is the only thing running.\n\t *\n\t * See ttps://github.com/nodejs/node/issues/22088\n\t */\n\t#keepNodeAliveInterval: NodeJS.Timeout;\n\n\t/** Promise used to indicate the socket has connected successfully. This will be rejected if the connection fails. */\n\t#onOpenPromise?: ReturnType<typeof promiseWithResolvers<undefined>>;\n\n\t#websocket?: UniversalWebSocket;\n\n\t#client: ClientRaw;\n\t#driver: ManagerDriver;\n\t#params: unknown;\n\t#encoding: Encoding;\n\t#actorQuery: ActorQuery;\n\n\t// TODO: ws message queue\n\n\t/**\n\t * Do not call this directly.\n\t *\n\t * Creates an instance of ActorConnRaw.\n\t *\n\t * @protected\n\t */\n\tpublic constructor(\n\t\tclient: ClientRaw,\n\t\tdriver: ManagerDriver,\n\t\tparams: unknown,\n\t\tencoding: Encoding,\n\t\tactorQuery: ActorQuery,\n\t) {\n\t\tthis.#client = client;\n\t\tthis.#driver = driver;\n\t\tthis.#params = params;\n\t\tthis.#encoding = encoding;\n\t\tthis.#actorQuery = actorQuery;\n\t\tthis.#queueSender = createQueueSender({\n\t\t\tencoding: this.#encoding,\n\t\t\tparams: this.#params,\n\t\t\tcustomFetch: async (request: Request) => {\n\t\t\t\tif (!this.#actorId) {\n\t\t\t\t\tconst { actorId } = await queryActor(\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tthis.#actorQuery,\n\t\t\t\t\t\tthis.#driver,\n\t\t\t\t\t);\n\t\t\t\t\tthis.#actorId = actorId;\n\t\t\t\t}\n\t\t\t\treturn this.#driver.sendRequest(this.#actorId, request);\n\t\t\t},\n\t\t});\n\n\t\tthis.#keepNodeAliveInterval = setInterval(() => 60_000);\n\t}\n\n\tsend(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions: QueueSendWaitOptions,\n\t): Promise<QueueSendResult>;\n\tsend(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions?: QueueSendNoWaitOptions,\n\t): Promise<void>;\n\tsend(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions?: QueueSendOptions,\n\t): Promise<QueueSendResult | void> {\n\t\treturn this.#queueSender.send(name, body, options as any);\n\t}\n\n\t/**\n\t * Call a raw action connection. See {@link ActorConn} for type-safe action calls.\n\t *\n\t * @see {@link ActorConn}\n\t * @template Args - The type of arguments to pass to the action function.\n\t * @template Response - The type of the response returned by the action function.\n\t * @param {string} name - The name of the action function to call.\n\t * @param {...Args} args - The arguments to pass to the action function.\n\t * @returns {Promise<Response>} - A promise that resolves to the response of the action function.\n\t */\n\tasync action<\n\t\tArgs extends Array<unknown> = unknown[],\n\t\tResponse = unknown,\n\t>(opts: {\n\t\tname: string;\n\t\targs: Args;\n\t\tsignal?: AbortSignal;\n\t}): Promise<Response> {\n\t\tlogger().debug({ msg: \"action\", name: opts.name, args: opts.args });\n\n\t\t// If we have an active connection, use the websockactionId\n\t\tconst actionId = this.#actionIdCounter;\n\t\tthis.#actionIdCounter += 1;\n\n\t\tconst { promise, resolve, reject } = promiseWithResolvers<{\n\t\t\tid: bigint;\n\t\t\toutput: unknown;\n\t\t}>((reason) => logger().warn({ msg: \"unhandled action promise rejection\", reason }));\n\t\tthis.#actionsInFlight.set(actionId, {\n\t\t\tname: opts.name,\n\t\t\tresolve,\n\t\t\treject,\n\t\t});\n\t\tlogger().debug({\n\t\t\tmsg: \"added action to in-flight map\",\n\t\t\tactionId,\n\t\t\tactionName: opts.name,\n\t\t\tinFlightCount: this.#actionsInFlight.size,\n\t\t});\n\n\t\tthis.#sendMessage({\n\t\t\tbody: {\n\t\t\t\ttag: \"ActionRequest\",\n\t\t\t\tval: {\n\t\t\t\t\tid: BigInt(actionId),\n\t\t\t\t\tname: opts.name,\n\t\t\t\t\targs: opts.args,\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\n\t\t// TODO: Throw error if disconnect is called\n\n\t\tconst { id: responseId, output } = await promise;\n\t\tif (responseId !== BigInt(actionId))\n\t\t\tthrow new Error(\n\t\t\t\t`Request ID ${actionId} does not match response ID ${responseId}`,\n\t\t\t);\n\n\t\treturn output as Response;\n\t}\n\n\t/**\n\t * Do not call this directly.\n\t * Establishes a connection to the server using the specified endpoint & encoding & driver.\n\t *\n\t * @protected\n\t */\n\tpublic [CONNECT_SYMBOL]() {\n\t\tthis.#connectWithRetry();\n\t}\n\n\t#setConnStatus(status: ActorConnStatus) {\n\t\tconst prevStatus = this.#connStatus;\n\t\tif (prevStatus === status) return;\n\t\tthis.#connStatus = status;\n\n\t\t// Notify status change handlers\n\t\tfor (const handler of [...this.#statusChangeHandlers]) {\n\t\t\ttry {\n\t\t\t\thandler(status);\n\t\t\t} catch (err) {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"error in status change handler\",\n\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Notify open handlers\n\t\tif (status === \"connected\") {\n\t\t\tfor (const handler of [...this.#openHandlers]) {\n\t\t\t\ttry {\n\t\t\t\t\thandler();\n\t\t\t\t} catch (err) {\n\t\t\t\t\tlogger().error({\n\t\t\t\t\t\tmsg: \"error in open handler\",\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}\n\n\t\t// Notify close handlers (only if transitioning from Connected to Disconnected or Idle)\n\t\tif (\n\t\t\t(status === \"disconnected\" || status === \"idle\") &&\n\t\t\tprevStatus === \"connected\"\n\t\t) {\n\t\t\tfor (const handler of [...this.#closeHandlers]) {\n\t\t\t\ttry {\n\t\t\t\t\thandler();\n\t\t\t\t} catch (err) {\n\t\t\t\t\tlogger().error({\n\t\t\t\t\t\tmsg: \"error in close handler\",\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}\n\t}\n\n\t#connectWithRetry() {\n\t\tthis.#setConnStatus(\"connecting\");\n\n\t\t// Attempt to reconnect indefinitely\n\t\t// This is intentionally not awaited - connection happens in background\n\t\tpRetry(this.#connectAndWait.bind(this), {\n\t\t\tforever: true,\n\t\t\tminTimeout: 250,\n\t\t\tmaxTimeout: 30_000,\n\n\t\t\tonFailedAttempt: (error) => {\n\t\t\t\tlogger().warn({\n\t\t\t\t\tmsg: \"failed to reconnect\",\n\t\t\t\t\tattempt: error.attemptNumber,\n\t\t\t\t\terror: stringifyError(error),\n\t\t\t\t});\n\t\t\t},\n\n\t\t\t// Cancel retry if aborted\n\t\t\tsignal: this.#abortController.signal,\n\t\t}).catch((err) => {\n\t\t\tif ((err as Error).name === \"AbortError\") {\n\t\t\t\tlogger().info({ msg: \"connection retry aborted\" });\n\t\t\t} else {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"unexpected error in connection retry\",\n\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\n\tasync #connectAndWait() {\n\t\ttry {\n\t\t\t// Create promise for open\n\t\t\tif (this.#onOpenPromise)\n\t\t\t\tthrow new Error(\"#onOpenPromise already defined\");\n\t\t\tthis.#onOpenPromise = promiseWithResolvers((reason) => logger().warn({ msg: \"unhandled open promise rejection\", reason }));\n\n\t\t\tawait this.#connectWebSocket();\n\n\t\t\t// Wait for result\n\t\t\tawait this.#onOpenPromise.promise;\n\t\t} finally {\n\t\t\tthis.#onOpenPromise = undefined;\n\t\t}\n\t}\n\n\tasync #connectWebSocket() {\n\t\tconst { actorId } = await queryActor(\n\t\t\tundefined,\n\t\t\tthis.#actorQuery,\n\t\t\tthis.#driver,\n\t\t);\n\n\t\t// Store actorId early so we can use it for error lookups\n\t\tthis.#actorId = actorId;\n\n\t\tconst ws = await this.#driver.openWebSocket(\n\t\t\tPATH_CONNECT,\n\t\t\tactorId,\n\t\t\tthis.#encoding,\n\t\t\tthis.#params,\n\t\t);\n\t\tlogger().debug({\n\t\t\tmsg: \"opened websocket\",\n\t\t\tconnId: this.#connId,\n\t\t\treadyState: ws.readyState,\n\t\t\tmessageQueueLength: this.#messageQueue.length,\n\t\t});\n\t\tthis.#websocket = ws;\n\t\tws.addEventListener(\"open\", () => {\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"client websocket open\",\n\t\t\t\tconnId: this.#connId,\n\t\t\t});\n\t\t});\n\t\tws.addEventListener(\"message\", async (ev) => {\n\t\t\ttry {\n\t\t\t\tawait this.#handleOnMessage(ev.data);\n\t\t\t} catch (err) {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"error in websocket message handler\",\n\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t\tws.addEventListener(\"close\", async (ev) => {\n\t\t\ttry {\n\t\t\t\tawait this.#handleOnClose(ev);\n\t\t\t} catch (err) {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"error in websocket close handler\",\n\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t\tws.addEventListener(\"error\", (_ev) => {\n\t\t\ttry {\n\t\t\t\tthis.#handleOnError();\n\t\t\t} catch (err) {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"error in websocket error handler\",\n\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\n\t/** Called by the onopen event from drivers. */\n\t#handleOnOpen() {\n\t\t// Connection was disposed before Init message arrived - close the websocket to avoid leak\n\t\tif (this.#disposed) {\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"handleOnOpen called after dispose, closing websocket\",\n\t\t\t});\n\t\t\tif (this.#websocket) {\n\t\t\t\tthis.#websocket.close(1000, \"Disposed\");\n\t\t\t\tthis.#websocket = undefined;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.#connStatus === \"connected\" || this.#openScheduled) {\n\t\t\treturn;\n\t\t}\n\t\tthis.#openScheduled = true;\n\n\t\tqueueMicrotask(() => {\n\t\t\tthis.#openScheduled = false;\n\t\t\tif (this.#disposed) {\n\t\t\t\tlogger().debug({\n\t\t\t\t\tmsg: \"handleOnOpen scheduled after dispose, closing websocket\",\n\t\t\t\t});\n\t\t\t\tif (this.#websocket) {\n\t\t\t\t\tthis.#websocket.close(1000, \"Disposed\");\n\t\t\t\t\tthis.#websocket = undefined;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"socket open\",\n\t\t\t\tmessageQueueLength: this.#messageQueue.length,\n\t\t\t\tconnId: this.#connId,\n\t\t\t});\n\n\t\t\t// Update connection state (this also notifies handlers)\n\t\t\tthis.#setConnStatus(\"connected\");\n\n\t\t\t// Resolve open promise\n\t\t\tif (this.#onOpenPromise) {\n\t\t\t\tthis.#onOpenPromise.resolve(undefined);\n\t\t\t} else {\n\t\t\t\tlogger().warn({ msg: \"#onOpenPromise is undefined\" });\n\t\t\t}\n\n\t\t\t// Resubscribe to all active events\n\t\t\tfor (const eventName of this.#eventSubscriptions.keys()) {\n\t\t\t\tthis.#sendSubscription(eventName, true);\n\t\t\t}\n\n\t\t\t// Flush queue\n\t\t\t//\n\t\t\t// If the message fails to send, the message will be re-queued\n\t\t\tconst queue = this.#messageQueue;\n\t\t\tthis.#messageQueue = [];\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"flushing message queue\",\n\t\t\t\tqueueLength: queue.length,\n\t\t\t});\n\t\t\tfor (const msg of queue) {\n\t\t\t\tthis.#sendMessage(msg);\n\t\t\t}\n\t\t});\n\t}\n\n\t/** Called by the onmessage event from drivers. */\n\tasync #handleOnMessage(data: any) {\n\t\tlogger().trace({\n\t\t\tmsg: \"received message\",\n\t\t\tdataType: typeof data,\n\t\t\tisBlob: data instanceof Blob,\n\t\t\tisArrayBuffer: data instanceof ArrayBuffer,\n\t\t});\n\n\t\tconst response = await this.#parseMessage(data as ConnMessage);\n\t\tlogger().trace(\n\t\t\tgetLogMessage()\n\t\t\t\t? {\n\t\t\t\t\t\tmsg: \"parsed message\",\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\tjsonStringifyCompat(response).substring(0, 100) +\n\t\t\t\t\t\t\t\"...\",\n\t\t\t\t\t}\n\t\t\t\t: { msg: \"parsed message\" },\n\t\t);\n\n\t\tif (response.body.tag === \"Init\") {\n\t\t\t// Store connection info\n\t\t\tthis.#actorId = response.body.val.actorId;\n\t\t\tthis.#connId = response.body.val.connectionId;\n\t\t\tlogger().trace({\n\t\t\t\tmsg: \"received init message\",\n\t\t\t\tactorId: this.#actorId,\n\t\t\t\tconnId: this.#connId,\n\t\t\t});\n\t\t\tthis.#handleOnOpen();\n\t\t} else if (response.body.tag === \"Error\") {\n\t\t\t// Connection error\n\t\t\tconst { group, code, message, metadata, actionId } =\n\t\t\t\tresponse.body.val;\n\n\t\t\tif (actionId) {\n\t\t\t\tconst inFlight = this.#takeActionInFlight(Number(actionId));\n\n\t\t\t\tlogger().warn({\n\t\t\t\t\tmsg: \"action error\",\n\t\t\t\t\tactionId: actionId,\n\t\t\t\t\tactionName: inFlight?.name,\n\t\t\t\t\tgroup,\n\t\t\t\t\tcode,\n\t\t\t\t\tmessage,\n\t\t\t\t\tmetadata,\n\t\t\t\t});\n\n\t\t\t\tinFlight.reject(\n\t\t\t\t\tnew errors.ActorError(group, code, message, metadata),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tlogger().warn({\n\t\t\t\t\tmsg: \"connection error\",\n\t\t\t\t\tgroup,\n\t\t\t\t\tcode,\n\t\t\t\t\tmessage,\n\t\t\t\t\tmetadata,\n\t\t\t\t});\n\n\t\t\t\t// Check if this is an actor scheduling error and try to get more details\n\t\t\t\tlet errorToThrow = new errors.ActorError(\n\t\t\t\t\tgroup,\n\t\t\t\t\tcode,\n\t\t\t\t\tmessage,\n\t\t\t\t\tmetadata,\n\t\t\t\t);\n\t\t\t\tif (errors.isSchedulingError(group, code) && this.#actorId) {\n\t\t\t\t\tconst schedulingError = await checkForSchedulingError(\n\t\t\t\t\t\tgroup,\n\t\t\t\t\t\tcode,\n\t\t\t\t\t\tthis.#actorId,\n\t\t\t\t\t\tthis.#actorQuery,\n\t\t\t\t\t\tthis.#driver,\n\t\t\t\t\t);\n\t\t\t\t\tif (schedulingError) {\n\t\t\t\t\t\terrorToThrow = schedulingError;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If we have an onOpenPromise, reject it with the error\n\t\t\t\tif (this.#onOpenPromise) {\n\t\t\t\t\tthis.#onOpenPromise.reject(errorToThrow);\n\t\t\t\t}\n\n\t\t\t\t// Reject any in-flight requests\n\t\t\t\tfor (const [id, inFlight] of this.#actionsInFlight.entries()) {\n\t\t\t\t\tinFlight.reject(errorToThrow);\n\t\t\t\t\tthis.#actionsInFlight.delete(id);\n\t\t\t\t}\n\n\t\t\t\tthis.#dispatchActorError(errorToThrow);\n\t\t\t}\n\t\t} else if (response.body.tag === \"ActionResponse\") {\n\t\t\t// Action response OK\n\t\t\tconst { id: actionId } = response.body.val;\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"received action response\",\n\t\t\t\tactionId: Number(actionId),\n\t\t\t\tinFlightCount: this.#actionsInFlight.size,\n\t\t\t\tinFlightIds: Array.from(this.#actionsInFlight.keys()),\n\t\t\t});\n\n\t\t\tconst inFlight = this.#takeActionInFlight(Number(actionId));\n\t\t\tlogger().trace({\n\t\t\t\tmsg: \"resolving action promise\",\n\t\t\t\tactionId,\n\t\t\t\tactionName: inFlight?.name,\n\t\t\t});\n\t\t\tinFlight.resolve(response.body.val);\n\t\t} else if (response.body.tag === \"Event\") {\n\t\t\tlogger().trace({\n\t\t\t\tmsg: \"received event\",\n\t\t\t\tname: response.body.val.name,\n\t\t\t});\n\t\t\tthis.#dispatchEvent(response.body.val);\n\t\t} else {\n\t\t\tassertUnreachable(response.body);\n\t\t}\n\t}\n\n\t/** Called by the onclose event from drivers. */\n\tasync #handleOnClose(event: Event | CloseEvent) {\n\t\t// We can't use `event instanceof CloseEvent` because it's not defined in NodeJS\n\t\tconst closeEvent = event as CloseEvent;\n\t\tconst wasClean = closeEvent.wasClean;\n\t\tconst wasConnected = this.#connStatus === \"connected\";\n\n\t\tlogger().info({\n\t\t\tmsg: \"socket closed\",\n\t\t\tcode: closeEvent.code,\n\t\t\treason: closeEvent.reason,\n\t\t\twasClean,\n\t\t\tdisposed: this.#disposed,\n\t\t\tconnId: this.#connId,\n\t\t});\n\n\t\tthis.#websocket = undefined;\n\n\t\tif (this.#disposed) {\n\t\t\t// Use ActorConnDisposed error and prevent unhandled rejection\n\t\t\tthis.#rejectPendingPromises(new errors.ActorConnDisposed(), true);\n\t\t} else {\n\t\t\tthis.#setConnStatus(\"disconnected\");\n\n\t\t\t// Build error from close event\n\t\t\tlet error: Error;\n\t\t\tconst reason = closeEvent.reason || \"\";\n\t\t\tconst parsed = parseWebSocketCloseReason(reason);\n\n\t\t\tif (parsed) {\n\t\t\t\tconst { group, code } = parsed;\n\n\t\t\t\t// Check if this is a scheduling error\n\t\t\t\tif (errors.isSchedulingError(group, code) && this.#actorId) {\n\t\t\t\t\tconst schedulingError = await checkForSchedulingError(\n\t\t\t\t\t\tgroup,\n\t\t\t\t\t\tcode,\n\t\t\t\t\t\tthis.#actorId,\n\t\t\t\t\t\tthis.#actorQuery,\n\t\t\t\t\t\tthis.#driver,\n\t\t\t\t\t);\n\t\t\t\t\tif (schedulingError) {\n\t\t\t\t\t\terror = schedulingError;\n\t\t\t\t\t} else {\n\t\t\t\t\t\terror = new errors.ActorError(\n\t\t\t\t\t\t\tgroup,\n\t\t\t\t\t\t\tcode,\n\t\t\t\t\t\t\t`Connection closed: ${reason}`,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\terror = new errors.ActorError(\n\t\t\t\t\t\tgroup,\n\t\t\t\t\t\tcode,\n\t\t\t\t\t\t`Connection closed: ${reason}`,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Default error for non-structured close reasons\n\t\t\t\terror = new Error(\n\t\t\t\t\t`${wasClean ? \"Connection closed\" : \"Connection lost\"} (code: ${closeEvent.code}, reason: ${reason})`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.#rejectPendingPromises(error, false);\n\n\t\t\t// Dispatch to error handler if it's an ActorError\n\t\t\tif (error instanceof errors.ActorError) {\n\t\t\t\tthis.#dispatchActorError(error);\n\t\t\t}\n\n\t\t\t// Automatically reconnect if we were connected\n\t\t\tif (wasConnected) {\n\t\t\t\tlogger().debug({\n\t\t\t\t\tmsg: \"triggering reconnect\",\n\t\t\t\t\tconnId: this.#connId,\n\t\t\t\t});\n\t\t\t\tthis.#connectWithRetry();\n\t\t\t}\n\t\t}\n\t}\n\n\t#rejectPendingPromises(error: Error, suppressUnhandled: boolean) {\n\t\tif (this.#onOpenPromise) {\n\t\t\tif (suppressUnhandled) {\n\t\t\t\tthis.#onOpenPromise.promise.catch(() => {});\n\t\t\t}\n\t\t\tthis.#onOpenPromise.reject(error);\n\t\t}\n\n\t\tfor (const actionInfo of this.#actionsInFlight.values()) {\n\t\t\tactionInfo.reject(error);\n\t\t}\n\t\tthis.#actionsInFlight.clear();\n\t}\n\n\t/** Called by the onerror event from drivers. */\n\t#handleOnError() {\n\t\tif (this.#disposed) return;\n\n\t\t// More detailed information will be logged in onclose\n\t\tlogger().warn(\"socket error\");\n\t}\n\n\t#takeActionInFlight(id: number): ActionInFlight {\n\t\tconst inFlight = this.#actionsInFlight.get(id);\n\t\tif (!inFlight) {\n\t\t\tlogger().error({\n\t\t\t\tmsg: \"action not found in in-flight map\",\n\t\t\t\tlookupId: id,\n\t\t\t\tinFlightCount: this.#actionsInFlight.size,\n\t\t\t\tinFlightIds: Array.from(this.#actionsInFlight.keys()),\n\t\t\t\tinFlightActions: Array.from(\n\t\t\t\t\tthis.#actionsInFlight.entries(),\n\t\t\t\t).map(([id, action]) => ({\n\t\t\t\t\tid,\n\t\t\t\t\tname: action.name,\n\t\t\t\t})),\n\t\t\t});\n\t\t\tthrow new errors.InternalError(`No in flight response for ${id}`);\n\t\t}\n\t\tthis.#actionsInFlight.delete(id);\n\t\tlogger().debug({\n\t\t\tmsg: \"removed action from in-flight map\",\n\t\t\tactionId: id,\n\t\t\tactionName: inFlight.name,\n\t\t\tinFlightCount: this.#actionsInFlight.size,\n\t\t});\n\t\treturn inFlight;\n\t}\n\n\t#dispatchEvent(event: { name: string; args: unknown }) {\n\t\tconst { name, args } = event;\n\n\t\tconst listeners = this.#eventSubscriptions.get(name);\n\t\tif (!listeners) return;\n\n\t\t// Create a new array to avoid issues with listeners being removed during iteration\n\t\tfor (const listener of [...listeners]) {\n\t\t\tlistener.callback(...(args as unknown[]));\n\n\t\t\t// Remove if this was a one-time listener\n\t\t\tif (listener.once) {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t}\n\t\t}\n\n\t\t// Clean up empty listener sets\n\t\tif (listeners.size === 0) {\n\t\t\tthis.#eventSubscriptions.delete(name);\n\t\t}\n\t}\n\n\t#dispatchActorError(error: errors.ActorError) {\n\t\t// Call all registered error handlers\n\t\tfor (const handler of [...this.#errorHandlers]) {\n\t\t\ttry {\n\t\t\t\thandler(error);\n\t\t\t} catch (err) {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"error in connection error handler\",\n\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t#addEventSubscription<Args extends Array<unknown>>(\n\t\teventName: string,\n\t\tcallback: (...args: Args) => void,\n\t\tonce: boolean,\n\t): EventUnsubscribe {\n\t\tconst listener: EventSubscriptions<Args> = {\n\t\t\tcallback,\n\t\t\tonce,\n\t\t};\n\n\t\tlet subscriptionSet = this.#eventSubscriptions.get(eventName);\n\t\tif (subscriptionSet === undefined) {\n\t\t\tsubscriptionSet = new Set();\n\t\t\tthis.#eventSubscriptions.set(eventName, subscriptionSet);\n\t\t\tthis.#sendSubscription(eventName, true);\n\t\t}\n\t\tsubscriptionSet.add(listener);\n\n\t\t// Return unsubscribe function\n\t\treturn () => {\n\t\t\tconst listeners = this.#eventSubscriptions.get(eventName);\n\t\t\tif (listeners) {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t\tif (listeners.size === 0) {\n\t\t\t\t\tthis.#eventSubscriptions.delete(eventName);\n\t\t\t\t\tthis.#sendSubscription(eventName, false);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Subscribes to an event that will happen repeatedly.\n\t *\n\t * @template Args - The type of arguments the event callback will receive.\n\t * @param {string} eventName - The name of the event to subscribe to.\n\t * @param {(...args: Args) => void} callback - The callback function to execute when the event is triggered.\n\t * @returns {EventUnsubscribe} - A function to unsubscribe from the event.\n\t * @see {@link https://rivet.dev/docs/events|Events Documentation}\n\t */\n\ton<Args extends Array<unknown> = unknown[]>(\n\t\teventName: string,\n\t\tcallback: (...args: Args) => void,\n\t): EventUnsubscribe {\n\t\treturn this.#addEventSubscription<Args>(eventName, callback, false);\n\t}\n\n\t/**\n\t * Subscribes to an event that will be triggered only once.\n\t *\n\t * @template Args - The type of arguments the event callback will receive.\n\t * @param {string} eventName - The name of the event to subscribe to.\n\t * @param {(...args: Args) => void} callback - The callback function to execute when the event is triggered.\n\t * @returns {EventUnsubscribe} - A function to unsubscribe from the event.\n\t * @see {@link https://rivet.dev/docs/events|Events Documentation}\n\t */\n\tonce<Args extends Array<unknown> = unknown[]>(\n\t\teventName: string,\n\t\tcallback: (...args: Args) => void,\n\t): EventUnsubscribe {\n\t\treturn this.#addEventSubscription<Args>(eventName, callback, true);\n\t}\n\n\t/**\n\t * Subscribes to connection errors.\n\t *\n\t * @param {ActorErrorCallback} callback - The callback function to execute when a connection error occurs.\n\t * @returns {() => void} - A function to unsubscribe from the error handler.\n\t */\n\tonError(callback: ActorErrorCallback): () => void {\n\t\tthis.#errorHandlers.add(callback);\n\n\t\t// Return unsubscribe function\n\t\treturn () => {\n\t\t\tthis.#errorHandlers.delete(callback);\n\t\t};\n\t}\n\n\t/**\n\t * Returns the current connection status.\n\t *\n\t * @returns {ActorConnStatus} - The current connection status.\n\t */\n\tget connStatus(): ActorConnStatus {\n\t\treturn this.#connStatus;\n\t}\n\n\t/**\n\t * Returns whether the connection is currently open.\n\t *\n\t * @deprecated Use `connStatus` instead.\n\t * @returns {boolean} - True if the connection is open, false otherwise.\n\t */\n\tget isConnected(): boolean {\n\t\treturn this.#connStatus === \"connected\";\n\t}\n\n\t/**\n\t * Subscribes to connection open events.\n\t *\n\t * This is called when the WebSocket connection is established and the Init message is received.\n\t *\n\t * @param {ConnectionStateCallback} callback - The callback function to execute when the connection opens.\n\t * @returns {() => void} - A function to unsubscribe from the open handler.\n\t */\n\tonOpen(callback: ConnectionStateCallback): () => void {\n\t\tthis.#openHandlers.add(callback);\n\n\t\t// Return unsubscribe function\n\t\treturn () => {\n\t\t\tthis.#openHandlers.delete(callback);\n\t\t};\n\t}\n\n\t/**\n\t * Subscribes to connection close events.\n\t *\n\t * This is called when the WebSocket connection is closed. The connection will automatically\n\t * attempt to reconnect unless disposed.\n\t *\n\t * @param {ConnectionStateCallback} callback - The callback function to execute when the connection closes.\n\t * @returns {() => void} - A function to unsubscribe from the close handler.\n\t */\n\tonClose(callback: ConnectionStateCallback): () => void {\n\t\tthis.#closeHandlers.add(callback);\n\n\t\t// Return unsubscribe function\n\t\treturn () => {\n\t\t\tthis.#closeHandlers.delete(callback);\n\t\t};\n\t}\n\n\t/**\n\t * Subscribes to connection status changes.\n\t *\n\t * This is called whenever the connection status changes between Disconnected, Connecting, and Connected.\n\t *\n\t * @param {StatusChangeCallback} callback - The callback function to execute when the status changes.\n\t * @returns {() => void} - A function to unsubscribe from the status change handler.\n\t */\n\tonStatusChange(callback: StatusChangeCallback): () => void {\n\t\tthis.#statusChangeHandlers.add(callback);\n\n\t\t// Return unsubscribe function\n\t\treturn () => {\n\t\t\tthis.#statusChangeHandlers.delete(callback);\n\t\t};\n\t}\n\n\t#sendMessage(\n\t\tmessage: {\n\t\t\tbody:\n\t\t\t\t| {\n\t\t\t\t\t\ttag: \"ActionRequest\";\n\t\t\t\t\t\tval: { id: bigint; name: string; args: unknown };\n\t\t\t\t }\n\t\t\t\t| {\n\t\t\t\t\t\ttag: \"SubscriptionRequest\";\n\t\t\t\t\t\tval: { eventName: string; subscribe: boolean };\n\t\t\t\t };\n\t\t},\n\t\topts?: SendHttpMessageOpts,\n\t) {\n\t\tif (this.#disposed) {\n\t\t\tif (opts?.ephemeral) {\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tthrow new errors.ActorConnDisposed();\n\t\t\t}\n\t\t}\n\n\t\tlet queueMessage = false;\n\t\tif (this.#websocket) {\n\t\t\tconst readyState = this.#websocket.readyState;\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"websocket send attempt\",\n\t\t\t\treadyState,\n\t\t\t\treadyStateString:\n\t\t\t\t\treadyState === 0\n\t\t\t\t\t\t? \"CONNECTING\"\n\t\t\t\t\t\t: readyState === 1\n\t\t\t\t\t\t\t? \"OPEN\"\n\t\t\t\t\t\t\t: readyState === 2\n\t\t\t\t\t\t\t\t? \"CLOSING\"\n\t\t\t\t\t\t\t\t: \"CLOSED\",\n\t\t\t\tconnId: this.#connId,\n\t\t\t\tmessageType: (message.body as any).tag,\n\t\t\t\tactionName: (message.body as any).val?.name,\n\t\t\t});\n\t\t\tif (this.#connStatus !== \"connected\") {\n\t\t\t\tlogger().debug({\n\t\t\t\t\tmsg: \"websocket init pending, queueing message\",\n\t\t\t\t\tconnStatus: this.#connStatus,\n\t\t\t\t\tmessageType: (message.body as any).tag,\n\t\t\t\t});\n\t\t\t\tqueueMessage = true;\n\t\t\t} else if (readyState === 1) {\n\t\t\t\ttry {\n\t\t\t\t\tconst messageSerialized = serializeWithEncoding(\n\t\t\t\t\t\tthis.#encoding,\n\t\t\t\t\t\tmessage,\n\t\t\t\t\t\tTO_SERVER_VERSIONED,\n\t\t\t\t\t\tCLIENT_PROTOCOL_CURRENT_VERSION,\n\t\t\t\t\t\tToServerSchema,\n\t\t\t\t\t\t// JSON: args is the raw value\n\t\t\t\t\t\t(msg): ToServerJson => msg as ToServerJson,\n\t\t\t\t\t\t// BARE: args needs to be CBOR-encoded to ArrayBuffer\n\t\t\t\t\t\t(msg): protocol.ToServer => {\n\t\t\t\t\t\t\tif (msg.body.tag === \"ActionRequest\") {\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\t\t\ttag: \"ActionRequest\",\n\t\t\t\t\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\t\t\t\t\tid: msg.body.val.id,\n\t\t\t\t\t\t\t\t\t\t\tname: msg.body.val.name,\n\t\t\t\t\t\t\t\t\t\t\targs: bufferToArrayBuffer(\n\t\t\t\t\t\t\t\t\t\t\t\tcbor.encode(msg.body.val.args),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\treturn msg as protocol.ToServer;\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\tthis.#websocket.send(messageSerialized);\n\t\t\t\t\tlogger().trace({\n\t\t\t\t\t\tmsg: \"sent websocket message\",\n\t\t\t\t\t\tlen: messageLength(messageSerialized),\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlogger().warn({\n\t\t\t\t\t\tmsg: \"failed to send message, added to queue\",\n\t\t\t\t\t\terror,\n\t\t\t\t\t\tconnId: this.#connId,\n\t\t\t\t\t});\n\n\t\t\t\t\t// Assuming the socket is disconnected and will be reconnected soon\n\t\t\t\t\tqueueMessage = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlogger().debug({\n\t\t\t\t\tmsg: \"websocket not open, queueing message\",\n\t\t\t\t\treadyState,\n\t\t\t\t});\n\t\t\t\tqueueMessage = true;\n\t\t\t}\n\t\t} else {\n\t\t\t// No websocket connected yet\n\t\t\tlogger().debug({ msg: \"no websocket, queueing message\" });\n\t\t\tqueueMessage = true;\n\t\t}\n\n\t\tif (!opts?.ephemeral && queueMessage) {\n\t\t\tthis.#messageQueue.push(message);\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"queued connection message\",\n\t\t\t\tqueueLength: this.#messageQueue.length,\n\t\t\t\tconnId: this.#connId,\n\t\t\t\tmessageType: (message.body as any).tag,\n\t\t\t\tactionName: (message.body as any).val?.name,\n\t\t\t});\n\t\t}\n\t}\n\n\tasync #parseMessage(data: ConnMessage): Promise<{\n\t\tbody:\n\t\t\t| { tag: \"Init\"; val: { actorId: string; connectionId: string } }\n\t\t\t| {\n\t\t\t\t\ttag: \"Error\";\n\t\t\t\t\tval: {\n\t\t\t\t\t\tgroup: string;\n\t\t\t\t\t\tcode: string;\n\t\t\t\t\t\tmessage: string;\n\t\t\t\t\t\tmetadata: unknown;\n\t\t\t\t\t\tactionId: bigint | null;\n\t\t\t\t\t};\n\t\t\t }\n\t\t\t| { tag: \"ActionResponse\"; val: { id: bigint; output: unknown } }\n\t\t\t| { tag: \"Event\"; val: { name: string; args: unknown } };\n\t}> {\n\t\tinvariant(this.#websocket, \"websocket must be defined\");\n\n\t\tconst buffer = await inputDataToBuffer(data);\n\n\t\treturn deserializeWithEncoding(\n\t\t\tthis.#encoding,\n\t\t\tbuffer,\n\t\t\tTO_CLIENT_VERSIONED,\n\t\t\tToClientSchema,\n\t\t\t// JSON: values are already the correct type\n\t\t\t(msg): ToClientJson => msg as ToClientJson,\n\t\t\t// BARE: need to decode ArrayBuffer fields back to unknown\n\t\t\t(msg): any => {\n\t\t\t\tif (msg.body.tag === \"Error\") {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\ttag: \"Error\",\n\t\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\t\tgroup: msg.body.val.group,\n\t\t\t\t\t\t\t\tcode: msg.body.val.code,\n\t\t\t\t\t\t\t\tmessage: msg.body.val.message,\n\t\t\t\t\t\t\t\tmetadata: msg.body.val.metadata\n\t\t\t\t\t\t\t\t\t? cbor.decode(\n\t\t\t\t\t\t\t\t\t\t\tnew Uint8Array(\n\t\t\t\t\t\t\t\t\t\t\t\tmsg.body.val.metadata,\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t\tactionId: msg.body.val.actionId,\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} else if (msg.body.tag === \"ActionResponse\") {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\ttag: \"ActionResponse\",\n\t\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\t\tid: msg.body.val.id,\n\t\t\t\t\t\t\t\toutput: cbor.decode(\n\t\t\t\t\t\t\t\t\tnew Uint8Array(msg.body.val.output),\n\t\t\t\t\t\t\t\t),\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} else if (msg.body.tag === \"Event\") {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\ttag: \"Event\",\n\t\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\t\tname: msg.body.val.name,\n\t\t\t\t\t\t\t\targs: cbor.decode(\n\t\t\t\t\t\t\t\t\tnew Uint8Array(msg.body.val.args),\n\t\t\t\t\t\t\t\t),\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} else {\n\t\t\t\t\t// Init has no ArrayBuffer fields\n\t\t\t\t\treturn msg;\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * Get the actor ID (for testing purposes).\n\t * @internal\n\t */\n\tget actorId(): string | undefined {\n\t\treturn this.#actorId;\n\t}\n\n\t/**\n\t * Get the connection ID (for testing purposes).\n\t * @internal\n\t */\n\tget connId(): string | undefined {\n\t\treturn this.#connId;\n\t}\n\n\t/**\n\t * Get the connection ID (for testing purposes).\n\t * @internal\n\t * @deprecated Use `connId` instead.\n\t */\n\tget connectionId(): string | undefined {\n\t\treturn this.#connId;\n\t}\n\n\t/**\n\t * Disconnects from the actor.\n\t *\n\t * @returns {Promise<void>} A promise that resolves when the socket is gracefully closed.\n\t */\n\tasync dispose(): Promise<void> {\n\t\t// Internally, this \"disposes\" the connection\n\n\t\tif (this.#disposed) {\n\t\t\tlogger().warn({ msg: \"connection already disconnected\" });\n\t\t\treturn;\n\t\t}\n\t\tthis.#disposed = true;\n\n\t\tlogger().debug({ msg: \"disposing actor conn\" });\n\n\t\t// Set status to Idle (intentionally closed, no auto-reconnect)\n\t\tthis.#setConnStatus(\"idle\");\n\n\t\t// Clear interval so NodeJS process can exit\n\t\tclearInterval(this.#keepNodeAliveInterval);\n\n\t\t// Abort retry loop\n\t\tthis.#abortController.abort();\n\n\t\t// Remove from registry\n\t\tthis.#client[ACTOR_CONNS_SYMBOL].delete(this);\n\n\t\t// Close websocket (#handleOnClose will reject pending promises)\n\t\tif (this.#websocket) {\n\t\t\tconst ws = this.#websocket;\n\t\t\tif (\n\t\t\t\tws.readyState !== 2 /* CLOSING */ &&\n\t\t\t\tws.readyState !== 3 /* CLOSED */\n\t\t\t) {\n\t\t\t\tconst { promise, resolve } = promiseWithResolvers((reason) => logger().warn({ msg: \"unhandled websocket close promise rejection\", reason }));\n\t\t\t\tws.addEventListener(\"close\", () => resolve(undefined));\n\t\t\t\tws.close(1000, \"Disposed\");\n\t\t\t\tawait promise;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.#rejectPendingPromises(new errors.ActorConnDisposed(), true);\n\t\t}\n\t\tthis.#websocket = undefined;\n\t}\n\n\t#sendSubscription(eventName: string, subscribe: boolean) {\n\t\tthis.#sendMessage(\n\t\t\t{\n\t\t\t\tbody: {\n\t\t\t\t\ttag: \"SubscriptionRequest\",\n\t\t\t\t\tval: {\n\t\t\t\t\t\teventName,\n\t\t\t\t\t\tsubscribe,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{ ephemeral: true },\n\t\t);\n\t}\n}\n\n/**\n * Connection to a actor. Allows calling actor's remote procedure calls with inferred types. See {@link ActorConnRaw} for underlying methods.\n *\n * @example\n * ```\n * const room = client.connect<ChatRoom>(...etc...);\n * // This calls the action named `sendMessage` on the `ChatRoom` actor.\n * await room.sendMessage('Hello, world!');\n * ```\n *\n * Private methods (e.g. those starting with `_`) are automatically excluded.\n *\n * @template AD The actor class that this connection is for.\n * @see {@link ActorConnRaw}\n */\nexport type ActorConn<AD extends AnyActorDefinition> = ActorConnRaw &\n\tActorDefinitionActions<AD>;\n","import type { Context as HonoContext } from \"hono\";\nimport * as errors from \"@/actor/errors\";\nimport { stringifyError } from \"@/common/utils\";\nimport type { ManagerDriver } from \"@/driver-helpers/mod\";\nimport type { ActorQuery } from \"@/manager/protocol/query\";\nimport { ActorSchedulingError } from \"./errors\";\nimport { logger } from \"./log\";\n\n/**\n * Query the manager driver to get or create a actor based on the provided query\n */\nexport async function queryActor(\n\tc: HonoContext | undefined,\n\tquery: ActorQuery,\n\tmanagerDriver: ManagerDriver,\n): Promise<{ actorId: string }> {\n\tlogger().debug({ msg: \"querying actor\", query: JSON.stringify(query) });\n\tlet actorOutput: { actorId: string };\n\tif (\"getForId\" in query) {\n\t\tconst output = await managerDriver.getForId({\n\t\t\tc,\n\t\t\tname: query.getForId.name,\n\t\t\tactorId: query.getForId.actorId,\n\t\t});\n\t\tif (!output) throw new errors.ActorNotFound(query.getForId.actorId);\n\t\tactorOutput = output;\n\t} else if (\"getForKey\" in query) {\n\t\tconst existingActor = await managerDriver.getWithKey({\n\t\t\tc,\n\t\t\tname: query.getForKey.name,\n\t\t\tkey: query.getForKey.key,\n\t\t});\n\t\tif (!existingActor) {\n\t\t\tthrow new errors.ActorNotFound(\n\t\t\t\t`${query.getForKey.name}:${JSON.stringify(query.getForKey.key)}`,\n\t\t\t);\n\t\t}\n\t\tactorOutput = existingActor;\n\t} else if (\"getOrCreateForKey\" in query) {\n\t\tconst getOrCreateOutput = await managerDriver.getOrCreateWithKey({\n\t\t\tc,\n\t\t\tname: query.getOrCreateForKey.name,\n\t\t\tkey: query.getOrCreateForKey.key,\n\t\t\tinput: query.getOrCreateForKey.input,\n\t\t\tregion: query.getOrCreateForKey.region,\n\t\t});\n\t\tactorOutput = {\n\t\t\tactorId: getOrCreateOutput.actorId,\n\t\t};\n\t} else if (\"create\" in query) {\n\t\tconst createOutput = await managerDriver.createActor({\n\t\t\tc,\n\t\t\tname: query.create.name,\n\t\t\tkey: query.create.key,\n\t\t\tinput: query.create.input,\n\t\t\tregion: query.create.region,\n\t\t});\n\t\tactorOutput = {\n\t\t\tactorId: createOutput.actorId,\n\t\t};\n\t} else {\n\t\tthrow new errors.InvalidRequest(\"Invalid query format\");\n\t}\n\n\tlogger().debug({ msg: \"actor query result\", actorId: actorOutput.actorId });\n\treturn { actorId: actorOutput.actorId };\n}\n\n/**\n * Extract the actor name from a query.\n */\nexport function getActorNameFromQuery(query: ActorQuery): string {\n\tif (\"getForId\" in query) return query.getForId.name;\n\tif (\"getForKey\" in query) return query.getForKey.name;\n\tif (\"getOrCreateForKey\" in query) return query.getOrCreateForKey.name;\n\tif (\"create\" in query) return query.create.name;\n\tthrow new errors.InvalidRequest(\"Invalid query format\");\n}\n\n/**\n * Fetch actor details and check for scheduling errors.\n */\nexport async function checkForSchedulingError(\n\tgroup: string,\n\tcode: string,\n\tactorId: string,\n\tquery: ActorQuery,\n\tdriver: ManagerDriver,\n): Promise<ActorSchedulingError | null> {\n\tconst name = getActorNameFromQuery(query);\n\n\ttry {\n\t\tconst actor = await driver.getForId({ name, actorId });\n\n\t\tif (actor?.error) {\n\t\t\tlogger().info({\n\t\t\t\tmsg: \"found actor scheduling error\",\n\t\t\t\tactorId,\n\t\t\t\terror: actor.error,\n\t\t\t});\n\t\t\treturn new ActorSchedulingError(group, code, actorId, actor.error);\n\t\t}\n\t} catch (err) {\n\t\tlogger().warn({\n\t\t\tmsg: \"failed to fetch actor details for scheduling error check\",\n\t\t\tactorId,\n\t\t\terror: stringifyError(err),\n\t\t});\n\t}\n\n\treturn null;\n}\n","import * as cbor from \"cbor-x\";\nimport type { Encoding } from \"@/actor/protocol/serde\";\nimport { HEADER_CONN_PARAMS, HEADER_ENCODING } from \"@/driver-helpers/mod\";\nimport type * as protocol from \"@/schemas/client-protocol/mod\";\nimport {\n\tCURRENT_VERSION as CLIENT_PROTOCOL_CURRENT_VERSION,\n\tHTTP_QUEUE_SEND_REQUEST_VERSIONED,\n\tHTTP_QUEUE_SEND_RESPONSE_VERSIONED,\n} from \"@/schemas/client-protocol/versioned\";\nimport {\n\ttype HttpQueueSendRequest as HttpQueueSendRequestJson,\n\tHttpQueueSendRequestSchema,\n\ttype HttpQueueSendResponse as HttpQueueSendResponseJson,\n\tHttpQueueSendResponseSchema,\n} from \"@/schemas/client-protocol-zod/mod\";\nimport { bufferToArrayBuffer } from \"@/utils\";\nimport { sendHttpRequest } from \"./utils\";\n\nexport interface QueueSender {\n\tsend(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions: QueueSendWaitOptions,\n\t): Promise<QueueSendResult>;\n\tsend(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions?: QueueSendNoWaitOptions,\n\t): Promise<void>;\n}\n\nexport interface QueueSendWaitOptions {\n\twait: true;\n\ttimeout?: number;\n\tsignal?: AbortSignal;\n}\n\nexport interface QueueSendNoWaitOptions {\n\twait?: false;\n\ttimeout?: never;\n\tsignal?: AbortSignal;\n}\n\nexport type QueueSendOptions = QueueSendWaitOptions | QueueSendNoWaitOptions;\n\nexport interface QueueSendResult {\n\tstatus: \"completed\" | \"timedOut\";\n\tresponse?: unknown;\n}\n\ninterface QueueSenderOptions {\n\tencoding: Encoding;\n\tparams: unknown;\n\tcustomFetch: (request: Request) => Promise<Response>;\n}\n\nexport function createQueueSender(senderOptions: QueueSenderOptions): QueueSender {\n\tasync function send(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions: QueueSendWaitOptions,\n\t): Promise<QueueSendResult>;\n\tasync function send(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions?: QueueSendNoWaitOptions,\n\t): Promise<void>;\n\tasync function send(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions?: QueueSendOptions,\n\t): Promise<QueueSendResult | void> {\n\t\tconst wait = options?.wait ?? false;\n\t\tconst timeout = options?.timeout;\n\n\t\tconst result = await sendHttpRequest<\n\t\t\tprotocol.HttpQueueSendRequest,\n\t\t\tprotocol.HttpQueueSendResponse,\n\t\t\tHttpQueueSendRequestJson,\n\t\t\tHttpQueueSendResponseJson,\n\t\t\t{ body: unknown; wait?: boolean; timeout?: number; name?: string },\n\t\t\tQueueSendResult\n\t\t>({\n\t\t\turl: `http://actor/queue/${encodeURIComponent(name)}`,\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t[HEADER_ENCODING]: senderOptions.encoding,\n\t\t\t\t...(senderOptions.params !== undefined\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t[HEADER_CONN_PARAMS]: JSON.stringify(\n\t\t\t\t\t\t\t\tsenderOptions.params,\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},\n\t\t\tbody: { body, wait, timeout },\n\t\t\tencoding: senderOptions.encoding,\n\t\t\tcustomFetch: senderOptions.customFetch,\n\t\t\tsignal: options?.signal,\n\t\t\trequestVersion: CLIENT_PROTOCOL_CURRENT_VERSION,\n\t\t\trequestVersionedDataHandler: HTTP_QUEUE_SEND_REQUEST_VERSIONED,\n\t\t\tresponseVersion: CLIENT_PROTOCOL_CURRENT_VERSION,\n\t\t\tresponseVersionedDataHandler:\n\t\t\t\tHTTP_QUEUE_SEND_RESPONSE_VERSIONED,\n\t\t\trequestZodSchema: HttpQueueSendRequestSchema,\n\t\t\tresponseZodSchema: HttpQueueSendResponseSchema,\n\t\t\trequestToJson: (value): HttpQueueSendRequestJson => ({\n\t\t\t\t...value,\n\t\t\t\tname,\n\t\t\t}),\n\t\t\trequestToBare: (value): protocol.HttpQueueSendRequest => ({\n\t\t\t\tname: value.name ?? name,\n\t\t\t\tbody: bufferToArrayBuffer(cbor.encode(value.body)),\n\t\t\t\twait: value.wait ?? false,\n\t\t\t\ttimeout: value.timeout !== undefined ? BigInt(value.timeout) : null,\n\t\t\t}),\n\t\t\tresponseFromJson: (json): QueueSendResult => {\n\t\t\t\tif (json.response === undefined) {\n\t\t\t\t\treturn { status: json.status as \"completed\" | \"timedOut\" };\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tstatus: json.status as \"completed\" | \"timedOut\",\n\t\t\t\t\tresponse: json.response,\n\t\t\t\t};\n\t\t\t},\n\t\t\tresponseFromBare: (bare): QueueSendResult => {\n\t\t\t\tif (bare.response === null || bare.response === undefined) {\n\t\t\t\t\treturn { status: bare.status as \"completed\" | \"timedOut\" };\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tstatus: bare.status as \"completed\" | \"timedOut\",\n\t\t\t\t\tresponse: cbor.decode(new Uint8Array(bare.response)),\n\t\t\t\t};\n\t\t\t},\n\t\t});\n\n\t\tif (wait) {\n\t\t\treturn result;\n\t\t}\n\t\treturn;\n\t}\n\n\treturn {\n\t\tsend,\n\t};\n}\n","import * as cbor from \"cbor-x\";\nimport invariant from \"invariant\";\nimport type { AnyActorDefinition } from \"@/actor/definition\";\nimport type { Encoding } from \"@/actor/protocol/serde\";\nimport { assertUnreachable } from \"@/actor/utils\";\nimport { deconstructError } from \"@/common/utils\";\nimport {\n\tHEADER_CONN_PARAMS,\n\tHEADER_ENCODING,\n\ttype ManagerDriver,\n} from \"@/driver-helpers/mod\";\nimport type { ActorQuery } from \"@/manager/protocol/query\";\nimport type * as protocol from \"@/schemas/client-protocol/mod\";\nimport {\n\tCURRENT_VERSION as CLIENT_PROTOCOL_CURRENT_VERSION,\n\tHTTP_ACTION_REQUEST_VERSIONED,\n\tHTTP_ACTION_RESPONSE_VERSIONED,\n} from \"@/schemas/client-protocol/versioned\";\nimport {\n\ttype HttpActionRequest as HttpActionRequestJson,\n\tHttpActionRequestSchema,\n\ttype HttpActionResponse as HttpActionResponseJson,\n\tHttpActionResponseSchema,\n} from \"@/schemas/client-protocol-zod/mod\";\nimport { bufferToArrayBuffer } from \"@/utils\";\nimport type { ActorDefinitionActions } from \"./actor-common\";\nimport { type ActorConn, ActorConnRaw } from \"./actor-conn\";\nimport { checkForSchedulingError, queryActor } from \"./actor-query\";\nimport { type ClientRaw, CREATE_ACTOR_CONN_PROXY } from \"./client\";\nimport { ActorError, isSchedulingError } from \"./errors\";\nimport { logger } from \"./log\";\nimport {\n\tcreateQueueSender,\n\ttype QueueSendNoWaitOptions,\n\ttype QueueSendOptions,\n\ttype QueueSendResult,\n\ttype QueueSendWaitOptions,\n} from \"./queue\";\nimport { rawHttpFetch, rawWebSocket } from \"./raw-utils\";\nimport { sendHttpRequest } from \"./utils\";\n\n/**\n * Provides underlying functions for stateless {@link ActorHandle} for action calls.\n * Similar to ActorConnRaw but doesn't maintain a connection.\n *\n * @see {@link ActorHandle}\n */\nexport class ActorHandleRaw {\n\t#client: ClientRaw;\n\t#driver: ManagerDriver;\n\t#encoding: Encoding;\n\t#actorQuery: ActorQuery;\n\t#params: unknown;\n\t#queueSender: ReturnType<typeof createQueueSender>;\n\n\t/**\n\t * Do not call this directly.\n\t *\n\t * Creates an instance of ActorHandleRaw.\n\t *\n\t * @protected\n\t */\n\tpublic constructor(\n\t\tclient: any,\n\t\tdriver: ManagerDriver,\n\t\tparams: unknown,\n\t\tencoding: Encoding,\n\t\tactorQuery: ActorQuery,\n\t) {\n\t\tthis.#client = client;\n\t\tthis.#driver = driver;\n\t\tthis.#encoding = encoding;\n\t\tthis.#actorQuery = actorQuery;\n\t\tthis.#params = params;\n\t\tthis.#queueSender = createQueueSender({\n\t\t\tencoding: this.#encoding,\n\t\t\tparams: this.#params,\n\t\t\tcustomFetch: async (request: Request) => {\n\t\t\t\tconst { actorId } = await queryActor(\n\t\t\t\t\tundefined,\n\t\t\t\t\tthis.#actorQuery,\n\t\t\t\t\tthis.#driver,\n\t\t\t\t);\n\t\t\t\treturn this.#driver.sendRequest(actorId, request);\n\t\t\t},\n\t\t});\n\t}\n\n\tsend(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions: QueueSendWaitOptions,\n\t): Promise<QueueSendResult>;\n\tsend(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions?: QueueSendNoWaitOptions,\n\t): Promise<void>;\n\tsend(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions?: QueueSendOptions,\n\t): Promise<QueueSendResult | void> {\n\t\treturn this.#queueSender.send(name, body, options as any);\n\t}\n\n\t/**\n\t * Call a raw action. This method sends an HTTP request to invoke the named action.\n\t *\n\t * @see {@link ActorHandle}\n\t * @template Args - The type of arguments to pass to the action function.\n\t * @template Response - The type of the response returned by the action function.\n\t */\n\tasync action<\n\t\tArgs extends Array<unknown> = unknown[],\n\t\tResponse = unknown,\n\t>(opts: {\n\t\tname: string;\n\t\targs: Args;\n\t\tsignal?: AbortSignal;\n\t}): Promise<Response> {\n\t\t// Track actorId for scheduling error lookups\n\t\tlet actorId: string | undefined;\n\n\t\ttry {\n\t\t\t// Get the actor ID\n\t\t\tconst result = await queryActor(\n\t\t\t\tundefined,\n\t\t\t\tthis.#actorQuery,\n\t\t\t\tthis.#driver,\n\t\t\t);\n\t\t\tactorId = result.actorId;\n\t\t\tlogger().debug({ msg: \"found actor for action\", actorId });\n\t\t\tinvariant(actorId, \"Missing actor ID\");\n\n\t\t\t// Invoke the action\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"handling action\",\n\t\t\t\tname: opts.name,\n\t\t\t\tencoding: this.#encoding,\n\t\t\t});\n\t\t\tconst responseData = await sendHttpRequest<\n\t\t\t\tprotocol.HttpActionRequest, // Bare type\n\t\t\t\tprotocol.HttpActionResponse, // Bare type\n\t\t\t\tHttpActionRequestJson, // Json type\n\t\t\t\tHttpActionResponseJson, // Json type\n\t\t\t\tunknown[], // Request type (the args array)\n\t\t\t\tResponse // Response type (the output value)\n\t\t\t>({\n\t\t\t\turl: `http://actor/action/${encodeURIComponent(opts.name)}`,\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\t[HEADER_ENCODING]: this.#encoding,\n\t\t\t\t\t...(this.#params !== undefined\n\t\t\t\t\t\t? { [HEADER_CONN_PARAMS]: JSON.stringify(this.#params) }\n\t\t\t\t\t\t: {}),\n\t\t\t\t},\n\t\t\t\tbody: opts.args,\n\t\t\t\tencoding: this.#encoding,\n\t\t\t\tcustomFetch: this.#driver.sendRequest.bind(\n\t\t\t\t\tthis.#driver,\n\t\t\t\t\tactorId,\n\t\t\t\t),\n\t\t\t\tsignal: opts?.signal,\n\t\t\t\trequestVersion: CLIENT_PROTOCOL_CURRENT_VERSION,\n\t\t\t\trequestVersionedDataHandler: HTTP_ACTION_REQUEST_VERSIONED,\n\t\t\t\tresponseVersion: CLIENT_PROTOCOL_CURRENT_VERSION,\n\t\t\t\tresponseVersionedDataHandler: HTTP_ACTION_RESPONSE_VERSIONED,\n\t\t\t\trequestZodSchema: HttpActionRequestSchema,\n\t\t\t\tresponseZodSchema: HttpActionResponseSchema,\n\t\t\t\t// JSON Request: args is the raw value\n\t\t\t\trequestToJson: (args): HttpActionRequestJson => ({\n\t\t\t\t\targs,\n\t\t\t\t}),\n\t\t\t\t// BARE Request: args needs to be CBOR-encoded\n\t\t\t\trequestToBare: (args): protocol.HttpActionRequest => ({\n\t\t\t\t\targs: bufferToArrayBuffer(cbor.encode(args)),\n\t\t\t\t}),\n\t\t\t\t// JSON Response: output is the raw value\n\t\t\t\tresponseFromJson: (json): Response => json.output as Response,\n\t\t\t\t// BARE Response: output is ArrayBuffer that needs CBOR-decoding\n\t\t\t\tresponseFromBare: (bare): Response =>\n\t\t\t\t\tcbor.decode(new Uint8Array(bare.output)) as Response,\n\t\t\t});\n\n\t\t\treturn responseData;\n\t\t} catch (err) {\n\t\t\t// Standardize to ClientActorError instead of the native backend error\n\t\t\tconst { group, code, message, metadata } = deconstructError(\n\t\t\t\terr,\n\t\t\t\tlogger(),\n\t\t\t\t{},\n\t\t\t\ttrue,\n\t\t\t);\n\n\t\t\t// Check if this is a scheduling error and try to get more details\n\t\t\tif (actorId && isSchedulingError(group, code)) {\n\t\t\t\tconst schedulingError = await checkForSchedulingError(\n\t\t\t\t\tgroup,\n\t\t\t\t\tcode,\n\t\t\t\t\tactorId,\n\t\t\t\t\tthis.#actorQuery,\n\t\t\t\t\tthis.#driver,\n\t\t\t\t);\n\t\t\t\tif (schedulingError) {\n\t\t\t\t\tthrow schedulingError;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow new ActorError(group, code, message, metadata);\n\t\t}\n\t}\n\n\t/**\n\t * Establishes a persistent connection to the actor.\n\t *\n\t * @template AD The actor class that this connection is for.\n\t * @returns {ActorConn<AD>} A connection to the actor.\n\t */\n\tconnect(): ActorConn<AnyActorDefinition> {\n\t\tlogger().debug({\n\t\t\tmsg: \"establishing connection from handle\",\n\t\t\tquery: this.#actorQuery,\n\t\t});\n\n\t\tconst conn = new ActorConnRaw(\n\t\t\tthis.#client,\n\t\t\tthis.#driver,\n\t\t\tthis.#params,\n\t\t\tthis.#encoding,\n\t\t\tthis.#actorQuery,\n\t\t);\n\n\t\treturn this.#client[CREATE_ACTOR_CONN_PROXY](\n\t\t\tconn,\n\t\t) as ActorConn<AnyActorDefinition>;\n\t}\n\n\t/**\n\t * Fetches a resource from this actor via the /request endpoint. This is a\n\t * convenience wrapper around the raw HTTP API.\n\t */\n\tfetch(input: string | URL | Request, init?: RequestInit) {\n\t\treturn rawHttpFetch(\n\t\t\tthis.#driver,\n\t\t\tthis.#actorQuery,\n\t\t\tthis.#params,\n\t\t\tinput,\n\t\t\tinit,\n\t\t);\n\t}\n\n\t/**\n\t * Opens a raw WebSocket connection to this actor.\n\t */\n\twebSocket(path?: string, protocols?: string | string[]) {\n\t\treturn rawWebSocket(\n\t\t\tthis.#driver,\n\t\t\tthis.#actorQuery,\n\t\t\tthis.#params,\n\t\t\tpath,\n\t\t\tprotocols,\n\t\t);\n\t}\n\n\t/**\n\t * Resolves the actor to get its unique actor ID.\n\t */\n\tasync resolve(): Promise<string> {\n\t\tif (\"getForKey\" in this.#actorQuery) {\n\t\t\tconst name = this.#actorQuery.getForKey.name;\n\n\t\t\t// Query the actor to get the id\n\t\t\tconst { actorId } = await queryActor(\n\t\t\t\tundefined,\n\t\t\t\tthis.#actorQuery,\n\t\t\t\tthis.#driver,\n\t\t\t);\n\n\t\t\tthis.#actorQuery = { getForId: { actorId, name } };\n\n\t\t\treturn actorId;\n\t\t} else if (\"getOrCreateForKey\" in this.#actorQuery) {\n\t\t\tconst name = this.#actorQuery.getOrCreateForKey.name;\n\n\t\t\t// Query the actor to get or create and get the id\n\t\t\tconst { actorId } = await queryActor(\n\t\t\t\tundefined,\n\t\t\t\tthis.#actorQuery,\n\t\t\t\tthis.#driver,\n\t\t\t);\n\n\t\t\tthis.#actorQuery = { getForId: { actorId, name } };\n\n\t\t\treturn actorId;\n\t\t} else if (\"getForId\" in this.#actorQuery) {\n\t\t\t// Skip since it's already resolved\n\t\t\treturn this.#actorQuery.getForId.actorId;\n\t\t} else if (\"create\" in this.#actorQuery) {\n\t\t\t// Cannot create a handle with this query\n\t\t\tinvariant(false, \"actorQuery cannot be create\");\n\t\t} else {\n\t\t\tassertUnreachable(this.#actorQuery);\n\t\t}\n\t}\n\n\t/**\n\t * Returns the raw URL for routing traffic to the actor.\n\t */\n\tasync getGatewayUrl(): Promise<string> {\n\t\tconst { actorId } = await queryActor(\n\t\t\tundefined,\n\t\t\tthis.#actorQuery,\n\t\t\tthis.#driver,\n\t\t);\n\t\treturn await this.#driver.buildGatewayUrl(actorId);\n\t}\n}\n\n/**\n * Stateless handle to a actor. Allows calling actor's remote procedure calls with inferred types\n * without establishing a persistent connection.\n *\n * @example\n * ```\n * const room = client.get<ChatRoom>(...etc...);\n * // This calls the action named `sendMessage` on the `ChatRoom` actor without a connection.\n * await room.sendMessage('Hello, world!');\n * ```\n *\n * Private methods (e.g. those starting with `_`) are automatically excluded.\n *\n * @template AD The actor class that this handle is for.\n * @see {@link ActorHandleRaw}\n */\nexport type ActorHandle<AD extends AnyActorDefinition> = Omit<\n\tActorHandleRaw,\n\t\"connect\"\n> & {\n\t// Add typed version of ActorConn (instead of using AnyActorDefinition)\n\tconnect(): ActorConn<AD>;\n\t// Resolve method returns the actor ID\n\tresolve(): Promise<string>;\n} & ActorDefinitionActions<AD>;\n","import invariant from \"invariant\";\nimport { PATH_WEBSOCKET_PREFIX } from \"@/common/actor-router-consts\";\nimport { deconstructError } from \"@/common/utils\";\nimport { HEADER_CONN_PARAMS, type ManagerDriver } from \"@/driver-helpers/mod\";\nimport type { ActorQuery } from \"@/manager/protocol/query\";\nimport { queryActor } from \"./actor-query\";\nimport { ActorError } from \"./errors\";\nimport { logger } from \"./log\";\n\n/**\n * Shared implementation for raw HTTP fetch requests\n */\nexport async function rawHttpFetch(\n\tdriver: ManagerDriver,\n\tactorQuery: ActorQuery,\n\tparams: unknown,\n\tinput: string | URL | Request,\n\tinit?: RequestInit,\n): Promise<Response> {\n\t// Extract path and merge init options\n\tlet path: string;\n\tlet mergedInit: RequestInit = init || {};\n\n\tif (typeof input === \"string\") {\n\t\tpath = input;\n\t} else if (input instanceof URL) {\n\t\tpath = input.pathname + input.search;\n\t} else if (input instanceof Request) {\n\t\t// Extract path from Request URL\n\t\tconst url = new URL(input.url);\n\t\tpath = url.pathname + url.search;\n\t\t// Merge Request properties with init\n\t\tconst requestHeaders = new Headers(input.headers);\n\t\tconst initHeaders = new Headers(init?.headers || {});\n\n\t\t// Merge headers - init headers override request headers\n\t\tconst mergedHeaders = new Headers(requestHeaders);\n\t\tinitHeaders.forEach((value, key) => {\n\t\t\tmergedHeaders.set(key, value);\n\t\t});\n\n\t\tmergedInit = {\n\t\t\tmethod: input.method,\n\t\t\tbody: input.body,\n\t\t\tmode: input.mode,\n\t\t\tcredentials: input.credentials,\n\t\t\tredirect: input.redirect,\n\t\t\treferrer: input.referrer,\n\t\t\treferrerPolicy: input.referrerPolicy,\n\t\t\tintegrity: input.integrity,\n\t\t\tkeepalive: input.keepalive,\n\t\t\tsignal: input.signal,\n\t\t\t...mergedInit, // init overrides Request properties\n\t\t\theaders: mergedHeaders, // headers must be set after spread to ensure proper merge\n\t\t};\n\t\t// Add duplex if body is present\n\t\tif (mergedInit.body) {\n\t\t\t(mergedInit as any).duplex = \"half\";\n\t\t}\n\t} else {\n\t\tthrow new TypeError(\"Invalid input type for fetch\");\n\t}\n\n\ttry {\n\t\t// Get the actor ID\n\t\tconst { actorId } = await queryActor(undefined, actorQuery, driver);\n\t\tlogger().debug({ msg: \"found actor for raw http\", actorId });\n\t\tinvariant(actorId, \"Missing actor ID\");\n\n\t\t// Build the URL with normalized path\n\t\tconst normalizedPath = path.startsWith(\"/\") ? path.slice(1) : path;\n\t\tconst url = new URL(`http://actor/request/${normalizedPath}`);\n\n\t\t// Forward conn params if provided\n\t\tconst proxyRequestHeaders = new Headers(mergedInit.headers);\n\t\tif (params) {\n\t\t\tproxyRequestHeaders.set(HEADER_CONN_PARAMS, JSON.stringify(params));\n\t\t}\n\n\t\t// Forward the request to the actor\n\t\tconst proxyRequest = new Request(url, {\n\t\t\t...mergedInit,\n\t\t\theaders: proxyRequestHeaders,\n\t\t});\n\n\t\treturn driver.sendRequest(actorId, proxyRequest);\n\t} catch (err) {\n\t\t// Standardize to ClientActorError instead of the native backend error\n\t\tconst { group, code, message, metadata } = deconstructError(\n\t\t\terr,\n\t\t\tlogger(),\n\t\t\t{},\n\t\t\ttrue,\n\t\t);\n\t\tthrow new ActorError(group, code, message, metadata);\n\t}\n}\n\n/**\n * Shared implementation for raw WebSocket connections\n */\nexport async function rawWebSocket(\n\tdriver: ManagerDriver,\n\tactorQuery: ActorQuery,\n\tparams: unknown,\n\tpath?: string,\n\t// TODO: Supportp rotocols\n\tprotocols?: string | string[],\n): Promise<any> {\n\t// TODO: Do we need encoding in rawWebSocket?\n\tconst encoding = \"bare\";\n\n\t// Get the actor ID\n\tconst { actorId } = await queryActor(undefined, actorQuery, driver);\n\tlogger().debug({ msg: \"found actor for action\", actorId });\n\tinvariant(actorId, \"Missing actor ID\");\n\n\t// Parse path and query parameters\n\tlet pathPortion = \"\";\n\tlet queryPortion = \"\";\n\tif (path) {\n\t\tconst queryIndex = path.indexOf(\"?\");\n\t\tif (queryIndex !== -1) {\n\t\t\tpathPortion = path.substring(0, queryIndex);\n\t\t\tqueryPortion = path.substring(queryIndex); // includes the '?'\n\t\t} else {\n\t\t\tpathPortion = path;\n\t\t}\n\t\t// Remove leading slash if present\n\t\tif (pathPortion.startsWith(\"/\")) {\n\t\t\tpathPortion = pathPortion.slice(1);\n\t\t}\n\t}\n\n\tconst fullPath = `${PATH_WEBSOCKET_PREFIX}${pathPortion}${queryPortion}`;\n\n\tlogger().debug({\n\t\tmsg: \"opening websocket\",\n\t\tactorId,\n\t\tencoding,\n\t\tpath: fullPath,\n\t});\n\n\t// Open WebSocket\n\tconst ws = await driver.openWebSocket(fullPath, actorId, encoding, params);\n\n\t// Node & browser WebSocket types are incompatible\n\treturn ws as any;\n}\n","import type { AnyActorDefinition } from \"@/actor/definition\";\nimport type { Encoding } from \"@/actor/protocol/serde\";\nimport type { ManagerDriver } from \"@/driver-helpers/mod\";\nimport type { ActorQuery } from \"@/manager/protocol/query\";\nimport type { Registry } from \"@/registry\";\nimport type { ActorActionFunction } from \"./actor-common\";\nimport {\n\ttype ActorConn,\n\ttype ActorConnRaw,\n\tCONNECT_SYMBOL,\n} from \"./actor-conn\";\nimport { type ActorHandle, ActorHandleRaw } from \"./actor-handle\";\nimport { queryActor } from \"./actor-query\";\nimport type { ClientConfig } from \"./config\";\nimport { logger } from \"./log\";\n\nexport type { ClientConfig, ClientConfigInput } from \"./config\";\n\n/** Extract the actor registry from the registry definition. */\nexport type ExtractActorsFromRegistry<A extends Registry<any>> =\n\tA extends Registry<infer Actors> ? Actors : never;\n\n/** Extract the registry definition from the client. */\nexport type ExtractRegistryFromClient<C extends Client<Registry<{}>>> =\n\tC extends Client<infer A> ? A : never;\n\n/**\n * Represents a actor accessor that provides methods to interact with a specific actor.\n */\nexport interface ActorAccessor<AD extends AnyActorDefinition> {\n\t/**\n\t * Gets a stateless handle to a actor by its key, but does not create the actor if it doesn't exist.\n\t * The actor name is automatically injected from the property accessor.\n\t *\n\t * @template AD The actor class that this handle is for.\n\t * @param {string | string[]} [key=[]] - The key to identify the actor. Can be a single string or an array of strings.\n\t * @param {GetWithIdOptions} [opts] - Options for getting the actor.\n\t * @returns {ActorHandle<AD>} - A handle to the actor.\n\t */\n\tget(key?: string | string[], opts?: GetWithIdOptions): ActorHandle<AD>;\n\n\t/**\n\t * Gets a stateless handle to a actor by its key, creating it if necessary.\n\t * The actor name is automatically injected from the property accessor.\n\t *\n\t * @template AD The actor class that this handle is for.\n\t * @param {string | string[]} [key=[]] - The key to identify the actor. Can be a single string or an array of strings.\n\t * @param {GetOptions} [opts] - Options for getting the actor.\n\t * @returns {ActorHandle<AD>} - A handle to the actor.\n\t */\n\tgetOrCreate(\n\t\tkey?: string | string[],\n\t\topts?: GetOrCreateOptions,\n\t): ActorHandle<AD>;\n\n\t/**\n\t * Gets a stateless handle to a actor by its ID.\n\t *\n\t * @template AD The actor class that this handle is for.\n\t * @param {string} actorId - The ID of the actor.\n\t * @param {GetWithIdOptions} [opts] - Options for getting the actor.\n\t * @returns {ActorHandle<AD>} - A handle to the actor.\n\t */\n\tgetForId(actorId: string, opts?: GetWithIdOptions): ActorHandle<AD>;\n\n\t/**\n\t * Creates a new actor with the name automatically injected from the property accessor,\n\t * and returns a stateless handle to it with the actor ID resolved.\n\t *\n\t * @template AD The actor class that this handle is for.\n\t * @param {string | string[]} key - The key to identify the actor. Can be a single string or an array of strings.\n\t * @param {CreateOptions} [opts] - Options for creating the actor (excluding name and key).\n\t * @returns {Promise<ActorHandle<AD>>} - A promise that resolves to a handle to the actor.\n\t */\n\tcreate(\n\t\tkey?: string | string[],\n\t\topts?: CreateOptions,\n\t): Promise<ActorHandle<AD>>;\n}\n\n/**\n * Options for querying actors.\n * @typedef {Object} QueryOptions\n * @property {unknown} [parameters] - Parameters to pass to the connection.\n */\nexport interface QueryOptions {\n\t/** Parameters to pass to the connection. */\n\tparams?: unknown;\n\t/** Signal to abort the request. */\n\tsignal?: AbortSignal;\n}\n\n/**\n * Options for getting a actor by ID.\n * @typedef {QueryOptions} GetWithIdOptions\n */\nexport interface GetWithIdOptions extends QueryOptions {}\n\n/**\n * Options for getting a actor.\n * @typedef {QueryOptions} GetOptions\n */\nexport interface GetOptions extends QueryOptions {}\n\n/**\n * Options for getting or creating a actor.\n * @typedef {QueryOptions} GetOrCreateOptions\n * @property {string} [createInRegion] - Region to create the actor in if it doesn't exist.\n */\nexport interface GetOrCreateOptions extends QueryOptions {\n\t/** Region to create the actor in if it doesn't exist. */\n\tcreateInRegion?: string;\n\t/** Input data to pass to the actor. */\n\tcreateWithInput?: unknown;\n}\n\n/**\n * Options for creating a actor.\n * @typedef {QueryOptions} CreateOptions\n * @property {string} [region] - The region to create the actor in.\n */\nexport interface CreateOptions extends QueryOptions {\n\t/** The region to create the actor in. */\n\tregion?: string;\n\t/** Input data to pass to the actor. */\n\tinput?: unknown;\n}\n\n/**\n * Represents a region to connect to.\n * @typedef {Object} Region\n * @property {string} id - The region ID.\n * @property {string} name - The region name.\n * @see {@link https://rivet.dev/docs/edge|Edge Networking}\n * @see {@link https://rivet.dev/docs/regions|Available Regions}\n */\nexport interface Region {\n\t/**\n\t * The region slug.\n\t */\n\tid: string;\n\n\t/**\n\t * The human-friendly region name.\n\t */\n\tname: string;\n}\n\nexport const ACTOR_CONNS_SYMBOL = Symbol(\"actorConns\");\nexport const CREATE_ACTOR_CONN_PROXY = Symbol(\"createActorConnProxy\");\n\n/**\n * Client for managing & connecting to actors.\n *\n * @template A The actors map type that defines the available actors.\n * @see {@link https://rivet.dev/docs/manage|Create & Manage Actors}\n */\nexport class ClientRaw {\n\t#disposed = false;\n\n\t[ACTOR_CONNS_SYMBOL] = new Set<ActorConnRaw>();\n\n\t#driver: ManagerDriver;\n\t#encodingKind: Encoding;\n\n\t/**\n\t * Creates an instance of Client.\n\t */\n\tpublic constructor(driver: ManagerDriver, encoding: Encoding | undefined) {\n\t\tthis.#driver = driver;\n\n\t\tthis.#encodingKind = encoding ?? \"bare\";\n\t}\n\n\t/**\n\t * Gets a stateless handle to a actor by its ID.\n\t *\n\t * @template AD The actor class that this handle is for.\n\t * @param {string} name - The name of the actor.\n\t * @param {string} actorId - The ID of the actor.\n\t * @param {GetWithIdOptions} [opts] - Options for getting the actor.\n\t * @returns {ActorHandle<AD>} - A handle to the actor.\n\t */\n\tgetForId<AD extends AnyActorDefinition>(\n\t\tname: string,\n\t\tactorId: string,\n\t\topts?: GetWithIdOptions,\n\t): ActorHandle<AD> {\n\t\tlogger().debug({\n\t\t\tmsg: \"get handle to actor with id\",\n\t\t\tname,\n\t\t\tactorId,\n\t\t\tparams: opts?.params,\n\t\t});\n\n\t\tconst actorQuery: ActorQuery = {\n\t\t\tgetForId: {\n\t\t\t\tname,\n\t\t\t\tactorId,\n\t\t\t},\n\t\t};\n\n\t\tconst handle = this.#createHandle(opts?.params, actorQuery);\n\t\treturn createActorProxy(handle) as ActorHandle<AD>;\n\t}\n\n\t/**\n\t * Gets a stateless handle to a actor by its key, but does not create the actor if it doesn't exist.\n\t *\n\t * @template AD The actor class that this handle is for.\n\t * @param {string} name - The name of the actor.\n\t * @param {string | string[]} [key=[]] - The key to identify the actor. Can be a single string or an array of strings.\n\t * @param {GetWithIdOptions} [opts] - Options for getting the actor.\n\t * @returns {ActorHandle<AD>} - A handle to the actor.\n\t */\n\tget<AD extends AnyActorDefinition>(\n\t\tname: string,\n\t\tkey?: string | string[],\n\t\topts?: GetWithIdOptions,\n\t): ActorHandle<AD> {\n\t\t// Convert string to array of strings\n\t\tconst keyArray: string[] = typeof key === \"string\" ? [key] : key || [];\n\n\t\tlogger().debug({\n\t\t\tmsg: \"get handle to actor\",\n\t\t\tname,\n\t\t\tkey: keyArray,\n\t\t\tparameters: opts?.params,\n\t\t});\n\n\t\tconst actorQuery: ActorQuery = {\n\t\t\tgetForKey: {\n\t\t\t\tname,\n\t\t\t\tkey: keyArray,\n\t\t\t},\n\t\t};\n\n\t\tconst handle = this.#createHandle(opts?.params, actorQuery);\n\t\treturn createActorProxy(handle) as ActorHandle<AD>;\n\t}\n\n\t/**\n\t * Gets a stateless handle to a actor by its key, creating it if necessary.\n\t *\n\t * @template AD The actor class that this handle is for.\n\t * @param {string} name - The name of the actor.\n\t * @param {string | string[]} [key=[]] - The key to identify the actor. Can be a single string or an array of strings.\n\t * @param {GetOptions} [opts] - Options for getting the actor.\n\t * @returns {ActorHandle<AD>} - A handle to the actor.\n\t */\n\tgetOrCreate<AD extends AnyActorDefinition>(\n\t\tname: string,\n\t\tkey?: string | string[],\n\t\topts?: GetOrCreateOptions,\n\t): ActorHandle<AD> {\n\t\t// Convert string to array of strings\n\t\tconst keyArray: string[] = typeof key === \"string\" ? [key] : key || [];\n\n\t\tlogger().debug({\n\t\t\tmsg: \"get or create handle to actor\",\n\t\t\tname,\n\t\t\tkey: keyArray,\n\t\t\tparameters: opts?.params,\n\t\t\tcreateInRegion: opts?.createInRegion,\n\t\t});\n\n\t\tconst actorQuery: ActorQuery = {\n\t\t\tgetOrCreateForKey: {\n\t\t\t\tname,\n\t\t\t\tkey: keyArray,\n\t\t\t\tinput: opts?.createWithInput,\n\t\t\t\tregion: opts?.createInRegion,\n\t\t\t},\n\t\t};\n\n\t\tconst handle = this.#createHandle(opts?.params, actorQuery);\n\t\treturn createActorProxy(handle) as ActorHandle<AD>;\n\t}\n\n\t/**\n\t * Creates a new actor with the provided key and returns a stateless handle to it.\n\t * Resolves the actor ID and returns a handle with getForId query.\n\t *\n\t * @template AD The actor class that this handle is for.\n\t * @param {string} name - The name of the actor.\n\t * @param {string | string[]} key - The key to identify the actor. Can be a single string or an array of strings.\n\t * @param {CreateOptions} [opts] - Options for creating the actor (excluding name and key).\n\t * @returns {Promise<ActorHandle<AD>>} - A promise that resolves to a handle to the actor.\n\t */\n\tasync create<AD extends AnyActorDefinition>(\n\t\tname: string,\n\t\tkey?: string | string[],\n\t\topts?: CreateOptions,\n\t): Promise<ActorHandle<AD>> {\n\t\t// Convert string to array of strings\n\t\tconst keyArray: string[] = typeof key === \"string\" ? [key] : key || [];\n\n\t\tconst createQuery = {\n\t\t\tcreate: {\n\t\t\t\t...opts,\n\t\t\t\t// Do these last to override `opts`\n\t\t\t\tname,\n\t\t\t\tkey: keyArray,\n\t\t\t},\n\t\t} satisfies ActorQuery;\n\n\t\tlogger().debug({\n\t\t\tmsg: \"create actor handle\",\n\t\t\tname,\n\t\t\tkey: keyArray,\n\t\t\tparameters: opts?.params,\n\t\t\tcreate: createQuery.create,\n\t\t});\n\n\t\t// Create the actor\n\t\tconst { actorId } = await queryActor(\n\t\t\tundefined,\n\t\t\tcreateQuery,\n\t\t\tthis.#driver,\n\t\t);\n\t\tlogger().debug({\n\t\t\tmsg: \"created actor with ID\",\n\t\t\tname,\n\t\t\tkey: keyArray,\n\t\t\tactorId,\n\t\t});\n\n\t\t// Create handle with actor ID\n\t\tconst getForIdQuery = {\n\t\t\tgetForId: {\n\t\t\t\tname,\n\t\t\t\tactorId,\n\t\t\t},\n\t\t} satisfies ActorQuery;\n\t\tconst handle = this.#createHandle(opts?.params, getForIdQuery);\n\n\t\tconst proxy = createActorProxy(handle) as ActorHandle<AD>;\n\n\t\treturn proxy;\n\t}\n\n\t#createHandle(params: unknown, actorQuery: ActorQuery): ActorHandleRaw {\n\t\treturn new ActorHandleRaw(\n\t\t\tthis,\n\t\t\tthis.#driver,\n\t\t\tparams,\n\t\t\tthis.#encodingKind,\n\t\t\tactorQuery,\n\t\t);\n\t}\n\n\t[CREATE_ACTOR_CONN_PROXY]<AD extends AnyActorDefinition>(\n\t\tconn: ActorConnRaw,\n\t): ActorConn<AD> {\n\t\t// Save to connection list\n\t\tthis[ACTOR_CONNS_SYMBOL].add(conn);\n\n\t\t// Start connection\n\t\tconn[CONNECT_SYMBOL]();\n\n\t\treturn createActorProxy(conn) as ActorConn<AD>;\n\t}\n\n\t/**\n\t * Disconnects from all actors.\n\t *\n\t * @returns {Promise<void>} A promise that resolves when all connections are closed.\n\t */\n\tasync dispose(): Promise<void> {\n\t\tif (this.#disposed) {\n\t\t\tlogger().warn({ msg: \"client already disconnected\" });\n\t\t\treturn;\n\t\t}\n\t\tthis.#disposed = true;\n\n\t\tlogger().debug({ msg: \"disposing client\" });\n\n\t\tconst disposePromises = [];\n\n\t\t// Dispose all connections\n\t\tfor (const conn of this[ACTOR_CONNS_SYMBOL].values()) {\n\t\t\tdisposePromises.push(conn.dispose());\n\t\t}\n\n\t\tawait Promise.all(disposePromises);\n\t}\n}\n\n/**\n * Client type with actor accessors.\n * This adds property accessors for actor names to the ClientRaw base class.\n *\n * @template A The actor registry type.\n */\nexport type Client<A extends Registry<any>> = ClientRaw & {\n\t[K in keyof ExtractActorsFromRegistry<A>]: ActorAccessor<\n\t\tExtractActorsFromRegistry<A>[K]\n\t>;\n};\n\nexport type AnyClient = Client<Registry<any>>;\n\nexport function createClientWithDriver<A extends Registry<any>>(\n\tdriver: ManagerDriver,\n\tconfig: { encoding?: Encoding } = {},\n): Client<A> {\n\tconst client = new ClientRaw(driver, config.encoding);\n\n\t// Create proxy for accessing actors by name\n\treturn new Proxy(client, {\n\t\tget: (target: ClientRaw, prop: string | symbol, receiver: unknown) => {\n\t\t\t// Get the real property if it exists\n\t\t\tif (typeof prop === \"symbol\" || prop in target) {\n\t\t\t\tconst value = Reflect.get(target, prop, receiver);\n\t\t\t\t// Preserve method binding\n\t\t\t\tif (typeof value === \"function\") {\n\t\t\t\t\treturn value.bind(target);\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t\t// Handle actor accessor for string properties (actor names)\n\t\t\tif (typeof prop === \"string\") {\n\t\t\t\t// Return actor accessor object with methods\n\t\t\t\treturn {\n\t\t\t\t\t// Handle methods (stateless action)\n\t\t\t\t\tget: (\n\t\t\t\t\t\tkey?: string | string[],\n\t\t\t\t\t\topts?: GetWithIdOptions,\n\t\t\t\t\t): ActorHandle<\n\t\t\t\t\t\tExtractActorsFromRegistry<A>[typeof prop]\n\t\t\t\t\t> => {\n\t\t\t\t\t\treturn target.get<\n\t\t\t\t\t\t\tExtractActorsFromRegistry<A>[typeof prop]\n\t\t\t\t\t\t>(prop, key, opts);\n\t\t\t\t\t},\n\t\t\t\t\tgetOrCreate: (\n\t\t\t\t\t\tkey?: string | string[],\n\t\t\t\t\t\topts?: GetOptions,\n\t\t\t\t\t): ActorHandle<\n\t\t\t\t\t\tExtractActorsFromRegistry<A>[typeof prop]\n\t\t\t\t\t> => {\n\t\t\t\t\t\treturn target.getOrCreate<\n\t\t\t\t\t\t\tExtractActorsFromRegistry<A>[typeof prop]\n\t\t\t\t\t\t>(prop, key, opts);\n\t\t\t\t\t},\n\t\t\t\t\tgetForId: (\n\t\t\t\t\t\tactorId: string,\n\t\t\t\t\t\topts?: GetWithIdOptions,\n\t\t\t\t\t): ActorHandle<\n\t\t\t\t\t\tExtractActorsFromRegistry<A>[typeof prop]\n\t\t\t\t\t> => {\n\t\t\t\t\t\treturn target.getForId<\n\t\t\t\t\t\t\tExtractActorsFromRegistry<A>[typeof prop]\n\t\t\t\t\t\t>(prop, actorId, opts);\n\t\t\t\t\t},\n\t\t\t\t\tcreate: async (\n\t\t\t\t\t\tkey: string | string[],\n\t\t\t\t\t\topts: CreateOptions = {},\n\t\t\t\t\t): Promise<\n\t\t\t\t\t\tActorHandle<ExtractActorsFromRegistry<A>[typeof prop]>\n\t\t\t\t\t> => {\n\t\t\t\t\t\treturn await target.create<\n\t\t\t\t\t\t\tExtractActorsFromRegistry<A>[typeof prop]\n\t\t\t\t\t\t>(prop, key, opts);\n\t\t\t\t\t},\n\t\t\t\t} as ActorAccessor<ExtractActorsFromRegistry<A>[typeof prop]>;\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t},\n\t}) as Client<A>;\n}\n\n/**\n * Creates a proxy for a actor that enables calling actions without explicitly using `.action`.\n **/\nfunction createActorProxy<AD extends AnyActorDefinition>(\n\thandle: ActorHandleRaw | ActorConnRaw,\n): ActorHandle<AD> | ActorConn<AD> {\n\t// Stores returned action functions for faster calls\n\tconst methodCache = new Map<string, ActorActionFunction>();\n\treturn new Proxy(handle, {\n\t\tget(target: ActorHandleRaw, prop: string | symbol, receiver: unknown) {\n\t\t\t// Handle built-in Symbol properties\n\t\t\tif (typeof prop === \"symbol\") {\n\t\t\t\treturn Reflect.get(target, prop, receiver);\n\t\t\t}\n\n\t\t\t// Handle built-in Promise methods and existing properties\n\t\t\tif (prop === \"constructor\" || prop in target) {\n\t\t\t\tconst value = Reflect.get(target, prop, target);\n\t\t\t\t// Preserve method binding\n\t\t\t\tif (typeof value === \"function\") {\n\t\t\t\t\treturn value.bind(target);\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t\t// Create action function that preserves 'this' context\n\t\t\tif (typeof prop === \"string\") {\n\t\t\t\t// If JS is attempting to calling this as a promise, ignore it\n\t\t\t\tif (prop === \"then\") return undefined;\n\n\t\t\t\tlet method = methodCache.get(prop);\n\t\t\t\tif (!method) {\n\t\t\t\t\tmethod = (...args: unknown[]) =>\n\t\t\t\t\t\ttarget.action({ name: prop, args });\n\t\t\t\t\tmethodCache.set(prop, method);\n\t\t\t\t}\n\t\t\t\treturn method;\n\t\t\t}\n\t\t},\n\n\t\t// Support for 'in' operator\n\t\thas(target: ActorHandleRaw, prop: string | symbol) {\n\t\t\t// All string properties are potentially action functions.\n\t\t\tif (typeof prop === \"string\") return true;\n\t\t\t// For symbols, defer to the target's own has behavior\n\t\t\treturn Reflect.has(target, prop);\n\t\t},\n\n\t\t// Support instanceof checks\n\t\tgetPrototypeOf(target: ActorHandleRaw) {\n\t\t\treturn Reflect.getPrototypeOf(target);\n\t\t},\n\n\t\t// Prevent property enumeration of non-existent action methods\n\t\townKeys(target: ActorHandleRaw) {\n\t\t\treturn Reflect.ownKeys(target);\n\t\t},\n\n\t\t// Support proper property descriptors\n\t\tgetOwnPropertyDescriptor(\n\t\t\ttarget: ActorHandleRaw,\n\t\t\tprop: string | symbol,\n\t\t) {\n\t\t\tconst targetDescriptor = Reflect.getOwnPropertyDescriptor(\n\t\t\t\ttarget,\n\t\t\t\tprop,\n\t\t\t);\n\t\t\tif (targetDescriptor) {\n\t\t\t\treturn targetDescriptor;\n\t\t\t}\n\t\t\tif (typeof prop === \"string\") {\n\t\t\t\t// Make action methods appear non-enumerable\n\t\t\t\treturn {\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\tenumerable: false,\n\t\t\t\t\twritable: false,\n\t\t\t\t\tvalue: (...args: unknown[]) =>\n\t\t\t\t\t\ttarget.action({ name: prop, args }),\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn undefined;\n\t\t},\n\t}) as ActorHandle<AD> | ActorConn<AD>;\n}\n","import z from \"zod/v4\";\nimport { EncodingSchema } from \"@/actor/protocol/serde\";\nimport { type GetUpgradeWebSocket } from \"@/utils\";\nimport {\n\tgetRivetEngine,\n\tgetRivetEndpoint,\n\tgetRivetToken,\n\tgetRivetNamespace,\n\tgetRivetRunner,\n} from \"@/utils/env-vars\";\nimport type { RegistryConfig } from \"@/registry/config\";\nimport { tryParseEndpoint } from \"@/utils/endpoint-parser\";\n\n/**\n * Gets the default endpoint for the client.\n *\n * In browser: uses current origin + /api/rivet\n *\n * Server-side: uses 127.0.0.1:6420\n */\nfunction getDefaultEndpoint(): string {\n\tif (typeof window !== \"undefined\" && window.location?.origin) {\n\t\treturn `${window.location.origin}/api/rivet`;\n\t}\n\treturn \"http://127.0.0.1:6420\";\n}\n\n/**\n * Base client config schema without transforms so it can be merged in to other schemas.\n */\nexport const ClientConfigSchemaBase = z.object({\n\t/**\n\t * Endpoint to connect to for Rivet Engine or RivetKit manager API.\n\t *\n\t * Supports URL auth syntax for namespace and token:\n\t * - `https://namespace:token@api.rivet.dev`\n\t * - `https://namespace@api.rivet.dev`\n\t *\n\t * Can also be set via RIVET_ENDPOINT environment variables.\n\t *\n\t * Defaults to current origin + /api/rivet in browser, or 127.0.0.1:6420 server-side.\n\t */\n\tendpoint: z\n\t\t.string()\n\t\t.optional()\n\t\t.transform(\n\t\t\t(val) =>\n\t\t\t\tval ??\n\t\t\t\tgetRivetEngine() ??\n\t\t\t\tgetRivetEndpoint() ??\n\t\t\t\tgetDefaultEndpoint(),\n\t\t),\n\n\t/** Token to use to authenticate with the API. */\n\ttoken: z\n\t\t.string()\n\t\t.optional()\n\t\t.transform((val) => val ?? getRivetToken()),\n\n\t/** Namespace to connect to. */\n\tnamespace: z\n\t\t.string()\n\t\t.optional()\n\t\t.transform((val) => val ?? getRivetNamespace()),\n\n\t/** Name of the runner. This is used to group together runners in to different pools. */\n\trunnerName: z.string().default(() => getRivetRunner() ?? \"default\"),\n\n\tencoding: EncodingSchema.default(\"bare\"),\n\n\theaders: z\n\t\t.record(z.string(), z.string())\n\t\t.optional()\n\t\t.default(() => ({})),\n\n\t// See RunConfig.getUpgradeWebSocket\n\t//\n\t// This is required in the client config in order to support\n\t// `proxyWebSocket`\n\tgetUpgradeWebSocket: z.custom<GetUpgradeWebSocket>().optional(),\n\n\t/** Whether to automatically perform health checks when the client is created. */\n\tdisableMetadataLookup: z.boolean().optional().default(false),\n\n\t/** Whether to enable RivetKit Devtools integration. */\n\tdevtools: z\n\t\t.boolean()\n\t\t.default(\n\t\t\t() =>\n\t\t\t\ttypeof window !== \"undefined\" &&\n\t\t\t\t(window?.location?.hostname === \"127.0.0.1\" ||\n\t\t\t\t\twindow.location?.hostname === \"localhost\"),\n\t\t),\n});\n\nexport const ClientConfigSchema = ClientConfigSchemaBase.transform(\n\t(config, ctx) => transformClientConfig(config, ctx),\n);\n\nexport type ClientConfig = z.infer<typeof ClientConfigSchema>;\n\nexport type ClientConfigInput = z.input<typeof ClientConfigSchema>;\n\nexport function transformClientConfig(\n\tconfig: z.infer<typeof ClientConfigSchemaBase>,\n\tctx: z.RefinementCtx,\n) {\n\tconst parsedEndpoint = tryParseEndpoint(ctx, {\n\t\tendpoint: config.endpoint,\n\t\tpath: [\"endpoint\"],\n\t\tnamespace: config.namespace,\n\t\ttoken: config.token,\n\t});\n\n\treturn {\n\t\t...config,\n\t\tendpoint: parsedEndpoint?.endpoint,\n\t\tnamespace: parsedEndpoint?.namespace ?? config.namespace ?? \"default\",\n\t\ttoken: parsedEndpoint?.token ?? config.token,\n\t};\n}\n\n/**\n * Converts a base config in to a client config.\n *\n * The base config does not include all of the properties of the client config,\n * so this converts the subset of properties in to the client config.\n *\n * Note: We construct the object directly rather than using ClientConfigSchema.parse()\n * because RegistryConfig has already transformed the endpoint, namespace, and token.\n * Re-parsing would attempt to extract namespace/token from the endpoint URL again.\n */\nexport function convertRegistryConfigToClientConfig(\n\tconfig: RegistryConfig,\n): ClientConfig {\n\treturn {\n\t\tendpoint: config.endpoint,\n\t\ttoken: config.token,\n\t\tnamespace: config.namespace,\n\t\trunnerName: config.runner.runnerName,\n\t\theaders: config.headers,\n\t\tencoding: \"bare\",\n\t\tgetUpgradeWebSocket: undefined,\n\t\t// We don't need health checks for internal clients\n\t\tdisableMetadataLookup: true,\n\t\tdevtools:\n\t\t\ttypeof window !== \"undefined\" &&\n\t\t\t(window?.location?.hostname === \"127.0.0.1\" ||\n\t\t\t\twindow?.location?.hostname === \"localhost\"),\n\t};\n}\n","import { injectDevtools } from \"@/devtools-loader\";\nimport type { Registry } from \"@/registry\";\nimport { RemoteManagerDriver } from \"@/remote-manager-driver/mod\";\nimport {\n\ttype Client,\n\ttype ClientConfigInput,\n\tcreateClientWithDriver,\n} from \"./client\";\nimport { ClientConfigSchema } from \"./config\";\n\nexport type { ActorDefinition, AnyActorDefinition } from \"@/actor/definition\";\nexport type { Encoding } from \"@/actor/protocol/serde\";\nexport {\n\tActorClientError,\n\tActorConnDisposed,\n\tActorError,\n\tInternalError,\n\tMalformedResponseMessage,\n\tManagerError,\n} from \"@/client/errors\";\nexport type { CreateRequest } from \"@/manager/protocol/query\";\nexport { KEYS as KV_KEYS } from \"../actor/instance/keys\";\nexport type { ActorActionFunction } from \"./actor-common\";\nexport type {\n\tActorConn,\n\tActorConnStatus,\n\tConnectionStateCallback,\n\tEventUnsubscribe,\n\tStatusChangeCallback,\n} from \"./actor-conn\";\nexport { ActorConnRaw } from \"./actor-conn\";\nexport type { ActorHandle } from \"./actor-handle\";\nexport { ActorHandleRaw } from \"./actor-handle\";\nexport type {\n\tActorAccessor,\n\tClient,\n\tClientRaw,\n\tCreateOptions,\n\tExtractActorsFromRegistry,\n\tExtractRegistryFromClient,\n\tGetOptions,\n\tGetWithIdOptions,\n\tQueryOptions,\n\tRegion,\n} from \"./client\";\n\n/**\n * Creates a client with the actor accessor proxy.\n */\nexport function createClient<A extends Registry<any>>(\n\tendpointOrConfig?: string | ClientConfigInput,\n): Client<A> {\n\t// Parse config\n\tconst configInput =\n\t\tendpointOrConfig === undefined\n\t\t\t? {}\n\t\t\t: typeof endpointOrConfig === \"string\"\n\t\t\t\t? { endpoint: endpointOrConfig }\n\t\t\t\t: endpointOrConfig;\n\tconst config = ClientConfigSchema.parse(configInput);\n\n\t// Create client\n\tconst driver = new RemoteManagerDriver(config);\n\n\tif (config.devtools) {\n\t\tinjectDevtools(config);\n\t}\n\n\treturn createClientWithDriver<A>(driver, config);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/rivet/rivet/rivetkit-typescript/packages/rivetkit/dist/tsup/chunk-HPAX7L72.cjs","../../src/devtools-loader/log.ts","../../src/devtools-loader/index.ts","../../src/remote-manager-driver/mod.ts","../../src/remote-manager-driver/api-utils.ts","../../src/client/utils.ts","../../src/client/errors.ts","../../src/remote-manager-driver/log.ts","../../src/remote-manager-driver/actor-websocket-client.ts","../../src/remote-manager-driver/actor-http-client.ts","../../src/remote-manager-driver/api-endpoints.ts","../../src/remote-manager-driver/metadata.ts","../../src/remote-manager-driver/ws-proxy.ts","../../src/client/actor-conn.ts","../../src/client/actor-query.ts","../../src/client/queue.ts","../../src/client/actor-handle.ts","../../src/client/raw-utils.ts","../../src/client/client.ts","../../src/client/config.ts","../../src/client/mod.ts"],"names":["logger","WebSocket","id"],"mappings":"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","file":"/home/runner/work/rivet/rivet/rivetkit-typescript/packages/rivetkit/dist/tsup/chunk-HPAX7L72.cjs","sourcesContent":[null,"import { getLogger } from \"@/common/log\";\n\nexport function logger() {\n\treturn getLogger(\"devtools\");\n}\n","import type { ClientConfigInput } from \"@/client/client\";\nimport { VERSION } from \"@/utils\";\nimport { logger } from \"./log\";\n\ndeclare global {\n\t// Injected via tsup config\n\t// biome-ignore lint/style/noVar: required for global declaration\n\tvar CUSTOM_RIVETKIT_DEVTOOLS_URL: string | undefined;\n}\n\nconst DEFAULT_DEVTOOLS_URL = (version = VERSION) =>\n\t`https://releases.rivet.dev/rivet/latest/devtools/mod.js?v=${version}`;\n\nconst scriptId = \"rivetkit-devtools-script\";\n\nexport function injectDevtools(config: ClientConfigInput) {\n\tif (!window) {\n\t\tlogger().warn(\"devtools not available outside browser environment\");\n\t\treturn;\n\t}\n\n\tif (!document.getElementById(scriptId)) {\n\t\tconst script = document.createElement(\"script\");\n\t\tscript.id = scriptId;\n\t\tscript.src =\n\t\t\tglobalThis.CUSTOM_RIVETKIT_DEVTOOLS_URL || DEFAULT_DEVTOOLS_URL();\n\t\tscript.async = true;\n\t\tdocument.head.appendChild(script);\n\t}\n\n\twindow.__rivetkit = window.__rivetkit || [];\n\twindow.__rivetkit.push(config);\n}\n","import * as cbor from \"cbor-x\";\nimport type { Context as HonoContext } from \"hono\";\nimport invariant from \"invariant\";\nimport { deserializeActorKey, serializeActorKey } from \"@/actor/keys\";\nimport type { ClientConfig } from \"@/client/client\";\nimport { noopNext } from \"@/common/utils\";\nimport type {\n\tActorOutput,\n\tCreateInput,\n\tGetForIdInput,\n\tGetOrCreateWithKeyInput,\n\tGetWithKeyInput,\n\tListActorsInput,\n\tManagerDisplayInformation,\n\tManagerDriver,\n} from \"@/driver-helpers/mod\";\nimport type { Actor as ApiActor } from \"@/manager-api/actors\";\nimport type { Encoding, UniversalWebSocket } from \"@/mod\";\nimport { uint8ArrayToBase64 } from \"@/serde\";\nimport { combineUrlPath, type GetUpgradeWebSocket } from \"@/utils\";\nimport { getNextPhase } from \"@/utils/env-vars\";\nimport { sendHttpRequestToActor } from \"./actor-http-client\";\nimport {\n\tbuildActorGatewayUrl,\n\tbuildWebSocketProtocols,\n\topenWebSocketToActor,\n} from \"./actor-websocket-client\";\nimport {\n\tcreateActor,\n\tdestroyActor,\n\tgetActor,\n\tgetActorByKey,\n\tgetOrCreateActor,\n\tkvGet,\n\tlistActorsByName,\n} from \"./api-endpoints\";\nimport { EngineApiError, getEndpoint } from \"./api-utils\";\nimport { logger } from \"./log\";\nimport { lookupMetadataCached } from \"./metadata\";\nimport { createWebSocketProxy } from \"./ws-proxy\";\n\n// TODO:\n// // Lazily import the dynamic imports so we don't have to turn `createClient` in to an async fn\n// const dynamicImports = (async () => {\n// \t// Import dynamic dependencies\n// \tconst [WebSocket, EventSource] = await Promise.all([\n// \t\timportWebSocket(),\n// \t\timportEventSource(),\n// \t]);\n// \treturn {\n// \t\tWebSocket,\n// \t\tEventSource,\n// \t};\n// })();\n\nexport class RemoteManagerDriver implements ManagerDriver {\n\t#config: ClientConfig;\n\t#metadataPromise: Promise<void> | undefined;\n\n\tconstructor(runConfig: ClientConfig) {\n\t\t// Disable health check if in Next.js build phase since there is no `/metadata` endpoint\n\t\t//\n\t\t// See https://github.com/vercel/next.js/blob/5e6b008b561caf2710ab7be63320a3d549474a5b/packages/next/shared/lib/constants.ts#L19-L23\n\t\tif (getNextPhase() === \"phase-production-build\") {\n\t\t\tlogger().info(\n\t\t\t\t\"detected next.js build phase, disabling health check\",\n\t\t\t);\n\t\t\trunConfig.disableMetadataLookup = true;\n\t\t}\n\n\t\t// Clone config so we can mutate the endpoint in #metadataPromise\n\t\t// NOTE: This is a shallow clone, so mutating nested properties will not do anything\n\t\tthis.#config = { ...runConfig };\n\n\t\t// Perform metadata check if enabled\n\t\tif (!runConfig.disableMetadataLookup) {\n\t\t\t// This should never error, since it uses pRetry. If it does for\n\t\t\t// any reason, we'll surface the error anywhere #metadataPromise is\n\t\t\t// awaited.\n\t\t\tthis.#metadataPromise = lookupMetadataCached(this.#config).then(\n\t\t\t\t(metadataData) => {\n\t\t\t\t\t// Override endpoint for all future requests\n\t\t\t\t\tif (metadataData.clientEndpoint) {\n\t\t\t\t\t\tthis.#config.endpoint = metadataData.clientEndpoint;\n\t\t\t\t\t\tif (metadataData.clientNamespace) {\n\t\t\t\t\t\t\tthis.#config.namespace =\n\t\t\t\t\t\t\t\tmetadataData.clientNamespace;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (metadataData.clientToken) {\n\t\t\t\t\t\t\tthis.#config.token = metadataData.clientToken;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlogger().info({\n\t\t\t\t\t\t\tmsg: \"overriding client endpoint\",\n\t\t\t\t\t\t\tendpoint: metadataData.clientEndpoint,\n\t\t\t\t\t\t\tnamespace: metadataData.clientNamespace,\n\t\t\t\t\t\t\ttoken: metadataData.clientToken,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tlogger().info({\n\t\t\t\t\t\tmsg: \"connected to rivetkit manager\",\n\t\t\t\t\t\truntime: metadataData.runtime,\n\t\t\t\t\t\tversion: metadataData.version,\n\t\t\t\t\t\trunner: metadataData.runner,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\n\tasync getForId({\n\t\tc,\n\t\tname,\n\t\tactorId,\n\t}: GetForIdInput): Promise<ActorOutput | undefined> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\t// Fetch from API if not in cache\n\t\tconst response = await getActor(this.#config, name, actorId);\n\t\tconst actor = response.actors[0];\n\t\tif (!actor) return undefined;\n\n\t\t// Validate name matches\n\t\tif (actor.name !== name) {\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"actor name mismatch from api\",\n\t\t\t\tactorId,\n\t\t\t\tapiName: actor.name,\n\t\t\t\trequestedName: name,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn apiActorToOutput(actor);\n\t}\n\n\tasync getWithKey({\n\t\tc,\n\t\tname,\n\t\tkey,\n\t}: GetWithKeyInput): Promise<ActorOutput | undefined> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\tlogger().debug({ msg: \"getWithKey: searching for actor\", name, key });\n\n\t\t// If not in local cache, fetch by key from API\n\t\ttry {\n\t\t\tconst response = await getActorByKey(this.#config, name, key);\n\t\t\tconst actor = response.actors[0];\n\t\t\tif (!actor) return undefined;\n\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"getWithKey: found actor via api\",\n\t\t\t\tactorId: actor.actor_id,\n\t\t\t\tname,\n\t\t\t\tkey,\n\t\t\t});\n\n\t\t\treturn apiActorToOutput(actor);\n\t\t} catch (error) {\n\t\t\tif (\n\t\t\t\terror instanceof EngineApiError &&\n\t\t\t\t(error as EngineApiError).group === \"actor\" &&\n\t\t\t\t(error as EngineApiError).code === \"not_found\"\n\t\t\t) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync getOrCreateWithKey(\n\t\tinput: GetOrCreateWithKeyInput,\n\t): Promise<ActorOutput> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\tconst { c, name, key, input: actorInput, region } = input;\n\n\t\tlogger().info({\n\t\t\tmsg: \"getOrCreateWithKey: getting or creating actor via engine api\",\n\t\t\tname,\n\t\t\tkey,\n\t\t});\n\n\t\tconst { actor, created } = await getOrCreateActor(this.#config, {\n\t\t\tdatacenter: region,\n\t\t\tname,\n\t\t\tkey: serializeActorKey(key),\n\t\t\trunner_name_selector: this.#config.runnerName,\n\t\t\tinput: actorInput\n\t\t\t\t? uint8ArrayToBase64(cbor.encode(actorInput))\n\t\t\t\t: undefined,\n\t\t\tcrash_policy: \"sleep\",\n\t\t});\n\n\t\tlogger().info({\n\t\t\tmsg: \"getOrCreateWithKey: actor ready\",\n\t\t\tactorId: actor.actor_id,\n\t\t\tname,\n\t\t\tkey,\n\t\t\tcreated,\n\t\t});\n\n\t\treturn apiActorToOutput(actor);\n\t}\n\n\tasync createActor({\n\t\tc,\n\t\tname,\n\t\tkey,\n\t\tinput,\n\t\tregion,\n\t}: CreateInput): Promise<ActorOutput> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\tlogger().info({ msg: \"creating actor via engine api\", name, key });\n\n\t\t// Create actor via engine API\n\t\tconst result = await createActor(this.#config, {\n\t\t\tdatacenter: region,\n\t\t\tname,\n\t\t\trunner_name_selector: this.#config.runnerName,\n\t\t\tkey: serializeActorKey(key),\n\t\t\tinput: input ? uint8ArrayToBase64(cbor.encode(input)) : undefined,\n\t\t\tcrash_policy: \"sleep\",\n\t\t});\n\n\t\tlogger().info({\n\t\t\tmsg: \"actor created\",\n\t\t\tactorId: result.actor.actor_id,\n\t\t\tname,\n\t\t\tkey,\n\t\t});\n\n\t\treturn apiActorToOutput(result.actor);\n\t}\n\n\tasync listActors({ c, name }: ListActorsInput): Promise<ActorOutput[]> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\tlogger().debug({ msg: \"listing actors via engine api\", name });\n\n\t\tconst response = await listActorsByName(this.#config, name);\n\n\t\treturn response.actors.map(apiActorToOutput);\n\t}\n\n\tasync destroyActor(actorId: string): Promise<void> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\tlogger().info({ msg: \"destroying actor via engine api\", actorId });\n\n\t\tawait destroyActor(this.#config, actorId);\n\n\t\tlogger().info({ msg: \"actor destroyed\", actorId });\n\t}\n\n\tasync sendRequest(\n\t\tactorId: string,\n\t\tactorRequest: Request,\n\t): Promise<Response> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\treturn await sendHttpRequestToActor(\n\t\t\tthis.#config,\n\t\t\tactorId,\n\t\t\tactorRequest,\n\t\t);\n\t}\n\n\tasync openWebSocket(\n\t\tpath: string,\n\t\tactorId: string,\n\t\tencoding: Encoding,\n\t\tparams: unknown,\n\t): Promise<UniversalWebSocket> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\treturn await openWebSocketToActor(\n\t\t\tthis.#config,\n\t\t\tpath,\n\t\t\tactorId,\n\t\t\tencoding,\n\t\t\tparams,\n\t\t);\n\t}\n\n\tasync buildGatewayUrl(actorId: string): Promise<string> {\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\tconst endpoint = getEndpoint(this.#config);\n\t\treturn buildActorGatewayUrl(endpoint, actorId, this.#config.token);\n\t}\n\n\tasync proxyRequest(\n\t\t_c: HonoContext,\n\t\tactorRequest: Request,\n\t\tactorId: string,\n\t): Promise<Response> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\treturn await sendHttpRequestToActor(\n\t\t\tthis.#config,\n\t\t\tactorId,\n\t\t\tactorRequest,\n\t\t);\n\t}\n\n\tasync proxyWebSocket(\n\t\tc: HonoContext,\n\t\tpath: string,\n\t\tactorId: string,\n\t\tencoding: Encoding,\n\t\tparams: unknown,\n\t): Promise<Response> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\tconst upgradeWebSocket = this.#config.getUpgradeWebSocket?.();\n\t\tinvariant(upgradeWebSocket, \"missing getUpgradeWebSocket\");\n\n\t\tconst endpoint = getEndpoint(this.#config);\n\t\tconst guardUrl = combineUrlPath(endpoint, path);\n\t\tconst wsGuardUrl = guardUrl.replace(\"http://\", \"ws://\");\n\n\t\tlogger().debug({\n\t\t\tmsg: \"forwarding websocket to actor via guard\",\n\t\t\tactorId,\n\t\t\tpath,\n\t\t\tguardUrl,\n\t\t});\n\n\t\t// Build protocols\n\t\tconst protocols = buildWebSocketProtocols(\n\t\t\tthis.#config,\n\t\t\tencoding,\n\t\t\tparams,\n\t\t);\n\t\tconst args = await createWebSocketProxy(c, wsGuardUrl, protocols);\n\n\t\treturn await upgradeWebSocket(() => args)(c, noopNext());\n\t}\n\n\tasync kvGet(actorId: string, key: Uint8Array): Promise<string | null> {\n\t\t// Wait for metadata check to complete if in progress\n\t\tif (this.#metadataPromise) {\n\t\t\tawait this.#metadataPromise;\n\t\t}\n\n\t\tlogger().debug({ msg: \"getting kv value via engine api\", key });\n\n\t\tconst response = await kvGet(\n\t\t\tthis.#config,\n\t\t\tactorId,\n\t\t\tnew TextDecoder(\"utf8\").decode(key),\n\t\t);\n\n\t\treturn response.value;\n\t}\n\n\tdisplayInformation(): ManagerDisplayInformation {\n\t\treturn { properties: {} };\n\t}\n\n\tsetGetUpgradeWebSocket(getUpgradeWebSocket: GetUpgradeWebSocket): void {\n\t\tthis.#config.getUpgradeWebSocket = getUpgradeWebSocket;\n\t}\n}\n\nfunction apiActorToOutput(actor: ApiActor): ActorOutput {\n\treturn {\n\t\tactorId: actor.actor_id,\n\t\tname: actor.name,\n\t\tkey: deserializeActorKey(actor.key),\n\t\tcreateTs: actor.create_ts,\n\t\tstartTs: actor.start_ts ?? null,\n\t\tconnectableTs: actor.connectable_ts ?? null,\n\t\tsleepTs: actor.sleep_ts ?? null,\n\t\tdestroyTs: actor.destroy_ts ?? null,\n\t\terror: actor.error ?? undefined,\n\t};\n}\n","import { z } from \"zod/v4\";\nimport type { ClientConfig } from \"@/client/config\";\nimport { sendHttpRequest } from \"@/client/utils\";\nimport { combineUrlPath } from \"@/utils\";\nimport { logger } from \"./log\";\nimport { RegistryConfig } from \"@/registry/config\";\n\n// Error class for Engine API errors\nexport class EngineApiError extends Error {\n\tconstructor(\n\t\tpublic readonly group: string,\n\t\tpublic readonly code: string,\n\t\tmessage?: string,\n\t) {\n\t\tsuper(message || `Engine API error: ${group}/${code}`);\n\t\tthis.name = \"EngineApiError\";\n\t}\n}\n\n// TODO: Remove getEndpoint, but it's used in a lot of places\nexport function getEndpoint(config: ClientConfig | RegistryConfig) {\n\t// Endpoint is always defined for ClientConfig (has default in schema).\n\t// RegistryConfig may not have endpoint if using local manager.\n\treturn config.endpoint ?? \"http://127.0.0.1:6420\";\n}\n\n// Helper function for making API calls\nexport async function apiCall<TInput = unknown, TOutput = unknown>(\n\tconfig: ClientConfig,\n\tmethod: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\",\n\tpath: string,\n\tbody?: TInput,\n): Promise<TOutput> {\n\tconst endpoint = getEndpoint(config);\n\tconst url = combineUrlPath(endpoint, path, {\n\t\tnamespace: config.namespace,\n\t});\n\n\tlogger().debug({ msg: \"making api call\", method, url });\n\n\tconst headers: Record<string, string> = {\n\t\t...config.headers,\n\t};\n\n\t// Add Authorization header if token is provided\n\tif (config.token) {\n\t\theaders.Authorization = `Bearer ${config.token}`;\n\t}\n\n\treturn await sendHttpRequest<TInput, TOutput>({\n\t\tmethod,\n\t\turl,\n\t\theaders,\n\t\tbody,\n\t\tencoding: \"json\",\n\t\tskipParseResponse: false,\n\t\trequestVersionedDataHandler: undefined,\n\t\trequestVersion: undefined,\n\t\tresponseVersionedDataHandler: undefined,\n\t\tresponseVersion: undefined,\n\t\trequestZodSchema: z.any() as z.ZodType<TInput>,\n\t\tresponseZodSchema: z.any() as z.ZodType<TOutput>,\n\t\t// Identity conversions (passthrough for generic API calls)\n\t\trequestToJson: (value) => value,\n\t\trequestToBare: (value) => value,\n\t\tresponseFromJson: (value) => value,\n\t\tresponseFromBare: (value) => value,\n\t});\n}\n","import * as cbor from \"cbor-x\";\nimport invariant from \"invariant\";\nimport type { VersionedDataHandler } from \"vbare\";\nimport type { z } from \"zod/v4\";\nimport type { Encoding } from \"@/actor/protocol/serde\";\nimport { assertUnreachable } from \"@/common/utils\";\nimport type { HttpResponseError } from \"@/schemas/client-protocol/mod\";\nimport { HTTP_RESPONSE_ERROR_VERSIONED } from \"@/schemas/client-protocol/versioned\";\nimport {\n\ttype HttpResponseError as HttpResponseErrorJson,\n\tHttpResponseErrorSchema,\n} from \"@/schemas/client-protocol-zod/mod\";\nimport {\n\tcontentTypeForEncoding,\n\tdeserializeWithEncoding,\n\tencodingIsBinary,\n\tserializeWithEncoding,\n} from \"@/serde\";\nimport { httpUserAgent } from \"@/utils\";\nimport { ActorError, HttpRequestError } from \"./errors\";\nimport { logger } from \"./log\";\n\nexport interface ParsedCloseReason {\n\tgroup: string;\n\tcode: string;\n\trayId?: string;\n}\n\n/**\n * Parses WebSocket close reason string into structured data.\n *\n * Expected format examples:\n * - \"guard.actor_runner_failed#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, code] = mainPart.split(\".\");\n\n\tif (!group || !code) {\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\tcode,\n\t\trayId,\n\t};\n}\n\nexport type WebSocketMessage = string | Blob | ArrayBuffer | Uint8Array;\n\nexport function messageLength(message: WebSocketMessage): number {\n\tif (message instanceof Blob) {\n\t\treturn message.size;\n\t}\n\tif (message instanceof ArrayBuffer) {\n\t\treturn message.byteLength;\n\t}\n\tif (message instanceof Uint8Array) {\n\t\treturn message.byteLength;\n\t}\n\tif (typeof message === \"string\") {\n\t\treturn message.length;\n\t}\n\tassertUnreachable(message);\n}\n\nexport interface HttpRequestOpts<\n\tRequestBare,\n\tResponseBare,\n\tRequestJson = RequestBare,\n\tResponseJson = ResponseBare,\n\tRequest = RequestBare,\n\tResponse = ResponseBare,\n> {\n\tmethod: string;\n\turl: string;\n\theaders: Record<string, string>;\n\tbody?: Request;\n\tencoding: Encoding;\n\tskipParseResponse?: boolean;\n\tsignal?: AbortSignal;\n\tcustomFetch?: (req: globalThis.Request) => Promise<globalThis.Response>;\n\trequestVersionedDataHandler: VersionedDataHandler<RequestBare> | undefined;\n\trequestVersion: number | undefined;\n\tresponseVersionedDataHandler:\n\t\t| VersionedDataHandler<ResponseBare>\n\t\t| undefined;\n\tresponseVersion: number | undefined;\n\trequestZodSchema: z.ZodType<RequestJson>;\n\tresponseZodSchema: z.ZodType<ResponseJson>;\n\trequestToJson: (value: Request) => RequestJson;\n\trequestToBare: (value: Request) => RequestBare;\n\tresponseFromJson: (value: ResponseJson) => Response;\n\tresponseFromBare: (value: ResponseBare) => Response;\n}\n\nexport async function sendHttpRequest<\n\tRequestBare = unknown,\n\tResponseBare = unknown,\n\tRequestJson = RequestBare,\n\tResponseJson = ResponseBare,\n\tRequest = RequestBare,\n\tResponse = ResponseBare,\n>(\n\topts: HttpRequestOpts<\n\t\tRequestBare,\n\t\tResponseBare,\n\t\tRequestJson,\n\t\tResponseJson,\n\t\tRequest,\n\t\tResponse\n\t>,\n): Promise<Response> {\n\tlogger().debug({\n\t\tmsg: \"sending http request\",\n\t\turl: opts.url,\n\t\tencoding: opts.encoding,\n\t});\n\n\t// Serialize body\n\tlet contentType: string | undefined;\n\tlet bodyData: string | Uint8Array | undefined;\n\tif (opts.method === \"POST\" || opts.method === \"PUT\") {\n\t\tinvariant(opts.body !== undefined, \"missing body\");\n\t\tcontentType = contentTypeForEncoding(opts.encoding);\n\t\tbodyData = serializeWithEncoding<RequestBare, RequestJson, Request>(\n\t\t\topts.encoding,\n\t\t\topts.body,\n\t\t\topts.requestVersionedDataHandler,\n\t\t\topts.requestVersion,\n\t\t\topts.requestZodSchema,\n\t\t\topts.requestToJson,\n\t\t\topts.requestToBare,\n\t\t);\n\t}\n\n\t// Send request\n\tlet response: globalThis.Response;\n\ttry {\n\t\t// Make the HTTP request\n\t\tresponse = await (opts.customFetch ?? fetch)(\n\t\t\tnew globalThis.Request(opts.url, {\n\t\t\t\tmethod: opts.method,\n\t\t\t\theaders: {\n\t\t\t\t\t...opts.headers,\n\t\t\t\t\t...(contentType\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\"Content-Type\": contentType,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {}),\n\t\t\t\t\t\"User-Agent\": httpUserAgent(),\n\t\t\t\t},\n\t\t\t\tbody: bodyData,\n\t\t\t\tcredentials: \"include\",\n\t\t\t\tsignal: opts.signal,\n\t\t\t}),\n\t\t);\n\t} catch (error) {\n\t\tthrow new HttpRequestError(`Request failed: ${error}`, {\n\t\t\tcause: error,\n\t\t});\n\t}\n\n\t// Parse response error\n\tif (!response.ok) {\n\t\tconst bufferResponse = await response.arrayBuffer();\n\t\tconst contentType = response.headers.get(\"content-type\");\n\t\tconst rayId = response.headers.get(\"x-rivet-ray-id\");\n\n\t\t// Determine encoding from Content-Type header, defaulting to provided encoding\n\t\tconst encoding: Encoding = contentType?.includes(\"application/json\")\n\t\t\t? \"json\"\n\t\t\t: opts.encoding;\n\n\t\t// Attempt to parse structured error data\n\t\ttry {\n\t\t\tconst responseData = deserializeWithEncoding(\n\t\t\t\tencoding,\n\t\t\t\tnew Uint8Array(bufferResponse),\n\t\t\t\tHTTP_RESPONSE_ERROR_VERSIONED,\n\t\t\t\tHttpResponseErrorSchema,\n\t\t\t\t// JSON: metadata is already unknown\n\t\t\t\t(json): HttpResponseErrorJson => json as HttpResponseErrorJson,\n\t\t\t\t// BARE: decode ArrayBuffer metadata to unknown\n\t\t\t\t(bare): any => ({\n\t\t\t\t\tgroup: bare.group,\n\t\t\t\t\tcode: bare.code,\n\t\t\t\t\tmessage: bare.message,\n\t\t\t\t\tmetadata: bare.metadata\n\t\t\t\t\t\t? cbor.decode(new Uint8Array(bare.metadata))\n\t\t\t\t\t\t: undefined,\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\tthrow new ActorError(\n\t\t\t\tresponseData.group,\n\t\t\t\tresponseData.code,\n\t\t\t\tresponseData.message,\n\t\t\t\tresponseData.metadata,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\t// If it's already an ActorError, re-throw it\n\t\t\tif (error instanceof ActorError) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\t// Otherwise, fall back to generic error with text response\n\t\t\tconst textResponse = new TextDecoder(\"utf-8\", {\n\t\t\t\tfatal: false,\n\t\t\t}).decode(bufferResponse);\n\n\t\t\tif (rayId) {\n\t\t\t\tthrow new HttpRequestError(\n\t\t\t\t\t`${response.statusText} (${response.status}) (Ray ID: ${rayId}):\\n${textResponse}`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthrow new HttpRequestError(\n\t\t\t\t\t`${response.statusText} (${response.status}):\\n${textResponse}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Some requests don't need the success response to be parsed, so this can speed things up\n\tif (opts.skipParseResponse) {\n\t\treturn undefined as Response;\n\t}\n\n\t// Parse the response based on encoding\n\ttry {\n\t\tconst buffer = new Uint8Array(await response.arrayBuffer());\n\t\treturn deserializeWithEncoding<ResponseBare, ResponseJson, Response>(\n\t\t\topts.encoding,\n\t\t\tbuffer,\n\t\t\topts.responseVersionedDataHandler,\n\t\t\topts.responseZodSchema,\n\t\t\topts.responseFromJson,\n\t\t\topts.responseFromBare,\n\t\t);\n\t} catch (error) {\n\t\tthrow new HttpRequestError(`Failed to parse response: ${error}`, {\n\t\t\tcause: error,\n\t\t});\n\t}\n}\n","export class ActorClientError extends Error {}\n\nexport class InternalError extends ActorClientError {}\n\nexport class ManagerError extends ActorClientError {\n\tconstructor(error: string, opts?: ErrorOptions) {\n\t\tsuper(`Manager error: ${error}`, opts);\n\t}\n}\n\nexport class MalformedResponseMessage extends ActorClientError {\n\tconstructor(cause?: unknown) {\n\t\tsuper(`Malformed response message: ${cause}`, { cause });\n\t}\n}\n\nexport class ActorError extends ActorClientError {\n\t__type = \"ActorError\";\n\n\tconstructor(\n\t\tpublic readonly group: string,\n\t\tpublic readonly code: string,\n\t\tmessage: string,\n\t\tpublic readonly metadata?: unknown,\n\t) {\n\t\tsuper(message);\n\t}\n}\n\nexport class HttpRequestError extends ActorClientError {\n\tconstructor(message: string, opts?: { cause?: unknown }) {\n\t\tsuper(`HTTP request error: ${message}`, { cause: opts?.cause });\n\t}\n}\n\nexport class ActorConnDisposed extends ActorClientError {\n\tconstructor() {\n\t\tsuper(\"Attempting to interact with a disposed actor connection.\");\n\t}\n}\n\n/**\n * Checks if an error code indicates a scheduling error that may have more details.\n */\nexport function isSchedulingError(group: string, code: string): boolean {\n\treturn (\n\t\tgroup === \"guard\" &&\n\t\t(code === \"actor_ready_timeout\" || code === \"actor_runner_failed\")\n\t);\n}\n\n/**\n * Error thrown when actor scheduling fails.\n * Provides detailed information about why the actor failed to start.\n */\nexport class ActorSchedulingError extends ActorError {\n\tpublic readonly actorId: string;\n\tpublic readonly details: unknown;\n\n\tconstructor(\n\t\tgroup: string,\n\t\tcode: string,\n\t\tactorId: string,\n\t\tdetails: unknown,\n\t) {\n\t\tsuper(\n\t\t\tgroup,\n\t\t\tcode,\n\t\t\t`Actor failed to start (${actorId}): ${JSON.stringify(details)}`,\n\t\t\t{ actorId, details },\n\t\t);\n\t\tthis.name = \"ActorSchedulingError\";\n\t\tthis.actorId = actorId;\n\t\tthis.details = details;\n\t}\n}\n","import { getLogger } from \"@/common//log\";\n\nexport function logger() {\n\treturn getLogger(\"remote-manager-driver\");\n}\n","import type { ClientConfig } from \"@/client/config\";\nimport {\n\tHEADER_CONN_PARAMS,\n\tHEADER_ENCODING,\n\tWS_PROTOCOL_CONN_PARAMS,\n\tWS_PROTOCOL_ENCODING,\n\tWS_PROTOCOL_STANDARD as WS_PROTOCOL_RIVETKIT,\n\tWS_PROTOCOL_TOKEN,\n} from \"@/common/actor-router-consts\";\nimport { importWebSocket } from \"@/common/websocket\";\nimport type { Encoding, UniversalWebSocket } from \"@/mod\";\nimport { combineUrlPath } from \"@/utils\";\nimport { getEndpoint } from \"./api-utils\";\nimport { logger } from \"./log\";\n\nexport function buildActorGatewayUrl(\n\tendpoint: string,\n\tactorId: string,\n\ttoken: string | undefined,\n\tpath = \"\",\n): string {\n\tconst tokenSegment =\n\t\ttoken !== undefined ? `@${encodeURIComponent(token)}` : \"\";\n\tconst gatewayPath = `/gateway/${encodeURIComponent(actorId)}${tokenSegment}${path}`;\n\treturn combineUrlPath(endpoint, gatewayPath);\n}\n\nexport async function openWebSocketToActor(\n\trunConfig: ClientConfig,\n\tpath: string,\n\tactorId: string,\n\tencoding: Encoding,\n\tparams: unknown,\n): Promise<UniversalWebSocket> {\n\tconst WebSocket = await importWebSocket();\n\n\t// WebSocket connections go through guard\n\tconst endpoint = getEndpoint(runConfig);\n\tconst guardUrl = buildActorGatewayUrl(\n\t\tendpoint,\n\t\tactorId,\n\t\trunConfig.token,\n\t\tpath,\n\t);\n\n\tlogger().debug({\n\t\tmsg: \"opening websocket to actor via guard\",\n\t\tactorId,\n\t\tpath,\n\t\tguardUrl,\n\t});\n\n\t// Create WebSocket connection\n\tconst ws = new WebSocket(\n\t\tguardUrl,\n\t\tbuildWebSocketProtocols(runConfig, encoding, params),\n\t);\n\n\t// Set binary type to arraybuffer for proper encoding support\n\tws.binaryType = \"arraybuffer\";\n\n\tlogger().debug({ msg: \"websocket connection opened\", actorId });\n\n\treturn ws as UniversalWebSocket;\n}\n\nexport function buildWebSocketProtocols(\n\trunConfig: ClientConfig,\n\tencoding: Encoding,\n\tparams?: unknown,\n): string[] {\n\tconst protocols: string[] = [];\n\tprotocols.push(WS_PROTOCOL_RIVETKIT);\n\tprotocols.push(`${WS_PROTOCOL_ENCODING}${encoding}`);\n\tif (params) {\n\t\tprotocols.push(\n\t\t\t`${WS_PROTOCOL_CONN_PARAMS}${encodeURIComponent(JSON.stringify(params))}`,\n\t\t);\n\t}\n\treturn protocols;\n}\n","import type { ClientConfig } from \"@/client/config\";\nimport { HEADER_RIVET_TOKEN } from \"@/common/actor-router-consts\";\nimport { buildActorGatewayUrl } from \"./actor-websocket-client\";\nimport { getEndpoint } from \"./api-utils\";\n\nexport async function sendHttpRequestToActor(\n\trunConfig: ClientConfig,\n\tactorId: string,\n\tactorRequest: Request,\n): Promise<Response> {\n\t// Route through guard port\n\tconst url = new URL(actorRequest.url);\n\tconst endpoint = getEndpoint(runConfig);\n\tconst guardUrl = buildActorGatewayUrl(\n\t\tendpoint,\n\t\tactorId,\n\t\trunConfig.token,\n\t\t`${url.pathname}${url.search}`,\n\t);\n\n\t// Handle body properly based on method and presence\n\tlet bodyToSend: ArrayBuffer | null = null;\n\tconst guardHeaders = buildGuardHeadersForHttp(\n\t\trunConfig,\n\t\tactorRequest,\n\t\tactorId,\n\t);\n\n\tif (actorRequest.method !== \"GET\" && actorRequest.method !== \"HEAD\") {\n\t\tif (actorRequest.bodyUsed) {\n\t\t\tthrow new Error(\"Request body has already been consumed\");\n\t\t}\n\n\t\t// TODO: This buffers the entire request in memory every time. We\n\t\t// need to properly implement streaming bodies.\n\t\tconst reqBody = await actorRequest.arrayBuffer();\n\n\t\tif (reqBody.byteLength !== 0) {\n\t\t\tbodyToSend = reqBody;\n\n\t\t\t// If this is a streaming request, we need to convert the headers\n\t\t\t// for the basic array buffer\n\t\t\tguardHeaders.delete(\"transfer-encoding\");\n\t\t\tguardHeaders.set(\"content-length\", String(bodyToSend.byteLength));\n\t\t}\n\t}\n\n\tconst guardRequest = new Request(guardUrl, {\n\t\tmethod: actorRequest.method,\n\t\theaders: guardHeaders,\n\t\tbody: bodyToSend,\n\t\tsignal: actorRequest.signal,\n\t});\n\n\treturn mutableResponse(await fetch(guardRequest));\n}\n\nfunction mutableResponse(fetchRes: Response): Response {\n\t// We cannot return the raw response from `fetch` since the response type is not mutable.\n\t//\n\t// In order for middleware to be able to mutate the response, we need to build a new Response object that is mutable.\n\treturn new Response(fetchRes.body, fetchRes);\n}\n\nfunction buildGuardHeadersForHttp(\n\trunConfig: ClientConfig,\n\tactorRequest: Request,\n\tactorId: string,\n): Headers {\n\tconst headers = new Headers();\n\t// Copy all headers from the original request\n\tactorRequest.headers.forEach((value, key) => {\n\t\theaders.set(key, value);\n\t});\n\t// Add extra headers from config\n\tfor (const [key, value] of Object.entries(runConfig.headers)) {\n\t\theaders.set(key, value as string);\n\t}\n\t// Add guard-specific headers\n\tif (runConfig.token) {\n\t\theaders.set(HEADER_RIVET_TOKEN, runConfig.token);\n\t}\n\treturn headers;\n}\n","import { serializeActorKey } from \"@/actor/keys\";\nimport type { ClientConfig } from \"@/client/client\";\nimport type { MetadataResponse } from \"@/common/router\";\nimport type {\n\tActorsCreateRequest,\n\tActorsCreateResponse,\n\tActorsDeleteResponse,\n\tActorsGetOrCreateRequest,\n\tActorsGetOrCreateResponse,\n\tActorsListResponse,\n} from \"@/manager-api/actors\";\nimport type { RivetId } from \"@/manager-api/common\";\nimport { apiCall } from \"./api-utils\";\n\n// MARK: Get actor\nexport async function getActor(\n\tconfig: ClientConfig,\n\t_: string,\n\tactorId: RivetId,\n): Promise<ActorsListResponse> {\n\treturn apiCall<never, ActorsListResponse>(\n\t\tconfig,\n\t\t\"GET\",\n\t\t`/actors?actor_ids=${encodeURIComponent(actorId)}`,\n\t);\n}\n\n// MARK: Get actor by key\nexport async function getActorByKey(\n\tconfig: ClientConfig,\n\tname: string,\n\tkey: string[],\n): Promise<ActorsListResponse> {\n\tconst serializedKey = serializeActorKey(key);\n\treturn apiCall<never, ActorsListResponse>(\n\t\tconfig,\n\t\t\"GET\",\n\t\t`/actors?name=${encodeURIComponent(name)}&key=${encodeURIComponent(serializedKey)}`,\n\t);\n}\n\n// MARK: List actors by name\nexport async function listActorsByName(\n\tconfig: ClientConfig,\n\tname: string,\n): Promise<ActorsListResponse> {\n\treturn apiCall<never, ActorsListResponse>(\n\t\tconfig,\n\t\t\"GET\",\n\t\t`/actors?name=${encodeURIComponent(name)}`,\n\t);\n}\n\n// MARK: Get or create actor by id\nexport async function getOrCreateActor(\n\tconfig: ClientConfig,\n\trequest: ActorsGetOrCreateRequest,\n): Promise<ActorsGetOrCreateResponse> {\n\treturn apiCall<ActorsGetOrCreateRequest, ActorsGetOrCreateResponse>(\n\t\tconfig,\n\t\t\"PUT\",\n\t\t`/actors`,\n\t\trequest,\n\t);\n}\n\n// MARK: Create actor\nexport async function createActor(\n\tconfig: ClientConfig,\n\trequest: ActorsCreateRequest,\n): Promise<ActorsCreateResponse> {\n\treturn apiCall<ActorsCreateRequest, ActorsCreateResponse>(\n\t\tconfig,\n\t\t\"POST\",\n\t\t`/actors`,\n\t\trequest,\n\t);\n}\n\n// MARK: Destroy actor\nexport async function destroyActor(\n\tconfig: ClientConfig,\n\tactorId: RivetId,\n): Promise<ActorsDeleteResponse> {\n\treturn apiCall<never, ActorsDeleteResponse>(\n\t\tconfig,\n\t\t\"DELETE\",\n\t\t`/actors/${encodeURIComponent(actorId)}`,\n\t);\n}\n\n// MARK: Get metadata\nexport async function getMetadata(\n\tconfig: ClientConfig,\n): Promise<MetadataResponse> {\n\treturn apiCall<never, MetadataResponse>(config, \"GET\", `/metadata`);\n}\n\n// MARK: Get datacenters\nexport interface DatacentersResponse {\n\tdatacenters: { name: string }[];\n}\n\nexport async function getDatacenters(\n\tconfig: ClientConfig,\n): Promise<DatacentersResponse> {\n\treturn apiCall<never, DatacentersResponse>(config, \"GET\", `/datacenters`);\n}\n\n// MARK: Update runner config\nexport interface RegistryConfigRequest {\n\tdatacenters: Record<\n\t\tstring,\n\t\t{\n\t\t\tserverless: {\n\t\t\t\turl: string;\n\t\t\t\theaders: Record<string, string>;\n\t\t\t\tmax_runners: number;\n\t\t\t\tmin_runners: number;\n\t\t\t\trequest_lifespan: number;\n\t\t\t\trunners_margin: number;\n\t\t\t\tslots_per_runner: number;\n\t\t\t\tmetadata_poll_interval?: number;\n\t\t\t};\n\t\t\tmetadata?: Record<string, unknown>;\n\t\t}\n\t>;\n}\n\nexport async function updateRunnerConfig(\n\tconfig: ClientConfig,\n\trunnerName: string,\n\trequest: RegistryConfigRequest,\n): Promise<void> {\n\treturn apiCall<RegistryConfigRequest, void>(\n\t\tconfig,\n\t\t\"PUT\",\n\t\t`/runner-configs/${runnerName}`,\n\t\trequest,\n\t);\n}\n\n// MARK: KV Get\ninterface KvGetResponse {\n\tupdate_ts: string;\n\tvalue: string | null;\n}\n\nexport async function kvGet(\n\tconfig: ClientConfig,\n\tactorId: RivetId,\n\tkey: string,\n): Promise<KvGetResponse> {\n\treturn apiCall<{}, KvGetResponse>(\n\t\tconfig,\n\t\t\"GET\",\n\t\t`/actors/${encodeURIComponent(actorId)}/kv/keys/${encodeURIComponent(key)}`,\n\t);\n}\n","import pRetry from \"p-retry\";\nimport type { ClientConfig } from \"@/client/client\";\nimport type { MetadataResponse } from \"@/common/router\";\nimport { stringifyError } from \"@/common/utils\";\nimport { getMetadata } from \"./api-endpoints\";\nimport { getEndpoint } from \"./api-utils\";\nimport { logger } from \"./log\";\n\n// Global cache to store metadata check promises for each endpoint\nconst metadataLookupCache = new Map<string, Promise<MetadataResponse>>();\n\nexport async function lookupMetadataCached(\n\tconfig: ClientConfig,\n): Promise<MetadataResponse> {\n\tconst endpoint = getEndpoint(config);\n\n\t// Check if metadata lookup is already in progress or completed for this endpoint\n\tconst existingPromise = metadataLookupCache.get(endpoint);\n\tif (existingPromise) {\n\t\treturn existingPromise;\n\t}\n\n\t// Create and store the promise immediately to prevent racing requests\n\tconst metadataLookupPromise = pRetry(\n\t\tasync () => {\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"fetching metadata\",\n\t\t\t\tendpoint,\n\t\t\t});\n\n\t\t\tconst metadataData = await getMetadata(config);\n\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"received metadata\",\n\t\t\t\tendpoint,\n\t\t\t\tclientEndpoint: metadataData.clientEndpoint,\n\t\t\t});\n\n\t\t\treturn metadataData;\n\t\t},\n\t\t{\n\t\t\tforever: true,\n\t\t\tminTimeout: 500,\n\t\t\tmaxTimeout: 15_000,\n\t\t\tonFailedAttempt: (error) => {\n\t\t\t\t// Skip logging warning on first attempt since this attempt\n\t\t\t\t// fails if called immediately on startup. This is because the\n\t\t\t\t// runtime startup is an async operation that will not be\n\t\t\t\t// available on the first tick.\n\t\t\t\tif (error.attemptNumber > 1) {\n\t\t\t\t\tlogger().warn({\n\t\t\t\t\t\tmsg: \"failed to fetch metadata, retrying\",\n\t\t\t\t\t\tendpoint,\n\t\t\t\t\t\tattempt: error.attemptNumber,\n\t\t\t\t\t\terror: stringifyError(error),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t);\n\n\tmetadataLookupCache.set(endpoint, metadataLookupPromise);\n\treturn metadataLookupPromise;\n}\n","import type { Context as HonoContext } from \"hono\";\nimport type { WSContext } from \"hono/ws\";\nimport type { UpgradeWebSocketArgs } from \"@/actor/router-websocket-endpoints\";\nimport { stringifyError } from \"@/common/utils\";\nimport { importWebSocket } from \"@/common/websocket\";\nimport { logger } from \"./log\";\n\n/**\n * Returns Hono `upgradeWebSocket` args that will proxy requests from the client to a destination address.\n */\nexport async function createWebSocketProxy(\n\tc: HonoContext,\n\ttargetUrl: string,\n\tprotocols: string[],\n): Promise<UpgradeWebSocketArgs> {\n\tconst WebSocket = await importWebSocket();\n\n\t// WebSocket state\n\tinterface WsState {\n\t\ttargetWs?: WebSocket;\n\t\tconnectPromise?: Promise<void>;\n\t}\n\tconst state: WsState = {};\n\n\treturn {\n\t\tonOpen: async (event: any, clientWs: WSContext) => {\n\t\t\tlogger().debug({ msg: \"client websocket connected\", targetUrl });\n\n\t\t\tif (clientWs.readyState !== 1) {\n\t\t\t\tlogger().warn({\n\t\t\t\t\tmsg: \"client websocket not open on connection\",\n\t\t\t\t\ttargetUrl,\n\t\t\t\t\treadyState: clientWs.readyState,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Create WebSocket\n\t\t\tconst targetWs = new WebSocket(targetUrl, protocols);\n\t\t\tstate.targetWs = targetWs;\n\n\t\t\t// Setup connection promise\n\t\t\tstate.connectPromise = new Promise<void>((resolve, reject) => {\n\t\t\t\ttargetWs.addEventListener(\"open\", () => {\n\t\t\t\t\tlogger().debug({\n\t\t\t\t\t\tmsg: \"target websocket connected\",\n\t\t\t\t\t\ttargetUrl,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (clientWs.readyState !== 1) {\n\t\t\t\t\t\tlogger().warn({\n\t\t\t\t\t\t\tmsg: \"client websocket closed before target connected\",\n\t\t\t\t\t\t\ttargetUrl,\n\t\t\t\t\t\t\tclientReadyState: clientWs.readyState,\n\t\t\t\t\t\t});\n\t\t\t\t\t\ttargetWs.close(1001, \"Client disconnected\");\n\t\t\t\t\t\treject(new Error(\"Client disconnected\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tresolve();\n\t\t\t\t});\n\n\t\t\t\ttargetWs.addEventListener(\"error\", (error) => {\n\t\t\t\t\tlogger().warn({\n\t\t\t\t\t\tmsg: \"target websocket error during connection\",\n\t\t\t\t\t\ttargetUrl,\n\t\t\t\t\t});\n\t\t\t\t\treject(error);\n\t\t\t\t});\n\t\t\t});\n\n\t\t\t// Setup bidirectional forwarding\n\t\t\tstate.targetWs.addEventListener(\"message\", (event) => {\n\t\t\t\tif (\n\t\t\t\t\ttypeof event.data === \"string\" ||\n\t\t\t\t\tevent.data instanceof ArrayBuffer\n\t\t\t\t) {\n\t\t\t\t\tclientWs.send(event.data);\n\t\t\t\t} else if (event.data instanceof Blob) {\n\t\t\t\t\tevent.data.arrayBuffer().then((buffer) => {\n\t\t\t\t\t\tclientWs.send(buffer);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tstate.targetWs.addEventListener(\"close\", (event) => {\n\t\t\t\tlogger().debug({\n\t\t\t\t\tmsg: \"target websocket closed\",\n\t\t\t\t\ttargetUrl,\n\t\t\t\t\tcode: event.code,\n\t\t\t\t\treason: event.reason,\n\t\t\t\t});\n\t\t\t\tcloseWebSocketIfOpen(clientWs, event.code, event.reason);\n\t\t\t});\n\n\t\t\tstate.targetWs.addEventListener(\"error\", (error) => {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"target websocket error\",\n\t\t\t\t\ttargetUrl,\n\t\t\t\t\terror: stringifyError(error),\n\t\t\t\t});\n\t\t\t\tcloseWebSocketIfOpen(clientWs, 1011, \"Target WebSocket error\");\n\t\t\t});\n\t\t},\n\n\t\tonMessage: async (event: any, clientWs: WSContext) => {\n\t\t\tif (!state.targetWs || !state.connectPromise) {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"websocket state not initialized\",\n\t\t\t\t\ttargetUrl,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tawait state.connectPromise;\n\t\t\t\tif (state.targetWs.readyState === WebSocket.OPEN) {\n\t\t\t\t\tstate.targetWs.send(event.data);\n\t\t\t\t} else {\n\t\t\t\t\tlogger().warn({\n\t\t\t\t\t\tmsg: \"target websocket not open\",\n\t\t\t\t\t\ttargetUrl,\n\t\t\t\t\t\treadyState: state.targetWs.readyState,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"failed to connect to target websocket\",\n\t\t\t\t\ttargetUrl,\n\t\t\t\t\terror,\n\t\t\t\t});\n\t\t\t\tcloseWebSocketIfOpen(\n\t\t\t\t\tclientWs,\n\t\t\t\t\t1011,\n\t\t\t\t\t\"Failed to connect to target\",\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\n\t\tonClose: (event: any, clientWs: WSContext) => {\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"client websocket closed\",\n\t\t\t\ttargetUrl,\n\t\t\t\tcode: event.code,\n\t\t\t\treason: event.reason,\n\t\t\t\twasClean: event.wasClean,\n\t\t\t});\n\n\t\t\tif (state.targetWs) {\n\t\t\t\tif (\n\t\t\t\t\tstate.targetWs.readyState === WebSocket.OPEN ||\n\t\t\t\t\tstate.targetWs.readyState === WebSocket.CONNECTING\n\t\t\t\t) {\n\t\t\t\t\tstate.targetWs.close(\n\t\t\t\t\t\t1000,\n\t\t\t\t\t\tevent.reason || \"Client disconnected\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tonError: (event: any, clientWs: WSContext) => {\n\t\t\tlogger().error({ msg: \"client websocket error\", targetUrl, event });\n\n\t\t\tif (state.targetWs) {\n\t\t\t\tif (state.targetWs.readyState === WebSocket.OPEN) {\n\t\t\t\t\tstate.targetWs.close(1011, \"Client WebSocket error\");\n\t\t\t\t} else if (state.targetWs.readyState === WebSocket.CONNECTING) {\n\t\t\t\t\tstate.targetWs.close();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n}\n\nfunction closeWebSocketIfOpen(\n\tws: WebSocket | WSContext,\n\tcode: number,\n\treason: string,\n): void {\n\tif (ws.readyState === 1) {\n\t\tws.close(code, reason);\n\t} else if (\n\t\t\"close\" in ws &&\n\t\t(ws as WebSocket).readyState === WebSocket.OPEN\n\t) {\n\t\tws.close(code, reason);\n\t}\n}\n","import * as cbor from \"cbor-x\";\nimport invariant from \"invariant\";\nimport pRetry from \"p-retry\";\nimport type { CloseEvent } from \"ws\";\nimport type { AnyActorDefinition } from \"@/actor/definition\";\nimport { inputDataToBuffer } from \"@/actor/protocol/old\";\nimport { type Encoding, jsonStringifyCompat } from \"@/actor/protocol/serde\";\nimport { PATH_CONNECT } from \"@/common/actor-router-consts\";\nimport { assertUnreachable, stringifyError } from \"@/common/utils\";\nimport type { UniversalWebSocket } from \"@/common/websocket-interface\";\nimport type { ManagerDriver } from \"@/driver-helpers/mod\";\nimport type { ActorQuery } from \"@/manager/protocol/query\";\nimport type * as protocol from \"@/schemas/client-protocol/mod\";\nimport {\n\tCURRENT_VERSION as CLIENT_PROTOCOL_CURRENT_VERSION,\n\tTO_CLIENT_VERSIONED,\n\tTO_SERVER_VERSIONED,\n} from \"@/schemas/client-protocol/versioned\";\nimport {\n\ttype ToClient as ToClientJson,\n\tToClientSchema,\n\ttype ToServer as ToServerJson,\n\tToServerSchema,\n} from \"@/schemas/client-protocol-zod/mod\";\nimport { deserializeWithEncoding, serializeWithEncoding } from \"@/serde\";\nimport { bufferToArrayBuffer, promiseWithResolvers } from \"@/utils\";\nimport { getLogMessage } from \"@/utils/env-vars\";\nimport type { ActorDefinitionActions } from \"./actor-common\";\nimport { checkForSchedulingError, queryActor } from \"./actor-query\";\nimport { ACTOR_CONNS_SYMBOL, type ClientRaw } from \"./client\";\nimport * as errors from \"./errors\";\nimport { logger } from \"./log\";\nimport {\n\tcreateQueueSender,\n\ttype QueueSendNoWaitOptions,\n\ttype QueueSendOptions,\n\ttype QueueSendResult,\n\ttype QueueSendWaitOptions,\n} from \"./queue\";\nimport {\n\ttype WebSocketMessage as ConnMessage,\n\tmessageLength,\n\tparseWebSocketCloseReason,\n\tsendHttpRequest,\n} from \"./utils\";\n\n/**\n * Connection status for an actor connection.\n *\n * - `\"idle\"`: Not connected, no auto-reconnect (initial state, after dispose, or disabled)\n * - `\"connecting\"`: Attempting to establish connection\n * - `\"connected\"`: Connection is active\n * - `\"disconnected\"`: Connection was lost, will auto-reconnect\n */\nexport type ActorConnStatus =\n\t| \"idle\"\n\t| \"connecting\"\n\t| \"connected\"\n\t| \"disconnected\";\n\ninterface ActionInFlight {\n\tname: string;\n\tresolve: (response: { id: bigint; output: unknown }) => void;\n\treject: (error: Error) => void;\n}\n\ninterface EventSubscriptions<Args extends Array<unknown>> {\n\tcallback: (...args: Args) => void;\n\tonce: boolean;\n}\n\n/**\n * A function that unsubscribes from an event.\n *\n * @typedef {Function} EventUnsubscribe\n */\nexport type EventUnsubscribe = () => void;\n\n/**\n * A function that handles connection errors.\n *\n * @typedef {Function} ActorErrorCallback\n */\nexport type ActorErrorCallback = (error: errors.ActorError) => void;\n\n/**\n * A callback for connection state changes.\n *\n * @typedef {Function} ConnectionStateCallback\n */\nexport type ConnectionStateCallback = () => void;\n\n/**\n * A callback for connection status changes.\n *\n * @typedef {Function} StatusChangeCallback\n */\nexport type StatusChangeCallback = (status: ActorConnStatus) => void;\n\nexport interface SendHttpMessageOpts {\n\tephemeral: boolean;\n\tsignal?: AbortSignal;\n}\n\nexport const CONNECT_SYMBOL = Symbol(\"connect\");\n\n/**\n * Provides underlying functions for {@link ActorConn}. See {@link ActorConn} for using type-safe remote procedure calls.\n *\n * @see {@link ActorConn}\n */\nexport class ActorConnRaw {\n\t#disposed = false;\n\n\t/* Will be aborted on dispose. */\n\t#abortController = new AbortController();\n\n\t#connStatus: ActorConnStatus = \"idle\";\n\n\t#actorId?: string;\n\t#connId?: string;\n\n\t#messageQueue: Array<{\n\t\tbody:\n\t\t\t| {\n\t\t\t\t\ttag: \"ActionRequest\";\n\t\t\t\t\tval: { id: bigint; name: string; args: unknown };\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\ttag: \"SubscriptionRequest\";\n\t\t\t\t\tval: { eventName: string; subscribe: boolean };\n\t\t\t };\n\t}> = [];\n\t#actionsInFlight = new Map<number, ActionInFlight>();\n\n\t// biome-ignore lint/suspicious/noExplicitAny: Unknown subscription type\n\t#eventSubscriptions = new Map<string, Set<EventSubscriptions<any[]>>>();\n\n\t#errorHandlers = new Set<ActorErrorCallback>();\n\t#openHandlers = new Set<ConnectionStateCallback>();\n\t#openScheduled = false;\n\t#closeHandlers = new Set<ConnectionStateCallback>();\n\t#statusChangeHandlers = new Set<StatusChangeCallback>();\n\n\t#actionIdCounter = 0;\n\t#queueSender: ReturnType<typeof createQueueSender>;\n\n\t/**\n\t * Interval that keeps the NodeJS process alive if this is the only thing running.\n\t *\n\t * See ttps://github.com/nodejs/node/issues/22088\n\t */\n\t#keepNodeAliveInterval: NodeJS.Timeout;\n\n\t/** Promise used to indicate the socket has connected successfully. This will be rejected if the connection fails. */\n\t#onOpenPromise?: ReturnType<typeof promiseWithResolvers<undefined>>;\n\n\t#websocket?: UniversalWebSocket;\n\n\t#client: ClientRaw;\n\t#driver: ManagerDriver;\n\t#params: unknown;\n\t#encoding: Encoding;\n\t#actorQuery: ActorQuery;\n\n\t// TODO: ws message queue\n\n\t/**\n\t * Do not call this directly.\n\t *\n\t * Creates an instance of ActorConnRaw.\n\t *\n\t * @protected\n\t */\n\tpublic constructor(\n\t\tclient: ClientRaw,\n\t\tdriver: ManagerDriver,\n\t\tparams: unknown,\n\t\tencoding: Encoding,\n\t\tactorQuery: ActorQuery,\n\t) {\n\t\tthis.#client = client;\n\t\tthis.#driver = driver;\n\t\tthis.#params = params;\n\t\tthis.#encoding = encoding;\n\t\tthis.#actorQuery = actorQuery;\n\t\tthis.#queueSender = createQueueSender({\n\t\t\tencoding: this.#encoding,\n\t\t\tparams: this.#params,\n\t\t\tcustomFetch: async (request: Request) => {\n\t\t\t\tif (!this.#actorId) {\n\t\t\t\t\tconst { actorId } = await queryActor(\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tthis.#actorQuery,\n\t\t\t\t\t\tthis.#driver,\n\t\t\t\t\t);\n\t\t\t\t\tthis.#actorId = actorId;\n\t\t\t\t}\n\t\t\t\treturn this.#driver.sendRequest(this.#actorId, request);\n\t\t\t},\n\t\t});\n\n\t\tthis.#keepNodeAliveInterval = setInterval(() => 60_000);\n\t}\n\n\tsend(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions: QueueSendWaitOptions,\n\t): Promise<QueueSendResult>;\n\tsend(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions?: QueueSendNoWaitOptions,\n\t): Promise<void>;\n\tsend(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions?: QueueSendOptions,\n\t): Promise<QueueSendResult | void> {\n\t\treturn this.#queueSender.send(name, body, options as any);\n\t}\n\n\t/**\n\t * Call a raw action connection. See {@link ActorConn} for type-safe action calls.\n\t *\n\t * @see {@link ActorConn}\n\t * @template Args - The type of arguments to pass to the action function.\n\t * @template Response - The type of the response returned by the action function.\n\t * @param {string} name - The name of the action function to call.\n\t * @param {...Args} args - The arguments to pass to the action function.\n\t * @returns {Promise<Response>} - A promise that resolves to the response of the action function.\n\t */\n\tasync action<\n\t\tArgs extends Array<unknown> = unknown[],\n\t\tResponse = unknown,\n\t>(opts: {\n\t\tname: string;\n\t\targs: Args;\n\t\tsignal?: AbortSignal;\n\t}): Promise<Response> {\n\t\tlogger().debug({ msg: \"action\", name: opts.name, args: opts.args });\n\n\t\t// If we have an active connection, use the websockactionId\n\t\tconst actionId = this.#actionIdCounter;\n\t\tthis.#actionIdCounter += 1;\n\n\t\tconst { promise, resolve, reject } = promiseWithResolvers<{\n\t\t\tid: bigint;\n\t\t\toutput: unknown;\n\t\t}>((reason) => logger().warn({ msg: \"unhandled action promise rejection\", reason }));\n\t\tthis.#actionsInFlight.set(actionId, {\n\t\t\tname: opts.name,\n\t\t\tresolve,\n\t\t\treject,\n\t\t});\n\t\tlogger().debug({\n\t\t\tmsg: \"added action to in-flight map\",\n\t\t\tactionId,\n\t\t\tactionName: opts.name,\n\t\t\tinFlightCount: this.#actionsInFlight.size,\n\t\t});\n\n\t\tthis.#sendMessage({\n\t\t\tbody: {\n\t\t\t\ttag: \"ActionRequest\",\n\t\t\t\tval: {\n\t\t\t\t\tid: BigInt(actionId),\n\t\t\t\t\tname: opts.name,\n\t\t\t\t\targs: opts.args,\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\n\t\t// TODO: Throw error if disconnect is called\n\n\t\tconst { id: responseId, output } = await promise;\n\t\tif (responseId !== BigInt(actionId))\n\t\t\tthrow new Error(\n\t\t\t\t`Request ID ${actionId} does not match response ID ${responseId}`,\n\t\t\t);\n\n\t\treturn output as Response;\n\t}\n\n\t/**\n\t * Do not call this directly.\n\t * Establishes a connection to the server using the specified endpoint & encoding & driver.\n\t *\n\t * @protected\n\t */\n\tpublic [CONNECT_SYMBOL]() {\n\t\tthis.#connectWithRetry();\n\t}\n\n\t#setConnStatus(status: ActorConnStatus) {\n\t\tconst prevStatus = this.#connStatus;\n\t\tif (prevStatus === status) return;\n\t\tthis.#connStatus = status;\n\n\t\t// Notify status change handlers\n\t\tfor (const handler of [...this.#statusChangeHandlers]) {\n\t\t\ttry {\n\t\t\t\thandler(status);\n\t\t\t} catch (err) {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"error in status change handler\",\n\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Notify open handlers\n\t\tif (status === \"connected\") {\n\t\t\tfor (const handler of [...this.#openHandlers]) {\n\t\t\t\ttry {\n\t\t\t\t\thandler();\n\t\t\t\t} catch (err) {\n\t\t\t\t\tlogger().error({\n\t\t\t\t\t\tmsg: \"error in open handler\",\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}\n\n\t\t// Notify close handlers (only if transitioning from Connected to Disconnected or Idle)\n\t\tif (\n\t\t\t(status === \"disconnected\" || status === \"idle\") &&\n\t\t\tprevStatus === \"connected\"\n\t\t) {\n\t\t\tfor (const handler of [...this.#closeHandlers]) {\n\t\t\t\ttry {\n\t\t\t\t\thandler();\n\t\t\t\t} catch (err) {\n\t\t\t\t\tlogger().error({\n\t\t\t\t\t\tmsg: \"error in close handler\",\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}\n\t}\n\n\t#connectWithRetry() {\n\t\tthis.#setConnStatus(\"connecting\");\n\n\t\t// Attempt to reconnect indefinitely\n\t\t// This is intentionally not awaited - connection happens in background\n\t\tpRetry(this.#connectAndWait.bind(this), {\n\t\t\tforever: true,\n\t\t\tminTimeout: 250,\n\t\t\tmaxTimeout: 30_000,\n\n\t\t\tonFailedAttempt: (error) => {\n\t\t\t\tlogger().warn({\n\t\t\t\t\tmsg: \"failed to reconnect\",\n\t\t\t\t\tattempt: error.attemptNumber,\n\t\t\t\t\terror: stringifyError(error),\n\t\t\t\t});\n\t\t\t},\n\n\t\t\t// Cancel retry if aborted\n\t\t\tsignal: this.#abortController.signal,\n\t\t}).catch((err) => {\n\t\t\tif ((err as Error).name === \"AbortError\") {\n\t\t\t\tlogger().info({ msg: \"connection retry aborted\" });\n\t\t\t} else {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"unexpected error in connection retry\",\n\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\n\tasync #connectAndWait() {\n\t\ttry {\n\t\t\t// Create promise for open\n\t\t\tif (this.#onOpenPromise)\n\t\t\t\tthrow new Error(\"#onOpenPromise already defined\");\n\t\t\tthis.#onOpenPromise = promiseWithResolvers((reason) => logger().warn({ msg: \"unhandled open promise rejection\", reason }));\n\n\t\t\tawait this.#connectWebSocket();\n\n\t\t\t// Wait for result\n\t\t\tawait this.#onOpenPromise.promise;\n\t\t} finally {\n\t\t\tthis.#onOpenPromise = undefined;\n\t\t}\n\t}\n\n\tasync #connectWebSocket() {\n\t\tconst { actorId } = await queryActor(\n\t\t\tundefined,\n\t\t\tthis.#actorQuery,\n\t\t\tthis.#driver,\n\t\t);\n\n\t\t// Store actorId early so we can use it for error lookups\n\t\tthis.#actorId = actorId;\n\n\t\tconst ws = await this.#driver.openWebSocket(\n\t\t\tPATH_CONNECT,\n\t\t\tactorId,\n\t\t\tthis.#encoding,\n\t\t\tthis.#params,\n\t\t);\n\t\tlogger().debug({\n\t\t\tmsg: \"opened websocket\",\n\t\t\tconnId: this.#connId,\n\t\t\treadyState: ws.readyState,\n\t\t\tmessageQueueLength: this.#messageQueue.length,\n\t\t});\n\t\tthis.#websocket = ws;\n\t\tws.addEventListener(\"open\", () => {\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"client websocket open\",\n\t\t\t\tconnId: this.#connId,\n\t\t\t});\n\t\t});\n\t\tws.addEventListener(\"message\", async (ev) => {\n\t\t\ttry {\n\t\t\t\tawait this.#handleOnMessage(ev.data);\n\t\t\t} catch (err) {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"error in websocket message handler\",\n\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t\tws.addEventListener(\"close\", async (ev) => {\n\t\t\ttry {\n\t\t\t\tawait this.#handleOnClose(ev);\n\t\t\t} catch (err) {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"error in websocket close handler\",\n\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t\tws.addEventListener(\"error\", (_ev) => {\n\t\t\ttry {\n\t\t\t\tthis.#handleOnError();\n\t\t\t} catch (err) {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"error in websocket error handler\",\n\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\n\t/** Called by the onopen event from drivers. */\n\t#handleOnOpen() {\n\t\t// Connection was disposed before Init message arrived - close the websocket to avoid leak\n\t\tif (this.#disposed) {\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"handleOnOpen called after dispose, closing websocket\",\n\t\t\t});\n\t\t\tif (this.#websocket) {\n\t\t\t\tthis.#websocket.close(1000, \"Disposed\");\n\t\t\t\tthis.#websocket = undefined;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.#connStatus === \"connected\" || this.#openScheduled) {\n\t\t\treturn;\n\t\t}\n\t\tthis.#openScheduled = true;\n\n\t\tqueueMicrotask(() => {\n\t\t\tthis.#openScheduled = false;\n\t\t\tif (this.#disposed) {\n\t\t\t\tlogger().debug({\n\t\t\t\t\tmsg: \"handleOnOpen scheduled after dispose, closing websocket\",\n\t\t\t\t});\n\t\t\t\tif (this.#websocket) {\n\t\t\t\t\tthis.#websocket.close(1000, \"Disposed\");\n\t\t\t\t\tthis.#websocket = undefined;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"socket open\",\n\t\t\t\tmessageQueueLength: this.#messageQueue.length,\n\t\t\t\tconnId: this.#connId,\n\t\t\t});\n\n\t\t\t// Update connection state (this also notifies handlers)\n\t\t\tthis.#setConnStatus(\"connected\");\n\n\t\t\t// Resolve open promise\n\t\t\tif (this.#onOpenPromise) {\n\t\t\t\tthis.#onOpenPromise.resolve(undefined);\n\t\t\t} else {\n\t\t\t\tlogger().warn({ msg: \"#onOpenPromise is undefined\" });\n\t\t\t}\n\n\t\t\t// Resubscribe to all active events\n\t\t\tfor (const eventName of this.#eventSubscriptions.keys()) {\n\t\t\t\tthis.#sendSubscription(eventName, true);\n\t\t\t}\n\n\t\t\t// Flush queue\n\t\t\t//\n\t\t\t// If the message fails to send, the message will be re-queued\n\t\t\tconst queue = this.#messageQueue;\n\t\t\tthis.#messageQueue = [];\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"flushing message queue\",\n\t\t\t\tqueueLength: queue.length,\n\t\t\t});\n\t\t\tfor (const msg of queue) {\n\t\t\t\tthis.#sendMessage(msg);\n\t\t\t}\n\t\t});\n\t}\n\n\t/** Called by the onmessage event from drivers. */\n\tasync #handleOnMessage(data: any) {\n\t\tlogger().trace({\n\t\t\tmsg: \"received message\",\n\t\t\tdataType: typeof data,\n\t\t\tisBlob: data instanceof Blob,\n\t\t\tisArrayBuffer: data instanceof ArrayBuffer,\n\t\t});\n\n\t\tconst response = await this.#parseMessage(data as ConnMessage);\n\t\tlogger().trace(\n\t\t\tgetLogMessage()\n\t\t\t\t? {\n\t\t\t\t\t\tmsg: \"parsed message\",\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\tjsonStringifyCompat(response).substring(0, 100) +\n\t\t\t\t\t\t\t\"...\",\n\t\t\t\t\t}\n\t\t\t\t: { msg: \"parsed message\" },\n\t\t);\n\n\t\tif (response.body.tag === \"Init\") {\n\t\t\t// Store connection info\n\t\t\tthis.#actorId = response.body.val.actorId;\n\t\t\tthis.#connId = response.body.val.connectionId;\n\t\t\tlogger().trace({\n\t\t\t\tmsg: \"received init message\",\n\t\t\t\tactorId: this.#actorId,\n\t\t\t\tconnId: this.#connId,\n\t\t\t});\n\t\t\tthis.#handleOnOpen();\n\t\t} else if (response.body.tag === \"Error\") {\n\t\t\t// Connection error\n\t\t\tconst { group, code, message, metadata, actionId } =\n\t\t\t\tresponse.body.val;\n\n\t\t\tif (actionId) {\n\t\t\t\tconst inFlight = this.#takeActionInFlight(Number(actionId));\n\n\t\t\t\tlogger().warn({\n\t\t\t\t\tmsg: \"action error\",\n\t\t\t\t\tactionId: actionId,\n\t\t\t\t\tactionName: inFlight?.name,\n\t\t\t\t\tgroup,\n\t\t\t\t\tcode,\n\t\t\t\t\tmessage,\n\t\t\t\t\tmetadata,\n\t\t\t\t});\n\n\t\t\t\tinFlight.reject(\n\t\t\t\t\tnew errors.ActorError(group, code, message, metadata),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tlogger().warn({\n\t\t\t\t\tmsg: \"connection error\",\n\t\t\t\t\tgroup,\n\t\t\t\t\tcode,\n\t\t\t\t\tmessage,\n\t\t\t\t\tmetadata,\n\t\t\t\t});\n\n\t\t\t\t// Check if this is an actor scheduling error and try to get more details\n\t\t\t\tlet errorToThrow = new errors.ActorError(\n\t\t\t\t\tgroup,\n\t\t\t\t\tcode,\n\t\t\t\t\tmessage,\n\t\t\t\t\tmetadata,\n\t\t\t\t);\n\t\t\t\tif (errors.isSchedulingError(group, code) && this.#actorId) {\n\t\t\t\t\tconst schedulingError = await checkForSchedulingError(\n\t\t\t\t\t\tgroup,\n\t\t\t\t\t\tcode,\n\t\t\t\t\t\tthis.#actorId,\n\t\t\t\t\t\tthis.#actorQuery,\n\t\t\t\t\t\tthis.#driver,\n\t\t\t\t\t);\n\t\t\t\t\tif (schedulingError) {\n\t\t\t\t\t\terrorToThrow = schedulingError;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If we have an onOpenPromise, reject it with the error\n\t\t\t\tif (this.#onOpenPromise) {\n\t\t\t\t\tthis.#onOpenPromise.reject(errorToThrow);\n\t\t\t\t}\n\n\t\t\t\t// Reject any in-flight requests\n\t\t\t\tfor (const [id, inFlight] of this.#actionsInFlight.entries()) {\n\t\t\t\t\tinFlight.reject(errorToThrow);\n\t\t\t\t\tthis.#actionsInFlight.delete(id);\n\t\t\t\t}\n\n\t\t\t\tthis.#dispatchActorError(errorToThrow);\n\t\t\t}\n\t\t} else if (response.body.tag === \"ActionResponse\") {\n\t\t\t// Action response OK\n\t\t\tconst { id: actionId } = response.body.val;\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"received action response\",\n\t\t\t\tactionId: Number(actionId),\n\t\t\t\tinFlightCount: this.#actionsInFlight.size,\n\t\t\t\tinFlightIds: Array.from(this.#actionsInFlight.keys()),\n\t\t\t});\n\n\t\t\tconst inFlight = this.#takeActionInFlight(Number(actionId));\n\t\t\tlogger().trace({\n\t\t\t\tmsg: \"resolving action promise\",\n\t\t\t\tactionId,\n\t\t\t\tactionName: inFlight?.name,\n\t\t\t});\n\t\t\tinFlight.resolve(response.body.val);\n\t\t} else if (response.body.tag === \"Event\") {\n\t\t\tlogger().trace({\n\t\t\t\tmsg: \"received event\",\n\t\t\t\tname: response.body.val.name,\n\t\t\t});\n\t\t\tthis.#dispatchEvent(response.body.val);\n\t\t} else {\n\t\t\tassertUnreachable(response.body);\n\t\t}\n\t}\n\n\t/** Called by the onclose event from drivers. */\n\tasync #handleOnClose(event: Event | CloseEvent) {\n\t\t// We can't use `event instanceof CloseEvent` because it's not defined in NodeJS\n\t\tconst closeEvent = event as CloseEvent;\n\t\tconst wasClean = closeEvent.wasClean;\n\t\tconst wasConnected = this.#connStatus === \"connected\";\n\n\t\tlogger().info({\n\t\t\tmsg: \"socket closed\",\n\t\t\tcode: closeEvent.code,\n\t\t\treason: closeEvent.reason,\n\t\t\twasClean,\n\t\t\tdisposed: this.#disposed,\n\t\t\tconnId: this.#connId,\n\t\t});\n\n\t\tthis.#websocket = undefined;\n\n\t\tif (this.#disposed) {\n\t\t\t// Use ActorConnDisposed error and prevent unhandled rejection\n\t\t\tthis.#rejectPendingPromises(new errors.ActorConnDisposed(), true);\n\t\t} else {\n\t\t\tthis.#setConnStatus(\"disconnected\");\n\n\t\t\t// Build error from close event\n\t\t\tlet error: Error;\n\t\t\tconst reason = closeEvent.reason || \"\";\n\t\t\tconst parsed = parseWebSocketCloseReason(reason);\n\n\t\t\tif (parsed) {\n\t\t\t\tconst { group, code } = parsed;\n\n\t\t\t\t// Check if this is a scheduling error\n\t\t\t\tif (errors.isSchedulingError(group, code) && this.#actorId) {\n\t\t\t\t\tconst schedulingError = await checkForSchedulingError(\n\t\t\t\t\t\tgroup,\n\t\t\t\t\t\tcode,\n\t\t\t\t\t\tthis.#actorId,\n\t\t\t\t\t\tthis.#actorQuery,\n\t\t\t\t\t\tthis.#driver,\n\t\t\t\t\t);\n\t\t\t\t\tif (schedulingError) {\n\t\t\t\t\t\terror = schedulingError;\n\t\t\t\t\t} else {\n\t\t\t\t\t\terror = new errors.ActorError(\n\t\t\t\t\t\t\tgroup,\n\t\t\t\t\t\t\tcode,\n\t\t\t\t\t\t\t`Connection closed: ${reason}`,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\terror = new errors.ActorError(\n\t\t\t\t\t\tgroup,\n\t\t\t\t\t\tcode,\n\t\t\t\t\t\t`Connection closed: ${reason}`,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Default error for non-structured close reasons\n\t\t\t\terror = new Error(\n\t\t\t\t\t`${wasClean ? \"Connection closed\" : \"Connection lost\"} (code: ${closeEvent.code}, reason: ${reason})`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.#rejectPendingPromises(error, false);\n\n\t\t\t// Dispatch to error handler if it's an ActorError\n\t\t\tif (error instanceof errors.ActorError) {\n\t\t\t\tthis.#dispatchActorError(error);\n\t\t\t}\n\n\t\t\t// Automatically reconnect if we were connected\n\t\t\tif (wasConnected) {\n\t\t\t\tlogger().debug({\n\t\t\t\t\tmsg: \"triggering reconnect\",\n\t\t\t\t\tconnId: this.#connId,\n\t\t\t\t});\n\t\t\t\tthis.#connectWithRetry();\n\t\t\t}\n\t\t}\n\t}\n\n\t#rejectPendingPromises(error: Error, suppressUnhandled: boolean) {\n\t\tif (this.#onOpenPromise) {\n\t\t\tif (suppressUnhandled) {\n\t\t\t\tthis.#onOpenPromise.promise.catch(() => {});\n\t\t\t}\n\t\t\tthis.#onOpenPromise.reject(error);\n\t\t}\n\n\t\tfor (const actionInfo of this.#actionsInFlight.values()) {\n\t\t\tactionInfo.reject(error);\n\t\t}\n\t\tthis.#actionsInFlight.clear();\n\t}\n\n\t/** Called by the onerror event from drivers. */\n\t#handleOnError() {\n\t\tif (this.#disposed) return;\n\n\t\t// More detailed information will be logged in onclose\n\t\tlogger().warn(\"socket error\");\n\t}\n\n\t#takeActionInFlight(id: number): ActionInFlight {\n\t\tconst inFlight = this.#actionsInFlight.get(id);\n\t\tif (!inFlight) {\n\t\t\tlogger().error({\n\t\t\t\tmsg: \"action not found in in-flight map\",\n\t\t\t\tlookupId: id,\n\t\t\t\tinFlightCount: this.#actionsInFlight.size,\n\t\t\t\tinFlightIds: Array.from(this.#actionsInFlight.keys()),\n\t\t\t\tinFlightActions: Array.from(\n\t\t\t\t\tthis.#actionsInFlight.entries(),\n\t\t\t\t).map(([id, action]) => ({\n\t\t\t\t\tid,\n\t\t\t\t\tname: action.name,\n\t\t\t\t})),\n\t\t\t});\n\t\t\tthrow new errors.InternalError(`No in flight response for ${id}`);\n\t\t}\n\t\tthis.#actionsInFlight.delete(id);\n\t\tlogger().debug({\n\t\t\tmsg: \"removed action from in-flight map\",\n\t\t\tactionId: id,\n\t\t\tactionName: inFlight.name,\n\t\t\tinFlightCount: this.#actionsInFlight.size,\n\t\t});\n\t\treturn inFlight;\n\t}\n\n\t#dispatchEvent(event: { name: string; args: unknown }) {\n\t\tconst { name, args } = event;\n\n\t\tconst listeners = this.#eventSubscriptions.get(name);\n\t\tif (!listeners) return;\n\n\t\t// Create a new array to avoid issues with listeners being removed during iteration\n\t\tfor (const listener of [...listeners]) {\n\t\t\tlistener.callback(...(args as unknown[]));\n\n\t\t\t// Remove if this was a one-time listener\n\t\t\tif (listener.once) {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t}\n\t\t}\n\n\t\t// Clean up empty listener sets\n\t\tif (listeners.size === 0) {\n\t\t\tthis.#eventSubscriptions.delete(name);\n\t\t}\n\t}\n\n\t#dispatchActorError(error: errors.ActorError) {\n\t\t// Call all registered error handlers\n\t\tfor (const handler of [...this.#errorHandlers]) {\n\t\t\ttry {\n\t\t\t\thandler(error);\n\t\t\t} catch (err) {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"error in connection error handler\",\n\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t#addEventSubscription<Args extends Array<unknown>>(\n\t\teventName: string,\n\t\tcallback: (...args: Args) => void,\n\t\tonce: boolean,\n\t): EventUnsubscribe {\n\t\tconst listener: EventSubscriptions<Args> = {\n\t\t\tcallback,\n\t\t\tonce,\n\t\t};\n\n\t\tlet subscriptionSet = this.#eventSubscriptions.get(eventName);\n\t\tif (subscriptionSet === undefined) {\n\t\t\tsubscriptionSet = new Set();\n\t\t\tthis.#eventSubscriptions.set(eventName, subscriptionSet);\n\t\t\tthis.#sendSubscription(eventName, true);\n\t\t}\n\t\tsubscriptionSet.add(listener);\n\n\t\t// Return unsubscribe function\n\t\treturn () => {\n\t\t\tconst listeners = this.#eventSubscriptions.get(eventName);\n\t\t\tif (listeners) {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t\tif (listeners.size === 0) {\n\t\t\t\t\tthis.#eventSubscriptions.delete(eventName);\n\t\t\t\t\tthis.#sendSubscription(eventName, false);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Subscribes to an event that will happen repeatedly.\n\t *\n\t * @template Args - The type of arguments the event callback will receive.\n\t * @param {string} eventName - The name of the event to subscribe to.\n\t * @param {(...args: Args) => void} callback - The callback function to execute when the event is triggered.\n\t * @returns {EventUnsubscribe} - A function to unsubscribe from the event.\n\t * @see {@link https://rivet.dev/docs/events|Events Documentation}\n\t */\n\ton<Args extends Array<unknown> = unknown[]>(\n\t\teventName: string,\n\t\tcallback: (...args: Args) => void,\n\t): EventUnsubscribe {\n\t\treturn this.#addEventSubscription<Args>(eventName, callback, false);\n\t}\n\n\t/**\n\t * Subscribes to an event that will be triggered only once.\n\t *\n\t * @template Args - The type of arguments the event callback will receive.\n\t * @param {string} eventName - The name of the event to subscribe to.\n\t * @param {(...args: Args) => void} callback - The callback function to execute when the event is triggered.\n\t * @returns {EventUnsubscribe} - A function to unsubscribe from the event.\n\t * @see {@link https://rivet.dev/docs/events|Events Documentation}\n\t */\n\tonce<Args extends Array<unknown> = unknown[]>(\n\t\teventName: string,\n\t\tcallback: (...args: Args) => void,\n\t): EventUnsubscribe {\n\t\treturn this.#addEventSubscription<Args>(eventName, callback, true);\n\t}\n\n\t/**\n\t * Subscribes to connection errors.\n\t *\n\t * @param {ActorErrorCallback} callback - The callback function to execute when a connection error occurs.\n\t * @returns {() => void} - A function to unsubscribe from the error handler.\n\t */\n\tonError(callback: ActorErrorCallback): () => void {\n\t\tthis.#errorHandlers.add(callback);\n\n\t\t// Return unsubscribe function\n\t\treturn () => {\n\t\t\tthis.#errorHandlers.delete(callback);\n\t\t};\n\t}\n\n\t/**\n\t * Returns the current connection status.\n\t *\n\t * @returns {ActorConnStatus} - The current connection status.\n\t */\n\tget connStatus(): ActorConnStatus {\n\t\treturn this.#connStatus;\n\t}\n\n\t/**\n\t * Returns whether the connection is currently open.\n\t *\n\t * @deprecated Use `connStatus` instead.\n\t * @returns {boolean} - True if the connection is open, false otherwise.\n\t */\n\tget isConnected(): boolean {\n\t\treturn this.#connStatus === \"connected\";\n\t}\n\n\t/**\n\t * Subscribes to connection open events.\n\t *\n\t * This is called when the WebSocket connection is established and the Init message is received.\n\t *\n\t * @param {ConnectionStateCallback} callback - The callback function to execute when the connection opens.\n\t * @returns {() => void} - A function to unsubscribe from the open handler.\n\t */\n\tonOpen(callback: ConnectionStateCallback): () => void {\n\t\tthis.#openHandlers.add(callback);\n\n\t\t// Return unsubscribe function\n\t\treturn () => {\n\t\t\tthis.#openHandlers.delete(callback);\n\t\t};\n\t}\n\n\t/**\n\t * Subscribes to connection close events.\n\t *\n\t * This is called when the WebSocket connection is closed. The connection will automatically\n\t * attempt to reconnect unless disposed.\n\t *\n\t * @param {ConnectionStateCallback} callback - The callback function to execute when the connection closes.\n\t * @returns {() => void} - A function to unsubscribe from the close handler.\n\t */\n\tonClose(callback: ConnectionStateCallback): () => void {\n\t\tthis.#closeHandlers.add(callback);\n\n\t\t// Return unsubscribe function\n\t\treturn () => {\n\t\t\tthis.#closeHandlers.delete(callback);\n\t\t};\n\t}\n\n\t/**\n\t * Subscribes to connection status changes.\n\t *\n\t * This is called whenever the connection status changes between Disconnected, Connecting, and Connected.\n\t *\n\t * @param {StatusChangeCallback} callback - The callback function to execute when the status changes.\n\t * @returns {() => void} - A function to unsubscribe from the status change handler.\n\t */\n\tonStatusChange(callback: StatusChangeCallback): () => void {\n\t\tthis.#statusChangeHandlers.add(callback);\n\n\t\t// Return unsubscribe function\n\t\treturn () => {\n\t\t\tthis.#statusChangeHandlers.delete(callback);\n\t\t};\n\t}\n\n\t#sendMessage(\n\t\tmessage: {\n\t\t\tbody:\n\t\t\t\t| {\n\t\t\t\t\t\ttag: \"ActionRequest\";\n\t\t\t\t\t\tval: { id: bigint; name: string; args: unknown };\n\t\t\t\t }\n\t\t\t\t| {\n\t\t\t\t\t\ttag: \"SubscriptionRequest\";\n\t\t\t\t\t\tval: { eventName: string; subscribe: boolean };\n\t\t\t\t };\n\t\t},\n\t\topts?: SendHttpMessageOpts,\n\t) {\n\t\tif (this.#disposed) {\n\t\t\tif (opts?.ephemeral) {\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tthrow new errors.ActorConnDisposed();\n\t\t\t}\n\t\t}\n\n\t\tlet queueMessage = false;\n\t\tif (this.#websocket) {\n\t\t\tconst readyState = this.#websocket.readyState;\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"websocket send attempt\",\n\t\t\t\treadyState,\n\t\t\t\treadyStateString:\n\t\t\t\t\treadyState === 0\n\t\t\t\t\t\t? \"CONNECTING\"\n\t\t\t\t\t\t: readyState === 1\n\t\t\t\t\t\t\t? \"OPEN\"\n\t\t\t\t\t\t\t: readyState === 2\n\t\t\t\t\t\t\t\t? \"CLOSING\"\n\t\t\t\t\t\t\t\t: \"CLOSED\",\n\t\t\t\tconnId: this.#connId,\n\t\t\t\tmessageType: (message.body as any).tag,\n\t\t\t\tactionName: (message.body as any).val?.name,\n\t\t\t});\n\t\t\tif (this.#connStatus !== \"connected\") {\n\t\t\t\tlogger().debug({\n\t\t\t\t\tmsg: \"websocket init pending, queueing message\",\n\t\t\t\t\tconnStatus: this.#connStatus,\n\t\t\t\t\tmessageType: (message.body as any).tag,\n\t\t\t\t});\n\t\t\t\tqueueMessage = true;\n\t\t\t} else if (readyState === 1) {\n\t\t\t\ttry {\n\t\t\t\t\tconst messageSerialized = serializeWithEncoding(\n\t\t\t\t\t\tthis.#encoding,\n\t\t\t\t\t\tmessage,\n\t\t\t\t\t\tTO_SERVER_VERSIONED,\n\t\t\t\t\t\tCLIENT_PROTOCOL_CURRENT_VERSION,\n\t\t\t\t\t\tToServerSchema,\n\t\t\t\t\t\t// JSON: args is the raw value\n\t\t\t\t\t\t(msg): ToServerJson => msg as ToServerJson,\n\t\t\t\t\t\t// BARE: args needs to be CBOR-encoded to ArrayBuffer\n\t\t\t\t\t\t(msg): protocol.ToServer => {\n\t\t\t\t\t\t\tif (msg.body.tag === \"ActionRequest\") {\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\t\t\ttag: \"ActionRequest\",\n\t\t\t\t\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\t\t\t\t\tid: msg.body.val.id,\n\t\t\t\t\t\t\t\t\t\t\tname: msg.body.val.name,\n\t\t\t\t\t\t\t\t\t\t\targs: bufferToArrayBuffer(\n\t\t\t\t\t\t\t\t\t\t\t\tcbor.encode(msg.body.val.args),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\treturn msg as protocol.ToServer;\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\tthis.#websocket.send(messageSerialized);\n\t\t\t\t\tlogger().trace({\n\t\t\t\t\t\tmsg: \"sent websocket message\",\n\t\t\t\t\t\tlen: messageLength(messageSerialized),\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlogger().warn({\n\t\t\t\t\t\tmsg: \"failed to send message, added to queue\",\n\t\t\t\t\t\terror,\n\t\t\t\t\t\tconnId: this.#connId,\n\t\t\t\t\t});\n\n\t\t\t\t\t// Assuming the socket is disconnected and will be reconnected soon\n\t\t\t\t\tqueueMessage = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlogger().debug({\n\t\t\t\t\tmsg: \"websocket not open, queueing message\",\n\t\t\t\t\treadyState,\n\t\t\t\t});\n\t\t\t\tqueueMessage = true;\n\t\t\t}\n\t\t} else {\n\t\t\t// No websocket connected yet\n\t\t\tlogger().debug({ msg: \"no websocket, queueing message\" });\n\t\t\tqueueMessage = true;\n\t\t}\n\n\t\tif (!opts?.ephemeral && queueMessage) {\n\t\t\tthis.#messageQueue.push(message);\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"queued connection message\",\n\t\t\t\tqueueLength: this.#messageQueue.length,\n\t\t\t\tconnId: this.#connId,\n\t\t\t\tmessageType: (message.body as any).tag,\n\t\t\t\tactionName: (message.body as any).val?.name,\n\t\t\t});\n\t\t}\n\t}\n\n\tasync #parseMessage(data: ConnMessage): Promise<{\n\t\tbody:\n\t\t\t| { tag: \"Init\"; val: { actorId: string; connectionId: string } }\n\t\t\t| {\n\t\t\t\t\ttag: \"Error\";\n\t\t\t\t\tval: {\n\t\t\t\t\t\tgroup: string;\n\t\t\t\t\t\tcode: string;\n\t\t\t\t\t\tmessage: string;\n\t\t\t\t\t\tmetadata: unknown;\n\t\t\t\t\t\tactionId: bigint | null;\n\t\t\t\t\t};\n\t\t\t }\n\t\t\t| { tag: \"ActionResponse\"; val: { id: bigint; output: unknown } }\n\t\t\t| { tag: \"Event\"; val: { name: string; args: unknown } };\n\t}> {\n\t\tinvariant(this.#websocket, \"websocket must be defined\");\n\n\t\tconst buffer = await inputDataToBuffer(data);\n\n\t\treturn deserializeWithEncoding(\n\t\t\tthis.#encoding,\n\t\t\tbuffer,\n\t\t\tTO_CLIENT_VERSIONED,\n\t\t\tToClientSchema,\n\t\t\t// JSON: values are already the correct type\n\t\t\t(msg): ToClientJson => msg as ToClientJson,\n\t\t\t// BARE: need to decode ArrayBuffer fields back to unknown\n\t\t\t(msg): any => {\n\t\t\t\tif (msg.body.tag === \"Error\") {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\ttag: \"Error\",\n\t\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\t\tgroup: msg.body.val.group,\n\t\t\t\t\t\t\t\tcode: msg.body.val.code,\n\t\t\t\t\t\t\t\tmessage: msg.body.val.message,\n\t\t\t\t\t\t\t\tmetadata: msg.body.val.metadata\n\t\t\t\t\t\t\t\t\t? cbor.decode(\n\t\t\t\t\t\t\t\t\t\t\tnew Uint8Array(\n\t\t\t\t\t\t\t\t\t\t\t\tmsg.body.val.metadata,\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t\tactionId: msg.body.val.actionId,\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} else if (msg.body.tag === \"ActionResponse\") {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\ttag: \"ActionResponse\",\n\t\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\t\tid: msg.body.val.id,\n\t\t\t\t\t\t\t\toutput: cbor.decode(\n\t\t\t\t\t\t\t\t\tnew Uint8Array(msg.body.val.output),\n\t\t\t\t\t\t\t\t),\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} else if (msg.body.tag === \"Event\") {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\ttag: \"Event\",\n\t\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\t\tname: msg.body.val.name,\n\t\t\t\t\t\t\t\targs: cbor.decode(\n\t\t\t\t\t\t\t\t\tnew Uint8Array(msg.body.val.args),\n\t\t\t\t\t\t\t\t),\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} else {\n\t\t\t\t\t// Init has no ArrayBuffer fields\n\t\t\t\t\treturn msg;\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * Get the actor ID (for testing purposes).\n\t * @internal\n\t */\n\tget actorId(): string | undefined {\n\t\treturn this.#actorId;\n\t}\n\n\t/**\n\t * Get the connection ID (for testing purposes).\n\t * @internal\n\t */\n\tget connId(): string | undefined {\n\t\treturn this.#connId;\n\t}\n\n\t/**\n\t * Get the connection ID (for testing purposes).\n\t * @internal\n\t * @deprecated Use `connId` instead.\n\t */\n\tget connectionId(): string | undefined {\n\t\treturn this.#connId;\n\t}\n\n\t/**\n\t * Disconnects from the actor.\n\t *\n\t * @returns {Promise<void>} A promise that resolves when the socket is gracefully closed.\n\t */\n\tasync dispose(): Promise<void> {\n\t\t// Internally, this \"disposes\" the connection\n\n\t\tif (this.#disposed) {\n\t\t\tlogger().warn({ msg: \"connection already disconnected\" });\n\t\t\treturn;\n\t\t}\n\t\tthis.#disposed = true;\n\n\t\tlogger().debug({ msg: \"disposing actor conn\" });\n\n\t\t// Set status to Idle (intentionally closed, no auto-reconnect)\n\t\tthis.#setConnStatus(\"idle\");\n\n\t\t// Clear interval so NodeJS process can exit\n\t\tclearInterval(this.#keepNodeAliveInterval);\n\n\t\t// Abort retry loop\n\t\tthis.#abortController.abort();\n\n\t\t// Remove from registry\n\t\tthis.#client[ACTOR_CONNS_SYMBOL].delete(this);\n\n\t\t// Close websocket (#handleOnClose will reject pending promises)\n\t\tif (this.#websocket) {\n\t\t\tconst ws = this.#websocket;\n\t\t\tif (\n\t\t\t\tws.readyState !== 2 /* CLOSING */ &&\n\t\t\t\tws.readyState !== 3 /* CLOSED */\n\t\t\t) {\n\t\t\t\tconst { promise, resolve } = promiseWithResolvers((reason) => logger().warn({ msg: \"unhandled websocket close promise rejection\", reason }));\n\t\t\t\tws.addEventListener(\"close\", () => resolve(undefined));\n\t\t\t\tws.close(1000, \"Disposed\");\n\t\t\t\tawait promise;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.#rejectPendingPromises(new errors.ActorConnDisposed(), true);\n\t\t}\n\t\tthis.#websocket = undefined;\n\t}\n\n\t#sendSubscription(eventName: string, subscribe: boolean) {\n\t\tthis.#sendMessage(\n\t\t\t{\n\t\t\t\tbody: {\n\t\t\t\t\ttag: \"SubscriptionRequest\",\n\t\t\t\t\tval: {\n\t\t\t\t\t\teventName,\n\t\t\t\t\t\tsubscribe,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{ ephemeral: true },\n\t\t);\n\t}\n}\n\n/**\n * Connection to a actor. Allows calling actor's remote procedure calls with inferred types. See {@link ActorConnRaw} for underlying methods.\n *\n * @example\n * ```\n * const room = client.connect<ChatRoom>(...etc...);\n * // This calls the action named `sendMessage` on the `ChatRoom` actor.\n * await room.sendMessage('Hello, world!');\n * ```\n *\n * Private methods (e.g. those starting with `_`) are automatically excluded.\n *\n * @template AD The actor class that this connection is for.\n * @see {@link ActorConnRaw}\n */\nexport type ActorConn<AD extends AnyActorDefinition> = ActorConnRaw &\n\tActorDefinitionActions<AD>;\n","import type { Context as HonoContext } from \"hono\";\nimport * as errors from \"@/actor/errors\";\nimport { stringifyError } from \"@/common/utils\";\nimport type { ManagerDriver } from \"@/driver-helpers/mod\";\nimport type { ActorQuery } from \"@/manager/protocol/query\";\nimport { ActorSchedulingError } from \"./errors\";\nimport { logger } from \"./log\";\n\n/**\n * Query the manager driver to get or create a actor based on the provided query\n */\nexport async function queryActor(\n\tc: HonoContext | undefined,\n\tquery: ActorQuery,\n\tmanagerDriver: ManagerDriver,\n): Promise<{ actorId: string }> {\n\tlogger().debug({ msg: \"querying actor\", query: JSON.stringify(query) });\n\tlet actorOutput: { actorId: string };\n\tif (\"getForId\" in query) {\n\t\tconst output = await managerDriver.getForId({\n\t\t\tc,\n\t\t\tname: query.getForId.name,\n\t\t\tactorId: query.getForId.actorId,\n\t\t});\n\t\tif (!output) throw new errors.ActorNotFound(query.getForId.actorId);\n\t\tactorOutput = output;\n\t} else if (\"getForKey\" in query) {\n\t\tconst existingActor = await managerDriver.getWithKey({\n\t\t\tc,\n\t\t\tname: query.getForKey.name,\n\t\t\tkey: query.getForKey.key,\n\t\t});\n\t\tif (!existingActor) {\n\t\t\tthrow new errors.ActorNotFound(\n\t\t\t\t`${query.getForKey.name}:${JSON.stringify(query.getForKey.key)}`,\n\t\t\t);\n\t\t}\n\t\tactorOutput = existingActor;\n\t} else if (\"getOrCreateForKey\" in query) {\n\t\tconst getOrCreateOutput = await managerDriver.getOrCreateWithKey({\n\t\t\tc,\n\t\t\tname: query.getOrCreateForKey.name,\n\t\t\tkey: query.getOrCreateForKey.key,\n\t\t\tinput: query.getOrCreateForKey.input,\n\t\t\tregion: query.getOrCreateForKey.region,\n\t\t});\n\t\tactorOutput = {\n\t\t\tactorId: getOrCreateOutput.actorId,\n\t\t};\n\t} else if (\"create\" in query) {\n\t\tconst createOutput = await managerDriver.createActor({\n\t\t\tc,\n\t\t\tname: query.create.name,\n\t\t\tkey: query.create.key,\n\t\t\tinput: query.create.input,\n\t\t\tregion: query.create.region,\n\t\t});\n\t\tactorOutput = {\n\t\t\tactorId: createOutput.actorId,\n\t\t};\n\t} else {\n\t\tthrow new errors.InvalidRequest(\"Invalid query format\");\n\t}\n\n\tlogger().debug({ msg: \"actor query result\", actorId: actorOutput.actorId });\n\treturn { actorId: actorOutput.actorId };\n}\n\n/**\n * Extract the actor name from a query.\n */\nexport function getActorNameFromQuery(query: ActorQuery): string {\n\tif (\"getForId\" in query) return query.getForId.name;\n\tif (\"getForKey\" in query) return query.getForKey.name;\n\tif (\"getOrCreateForKey\" in query) return query.getOrCreateForKey.name;\n\tif (\"create\" in query) return query.create.name;\n\tthrow new errors.InvalidRequest(\"Invalid query format\");\n}\n\n/**\n * Fetch actor details and check for scheduling errors.\n */\nexport async function checkForSchedulingError(\n\tgroup: string,\n\tcode: string,\n\tactorId: string,\n\tquery: ActorQuery,\n\tdriver: ManagerDriver,\n): Promise<ActorSchedulingError | null> {\n\tconst name = getActorNameFromQuery(query);\n\n\ttry {\n\t\tconst actor = await driver.getForId({ name, actorId });\n\n\t\tif (actor?.error) {\n\t\t\tlogger().info({\n\t\t\t\tmsg: \"found actor scheduling error\",\n\t\t\t\tactorId,\n\t\t\t\terror: actor.error,\n\t\t\t});\n\t\t\treturn new ActorSchedulingError(group, code, actorId, actor.error);\n\t\t}\n\t} catch (err) {\n\t\tlogger().warn({\n\t\t\tmsg: \"failed to fetch actor details for scheduling error check\",\n\t\t\tactorId,\n\t\t\terror: stringifyError(err),\n\t\t});\n\t}\n\n\treturn null;\n}\n","import * as cbor from \"cbor-x\";\nimport type { Encoding } from \"@/actor/protocol/serde\";\nimport { HEADER_CONN_PARAMS, HEADER_ENCODING } from \"@/driver-helpers/mod\";\nimport type * as protocol from \"@/schemas/client-protocol/mod\";\nimport {\n\tCURRENT_VERSION as CLIENT_PROTOCOL_CURRENT_VERSION,\n\tHTTP_QUEUE_SEND_REQUEST_VERSIONED,\n\tHTTP_QUEUE_SEND_RESPONSE_VERSIONED,\n} from \"@/schemas/client-protocol/versioned\";\nimport {\n\ttype HttpQueueSendRequest as HttpQueueSendRequestJson,\n\tHttpQueueSendRequestSchema,\n\ttype HttpQueueSendResponse as HttpQueueSendResponseJson,\n\tHttpQueueSendResponseSchema,\n} from \"@/schemas/client-protocol-zod/mod\";\nimport { bufferToArrayBuffer } from \"@/utils\";\nimport { sendHttpRequest } from \"./utils\";\n\nexport interface QueueSender {\n\tsend(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions: QueueSendWaitOptions,\n\t): Promise<QueueSendResult>;\n\tsend(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions?: QueueSendNoWaitOptions,\n\t): Promise<void>;\n}\n\nexport interface QueueSendWaitOptions {\n\twait: true;\n\ttimeout?: number;\n\tsignal?: AbortSignal;\n}\n\nexport interface QueueSendNoWaitOptions {\n\twait?: false;\n\ttimeout?: never;\n\tsignal?: AbortSignal;\n}\n\nexport type QueueSendOptions = QueueSendWaitOptions | QueueSendNoWaitOptions;\n\nexport interface QueueSendResult {\n\tstatus: \"completed\" | \"timedOut\";\n\tresponse?: unknown;\n}\n\ninterface QueueSenderOptions {\n\tencoding: Encoding;\n\tparams: unknown;\n\tcustomFetch: (request: Request) => Promise<Response>;\n}\n\nexport function createQueueSender(senderOptions: QueueSenderOptions): QueueSender {\n\tasync function send(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions: QueueSendWaitOptions,\n\t): Promise<QueueSendResult>;\n\tasync function send(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions?: QueueSendNoWaitOptions,\n\t): Promise<void>;\n\tasync function send(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions?: QueueSendOptions,\n\t): Promise<QueueSendResult | void> {\n\t\tconst wait = options?.wait ?? false;\n\t\tconst timeout = options?.timeout;\n\n\t\tconst result = await sendHttpRequest<\n\t\t\tprotocol.HttpQueueSendRequest,\n\t\t\tprotocol.HttpQueueSendResponse,\n\t\t\tHttpQueueSendRequestJson,\n\t\t\tHttpQueueSendResponseJson,\n\t\t\t{ body: unknown; wait?: boolean; timeout?: number; name?: string },\n\t\t\tQueueSendResult\n\t\t>({\n\t\t\turl: `http://actor/queue/${encodeURIComponent(name)}`,\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t[HEADER_ENCODING]: senderOptions.encoding,\n\t\t\t\t...(senderOptions.params !== undefined\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t[HEADER_CONN_PARAMS]: JSON.stringify(\n\t\t\t\t\t\t\t\tsenderOptions.params,\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},\n\t\t\tbody: { body, wait, timeout },\n\t\t\tencoding: senderOptions.encoding,\n\t\t\tcustomFetch: senderOptions.customFetch,\n\t\t\tsignal: options?.signal,\n\t\t\trequestVersion: CLIENT_PROTOCOL_CURRENT_VERSION,\n\t\t\trequestVersionedDataHandler: HTTP_QUEUE_SEND_REQUEST_VERSIONED,\n\t\t\tresponseVersion: CLIENT_PROTOCOL_CURRENT_VERSION,\n\t\t\tresponseVersionedDataHandler:\n\t\t\t\tHTTP_QUEUE_SEND_RESPONSE_VERSIONED,\n\t\t\trequestZodSchema: HttpQueueSendRequestSchema,\n\t\t\tresponseZodSchema: HttpQueueSendResponseSchema,\n\t\t\trequestToJson: (value): HttpQueueSendRequestJson => ({\n\t\t\t\t...value,\n\t\t\t\tname,\n\t\t\t}),\n\t\t\trequestToBare: (value): protocol.HttpQueueSendRequest => ({\n\t\t\t\tname: value.name ?? name,\n\t\t\t\tbody: bufferToArrayBuffer(cbor.encode(value.body)),\n\t\t\t\twait: value.wait ?? false,\n\t\t\t\ttimeout: value.timeout !== undefined ? BigInt(value.timeout) : null,\n\t\t\t}),\n\t\t\tresponseFromJson: (json): QueueSendResult => {\n\t\t\t\tif (json.response === undefined) {\n\t\t\t\t\treturn { status: json.status as \"completed\" | \"timedOut\" };\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tstatus: json.status as \"completed\" | \"timedOut\",\n\t\t\t\t\tresponse: json.response,\n\t\t\t\t};\n\t\t\t},\n\t\t\tresponseFromBare: (bare): QueueSendResult => {\n\t\t\t\tif (bare.response === null || bare.response === undefined) {\n\t\t\t\t\treturn { status: bare.status as \"completed\" | \"timedOut\" };\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tstatus: bare.status as \"completed\" | \"timedOut\",\n\t\t\t\t\tresponse: cbor.decode(new Uint8Array(bare.response)),\n\t\t\t\t};\n\t\t\t},\n\t\t});\n\n\t\tif (wait) {\n\t\t\treturn result;\n\t\t}\n\t\treturn;\n\t}\n\n\treturn {\n\t\tsend,\n\t};\n}\n","import * as cbor from \"cbor-x\";\nimport invariant from \"invariant\";\nimport type { AnyActorDefinition } from \"@/actor/definition\";\nimport type { Encoding } from \"@/actor/protocol/serde\";\nimport { assertUnreachable } from \"@/actor/utils\";\nimport { deconstructError } from \"@/common/utils\";\nimport {\n\tHEADER_CONN_PARAMS,\n\tHEADER_ENCODING,\n\ttype ManagerDriver,\n} from \"@/driver-helpers/mod\";\nimport type { ActorQuery } from \"@/manager/protocol/query\";\nimport type * as protocol from \"@/schemas/client-protocol/mod\";\nimport {\n\tCURRENT_VERSION as CLIENT_PROTOCOL_CURRENT_VERSION,\n\tHTTP_ACTION_REQUEST_VERSIONED,\n\tHTTP_ACTION_RESPONSE_VERSIONED,\n} from \"@/schemas/client-protocol/versioned\";\nimport {\n\ttype HttpActionRequest as HttpActionRequestJson,\n\tHttpActionRequestSchema,\n\ttype HttpActionResponse as HttpActionResponseJson,\n\tHttpActionResponseSchema,\n} from \"@/schemas/client-protocol-zod/mod\";\nimport { bufferToArrayBuffer } from \"@/utils\";\nimport type { ActorDefinitionActions } from \"./actor-common\";\nimport { type ActorConn, ActorConnRaw } from \"./actor-conn\";\nimport { checkForSchedulingError, queryActor } from \"./actor-query\";\nimport { type ClientRaw, CREATE_ACTOR_CONN_PROXY } from \"./client\";\nimport { ActorError, isSchedulingError } from \"./errors\";\nimport { logger } from \"./log\";\nimport {\n\tcreateQueueSender,\n\ttype QueueSendNoWaitOptions,\n\ttype QueueSendOptions,\n\ttype QueueSendResult,\n\ttype QueueSendWaitOptions,\n} from \"./queue\";\nimport { rawHttpFetch, rawWebSocket } from \"./raw-utils\";\nimport { sendHttpRequest } from \"./utils\";\n\n/**\n * Provides underlying functions for stateless {@link ActorHandle} for action calls.\n * Similar to ActorConnRaw but doesn't maintain a connection.\n *\n * @see {@link ActorHandle}\n */\nexport class ActorHandleRaw {\n\t#client: ClientRaw;\n\t#driver: ManagerDriver;\n\t#encoding: Encoding;\n\t#actorQuery: ActorQuery;\n\t#params: unknown;\n\t#queueSender: ReturnType<typeof createQueueSender>;\n\n\t/**\n\t * Do not call this directly.\n\t *\n\t * Creates an instance of ActorHandleRaw.\n\t *\n\t * @protected\n\t */\n\tpublic constructor(\n\t\tclient: any,\n\t\tdriver: ManagerDriver,\n\t\tparams: unknown,\n\t\tencoding: Encoding,\n\t\tactorQuery: ActorQuery,\n\t) {\n\t\tthis.#client = client;\n\t\tthis.#driver = driver;\n\t\tthis.#encoding = encoding;\n\t\tthis.#actorQuery = actorQuery;\n\t\tthis.#params = params;\n\t\tthis.#queueSender = createQueueSender({\n\t\t\tencoding: this.#encoding,\n\t\t\tparams: this.#params,\n\t\t\tcustomFetch: async (request: Request) => {\n\t\t\t\tconst { actorId } = await queryActor(\n\t\t\t\t\tundefined,\n\t\t\t\t\tthis.#actorQuery,\n\t\t\t\t\tthis.#driver,\n\t\t\t\t);\n\t\t\t\treturn this.#driver.sendRequest(actorId, request);\n\t\t\t},\n\t\t});\n\t}\n\n\tsend(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions: QueueSendWaitOptions,\n\t): Promise<QueueSendResult>;\n\tsend(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions?: QueueSendNoWaitOptions,\n\t): Promise<void>;\n\tsend(\n\t\tname: string,\n\t\tbody: unknown,\n\t\toptions?: QueueSendOptions,\n\t): Promise<QueueSendResult | void> {\n\t\treturn this.#queueSender.send(name, body, options as any);\n\t}\n\n\t/**\n\t * Call a raw action. This method sends an HTTP request to invoke the named action.\n\t *\n\t * @see {@link ActorHandle}\n\t * @template Args - The type of arguments to pass to the action function.\n\t * @template Response - The type of the response returned by the action function.\n\t */\n\tasync action<\n\t\tArgs extends Array<unknown> = unknown[],\n\t\tResponse = unknown,\n\t>(opts: {\n\t\tname: string;\n\t\targs: Args;\n\t\tsignal?: AbortSignal;\n\t}): Promise<Response> {\n\t\t// Track actorId for scheduling error lookups\n\t\tlet actorId: string | undefined;\n\n\t\ttry {\n\t\t\t// Get the actor ID\n\t\t\tconst result = await queryActor(\n\t\t\t\tundefined,\n\t\t\t\tthis.#actorQuery,\n\t\t\t\tthis.#driver,\n\t\t\t);\n\t\t\tactorId = result.actorId;\n\t\t\tlogger().debug({ msg: \"found actor for action\", actorId });\n\t\t\tinvariant(actorId, \"Missing actor ID\");\n\n\t\t\t// Invoke the action\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"handling action\",\n\t\t\t\tname: opts.name,\n\t\t\t\tencoding: this.#encoding,\n\t\t\t});\n\t\t\tconst responseData = await sendHttpRequest<\n\t\t\t\tprotocol.HttpActionRequest, // Bare type\n\t\t\t\tprotocol.HttpActionResponse, // Bare type\n\t\t\t\tHttpActionRequestJson, // Json type\n\t\t\t\tHttpActionResponseJson, // Json type\n\t\t\t\tunknown[], // Request type (the args array)\n\t\t\t\tResponse // Response type (the output value)\n\t\t\t>({\n\t\t\t\turl: `http://actor/action/${encodeURIComponent(opts.name)}`,\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\t[HEADER_ENCODING]: this.#encoding,\n\t\t\t\t\t...(this.#params !== undefined\n\t\t\t\t\t\t? { [HEADER_CONN_PARAMS]: JSON.stringify(this.#params) }\n\t\t\t\t\t\t: {}),\n\t\t\t\t},\n\t\t\t\tbody: opts.args,\n\t\t\t\tencoding: this.#encoding,\n\t\t\t\tcustomFetch: this.#driver.sendRequest.bind(\n\t\t\t\t\tthis.#driver,\n\t\t\t\t\tactorId,\n\t\t\t\t),\n\t\t\t\tsignal: opts?.signal,\n\t\t\t\trequestVersion: CLIENT_PROTOCOL_CURRENT_VERSION,\n\t\t\t\trequestVersionedDataHandler: HTTP_ACTION_REQUEST_VERSIONED,\n\t\t\t\tresponseVersion: CLIENT_PROTOCOL_CURRENT_VERSION,\n\t\t\t\tresponseVersionedDataHandler: HTTP_ACTION_RESPONSE_VERSIONED,\n\t\t\t\trequestZodSchema: HttpActionRequestSchema,\n\t\t\t\tresponseZodSchema: HttpActionResponseSchema,\n\t\t\t\t// JSON Request: args is the raw value\n\t\t\t\trequestToJson: (args): HttpActionRequestJson => ({\n\t\t\t\t\targs,\n\t\t\t\t}),\n\t\t\t\t// BARE Request: args needs to be CBOR-encoded\n\t\t\t\trequestToBare: (args): protocol.HttpActionRequest => ({\n\t\t\t\t\targs: bufferToArrayBuffer(cbor.encode(args)),\n\t\t\t\t}),\n\t\t\t\t// JSON Response: output is the raw value\n\t\t\t\tresponseFromJson: (json): Response => json.output as Response,\n\t\t\t\t// BARE Response: output is ArrayBuffer that needs CBOR-decoding\n\t\t\t\tresponseFromBare: (bare): Response =>\n\t\t\t\t\tcbor.decode(new Uint8Array(bare.output)) as Response,\n\t\t\t});\n\n\t\t\treturn responseData;\n\t\t} catch (err) {\n\t\t\t// Standardize to ClientActorError instead of the native backend error\n\t\t\tconst { group, code, message, metadata } = deconstructError(\n\t\t\t\terr,\n\t\t\t\tlogger(),\n\t\t\t\t{},\n\t\t\t\ttrue,\n\t\t\t);\n\n\t\t\t// Check if this is a scheduling error and try to get more details\n\t\t\tif (actorId && isSchedulingError(group, code)) {\n\t\t\t\tconst schedulingError = await checkForSchedulingError(\n\t\t\t\t\tgroup,\n\t\t\t\t\tcode,\n\t\t\t\t\tactorId,\n\t\t\t\t\tthis.#actorQuery,\n\t\t\t\t\tthis.#driver,\n\t\t\t\t);\n\t\t\t\tif (schedulingError) {\n\t\t\t\t\tthrow schedulingError;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow new ActorError(group, code, message, metadata);\n\t\t}\n\t}\n\n\t/**\n\t * Establishes a persistent connection to the actor.\n\t *\n\t * @template AD The actor class that this connection is for.\n\t * @returns {ActorConn<AD>} A connection to the actor.\n\t */\n\tconnect(): ActorConn<AnyActorDefinition> {\n\t\tlogger().debug({\n\t\t\tmsg: \"establishing connection from handle\",\n\t\t\tquery: this.#actorQuery,\n\t\t});\n\n\t\tconst conn = new ActorConnRaw(\n\t\t\tthis.#client,\n\t\t\tthis.#driver,\n\t\t\tthis.#params,\n\t\t\tthis.#encoding,\n\t\t\tthis.#actorQuery,\n\t\t);\n\n\t\treturn this.#client[CREATE_ACTOR_CONN_PROXY](\n\t\t\tconn,\n\t\t) as ActorConn<AnyActorDefinition>;\n\t}\n\n\t/**\n\t * Fetches a resource from this actor via the /request endpoint. This is a\n\t * convenience wrapper around the raw HTTP API.\n\t */\n\tfetch(input: string | URL | Request, init?: RequestInit) {\n\t\treturn rawHttpFetch(\n\t\t\tthis.#driver,\n\t\t\tthis.#actorQuery,\n\t\t\tthis.#params,\n\t\t\tinput,\n\t\t\tinit,\n\t\t);\n\t}\n\n\t/**\n\t * Opens a raw WebSocket connection to this actor.\n\t */\n\twebSocket(path?: string, protocols?: string | string[]) {\n\t\treturn rawWebSocket(\n\t\t\tthis.#driver,\n\t\t\tthis.#actorQuery,\n\t\t\tthis.#params,\n\t\t\tpath,\n\t\t\tprotocols,\n\t\t);\n\t}\n\n\t/**\n\t * Resolves the actor to get its unique actor ID.\n\t */\n\tasync resolve(): Promise<string> {\n\t\tif (\"getForKey\" in this.#actorQuery) {\n\t\t\tconst name = this.#actorQuery.getForKey.name;\n\n\t\t\t// Query the actor to get the id\n\t\t\tconst { actorId } = await queryActor(\n\t\t\t\tundefined,\n\t\t\t\tthis.#actorQuery,\n\t\t\t\tthis.#driver,\n\t\t\t);\n\n\t\t\tthis.#actorQuery = { getForId: { actorId, name } };\n\n\t\t\treturn actorId;\n\t\t} else if (\"getOrCreateForKey\" in this.#actorQuery) {\n\t\t\tconst name = this.#actorQuery.getOrCreateForKey.name;\n\n\t\t\t// Query the actor to get or create and get the id\n\t\t\tconst { actorId } = await queryActor(\n\t\t\t\tundefined,\n\t\t\t\tthis.#actorQuery,\n\t\t\t\tthis.#driver,\n\t\t\t);\n\n\t\t\tthis.#actorQuery = { getForId: { actorId, name } };\n\n\t\t\treturn actorId;\n\t\t} else if (\"getForId\" in this.#actorQuery) {\n\t\t\t// Skip since it's already resolved\n\t\t\treturn this.#actorQuery.getForId.actorId;\n\t\t} else if (\"create\" in this.#actorQuery) {\n\t\t\t// Cannot create a handle with this query\n\t\t\tinvariant(false, \"actorQuery cannot be create\");\n\t\t} else {\n\t\t\tassertUnreachable(this.#actorQuery);\n\t\t}\n\t}\n\n\t/**\n\t * Returns the raw URL for routing traffic to the actor.\n\t */\n\tasync getGatewayUrl(): Promise<string> {\n\t\tconst { actorId } = await queryActor(\n\t\t\tundefined,\n\t\t\tthis.#actorQuery,\n\t\t\tthis.#driver,\n\t\t);\n\t\treturn await this.#driver.buildGatewayUrl(actorId);\n\t}\n}\n\n/**\n * Stateless handle to a actor. Allows calling actor's remote procedure calls with inferred types\n * without establishing a persistent connection.\n *\n * @example\n * ```\n * const room = client.get<ChatRoom>(...etc...);\n * // This calls the action named `sendMessage` on the `ChatRoom` actor without a connection.\n * await room.sendMessage('Hello, world!');\n * ```\n *\n * Private methods (e.g. those starting with `_`) are automatically excluded.\n *\n * @template AD The actor class that this handle is for.\n * @see {@link ActorHandleRaw}\n */\nexport type ActorHandle<AD extends AnyActorDefinition> = Omit<\n\tActorHandleRaw,\n\t\"connect\"\n> & {\n\t// Add typed version of ActorConn (instead of using AnyActorDefinition)\n\tconnect(): ActorConn<AD>;\n\t// Resolve method returns the actor ID\n\tresolve(): Promise<string>;\n} & ActorDefinitionActions<AD>;\n","import invariant from \"invariant\";\nimport { PATH_WEBSOCKET_PREFIX } from \"@/common/actor-router-consts\";\nimport { deconstructError } from \"@/common/utils\";\nimport { HEADER_CONN_PARAMS, type ManagerDriver } from \"@/driver-helpers/mod\";\nimport type { ActorQuery } from \"@/manager/protocol/query\";\nimport { queryActor } from \"./actor-query\";\nimport { ActorError } from \"./errors\";\nimport { logger } from \"./log\";\n\n/**\n * Shared implementation for raw HTTP fetch requests\n */\nexport async function rawHttpFetch(\n\tdriver: ManagerDriver,\n\tactorQuery: ActorQuery,\n\tparams: unknown,\n\tinput: string | URL | Request,\n\tinit?: RequestInit,\n): Promise<Response> {\n\t// Extract path and merge init options\n\tlet path: string;\n\tlet mergedInit: RequestInit = init || {};\n\n\tif (typeof input === \"string\") {\n\t\tpath = input;\n\t} else if (input instanceof URL) {\n\t\tpath = input.pathname + input.search;\n\t} else if (input instanceof Request) {\n\t\t// Extract path from Request URL\n\t\tconst url = new URL(input.url);\n\t\tpath = url.pathname + url.search;\n\t\t// Merge Request properties with init\n\t\tconst requestHeaders = new Headers(input.headers);\n\t\tconst initHeaders = new Headers(init?.headers || {});\n\n\t\t// Merge headers - init headers override request headers\n\t\tconst mergedHeaders = new Headers(requestHeaders);\n\t\tinitHeaders.forEach((value, key) => {\n\t\t\tmergedHeaders.set(key, value);\n\t\t});\n\n\t\tmergedInit = {\n\t\t\tmethod: input.method,\n\t\t\tbody: input.body,\n\t\t\tmode: input.mode,\n\t\t\tcredentials: input.credentials,\n\t\t\tredirect: input.redirect,\n\t\t\treferrer: input.referrer,\n\t\t\treferrerPolicy: input.referrerPolicy,\n\t\t\tintegrity: input.integrity,\n\t\t\tkeepalive: input.keepalive,\n\t\t\tsignal: input.signal,\n\t\t\t...mergedInit, // init overrides Request properties\n\t\t\theaders: mergedHeaders, // headers must be set after spread to ensure proper merge\n\t\t};\n\t\t// Add duplex if body is present\n\t\tif (mergedInit.body) {\n\t\t\t(mergedInit as any).duplex = \"half\";\n\t\t}\n\t} else {\n\t\tthrow new TypeError(\"Invalid input type for fetch\");\n\t}\n\n\ttry {\n\t\t// Get the actor ID\n\t\tconst { actorId } = await queryActor(undefined, actorQuery, driver);\n\t\tlogger().debug({ msg: \"found actor for raw http\", actorId });\n\t\tinvariant(actorId, \"Missing actor ID\");\n\n\t\t// Build the URL with normalized path\n\t\tconst normalizedPath = path.startsWith(\"/\") ? path.slice(1) : path;\n\t\tconst url = new URL(`http://actor/request/${normalizedPath}`);\n\n\t\t// Forward conn params if provided\n\t\tconst proxyRequestHeaders = new Headers(mergedInit.headers);\n\t\tif (params) {\n\t\t\tproxyRequestHeaders.set(HEADER_CONN_PARAMS, JSON.stringify(params));\n\t\t}\n\n\t\t// Forward the request to the actor\n\t\tconst proxyRequest = new Request(url, {\n\t\t\t...mergedInit,\n\t\t\theaders: proxyRequestHeaders,\n\t\t});\n\n\t\treturn driver.sendRequest(actorId, proxyRequest);\n\t} catch (err) {\n\t\t// Standardize to ClientActorError instead of the native backend error\n\t\tconst { group, code, message, metadata } = deconstructError(\n\t\t\terr,\n\t\t\tlogger(),\n\t\t\t{},\n\t\t\ttrue,\n\t\t);\n\t\tthrow new ActorError(group, code, message, metadata);\n\t}\n}\n\n/**\n * Shared implementation for raw WebSocket connections\n */\nexport async function rawWebSocket(\n\tdriver: ManagerDriver,\n\tactorQuery: ActorQuery,\n\tparams: unknown,\n\tpath?: string,\n\t// TODO: Supportp rotocols\n\tprotocols?: string | string[],\n): Promise<any> {\n\t// TODO: Do we need encoding in rawWebSocket?\n\tconst encoding = \"bare\";\n\n\t// Get the actor ID\n\tconst { actorId } = await queryActor(undefined, actorQuery, driver);\n\tlogger().debug({ msg: \"found actor for action\", actorId });\n\tinvariant(actorId, \"Missing actor ID\");\n\n\t// Parse path and query parameters\n\tlet pathPortion = \"\";\n\tlet queryPortion = \"\";\n\tif (path) {\n\t\tconst queryIndex = path.indexOf(\"?\");\n\t\tif (queryIndex !== -1) {\n\t\t\tpathPortion = path.substring(0, queryIndex);\n\t\t\tqueryPortion = path.substring(queryIndex); // includes the '?'\n\t\t} else {\n\t\t\tpathPortion = path;\n\t\t}\n\t\t// Remove leading slash if present\n\t\tif (pathPortion.startsWith(\"/\")) {\n\t\t\tpathPortion = pathPortion.slice(1);\n\t\t}\n\t}\n\n\tconst fullPath = `${PATH_WEBSOCKET_PREFIX}${pathPortion}${queryPortion}`;\n\n\tlogger().debug({\n\t\tmsg: \"opening websocket\",\n\t\tactorId,\n\t\tencoding,\n\t\tpath: fullPath,\n\t});\n\n\t// Open WebSocket\n\tconst ws = await driver.openWebSocket(fullPath, actorId, encoding, params);\n\n\t// Node & browser WebSocket types are incompatible\n\treturn ws as any;\n}\n","import type { AnyActorDefinition } from \"@/actor/definition\";\nimport type { Encoding } from \"@/actor/protocol/serde\";\nimport type { ManagerDriver } from \"@/driver-helpers/mod\";\nimport type { ActorQuery } from \"@/manager/protocol/query\";\nimport type { Registry } from \"@/registry\";\nimport type { ActorActionFunction } from \"./actor-common\";\nimport {\n\ttype ActorConn,\n\ttype ActorConnRaw,\n\tCONNECT_SYMBOL,\n} from \"./actor-conn\";\nimport { type ActorHandle, ActorHandleRaw } from \"./actor-handle\";\nimport { queryActor } from \"./actor-query\";\nimport type { ClientConfig } from \"./config\";\nimport { logger } from \"./log\";\n\nexport type { ClientConfig, ClientConfigInput } from \"./config\";\n\n/** Extract the actor registry from the registry definition. */\nexport type ExtractActorsFromRegistry<A extends Registry<any>> =\n\tA extends Registry<infer Actors> ? Actors : never;\n\n/** Extract the registry definition from the client. */\nexport type ExtractRegistryFromClient<C extends Client<Registry<{}>>> =\n\tC extends Client<infer A> ? A : never;\n\n/**\n * Represents a actor accessor that provides methods to interact with a specific actor.\n */\nexport interface ActorAccessor<AD extends AnyActorDefinition> {\n\t/**\n\t * Gets a stateless handle to a actor by its key, but does not create the actor if it doesn't exist.\n\t * The actor name is automatically injected from the property accessor.\n\t *\n\t * @template AD The actor class that this handle is for.\n\t * @param {string | string[]} [key=[]] - The key to identify the actor. Can be a single string or an array of strings.\n\t * @param {GetWithIdOptions} [opts] - Options for getting the actor.\n\t * @returns {ActorHandle<AD>} - A handle to the actor.\n\t */\n\tget(key?: string | string[], opts?: GetWithIdOptions): ActorHandle<AD>;\n\n\t/**\n\t * Gets a stateless handle to a actor by its key, creating it if necessary.\n\t * The actor name is automatically injected from the property accessor.\n\t *\n\t * @template AD The actor class that this handle is for.\n\t * @param {string | string[]} [key=[]] - The key to identify the actor. Can be a single string or an array of strings.\n\t * @param {GetOptions} [opts] - Options for getting the actor.\n\t * @returns {ActorHandle<AD>} - A handle to the actor.\n\t */\n\tgetOrCreate(\n\t\tkey?: string | string[],\n\t\topts?: GetOrCreateOptions,\n\t): ActorHandle<AD>;\n\n\t/**\n\t * Gets a stateless handle to a actor by its ID.\n\t *\n\t * @template AD The actor class that this handle is for.\n\t * @param {string} actorId - The ID of the actor.\n\t * @param {GetWithIdOptions} [opts] - Options for getting the actor.\n\t * @returns {ActorHandle<AD>} - A handle to the actor.\n\t */\n\tgetForId(actorId: string, opts?: GetWithIdOptions): ActorHandle<AD>;\n\n\t/**\n\t * Creates a new actor with the name automatically injected from the property accessor,\n\t * and returns a stateless handle to it with the actor ID resolved.\n\t *\n\t * @template AD The actor class that this handle is for.\n\t * @param {string | string[]} key - The key to identify the actor. Can be a single string or an array of strings.\n\t * @param {CreateOptions} [opts] - Options for creating the actor (excluding name and key).\n\t * @returns {Promise<ActorHandle<AD>>} - A promise that resolves to a handle to the actor.\n\t */\n\tcreate(\n\t\tkey?: string | string[],\n\t\topts?: CreateOptions,\n\t): Promise<ActorHandle<AD>>;\n}\n\n/**\n * Options for querying actors.\n * @typedef {Object} QueryOptions\n * @property {unknown} [parameters] - Parameters to pass to the connection.\n */\nexport interface QueryOptions {\n\t/** Parameters to pass to the connection. */\n\tparams?: unknown;\n\t/** Signal to abort the request. */\n\tsignal?: AbortSignal;\n}\n\n/**\n * Options for getting a actor by ID.\n * @typedef {QueryOptions} GetWithIdOptions\n */\nexport interface GetWithIdOptions extends QueryOptions {}\n\n/**\n * Options for getting a actor.\n * @typedef {QueryOptions} GetOptions\n */\nexport interface GetOptions extends QueryOptions {}\n\n/**\n * Options for getting or creating a actor.\n * @typedef {QueryOptions} GetOrCreateOptions\n * @property {string} [createInRegion] - Region to create the actor in if it doesn't exist.\n */\nexport interface GetOrCreateOptions extends QueryOptions {\n\t/** Region to create the actor in if it doesn't exist. */\n\tcreateInRegion?: string;\n\t/** Input data to pass to the actor. */\n\tcreateWithInput?: unknown;\n}\n\n/**\n * Options for creating a actor.\n * @typedef {QueryOptions} CreateOptions\n * @property {string} [region] - The region to create the actor in.\n */\nexport interface CreateOptions extends QueryOptions {\n\t/** The region to create the actor in. */\n\tregion?: string;\n\t/** Input data to pass to the actor. */\n\tinput?: unknown;\n}\n\n/**\n * Represents a region to connect to.\n * @typedef {Object} Region\n * @property {string} id - The region ID.\n * @property {string} name - The region name.\n * @see {@link https://rivet.dev/docs/edge|Edge Networking}\n * @see {@link https://rivet.dev/docs/regions|Available Regions}\n */\nexport interface Region {\n\t/**\n\t * The region slug.\n\t */\n\tid: string;\n\n\t/**\n\t * The human-friendly region name.\n\t */\n\tname: string;\n}\n\nexport const ACTOR_CONNS_SYMBOL = Symbol(\"actorConns\");\nexport const CREATE_ACTOR_CONN_PROXY = Symbol(\"createActorConnProxy\");\n\n/**\n * Client for managing & connecting to actors.\n *\n * @template A The actors map type that defines the available actors.\n * @see {@link https://rivet.dev/docs/manage|Create & Manage Actors}\n */\nexport class ClientRaw {\n\t#disposed = false;\n\n\t[ACTOR_CONNS_SYMBOL] = new Set<ActorConnRaw>();\n\n\t#driver: ManagerDriver;\n\t#encodingKind: Encoding;\n\n\t/**\n\t * Creates an instance of Client.\n\t */\n\tpublic constructor(driver: ManagerDriver, encoding: Encoding | undefined) {\n\t\tthis.#driver = driver;\n\n\t\tthis.#encodingKind = encoding ?? \"bare\";\n\t}\n\n\t/**\n\t * Gets a stateless handle to a actor by its ID.\n\t *\n\t * @template AD The actor class that this handle is for.\n\t * @param {string} name - The name of the actor.\n\t * @param {string} actorId - The ID of the actor.\n\t * @param {GetWithIdOptions} [opts] - Options for getting the actor.\n\t * @returns {ActorHandle<AD>} - A handle to the actor.\n\t */\n\tgetForId<AD extends AnyActorDefinition>(\n\t\tname: string,\n\t\tactorId: string,\n\t\topts?: GetWithIdOptions,\n\t): ActorHandle<AD> {\n\t\tlogger().debug({\n\t\t\tmsg: \"get handle to actor with id\",\n\t\t\tname,\n\t\t\tactorId,\n\t\t\tparams: opts?.params,\n\t\t});\n\n\t\tconst actorQuery: ActorQuery = {\n\t\t\tgetForId: {\n\t\t\t\tname,\n\t\t\t\tactorId,\n\t\t\t},\n\t\t};\n\n\t\tconst handle = this.#createHandle(opts?.params, actorQuery);\n\t\treturn createActorProxy(handle) as ActorHandle<AD>;\n\t}\n\n\t/**\n\t * Gets a stateless handle to a actor by its key, but does not create the actor if it doesn't exist.\n\t *\n\t * @template AD The actor class that this handle is for.\n\t * @param {string} name - The name of the actor.\n\t * @param {string | string[]} [key=[]] - The key to identify the actor. Can be a single string or an array of strings.\n\t * @param {GetWithIdOptions} [opts] - Options for getting the actor.\n\t * @returns {ActorHandle<AD>} - A handle to the actor.\n\t */\n\tget<AD extends AnyActorDefinition>(\n\t\tname: string,\n\t\tkey?: string | string[],\n\t\topts?: GetWithIdOptions,\n\t): ActorHandle<AD> {\n\t\t// Convert string to array of strings\n\t\tconst keyArray: string[] = typeof key === \"string\" ? [key] : key || [];\n\n\t\tlogger().debug({\n\t\t\tmsg: \"get handle to actor\",\n\t\t\tname,\n\t\t\tkey: keyArray,\n\t\t\tparameters: opts?.params,\n\t\t});\n\n\t\tconst actorQuery: ActorQuery = {\n\t\t\tgetForKey: {\n\t\t\t\tname,\n\t\t\t\tkey: keyArray,\n\t\t\t},\n\t\t};\n\n\t\tconst handle = this.#createHandle(opts?.params, actorQuery);\n\t\treturn createActorProxy(handle) as ActorHandle<AD>;\n\t}\n\n\t/**\n\t * Gets a stateless handle to a actor by its key, creating it if necessary.\n\t *\n\t * @template AD The actor class that this handle is for.\n\t * @param {string} name - The name of the actor.\n\t * @param {string | string[]} [key=[]] - The key to identify the actor. Can be a single string or an array of strings.\n\t * @param {GetOptions} [opts] - Options for getting the actor.\n\t * @returns {ActorHandle<AD>} - A handle to the actor.\n\t */\n\tgetOrCreate<AD extends AnyActorDefinition>(\n\t\tname: string,\n\t\tkey?: string | string[],\n\t\topts?: GetOrCreateOptions,\n\t): ActorHandle<AD> {\n\t\t// Convert string to array of strings\n\t\tconst keyArray: string[] = typeof key === \"string\" ? [key] : key || [];\n\n\t\tlogger().debug({\n\t\t\tmsg: \"get or create handle to actor\",\n\t\t\tname,\n\t\t\tkey: keyArray,\n\t\t\tparameters: opts?.params,\n\t\t\tcreateInRegion: opts?.createInRegion,\n\t\t});\n\n\t\tconst actorQuery: ActorQuery = {\n\t\t\tgetOrCreateForKey: {\n\t\t\t\tname,\n\t\t\t\tkey: keyArray,\n\t\t\t\tinput: opts?.createWithInput,\n\t\t\t\tregion: opts?.createInRegion,\n\t\t\t},\n\t\t};\n\n\t\tconst handle = this.#createHandle(opts?.params, actorQuery);\n\t\treturn createActorProxy(handle) as ActorHandle<AD>;\n\t}\n\n\t/**\n\t * Creates a new actor with the provided key and returns a stateless handle to it.\n\t * Resolves the actor ID and returns a handle with getForId query.\n\t *\n\t * @template AD The actor class that this handle is for.\n\t * @param {string} name - The name of the actor.\n\t * @param {string | string[]} key - The key to identify the actor. Can be a single string or an array of strings.\n\t * @param {CreateOptions} [opts] - Options for creating the actor (excluding name and key).\n\t * @returns {Promise<ActorHandle<AD>>} - A promise that resolves to a handle to the actor.\n\t */\n\tasync create<AD extends AnyActorDefinition>(\n\t\tname: string,\n\t\tkey?: string | string[],\n\t\topts?: CreateOptions,\n\t): Promise<ActorHandle<AD>> {\n\t\t// Convert string to array of strings\n\t\tconst keyArray: string[] = typeof key === \"string\" ? [key] : key || [];\n\n\t\tconst createQuery = {\n\t\t\tcreate: {\n\t\t\t\t...opts,\n\t\t\t\t// Do these last to override `opts`\n\t\t\t\tname,\n\t\t\t\tkey: keyArray,\n\t\t\t},\n\t\t} satisfies ActorQuery;\n\n\t\tlogger().debug({\n\t\t\tmsg: \"create actor handle\",\n\t\t\tname,\n\t\t\tkey: keyArray,\n\t\t\tparameters: opts?.params,\n\t\t\tcreate: createQuery.create,\n\t\t});\n\n\t\t// Create the actor\n\t\tconst { actorId } = await queryActor(\n\t\t\tundefined,\n\t\t\tcreateQuery,\n\t\t\tthis.#driver,\n\t\t);\n\t\tlogger().debug({\n\t\t\tmsg: \"created actor with ID\",\n\t\t\tname,\n\t\t\tkey: keyArray,\n\t\t\tactorId,\n\t\t});\n\n\t\t// Create handle with actor ID\n\t\tconst getForIdQuery = {\n\t\t\tgetForId: {\n\t\t\t\tname,\n\t\t\t\tactorId,\n\t\t\t},\n\t\t} satisfies ActorQuery;\n\t\tconst handle = this.#createHandle(opts?.params, getForIdQuery);\n\n\t\tconst proxy = createActorProxy(handle) as ActorHandle<AD>;\n\n\t\treturn proxy;\n\t}\n\n\t#createHandle(params: unknown, actorQuery: ActorQuery): ActorHandleRaw {\n\t\treturn new ActorHandleRaw(\n\t\t\tthis,\n\t\t\tthis.#driver,\n\t\t\tparams,\n\t\t\tthis.#encodingKind,\n\t\t\tactorQuery,\n\t\t);\n\t}\n\n\t[CREATE_ACTOR_CONN_PROXY]<AD extends AnyActorDefinition>(\n\t\tconn: ActorConnRaw,\n\t): ActorConn<AD> {\n\t\t// Save to connection list\n\t\tthis[ACTOR_CONNS_SYMBOL].add(conn);\n\n\t\t// Start connection\n\t\tconn[CONNECT_SYMBOL]();\n\n\t\treturn createActorProxy(conn) as ActorConn<AD>;\n\t}\n\n\t/**\n\t * Disconnects from all actors.\n\t *\n\t * @returns {Promise<void>} A promise that resolves when all connections are closed.\n\t */\n\tasync dispose(): Promise<void> {\n\t\tif (this.#disposed) {\n\t\t\tlogger().warn({ msg: \"client already disconnected\" });\n\t\t\treturn;\n\t\t}\n\t\tthis.#disposed = true;\n\n\t\tlogger().debug({ msg: \"disposing client\" });\n\n\t\tconst disposePromises = [];\n\n\t\t// Dispose all connections\n\t\tfor (const conn of this[ACTOR_CONNS_SYMBOL].values()) {\n\t\t\tdisposePromises.push(conn.dispose());\n\t\t}\n\n\t\tawait Promise.all(disposePromises);\n\t}\n}\n\n/**\n * Client type with actor accessors.\n * This adds property accessors for actor names to the ClientRaw base class.\n *\n * @template A The actor registry type.\n */\nexport type Client<A extends Registry<any>> = ClientRaw & {\n\t[K in keyof ExtractActorsFromRegistry<A>]: ActorAccessor<\n\t\tExtractActorsFromRegistry<A>[K]\n\t>;\n};\n\nexport type AnyClient = Client<Registry<any>>;\n\nexport function createClientWithDriver<A extends Registry<any>>(\n\tdriver: ManagerDriver,\n\tconfig: { encoding?: Encoding } = {},\n): Client<A> {\n\tconst client = new ClientRaw(driver, config.encoding);\n\n\t// Create proxy for accessing actors by name\n\treturn new Proxy(client, {\n\t\tget: (target: ClientRaw, prop: string | symbol, receiver: unknown) => {\n\t\t\t// Get the real property if it exists\n\t\t\tif (typeof prop === \"symbol\" || prop in target) {\n\t\t\t\tconst value = Reflect.get(target, prop, receiver);\n\t\t\t\t// Preserve method binding\n\t\t\t\tif (typeof value === \"function\") {\n\t\t\t\t\treturn value.bind(target);\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t\t// Handle actor accessor for string properties (actor names)\n\t\t\tif (typeof prop === \"string\") {\n\t\t\t\t// Return actor accessor object with methods\n\t\t\t\treturn {\n\t\t\t\t\t// Handle methods (stateless action)\n\t\t\t\t\tget: (\n\t\t\t\t\t\tkey?: string | string[],\n\t\t\t\t\t\topts?: GetWithIdOptions,\n\t\t\t\t\t): ActorHandle<\n\t\t\t\t\t\tExtractActorsFromRegistry<A>[typeof prop]\n\t\t\t\t\t> => {\n\t\t\t\t\t\treturn target.get<\n\t\t\t\t\t\t\tExtractActorsFromRegistry<A>[typeof prop]\n\t\t\t\t\t\t>(prop, key, opts);\n\t\t\t\t\t},\n\t\t\t\t\tgetOrCreate: (\n\t\t\t\t\t\tkey?: string | string[],\n\t\t\t\t\t\topts?: GetOptions,\n\t\t\t\t\t): ActorHandle<\n\t\t\t\t\t\tExtractActorsFromRegistry<A>[typeof prop]\n\t\t\t\t\t> => {\n\t\t\t\t\t\treturn target.getOrCreate<\n\t\t\t\t\t\t\tExtractActorsFromRegistry<A>[typeof prop]\n\t\t\t\t\t\t>(prop, key, opts);\n\t\t\t\t\t},\n\t\t\t\t\tgetForId: (\n\t\t\t\t\t\tactorId: string,\n\t\t\t\t\t\topts?: GetWithIdOptions,\n\t\t\t\t\t): ActorHandle<\n\t\t\t\t\t\tExtractActorsFromRegistry<A>[typeof prop]\n\t\t\t\t\t> => {\n\t\t\t\t\t\treturn target.getForId<\n\t\t\t\t\t\t\tExtractActorsFromRegistry<A>[typeof prop]\n\t\t\t\t\t\t>(prop, actorId, opts);\n\t\t\t\t\t},\n\t\t\t\t\tcreate: async (\n\t\t\t\t\t\tkey: string | string[],\n\t\t\t\t\t\topts: CreateOptions = {},\n\t\t\t\t\t): Promise<\n\t\t\t\t\t\tActorHandle<ExtractActorsFromRegistry<A>[typeof prop]>\n\t\t\t\t\t> => {\n\t\t\t\t\t\treturn await target.create<\n\t\t\t\t\t\t\tExtractActorsFromRegistry<A>[typeof prop]\n\t\t\t\t\t\t>(prop, key, opts);\n\t\t\t\t\t},\n\t\t\t\t} as ActorAccessor<ExtractActorsFromRegistry<A>[typeof prop]>;\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t},\n\t}) as Client<A>;\n}\n\n/**\n * Creates a proxy for a actor that enables calling actions without explicitly using `.action`.\n **/\nfunction createActorProxy<AD extends AnyActorDefinition>(\n\thandle: ActorHandleRaw | ActorConnRaw,\n): ActorHandle<AD> | ActorConn<AD> {\n\t// Stores returned action functions for faster calls\n\tconst methodCache = new Map<string, ActorActionFunction>();\n\treturn new Proxy(handle, {\n\t\tget(target: ActorHandleRaw, prop: string | symbol, receiver: unknown) {\n\t\t\t// Handle built-in Symbol properties\n\t\t\tif (typeof prop === \"symbol\") {\n\t\t\t\treturn Reflect.get(target, prop, receiver);\n\t\t\t}\n\n\t\t\t// Handle built-in Promise methods and existing properties\n\t\t\tif (prop === \"constructor\" || prop in target) {\n\t\t\t\tconst value = Reflect.get(target, prop, target);\n\t\t\t\t// Preserve method binding\n\t\t\t\tif (typeof value === \"function\") {\n\t\t\t\t\treturn value.bind(target);\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t\t// Create action function that preserves 'this' context\n\t\t\tif (typeof prop === \"string\") {\n\t\t\t\t// If JS is attempting to calling this as a promise, ignore it\n\t\t\t\tif (prop === \"then\") return undefined;\n\n\t\t\t\tlet method = methodCache.get(prop);\n\t\t\t\tif (!method) {\n\t\t\t\t\tmethod = (...args: unknown[]) =>\n\t\t\t\t\t\ttarget.action({ name: prop, args });\n\t\t\t\t\tmethodCache.set(prop, method);\n\t\t\t\t}\n\t\t\t\treturn method;\n\t\t\t}\n\t\t},\n\n\t\t// Support for 'in' operator\n\t\thas(target: ActorHandleRaw, prop: string | symbol) {\n\t\t\t// All string properties are potentially action functions.\n\t\t\tif (typeof prop === \"string\") return true;\n\t\t\t// For symbols, defer to the target's own has behavior\n\t\t\treturn Reflect.has(target, prop);\n\t\t},\n\n\t\t// Support instanceof checks\n\t\tgetPrototypeOf(target: ActorHandleRaw) {\n\t\t\treturn Reflect.getPrototypeOf(target);\n\t\t},\n\n\t\t// Prevent property enumeration of non-existent action methods\n\t\townKeys(target: ActorHandleRaw) {\n\t\t\treturn Reflect.ownKeys(target);\n\t\t},\n\n\t\t// Support proper property descriptors\n\t\tgetOwnPropertyDescriptor(\n\t\t\ttarget: ActorHandleRaw,\n\t\t\tprop: string | symbol,\n\t\t) {\n\t\t\tconst targetDescriptor = Reflect.getOwnPropertyDescriptor(\n\t\t\t\ttarget,\n\t\t\t\tprop,\n\t\t\t);\n\t\t\tif (targetDescriptor) {\n\t\t\t\treturn targetDescriptor;\n\t\t\t}\n\t\t\tif (typeof prop === \"string\") {\n\t\t\t\t// Make action methods appear non-enumerable\n\t\t\t\treturn {\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\tenumerable: false,\n\t\t\t\t\twritable: false,\n\t\t\t\t\tvalue: (...args: unknown[]) =>\n\t\t\t\t\t\ttarget.action({ name: prop, args }),\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn undefined;\n\t\t},\n\t}) as ActorHandle<AD> | ActorConn<AD>;\n}\n","import z from \"zod/v4\";\nimport { EncodingSchema } from \"@/actor/protocol/serde\";\nimport { type GetUpgradeWebSocket } from \"@/utils\";\nimport {\n\tgetRivetEngine,\n\tgetRivetEndpoint,\n\tgetRivetToken,\n\tgetRivetNamespace,\n\tgetRivetRunner,\n} from \"@/utils/env-vars\";\nimport type { RegistryConfig } from \"@/registry/config\";\nimport { tryParseEndpoint } from \"@/utils/endpoint-parser\";\n\n/**\n * Gets the default endpoint for the client.\n *\n * In browser: uses current origin + /api/rivet\n *\n * Server-side: uses 127.0.0.1:6420\n */\nfunction getDefaultEndpoint(): string {\n\tif (typeof window !== \"undefined\" && window.location?.origin) {\n\t\treturn `${window.location.origin}/api/rivet`;\n\t}\n\treturn \"http://127.0.0.1:6420\";\n}\n\n/**\n * Base client config schema without transforms so it can be merged in to other schemas.\n */\nexport const ClientConfigSchemaBase = z.object({\n\t/**\n\t * Endpoint to connect to for Rivet Engine or RivetKit manager API.\n\t *\n\t * Supports URL auth syntax for namespace and token:\n\t * - `https://namespace:token@api.rivet.dev`\n\t * - `https://namespace@api.rivet.dev`\n\t *\n\t * Can also be set via RIVET_ENDPOINT environment variables.\n\t *\n\t * Defaults to current origin + /api/rivet in browser, or 127.0.0.1:6420 server-side.\n\t */\n\tendpoint: z\n\t\t.string()\n\t\t.optional()\n\t\t.transform(\n\t\t\t(val) =>\n\t\t\t\tval ??\n\t\t\t\tgetRivetEngine() ??\n\t\t\t\tgetRivetEndpoint() ??\n\t\t\t\tgetDefaultEndpoint(),\n\t\t),\n\n\t/** Token to use to authenticate with the API. */\n\ttoken: z\n\t\t.string()\n\t\t.optional()\n\t\t.transform((val) => val ?? getRivetToken()),\n\n\t/** Namespace to connect to. */\n\tnamespace: z\n\t\t.string()\n\t\t.optional()\n\t\t.transform((val) => val ?? getRivetNamespace()),\n\n\t/** Name of the runner. This is used to group together runners in to different pools. */\n\trunnerName: z.string().default(() => getRivetRunner() ?? \"default\"),\n\n\tencoding: EncodingSchema.default(\"bare\"),\n\n\theaders: z\n\t\t.record(z.string(), z.string())\n\t\t.optional()\n\t\t.default(() => ({})),\n\n\t// See RunConfig.getUpgradeWebSocket\n\t//\n\t// This is required in the client config in order to support\n\t// `proxyWebSocket`\n\tgetUpgradeWebSocket: z.custom<GetUpgradeWebSocket>().optional(),\n\n\t/** Whether to automatically perform health checks when the client is created. */\n\tdisableMetadataLookup: z.boolean().optional().default(false),\n\n\t/** Whether to enable RivetKit Devtools integration. */\n\tdevtools: z\n\t\t.boolean()\n\t\t.default(\n\t\t\t() =>\n\t\t\t\ttypeof window !== \"undefined\" &&\n\t\t\t\t(window?.location?.hostname === \"127.0.0.1\" ||\n\t\t\t\t\twindow.location?.hostname === \"localhost\"),\n\t\t),\n});\n\nexport const ClientConfigSchema = ClientConfigSchemaBase.transform(\n\t(config, ctx) => transformClientConfig(config, ctx),\n);\n\nexport type ClientConfig = z.infer<typeof ClientConfigSchema>;\n\nexport type ClientConfigInput = z.input<typeof ClientConfigSchema>;\n\nexport function transformClientConfig(\n\tconfig: z.infer<typeof ClientConfigSchemaBase>,\n\tctx: z.RefinementCtx,\n) {\n\tconst parsedEndpoint = tryParseEndpoint(ctx, {\n\t\tendpoint: config.endpoint,\n\t\tpath: [\"endpoint\"],\n\t\tnamespace: config.namespace,\n\t\ttoken: config.token,\n\t});\n\n\treturn {\n\t\t...config,\n\t\tendpoint: parsedEndpoint?.endpoint,\n\t\tnamespace: parsedEndpoint?.namespace ?? config.namespace ?? \"default\",\n\t\ttoken: parsedEndpoint?.token ?? config.token,\n\t};\n}\n\n/**\n * Converts a base config in to a client config.\n *\n * The base config does not include all of the properties of the client config,\n * so this converts the subset of properties in to the client config.\n *\n * Note: We construct the object directly rather than using ClientConfigSchema.parse()\n * because RegistryConfig has already transformed the endpoint, namespace, and token.\n * Re-parsing would attempt to extract namespace/token from the endpoint URL again.\n */\nexport function convertRegistryConfigToClientConfig(\n\tconfig: RegistryConfig,\n): ClientConfig {\n\treturn {\n\t\tendpoint: config.endpoint,\n\t\ttoken: config.token,\n\t\tnamespace: config.namespace,\n\t\trunnerName: config.runner.runnerName,\n\t\theaders: config.headers,\n\t\tencoding: \"bare\",\n\t\tgetUpgradeWebSocket: undefined,\n\t\t// We don't need health checks for internal clients\n\t\tdisableMetadataLookup: true,\n\t\tdevtools:\n\t\t\ttypeof window !== \"undefined\" &&\n\t\t\t(window?.location?.hostname === \"127.0.0.1\" ||\n\t\t\t\twindow?.location?.hostname === \"localhost\"),\n\t};\n}\n","import { injectDevtools } from \"@/devtools-loader\";\nimport type { Registry } from \"@/registry\";\nimport { RemoteManagerDriver } from \"@/remote-manager-driver/mod\";\nimport {\n\ttype Client,\n\ttype ClientConfigInput,\n\tcreateClientWithDriver,\n} from \"./client\";\nimport { ClientConfigSchema } from \"./config\";\n\nexport type { ActorDefinition, AnyActorDefinition } from \"@/actor/definition\";\nexport type { Encoding } from \"@/actor/protocol/serde\";\nexport {\n\tActorClientError,\n\tActorConnDisposed,\n\tActorError,\n\tInternalError,\n\tMalformedResponseMessage,\n\tManagerError,\n} from \"@/client/errors\";\nexport type { CreateRequest } from \"@/manager/protocol/query\";\nexport { KEYS as KV_KEYS } from \"../actor/instance/keys\";\nexport type { ActorActionFunction } from \"./actor-common\";\nexport type {\n\tActorConn,\n\tActorConnStatus,\n\tConnectionStateCallback,\n\tEventUnsubscribe,\n\tStatusChangeCallback,\n} from \"./actor-conn\";\nexport { ActorConnRaw } from \"./actor-conn\";\nexport type { ActorHandle } from \"./actor-handle\";\nexport { ActorHandleRaw } from \"./actor-handle\";\nexport type {\n\tActorAccessor,\n\tClient,\n\tClientRaw,\n\tCreateOptions,\n\tExtractActorsFromRegistry,\n\tExtractRegistryFromClient,\n\tGetOptions,\n\tGetWithIdOptions,\n\tQueryOptions,\n\tRegion,\n} from \"./client\";\n\n/**\n * Creates a client with the actor accessor proxy.\n */\nexport function createClient<A extends Registry<any>>(\n\tendpointOrConfig?: string | ClientConfigInput,\n): Client<A> {\n\t// Parse config\n\tconst configInput =\n\t\tendpointOrConfig === undefined\n\t\t\t? {}\n\t\t\t: typeof endpointOrConfig === \"string\"\n\t\t\t\t? { endpoint: endpointOrConfig }\n\t\t\t\t: endpointOrConfig;\n\tconst config = ClientConfigSchema.parse(configInput);\n\n\t// Create client\n\tconst driver = new RemoteManagerDriver(config);\n\n\tif (config.devtools) {\n\t\tinjectDevtools(config);\n\t}\n\n\treturn createClientWithDriver<A>(driver, config);\n}\n"]}
|