rivetkit 2.0.5 → 2.0.6
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/tsup/actor-router-consts-BK6arfy8.d.cts +17 -0
- package/dist/tsup/actor-router-consts-BK6arfy8.d.ts +17 -0
- package/dist/tsup/chunk-2K3JMDAN.js +232 -0
- package/dist/tsup/chunk-2K3JMDAN.js.map +1 -0
- package/dist/tsup/chunk-42I3OZ3Q.js +15 -0
- package/dist/tsup/chunk-42I3OZ3Q.js.map +1 -0
- package/dist/tsup/{chunk-L7QRXNWP.js → chunk-4CKHQRXG.js} +1642 -4408
- package/dist/tsup/chunk-4CKHQRXG.js.map +1 -0
- package/dist/tsup/{chunk-WADSS5X4.cjs → chunk-5JBFVV4C.cjs} +2 -2
- package/dist/tsup/{chunk-WADSS5X4.cjs.map → chunk-5JBFVV4C.cjs.map} +1 -1
- package/dist/tsup/{chunk-FGFT4FVX.cjs → chunk-6P6RA47N.cjs} +9 -9
- package/dist/tsup/{chunk-FGFT4FVX.cjs.map → chunk-6P6RA47N.cjs.map} +1 -1
- package/dist/tsup/chunk-7OUKNSTU.js +1043 -0
- package/dist/tsup/chunk-7OUKNSTU.js.map +1 -0
- package/dist/tsup/{chunk-LZIBTLEY.cjs → chunk-DIAYNQTE.cjs} +13 -25
- package/dist/tsup/chunk-DIAYNQTE.cjs.map +1 -0
- package/dist/tsup/{chunk-YW6Y6VNE.js → chunk-G75SVQON.js} +4 -4
- package/dist/tsup/{chunk-PHSQJ6QI.cjs → chunk-KG3C7MKR.cjs} +3 -3
- package/dist/tsup/{chunk-PHSQJ6QI.cjs.map → chunk-KG3C7MKR.cjs.map} +1 -1
- package/dist/tsup/chunk-KUPQZYUQ.cjs +15 -0
- package/dist/tsup/chunk-KUPQZYUQ.cjs.map +1 -0
- package/dist/tsup/{chunk-5YTI25C3.cjs → chunk-MRRT2CZD.cjs} +7 -7
- package/dist/tsup/{chunk-5YTI25C3.cjs.map → chunk-MRRT2CZD.cjs.map} +1 -1
- package/dist/tsup/chunk-NTCUGYSD.cjs +1043 -0
- package/dist/tsup/chunk-NTCUGYSD.cjs.map +1 -0
- package/dist/tsup/{chunk-CFFKMUYH.js → chunk-RGQR2J7S.js} +2 -2
- package/dist/tsup/{chunk-CFFKMUYH.js.map → chunk-RGQR2J7S.js.map} +1 -1
- package/dist/tsup/chunk-TCUI5JFE.cjs +232 -0
- package/dist/tsup/chunk-TCUI5JFE.cjs.map +1 -0
- package/dist/tsup/chunk-TWGATZ3X.cjs +3676 -0
- package/dist/tsup/chunk-TWGATZ3X.cjs.map +1 -0
- package/dist/tsup/chunk-UFWAK3X2.cjs +3796 -0
- package/dist/tsup/chunk-UFWAK3X2.cjs.map +1 -0
- package/dist/tsup/{chunk-D7NWUCRK.cjs → chunk-UTI5NCES.cjs} +6 -6
- package/dist/tsup/{chunk-D7NWUCRK.cjs.map → chunk-UTI5NCES.cjs.map} +1 -1
- package/dist/tsup/{chunk-PG3K2LI7.js → chunk-VCEHU56K.js} +2 -2
- package/dist/tsup/{chunk-I5VTWPHW.js → chunk-VPV4MWXR.js} +3 -3
- package/dist/tsup/chunk-W6LN7AF5.js +3676 -0
- package/dist/tsup/chunk-W6LN7AF5.js.map +1 -0
- package/dist/tsup/{chunk-WNGOBAA7.js → chunk-WC2PSJWN.js} +2 -2
- package/dist/tsup/{chunk-CKA54YQN.js → chunk-ZYLTS2EM.js} +3 -15
- package/dist/tsup/chunk-ZYLTS2EM.js.map +1 -0
- package/dist/tsup/client/mod.cjs +9 -9
- package/dist/tsup/client/mod.d.cts +2 -2
- package/dist/tsup/client/mod.d.ts +2 -2
- package/dist/tsup/client/mod.js +8 -8
- package/dist/tsup/common/log.cjs +3 -3
- package/dist/tsup/common/log.js +2 -2
- package/dist/tsup/common/websocket.cjs +4 -4
- package/dist/tsup/common/websocket.js +3 -3
- package/dist/tsup/{connection-BvE-Oq7t.d.ts → connection-BLemxi4f.d.ts} +1 -1
- package/dist/tsup/{connection-DTzmWwU5.d.cts → connection-CpDIydXf.d.cts} +1 -1
- package/dist/tsup/driver-helpers/mod.cjs +5 -5
- package/dist/tsup/driver-helpers/mod.d.cts +2 -2
- package/dist/tsup/driver-helpers/mod.d.ts +2 -2
- package/dist/tsup/driver-helpers/mod.js +4 -4
- package/dist/tsup/driver-test-suite/mod.cjs +66 -58
- package/dist/tsup/driver-test-suite/mod.cjs.map +1 -1
- package/dist/tsup/driver-test-suite/mod.d.cts +1 -1
- package/dist/tsup/driver-test-suite/mod.d.ts +1 -1
- package/dist/tsup/driver-test-suite/mod.js +24 -16
- package/dist/tsup/driver-test-suite/mod.js.map +1 -1
- package/dist/tsup/inspector/mod.cjs +7 -5
- package/dist/tsup/inspector/mod.cjs.map +1 -1
- package/dist/tsup/inspector/mod.js +9 -7
- package/dist/tsup/mod.cjs +11 -8
- package/dist/tsup/mod.cjs.map +1 -1
- package/dist/tsup/mod.d.cts +52 -7
- package/dist/tsup/mod.d.ts +52 -7
- package/dist/tsup/mod.js +17 -14
- package/dist/tsup/test/mod.cjs +11 -9
- package/dist/tsup/test/mod.cjs.map +1 -1
- package/dist/tsup/test/mod.d.cts +1 -1
- package/dist/tsup/test/mod.d.ts +1 -1
- package/dist/tsup/test/mod.js +10 -8
- package/dist/tsup/utils.cjs +2 -2
- package/dist/tsup/utils.js +1 -1
- package/package.json +1 -1
- package/src/actor/mod.ts +5 -3
- package/src/actor/router-endpoints.ts +5 -32
- package/src/actor/router.ts +9 -8
- package/src/client/actor-conn.ts +9 -8
- package/src/client/actor-handle.ts +0 -1
- package/src/client/client.ts +1 -1
- package/src/client/raw-utils.ts +1 -1
- package/src/client/utils.ts +1 -1
- package/src/common/actor-router-consts.ts +38 -0
- package/src/driver-helpers/mod.ts +1 -1
- package/src/driver-test-suite/test-inline-client-driver.ts +4 -4
- package/src/driver-test-suite/utils.ts +7 -2
- package/src/drivers/engine/actor-driver.ts +18 -17
- package/src/manager/driver.ts +1 -1
- package/src/manager/protocol/query.ts +1 -1
- package/src/registry/mod.ts +7 -2
- package/src/registry/serve.ts +8 -3
- package/src/remote-manager-driver/actor-websocket-client.ts +2 -2
- package/src/remote-manager-driver/mod.ts +2 -5
- package/dist/tsup/chunk-2MD57QF4.js +0 -1794
- package/dist/tsup/chunk-2MD57QF4.js.map +0 -1
- package/dist/tsup/chunk-B2QGJGZQ.js +0 -338
- package/dist/tsup/chunk-B2QGJGZQ.js.map +0 -1
- package/dist/tsup/chunk-CKA54YQN.js.map +0 -1
- package/dist/tsup/chunk-IRMBWX36.cjs +0 -1794
- package/dist/tsup/chunk-IRMBWX36.cjs.map +0 -1
- package/dist/tsup/chunk-L7QRXNWP.js.map +0 -1
- package/dist/tsup/chunk-LZIBTLEY.cjs.map +0 -1
- package/dist/tsup/chunk-MRZS2J4X.cjs +0 -6562
- package/dist/tsup/chunk-MRZS2J4X.cjs.map +0 -1
- package/dist/tsup/chunk-RM2SVURR.cjs +0 -338
- package/dist/tsup/chunk-RM2SVURR.cjs.map +0 -1
- package/dist/tsup/router-endpoints-CctffZNL.d.cts +0 -65
- package/dist/tsup/router-endpoints-DFm1BglJ.d.ts +0 -65
- /package/dist/tsup/{chunk-YW6Y6VNE.js.map → chunk-G75SVQON.js.map} +0 -0
- /package/dist/tsup/{chunk-PG3K2LI7.js.map → chunk-VCEHU56K.js.map} +0 -0
- /package/dist/tsup/{chunk-I5VTWPHW.js.map → chunk-VPV4MWXR.js.map} +0 -0
- /package/dist/tsup/{chunk-WNGOBAA7.js.map → chunk-WC2PSJWN.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/nathan/rivetkit/packages/rivetkit/dist/tsup/chunk-MRZS2J4X.cjs","../../src/actor/config.ts","../../src/actor/instance.ts","../../src/inspector/actor.ts","../../src/actor/context.ts","../../src/actor/keys.ts","../../src/actor/schedule.ts","../../src/actor/definition.ts","../../src/actor/generic-conn-driver.ts","../../src/actor/router.ts","../../src/common/router.ts","../../src/inspector/utils.ts","../../src/inspector/log.ts","../../src/actor/mod.ts","../../src/client/actor-conn.ts","../../src/common/eventsource.ts","../../src/client/actor-query.ts","../../src/client/errors.ts","../../src/client/utils.ts","../../src/client/actor-handle.ts","../../src/client/raw-utils.ts","../../src/client/client.ts","../../src/common/inline-websocket-adapter2.ts","../../src/remote-manager-driver/mod.ts","../../src/remote-manager-driver/log.ts","../../src/remote-manager-driver/api-utils.ts","../../src/remote-manager-driver/actor-http-client.ts","../../src/remote-manager-driver/actor-websocket-client.ts","../../src/remote-manager-driver/api-endpoints.ts","../../src/remote-manager-driver/ws-proxy.ts","../../src/drivers/engine/actor-driver.ts","../../src/drivers/engine/kv.ts","../../src/drivers/engine/log.ts","../../src/drivers/engine/config.ts","../../src/drivers/engine/mod.ts","../../src/drivers/file-system/actor.ts","../../src/drivers/file-system/global-state.ts","../schemas/file-system-driver/v1.ts","../../src/schemas/file-system-driver/versioned.ts","../../src/drivers/file-system/log.ts","../../src/drivers/file-system/utils.ts","../../src/drivers/file-system/manager.ts","../../src/inspector/manager.ts","../../src/drivers/file-system/mod.ts","../../src/drivers/default.ts","../../src/manager/router.ts","../../src/manager-api/routes/actors-create.ts","../../src/manager-api/routes/common.ts","../../src/manager-api/routes/actors-get.ts","../../src/manager-api/routes/actors-get-by-id.ts","../../src/manager-api/routes/actors-get-or-create-by-id.ts","../../src/registry/config.ts","../../src/registry/log.ts","../../src/registry/serve.ts","../../src/registry/mod.ts"],"names":["z","actor","config","path","InternalError","invariant","transformActor","createMiddleware","_a"],"mappings":"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","file":"/Users/nathan/rivetkit/packages/rivetkit/dist/tsup/chunk-MRZS2J4X.cjs","sourcesContent":[null,"import { z } from \"zod\";\nimport type { UniversalWebSocket } from \"@/common/websocket-interface\";\nimport type { ActionContext } from \"./action\";\nimport type { Conn } from \"./connection\";\nimport type { ActorContext } from \"./context\";\nimport type { AnyDatabaseProvider } from \"./database\";\n\nexport type InitContext = ActorContext<\n\tundefined,\n\tundefined,\n\tundefined,\n\tundefined,\n\tundefined,\n\tundefined\n>;\n\nexport interface ActorTypes<\n\tTState,\n\tTConnParams,\n\tTConnState,\n\tTVars,\n\tTInput,\n\tTDatabase extends AnyDatabaseProvider,\n> {\n\tstate?: TState;\n\tconnParams?: TConnParams;\n\tconnState?: TConnState;\n\tvars?: TVars;\n\tinput?: TInput;\n\tdatabase?: TDatabase;\n}\n\n// This schema is used to validate the input at runtime. The generic types are defined below in `ActorConfig`.\n//\n// We don't use Zod generics with `z.custom` because:\n// (a) there seems to be a weird bug in either Zod, tsup, or TSC that causese external packages to have different types from `z.infer` than from within the same package and\n// (b) it makes the type definitions incredibly difficult to read as opposed to vanilla TypeScript.\nexport const ActorConfigSchema = z\n\t.object({\n\t\tonCreate: z.function().optional(),\n\t\tonStart: z.function().optional(),\n\t\tonStop: z.function().optional(),\n\t\tonStateChange: z.function().optional(),\n\t\tonBeforeConnect: z.function().optional(),\n\t\tonConnect: z.function().optional(),\n\t\tonDisconnect: z.function().optional(),\n\t\tonBeforeActionResponse: z.function().optional(),\n\t\tonFetch: z.function().optional(),\n\t\tonWebSocket: z.function().optional(),\n\t\tactions: z.record(z.function()).default({}),\n\t\tstate: z.any().optional(),\n\t\tcreateState: z.function().optional(),\n\t\tconnState: z.any().optional(),\n\t\tcreateConnState: z.function().optional(),\n\t\tvars: z.any().optional(),\n\t\tdb: z.any().optional(),\n\t\tcreateVars: z.function().optional(),\n\t\toptions: z\n\t\t\t.object({\n\t\t\t\tcreateVarsTimeout: z.number().positive().default(5000),\n\t\t\t\tcreateConnStateTimeout: z.number().positive().default(5000),\n\t\t\t\tonConnectTimeout: z.number().positive().default(5000),\n\t\t\t\t// This must be less than ACTOR_STOP_THRESHOLD_MS\n\t\t\t\tonStopTimeout: z.number().positive().default(5000),\n\t\t\t\tstateSaveInterval: z.number().positive().default(10_000),\n\t\t\t\tactionTimeout: z.number().positive().default(60_000),\n\t\t\t\t// Max time to wait for waitUntil background promises during shutdown\n\t\t\t\twaitUntilTimeout: z.number().positive().default(15_000),\n\t\t\t\tconnectionLivenessTimeout: z.number().positive().default(2500),\n\t\t\t\tconnectionLivenessInterval: z.number().positive().default(5000),\n\t\t\t\tnoSleep: z.boolean().default(false),\n\t\t\t\tsleepTimeout: z.number().positive().default(30_000),\n\t\t\t})\n\t\t\t.strict()\n\t\t\t.default({}),\n\t})\n\t.strict()\n\t.refine(\n\t\t(data) => !(data.state !== undefined && data.createState !== undefined),\n\t\t{\n\t\t\tmessage: \"Cannot define both 'state' and 'createState'\",\n\t\t\tpath: [\"state\"],\n\t\t},\n\t)\n\t.refine(\n\t\t(data) =>\n\t\t\t!(data.connState !== undefined && data.createConnState !== undefined),\n\t\t{\n\t\t\tmessage: \"Cannot define both 'connState' and 'createConnState'\",\n\t\t\tpath: [\"connState\"],\n\t\t},\n\t)\n\t.refine(\n\t\t(data) => !(data.vars !== undefined && data.createVars !== undefined),\n\t\t{\n\t\t\tmessage: \"Cannot define both 'vars' and 'createVars'\",\n\t\t\tpath: [\"vars\"],\n\t\t},\n\t);\n\nexport interface OnConnectOptions {\n\t/**\n\t * The request object associated with the connection.\n\t *\n\t * @experimental\n\t */\n\trequest?: Request;\n}\n\n// Creates state config\n//\n// This must have only one or the other or else TState will not be able to be inferred\n//\n// Data returned from this handler will be available on `c.state`.\ntype CreateState<TState, TConnParams, TConnState, TVars, TInput, TDatabase> =\n\t| { state: TState }\n\t| {\n\t\t\tcreateState: (c: InitContext, input: TInput) => TState | Promise<TState>;\n\t }\n\t| Record<never, never>;\n\n// Creates connection state config\n//\n// This must have only one or the other or else TState will not be able to be inferred\n//\n// Data returned from this handler will be available on `c.conn.state`.\ntype CreateConnState<\n\tTState,\n\tTConnParams,\n\tTConnState,\n\tTVars,\n\tTInput,\n\tTDatabase,\n> =\n\t| { connState: TConnState }\n\t| {\n\t\t\tcreateConnState: (\n\t\t\t\tc: InitContext,\n\t\t\t\topts: OnConnectOptions,\n\t\t\t\tparams: TConnParams,\n\t\t\t) => TConnState | Promise<TConnState>;\n\t }\n\t| Record<never, never>;\n\n// Creates vars config\n//\n// This must have only one or the other or else TState will not be able to be inferred\n/**\n * @experimental\n */\ntype CreateVars<TState, TConnParams, TConnState, TVars, TInput, TDatabase> =\n\t| {\n\t\t\t/**\n\t\t\t * @experimental\n\t\t\t */\n\t\t\tvars: TVars;\n\t }\n\t| {\n\t\t\t/**\n\t\t\t * @experimental\n\t\t\t */\n\t\t\tcreateVars: (c: InitContext, driverCtx: any) => TVars | Promise<TVars>;\n\t }\n\t| Record<never, never>;\n\nexport interface Actions<\n\tTState,\n\tTConnParams,\n\tTConnState,\n\tTVars,\n\tTInput,\n\tTDatabase extends AnyDatabaseProvider,\n> {\n\t[Action: string]: (\n\t\tc: ActionContext<TState, TConnParams, TConnState, TVars, TInput, TDatabase>,\n\t\t...args: any[]\n\t) => any;\n}\n\n//export type ActorConfig<TState, TConnParams, TConnState, TVars, TInput, TAuthData> = BaseActorConfig<TState, TConnParams, TConnState, TVars, TInput, TAuthData> &\n//\tActorConfigLifecycle<TState, TConnParams, TConnState, TVars, TInput, TAuthData> &\n//\tCreateState<TState, TConnParams, TConnState, TVars, TInput, TAuthData> &\n//\tCreateConnState<TState, TConnParams, TConnState, TVars, TInput, TAuthData>;\n\n/**\n * @experimental\n */\nexport type AuthIntent = \"get\" | \"create\" | \"connect\" | \"action\" | \"message\";\n\ninterface BaseActorConfig<\n\tTState,\n\tTConnParams,\n\tTConnState,\n\tTVars,\n\tTInput,\n\tTDatabase extends AnyDatabaseProvider,\n\tTActions extends Actions<\n\t\tTState,\n\t\tTConnParams,\n\t\tTConnState,\n\t\tTVars,\n\t\tTInput,\n\t\tTDatabase\n\t>,\n> {\n\t/**\n\t * Called when the actor is first initialized.\n\t *\n\t * Use this hook to initialize your actor's state.\n\t * This is called before any other lifecycle hooks.\n\t */\n\tonCreate?: (\n\t\tc: ActorContext<TState, TConnParams, TConnState, TVars, TInput, TDatabase>,\n\t\tinput: TInput,\n\t) => void | Promise<void>;\n\n\t/**\n\t * Called when the actor is started and ready to receive connections and action.\n\t *\n\t * Use this hook to initialize resources needed for the actor's operation\n\t * (timers, external connections, etc.)\n\t *\n\t * @returns Void or a Promise that resolves when startup is complete\n\t */\n\tonStart?: (\n\t\tc: ActorContext<TState, TConnParams, TConnState, TVars, TInput, TDatabase>,\n\t) => void | Promise<void>;\n\n\t/**\n\t * Called when the actor is stopping or sleeping.\n\t *\n\t * Use this hook to clean up resources, save state, or perform\n\t * any shutdown operations before the actor sleeps or stops.\n\t *\n\t * Not supported on all platforms.\n\t *\n\t * @returns Void or a Promise that resolves when shutdown is complete\n\t */\n\tonStop?: (\n\t\tc: ActorContext<TState, TConnParams, TConnState, TVars, TInput, TDatabase>,\n\t) => void | Promise<void>;\n\n\t/**\n\t * Called when the actor's state changes.\n\t *\n\t * Use this hook to react to state changes, such as updating\n\t * external systems or triggering events.\n\t *\n\t * State changes made within this hook will NOT trigger\n\t * another onStateChange call, preventing infinite recursion.\n\t *\n\t * @param newState The updated state\n\t */\n\tonStateChange?: (\n\t\tc: ActorContext<TState, TConnParams, TConnState, TVars, TInput, TDatabase>,\n\t\tnewState: TState,\n\t) => void;\n\n\t/**\n\t * Called before a client connects to the actor.\n\t *\n\t * Use this hook to determine if a connection should be accepted\n\t * and to initialize connection-specific state.\n\t *\n\t * @param opts Connection parameters including client-provided data\n\t * @returns The initial connection state or a Promise that resolves to it\n\t * @throws Throw an error to reject the connection\n\t */\n\tonBeforeConnect?: (\n\t\tc: ActorContext<TState, TConnParams, TConnState, TVars, TInput, TDatabase>,\n\t\topts: OnConnectOptions,\n\t\tparams: TConnParams,\n\t) => void | Promise<void>;\n\n\t/**\n\t * Called when a client successfully connects to the actor.\n\t *\n\t * Use this hook to perform actions when a connection is established,\n\t * such as sending initial data or updating the actor's state.\n\t *\n\t * @param conn The connection object\n\t * @returns Void or a Promise that resolves when connection handling is complete\n\t */\n\tonConnect?: (\n\t\tc: ActorContext<TState, TConnParams, TConnState, TVars, TInput, TDatabase>,\n\t\tconn: Conn<TState, TConnParams, TConnState, TVars, TInput, TDatabase>,\n\t) => void | Promise<void>;\n\n\t/**\n\t * Called when a client disconnects from the actor.\n\t *\n\t * Use this hook to clean up resources associated with the connection\n\t * or update the actor's state.\n\t *\n\t * @param conn The connection that is being closed\n\t * @returns Void or a Promise that resolves when disconnect handling is complete\n\t */\n\tonDisconnect?: (\n\t\tc: ActorContext<TState, TConnParams, TConnState, TVars, TInput, TDatabase>,\n\t\tconn: Conn<TState, TConnParams, TConnState, TVars, TInput, TDatabase>,\n\t) => void | Promise<void>;\n\n\t/**\n\t * Called before sending an action response to the client.\n\t *\n\t * Use this hook to modify or transform the output of an action before it's sent\n\t * to the client. This is useful for formatting responses, adding metadata,\n\t * or applying transformations to the output.\n\t *\n\t * @param name The name of the action that was called\n\t * @param args The arguments that were passed to the action\n\t * @param output The output that will be sent to the client\n\t * @returns The modified output to send to the client\n\t */\n\tonBeforeActionResponse?: <Out>(\n\t\tc: ActorContext<TState, TConnParams, TConnState, TVars, TInput, TDatabase>,\n\t\tname: string,\n\t\targs: unknown[],\n\t\toutput: Out,\n\t) => Out | Promise<Out>;\n\n\t/**\n\t * Called when a raw HTTP request is made to the actor.\n\t *\n\t * This handler receives raw HTTP requests made to `/actors/{actorName}/http/*` endpoints.\n\t * Use this hook to handle custom HTTP patterns, REST APIs, or other HTTP-based protocols.\n\t *\n\t * @param request The raw HTTP request object\n\t * @returns A Response object to send back, or void to continue with default routing\n\t */\n\tonFetch?: (\n\t\tc: ActorContext<TState, TConnParams, TConnState, TVars, TInput, TDatabase>,\n\t\trequest: Request,\n\t\topts: {},\n\t) => Response | Promise<Response>;\n\n\t/**\n\t * Called when a raw WebSocket connection is established to the actor.\n\t *\n\t * This handler receives WebSocket connections made to `/actors/{actorName}/websocket/*` endpoints.\n\t * Use this hook to handle custom WebSocket protocols, binary streams, or other WebSocket-based communication.\n\t *\n\t * @param websocket The raw WebSocket connection\n\t * @param request The original HTTP upgrade request\n\t */\n\tonWebSocket?: (\n\t\tc: ActorContext<TState, TConnParams, TConnState, TVars, TInput, TDatabase>,\n\t\twebsocket: UniversalWebSocket,\n\t\topts: { request: Request },\n\t) => void | Promise<void>;\n\n\tactions: TActions;\n}\n\ntype ActorDatabaseConfig<TDatabase extends AnyDatabaseProvider> =\n\t| {\n\t\t\t/**\n\t\t\t * @experimental\n\t\t\t */\n\t\t\tdb: TDatabase;\n\t }\n\t| Record<never, never>;\n\n// 1. Infer schema\n// 2. Omit keys that we'll manually define (because of generics)\n// 3. Define our own types that have generic constraints\nexport type ActorConfig<\n\tTState,\n\tTConnParams,\n\tTConnState,\n\tTVars,\n\tTInput,\n\tTDatabase extends AnyDatabaseProvider,\n> = Omit<\n\tz.infer<typeof ActorConfigSchema>,\n\t| \"actions\"\n\t| \"onCreate\"\n\t| \"onStart\"\n\t| \"onStateChange\"\n\t| \"onBeforeConnect\"\n\t| \"onConnect\"\n\t| \"onDisconnect\"\n\t| \"onBeforeActionResponse\"\n\t| \"onFetch\"\n\t| \"onWebSocket\"\n\t| \"state\"\n\t| \"createState\"\n\t| \"connState\"\n\t| \"createConnState\"\n\t| \"vars\"\n\t| \"createVars\"\n\t| \"db\"\n> &\n\tBaseActorConfig<\n\t\tTState,\n\t\tTConnParams,\n\t\tTConnState,\n\t\tTVars,\n\t\tTInput,\n\t\tTDatabase,\n\t\tActions<TState, TConnParams, TConnState, TVars, TInput, TDatabase>\n\t> &\n\tCreateState<TState, TConnParams, TConnState, TVars, TInput, TDatabase> &\n\tCreateConnState<TState, TConnParams, TConnState, TVars, TInput, TDatabase> &\n\tCreateVars<TState, TConnParams, TConnState, TVars, TInput, TDatabase> &\n\tActorDatabaseConfig<TDatabase>;\n\n// See description on `ActorConfig`\nexport type ActorConfigInput<\n\tTState = undefined,\n\tTConnParams = undefined,\n\tTConnState = undefined,\n\tTVars = undefined,\n\tTInput = undefined,\n\tTDatabase extends AnyDatabaseProvider = undefined,\n\tTActions extends Actions<\n\t\tTState,\n\t\tTConnParams,\n\t\tTConnState,\n\t\tTVars,\n\t\tTInput,\n\t\tTDatabase\n\t> = Record<never, never>,\n> = {\n\ttypes?: ActorTypes<TState, TConnParams, TConnState, TVars, TInput, TDatabase>;\n} & Omit<\n\tz.input<typeof ActorConfigSchema>,\n\t| \"actions\"\n\t| \"onCreate\"\n\t| \"onStart\"\n\t| \"onStop\"\n\t| \"onStateChange\"\n\t| \"onBeforeConnect\"\n\t| \"onConnect\"\n\t| \"onDisconnect\"\n\t| \"onBeforeActionResponse\"\n\t| \"onFetch\"\n\t| \"onWebSocket\"\n\t| \"state\"\n\t| \"createState\"\n\t| \"connState\"\n\t| \"createConnState\"\n\t| \"vars\"\n\t| \"createVars\"\n\t| \"db\"\n> &\n\tBaseActorConfig<\n\t\tTState,\n\t\tTConnParams,\n\t\tTConnState,\n\t\tTVars,\n\t\tTInput,\n\t\tTDatabase,\n\t\tTActions\n\t> &\n\tCreateState<TState, TConnParams, TConnState, TVars, TInput, TDatabase> &\n\tCreateConnState<TState, TConnParams, TConnState, TVars, TInput, TDatabase> &\n\tCreateVars<TState, TConnParams, TConnState, TVars, TInput, TDatabase> &\n\tActorDatabaseConfig<TDatabase>;\n\n// For testing type definitions:\nexport function test<\n\tTState,\n\tTConnParams,\n\tTConnState,\n\tTVars,\n\tTInput,\n\tTDatabase extends AnyDatabaseProvider,\n\tTActions extends Actions<\n\t\tTState,\n\t\tTConnParams,\n\t\tTConnState,\n\t\tTVars,\n\t\tTInput,\n\t\tTDatabase\n\t>,\n>(\n\tinput: ActorConfigInput<\n\t\tTState,\n\t\tTConnParams,\n\t\tTConnState,\n\t\tTVars,\n\t\tTInput,\n\t\tTDatabase,\n\t\tTActions\n\t>,\n): ActorConfig<TState, TConnParams, TConnState, TVars, TInput, TDatabase> {\n\tconst config = ActorConfigSchema.parse(input) as ActorConfig<\n\t\tTState,\n\t\tTConnParams,\n\t\tTConnState,\n\t\tTVars,\n\t\tTInput,\n\t\tTDatabase\n\t>;\n\treturn config;\n}\n","import * as cbor from \"cbor-x\";\nimport invariant from \"invariant\";\nimport onChange from \"on-change\";\nimport type { ActorKey } from \"@/actor/mod\";\nimport type { Client } from \"@/client/client\";\nimport { getBaseLogger, getIncludeTarget, type Logger } from \"@/common/log\";\nimport { isCborSerializable, stringifyError } from \"@/common/utils\";\nimport type { UniversalWebSocket } from \"@/common/websocket-interface\";\nimport { ActorInspector } from \"@/inspector/actor\";\nimport type { Registry } from \"@/mod\";\nimport type * as bareSchema from \"@/schemas/actor-persist/mod\";\nimport { PERSISTED_ACTOR_VERSIONED } from \"@/schemas/actor-persist/versioned\";\nimport type * as protocol from \"@/schemas/client-protocol/mod\";\nimport { TO_CLIENT_VERSIONED } from \"@/schemas/client-protocol/versioned\";\nimport {\n\tbufferToArrayBuffer,\n\tgetEnvUniversal,\n\tSinglePromiseQueue,\n} from \"@/utils\";\nimport type { ActionContext } from \"./action\";\nimport type { ActorConfig, OnConnectOptions } from \"./config\";\nimport {\n\tCONNECTION_CHECK_LIVENESS_SYMBOL,\n\tConn,\n\ttype ConnectionDriver,\n\ttype ConnId,\n} from \"./connection\";\nimport { ActorContext } from \"./context\";\nimport type { AnyDatabaseProvider, InferDatabaseClient } from \"./database\";\nimport type { ActorDriver, ConnDriver, ConnectionDriversMap } from \"./driver\";\nimport * as errors from \"./errors\";\nimport { serializeActorKey } from \"./keys\";\nimport { loggerWithoutContext } from \"./log\";\nimport type {\n\tPersistedActor,\n\tPersistedConn,\n\tPersistedScheduleEvent,\n} from \"./persisted\";\nimport { processMessage } from \"./protocol/old\";\nimport { CachedSerializer } from \"./protocol/serde\";\nimport { Schedule } from \"./schedule\";\nimport { DeadlineError, deadline } from \"./utils\";\n\n/**\n * Options for the `_saveState` method.\n */\nexport interface SaveStateOptions {\n\t/**\n\t * Forces the state to be saved immediately. This function will return when the state has saved successfully.\n\t */\n\timmediate?: boolean;\n\t/** Bypass ready check for stopping. */\n\tallowStoppingState?: boolean;\n}\n\n/** Actor type alias with all `any` types. Used for `extends` in classes referencing this actor. */\nexport type AnyActorInstance = ActorInstance<\n\t// biome-ignore lint/suspicious/noExplicitAny: Needs to be used in `extends`\n\tany,\n\t// biome-ignore lint/suspicious/noExplicitAny: Needs to be used in `extends`\n\tany,\n\t// biome-ignore lint/suspicious/noExplicitAny: Needs to be used in `extends`\n\tany,\n\t// biome-ignore lint/suspicious/noExplicitAny: Needs to be used in `extends`\n\tany,\n\t// biome-ignore lint/suspicious/noExplicitAny: Needs to be used in `extends`\n\tany,\n\t// biome-ignore lint/suspicious/noExplicitAny: Needs to be used in `extends`\n\tany\n>;\n\nexport type ExtractActorState<A extends AnyActorInstance> =\n\tA extends ActorInstance<\n\t\tinfer State,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Must be used for `extends`\n\t\tany,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Must be used for `extends`\n\t\tany,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Must be used for `extends`\n\t\tany,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Must be used for `extends`\n\t\tany,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Must be used for `extends`\n\t\tany\n\t>\n\t\t? State\n\t\t: never;\n\nexport type ExtractActorConnParams<A extends AnyActorInstance> =\n\tA extends ActorInstance<\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Must be used for `extends`\n\t\tany,\n\t\tinfer ConnParams,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Must be used for `extends`\n\t\tany,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Must be used for `extends`\n\t\tany,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Must be used for `extends`\n\t\tany,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Must be used for `extends`\n\t\tany\n\t>\n\t\t? ConnParams\n\t\t: never;\n\nexport type ExtractActorConnState<A extends AnyActorInstance> =\n\tA extends ActorInstance<\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Must be used for `extends`\n\t\tany,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Must be used for `extends`\n\t\tany,\n\t\tinfer ConnState,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Must be used for `extends`\n\t\tany,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Must be used for `extends`\n\t\tany,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Must be used for `extends`\n\t\tany\n\t>\n\t\t? ConnState\n\t\t: never;\n\nexport class ActorInstance<S, CP, CS, V, I, DB extends AnyDatabaseProvider> {\n\t// Shared actor context for this instance\n\tactorContext: ActorContext<S, CP, CS, V, I, DB>;\n\n\t/** Actor log, intended for the user to call */\n\t#log!: Logger;\n\n\t/** Runtime log, intended for internal actor logs */\n\t#rLog!: Logger;\n\n\t#sleepCalled = false;\n\t#stopCalled = false;\n\n\tget isStopping() {\n\t\treturn this.#stopCalled || this.#sleepCalled;\n\t}\n\n\t#persistChanged = false;\n\t#isInOnStateChange = false;\n\n\t/**\n\t * The proxied state that notifies of changes automatically.\n\t *\n\t * Any data that should be stored indefinitely should be held within this object.\n\t */\n\t#persist!: PersistedActor<S, CP, CS, I>;\n\n\t/** Raw state without the proxy wrapper */\n\t#persistRaw!: PersistedActor<S, CP, CS, I>;\n\n\t#persistWriteQueue = new SinglePromiseQueue();\n\t#alarmWriteQueue = new SinglePromiseQueue();\n\n\t#lastSaveTime = 0;\n\t#pendingSaveTimeout?: NodeJS.Timeout;\n\n\t#vars?: V;\n\n\t#backgroundPromises: Promise<void>[] = [];\n\t#abortController = new AbortController();\n\t#config: ActorConfig<S, CP, CS, V, I, DB>;\n\t#connectionDrivers!: ConnectionDriversMap;\n\t#actorDriver!: ActorDriver;\n\t#inlineClient!: Client<Registry<any>>;\n\t#actorId!: string;\n\t#name!: string;\n\t#key!: ActorKey;\n\t#region!: string;\n\t#ready = false;\n\n\t#connections = new Map<ConnId, Conn<S, CP, CS, V, I, DB>>();\n\t#subscriptionIndex = new Map<string, Set<Conn<S, CP, CS, V, I, DB>>>();\n\t#checkConnLivenessInterval?: NodeJS.Timeout;\n\n\t#sleepTimeout?: NodeJS.Timeout;\n\n\t// Track active raw requests so sleep logic can account for them\n\t#activeRawFetchCount = 0;\n\t#activeRawWebSockets = new Set<UniversalWebSocket>();\n\n\t#schedule!: Schedule;\n\t#db!: InferDatabaseClient<DB>;\n\n\t#inspector = new ActorInspector(() => {\n\t\treturn {\n\t\t\tisDbEnabled: async () => {\n\t\t\t\treturn this.#db !== undefined;\n\t\t\t},\n\t\t\tgetDb: async () => {\n\t\t\t\treturn this.db;\n\t\t\t},\n\t\t\tisStateEnabled: async () => {\n\t\t\t\treturn this.stateEnabled;\n\t\t\t},\n\t\t\tgetState: async () => {\n\t\t\t\tthis.#validateStateEnabled();\n\n\t\t\t\t// Must return from `#persistRaw` in order to not return the `onchange` proxy\n\t\t\t\treturn this.#persistRaw.state as Record<string, any> as unknown;\n\t\t\t},\n\t\t\tgetRpcs: async () => {\n\t\t\t\treturn Object.keys(this.#config.actions);\n\t\t\t},\n\t\t\tgetConnections: async () => {\n\t\t\t\treturn Array.from(this.#connections.entries()).map(([id, conn]) => ({\n\t\t\t\t\tid,\n\t\t\t\t\tstateEnabled: conn._stateEnabled,\n\t\t\t\t\tparams: conn.params as {},\n\t\t\t\t\tstate: conn._stateEnabled ? conn.state : undefined,\n\t\t\t\t}));\n\t\t\t},\n\t\t\tsetState: async (state: unknown) => {\n\t\t\t\tthis.#validateStateEnabled();\n\n\t\t\t\t// Must set on `#persist` instead of `#persistRaw` in order to ensure that the `Proxy` is correctly configured\n\t\t\t\t//\n\t\t\t\t// We have to use `...` so `on-change` recognizes the changes to `state` (i.e. set #persistChanged` to true). This is because:\n\t\t\t\t// 1. In `getState`, we returned the value from `persistRaw`, which does not have the Proxy to monitor state changes\n\t\t\t\t// 2. If we were to assign `state` to `#persist.s`, `on-change` would assume nothing changed since `state` is still === `#persist.s` since we returned a reference in `getState`\n\t\t\t\tthis.#persist.state = { ...(state as S) };\n\t\t\t\tawait this.saveState({ immediate: true });\n\t\t\t},\n\t\t};\n\t});\n\n\tget id() {\n\t\treturn this.#actorId;\n\t}\n\n\tget inlineClient(): Client<Registry<any>> {\n\t\treturn this.#inlineClient;\n\t}\n\n\tget inspector() {\n\t\treturn this.#inspector;\n\t}\n\n\tget #sleepingSupported(): boolean {\n\t\treturn this.#actorDriver.sleep !== undefined;\n\t}\n\n\t/**\n\t * This constructor should never be used directly.\n\t *\n\t * Constructed in {@link ActorInstance.start}.\n\t *\n\t * @private\n\t */\n\tconstructor(config: ActorConfig<S, CP, CS, V, I, DB>) {\n\t\tthis.#config = config;\n\t\tthis.actorContext = new ActorContext(this);\n\t}\n\n\tasync start(\n\t\tconnectionDrivers: ConnectionDriversMap,\n\t\tactorDriver: ActorDriver,\n\t\tinlineClient: Client<Registry<any>>,\n\t\tactorId: string,\n\t\tname: string,\n\t\tkey: ActorKey,\n\t\tregion: string,\n\t) {\n\t\tconst logParams = {\n\t\t\tactor: name,\n\t\t\tkey: serializeActorKey(key),\n\t\t\tactorId,\n\t\t};\n\n\t\tthis.#log = getBaseLogger().child(\n\t\t\tObject.assign(getIncludeTarget() ? { target: \"actor\" } : {}, logParams),\n\t\t);\n\t\tthis.#rLog = getBaseLogger().child(\n\t\t\tObject.assign(\n\t\t\t\tgetIncludeTarget() ? { target: \"actor-runtime\" } : {},\n\t\t\t\tlogParams,\n\t\t\t),\n\t\t);\n\n\t\tthis.#connectionDrivers = connectionDrivers;\n\t\tthis.#actorDriver = actorDriver;\n\t\tthis.#inlineClient = inlineClient;\n\t\tthis.#actorId = actorId;\n\t\tthis.#name = name;\n\t\tthis.#key = key;\n\t\tthis.#region = region;\n\t\tthis.#schedule = new Schedule(this);\n\n\t\t// Initialize server\n\t\t//\n\t\t// Store the promise so network requests can await initialization\n\t\tawait this.#initialize();\n\n\t\t// TODO: Exit process if this errors\n\t\tif (this.#varsEnabled) {\n\t\t\tlet vars: V | undefined;\n\t\t\tif (\"createVars\" in this.#config) {\n\t\t\t\tconst dataOrPromise = this.#config.createVars(\n\t\t\t\t\tthis.actorContext as unknown as ActorContext<\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tany\n\t\t\t\t\t>,\n\t\t\t\t\tthis.#actorDriver.getContext(this.#actorId),\n\t\t\t\t);\n\t\t\t\tif (dataOrPromise instanceof Promise) {\n\t\t\t\t\tvars = await deadline(\n\t\t\t\t\t\tdataOrPromise,\n\t\t\t\t\t\tthis.#config.options.createVarsTimeout,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tvars = dataOrPromise;\n\t\t\t\t}\n\t\t\t} else if (\"vars\" in this.#config) {\n\t\t\t\tvars = structuredClone(this.#config.vars);\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"Could not variables from 'createVars' or 'vars'\");\n\t\t\t}\n\t\t\tthis.#vars = vars;\n\t\t}\n\n\t\t// TODO: Exit process if this errors\n\t\tthis.#rLog.info({ msg: \"actor starting\" });\n\t\tif (this.#config.onStart) {\n\t\t\tconst result = this.#config.onStart(this.actorContext);\n\t\t\tif (result instanceof Promise) {\n\t\t\t\tawait result;\n\t\t\t}\n\t\t}\n\n\t\t// Setup Database\n\t\tif (\"db\" in this.#config && this.#config.db) {\n\t\t\tconst client = await this.#config.db.createClient({\n\t\t\t\tgetDatabase: () => actorDriver.getDatabase(this.#actorId),\n\t\t\t});\n\t\t\tthis.#rLog.info({ msg: \"database migration starting\" });\n\t\t\tawait this.#config.db.onMigrate?.(client);\n\t\t\tthis.#rLog.info({ msg: \"database migration complete\" });\n\t\t\tthis.#db = client;\n\t\t}\n\n\t\t// Set alarm for next scheduled event if any exist after finishing initiation sequence\n\t\tif (this.#persist.scheduledEvents.length > 0) {\n\t\t\tawait this.#queueSetAlarm(this.#persist.scheduledEvents[0].timestamp);\n\t\t}\n\n\t\tthis.#rLog.info({ msg: \"actor ready\" });\n\t\tthis.#ready = true;\n\n\t\t// Must be called after setting `#ready` or else it will not schedule sleep\n\t\tthis.#resetSleepTimer();\n\n\t\t// Start conn liveness interval\n\t\t//\n\t\t// Check for liveness immediately since we may have connections that\n\t\t// were in `reconnecting` state when the actor went to sleep that we\n\t\t// need to purge.\n\t\t//\n\t\t// We don't use alarms for connection liveness since alarms require\n\t\t// durability & are expensive. Connection liveness is safe to assume\n\t\t// it only needs to be ran while the actor is awake and does not need\n\t\t// to manually wake the actor. The only case this is not true is if the\n\t\t// connection liveness timeout is greater than the actor sleep timeout\n\t\t// OR if the actor is manually put to sleep. In this case, the connections\n\t\t// will be stuck in a `reconnecting` state until the actor is awaken again.\n\t\tthis.#checkConnLivenessInterval = setInterval(\n\t\t\tthis.#checkConnectionsLiveness.bind(this),\n\t\t\tthis.#config.options.connectionLivenessInterval,\n\t\t);\n\t\tthis.#checkConnectionsLiveness();\n\t}\n\n\tasync #scheduleEventInner(newEvent: PersistedScheduleEvent) {\n\t\tthis.actorContext.log.info({ msg: \"scheduling event\", ...newEvent });\n\n\t\t// Insert event in to index\n\t\tconst insertIndex = this.#persist.scheduledEvents.findIndex(\n\t\t\t(x) => x.timestamp > newEvent.timestamp,\n\t\t);\n\t\tif (insertIndex === -1) {\n\t\t\tthis.#persist.scheduledEvents.push(newEvent);\n\t\t} else {\n\t\t\tthis.#persist.scheduledEvents.splice(insertIndex, 0, newEvent);\n\t\t}\n\n\t\t// Update alarm if:\n\t\t// - this is the newest event (i.e. at beginning of array) or\n\t\t// - this is the only event (i.e. the only event in the array)\n\t\tif (insertIndex === 0 || this.#persist.scheduledEvents.length === 1) {\n\t\t\tthis.actorContext.log.info({\n\t\t\t\tmsg: \"setting alarm\",\n\t\t\t\ttimestamp: newEvent.timestamp,\n\t\t\t\teventCount: this.#persist.scheduledEvents.length,\n\t\t\t});\n\t\t\tawait this.#queueSetAlarm(newEvent.timestamp);\n\t\t}\n\t}\n\n\tasync _onAlarm() {\n\t\tconst now = Date.now();\n\t\tthis.actorContext.log.debug({\n\t\t\tmsg: \"alarm triggered\",\n\t\t\tnow,\n\t\t\tevents: this.#persist.scheduledEvents.length,\n\t\t});\n\n\t\t// Update sleep\n\t\t//\n\t\t// Do this before any async logic\n\t\tthis.#resetSleepTimer();\n\n\t\t// Remove events from schedule that we're about to run\n\t\tconst runIndex = this.#persist.scheduledEvents.findIndex(\n\t\t\t(x) => x.timestamp <= now,\n\t\t);\n\t\tif (runIndex === -1) {\n\t\t\t// No events are due yet. This will happen if timers fire slightly early.\n\t\t\t// Ensure we reschedule the alarm for the next upcoming event to avoid losing it.\n\t\t\tthis.#rLog.warn({ msg: \"no events are due yet, time may have broken\" });\n\t\t\tif (this.#persist.scheduledEvents.length > 0) {\n\t\t\t\tconst nextTs = this.#persist.scheduledEvents[0].timestamp;\n\t\t\t\tthis.actorContext.log.warn({\n\t\t\t\t\tmsg: \"alarm fired early, rescheduling for next event\",\n\t\t\t\t\tnow,\n\t\t\t\t\tnextTs,\n\t\t\t\t\tdelta: nextTs - now,\n\t\t\t\t});\n\t\t\t\tawait this.#queueSetAlarm(nextTs);\n\t\t\t}\n\t\t\tthis.actorContext.log.debug({ msg: \"no events to run\", now });\n\t\t\treturn;\n\t\t}\n\t\tconst scheduleEvents = this.#persist.scheduledEvents.splice(\n\t\t\t0,\n\t\t\trunIndex + 1,\n\t\t);\n\t\tthis.actorContext.log.debug({\n\t\t\tmsg: \"running events\",\n\t\t\tcount: scheduleEvents.length,\n\t\t});\n\n\t\t// Set alarm for next event\n\t\tif (this.#persist.scheduledEvents.length > 0) {\n\t\t\tconst nextTs = this.#persist.scheduledEvents[0].timestamp;\n\t\t\tthis.actorContext.log.info({\n\t\t\t\tmsg: \"setting next alarm\",\n\t\t\t\tnextTs,\n\t\t\t\tremainingEvents: this.#persist.scheduledEvents.length,\n\t\t\t});\n\t\t\tawait this.#queueSetAlarm(nextTs);\n\t\t}\n\n\t\t// Iterate by event key in order to ensure we call the events in order\n\t\tfor (const event of scheduleEvents) {\n\t\t\ttry {\n\t\t\t\tthis.actorContext.log.info({\n\t\t\t\t\tmsg: \"running action for event\",\n\t\t\t\t\tevent: event.eventId,\n\t\t\t\t\ttimestamp: event.timestamp,\n\t\t\t\t\taction: event.kind.generic.actionName,\n\t\t\t\t});\n\n\t\t\t\t// Look up function\n\t\t\t\tconst fn: unknown = this.#config.actions[event.kind.generic.actionName];\n\n\t\t\t\tif (!fn)\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Missing action for alarm ${event.kind.generic.actionName}`,\n\t\t\t\t\t);\n\t\t\t\tif (typeof fn !== \"function\")\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Alarm function lookup for ${event.kind.generic.actionName} returned ${typeof fn}`,\n\t\t\t\t\t);\n\n\t\t\t\t// Call function\n\t\t\t\ttry {\n\t\t\t\t\tconst args = event.kind.generic.args\n\t\t\t\t\t\t? cbor.decode(new Uint8Array(event.kind.generic.args))\n\t\t\t\t\t\t: [];\n\t\t\t\t\tawait fn.call(undefined, this.actorContext, ...args);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.actorContext.log.error({\n\t\t\t\t\t\tmsg: \"error while running event\",\n\t\t\t\t\t\terror: stringifyError(error),\n\t\t\t\t\t\tevent: event.eventId,\n\t\t\t\t\t\ttimestamp: event.timestamp,\n\t\t\t\t\t\taction: event.kind.generic.actionName,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tthis.actorContext.log.error({\n\t\t\t\t\tmsg: \"internal error while running event\",\n\t\t\t\t\terror: stringifyError(error),\n\t\t\t\t\t...event,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tasync scheduleEvent(\n\t\ttimestamp: number,\n\t\taction: string,\n\t\targs: unknown[],\n\t): Promise<void> {\n\t\treturn this.#scheduleEventInner({\n\t\t\teventId: crypto.randomUUID(),\n\t\t\ttimestamp,\n\t\t\tkind: {\n\t\t\t\tgeneric: {\n\t\t\t\t\tactionName: action,\n\t\t\t\t\targs: bufferToArrayBuffer(cbor.encode(args)),\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\t}\n\n\tget stateEnabled() {\n\t\treturn \"createState\" in this.#config || \"state\" in this.#config;\n\t}\n\n\t#validateStateEnabled() {\n\t\tif (!this.stateEnabled) {\n\t\t\tthrow new errors.StateNotEnabled();\n\t\t}\n\t}\n\n\tget #connStateEnabled() {\n\t\treturn \"createConnState\" in this.#config || \"connState\" in this.#config;\n\t}\n\n\tget #varsEnabled() {\n\t\treturn \"createVars\" in this.#config || \"vars\" in this.#config;\n\t}\n\n\t#validateVarsEnabled() {\n\t\tif (!this.#varsEnabled) {\n\t\t\tthrow new errors.VarsNotEnabled();\n\t\t}\n\t}\n\n\t/** Promise used to wait for a save to complete. This is required since you cannot await `#saveStateThrottled`. */\n\t#onPersistSavedPromise?: PromiseWithResolvers<void>;\n\n\t/** Throttled save state method. Used to write to KV at a reasonable cadence. */\n\t#savePersistThrottled() {\n\t\tconst now = Date.now();\n\t\tconst timeSinceLastSave = now - this.#lastSaveTime;\n\t\tconst saveInterval = this.#config.options.stateSaveInterval;\n\n\t\t// If we're within the throttle window and not already scheduled, schedule the next save.\n\t\tif (timeSinceLastSave < saveInterval) {\n\t\t\tif (this.#pendingSaveTimeout === undefined) {\n\t\t\t\tthis.#pendingSaveTimeout = setTimeout(() => {\n\t\t\t\t\tthis.#pendingSaveTimeout = undefined;\n\t\t\t\t\tthis.#savePersistInner();\n\t\t\t\t}, saveInterval - timeSinceLastSave);\n\t\t\t}\n\t\t} else {\n\t\t\t// If we're outside the throttle window, save immediately\n\t\t\tthis.#savePersistInner();\n\t\t}\n\t}\n\n\t/** Saves the state to KV. You probably want to use #saveStateThrottled instead except for a few edge cases. */\n\tasync #savePersistInner() {\n\t\ttry {\n\t\t\tthis.#lastSaveTime = Date.now();\n\n\t\t\tif (this.#persistChanged) {\n\t\t\t\tconst finished = this.#persistWriteQueue.enqueue(async () => {\n\t\t\t\t\tthis.#rLog.debug({ msg: \"saving persist\" });\n\n\t\t\t\t\t// There might be more changes while we're writing, so we set this\n\t\t\t\t\t// before writing to KV in order to avoid a race condition.\n\t\t\t\t\tthis.#persistChanged = false;\n\n\t\t\t\t\t// Convert to BARE types and write to KV\n\t\t\t\t\tconst bareData = this.#convertToBarePersisted(this.#persistRaw);\n\t\t\t\t\tawait this.#actorDriver.writePersistedData(\n\t\t\t\t\t\tthis.#actorId,\n\t\t\t\t\t\tPERSISTED_ACTOR_VERSIONED.serializeWithEmbeddedVersion(bareData),\n\t\t\t\t\t);\n\n\t\t\t\t\tthis.#rLog.debug({ msg: \"persist saved\" });\n\t\t\t\t});\n\n\t\t\t\tawait finished;\n\t\t\t}\n\n\t\t\tthis.#onPersistSavedPromise?.resolve();\n\t\t} catch (error) {\n\t\t\tthis.#onPersistSavedPromise?.reject(error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync #queueSetAlarm(timestamp: number): Promise<void> {\n\t\tawait this.#alarmWriteQueue.enqueue(async () => {\n\t\t\tawait this.#actorDriver.setAlarm(this, timestamp);\n\t\t});\n\t}\n\n\t/**\n\t * Creates proxy for `#persist` that handles automatically flagging when state needs to be updated.\n\t */\n\t#setPersist(target: PersistedActor<S, CP, CS, I>) {\n\t\t// Set raw persist object\n\t\tthis.#persistRaw = target;\n\n\t\t// TODO: Only validate this for conn state\n\t\t// TODO: Allow disabling in production\n\t\t// If this can't be proxied, return raw value\n\t\tif (target === null || typeof target !== \"object\") {\n\t\t\tlet invalidPath = \"\";\n\t\t\tif (\n\t\t\t\t!isCborSerializable(\n\t\t\t\t\ttarget,\n\t\t\t\t\t(path) => {\n\t\t\t\t\t\tinvalidPath = path;\n\t\t\t\t\t},\n\t\t\t\t\t\"\",\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tthrow new errors.InvalidStateType({ path: invalidPath });\n\t\t\t}\n\t\t\treturn target;\n\t\t}\n\n\t\t// Unsubscribe from old state\n\t\tif (this.#persist) {\n\t\t\tonChange.unsubscribe(this.#persist);\n\t\t}\n\n\t\t// Listen for changes to the object in order to automatically write state\n\t\tthis.#persist = onChange(\n\t\t\ttarget,\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: Don't know types in proxy\n\t\t\t(path: string, value: any, _previousValue: any, _applyData: any) => {\n\t\t\t\tif (path !== \"state\" && !path.startsWith(\"state.\")) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlet invalidPath = \"\";\n\t\t\t\tif (\n\t\t\t\t\t!isCborSerializable(\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t(invalidPathPart) => {\n\t\t\t\t\t\t\tinvalidPath = invalidPathPart;\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"\",\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\tthrow new errors.InvalidStateType({\n\t\t\t\t\t\tpath: path + (invalidPath ? `.${invalidPath}` : \"\"),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tthis.#persistChanged = true;\n\n\t\t\t\t// Inform the inspector about state changes\n\t\t\t\tthis.inspector.emitter.emit(\"stateUpdated\", this.#persist.state);\n\n\t\t\t\t// Call onStateChange if it exists\n\t\t\t\t// Skip if we're already inside onStateChange to prevent infinite recursion\n\t\t\t\tif (\n\t\t\t\t\tthis.#config.onStateChange &&\n\t\t\t\t\tthis.#ready &&\n\t\t\t\t\t!this.#isInOnStateChange\n\t\t\t\t) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.#isInOnStateChange = true;\n\t\t\t\t\t\tthis.#config.onStateChange(\n\t\t\t\t\t\t\tthis.actorContext,\n\t\t\t\t\t\t\tthis.#persistRaw.state,\n\t\t\t\t\t\t);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthis.#rLog.error({\n\t\t\t\t\t\t\tmsg: \"error in `_onStateChange`\",\n\t\t\t\t\t\t\terror: stringifyError(error),\n\t\t\t\t\t\t});\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tthis.#isInOnStateChange = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// State will be flushed at the end of the action\n\t\t\t},\n\t\t\t{ ignoreDetached: true },\n\t\t);\n\t}\n\n\tasync #initialize() {\n\t\t// Read initial state\n\t\tconst persistDataBuffer = await this.#actorDriver.readPersistedData(\n\t\t\tthis.#actorId,\n\t\t);\n\t\tinvariant(\n\t\t\tpersistDataBuffer !== undefined,\n\t\t\t\"persist data has not been set, it should be set when initialized\",\n\t\t);\n\t\tconst bareData =\n\t\t\tPERSISTED_ACTOR_VERSIONED.deserializeWithEmbeddedVersion(\n\t\t\t\tpersistDataBuffer,\n\t\t\t);\n\t\tconst persistData = this.#convertFromBarePersisted(bareData);\n\n\t\tif (persistData.hasInitiated) {\n\t\t\tthis.#rLog.info({\n\t\t\t\tmsg: \"actor restoring\",\n\t\t\t\tconnections: persistData.connections.length,\n\t\t\t});\n\n\t\t\t// Set initial state\n\t\t\tthis.#setPersist(persistData);\n\n\t\t\t// Load connections\n\t\t\tfor (const connPersist of this.#persist.connections) {\n\t\t\t\t// Create connections\n\t\t\t\tconst driver = this.__getConnDriver(connPersist.connDriver);\n\t\t\t\tconst conn = new Conn<S, CP, CS, V, I, DB>(\n\t\t\t\t\tthis,\n\t\t\t\t\tconnPersist,\n\t\t\t\t\tdriver,\n\t\t\t\t\tthis.#connStateEnabled,\n\t\t\t\t);\n\t\t\t\tthis.#connections.set(conn.id, conn);\n\n\t\t\t\t// Register event subscriptions\n\t\t\t\tfor (const sub of connPersist.subscriptions) {\n\t\t\t\t\tthis.#addSubscription(sub.eventName, conn, true);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.#rLog.info({ msg: \"actor creating\" });\n\n\t\t\t// Initialize actor state\n\t\t\tlet stateData: unknown;\n\t\t\tif (this.stateEnabled) {\n\t\t\t\tthis.#rLog.info({ msg: \"actor state initializing\" });\n\n\t\t\t\tif (\"createState\" in this.#config) {\n\t\t\t\t\tthis.#config.createState;\n\n\t\t\t\t\t// Convert state to undefined since state is not defined yet here\n\t\t\t\t\tstateData = await this.#config.createState(\n\t\t\t\t\t\tthis.actorContext as unknown as ActorContext<\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tundefined\n\t\t\t\t\t\t>,\n\t\t\t\t\t\tpersistData.input!,\n\t\t\t\t\t);\n\t\t\t\t} else if (\"state\" in this.#config) {\n\t\t\t\t\tstateData = structuredClone(this.#config.state);\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(\"Both 'createState' or 'state' were not defined\");\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.#rLog.debug({ msg: \"state not enabled\" });\n\t\t\t}\n\n\t\t\t// Save state and mark as initialized\n\t\t\tpersistData.state = stateData as S;\n\t\t\tpersistData.hasInitiated = true;\n\n\t\t\t// Update state\n\t\t\tthis.#rLog.debug({ msg: \"writing state\" });\n\t\t\tconst bareData = this.#convertToBarePersisted(persistData);\n\t\t\tawait this.#actorDriver.writePersistedData(\n\t\t\t\tthis.#actorId,\n\t\t\t\tPERSISTED_ACTOR_VERSIONED.serializeWithEmbeddedVersion(bareData),\n\t\t\t);\n\n\t\t\tthis.#setPersist(persistData);\n\n\t\t\t// Notify creation\n\t\t\tif (this.#config.onCreate) {\n\t\t\t\tawait this.#config.onCreate(this.actorContext, persistData.input!);\n\t\t\t}\n\t\t}\n\t}\n\n\t__getConnForId(id: string): Conn<S, CP, CS, V, I, DB> | undefined {\n\t\treturn this.#connections.get(id);\n\t}\n\n\t/**\n\t * Removes a connection and cleans up its resources.\n\t */\n\t__removeConn(conn: Conn<S, CP, CS, V, I, DB> | undefined) {\n\t\tif (!conn) {\n\t\t\tthis.#rLog.warn({ msg: \"`conn` does not exist\" });\n\t\t\treturn;\n\t\t}\n\n\t\t// Remove from persist & save immediately\n\t\tconst connIdx = this.#persist.connections.findIndex(\n\t\t\t(c) => c.connId === conn.id,\n\t\t);\n\t\tif (connIdx !== -1) {\n\t\t\tthis.#persist.connections.splice(connIdx, 1);\n\t\t\tthis.saveState({ immediate: true, allowStoppingState: true });\n\t\t} else {\n\t\t\tthis.#rLog.warn({\n\t\t\t\tmsg: \"could not find persisted connection to remove\",\n\t\t\t\tconnId: conn.id,\n\t\t\t});\n\t\t}\n\n\t\t// Remove from state\n\t\tthis.#connections.delete(conn.id);\n\n\t\t// Remove subscriptions\n\t\tfor (const eventName of [...conn.subscriptions.values()]) {\n\t\t\tthis.#removeSubscription(eventName, conn, true);\n\t\t}\n\n\t\tthis.inspector.emitter.emit(\"connectionUpdated\");\n\t\tif (this.#config.onDisconnect) {\n\t\t\ttry {\n\t\t\t\tconst result = this.#config.onDisconnect(this.actorContext, conn);\n\t\t\t\tif (result instanceof Promise) {\n\t\t\t\t\t// Handle promise but don't await it to prevent blocking\n\t\t\t\t\tresult.catch((error) => {\n\t\t\t\t\t\tthis.#rLog.error({\n\t\t\t\t\t\t\tmsg: \"error in `onDisconnect`\",\n\t\t\t\t\t\t\terror: stringifyError(error),\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tthis.#rLog.error({\n\t\t\t\t\tmsg: \"error in `onDisconnect`\",\n\t\t\t\t\terror: stringifyError(error),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Update sleep\n\t\tthis.#resetSleepTimer();\n\t}\n\n\tasync prepareConn(\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypeScript bug with ExtractActorConnParams<this>,\n\t\tparams: any,\n\t\trequest?: Request,\n\t): Promise<CS> {\n\t\t// Authenticate connection\n\t\tlet connState: CS | undefined;\n\n\t\tconst onBeforeConnectOpts = {\n\t\t\trequest,\n\t\t} satisfies OnConnectOptions;\n\n\t\tif (this.#config.onBeforeConnect) {\n\t\t\tawait this.#config.onBeforeConnect(\n\t\t\t\tthis.actorContext,\n\t\t\t\tonBeforeConnectOpts,\n\t\t\t\tparams,\n\t\t\t);\n\t\t}\n\n\t\tif (this.#connStateEnabled) {\n\t\t\tif (\"createConnState\" in this.#config) {\n\t\t\t\tconst dataOrPromise = this.#config.createConnState(\n\t\t\t\t\tthis.actorContext as unknown as ActorContext<\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tundefined\n\t\t\t\t\t>,\n\t\t\t\t\tonBeforeConnectOpts,\n\t\t\t\t\tparams,\n\t\t\t\t);\n\t\t\t\tif (dataOrPromise instanceof Promise) {\n\t\t\t\t\tconnState = await deadline(\n\t\t\t\t\t\tdataOrPromise,\n\t\t\t\t\t\tthis.#config.options.createConnStateTimeout,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tconnState = dataOrPromise;\n\t\t\t\t}\n\t\t\t} else if (\"connState\" in this.#config) {\n\t\t\t\tconnState = structuredClone(this.#config.connState);\n\t\t\t} else {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Could not create connection state from 'createConnState' or 'connState'\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn connState as CS;\n\t}\n\n\t__getConnDriver(driverId: ConnectionDriver): ConnDriver {\n\t\t// Get driver\n\t\tconst driver = this.#connectionDrivers[driverId];\n\t\tif (!driver) throw new Error(`No connection driver: ${driverId}`);\n\t\treturn driver;\n\t}\n\n\t/**\n\t * Called after establishing a connection handshake.\n\t */\n\tasync createConn(\n\t\tconnectionId: string,\n\t\tconnectionToken: string,\n\t\tparams: CP,\n\t\tstate: CS,\n\t\tdriverId: ConnectionDriver,\n\t\tdriverState: unknown,\n\t\tauthData: unknown,\n\t): Promise<Conn<S, CP, CS, V, I, DB>> {\n\t\tthis.#assertReady();\n\n\t\tif (this.#connections.has(connectionId)) {\n\t\t\tthrow new Error(`Connection already exists: ${connectionId}`);\n\t\t}\n\n\t\t// Create connection\n\t\tconst driver = this.__getConnDriver(driverId);\n\t\tconst persist: PersistedConn<CP, CS> = {\n\t\t\tconnId: connectionId,\n\t\t\ttoken: connectionToken,\n\t\t\tconnDriver: driverId,\n\t\t\tconnDriverState: driverState,\n\t\t\tparams: params,\n\t\t\tstate: state,\n\t\t\tauthData: authData,\n\t\t\tlastSeen: Date.now(),\n\t\t\tsubscriptions: [],\n\t\t};\n\t\tconst conn = new Conn<S, CP, CS, V, I, DB>(\n\t\t\tthis,\n\t\t\tpersist,\n\t\t\tdriver,\n\t\t\tthis.#connStateEnabled,\n\t\t);\n\t\tthis.#connections.set(conn.id, conn);\n\n\t\t// Update sleep\n\t\t//\n\t\t// Do this immediately after adding connection & before any async logic in order to avoid race conditions with sleep timeouts\n\t\tthis.#resetSleepTimer();\n\n\t\t// Add to persistence & save immediately\n\t\tthis.#persist.connections.push(persist);\n\t\tthis.saveState({ immediate: true });\n\n\t\t// Handle connection\n\t\tif (this.#config.onConnect) {\n\t\t\ttry {\n\t\t\t\tconst result = this.#config.onConnect(this.actorContext, conn);\n\t\t\t\tif (result instanceof Promise) {\n\t\t\t\t\tdeadline(result, this.#config.options.onConnectTimeout).catch(\n\t\t\t\t\t\t(error) => {\n\t\t\t\t\t\t\tthis.#rLog.error({\n\t\t\t\t\t\t\t\tmsg: \"error in `onConnect`, closing socket\",\n\t\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconn?.disconnect(\"`onConnect` failed\");\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tthis.#rLog.error({\n\t\t\t\t\tmsg: \"error in `onConnect`\",\n\t\t\t\t\terror: stringifyError(error),\n\t\t\t\t});\n\t\t\t\tconn?.disconnect(\"`onConnect` failed\");\n\t\t\t}\n\t\t}\n\n\t\tthis.inspector.emitter.emit(\"connectionUpdated\");\n\n\t\t// Send init message\n\t\tconn._sendMessage(\n\t\t\tnew CachedSerializer<protocol.ToClient>(\n\t\t\t\t{\n\t\t\t\t\tbody: {\n\t\t\t\t\t\ttag: \"Init\",\n\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\tactorId: this.id,\n\t\t\t\t\t\t\tconnectionId: conn.id,\n\t\t\t\t\t\t\tconnectionToken: conn._token,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tTO_CLIENT_VERSIONED,\n\t\t\t),\n\t\t);\n\n\t\treturn conn;\n\t}\n\n\t// MARK: Messages\n\tasync processMessage(\n\t\tmessage: protocol.ToServer,\n\t\tconn: Conn<S, CP, CS, V, I, DB>,\n\t) {\n\t\tawait processMessage(message, this, conn, {\n\t\t\tonExecuteAction: async (ctx, name, args) => {\n\t\t\t\tthis.inspector.emitter.emit(\"eventFired\", {\n\t\t\t\t\ttype: \"action\",\n\t\t\t\t\tname,\n\t\t\t\t\targs,\n\t\t\t\t\tconnId: conn.id,\n\t\t\t\t});\n\t\t\t\treturn await this.executeAction(ctx, name, args);\n\t\t\t},\n\t\t\tonSubscribe: async (eventName, conn) => {\n\t\t\t\tthis.inspector.emitter.emit(\"eventFired\", {\n\t\t\t\t\ttype: \"subscribe\",\n\t\t\t\t\teventName,\n\t\t\t\t\tconnId: conn.id,\n\t\t\t\t});\n\t\t\t\tthis.#addSubscription(eventName, conn, false);\n\t\t\t},\n\t\t\tonUnsubscribe: async (eventName, conn) => {\n\t\t\t\tthis.inspector.emitter.emit(\"eventFired\", {\n\t\t\t\t\ttype: \"unsubscribe\",\n\t\t\t\t\teventName,\n\t\t\t\t\tconnId: conn.id,\n\t\t\t\t});\n\t\t\t\tthis.#removeSubscription(eventName, conn, false);\n\t\t\t},\n\t\t});\n\t}\n\n\t// MARK: Events\n\t#addSubscription(\n\t\teventName: string,\n\t\tconnection: Conn<S, CP, CS, V, I, DB>,\n\t\tfromPersist: boolean,\n\t) {\n\t\tif (connection.subscriptions.has(eventName)) {\n\t\t\tthis.#rLog.debug({\n\t\t\t\tmsg: \"connection already has subscription\",\n\t\t\t\teventName,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Persist subscriptions & save immediately\n\t\t//\n\t\t// Don't update persistence if already restoring from persistence\n\t\tif (!fromPersist) {\n\t\t\tconnection.__persist.subscriptions.push({ eventName: eventName });\n\t\t\tthis.saveState({ immediate: true });\n\t\t}\n\n\t\t// Update subscriptions\n\t\tconnection.subscriptions.add(eventName);\n\n\t\t// Update subscription index\n\t\tlet subscribers = this.#subscriptionIndex.get(eventName);\n\t\tif (!subscribers) {\n\t\t\tsubscribers = new Set();\n\t\t\tthis.#subscriptionIndex.set(eventName, subscribers);\n\t\t}\n\t\tsubscribers.add(connection);\n\t}\n\n\t#removeSubscription(\n\t\teventName: string,\n\t\tconnection: Conn<S, CP, CS, V, I, DB>,\n\t\tfromRemoveConn: boolean,\n\t) {\n\t\tif (!connection.subscriptions.has(eventName)) {\n\t\t\tthis.#rLog.warn({\n\t\t\t\tmsg: \"connection does not have subscription\",\n\t\t\t\teventName,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Persist subscriptions & save immediately\n\t\t//\n\t\t// Don't update the connection itself if the connection is already being removed\n\t\tif (!fromRemoveConn) {\n\t\t\tconnection.subscriptions.delete(eventName);\n\n\t\t\tconst subIdx = connection.__persist.subscriptions.findIndex(\n\t\t\t\t(s) => s.eventName === eventName,\n\t\t\t);\n\t\t\tif (subIdx !== -1) {\n\t\t\t\tconnection.__persist.subscriptions.splice(subIdx, 1);\n\t\t\t} else {\n\t\t\t\tthis.#rLog.warn({\n\t\t\t\t\tmsg: \"subscription does not exist with name\",\n\t\t\t\t\teventName,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthis.saveState({ immediate: true });\n\t\t}\n\n\t\t// Update scriptions index\n\t\tconst subscribers = this.#subscriptionIndex.get(eventName);\n\t\tif (subscribers) {\n\t\t\tsubscribers.delete(connection);\n\t\t\tif (subscribers.size === 0) {\n\t\t\t\tthis.#subscriptionIndex.delete(eventName);\n\t\t\t}\n\t\t}\n\t}\n\n\t#assertReady(allowStoppingState: boolean = false) {\n\t\tif (!this.#ready) throw new errors.InternalError(\"Actor not ready\");\n\t\tif (!allowStoppingState && this.#sleepCalled)\n\t\t\tthrow new errors.InternalError(\"Actor is going to sleep\");\n\t\tif (!allowStoppingState && this.#stopCalled)\n\t\t\tthrow new errors.InternalError(\"Actor is stopping\");\n\t}\n\n\t/**\n\t * Check the liveness of all connections.\n\t * Sets up a recurring check based on the configured interval.\n\t */\n\t#checkConnectionsLiveness() {\n\t\tthis.#rLog.debug({ msg: \"checking connections liveness\" });\n\n\t\tfor (const conn of this.#connections.values()) {\n\t\t\tconst liveness = conn[CONNECTION_CHECK_LIVENESS_SYMBOL]();\n\t\t\tif (liveness.status === \"connected\") {\n\t\t\t\tthis.#rLog.debug({ msg: \"connection is alive\", connId: conn.id });\n\t\t\t} else {\n\t\t\t\tconst lastSeen = liveness.lastSeen;\n\t\t\t\tconst sinceLastSeen = Date.now() - lastSeen;\n\t\t\t\tif (sinceLastSeen < this.#config.options.connectionLivenessTimeout) {\n\t\t\t\t\tthis.#rLog.debug({\n\t\t\t\t\t\tmsg: \"connection might be alive, will check later\",\n\t\t\t\t\t\tconnId: conn.id,\n\t\t\t\t\t\tlastSeen,\n\t\t\t\t\t\tsinceLastSeen,\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Connection is dead, remove it\n\t\t\t\tthis.#rLog.warn({\n\t\t\t\t\tmsg: \"connection is dead, removing\",\n\t\t\t\t\tconnId: conn.id,\n\t\t\t\t\tlastSeen,\n\t\t\t\t});\n\n\t\t\t\t// TODO: Do we need to force disconnect the connection here?\n\n\t\t\t\tthis.__removeConn(conn);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Check if the actor is ready to handle requests.\n\t */\n\tisReady(): boolean {\n\t\treturn this.#ready;\n\t}\n\n\t/**\n\t * Execute an action call from a client.\n\t *\n\t * This method handles:\n\t * 1. Validating the action name\n\t * 2. Executing the action function\n\t * 3. Processing the result through onBeforeActionResponse (if configured)\n\t * 4. Handling timeouts and errors\n\t * 5. Saving state changes\n\t *\n\t * @param ctx The action context\n\t * @param actionName The name of the action being called\n\t * @param args The arguments passed to the action\n\t * @returns The result of the action call\n\t * @throws {ActionNotFound} If the action doesn't exist\n\t * @throws {ActionTimedOut} If the action times out\n\t * @internal\n\t */\n\tasync executeAction(\n\t\tctx: ActionContext<S, CP, CS, V, I, DB>,\n\t\tactionName: string,\n\t\targs: unknown[],\n\t): Promise<unknown> {\n\t\tinvariant(this.#ready, \"executing action before ready\");\n\n\t\t// Prevent calling private or reserved methods\n\t\tif (!(actionName in this.#config.actions)) {\n\t\t\tthis.#rLog.warn({ msg: \"action does not exist\", actionName });\n\t\t\tthrow new errors.ActionNotFound(actionName);\n\t\t}\n\n\t\t// Check if the method exists on this object\n\t\tconst actionFunction = this.#config.actions[actionName];\n\t\tif (typeof actionFunction !== \"function\") {\n\t\t\tthis.#rLog.warn({\n\t\t\t\tmsg: \"action is not a function\",\n\t\t\t\tactionName: actionName,\n\t\t\t\ttype: typeof actionFunction,\n\t\t\t});\n\t\t\tthrow new errors.ActionNotFound(actionName);\n\t\t}\n\n\t\t// TODO: pass abortable to the action to decide when to abort\n\t\t// TODO: Manually call abortable for better error handling\n\t\t// Call the function on this object with those arguments\n\t\ttry {\n\t\t\t// Log when we start executing the action\n\t\t\tthis.#rLog.debug({\n\t\t\t\tmsg: \"executing action\",\n\t\t\t\tactionName: actionName,\n\t\t\t\targs,\n\t\t\t});\n\n\t\t\tconst outputOrPromise = actionFunction.call(undefined, ctx, ...args);\n\t\t\tlet output: unknown;\n\t\t\tif (outputOrPromise instanceof Promise) {\n\t\t\t\t// Log that we're waiting for an async action\n\t\t\t\tthis.#rLog.debug({\n\t\t\t\t\tmsg: \"awaiting async action\",\n\t\t\t\t\tactionName: actionName,\n\t\t\t\t});\n\n\t\t\t\toutput = await deadline(\n\t\t\t\t\toutputOrPromise,\n\t\t\t\t\tthis.#config.options.actionTimeout,\n\t\t\t\t);\n\n\t\t\t\t// Log that async action completed\n\t\t\t\tthis.#rLog.debug({\n\t\t\t\t\tmsg: \"async action completed\",\n\t\t\t\t\tactionName: actionName,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\toutput = outputOrPromise;\n\t\t\t}\n\n\t\t\t// Process the output through onBeforeActionResponse if configured\n\t\t\tif (this.#config.onBeforeActionResponse) {\n\t\t\t\ttry {\n\t\t\t\t\tconst processedOutput = this.#config.onBeforeActionResponse(\n\t\t\t\t\t\tthis.actorContext,\n\t\t\t\t\t\tactionName,\n\t\t\t\t\t\targs,\n\t\t\t\t\t\toutput,\n\t\t\t\t\t);\n\t\t\t\t\tif (processedOutput instanceof Promise) {\n\t\t\t\t\t\tthis.#rLog.debug({\n\t\t\t\t\t\t\tmsg: \"awaiting onBeforeActionResponse\",\n\t\t\t\t\t\t\tactionName: actionName,\n\t\t\t\t\t\t});\n\t\t\t\t\t\toutput = await processedOutput;\n\t\t\t\t\t\tthis.#rLog.debug({\n\t\t\t\t\t\t\tmsg: \"onBeforeActionResponse completed\",\n\t\t\t\t\t\t\tactionName: actionName,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\toutput = processedOutput;\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.#rLog.error({\n\t\t\t\t\t\tmsg: \"error in `onBeforeActionResponse`\",\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\n\t\t\t// Log the output before returning\n\t\t\tthis.#rLog.debug({\n\t\t\t\tmsg: \"action completed\",\n\t\t\t\tactionName: actionName,\n\t\t\t\toutputType: typeof output,\n\t\t\t\tisPromise: output instanceof Promise,\n\t\t\t});\n\n\t\t\t// This output *might* reference a part of the state (using onChange), but\n\t\t\t// that's OK since this value always gets serialized and sent over the\n\t\t\t// network.\n\t\t\treturn output;\n\t\t} catch (error) {\n\t\t\tif (error instanceof DeadlineError) {\n\t\t\t\tthrow new errors.ActionTimedOut();\n\t\t\t}\n\t\t\tthis.#rLog.error({\n\t\t\t\tmsg: \"action error\",\n\t\t\t\tactionName: actionName,\n\t\t\t\terror: stringifyError(error),\n\t\t\t});\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\tthis.#savePersistThrottled();\n\t\t}\n\t}\n\n\t/**\n\t * Returns a list of action methods available on this actor.\n\t */\n\tget actions(): string[] {\n\t\treturn Object.keys(this.#config.actions);\n\t}\n\n\t/**\n\t * Handles raw HTTP requests to the actor.\n\t */\n\tasync handleFetch(request: Request, opts: {}): Promise<Response> {\n\t\tthis.#assertReady();\n\n\t\tif (!this.#config.onFetch) {\n\t\t\tthrow new errors.FetchHandlerNotDefined();\n\t\t}\n\n\t\t// Track active raw fetch while handler runs\n\t\tthis.#activeRawFetchCount++;\n\t\tthis.#resetSleepTimer();\n\n\t\ttry {\n\t\t\tconst response = await this.#config.onFetch(\n\t\t\t\tthis.actorContext,\n\t\t\t\trequest,\n\t\t\t\topts,\n\t\t\t);\n\t\t\tif (!response) {\n\t\t\t\tthrow new errors.InvalidFetchResponse();\n\t\t\t}\n\t\t\treturn response;\n\t\t} catch (error) {\n\t\t\tthis.#rLog.error({ msg: \"onFetch error\", error: stringifyError(error) });\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\t// Decrement active raw fetch counter and re-evaluate sleep\n\t\t\tthis.#activeRawFetchCount = Math.max(0, this.#activeRawFetchCount - 1);\n\t\t\tthis.#resetSleepTimer();\n\t\t\tthis.#savePersistThrottled();\n\t\t}\n\t}\n\n\t/**\n\t * Handles raw WebSocket connections to the actor.\n\t */\n\tasync handleWebSocket(\n\t\twebsocket: UniversalWebSocket,\n\t\topts: { request: Request },\n\t): Promise<void> {\n\t\tthis.#assertReady();\n\n\t\tif (!this.#config.onWebSocket) {\n\t\t\tthrow new errors.InternalError(\"onWebSocket handler not defined\");\n\t\t}\n\n\t\ttry {\n\t\t\t// Set up state tracking to detect changes during WebSocket handling\n\t\t\tconst stateBeforeHandler = this.#persistChanged;\n\n\t\t\t// Track active websocket until it fully closes\n\t\t\tthis.#activeRawWebSockets.add(websocket);\n\t\t\tthis.#resetSleepTimer();\n\n\t\t\t// Track socket close\n\t\t\tconst onSocketClosed = () => {\n\t\t\t\t// Remove listener and socket from tracking\n\t\t\t\ttry {\n\t\t\t\t\twebsocket.removeEventListener(\"close\", onSocketClosed);\n\t\t\t\t\twebsocket.removeEventListener(\"error\", onSocketClosed);\n\t\t\t\t} catch {}\n\t\t\t\tthis.#activeRawWebSockets.delete(websocket);\n\t\t\t\tthis.#resetSleepTimer();\n\t\t\t};\n\t\t\ttry {\n\t\t\t\twebsocket.addEventListener(\"close\", onSocketClosed);\n\t\t\t\twebsocket.addEventListener(\"error\", onSocketClosed);\n\t\t\t} catch {}\n\n\t\t\t// Handle WebSocket\n\t\t\tawait this.#config.onWebSocket(this.actorContext, websocket, opts);\n\n\t\t\t// If state changed during the handler, save it\n\t\t\tif (this.#persistChanged && !stateBeforeHandler) {\n\t\t\t\tawait this.saveState({ immediate: true });\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.#rLog.error({\n\t\t\t\tmsg: \"onWebSocket error\",\n\t\t\t\terror: stringifyError(error),\n\t\t\t});\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\tthis.#savePersistThrottled();\n\t\t}\n\t}\n\n\t// MARK: Lifecycle hooks\n\n\t// MARK: Exposed methods\n\tget log(): Logger {\n\t\tinvariant(this.#log, \"log not configured\");\n\t\treturn this.#log;\n\t}\n\n\tget rLog(): Logger {\n\t\tinvariant(this.#rLog, \"log not configured\");\n\t\treturn this.#rLog;\n\t}\n\n\t/**\n\t * Gets the name.\n\t */\n\tget name(): string {\n\t\treturn this.#name;\n\t}\n\n\t/**\n\t * Gets the key.\n\t */\n\tget key(): ActorKey {\n\t\treturn this.#key;\n\t}\n\n\t/**\n\t * Gets the region.\n\t */\n\tget region(): string {\n\t\treturn this.#region;\n\t}\n\n\t/**\n\t * Gets the scheduler.\n\t */\n\tget schedule(): Schedule {\n\t\treturn this.#schedule;\n\t}\n\n\t/**\n\t * Gets the map of connections.\n\t */\n\tget conns(): Map<ConnId, Conn<S, CP, CS, V, I, DB>> {\n\t\treturn this.#connections;\n\t}\n\n\t/**\n\t * Gets the current state.\n\t *\n\t * Changing properties of this value will automatically be persisted.\n\t */\n\tget state(): S {\n\t\tthis.#validateStateEnabled();\n\t\treturn this.#persist.state;\n\t}\n\n\t/**\n\t * Gets the database.\n\t * @experimental\n\t * @throws {DatabaseNotEnabled} If the database is not enabled.\n\t */\n\tget db(): InferDatabaseClient<DB> {\n\t\tif (!this.#db) {\n\t\t\tthrow new errors.DatabaseNotEnabled();\n\t\t}\n\t\treturn this.#db;\n\t}\n\n\t/**\n\t * Sets the current state.\n\t *\n\t * This property will automatically be persisted.\n\t */\n\tset state(value: S) {\n\t\tthis.#validateStateEnabled();\n\t\tthis.#persist.state = value;\n\t}\n\n\tget vars(): V {\n\t\tthis.#validateVarsEnabled();\n\t\tinvariant(this.#vars !== undefined, \"vars not enabled\");\n\t\treturn this.#vars;\n\t}\n\n\t/**\n\t * Broadcasts an event to all connected clients.\n\t * @param name - The name of the event.\n\t * @param args - The arguments to send with the event.\n\t */\n\t_broadcast<Args extends Array<unknown>>(name: string, ...args: Args) {\n\t\tthis.#assertReady();\n\n\t\tthis.inspector.emitter.emit(\"eventFired\", {\n\t\t\ttype: \"broadcast\",\n\t\t\teventName: name,\n\t\t\targs,\n\t\t});\n\n\t\t// Send to all connected clients\n\t\tconst subscriptions = this.#subscriptionIndex.get(name);\n\t\tif (!subscriptions) return;\n\n\t\tconst toClientSerializer = new CachedSerializer<protocol.ToClient>(\n\t\t\t{\n\t\t\t\tbody: {\n\t\t\t\t\ttag: \"Event\",\n\t\t\t\t\tval: {\n\t\t\t\t\t\tname,\n\t\t\t\t\t\targs: bufferToArrayBuffer(cbor.encode(args)),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tTO_CLIENT_VERSIONED,\n\t\t);\n\n\t\t// Send message to clients\n\t\tfor (const connection of subscriptions) {\n\t\t\tconnection._sendMessage(toClientSerializer);\n\t\t}\n\t}\n\n\t/**\n\t * Prevents the actor from sleeping until promise is complete.\n\t *\n\t * This allows the actor runtime to ensure that a promise completes while\n\t * returning from an action request early.\n\t *\n\t * @param promise - The promise to run in the background.\n\t */\n\t_waitUntil(promise: Promise<void>) {\n\t\tthis.#assertReady();\n\n\t\t// TODO: Should we force save the state?\n\t\t// Add logging to promise and make it non-failable\n\t\tconst nonfailablePromise = promise\n\t\t\t.then(() => {\n\t\t\t\tthis.#rLog.debug({ msg: \"wait until promise complete\" });\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tthis.#rLog.error({\n\t\t\t\t\tmsg: \"wait until promise failed\",\n\t\t\t\t\terror: stringifyError(error),\n\t\t\t\t});\n\t\t\t});\n\t\tthis.#backgroundPromises.push(nonfailablePromise);\n\t}\n\n\t/**\n\t * Forces the state to get saved.\n\t *\n\t * This is helpful if running a long task that may fail later or when\n\t * running a background job that updates the state.\n\t *\n\t * @param opts - Options for saving the state.\n\t */\n\tasync saveState(opts: SaveStateOptions) {\n\t\tthis.#assertReady(opts.allowStoppingState);\n\n\t\tif (this.#persistChanged) {\n\t\t\tif (opts.immediate) {\n\t\t\t\t// Save immediately\n\t\t\t\tawait this.#savePersistInner();\n\t\t\t} else {\n\t\t\t\t// Create callback\n\t\t\t\tif (!this.#onPersistSavedPromise) {\n\t\t\t\t\tthis.#onPersistSavedPromise = Promise.withResolvers();\n\t\t\t\t}\n\n\t\t\t\t// Save state throttled\n\t\t\t\tthis.#savePersistThrottled();\n\n\t\t\t\t// Wait for save\n\t\t\t\tawait this.#onPersistSavedPromise.promise;\n\t\t\t}\n\t\t}\n\t}\n\n\t// MARK: Sleep\n\t/**\n\t * Reset timer from the last actor interaction that allows it to be put to sleep.\n\t *\n\t * This should be called any time a sleep-related event happens:\n\t * - Connection opens (will clear timer)\n\t * - Connection closes (will schedule timer if there are no open connections)\n\t * - Alarm triggers (will reset timer)\n\t *\n\t * We don't need to call this on events like individual action calls, since there will always be a connection open for these.\n\t **/\n\t#resetSleepTimer() {\n\t\tif (this.#config.options.noSleep || !this.#sleepingSupported) return;\n\n\t\tconst canSleep = this.#canSleep();\n\n\t\tthis.#rLog.debug({\n\t\t\tmsg: \"resetting sleep timer\",\n\t\t\tcanSleep,\n\t\t\texistingTimeout: !!this.#sleepTimeout,\n\t\t});\n\n\t\tif (this.#sleepTimeout) {\n\t\t\tclearTimeout(this.#sleepTimeout);\n\t\t\tthis.#sleepTimeout = undefined;\n\t\t}\n\n\t\t// Don't set a new timer if already sleeping\n\t\tif (this.#sleepCalled) return;\n\n\t\tif (canSleep) {\n\t\t\tthis.#sleepTimeout = setTimeout(() => {\n\t\t\t\tthis._sleep().catch((error) => {\n\t\t\t\t\tthis.#rLog.error({\n\t\t\t\t\t\tmsg: \"error during sleep\",\n\t\t\t\t\t\terror: stringifyError(error),\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}, this.#config.options.sleepTimeout);\n\t\t}\n\t}\n\n\t/** If this actor can be put in a sleeping state. */\n\t#canSleep(): boolean {\n\t\tif (!this.#ready) return false;\n\n\t\t// Check for active conns. This will also cover active actions, since all actions have a connection.\n\t\tfor (const conn of this.#connections.values()) {\n\t\t\tif (conn.status === \"connected\") return false;\n\t\t}\n\n\t\t// Do not sleep if raw fetches are in-flight\n\t\tif (this.#activeRawFetchCount > 0) return false;\n\n\t\t// Do not sleep if there are raw websockets open\n\t\tif (this.#activeRawWebSockets.size > 0) return false;\n\n\t\treturn true;\n\t}\n\n\t/** Puts an actor to sleep. This should just start the sleep sequence, most shutdown logic should be in _stop (which is called by the ActorDriver when sleeping). */\n\tasync _sleep() {\n\t\tconst sleep = this.#actorDriver.sleep?.bind(\n\t\t\tthis.#actorDriver,\n\t\t\tthis.#actorId,\n\t\t);\n\t\tinvariant(this.#sleepingSupported, \"sleeping not supported\");\n\t\tinvariant(sleep, \"no sleep on driver\");\n\n\t\tif (this.#sleepCalled) {\n\t\t\tthis.#rLog.warn({ msg: \"already sleeping actor\" });\n\t\t\treturn;\n\t\t}\n\t\tthis.#sleepCalled = true;\n\n\t\tthis.#rLog.info({ msg: \"actor sleeping\" });\n\n\t\t// Schedule sleep to happen on the next tick. This allows for any action that calls _sleep to complete.\n\t\tsetImmediate(async () => {\n\t\t\t// The actor driver should call stop when ready to stop\n\t\t\t//\n\t\t\t// This will call _stop once Pegboard responds with the new status\n\t\t\tawait sleep();\n\t\t});\n\t}\n\n\t// MARK: Stop\n\tasync _stop() {\n\t\tif (this.#stopCalled) {\n\t\t\tthis.#rLog.warn({ msg: \"already stopping actor\" });\n\t\t\treturn;\n\t\t}\n\t\tthis.#stopCalled = true;\n\n\t\tthis.#rLog.info({ msg: \"actor stopping\" });\n\n\t\t// Abort any listeners waiting for shutdown\n\t\ttry {\n\t\t\tthis.#abortController.abort();\n\t\t} catch {}\n\n\t\t// Call onStop lifecycle hook if defined\n\t\tif (this.#config.onStop) {\n\t\t\ttry {\n\t\t\t\tthis.#rLog.debug({ msg: \"calling onStop\" });\n\t\t\t\tconst result = this.#config.onStop(this.actorContext);\n\t\t\t\tif (result instanceof Promise) {\n\t\t\t\t\tawait deadline(result, this.#config.options.onStopTimeout);\n\t\t\t\t}\n\t\t\t\tthis.#rLog.debug({ msg: \"onStop completed\" });\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof DeadlineError) {\n\t\t\t\t\tthis.#rLog.error({ msg: \"onStop timed out\" });\n\t\t\t\t} else {\n\t\t\t\t\tthis.#rLog.error({\n\t\t\t\t\t\tmsg: \"error in onStop\",\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\n\t\t// Disconnect existing connections\n\t\tconst promises: Promise<unknown>[] = [];\n\t\tfor (const connection of this.#connections.values()) {\n\t\t\tpromises.push(connection.disconnect());\n\n\t\t\t// TODO: Figure out how to abort HTTP requests on shutdown\n\t\t}\n\n\t\t// Wait for any background tasks to finish, with timeout\n\t\tawait this.#waitBackgroundPromises(this.#config.options.waitUntilTimeout);\n\n\t\t// Clear timeouts\n\t\tif (this.#pendingSaveTimeout) clearTimeout(this.#pendingSaveTimeout);\n\t\tif (this.#sleepTimeout) clearTimeout(this.#sleepTimeout);\n\t\tif (this.#checkConnLivenessInterval)\n\t\t\tclearInterval(this.#checkConnLivenessInterval);\n\n\t\t// Write state\n\t\tawait this.saveState({ immediate: true, allowStoppingState: true });\n\n\t\t// Await all `close` event listeners with 1.5 second timeout\n\t\tconst res = Promise.race([\n\t\t\tPromise.all(promises).then(() => false),\n\t\t\tnew Promise<boolean>((res) =>\n\t\t\t\tglobalThis.setTimeout(() => res(true), 1500),\n\t\t\t),\n\t\t]);\n\n\t\tif (await res) {\n\t\t\tthis.#rLog.warn({\n\t\t\t\tmsg: \"timed out waiting for connections to close, shutting down anyway\",\n\t\t\t});\n\t\t}\n\n\t\t// Wait for queues to finish\n\t\tif (this.#persistWriteQueue.runningDrainLoop)\n\t\t\tawait this.#persistWriteQueue.runningDrainLoop;\n\t\tif (this.#alarmWriteQueue.runningDrainLoop)\n\t\t\tawait this.#alarmWriteQueue.runningDrainLoop;\n\t}\n\n\t/** Abort signal that fires when the actor is stopping. */\n\tget abortSignal(): AbortSignal {\n\t\treturn this.#abortController.signal;\n\t}\n\n\t/** Wait for background waitUntil promises with a timeout. */\n\tasync #waitBackgroundPromises(timeoutMs: number) {\n\t\tconst pending = this.#backgroundPromises;\n\t\tif (pending.length === 0) {\n\t\t\tthis.#rLog.debug({ msg: \"no background promises\" });\n\t\t\treturn;\n\t\t}\n\n\t\t// Race promises with timeout to determine if pending promises settled fast enough\n\t\tconst timedOut = await Promise.race([\n\t\t\tPromise.allSettled(pending).then(() => false),\n\t\t\tnew Promise<true>((resolve) =>\n\t\t\t\tsetTimeout(() => resolve(true), timeoutMs),\n\t\t\t),\n\t\t]);\n\n\t\tif (timedOut) {\n\t\t\tthis.#rLog.error({\n\t\t\t\tmsg: \"timed out waiting for background tasks, background promises may have leaked\",\n\t\t\t\tcount: pending.length,\n\t\t\t\ttimeoutMs,\n\t\t\t});\n\t\t} else {\n\t\t\tthis.#rLog.debug({ msg: \"background promises finished\" });\n\t\t}\n\t}\n\n\t// MARK: BARE Conversion Helpers\n\t#convertToBarePersisted(\n\t\tpersist: PersistedActor<S, CP, CS, I>,\n\t): bareSchema.PersistedActor {\n\t\treturn {\n\t\t\tinput:\n\t\t\t\tpersist.input !== undefined\n\t\t\t\t\t? bufferToArrayBuffer(cbor.encode(persist.input))\n\t\t\t\t\t: null,\n\t\t\thasInitialized: persist.hasInitiated,\n\t\t\tstate: bufferToArrayBuffer(cbor.encode(persist.state)),\n\t\t\tconnections: persist.connections.map((conn) => ({\n\t\t\t\tid: conn.connId,\n\t\t\t\ttoken: conn.token,\n\t\t\t\tdriver: conn.connDriver as string,\n\t\t\t\tdriverState: bufferToArrayBuffer(\n\t\t\t\t\tcbor.encode(conn.connDriverState || {}),\n\t\t\t\t),\n\t\t\t\tparameters: bufferToArrayBuffer(cbor.encode(conn.params || {})),\n\t\t\t\tstate: bufferToArrayBuffer(cbor.encode(conn.state || {})),\n\t\t\t\tsubscriptions: conn.subscriptions.map((sub) => ({\n\t\t\t\t\teventName: sub.eventName,\n\t\t\t\t})),\n\t\t\t\tlastSeen: BigInt(conn.lastSeen),\n\t\t\t})),\n\t\t\tscheduledEvents: persist.scheduledEvents.map((event) => ({\n\t\t\t\teventId: event.eventId,\n\t\t\t\ttimestamp: BigInt(event.timestamp),\n\t\t\t\tkind: {\n\t\t\t\t\ttag: \"GenericPersistedScheduleEvent\" as const,\n\t\t\t\t\tval: {\n\t\t\t\t\t\taction: event.kind.generic.actionName,\n\t\t\t\t\t\targs: event.kind.generic.args ?? null,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t})),\n\t\t};\n\t}\n\n\t#convertFromBarePersisted(\n\t\tbareData: bareSchema.PersistedActor,\n\t): PersistedActor<S, CP, CS, I> {\n\t\treturn {\n\t\t\tinput: bareData.input\n\t\t\t\t? cbor.decode(new Uint8Array(bareData.input))\n\t\t\t\t: undefined,\n\t\t\thasInitiated: bareData.hasInitialized,\n\t\t\tstate: cbor.decode(new Uint8Array(bareData.state)),\n\t\t\tconnections: bareData.connections.map((conn) => ({\n\t\t\t\tconnId: conn.id,\n\t\t\t\ttoken: conn.token,\n\t\t\t\tconnDriver: conn.driver as ConnectionDriver,\n\t\t\t\tconnDriverState: cbor.decode(new Uint8Array(conn.driverState)),\n\t\t\t\tparams: cbor.decode(new Uint8Array(conn.parameters)),\n\t\t\t\tstate: cbor.decode(new Uint8Array(conn.state)),\n\t\t\t\tsubscriptions: conn.subscriptions.map((sub) => ({\n\t\t\t\t\teventName: sub.eventName,\n\t\t\t\t})),\n\t\t\t\tlastSeen: Number(conn.lastSeen),\n\t\t\t})),\n\t\t\tscheduledEvents: bareData.scheduledEvents.map((event) => ({\n\t\t\t\teventId: event.eventId,\n\t\t\t\ttimestamp: Number(event.timestamp),\n\t\t\t\tkind: {\n\t\t\t\t\tgeneric: {\n\t\t\t\t\t\tactionName: event.kind.val.action,\n\t\t\t\t\t\targs: event.kind.val.args,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t})),\n\t\t};\n\t}\n}\n","import { sValidator } from \"@hono/standard-validator\";\nimport jsonPatch from \"@rivetkit/fast-json-patch\";\nimport { Hono } from \"hono\";\nimport { streamSSE } from \"hono/streaming\";\nimport { createNanoEvents, type Unsubscribe } from \"nanoevents\";\nimport z from \"zod/v4\";\nimport type {\n\tAnyDatabaseProvider,\n\tInferDatabaseClient,\n} from \"@/actor/database\";\nimport {\n\tColumnsSchema,\n\ttype Connection,\n\tForeignKeysSchema,\n\tPatchSchema,\n\ttype RealtimeEvent,\n\ttype RecordedRealtimeEvent,\n\tTablesSchema,\n} from \"./protocol/common\";\n\nexport type ActorInspectorRouterEnv = {\n\tVariables: {\n\t\tinspector: ActorInspector;\n\t};\n};\n\n/**\n * Create a router for the Actor Inspector.\n * @internal\n */\nexport function createActorInspectorRouter() {\n\treturn new Hono<ActorInspectorRouterEnv>()\n\t\t.get(\"/ping\", (c) => {\n\t\t\treturn c.json({ message: \"pong\" }, 200);\n\t\t})\n\t\t.get(\"/state\", async (c) => {\n\t\t\tif (await c.var.inspector.accessors.isStateEnabled()) {\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\tenabled: true,\n\t\t\t\t\t\tstate: await c.var.inspector.accessors.getState(),\n\t\t\t\t\t},\n\t\t\t\t\t200,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn c.json({ enabled: false, state: null }, 200);\n\t\t})\n\t\t.patch(\n\t\t\t\"/state\",\n\t\t\tsValidator(\n\t\t\t\t\"json\",\n\t\t\t\tz.object({ patch: PatchSchema }).or(z.object({ replace: z.any() })),\n\t\t\t),\n\t\t\tasync (c) => {\n\t\t\t\tif (!(await c.var.inspector.accessors.isStateEnabled())) {\n\t\t\t\t\treturn c.json({ enabled: false }, 200);\n\t\t\t\t}\n\n\t\t\t\tconst body = c.req.valid(\"json\");\n\t\t\t\tif (\"replace\" in body) {\n\t\t\t\t\tawait c.var.inspector.accessors.setState(body.replace);\n\t\t\t\t\treturn c.json(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tenabled: true,\n\t\t\t\t\t\t\tstate: await c.var.inspector.accessors.getState(),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t200,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst state = await c.var.inspector.accessors.getState();\n\n\t\t\t\tconst { newDocument: newState } = jsonPatch.applyPatch(\n\t\t\t\t\tstate,\n\t\t\t\t\tbody.patch,\n\t\t\t\t);\n\t\t\t\tawait c.var.inspector.accessors.setState(newState);\n\n\t\t\t\treturn c.json(\n\t\t\t\t\t{ enabled: true, state: await c.var.inspector.accessors.getState() },\n\t\t\t\t\t200,\n\t\t\t\t);\n\t\t\t},\n\t\t)\n\t\t.get(\"/state/stream\", async (c) => {\n\t\t\tif (!(await c.var.inspector.accessors.isStateEnabled())) {\n\t\t\t\treturn c.json({ enabled: false }, 200);\n\t\t\t}\n\n\t\t\tlet id = 0;\n\t\t\tlet unsub: Unsubscribe;\n\t\t\treturn streamSSE(\n\t\t\t\tc,\n\t\t\t\tasync (stream) => {\n\t\t\t\t\tunsub = c.var.inspector.emitter.on(\"stateUpdated\", async (state) => {\n\t\t\t\t\t\tstream.writeSSE({\n\t\t\t\t\t\t\tdata: JSON.stringify(state) || \"\",\n\t\t\t\t\t\t\tevent: \"state-update\",\n\t\t\t\t\t\t\tid: String(id++),\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\t\tconst { promise } = Promise.withResolvers<void>();\n\n\t\t\t\t\treturn promise;\n\t\t\t\t},\n\t\t\t\tasync () => {\n\t\t\t\t\tunsub?.();\n\t\t\t\t},\n\t\t\t);\n\t\t})\n\t\t.get(\"/connections\", async (c) => {\n\t\t\tconst connections = await c.var.inspector.accessors.getConnections();\n\t\t\treturn c.json({ connections }, 200);\n\t\t})\n\t\t.get(\"/connections/stream\", async (c) => {\n\t\t\tlet id = 0;\n\t\t\tlet unsub: Unsubscribe;\n\t\t\treturn streamSSE(\n\t\t\t\tc,\n\t\t\t\tasync (stream) => {\n\t\t\t\t\tunsub = c.var.inspector.emitter.on(\"connectionUpdated\", async () => {\n\t\t\t\t\t\tstream.writeSSE({\n\t\t\t\t\t\t\tdata: JSON.stringify(\n\t\t\t\t\t\t\t\tawait c.var.inspector.accessors.getConnections(),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tevent: \"connection-update\",\n\t\t\t\t\t\t\tid: String(id++),\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\t\tconst { promise } = Promise.withResolvers<void>();\n\n\t\t\t\t\treturn promise;\n\t\t\t\t},\n\t\t\t\tasync () => {\n\t\t\t\t\tunsub?.();\n\t\t\t\t},\n\t\t\t);\n\t\t})\n\t\t.get(\"/events\", async (c) => {\n\t\t\tconst events = c.var.inspector.lastRealtimeEvents;\n\t\t\treturn c.json({ events }, 200);\n\t\t})\n\t\t.post(\"/events/clear\", async (c) => {\n\t\t\tc.var.inspector.lastRealtimeEvents.length = 0; // Clear the events\n\t\t\treturn c.json({ message: \"Events cleared\" }, 200);\n\t\t})\n\t\t.get(\"/events/stream\", async (c) => {\n\t\t\tlet id = 0;\n\t\t\tlet unsub: Unsubscribe;\n\t\t\treturn streamSSE(\n\t\t\t\tc,\n\t\t\t\tasync (stream) => {\n\t\t\t\t\tunsub = c.var.inspector.emitter.on(\"eventFired\", () => {\n\t\t\t\t\t\tstream.writeSSE({\n\t\t\t\t\t\t\tdata: JSON.stringify(c.var.inspector.lastRealtimeEvents),\n\t\t\t\t\t\t\tevent: \"realtime-event\",\n\t\t\t\t\t\t\tid: String(id++),\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\t\tconst { promise } = Promise.withResolvers<void>();\n\n\t\t\t\t\treturn promise;\n\t\t\t\t},\n\t\t\t\tasync () => {\n\t\t\t\t\tunsub?.();\n\t\t\t\t},\n\t\t\t);\n\t\t})\n\t\t.get(\"/rpcs\", async (c) => {\n\t\t\tconst rpcs = await c.var.inspector.accessors.getRpcs();\n\t\t\treturn c.json({ rpcs }, 200);\n\t\t})\n\t\t.get(\"/db\", async (c) => {\n\t\t\tif (!(await c.var.inspector.accessors.isDbEnabled())) {\n\t\t\t\treturn c.json({ enabled: false, db: null }, 200);\n\t\t\t}\n\n\t\t\t// Access the SQLite database\n\t\t\tconst db = await c.var.inspector.accessors.getDb();\n\n\t\t\t// Get list of tables\n\t\t\tconst rows = await db.execute(`PRAGMA table_list`);\n\t\t\tconst tables = TablesSchema.parse(rows).filter(\n\t\t\t\t(table) => table.schema !== \"temp\" && !table.name.startsWith(\"sqlite_\"),\n\t\t\t);\n\t\t\t// Get columns for each table\n\t\t\tconst tablesInfo = await Promise.all(\n\t\t\t\ttables.map((table) => db.execute(`PRAGMA table_info(${table.name})`)),\n\t\t\t);\n\t\t\tconst columns = tablesInfo.map((def) => ColumnsSchema.parse(def));\n\n\t\t\t// Get foreign keys for each table\n\t\t\tconst foreignKeysList = await Promise.all(\n\t\t\t\ttables.map((table) =>\n\t\t\t\t\tdb.execute(`PRAGMA foreign_key_list(${table.name})`),\n\t\t\t\t),\n\t\t\t);\n\t\t\tconst foreignKeys = foreignKeysList.map((def) =>\n\t\t\t\tForeignKeysSchema.parse(def),\n\t\t\t);\n\n\t\t\t// Get record counts for each table\n\t\t\tconst countInfo = await Promise.all(\n\t\t\t\ttables.map((table) =>\n\t\t\t\t\tdb.execute(`SELECT COUNT(*) as count FROM ${table.name}`),\n\t\t\t\t),\n\t\t\t);\n\t\t\tconst counts = countInfo.map((def) => {\n\t\t\t\treturn def[0].count || 0;\n\t\t\t});\n\n\t\t\treturn c.json(\n\t\t\t\t{\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tdb: tablesInfo.map((_, index) => {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttable: tables[index],\n\t\t\t\t\t\t\tcolumns: columns[index],\n\t\t\t\t\t\t\tforeignKeys: foreignKeys[index],\n\t\t\t\t\t\t\trecords: counts[index],\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t\t200,\n\t\t\t);\n\t\t})\n\t\t.post(\n\t\t\t\"/db\",\n\t\t\tsValidator(\n\t\t\t\t\"json\",\n\t\t\t\tz.object({ query: z.string(), params: z.array(z.any()).optional() }),\n\t\t\t),\n\t\t\tasync (c) => {\n\t\t\t\tif (!(await c.var.inspector.accessors.isDbEnabled())) {\n\t\t\t\t\treturn c.json({ enabled: false }, 200);\n\t\t\t\t}\n\t\t\t\tconst db = await c.var.inspector.accessors.getDb();\n\n\t\t\t\ttry {\n\t\t\t\t\tconst result = (await db.execute(\n\t\t\t\t\t\tc.req.valid(\"json\").query,\n\t\t\t\t\t\t...(c.req.valid(\"json\").params || []),\n\t\t\t\t\t)) as unknown;\n\t\t\t\t\treturn c.json({ result }, 200);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tc;\n\t\t\t\t\treturn c.json({ error: (error as Error).message }, 500);\n\t\t\t\t}\n\t\t\t},\n\t\t);\n}\n\ninterface ActorInspectorAccessors {\n\tisStateEnabled: () => Promise<boolean>;\n\tgetState: () => Promise<unknown>;\n\tsetState: (state: unknown) => Promise<void>;\n\tisDbEnabled: () => Promise<boolean>;\n\tgetDb: () => Promise<InferDatabaseClient<AnyDatabaseProvider>>;\n\tgetRpcs: () => Promise<string[]>;\n\tgetConnections: () => Promise<Connection[]>;\n}\n\ninterface ActorInspectorEmitterEvents {\n\tstateUpdated: (state: unknown) => void;\n\tconnectionUpdated: () => void;\n\teventFired: (event: RealtimeEvent) => void;\n}\n\n/**\n * Provides a unified interface for inspecting actor external and internal state.\n */\nexport class ActorInspector {\n\tpublic readonly accessors: ActorInspectorAccessors;\n\tpublic readonly emitter = createNanoEvents<ActorInspectorEmitterEvents>();\n\n\t#lastRealtimeEvents: RecordedRealtimeEvent[] = [];\n\n\tget lastRealtimeEvents() {\n\t\treturn this.#lastRealtimeEvents;\n\t}\n\n\tconstructor(accessors: () => ActorInspectorAccessors) {\n\t\tthis.accessors = accessors();\n\t\tthis.emitter.on(\"eventFired\", (event) => {\n\t\t\tthis.#lastRealtimeEvents.push({\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t...event,\n\t\t\t});\n\t\t\t// keep the last 100 events\n\t\t\tif (this.#lastRealtimeEvents.length > 100) {\n\t\t\t\tthis.#lastRealtimeEvents = this.#lastRealtimeEvents.slice(-100);\n\t\t\t}\n\t\t});\n\t}\n}\n","import type { ActorKey } from \"@/actor/mod\";\nimport type { Client } from \"@/client/client\";\nimport type { Logger } from \"@/common/log\";\nimport type { Registry } from \"@/registry/mod\";\nimport type { Conn, ConnId } from \"./connection\";\nimport type { AnyDatabaseProvider, InferDatabaseClient } from \"./database\";\nimport type { ActorInstance, SaveStateOptions } from \"./instance\";\nimport type { Schedule } from \"./schedule\";\n\n/**\n * ActorContext class that provides access to actor methods and state\n */\nexport class ActorContext<\n\tTState,\n\tTConnParams,\n\tTConnState,\n\tTVars,\n\tTInput,\n\tTDatabase extends AnyDatabaseProvider,\n> {\n\t#actor: ActorInstance<\n\t\tTState,\n\t\tTConnParams,\n\t\tTConnState,\n\t\tTVars,\n\t\tTInput,\n\t\tTDatabase\n\t>;\n\n\tconstructor(\n\t\tactor: ActorInstance<\n\t\t\tTState,\n\t\t\tTConnParams,\n\t\t\tTConnState,\n\t\t\tTVars,\n\t\t\tTInput,\n\t\t\tTDatabase\n\t\t>,\n\t) {\n\t\tthis.#actor = actor;\n\t}\n\n\t/**\n\t * Get the actor state\n\t */\n\tget state(): TState {\n\t\treturn this.#actor.state;\n\t}\n\n\t/**\n\t * Get the actor variables\n\t */\n\tget vars(): TVars {\n\t\treturn this.#actor.vars;\n\t}\n\n\t/**\n\t * Broadcasts an event to all connected clients.\n\t * @param name - The name of the event.\n\t * @param args - The arguments to send with the event.\n\t */\n\tbroadcast<Args extends Array<unknown>>(name: string, ...args: Args): void {\n\t\tthis.#actor._broadcast(name, ...args);\n\t\treturn;\n\t}\n\n\t/**\n\t * Gets the logger instance.\n\t */\n\tget log(): Logger {\n\t\treturn this.#actor.log;\n\t}\n\n\t/**\n\t * Gets actor ID.\n\t */\n\tget actorId(): string {\n\t\treturn this.#actor.id;\n\t}\n\n\t/**\n\t * Gets the actor name.\n\t */\n\tget name(): string {\n\t\treturn this.#actor.name;\n\t}\n\n\t/**\n\t * Gets the actor key.\n\t */\n\tget key(): ActorKey {\n\t\treturn this.#actor.key;\n\t}\n\n\t/**\n\t * Gets the region.\n\t */\n\tget region(): string {\n\t\treturn this.#actor.region;\n\t}\n\n\t/**\n\t * Gets the scheduler.\n\t */\n\tget schedule(): Schedule {\n\t\treturn this.#actor.schedule;\n\t}\n\n\t/**\n\t * Gets the map of connections.\n\t */\n\tget conns(): Map<\n\t\tConnId,\n\t\tConn<TState, TConnParams, TConnState, TVars, TInput, TDatabase>\n\t> {\n\t\treturn this.#actor.conns;\n\t}\n\n\t/**\n\t * Returns the client for the given registry.\n\t */\n\tclient<R extends Registry<any>>(): Client<R> {\n\t\treturn this.#actor.inlineClient as Client<R>;\n\t}\n\n\t/**\n\t * Gets the database.\n\t * @experimental\n\t * @throws {DatabaseNotEnabled} If the database is not enabled.\n\t */\n\tget db(): InferDatabaseClient<TDatabase> {\n\t\treturn this.#actor.db;\n\t}\n\n\t/**\n\t * Forces the state to get saved.\n\t *\n\t * @param opts - Options for saving the state.\n\t */\n\tasync saveState(opts: SaveStateOptions): Promise<void> {\n\t\treturn this.#actor.saveState(opts);\n\t}\n\n\t/**\n\t * Prevents the actor from sleeping until promise is complete.\n\t */\n\twaitUntil(promise: Promise<void>): void {\n\t\tthis.#actor._waitUntil(promise);\n\t}\n\n\t/**\n\t * AbortSignal that fires when the actor is stopping.\n\t */\n\tget abortSignal(): AbortSignal {\n\t\treturn this.#actor.abortSignal;\n\t}\n\n\t/**\n\t * Forces the actor to sleep.\n\t *\n\t * Not supported on all drivers.\n\t *\n\t * @experimental\n\t */\n\tsleep() {\n\t\tthis.#actor._sleep();\n\t}\n}\n","import type { ActorKey } from \"@/mod\";\n\nexport const EMPTY_KEY = \"/\";\nexport const KEY_SEPARATOR = \"/\";\n\nexport function serializeActorKey(key: ActorKey): string {\n\t// Use a special marker for empty key arrays\n\tif (key.length === 0) {\n\t\treturn EMPTY_KEY;\n\t}\n\n\t// Escape each key part to handle the separator and the empty key marker\n\tconst escapedParts = key.map((part) => {\n\t\t// Handle empty strings by using a special marker\n\t\tif (part === \"\") {\n\t\t\treturn \"\\\\0\"; // Use \\0 as a marker for empty strings\n\t\t}\n\n\t\t// Escape backslashes first to avoid conflicts with our markers\n\t\tlet escaped = part.replace(/\\\\/g, \"\\\\\\\\\");\n\n\t\t// Then escape separators\n\t\tescaped = escaped.replace(/\\//g, `\\\\${KEY_SEPARATOR}`);\n\n\t\treturn escaped;\n\t});\n\n\treturn escapedParts.join(KEY_SEPARATOR);\n}\n\nexport function deserializeActorKey(keyString: string | undefined): ActorKey {\n\t// Check for special empty key marker\n\tif (\n\t\tkeyString === undefined ||\n\t\tkeyString === null ||\n\t\tkeyString === EMPTY_KEY\n\t) {\n\t\treturn [];\n\t}\n\n\t// Split by unescaped separators and unescape the escaped characters\n\tconst parts: string[] = [];\n\tlet currentPart = \"\";\n\tlet escaping = false;\n\tlet isEmptyStringMarker = false;\n\n\tfor (let i = 0; i < keyString.length; i++) {\n\t\tconst char = keyString[i];\n\n\t\tif (escaping) {\n\t\t\t// Handle special escape sequences\n\t\t\tif (char === \"0\") {\n\t\t\t\t// \\0 represents an empty string marker\n\t\t\t\tisEmptyStringMarker = true;\n\t\t\t} else {\n\t\t\t\t// This is an escaped character, add it directly\n\t\t\t\tcurrentPart += char;\n\t\t\t}\n\t\t\tescaping = false;\n\t\t} else if (char === \"\\\\\") {\n\t\t\t// Start of an escape sequence\n\t\t\tescaping = true;\n\t\t} else if (char === KEY_SEPARATOR) {\n\t\t\t// This is a separator\n\t\t\tif (isEmptyStringMarker) {\n\t\t\t\tparts.push(\"\");\n\t\t\t\tisEmptyStringMarker = false;\n\t\t\t} else {\n\t\t\t\tparts.push(currentPart);\n\t\t\t}\n\t\t\tcurrentPart = \"\";\n\t\t} else {\n\t\t\t// Regular character\n\t\t\tcurrentPart += char;\n\t\t}\n\t}\n\n\t// Add the last part\n\tif (escaping) {\n\t\t// Incomplete escape at the end - treat as literal backslash\n\t\tparts.push(currentPart + \"\\\\\");\n\t} else if (isEmptyStringMarker) {\n\t\tparts.push(\"\");\n\t} else if (currentPart !== \"\" || parts.length > 0) {\n\t\tparts.push(currentPart);\n\t}\n\n\treturn parts;\n}\n","import type { AnyActorInstance } from \"./instance\";\n\nexport class Schedule {\n\t#actor: AnyActorInstance;\n\n\tconstructor(actor: AnyActorInstance) {\n\t\tthis.#actor = actor;\n\t}\n\n\tasync after(duration: number, fn: string, ...args: unknown[]) {\n\t\tawait this.#actor.scheduleEvent(Date.now() + duration, fn, args);\n\t}\n\n\tasync at(timestamp: number, fn: string, ...args: unknown[]) {\n\t\tawait this.#actor.scheduleEvent(timestamp, fn, args);\n\t}\n}\n","import type { RegistryConfig } from \"@/registry/config\";\nimport type { ActionContext } from \"./action\";\nimport type { Actions, ActorConfig } from \"./config\";\nimport type { ActorContext } from \"./context\";\nimport type { AnyDatabaseProvider } from \"./database\";\nimport { ActorInstance } from \"./instance\";\n\nexport type AnyActorDefinition = ActorDefinition<\n\tany,\n\tany,\n\tany,\n\tany,\n\tany,\n\tany,\n\tany\n>;\n\n/**\n * Extracts the context type from an ActorDefinition\n */\nexport type ActorContextOf<AD extends AnyActorDefinition> =\n\tAD extends ActorDefinition<\n\t\tinfer S,\n\t\tinfer CP,\n\t\tinfer CS,\n\t\tinfer V,\n\t\tinfer I,\n\t\tinfer DB,\n\t\tany\n\t>\n\t\t? ActorContext<S, CP, CS, V, I, DB>\n\t\t: never;\n\n/**\n * Extracts the context type from an ActorDefinition\n */\nexport type ActionContextOf<AD extends AnyActorDefinition> =\n\tAD extends ActorDefinition<\n\t\tinfer S,\n\t\tinfer CP,\n\t\tinfer CS,\n\t\tinfer V,\n\t\tinfer I,\n\t\tinfer DB,\n\t\tany\n\t>\n\t\t? ActionContext<S, CP, CS, V, I, DB>\n\t\t: never;\n\nexport class ActorDefinition<\n\tS,\n\tCP,\n\tCS,\n\tV,\n\tI,\n\tDB extends AnyDatabaseProvider,\n\tR extends Actions<S, CP, CS, V, I, DB>,\n> {\n\t#config: ActorConfig<S, CP, CS, V, I, DB>;\n\n\tconstructor(config: ActorConfig<S, CP, CS, V, I, DB>) {\n\t\tthis.#config = config;\n\t}\n\n\tget config(): ActorConfig<S, CP, CS, V, I, DB> {\n\t\treturn this.#config;\n\t}\n\n\tinstantiate(): ActorInstance<S, CP, CS, V, I, DB> {\n\t\treturn new ActorInstance(this.#config);\n\t}\n}\n\nexport function lookupInRegistry(\n\tregistryConfig: RegistryConfig,\n\tname: string,\n): AnyActorDefinition {\n\t// Build actor\n\tconst definition = registryConfig.use[name];\n\tif (!definition) throw new Error(`no actor in registry for name ${name}`);\n\treturn definition;\n}\n","import type { SSEStreamingApi } from \"hono/streaming\";\nimport type { WSContext } from \"hono/ws\";\nimport type { WebSocket } from \"ws\";\nimport {\n\ttype AnyConn,\n\tCONNECTION_DRIVER_HTTP,\n\tCONNECTION_DRIVER_SSE,\n\tCONNECTION_DRIVER_WEBSOCKET,\n} from \"@/actor/connection\";\nimport {\n\ttype ConnDriver,\n\ttype ConnectionDriversMap,\n\tConnectionReadyState,\n} from \"@/actor/driver\";\nimport type { AnyActorInstance } from \"@/actor/instance\";\nimport type { CachedSerializer, Encoding } from \"@/actor/protocol/serde\";\nimport { encodeDataToString } from \"@/actor/protocol/serde\";\nimport type * as protocol from \"@/schemas/client-protocol/mod\";\nimport { loggerWithoutContext } from \"./log\";\n\n// This state is different than `PersistedConn` state since the connection-specific state is persisted & must be serializable. This is also part of the connection driver, not part of the core actor.\n//\n// This holds the actual connections, which are not serializable.\n//\n// This is scoped to each actor. Do not share between multiple actors.\nexport class GenericConnGlobalState {\n\twebsockets = new Map<string, WSContext>();\n\tsseStreams = new Map<string, SSEStreamingApi>();\n}\n\n/**\n * Exposes connection drivers for platforms that support vanilla WebSocket, SSE, and HTTP.\n */\nexport function createGenericConnDrivers(\n\tglobalState: GenericConnGlobalState,\n): ConnectionDriversMap {\n\treturn {\n\t\t[CONNECTION_DRIVER_WEBSOCKET]: createGenericWebSocketDriver(globalState),\n\t\t[CONNECTION_DRIVER_SSE]: createGenericSseDriver(globalState),\n\t\t[CONNECTION_DRIVER_HTTP]: createGenericHttpDriver(),\n\t};\n}\n\n// MARK: WebSocket\nexport interface GenericWebSocketDriverState {\n\tencoding: Encoding;\n}\n\nexport function createGenericWebSocketDriver(\n\tglobalState: GenericConnGlobalState,\n): ConnDriver<GenericWebSocketDriverState> {\n\treturn {\n\t\tsendMessage: (\n\t\t\tactor: AnyActorInstance,\n\t\t\tconn: AnyConn,\n\t\t\tstate: GenericWebSocketDriverState,\n\t\t\tmessage: CachedSerializer<protocol.ToClient>,\n\t\t) => {\n\t\t\tconst ws = globalState.websockets.get(conn.id);\n\t\t\tif (!ws) {\n\t\t\t\tactor.rLog.warn({\n\t\t\t\t\tmsg: \"missing ws for sendMessage\",\n\t\t\t\t\tactorId: actor.id,\n\t\t\t\t\tconnId: conn.id,\n\t\t\t\t\ttotalCount: globalState.websockets.size,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst serialized = message.serialize(state.encoding);\n\n\t\t\tactor.rLog.debug({\n\t\t\t\tmsg: \"sending websocket message\",\n\t\t\t\tencoding: state.encoding,\n\t\t\t\tdataType: typeof serialized,\n\t\t\t\tisUint8Array: serialized instanceof Uint8Array,\n\t\t\t\tisArrayBuffer: serialized instanceof ArrayBuffer,\n\t\t\t\tdataLength:\n\t\t\t\t\t(serialized as any).byteLength || (serialized as any).length,\n\t\t\t});\n\n\t\t\t// Convert Uint8Array to ArrayBuffer for proper transmission\n\t\t\tif (serialized instanceof Uint8Array) {\n\t\t\t\tconst buffer = serialized.buffer.slice(\n\t\t\t\t\tserialized.byteOffset,\n\t\t\t\t\tserialized.byteOffset + serialized.byteLength,\n\t\t\t\t);\n\t\t\t\t// Handle SharedArrayBuffer case\n\t\t\t\tif (buffer instanceof SharedArrayBuffer) {\n\t\t\t\t\tconst arrayBuffer = new ArrayBuffer(buffer.byteLength);\n\t\t\t\t\tnew Uint8Array(arrayBuffer).set(new Uint8Array(buffer));\n\t\t\t\t\tactor.rLog.debug({\n\t\t\t\t\t\tmsg: \"converted SharedArrayBuffer to ArrayBuffer\",\n\t\t\t\t\t\tbyteLength: arrayBuffer.byteLength,\n\t\t\t\t\t});\n\t\t\t\t\tws.send(arrayBuffer);\n\t\t\t\t} else {\n\t\t\t\t\tactor.rLog.debug({\n\t\t\t\t\t\tmsg: \"sending ArrayBuffer\",\n\t\t\t\t\t\tbyteLength: buffer.byteLength,\n\t\t\t\t\t});\n\t\t\t\t\tws.send(buffer);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tactor.rLog.debug({\n\t\t\t\t\tmsg: \"sending string data\",\n\t\t\t\t\tlength: (serialized as string).length,\n\t\t\t\t});\n\t\t\t\tws.send(serialized);\n\t\t\t}\n\t\t},\n\n\t\tdisconnect: async (\n\t\t\tactor: AnyActorInstance,\n\t\t\tconn: AnyConn,\n\t\t\t_state: GenericWebSocketDriverState,\n\t\t\treason?: string,\n\t\t) => {\n\t\t\tconst ws = globalState.websockets.get(conn.id);\n\t\t\tif (!ws) {\n\t\t\t\tactor.rLog.warn({\n\t\t\t\t\tmsg: \"missing ws for disconnect\",\n\t\t\t\t\tactorId: actor.id,\n\t\t\t\t\tconnId: conn.id,\n\t\t\t\t\ttotalCount: globalState.websockets.size,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst raw = ws.raw as WebSocket;\n\t\t\tif (!raw) {\n\t\t\t\tactor.rLog.warn({ msg: \"ws.raw does not exist\" });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Create promise to wait for socket to close gracefully\n\t\t\tconst { promise, resolve } = Promise.withResolvers<void>();\n\t\t\traw.addEventListener(\"close\", () => resolve());\n\n\t\t\t// Close socket\n\t\t\tws.close(1000, reason);\n\n\t\t\tawait promise;\n\t\t},\n\n\t\tgetConnectionReadyState: (\n\t\t\tactor: AnyActorInstance,\n\t\t\tconn: AnyConn,\n\t\t): ConnectionReadyState | undefined => {\n\t\t\tconst ws = globalState.websockets.get(conn.id);\n\t\t\tif (!ws) {\n\t\t\t\tactor.rLog.warn({\n\t\t\t\t\tmsg: \"missing ws for getConnectionReadyState\",\n\t\t\t\t\tconnId: conn.id,\n\t\t\t\t});\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tconst raw = ws.raw as WebSocket;\n\n\t\t\treturn raw.readyState as ConnectionReadyState;\n\t\t},\n\t};\n}\n\n// MARK: SSE\nexport interface GenericSseDriverState {\n\tencoding: Encoding;\n}\n\nexport function createGenericSseDriver(\n\tglobalState: GenericConnGlobalState,\n): ConnDriver<GenericSseDriverState> {\n\treturn {\n\t\tsendMessage: (\n\t\t\tactor: AnyActorInstance,\n\t\t\tconn: AnyConn,\n\t\t\tstate: GenericSseDriverState,\n\t\t\tmessage: CachedSerializer<protocol.ToClient>,\n\t\t) => {\n\t\t\tconst stream = globalState.sseStreams.get(conn.id);\n\t\t\tif (!stream) {\n\t\t\t\tactor.rLog.warn({\n\t\t\t\t\tmsg: \"missing sse stream for sendMessage\",\n\t\t\t\t\tconnId: conn.id,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tstream.writeSSE({\n\t\t\t\tdata: encodeDataToString(message.serialize(state.encoding)),\n\t\t\t});\n\t\t},\n\n\t\tdisconnect: async (\n\t\t\tactor: AnyActorInstance,\n\t\t\tconn: AnyConn,\n\t\t\t_state: GenericSseDriverState,\n\t\t\t_reason?: string,\n\t\t) => {\n\t\t\tconst stream = globalState.sseStreams.get(conn.id);\n\t\t\tif (!stream) {\n\t\t\t\tactor.rLog.warn({\n\t\t\t\t\tmsg: \"missing sse stream for disconnect\",\n\t\t\t\t\tconnId: conn.id,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tstream.close();\n\t\t},\n\n\t\tgetConnectionReadyState: (\n\t\t\tactor: AnyActorInstance,\n\t\t\tconn: AnyConn,\n\t\t): ConnectionReadyState | undefined => {\n\t\t\tconst stream = globalState.sseStreams.get(conn.id);\n\t\t\tif (!stream) {\n\t\t\t\tactor.rLog.warn({\n\t\t\t\t\tmsg: \"missing sse stream for getConnectionReadyState\",\n\t\t\t\t\tconnId: conn.id,\n\t\t\t\t});\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tif (stream.aborted || stream.closed) {\n\t\t\t\treturn ConnectionReadyState.CLOSED;\n\t\t\t}\n\n\t\t\treturn ConnectionReadyState.OPEN;\n\t\t},\n\t};\n}\n\n// MARK: HTTP\nexport type GenericHttpDriverState = Record<never, never>;\n\nexport function createGenericHttpDriver(): ConnDriver<GenericHttpDriverState> {\n\treturn {\n\t\tgetConnectionReadyState(_actor, _conn) {\n\t\t\t// TODO: This might not be the correct logic\n\t\t\treturn ConnectionReadyState.OPEN;\n\t\t},\n\t\tdisconnect: async () => {\n\t\t\t// Noop\n\t\t},\n\t};\n}\n","import { Hono, type Context as HonoContext } from \"hono\";\nimport { cors } from \"hono/cors\";\nimport invariant from \"invariant\";\nimport { EncodingSchema } from \"@/actor/protocol/serde\";\nimport {\n\ttype ActionOpts,\n\ttype ActionOutput,\n\ttype ConnectSseOpts,\n\ttype ConnectSseOutput,\n\ttype ConnectWebSocketOpts,\n\ttype ConnectWebSocketOutput,\n\ttype ConnsMessageOpts,\n\tHEADER_AUTH_DATA,\n\tHEADER_CONN_ID,\n\tHEADER_CONN_PARAMS,\n\tHEADER_CONN_TOKEN,\n\tHEADER_ENCODING,\n\thandleAction,\n\thandleConnectionMessage,\n\thandleRawWebSocketHandler,\n\thandleSseConnect,\n\thandleWebSocketConnect,\n} from \"@/actor/router-endpoints\";\nimport {\n\thandleRouteError,\n\thandleRouteNotFound,\n\tloggerMiddleware,\n} from \"@/common/router\";\nimport { noopNext } from \"@/common/utils\";\nimport {\n\ttype ActorInspectorRouterEnv,\n\tcreateActorInspectorRouter,\n} from \"@/inspector/actor\";\nimport { secureInspector } from \"@/inspector/utils\";\nimport type { RunConfig } from \"@/registry/run-config\";\nimport type { ActorDriver } from \"./driver\";\nimport { InternalError } from \"./errors\";\nimport { loggerWithoutContext } from \"./log\";\n\nexport const PATH_CONNECT_WEBSOCKET = \"/connect/websocket\";\nexport const PATH_RAW_WEBSOCKET_PREFIX = \"/raw/websocket/\";\n\nexport type {\n\tConnectWebSocketOpts,\n\tConnectWebSocketOutput,\n\tConnectSseOpts,\n\tConnectSseOutput,\n\tActionOpts,\n\tActionOutput,\n\tConnsMessageOpts,\n};\n\ninterface ActorRouterBindings {\n\tactorId: string;\n}\n\nexport type ActorRouter = Hono<{ Bindings: ActorRouterBindings }>;\n\n/**\n * Creates a router that runs on the partitioned instance.\n */\nexport function createActorRouter(\n\trunConfig: RunConfig,\n\tactorDriver: ActorDriver,\n): ActorRouter {\n\tconst router = new Hono<{ Bindings: ActorRouterBindings }>({ strict: false });\n\n\trouter.use(\"*\", loggerMiddleware(loggerWithoutContext()));\n\n\trouter.get(\"/\", (c) => {\n\t\treturn c.text(\n\t\t\t\"This is an RivetKit actor.\\n\\nLearn more at https://rivetkit.org\",\n\t\t);\n\t});\n\n\trouter.get(\"/health\", (c) => {\n\t\treturn c.text(\"ok\");\n\t});\n\n\trouter.get(PATH_CONNECT_WEBSOCKET, async (c) => {\n\t\tconst upgradeWebSocket = runConfig.getUpgradeWebSocket?.();\n\t\tif (upgradeWebSocket) {\n\t\t\treturn upgradeWebSocket(async (c) => {\n\t\t\t\tconst encodingRaw = c.req.header(HEADER_ENCODING);\n\t\t\t\tconst connParamsRaw = c.req.header(HEADER_CONN_PARAMS);\n\t\t\t\tconst authDataRaw = c.req.header(HEADER_AUTH_DATA);\n\n\t\t\t\tconst encoding = EncodingSchema.parse(encodingRaw);\n\t\t\t\tconst connParams = connParamsRaw\n\t\t\t\t\t? JSON.parse(connParamsRaw)\n\t\t\t\t\t: undefined;\n\t\t\t\tconst authData = authDataRaw ? JSON.parse(authDataRaw) : undefined;\n\n\t\t\t\treturn await handleWebSocketConnect(\n\t\t\t\t\tc.req.raw,\n\t\t\t\t\trunConfig,\n\t\t\t\t\tactorDriver,\n\t\t\t\t\tc.env.actorId,\n\t\t\t\t\tencoding,\n\t\t\t\t\tconnParams,\n\t\t\t\t\tauthData,\n\t\t\t\t);\n\t\t\t})(c, noopNext());\n\t\t} else {\n\t\t\treturn c.text(\n\t\t\t\t\"WebSockets are not enabled for this driver. Use SSE instead.\",\n\t\t\t\t400,\n\t\t\t);\n\t\t}\n\t});\n\n\trouter.get(\"/connect/sse\", async (c) => {\n\t\tconst authDataRaw = c.req.header(HEADER_AUTH_DATA);\n\t\tlet authData: unknown;\n\t\tif (authDataRaw) {\n\t\t\tauthData = JSON.parse(authDataRaw);\n\t\t}\n\n\t\treturn handleSseConnect(c, runConfig, actorDriver, c.env.actorId, authData);\n\t});\n\n\trouter.post(\"/action/:action\", async (c) => {\n\t\tconst actionName = c.req.param(\"action\");\n\n\t\tconst authDataRaw = c.req.header(HEADER_AUTH_DATA);\n\t\tlet authData: unknown;\n\t\tif (authDataRaw) {\n\t\t\tauthData = JSON.parse(authDataRaw);\n\t\t}\n\n\t\treturn handleAction(\n\t\t\tc,\n\t\t\trunConfig,\n\t\t\tactorDriver,\n\t\t\tactionName,\n\t\t\tc.env.actorId,\n\t\t\tauthData,\n\t\t);\n\t});\n\n\trouter.post(\"/connections/message\", async (c) => {\n\t\tconst connId = c.req.header(HEADER_CONN_ID);\n\t\tconst connToken = c.req.header(HEADER_CONN_TOKEN);\n\t\tif (!connId || !connToken) {\n\t\t\tthrow new Error(\"Missing required parameters\");\n\t\t}\n\t\treturn handleConnectionMessage(\n\t\t\tc,\n\t\t\trunConfig,\n\t\t\tactorDriver,\n\t\t\tconnId,\n\t\t\tconnToken,\n\t\t\tc.env.actorId,\n\t\t);\n\t});\n\n\t// Raw HTTP endpoints - /http/*\n\trouter.all(\"/raw/http/*\", async (c) => {\n\t\tconst authDataRaw = c.req.header(HEADER_AUTH_DATA);\n\t\tlet authData: unknown;\n\t\tif (authDataRaw) {\n\t\t\tauthData = JSON.parse(authDataRaw);\n\t\t}\n\n\t\tconst actor = await actorDriver.loadActor(c.env.actorId);\n\n\t\t// TODO: This is not a clean way of doing this since `/http/` might exist mid-path\n\t\t// Strip the /http prefix from the URL to get the original path\n\t\tconst url = new URL(c.req.url);\n\t\tconst originalPath = url.pathname.replace(/^\\/raw\\/http/, \"\") || \"/\";\n\n\t\t// Create a new request with the corrected URL\n\t\tconst correctedUrl = new URL(originalPath + url.search, url.origin);\n\t\tconst correctedRequest = new Request(correctedUrl, {\n\t\t\tmethod: c.req.method,\n\t\t\theaders: c.req.raw.headers,\n\t\t\tbody: c.req.raw.body,\n\t\t\tduplex: \"half\",\n\t\t} as RequestInit);\n\n\t\tloggerWithoutContext().debug({\n\t\t\tmsg: \"rewriting http url\",\n\t\t\tfrom: c.req.url,\n\t\t\tto: correctedRequest.url,\n\t\t});\n\n\t\t// Call the actor's onFetch handler - it will throw appropriate errors\n\t\tconst response = await actor.handleFetch(correctedRequest, {\n\t\t\tauth: authData,\n\t\t});\n\n\t\t// This should never happen now since handleFetch throws errors\n\t\tif (!response) {\n\t\t\tthrow new InternalError(\"handleFetch returned void unexpectedly\");\n\t\t}\n\n\t\treturn response;\n\t});\n\n\t// Raw WebSocket endpoint - /websocket/*\n\trouter.get(`${PATH_RAW_WEBSOCKET_PREFIX}*`, async (c) => {\n\t\tconst upgradeWebSocket = runConfig.getUpgradeWebSocket?.();\n\t\tif (upgradeWebSocket) {\n\t\t\treturn upgradeWebSocket(async (c) => {\n\t\t\t\tconst encodingRaw = c.req.header(HEADER_ENCODING);\n\t\t\t\tconst connParamsRaw = c.req.header(HEADER_CONN_PARAMS);\n\t\t\t\tconst authDataRaw = c.req.header(HEADER_AUTH_DATA);\n\n\t\t\t\tconst encoding = EncodingSchema.parse(encodingRaw);\n\t\t\t\tconst connParams = connParamsRaw\n\t\t\t\t\t? JSON.parse(connParamsRaw)\n\t\t\t\t\t: undefined;\n\t\t\t\tconst authData = authDataRaw ? JSON.parse(authDataRaw) : undefined;\n\n\t\t\t\tconst url = new URL(c.req.url);\n\t\t\t\tconst pathWithQuery = c.req.path + url.search;\n\n\t\t\t\tloggerWithoutContext().debug({\n\t\t\t\t\tmsg: \"actor router raw websocket\",\n\t\t\t\t\tpath: c.req.path,\n\t\t\t\t\turl: c.req.url,\n\t\t\t\t\tsearch: url.search,\n\t\t\t\t\tpathWithQuery,\n\t\t\t\t});\n\n\t\t\t\treturn await handleRawWebSocketHandler(\n\t\t\t\t\tc.req.raw,\n\t\t\t\t\tpathWithQuery,\n\t\t\t\t\tactorDriver,\n\t\t\t\t\tc.env.actorId,\n\t\t\t\t\tauthData,\n\t\t\t\t);\n\t\t\t})(c, noopNext());\n\t\t} else {\n\t\t\treturn c.text(\n\t\t\t\t\"WebSockets are not enabled for this driver. Use SSE instead.\",\n\t\t\t\t400,\n\t\t\t);\n\t\t}\n\t});\n\n\tif (runConfig.inspector.enabled) {\n\t\trouter.route(\n\t\t\t\"/inspect\",\n\t\t\tnew Hono<ActorInspectorRouterEnv & { Bindings: ActorRouterBindings }>()\n\t\t\t\t.use(\n\t\t\t\t\tcors(runConfig.inspector.cors),\n\t\t\t\t\tsecureInspector(runConfig),\n\t\t\t\t\tasync (c, next) => {\n\t\t\t\t\t\tconst inspector = (await actorDriver.loadActor(c.env.actorId))\n\t\t\t\t\t\t\t.inspector;\n\t\t\t\t\t\tinvariant(inspector, \"inspector not supported on this platform\");\n\n\t\t\t\t\t\tc.set(\"inspector\", inspector);\n\t\t\t\t\t\treturn next();\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t\t.route(\"/\", createActorInspectorRouter()),\n\t\t);\n\t}\n\n\trouter.notFound(handleRouteNotFound);\n\trouter.onError(handleRouteError);\n\n\treturn router;\n}\n","import * as cbor from \"cbor-x\";\nimport type { Context as HonoContext, Next } from \"hono\";\nimport type { Encoding } from \"@/actor/protocol/serde\";\nimport {\n\tgetRequestEncoding,\n\tgetRequestExposeInternalError,\n} from \"@/actor/router-endpoints\";\nimport { HttpResponseError } from \"@/schemas/client-protocol/mod\";\nimport { HTTP_RESPONSE_ERROR_VERSIONED } from \"@/schemas/client-protocol/versioned\";\nimport { encodingIsBinary, serializeWithEncoding } from \"@/serde\";\nimport { bufferToArrayBuffer } from \"@/utils\";\nimport { getLogger, type Logger } from \"./log\";\nimport { deconstructError, stringifyError } from \"./utils\";\n\nexport function logger() {\n\treturn getLogger(\"router\");\n}\n\nexport function loggerMiddleware(logger: Logger) {\n\treturn async (c: HonoContext, next: Next) => {\n\t\tconst method = c.req.method;\n\t\tconst path = c.req.path;\n\t\tconst startTime = Date.now();\n\n\t\tawait next();\n\n\t\tconst duration = Date.now() - startTime;\n\t\tlogger.debug({\n\t\t\tmsg: \"http request\",\n\t\t\tmethod,\n\t\t\tpath,\n\t\t\tstatus: c.res.status,\n\t\t\tdt: `${duration}ms`,\n\t\t\treqSize: c.req.header(\"content-length\"),\n\t\t\tresSize: c.res.headers.get(\"content-length\"),\n\t\t\tuserAgent: c.req.header(\"user-agent\"),\n\t\t});\n\t};\n}\n\nexport function handleRouteNotFound(c: HonoContext) {\n\treturn c.text(\"Not Found (RivetKit)\", 404);\n}\n\nexport function handleRouteError(error: unknown, c: HonoContext) {\n\tconst exposeInternalError = getRequestExposeInternalError(c.req.raw);\n\n\tconst { statusCode, group, code, message, metadata } = deconstructError(\n\t\terror,\n\t\tlogger(),\n\t\t{\n\t\t\tmethod: c.req.method,\n\t\t\tpath: c.req.path,\n\t\t},\n\t\texposeInternalError,\n\t);\n\n\tlet encoding: Encoding;\n\ttry {\n\t\tencoding = getRequestEncoding(c.req);\n\t} catch (_) {\n\t\tencoding = \"json\";\n\t}\n\n\tconst output = serializeWithEncoding(\n\t\tencoding,\n\t\t{\n\t\t\tgroup,\n\t\t\tcode,\n\t\t\tmessage,\n\t\t\t// TODO: Cannot serialize non-binary meta since it requires ArrayBuffer atm\n\t\t\tmetadata: encodingIsBinary(encoding)\n\t\t\t\t? bufferToArrayBuffer(cbor.encode(metadata))\n\t\t\t\t: null,\n\t\t},\n\t\tHTTP_RESPONSE_ERROR_VERSIONED,\n\t);\n\n\treturn c.body(output, { status: statusCode });\n}\n","import crypto from \"node:crypto\";\nimport { createMiddleware } from \"hono/factory\";\nimport type { RunConfig } from \"@/mod\";\nimport type { RunConfigInput } from \"@/registry/run-config\";\nimport { inspectorLogger } from \"./log\";\n\nexport function compareSecrets(providedSecret: string, validSecret: string) {\n\t// Early length check to avoid unnecessary processing\n\tif (providedSecret.length !== validSecret.length) {\n\t\treturn false;\n\t}\n\n\tconst encoder = new TextEncoder();\n\n\tconst a = encoder.encode(providedSecret);\n\tconst b = encoder.encode(validSecret);\n\n\tif (a.byteLength !== b.byteLength) {\n\t\treturn false;\n\t}\n\n\t// Perform timing-safe comparison\n\tif (!crypto.timingSafeEqual(a, b)) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nexport const secureInspector = (runConfig: RunConfig) =>\n\tcreateMiddleware(async (c, next) => {\n\t\tif (!runConfig.inspector.enabled) {\n\t\t\treturn c.text(\"Inspector is not enabled\", 503);\n\t\t}\n\n\t\tconst userToken = c.req.header(\"Authorization\")?.replace(\"Bearer \", \"\");\n\t\tif (!userToken) {\n\t\t\treturn c.text(\"Unauthorized\", 401);\n\t\t}\n\n\t\tconst inspectorToken = runConfig.inspector.token?.();\n\t\tif (!inspectorToken) {\n\t\t\treturn c.text(\"Unauthorized\", 401);\n\t\t}\n\n\t\tconst isValid = compareSecrets(userToken, inspectorToken);\n\n\t\tif (!isValid) {\n\t\t\treturn c.text(\"Unauthorized\", 401);\n\t\t}\n\t\tawait next();\n\t});\n\nexport function getInspectorUrl(runConfig: RunConfigInput | undefined) {\n\tif (!runConfig?.inspector?.enabled) {\n\t\treturn \"disabled\";\n\t}\n\n\tconst accessToken = runConfig?.inspector?.token?.();\n\n\tif (!accessToken) {\n\t\tinspectorLogger().warn(\n\t\t\t\"Inspector Token is not set, but Inspector is enabled. Please set it in the run configuration `inspector.token` or via `RIVETKIT_INSPECTOR_TOKEN` environment variable. Inspector will not be accessible.\",\n\t\t);\n\t\treturn \"disabled\";\n\t}\n\n\tconst url = new URL(\"https://inspect.rivet.dev\");\n\n\turl.searchParams.set(\"t\", accessToken);\n\n\tif (runConfig?.inspector?.defaultEndpoint) {\n\t\turl.searchParams.set(\"u\", runConfig.inspector.defaultEndpoint);\n\t}\n\n\treturn url.href;\n}\n","import { getLogger } from \"@/common/log\";\n\nexport function inspectorLogger() {\n\treturn getLogger(\"inspector\");\n}\n","import {\n\ttype Actions,\n\ttype ActorConfig,\n\ttype ActorConfigInput,\n\tActorConfigSchema,\n\tActorTypes,\n} from \"./config\";\nimport type { AnyDatabaseProvider } from \"./database\";\nimport { ActorDefinition } from \"./definition\";\n\nexport function actor<\n\tTState,\n\tTConnParams,\n\tTConnState,\n\tTVars,\n\tTInput,\n\tTDatabase extends AnyDatabaseProvider,\n\tTActions extends Actions<\n\t\tTState,\n\t\tTConnParams,\n\t\tTConnState,\n\t\tTVars,\n\t\tTInput,\n\t\tTDatabase\n\t>,\n>(\n\tinput: ActorConfigInput<\n\t\tTState,\n\t\tTConnParams,\n\t\tTConnState,\n\t\tTVars,\n\t\tTInput,\n\t\tTDatabase,\n\t\tTActions\n\t>,\n): ActorDefinition<\n\tTState,\n\tTConnParams,\n\tTConnState,\n\tTVars,\n\tTInput,\n\tTDatabase,\n\tTActions\n> {\n\tconst config = ActorConfigSchema.parse(input) as ActorConfig<\n\t\tTState,\n\t\tTConnParams,\n\t\tTConnState,\n\t\tTVars,\n\t\tTInput,\n\t\tTDatabase\n\t>;\n\treturn new ActorDefinition(config);\n}\nexport type { Encoding } from \"@/actor/protocol/serde\";\nexport type {\n\tUniversalErrorEvent,\n\tUniversalEvent,\n\tUniversalEventSource,\n\tUniversalMessageEvent,\n} from \"@/common/eventsource-interface\";\nexport type { UpgradeWebSocketArgs } from \"@/common/inline-websocket-adapter2\";\nexport type {\n\tRivetCloseEvent,\n\tRivetEvent,\n\tRivetMessageEvent,\n\tUniversalWebSocket,\n} from \"@/common/websocket-interface\";\nexport type { ActorKey } from \"@/manager/protocol/query\";\nexport type { ActionContext } from \"./action\";\nexport type * from \"./config\";\nexport type {\n\tConn,\n\tConnectionDriver,\n\tConnectionStatus,\n\tgenerateConnId,\n\tgenerateConnToken,\n} from \"./connection\";\nexport {\n\tCONNECTION_DRIVER_HTTP,\n\tCONNECTION_DRIVER_SSE,\n\tCONNECTION_DRIVER_WEBSOCKET,\n} from \"./connection\";\nexport type { ActorContext } from \"./context\";\nexport type {\n\tActionContextOf,\n\tActorContextOf,\n\tActorDefinition,\n\tAnyActorDefinition,\n} from \"./definition\";\nexport { lookupInRegistry } from \"./definition\";\nexport { UserError, type UserErrorOptions } from \"./errors\";\nexport {\n\tcreateGenericConnDrivers,\n\tGenericConnGlobalState,\n} from \"./generic-conn-driver\";\nexport type { AnyActorInstance } from \"./instance\";\nexport {\n\ttype ActorRouter,\n\tcreateActorRouter,\n\tPATH_CONNECT_WEBSOCKET,\n\tPATH_RAW_WEBSOCKET_PREFIX,\n} from \"./router\";\nexport {\n\tALLOWED_PUBLIC_HEADERS,\n\thandleRawWebSocketHandler,\n\thandleWebSocketConnect,\n} from \"./router-endpoints\";\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 { importEventSource } from \"@/common/eventsource\";\nimport type {\n\tUniversalErrorEvent,\n\tUniversalEventSource,\n\tUniversalMessageEvent,\n} from \"@/common/eventsource-interface\";\nimport { assertUnreachable, stringifyError } from \"@/common/utils\";\nimport {\n\tHEADER_CONN_ID,\n\tHEADER_CONN_PARAMS,\n\tHEADER_CONN_TOKEN,\n\tHEADER_ENCODING,\n\ttype ManagerDriver,\n} from \"@/driver-helpers/mod\";\nimport type { ActorQuery } from \"@/manager/protocol/query\";\nimport { PATH_CONNECT_WEBSOCKET, type UniversalWebSocket } from \"@/mod\";\nimport type * as protocol from \"@/schemas/client-protocol/mod\";\nimport {\n\tTO_CLIENT_VERSIONED,\n\tTO_SERVER_VERSIONED,\n} from \"@/schemas/client-protocol/versioned\";\nimport {\n\tdeserializeWithEncoding,\n\tencodingIsBinary,\n\tserializeWithEncoding,\n} from \"@/serde\";\nimport { bufferToArrayBuffer, getEnvUniversal, httpUserAgent } from \"@/utils\";\nimport type { ActorDefinitionActions } from \"./actor-common\";\nimport { queryActor } from \"./actor-query\";\nimport { ACTOR_CONNS_SYMBOL, type ClientRaw, TRANSPORT_SYMBOL } from \"./client\";\nimport * as errors from \"./errors\";\nimport { logger } from \"./log\";\nimport {\n\ttype WebSocketMessage as ConnMessage,\n\tmessageLength,\n\tsendHttpRequest,\n} from \"./utils\";\n\ninterface ActionInFlight {\n\tname: string;\n\tresolve: (response: protocol.ActionResponse) => 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\nexport interface SendHttpMessageOpts {\n\tephemeral: boolean;\n\tsignal?: AbortSignal;\n}\n\nexport type ConnTransport =\n\t| { websocket: UniversalWebSocket }\n\t| { sse: UniversalEventSource };\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/** If attempting to connect. Helpful for knowing if in a retry loop when reconnecting. */\n\t#connecting = false;\n\n\t// These will only be set on SSE driver\n\t#actorId?: string;\n\t#connectionId?: string;\n\t#connectionToken?: string;\n\n\t#transport?: ConnTransport;\n\n\t#messageQueue: protocol.ToServer[] = [];\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\n\t#actionIdCounter = 0;\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?: PromiseWithResolvers<undefined>;\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\n\t\tthis.#keepNodeAliveInterval = setInterval(() => 60_000);\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 } =\n\t\t\tPromise.withResolvers<protocol.ActionResponse>();\n\t\tthis.#actionsInFlight.set(actionId, { name: opts.name, resolve, reject });\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: bufferToArrayBuffer(cbor.encode(opts.args)),\n\t\t\t\t},\n\t\t\t},\n\t\t} satisfies protocol.ToServer);\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 cbor.decode(new Uint8Array(output)) as Response;\n\t}\n\n\t/**\n\t * Do not call this directly.\nenc\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\tasync #connectWithRetry() {\n\t\tthis.#connecting = true;\n\n\t\t// Attempt to reconnect indefinitely\n\t\ttry {\n\t\t\tawait pRetry(this.#connectAndWait.bind(this), {\n\t\t\t\tforever: true,\n\t\t\t\tminTimeout: 250,\n\t\t\t\tmaxTimeout: 30_000,\n\n\t\t\t\tonFailedAttempt: (error) => {\n\t\t\t\t\tlogger().warn({\n\t\t\t\t\t\tmsg: \"failed to reconnect\",\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\n\t\t\t\t// Cancel retry if aborted\n\t\t\t\tsignal: this.#abortController.signal,\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tif ((err as Error).name === \"AbortError\") {\n\t\t\t\t// Ignore abortions\n\t\t\t\tlogger().info({ msg: \"connection retry aborted\" });\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\t// Unknown error\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t}\n\n\t\tthis.#connecting = false;\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 = Promise.withResolvers();\n\n\t\t\t// Connect transport\n\t\t\tif (this.#client[TRANSPORT_SYMBOL] === \"websocket\") {\n\t\t\t\tawait this.#connectWebSocket();\n\t\t\t} else if (this.#client[TRANSPORT_SYMBOL] === \"sse\") {\n\t\t\t\tawait this.#connectSse();\n\t\t\t} else {\n\t\t\t\tassertUnreachable(this.#client[TRANSPORT_SYMBOL]);\n\t\t\t}\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\t\tconst ws = await this.#driver.openWebSocket(\n\t\t\tPATH_CONNECT_WEBSOCKET,\n\t\t\tactorId,\n\t\t\tthis.#encoding,\n\t\t\tthis.#params,\n\t\t);\n\t\tthis.#transport = { websocket: ws };\n\t\tws.addEventListener(\"open\", () => {\n\t\t\tlogger().debug({ msg: \"websocket open\" });\n\t\t});\n\t\tws.addEventListener(\"message\", async (ev) => {\n\t\t\tthis.#handleOnMessage(ev.data);\n\t\t});\n\t\tws.addEventListener(\"close\", (ev) => {\n\t\t\tthis.#handleOnClose(ev);\n\t\t});\n\t\tws.addEventListener(\"error\", (_ev) => {\n\t\t\tthis.#handleOnError();\n\t\t});\n\t}\n\n\tasync #connectSse() {\n\t\tconst EventSource = await importEventSource();\n\n\t\t// Get the actor ID\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\tlogger().debug({ msg: \"found actor for sse connection\", actorId });\n\t\tinvariant(actorId, \"Missing actor ID\");\n\n\t\tlogger().debug({\n\t\t\tmsg: \"opening sse connection\",\n\t\t\tactorId,\n\t\t\tencoding: this.#encoding,\n\t\t});\n\n\t\tconst eventSource = new EventSource(\"http://actor/connect/sse\", {\n\t\t\tfetch: (input, init) => {\n\t\t\t\treturn this.#driver.sendRequest(\n\t\t\t\t\tactorId,\n\t\t\t\t\tnew Request(input, {\n\t\t\t\t\t\t...init,\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t...init?.headers,\n\t\t\t\t\t\t\t\"User-Agent\": httpUserAgent(),\n\t\t\t\t\t\t\t[HEADER_ENCODING]: this.#encoding,\n\t\t\t\t\t\t\t...(this.#params !== undefined\n\t\t\t\t\t\t\t\t? { [HEADER_CONN_PARAMS]: JSON.stringify(this.#params) }\n\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t},\n\t\t}) as UniversalEventSource;\n\n\t\tthis.#transport = { sse: eventSource };\n\n\t\teventSource.addEventListener(\"message\", (ev: UniversalMessageEvent) => {\n\t\t\tthis.#handleOnMessage(ev.data);\n\t\t});\n\n\t\teventSource.addEventListener(\"error\", (ev: UniversalErrorEvent) => {\n\t\t\tthis.#handleOnError();\n\t\t});\n\t}\n\n\t/** Called by the onopen event from drivers. */\n\t#handleOnOpen() {\n\t\tlogger().debug({\n\t\t\tmsg: \"socket open\",\n\t\t\tmessageQueueLength: this.#messageQueue.length,\n\t\t});\n\n\t\t// Resolve open promise\n\t\tif (this.#onOpenPromise) {\n\t\t\tthis.#onOpenPromise.resolve(undefined);\n\t\t} else {\n\t\t\tlogger().warn({ msg: \"#onOpenPromise is undefined\" });\n\t\t}\n\n\t\t// Resubscribe to all active events\n\t\tfor (const eventName of this.#eventSubscriptions.keys()) {\n\t\t\tthis.#sendSubscription(eventName, true);\n\t\t}\n\n\t\t// Flush queue\n\t\t//\n\t\t// If the message fails to send, the message will be re-queued\n\t\tconst queue = this.#messageQueue;\n\t\tthis.#messageQueue = [];\n\t\tfor (const msg of queue) {\n\t\t\tthis.#sendMessage(msg);\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\tgetEnvUniversal(\"_RIVETKIT_LOG_MESSAGE\")\n\t\t\t\t? {\n\t\t\t\t\t\tmsg: \"parsed message\",\n\t\t\t\t\t\tmessage: jsonStringifyCompat(response).substring(0, 100) + \"...\",\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// This is only called for SSE\n\t\t\tthis.#actorId = response.body.val.actorId;\n\t\t\tthis.#connectionId = response.body.val.connectionId;\n\t\t\tthis.#connectionToken = response.body.val.connectionToken;\n\t\t\tlogger().trace({\n\t\t\t\tmsg: \"received init message\",\n\t\t\t\tactorId: this.#actorId,\n\t\t\t\tconnectionId: this.#connectionId,\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 } = response.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(new errors.ActorError(group, code, message, metadata));\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// Create a connection error\n\t\t\t\tconst actorError = 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\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(actorError);\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(actorError);\n\t\t\t\t\tthis.#actionsInFlight.delete(id);\n\t\t\t\t}\n\n\t\t\t\t// Dispatch to error handler if registered\n\t\t\t\tthis.#dispatchActorError(actorError);\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().trace({\n\t\t\t\tmsg: \"received action response\",\n\t\t\t\tactionId,\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({ msg: \"received event\", name: response.body.val.name });\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\t#handleOnClose(event: Event | CloseEvent) {\n\t\t// TODO: Handle queue\n\t\t// TODO: Reconnect with backoff\n\n\t\t// Reject open promise\n\t\tif (this.#onOpenPromise) {\n\t\t\tthis.#onOpenPromise.reject(new Error(\"Closed\"));\n\t\t}\n\n\t\t// We can't use `event instanceof CloseEvent` because it's not defined in NodeJS\n\t\t//\n\t\t// These properties will be undefined\n\t\tconst closeEvent = event as CloseEvent;\n\t\tif (closeEvent.wasClean) {\n\t\t\tlogger().info({\n\t\t\t\tmsg: \"socket closed\",\n\t\t\t\tcode: closeEvent.code,\n\t\t\t\treason: closeEvent.reason,\n\t\t\t\twasClean: closeEvent.wasClean,\n\t\t\t});\n\t\t} else {\n\t\t\tlogger().warn({\n\t\t\t\tmsg: \"socket closed\",\n\t\t\t\tcode: closeEvent.code,\n\t\t\t\treason: closeEvent.reason,\n\t\t\t\twasClean: closeEvent.wasClean,\n\t\t\t});\n\t\t}\n\n\t\tthis.#transport = undefined;\n\n\t\t// Automatically reconnect. Skip if already attempting to connect.\n\t\tif (!this.#disposed && !this.#connecting) {\n\t\t\t// TODO: Fetch actor to check if it's destroyed\n\t\t\t// TODO: Add backoff for reconnect\n\t\t\t// TODO: Add a way of preserving connection ID for connection state\n\n\t\t\t// Attempt to connect again\n\t\t\tthis.#connectWithRetry();\n\t\t}\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\tthrow new errors.InternalError(`No in flight response for ${id}`);\n\t\t}\n\t\tthis.#actionsInFlight.delete(id);\n\t\treturn inFlight;\n\t}\n\n\t#dispatchEvent(event: protocol.Event) {\n\t\tconst { name, args: argsRaw } = event;\n\t\tconst args = cbor.decode(new Uint8Array(argsRaw));\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);\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#sendMessage(message: protocol.ToServer, opts?: SendHttpMessageOpts) {\n\t\tif (this.#disposed) {\n\t\t\tthrow new errors.ActorConnDisposed();\n\t\t}\n\n\t\tlet queueMessage = false;\n\t\tif (!this.#transport) {\n\t\t\t// No transport connected yet\n\t\t\tqueueMessage = true;\n\t\t} else if (\"websocket\" in this.#transport) {\n\t\t\tif (this.#transport.websocket.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);\n\t\t\t\t\tthis.#transport.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});\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\tqueueMessage = true;\n\t\t\t}\n\t\t} else if (\"sse\" in this.#transport) {\n\t\t\tif (this.#transport.sse.readyState === 1) {\n\t\t\t\t// Spawn in background since #sendMessage cannot be async\n\t\t\t\tthis.#sendHttpMessage(message, opts);\n\t\t\t} else {\n\t\t\t\tqueueMessage = true;\n\t\t\t}\n\t\t} else {\n\t\t\tassertUnreachable(this.#transport);\n\t\t}\n\n\t\tif (!opts?.ephemeral && queueMessage) {\n\t\t\tthis.#messageQueue.push(message);\n\t\t\tlogger().debug({ msg: \"queued connection message\" });\n\t\t}\n\t}\n\n\tasync #sendHttpMessage(\n\t\tmessage: protocol.ToServer,\n\t\topts?: SendHttpMessageOpts,\n\t) {\n\t\ttry {\n\t\t\tif (!this.#actorId || !this.#connectionId || !this.#connectionToken)\n\t\t\t\tthrow new errors.InternalError(\"Missing connection ID or token.\");\n\n\t\t\tlogger().trace(\n\t\t\t\tgetEnvUniversal(\"_RIVETKIT_LOG_MESSAGE\")\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tmsg: \"sent http message\",\n\t\t\t\t\t\t\tmessage: `${jsonStringifyCompat(message).substring(0, 100)}...`,\n\t\t\t\t\t\t}\n\t\t\t\t\t: { msg: \"sent http message\" },\n\t\t\t);\n\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"sending http message\",\n\t\t\t\tactorId: this.#actorId,\n\t\t\t\tconnectionId: this.#connectionId,\n\t\t\t});\n\n\t\t\t// Send an HTTP request to the connections endpoint\n\t\t\tawait sendHttpRequest({\n\t\t\t\turl: \"http://actor/connections/message\",\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[HEADER_CONN_ID]: this.#connectionId,\n\t\t\t\t\t[HEADER_CONN_TOKEN]: this.#connectionToken,\n\t\t\t\t},\n\t\t\t\tbody: message,\n\t\t\t\tencoding: this.#encoding,\n\t\t\t\tskipParseResponse: true,\n\t\t\t\tcustomFetch: this.#driver.sendRequest.bind(this.#driver, this.#actorId),\n\t\t\t\trequestVersionedDataHandler: TO_SERVER_VERSIONED,\n\t\t\t\tresponseVersionedDataHandler: TO_CLIENT_VERSIONED,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\t// TODO: This will not automatically trigger a re-broadcast of HTTP events since SSE is separate from the HTTP action\n\n\t\t\tlogger().warn({ msg: \"failed to send message, added to queue\", error });\n\n\t\t\t// Assuming the socket is disconnected and will be reconnected soon\n\t\t\t//\n\t\t\t// Will attempt to resend soon\n\t\t\tif (!opts?.ephemeral) {\n\t\t\t\tthis.#messageQueue.unshift(message);\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #parseMessage(data: ConnMessage): Promise<protocol.ToClient> {\n\t\tinvariant(this.#transport, \"transport must be defined\");\n\n\t\t// Decode base64 since SSE sends raw strings\n\t\tif (encodingIsBinary(this.#encoding) && \"sse\" in this.#transport) {\n\t\t\tif (typeof data === \"string\") {\n\t\t\t\tconst binaryString = atob(data);\n\t\t\t\tdata = new Uint8Array(\n\t\t\t\t\t[...binaryString].map((char) => char.charCodeAt(0)),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthrow new errors.InternalError(\n\t\t\t\t\t`Expected data to be a string for SSE, got ${data}.`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst buffer = await inputDataToBuffer(data);\n\n\t\treturn deserializeWithEncoding(this.#encoding, buffer, TO_CLIENT_VERSIONED);\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// Clear interval so NodeJS process can exit\n\t\tclearInterval(this.#keepNodeAliveInterval);\n\n\t\t// Abort\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// Disconnect transport cleanly\n\t\tif (!this.#transport) {\n\t\t\t// Nothing to do\n\t\t} else if (\"websocket\" in this.#transport) {\n\t\t\tconst ws = this.#transport.websocket;\n\t\t\t// Check if WebSocket is already closed or closing\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\tlogger().debug({ msg: \"ws already closed or closing\" });\n\t\t\t} else {\n\t\t\t\tconst { promise, resolve } = Promise.withResolvers();\n\t\t\t\tws.addEventListener(\"close\", () => {\n\t\t\t\t\tlogger().debug({ msg: \"ws closed\" });\n\t\t\t\t\tresolve(undefined);\n\t\t\t\t});\n\t\t\t\tws.close();\n\t\t\t\tawait promise;\n\t\t\t}\n\t\t} else if (\"sse\" in this.#transport) {\n\t\t\tthis.#transport.sse.close();\n\t\t} else {\n\t\t\tassertUnreachable(this.#transport);\n\t\t}\n\t\tthis.#transport = 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 { EventSource } from \"eventsource\";\nimport { logger } from \"@/client/log\";\n\n// Global singleton promise that will be reused for subsequent calls\nlet eventSourcePromise: Promise<typeof EventSource> | null = null;\n\n/**\n * Import `eventsource` from the custom `eventsource` library. We need a custom implemnetation since we need to attach our own custom headers to the request.\n **/\nexport async function importEventSource(): Promise<typeof EventSource> {\n\t// Return existing promise if we already started loading\n\tif (eventSourcePromise !== null) {\n\t\treturn eventSourcePromise;\n\t}\n\n\t// Create and store the promise\n\teventSourcePromise = (async () => {\n\t\tlet _EventSource: typeof EventSource;\n\n\t\t// Node.js environment\n\t\ttry {\n\t\t\tconst es = await import(\"eventsource\");\n\t\t\t_EventSource = es.EventSource;\n\t\t\tlogger().debug(\"using eventsource from npm\");\n\t\t} catch (err) {\n\t\t\t// EventSource not available\n\t\t\t_EventSource = class MockEventSource {\n\t\t\t\tconstructor() {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t'EventSource support requires installing the \"eventsource\" peer dependency.',\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} as unknown as typeof EventSource;\n\t\t\tlogger().debug(\"using mock eventsource\");\n\t\t}\n\n\t\treturn _EventSource;\n\t})();\n\n\treturn eventSourcePromise;\n}\n\n//export async function importEventSource(): Promise<typeof EventSource> {\n//\t// Return existing promise if we already started loading\n//\tif (eventSourcePromise !== null) {\n//\t\treturn eventSourcePromise;\n//\t}\n//\n//\t// Create and store the promise\n//\teventSourcePromise = (async () => {\n//\t\tlet _EventSource: typeof EventSource;\n//\n//\t\tif (typeof EventSource !== \"undefined\") {\n//\t\t\t// Browser environment\n//\t\t\t_EventSource = EventSource;\n//\t\t\tlogger().debug(\"using native eventsource\");\n//\t\t} else {\n//\t\t\t// Node.js environment\n//\t\t\ttry {\n//\t\t\t\tconst es = await import(\"eventsource\");\n//\t\t\t\t_EventSource = es.EventSource;\n//\t\t\t\tlogger().debug(\"using eventsource from npm\");\n//\t\t\t} catch (err) {\n//\t\t\t\t// EventSource not available\n//\t\t\t\t_EventSource = class MockEventSource {\n//\t\t\t\t\tconstructor() {\n//\t\t\t\t\t\tthrow new Error(\n//\t\t\t\t\t\t\t'EventSource support requires installing the \"eventsource\" peer dependency.',\n//\t\t\t\t\t\t);\n//\t\t\t\t\t}\n//\t\t\t\t} as unknown as typeof EventSource;\n//\t\t\t\tlogger().debug(\"using mock eventsource\");\n//\t\t\t}\n//\t\t}\n//\n//\t\treturn _EventSource;\n//\t})();\n//\n//\treturn eventSourcePromise;\n//}\n","import type { Context as HonoContext } from \"hono\";\nimport * as errors from \"@/actor/errors\";\nimport type { ManagerDriver } from \"@/driver-helpers/mod\";\nimport type { ActorQuery } from \"@/manager/protocol/query\";\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","import { MAX_CONN_PARAMS_SIZE } from \"@/common//network\";\n\nexport 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","import * as cbor from \"cbor-x\";\nimport invariant from \"invariant\";\nimport { assertUnreachable } from \"@/common/utils\";\nimport type { VersionedDataHandler } from \"@/common/versioned-data\";\nimport type { Encoding } from \"@/mod\";\nimport type { HttpResponseError } from \"@/schemas/client-protocol/mod\";\nimport { HTTP_RESPONSE_ERROR_VERSIONED } from \"@/schemas/client-protocol/versioned\";\nimport {\n\tcontentTypeForEncoding,\n\tdeserializeWithEncoding,\n\tserializeWithEncoding,\n} from \"@/serde\";\nimport { httpUserAgent } from \"@/utils\";\nimport { ActorError, HttpRequestError } from \"./errors\";\nimport { logger } from \"./log\";\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<RequestBody, ResponseBody> {\n\tmethod: string;\n\turl: string;\n\theaders: Record<string, string>;\n\tbody?: RequestBody;\n\tencoding: Encoding;\n\tskipParseResponse?: boolean;\n\tsignal?: AbortSignal;\n\tcustomFetch?: (req: Request) => Promise<Response>;\n\trequestVersionedDataHandler: VersionedDataHandler<RequestBody> | undefined;\n\tresponseVersionedDataHandler: VersionedDataHandler<ResponseBody> | undefined;\n}\n\nexport async function sendHttpRequest<\n\tRequestBody = unknown,\n\tResponseBody = unknown,\n>(opts: HttpRequestOpts<RequestBody, ResponseBody>): Promise<ResponseBody> {\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<RequestBody>(\n\t\t\topts.encoding,\n\t\t\topts.body,\n\t\t\topts.requestVersionedDataHandler,\n\t\t);\n\t}\n\n\t// Send request\n\tlet response: Response;\n\ttry {\n\t\t// Make the HTTP request\n\t\tresponse = await (opts.customFetch ?? fetch)(\n\t\t\tnew 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\t// Attempt to parse structured data\n\t\tconst bufferResponse = await response.arrayBuffer();\n\t\tlet responseData: HttpResponseError;\n\t\ttry {\n\t\t\tresponseData = deserializeWithEncoding(\n\t\t\t\topts.encoding,\n\t\t\t\tnew Uint8Array(bufferResponse),\n\t\t\t\tHTTP_RESPONSE_ERROR_VERSIONED,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\t//logger().warn(\"failed to cleanly parse error, this is likely because a non-structured response is being served\", {\n\t\t\t//\terror: stringifyError(error),\n\t\t\t//});\n\n\t\t\t// Error is not structured\n\t\t\tconst textResponse = new TextDecoder(\"utf-8\", { fatal: false }).decode(\n\t\t\t\tbufferResponse,\n\t\t\t);\n\t\t\tthrow new HttpRequestError(\n\t\t\t\t`${response.statusText} (${response.status}):\\n${textResponse}`,\n\t\t\t);\n\t\t}\n\n\t\t// Throw structured error\n\t\tthrow new ActorError(\n\t\t\tresponseData.group,\n\t\t\tresponseData.code,\n\t\t\tresponseData.message,\n\t\t\tresponseData.metadata\n\t\t\t\t? cbor.decode(new Uint8Array(responseData.metadata))\n\t\t\t\t: undefined,\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 ResponseBody;\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(\n\t\t\topts.encoding,\n\t\t\tbuffer,\n\t\t\topts.responseVersionedDataHandler,\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","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 { importWebSocket } from \"@/common/websocket\";\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\tHTTP_ACTION_REQUEST_VERSIONED,\n\tHTTP_ACTION_RESPONSE_VERSIONED,\n} from \"@/schemas/client-protocol/versioned\";\nimport { bufferToArrayBuffer } from \"@/utils\";\nimport type { ActorDefinitionActions } from \"./actor-common\";\nimport { type ActorConn, ActorConnRaw } from \"./actor-conn\";\nimport { queryActor } from \"./actor-query\";\nimport { type ClientRaw, CREATE_ACTOR_CONN_PROXY } from \"./client\";\nimport { ActorError } from \"./errors\";\nimport { logger } from \"./log\";\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\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}\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// return await this.#driver.action<Args, Response>(\n\t\t// \tundefined,\n\t\t// \tthis.#actorQuery,\n\t\t// \tthis.#encodingKind,\n\t\t// \tthis.#params,\n\t\t// \topts.name,\n\t\t// \topts.args,\n\t\t// \t{ signal: opts.signal },\n\t\t// );\n\t\ttry {\n\t\t\t// Get the actor 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\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,\n\t\t\t\tprotocol.HttpActionResponse\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: {\n\t\t\t\t\targs: bufferToArrayBuffer(cbor.encode(opts.args)),\n\t\t\t\t} satisfies protocol.HttpActionRequest,\n\t\t\t\tencoding: this.#encoding,\n\t\t\t\tcustomFetch: this.#driver.sendRequest.bind(this.#driver, actorId),\n\t\t\t\tsignal: opts?.signal,\n\t\t\t\trequestVersionedDataHandler: HTTP_ACTION_REQUEST_VERSIONED,\n\t\t\t\tresponseVersionedDataHandler: HTTP_ACTION_RESPONSE_VERSIONED,\n\t\t\t});\n\n\t\t\treturn cbor.decode(new Uint8Array(responseData.output));\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\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 * Makes a raw HTTP request to the actor.\n\t *\n\t * @param input - The URL, path, or Request object\n\t * @param init - Standard fetch RequestInit options\n\t * @returns Promise<Response> - The raw HTTP response\n\t */\n\tasync fetch(\n\t\tinput: string | URL | Request,\n\t\tinit?: RequestInit,\n\t): Promise<Response> {\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 * Creates a raw WebSocket connection to the actor.\n\t *\n\t * @param path - The path for the WebSocket connection (e.g., \"stream\")\n\t * @param protocols - Optional WebSocket subprotocols\n\t * @returns WebSocket - A raw WebSocket connection\n\t */\n\tasync websocket(\n\t\tpath?: string,\n\t\tprotocols?: string | string[],\n\t): Promise<WebSocket> {\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\t * @returns {Promise<string>} - A promise that resolves to the actor's ID\n\t */\n\tasync resolve({ signal }: { signal?: AbortSignal } = {}): Promise<string> {\n\t\tif (\n\t\t\t\"getForKey\" in this.#actorQuery ||\n\t\t\t\"getOrCreateForKey\" in this.#actorQuery\n\t\t) {\n\t\t\t// TODO:\n\t\t\tlet name: string;\n\t\t\tif (\"getForKey\" in this.#actorQuery) {\n\t\t\t\tname = this.#actorQuery.getForKey.name;\n\t\t\t} else if (\"getOrCreateForKey\" in this.#actorQuery) {\n\t\t\t\tname = this.#actorQuery.getOrCreateForKey.name;\n\t\t\t} else {\n\t\t\t\tassertUnreachable(this.#actorQuery);\n\t\t\t}\n\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\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_RAW_WEBSOCKET_PREFIX } from \"@/actor/router\";\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\tfor (const [key, value] of initHeaders) {\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/raw/http/${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_RAW_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 { Transport } from \"@/actor/protocol/old\";\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 \"@/mod\";\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\");\nexport const TRANSPORT_SYMBOL = Symbol(\"transport\");\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\t[TRANSPORT_SYMBOL]: Transport;\n\n\t/**\n\t * Creates an instance of Client.\n\t *\n\t * @param {string} managerEndpoint - The manager endpoint. See {@link https://rivet.dev/docs/setup|Initial Setup} for instructions on getting the manager endpoint.\n\t * @param {ClientConfig} [opts] - Options for configuring the client.\n\t * @see {@link https://rivet.dev/docs/setup|Initial Setup}\n\t */\n\tpublic constructor(driver: ManagerDriver, opts?: ClientConfig) {\n\t\tthis.#driver = driver;\n\n\t\tthis.#encodingKind = opts?.encoding ?? \"bare\";\n\t\tthis[TRANSPORT_SYMBOL] = opts?.transport ?? \"websocket\";\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(undefined, createQuery, this.#driver);\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?: ClientConfig,\n): Client<A> {\n\tconst client = new ClientRaw(driver, config);\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<ExtractActorsFromRegistry<A>[typeof prop]> => {\n\t\t\t\t\t\treturn target.get<ExtractActorsFromRegistry<A>[typeof prop]>(\n\t\t\t\t\t\t\tprop,\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t\topts,\n\t\t\t\t\t\t);\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<ExtractActorsFromRegistry<A>[typeof prop]> => {\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<ExtractActorsFromRegistry<A>[typeof prop]> => {\n\t\t\t\t\t\treturn target.getForId<ExtractActorsFromRegistry<A>[typeof prop]>(\n\t\t\t\t\t\t\tprop,\n\t\t\t\t\t\t\tactorId,\n\t\t\t\t\t\t\topts,\n\t\t\t\t\t\t);\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, 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// 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[]) => target.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\") {\n\t\t\t\treturn true;\n\t\t\t}\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(target: ActorHandleRaw, prop: string | symbol) {\n\t\t\tconst targetDescriptor = Reflect.getOwnPropertyDescriptor(target, prop);\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[]) => target.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 { WSContext } from \"hono/ws\";\nimport type {\n\tRivetCloseEvent,\n\tRivetEvent,\n\tRivetMessageEvent,\n\tUniversalWebSocket,\n} from \"@/common/websocket-interface\";\nimport { getLogger } from \"./log\";\n\nexport function logger() {\n\treturn getLogger(\"fake-event-source2\");\n}\n\n// TODO: Merge with ConnectWebSocketOutput interface\nexport interface UpgradeWebSocketArgs {\n\tonOpen: (event: any, ws: WSContext) => void;\n\tonMessage: (event: any, ws: WSContext) => void;\n\tonClose: (event: any, ws: WSContext) => void;\n\tonError: (error: any, ws: WSContext) => void;\n}\n\n// TODO: Remove `2` suffix\n/**\n * InlineWebSocketAdapter implements a WebSocket-like interface\n * that connects to a UpgradeWebSocketArgs handler\n */\nexport class InlineWebSocketAdapter2 implements UniversalWebSocket {\n\t// WebSocket readyState values\n\treadonly CONNECTING = 0 as const;\n\treadonly OPEN = 1 as const;\n\treadonly CLOSING = 2 as const;\n\treadonly CLOSED = 3 as const;\n\n\t// Private properties\n\t#handler: UpgradeWebSocketArgs;\n\t#wsContext: WSContext;\n\t#readyState: 0 | 1 | 2 | 3 = 0; // Start in CONNECTING state\n\t#queuedMessages: Array<string | ArrayBuffer | Uint8Array> = [];\n\t// Event buffering is needed since events can be fired\n\t// before JavaScript has a chance to add event listeners (e.g. within the same tick)\n\t#bufferedEvents: Array<{\n\t\ttype: string;\n\t\tevent: any;\n\t}> = [];\n\n\t// Event listeners with buffering\n\t#eventListeners: Map<string, ((ev: any) => void)[]> = new Map();\n\n\tconstructor(handler: UpgradeWebSocketArgs) {\n\t\tthis.#handler = handler;\n\n\t\t// Create a fake WSContext to pass to the handler\n\t\tthis.#wsContext = new WSContext({\n\t\t\traw: this,\n\t\t\tsend: (data: string | ArrayBuffer | Uint8Array) => {\n\t\t\t\tlogger().debug({ msg: \"WSContext.send called\" });\n\t\t\t\tthis.#handleMessage(data);\n\t\t\t},\n\t\t\tclose: (code?: number, reason?: string) => {\n\t\t\t\tlogger().debug({ msg: \"WSContext.close called\", code, reason });\n\t\t\t\tthis.#handleClose(code || 1000, reason || \"\");\n\t\t\t},\n\t\t\t// Set readyState to 1 (OPEN) since handlers expect an open connection\n\t\t\treadyState: 1,\n\t\t});\n\n\t\t// Initialize the connection\n\t\tthis.#initialize();\n\t}\n\n\tget readyState(): 0 | 1 | 2 | 3 {\n\t\treturn this.#readyState;\n\t}\n\n\tget binaryType(): \"arraybuffer\" | \"blob\" {\n\t\treturn \"arraybuffer\";\n\t}\n\n\tset binaryType(value: \"arraybuffer\" | \"blob\") {\n\t\t// Ignored for now - always use arraybuffer\n\t}\n\n\tget bufferedAmount(): number {\n\t\treturn 0; // Not tracked in InlineWebSocketAdapter\n\t}\n\n\tget extensions(): string {\n\t\treturn \"\"; // Not available in InlineWebSocketAdapter\n\t}\n\n\tget protocol(): string {\n\t\treturn \"\"; // Not available in InlineWebSocketAdapter\n\t}\n\n\tget url(): string {\n\t\treturn \"\"; // Not available in InlineWebSocketAdapter\n\t}\n\n\tsend(data: string | ArrayBufferLike | Blob | ArrayBufferView): void {\n\t\tlogger().debug({ msg: \"send called\", readyState: this.readyState });\n\n\t\tif (this.readyState !== this.OPEN) {\n\t\t\tconst error = new Error(\"WebSocket is not open\");\n\t\t\tlogger().warn({\n\t\t\t\tmsg: \"cannot send message, websocket not open\",\n\t\t\t\treadyState: this.readyState,\n\t\t\t\tdataType: typeof data,\n\t\t\t\tdataLength: typeof data === \"string\" ? data.length : \"binary\",\n\t\t\t\terror,\n\t\t\t});\n\t\t\tthis.#fireError(error);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#handler.onMessage({ data }, this.#wsContext);\n\t}\n\n\t/**\n\t * Closes the connection\n\t */\n\tclose(code = 1000, reason = \"\"): void {\n\t\tif (this.readyState === this.CLOSED || this.readyState === this.CLOSING) {\n\t\t\treturn;\n\t\t}\n\n\t\tlogger().debug({ msg: \"closing fake websocket\", code, reason });\n\n\t\tthis.#readyState = this.CLOSING;\n\n\t\t// Call the handler's onClose method\n\t\ttry {\n\t\t\tthis.#handler.onClose({ code, reason, wasClean: true }, this.#wsContext);\n\t\t} catch (err) {\n\t\t\tlogger().error({ msg: \"error closing websocket\", error: err });\n\t\t} finally {\n\t\t\tthis.#readyState = this.CLOSED;\n\n\t\t\t// Fire the close event\n\t\t\t// Create a close event object since CloseEvent is not available in Node.js\n\t\t\tconst closeEvent = {\n\t\t\t\ttype: \"close\",\n\t\t\t\twasClean: code === 1000,\n\t\t\t\tcode,\n\t\t\t\treason,\n\t\t\t\ttarget: this,\n\t\t\t\tcurrentTarget: this,\n\t\t\t} as unknown as RivetCloseEvent;\n\n\t\t\tthis.#fireClose(closeEvent);\n\t\t}\n\t}\n\n\t/**\n\t * Initialize the connection with the handler\n\t */\n\tasync #initialize(): Promise<void> {\n\t\ttry {\n\t\t\tlogger().debug({ msg: \"fake websocket initializing\" });\n\n\t\t\t// Call the handler's onOpen method\n\t\t\tlogger().debug({ msg: \"calling handler.onOpen with WSContext\" });\n\t\t\tthis.#handler.onOpen(undefined, this.#wsContext);\n\n\t\t\t// Update the ready state and fire events\n\t\t\tthis.#readyState = this.OPEN;\n\t\t\tlogger().debug({ msg: \"fake websocket initialized and now OPEN\" });\n\n\t\t\t// Fire the open event\n\t\t\tthis.#fireOpen();\n\n\t\t\t// Delay processing queued messages slightly to allow event handlers to be set up\n\t\t\tif (this.#queuedMessages.length > 0) {\n\t\t\t\tif (this.readyState !== this.OPEN) {\n\t\t\t\t\tlogger().warn({\n\t\t\t\t\t\tmsg: \"socket no longer open, dropping queued messages\",\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlogger().debug({\n\t\t\t\t\tmsg: `now processing ${this.#queuedMessages.length} queued messages`,\n\t\t\t\t});\n\n\t\t\t\t// Create a copy to avoid issues if new messages arrive during processing\n\t\t\t\tconst messagesToProcess = [...this.#queuedMessages];\n\t\t\t\tthis.#queuedMessages = [];\n\n\t\t\t\t// Process each queued message\n\t\t\t\tfor (const message of messagesToProcess) {\n\t\t\t\t\tlogger().debug({ msg: \"processing queued message\" });\n\t\t\t\t\tthis.#handleMessage(message);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tlogger().error({\n\t\t\t\tmsg: \"error opening fake websocket\",\n\t\t\t\terror: err,\n\t\t\t\terrorMessage: err instanceof Error ? err.message : String(err),\n\t\t\t\tstack: err instanceof Error ? err.stack : undefined,\n\t\t\t});\n\t\t\tthis.#fireError(err);\n\t\t\tthis.close(1011, \"Internal error during initialization\");\n\t\t}\n\t}\n\n\t/**\n\t * Handle messages received from the server via the WSContext\n\t */\n\t#handleMessage(data: string | ArrayBuffer | Uint8Array): void {\n\t\t// Store messages that arrive before the socket is fully initialized\n\t\tif (this.readyState !== this.OPEN) {\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"message received before socket is OPEN, queuing\",\n\t\t\t\treadyState: this.readyState,\n\t\t\t\tdataType: typeof data,\n\t\t\t\tdataLength:\n\t\t\t\t\ttypeof data === \"string\"\n\t\t\t\t\t\t? data.length\n\t\t\t\t\t\t: data instanceof ArrayBuffer\n\t\t\t\t\t\t\t? data.byteLength\n\t\t\t\t\t\t\t: data instanceof Uint8Array\n\t\t\t\t\t\t\t\t? data.byteLength\n\t\t\t\t\t\t\t\t: \"unknown\",\n\t\t\t});\n\n\t\t\t// Queue the message to be processed once the socket is open\n\t\t\tthis.#queuedMessages.push(data);\n\t\t\treturn;\n\t\t}\n\n\t\t// Log message received from server\n\t\tlogger().debug({\n\t\t\tmsg: \"fake websocket received message from server\",\n\t\t\tdataType: typeof data,\n\t\t\tdataLength:\n\t\t\t\ttypeof data === \"string\"\n\t\t\t\t\t? data.length\n\t\t\t\t\t: data instanceof ArrayBuffer\n\t\t\t\t\t\t? data.byteLength\n\t\t\t\t\t\t: data instanceof Uint8Array\n\t\t\t\t\t\t\t? data.byteLength\n\t\t\t\t\t\t\t: \"unknown\",\n\t\t});\n\n\t\t// Create a MessageEvent-like object\n\t\tconst event = {\n\t\t\ttype: \"message\",\n\t\t\tdata,\n\t\t\ttarget: this,\n\t\t\tcurrentTarget: this,\n\t\t} as unknown as RivetMessageEvent;\n\n\t\t// Dispatch the event\n\t\tthis.#dispatchEvent(\"message\", event);\n\t}\n\n\t#handleClose(code: number, reason: string): void {\n\t\tif (this.readyState === this.CLOSED) return;\n\n\t\tthis.#readyState = this.CLOSED;\n\n\t\t// Create a CloseEvent-like object\n\t\tconst event = {\n\t\t\ttype: \"close\",\n\t\t\tcode,\n\t\t\treason,\n\t\t\twasClean: code === 1000,\n\t\t\ttarget: this,\n\t\t\tcurrentTarget: this,\n\t\t} as unknown as RivetCloseEvent;\n\n\t\t// Dispatch the event\n\t\tthis.#dispatchEvent(\"close\", event);\n\t}\n\n\taddEventListener(type: string, listener: (ev: any) => void): void {\n\t\tif (!this.#eventListeners.has(type)) {\n\t\t\tthis.#eventListeners.set(type, []);\n\t\t}\n\t\tthis.#eventListeners.get(type)!.push(listener);\n\n\t\t// Flush any buffered events for this type\n\t\tthis.#flushBufferedEvents(type);\n\t}\n\n\tremoveEventListener(type: string, listener: (ev: any) => void): void {\n\t\tconst listeners = this.#eventListeners.get(type);\n\t\tif (listeners) {\n\t\t\tconst index = listeners.indexOf(listener);\n\t\t\tif (index !== -1) {\n\t\t\t\tlisteners.splice(index, 1);\n\t\t\t}\n\t\t}\n\t}\n\n\t#dispatchEvent(type: string, event: any): void {\n\t\tconst listeners = this.#eventListeners.get(type);\n\t\tif (listeners && listeners.length > 0) {\n\t\t\tlogger().debug(\n\t\t\t\t`dispatching ${type} event to ${listeners.length} listeners`,\n\t\t\t);\n\t\t\tfor (const listener of listeners) {\n\t\t\t\ttry {\n\t\t\t\t\tlistener(event);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tlogger().error({\n\t\t\t\t\t\tmsg: `error in ${type} event listener`,\n\t\t\t\t\t\terror: err,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tlogger().debug({\n\t\t\t\tmsg: `no ${type} listeners registered, buffering event`,\n\t\t\t});\n\t\t\tthis.#bufferedEvents.push({ type, event });\n\t\t}\n\n\t\t// Also check for on* properties\n\t\tswitch (type) {\n\t\t\tcase \"open\":\n\t\t\t\tif (this.#onopen) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.#onopen(event);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tlogger().error({ msg: \"error in onopen handler\", error });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"close\":\n\t\t\t\tif (this.#onclose) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.#onclose(event);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tlogger().error({ msg: \"error in onclose handler\", error });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"error\":\n\t\t\t\tif (this.#onerror) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.#onerror(event);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tlogger().error({ msg: \"error in onerror handler\", error });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"message\":\n\t\t\t\tif (this.#onmessage) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.#onmessage(event);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tlogger().error({ msg: \"error in onmessage handler\", error });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tdispatchEvent(event: RivetEvent): boolean {\n\t\tthis.#dispatchEvent(event.type, event);\n\t\treturn true;\n\t}\n\n\t#flushBufferedEvents(type: string): void {\n\t\tconst eventsToFlush = this.#bufferedEvents.filter(\n\t\t\t(buffered) => buffered.type === type,\n\t\t);\n\t\tthis.#bufferedEvents = this.#bufferedEvents.filter(\n\t\t\t(buffered) => buffered.type !== type,\n\t\t);\n\n\t\tfor (const { event } of eventsToFlush) {\n\t\t\tthis.#dispatchEvent(type, event);\n\t\t}\n\t}\n\n\t#fireOpen(): void {\n\t\ttry {\n\t\t\t// Create an Event-like object since Event constructor may not be available\n\t\t\tconst event = {\n\t\t\t\ttype: \"open\",\n\t\t\t\ttarget: this,\n\t\t\t\tcurrentTarget: this,\n\t\t\t} as unknown as RivetEvent;\n\n\t\t\tthis.#dispatchEvent(\"open\", event);\n\t\t} catch (err) {\n\t\t\tlogger().error({ msg: \"error in open event\", error: err });\n\t\t}\n\t}\n\n\t#fireClose(event: RivetCloseEvent): void {\n\t\ttry {\n\t\t\tthis.#dispatchEvent(\"close\", event);\n\t\t} catch (err) {\n\t\t\tlogger().error({ msg: \"error in close event\", error: err });\n\t\t}\n\t}\n\n\t#fireError(error: unknown): void {\n\t\ttry {\n\t\t\t// Create an Event-like object for error\n\t\t\tconst event = {\n\t\t\t\ttype: \"error\",\n\t\t\t\ttarget: this,\n\t\t\t\tcurrentTarget: this,\n\t\t\t\terror,\n\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t} as unknown as RivetEvent;\n\n\t\t\tthis.#dispatchEvent(\"error\", event);\n\t\t} catch (err) {\n\t\t\tlogger().error({ msg: \"error in error event\", error: err });\n\t\t}\n\n\t\t// Log the error\n\t\tlogger().error({ msg: \"websocket error\", error });\n\t}\n\n\t// Event handler properties with getters/setters\n\t#onopen: ((event: RivetEvent) => void) | null = null;\n\t#onclose: ((event: RivetCloseEvent) => void) | null = null;\n\t#onerror: ((event: RivetEvent) => void) | null = null;\n\t#onmessage: ((event: RivetMessageEvent) => void) | null = null;\n\n\tget onopen(): ((event: RivetEvent) => void) | null {\n\t\treturn this.#onopen;\n\t}\n\tset onopen(handler: ((event: RivetEvent) => void) | null) {\n\t\tthis.#onopen = handler;\n\t}\n\n\tget onclose(): ((event: RivetCloseEvent) => void) | null {\n\t\treturn this.#onclose;\n\t}\n\tset onclose(handler: ((event: RivetCloseEvent) => void) | null) {\n\t\tthis.#onclose = handler;\n\t}\n\n\tget onerror(): ((event: RivetEvent) => void) | null {\n\t\treturn this.#onerror;\n\t}\n\tset onerror(handler: ((event: RivetEvent) => void) | null) {\n\t\tthis.#onerror = handler;\n\t}\n\n\tget onmessage(): ((event: RivetMessageEvent) => void) | null {\n\t\treturn this.#onmessage;\n\t}\n\tset onmessage(handler: ((event: RivetMessageEvent) => void) | null) {\n\t\tthis.#onmessage = handler;\n\t}\n}\n","import * as cbor from \"cbor-x\";\nimport type { Hono, Context as HonoContext } from \"hono\";\nimport invariant from \"invariant\";\nimport { ActorAlreadyExists } from \"@/actor/errors\";\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\tManagerDisplayInformation,\n\tManagerDriver,\n} from \"@/driver-helpers/mod\";\nimport type { ManagerInspector } from \"@/inspector/manager\";\nimport type { Encoding, RegistryConfig, UniversalWebSocket } from \"@/mod\";\nimport type { RunConfig } from \"@/registry/run-config\";\nimport { combineUrlPath } from \"@/utils\";\nimport { sendHttpRequestToActor } from \"./actor-http-client\";\nimport {\n\tbuildGuardHeadersForWebSocket,\n\topenWebSocketToActor,\n} from \"./actor-websocket-client\";\nimport {\n\tcreateActor,\n\tdestroyActor,\n\tgetActor,\n\tgetActorById,\n\tgetOrCreateActorById,\n} from \"./api-endpoints\";\nimport { EngineApiError, getEndpoint } from \"./api-utils\";\nimport { logger } from \"./log\";\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\n\tconstructor(runConfig: ClientConfig) {\n\t\tthis.#config = runConfig;\n\t}\n\n\tasync getForId({\n\t\tc,\n\t\tname,\n\t\tactorId,\n\t}: GetForIdInput): Promise<ActorOutput | undefined> {\n\t\t// Fetch from API if not in cache\n\t\ttry {\n\t\t\tconst response = await getActor(this.#config, actorId);\n\n\t\t\t// Validate name matches\n\t\t\tif (response.actor.name !== name) {\n\t\t\t\tlogger().debug({\n\t\t\t\t\tmsg: \"actor name mismatch from api\",\n\t\t\t\t\tactorId,\n\t\t\t\t\tapiName: response.actor.name,\n\t\t\t\t\trequestedName: name,\n\t\t\t\t});\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tconst keyRaw = response.actor.key;\n\t\t\tinvariant(keyRaw, `actor ${actorId} should have key`);\n\t\t\tconst key = deserializeActorKey(keyRaw);\n\n\t\t\treturn {\n\t\t\t\tactorId,\n\t\t\t\tname,\n\t\t\t\tkey,\n\t\t\t};\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 getWithKey({\n\t\tc,\n\t\tname,\n\t\tkey,\n\t}: GetWithKeyInput): Promise<ActorOutput | undefined> {\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 getActorById(this.#config, name, key);\n\n\t\t\tif (!response.actor_id) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tconst actorId = response.actor_id;\n\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"getWithKey: found actor via api\",\n\t\t\t\tactorId,\n\t\t\t\tname,\n\t\t\t\tkey,\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\tactorId,\n\t\t\t\tname,\n\t\t\t\tkey,\n\t\t\t};\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\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 response = await getOrCreateActorById(this.#config, {\n\t\t\tname,\n\t\t\tkey: serializeActorKey(key),\n\t\t\trunner_name_selector: this.#config.runnerName,\n\t\t\tinput: input ? cbor.encode(actorInput).toString(\"base64\") : undefined,\n\t\t\tcrash_policy: \"sleep\",\n\t\t});\n\n\t\tconst actorId = response.actor_id;\n\n\t\tlogger().info({\n\t\t\tmsg: \"getOrCreateWithKey: actor ready\",\n\t\t\tactorId,\n\t\t\tname,\n\t\t\tkey,\n\t\t\tcreated: response.created,\n\t\t});\n\n\t\treturn {\n\t\t\tactorId,\n\t\t\tname,\n\t\t\tkey,\n\t\t};\n\t}\n\n\tasync createActor({\n\t\tc,\n\t\tname,\n\t\tkey,\n\t\tinput,\n\t}: CreateInput): Promise<ActorOutput> {\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\tname,\n\t\t\trunner_name_selector: this.#config.runnerName,\n\t\t\tkey: serializeActorKey(key),\n\t\t\tinput: input ? cbor.encode(input).toString(\"base64\") : null,\n\t\t\tcrash_policy: \"sleep\",\n\t\t});\n\t\tconst actorId = result.actor.actor_id;\n\n\t\tlogger().info({ msg: \"actor created\", actorId, name, key });\n\n\t\treturn {\n\t\t\tactorId,\n\t\t\tname,\n\t\t\tkey,\n\t\t};\n\t}\n\n\tasync destroyActor(actorId: string): Promise<void> {\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(actorId: string, actorRequest: Request): Promise<Response> {\n\t\treturn await sendHttpRequestToActor(this.#config, actorId, actorRequest);\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\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 proxyRequest(\n\t\t_c: HonoContext,\n\t\tactorRequest: Request,\n\t\tactorId: string,\n\t): Promise<Response> {\n\t\treturn await sendHttpRequestToActor(this.#config, actorId, actorRequest);\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\tauthData: unknown,\n\t): Promise<Response> {\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 headers\n\t\tconst headers = buildGuardHeadersForWebSocket(\n\t\t\tactorId,\n\t\t\tencoding,\n\t\t\tparams,\n\t\t\tauthData,\n\t\t);\n\t\tconst args = await createWebSocketProxy(c, wsGuardUrl, headers);\n\n\t\treturn await upgradeWebSocket(() => args)(c, noopNext());\n\t}\n\n\tdisplayInformation(): ManagerDisplayInformation {\n\t\treturn { name: \"Remote\", properties: {} };\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 { sendHttpRequest } from \"@/client/utils\";\nimport { combineUrlPath } from \"@/utils\";\nimport { logger } from \"./log\";\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\nexport function getEndpoint(config: ClientConfig) {\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\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\tresponseVersionedDataHandler: undefined,\n\t});\n}\n","import type { ClientConfig } from \"@/client/config\";\nimport { combineUrlPath } from \"@/utils\";\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 = combineUrlPath(endpoint, url.pathname + url.search);\n\n\t// Handle body properly based on method and presence\n\tlet bodyToSend: ArrayBuffer | null = null;\n\tconst guardHeaders = buildGuardHeadersForHttp(actorRequest, actorId);\n\n\tif (\n\t\tactorRequest.body &&\n\t\tactorRequest.method !== \"GET\" &&\n\t\tactorRequest.method !== \"HEAD\"\n\t) {\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\t// Clone and read the body to ensure it can be sent\n\t\tconst clonedRequest = actorRequest.clone();\n\t\tbodyToSend = await clonedRequest.arrayBuffer();\n\n\t\t// If this is a streaming request, we need to convert the headers\n\t\t// for the basic array buffer\n\t\tguardHeaders.delete(\"transfer-encoding\");\n\t\tguardHeaders.set(\n\t\t\t\"content-length\",\n\t\t\tString((bodyToSend as ArrayBuffer).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\tactorRequest: Request,\n\tactorId: string,\n): Headers {\n\tconst headers = new Headers();\n\t// Copy all headers from the original request\n\tfor (const [key, value] of actorRequest.headers.entries()) {\n\t\theaders.set(key, value);\n\t}\n\t// Add guard-specific headers\n\theaders.set(\"x-rivet-target\", \"actor\");\n\theaders.set(\"x-rivet-actor\", actorId);\n\theaders.set(\"x-rivet-port\", \"main\");\n\treturn headers;\n}\n","import {\n\tHEADER_AUTH_DATA,\n\tHEADER_CONN_PARAMS,\n\tHEADER_ENCODING,\n} from \"@/actor/router-endpoints\";\nimport type { ClientConfig } from \"@/client/config\";\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 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 = combineUrlPath(endpoint, path);\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(guardUrl, {\n\t\theaders: buildGuardHeadersForWebSocket(actorId, 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 buildGuardHeadersForWebSocket(\n\tactorId: string,\n\tencoding: Encoding,\n\tparams?: unknown,\n\tauthData?: unknown,\n): Record<string, string> {\n\tconst headers: Record<string, string> = {};\n\theaders[\"x-rivet-target\"] = \"actor\";\n\theaders[\"x-rivet-actor\"] = actorId;\n\theaders[\"x-rivet-port\"] = \"main\";\n\theaders[HEADER_ENCODING] = encoding;\n\tif (params) {\n\t\theaders[HEADER_CONN_PARAMS] = JSON.stringify(params);\n\t}\n\tif (authData) {\n\t\theaders[HEADER_AUTH_DATA] = JSON.stringify(authData);\n\t}\n\treturn headers;\n}\n","import { serializeActorKey } from \"@/actor/keys\";\nimport type { ClientConfig } from \"@/client/client\";\nimport type {\n\tActorsCreateRequest,\n\tActorsCreateResponse,\n} from \"@/manager-api/routes/actors-create\";\nimport type { ActorsDeleteResponse } from \"@/manager-api/routes/actors-delete\";\nimport type { ActorsGetResponse } from \"@/manager-api/routes/actors-get\";\nimport type { ActorsGetByIdResponse } from \"@/manager-api/routes/actors-get-by-id\";\nimport type {\n\tActorsGetOrCreateByIdRequest,\n\tActorsGetOrCreateByIdResponse,\n} from \"@/manager-api/routes/actors-get-or-create-by-id\";\nimport type { RivetId } from \"@/manager-api/routes/common\";\nimport { apiCall } from \"./api-utils\";\n\n// MARK: Get actor\nexport async function getActor(\n\tconfig: ClientConfig,\n\tactorId: RivetId,\n): Promise<ActorsGetResponse> {\n\treturn apiCall<never, ActorsGetResponse>(\n\t\tconfig,\n\t\t\"GET\",\n\t\t`/actors/${encodeURIComponent(actorId)}`,\n\t);\n}\n\n// MARK: Get actor by id\nexport async function getActorById(\n\tconfig: ClientConfig,\n\tname: string,\n\tkey: string[],\n): Promise<ActorsGetByIdResponse> {\n\tconst serializedKey = serializeActorKey(key);\n\treturn apiCall<never, ActorsGetByIdResponse>(\n\t\tconfig,\n\t\t\"GET\",\n\t\t`/actors/by-id?name=${encodeURIComponent(name)}&key=${encodeURIComponent(serializedKey)}`,\n\t);\n}\n\n// MARK: Get or create actor by id\nexport async function getOrCreateActorById(\n\tconfig: ClientConfig,\n\trequest: ActorsGetOrCreateByIdRequest,\n): Promise<ActorsGetOrCreateByIdResponse> {\n\treturn apiCall<ActorsGetOrCreateByIdRequest, ActorsGetOrCreateByIdResponse>(\n\t\tconfig,\n\t\t\"PUT\",\n\t\t`/actors/by-id`,\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","import type { Context as HonoContext } from \"hono\";\nimport type { WSContext } from \"hono/ws\";\nimport { stringifyError } from \"@/common/utils\";\nimport { importWebSocket } from \"@/common/websocket\";\nimport type { UpgradeWebSocketArgs } from \"@/mod\";\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\theaders: Record<string, string>,\n): Promise<UpgradeWebSocketArgs> {\n\tconst WebSocket = await importWebSocket();\n\n\t// HACK: Sanitize WebSocket-specific headers. If we don't do this, some WebSocket implementations (i.e. native WebSocket in Node.js) will fail to connect.\n\tfor (const [k, v] of c.req.raw.headers.entries()) {\n\t\tif (!k.startsWith(\"sec-\") && k !== \"connection\" && k !== \"upgrade\") {\n\t\t\theaders[k] = v;\n\t\t}\n\t}\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, { headers });\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({ msg: \"target websocket connected\", targetUrl });\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({ msg: \"websocket state not initialized\", targetUrl });\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(clientWs, 1011, \"Failed to connect to target\");\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(1000, event.reason || \"Client disconnected\");\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 (\"close\" in ws && (ws as WebSocket).readyState === WebSocket.OPEN) {\n\t\tws.close(code, reason);\n\t}\n}\n","import type {\n\tActorConfig as RunnerActorConfig,\n\tRunnerConfig,\n} from \"@rivetkit/engine-runner\";\nimport { Runner } from \"@rivetkit/engine-runner\";\nimport * as cbor from \"cbor-x\";\nimport { WSContext } from \"hono/ws\";\nimport invariant from \"invariant\";\nimport { deserializeActorKey } from \"@/actor/keys\";\nimport { EncodingSchema } from \"@/actor/protocol/serde\";\nimport type { Client } from \"@/client/client\";\nimport { getLogger } from \"@/common/log\";\nimport {\n\ttype ActorDriver,\n\ttype AnyActorInstance,\n\tHEADER_AUTH_DATA,\n\tHEADER_CONN_PARAMS,\n\tHEADER_ENCODING,\n\ttype ManagerDriver,\n\tserializeEmptyPersistData,\n} from \"@/driver-helpers/mod\";\nimport type {\n\tActorRouter,\n\tRegistryConfig,\n\tRunConfig,\n\tUniversalWebSocket,\n\tUpgradeWebSocketArgs,\n} from \"@/mod\";\nimport {\n\tcreateActorRouter,\n\tcreateGenericConnDrivers,\n\tGenericConnGlobalState,\n\thandleRawWebSocketHandler,\n\thandleWebSocketConnect,\n\tlookupInRegistry,\n\tPATH_CONNECT_WEBSOCKET,\n\tPATH_RAW_WEBSOCKET_PREFIX,\n} from \"@/mod\";\nimport type { Config } from \"./config\";\nimport { KEYS } from \"./kv\";\nimport { logger } from \"./log\";\n\ninterface ActorHandler {\n\tactor?: AnyActorInstance;\n\tactorStartPromise?: PromiseWithResolvers<void>;\n\tgenericConnGlobalState: GenericConnGlobalState;\n\tpersistedData?: Uint8Array;\n}\n\nexport type DriverContext = {};\n\nexport class EngineActorDriver implements ActorDriver {\n\t#registryConfig: RegistryConfig;\n\t#runConfig: RunConfig;\n\t#managerDriver: ManagerDriver;\n\t#inlineClient: Client<any>;\n\t#config: Config;\n\t#runner: Runner;\n\t#actors: Map<string, ActorHandler> = new Map();\n\t#actorRouter: ActorRouter;\n\t#version: number = 1; // Version for the runner protocol\n\n\tconstructor(\n\t\tregistryConfig: RegistryConfig,\n\t\trunConfig: RunConfig,\n\t\tmanagerDriver: ManagerDriver,\n\t\tinlineClient: Client<any>,\n\t\tconfig: Config,\n\t) {\n\t\tthis.#registryConfig = registryConfig;\n\t\tthis.#runConfig = runConfig;\n\t\tthis.#managerDriver = managerDriver;\n\t\tthis.#inlineClient = inlineClient;\n\t\tthis.#config = config;\n\t\tthis.#actorRouter = createActorRouter(runConfig, this);\n\n\t\t// Create runner configuration\n\t\tlet hasDisconnected = false;\n\t\tconst runnerConfig: RunnerConfig = {\n\t\t\tversion: this.#version,\n\t\t\tendpoint: config.endpoint,\n\t\t\tpegboardEndpoint: config.pegboardEndpoint,\n\t\t\tnamespace: config.namespace,\n\t\t\ttotalSlots: config.totalSlots,\n\t\t\trunnerName: config.runnerName,\n\t\t\trunnerKey: config.runnerKey,\n\t\t\tmetadata: {\n\t\t\t\tinspectorToken: this.#runConfig.inspector.token(),\n\t\t\t},\n\t\t\tprepopulateActorNames: Object.fromEntries(\n\t\t\t\tObject.keys(this.#registryConfig.use).map((name) => [\n\t\t\t\t\tname,\n\t\t\t\t\t{ metadata: {} },\n\t\t\t\t]),\n\t\t\t),\n\t\t\tonConnected: () => {\n\t\t\t\tif (hasDisconnected) {\n\t\t\t\t\tlogger().info({\n\t\t\t\t\t\tmsg: \"runner reconnected\",\n\t\t\t\t\t\tnamespace: this.#config.namespace,\n\t\t\t\t\t\trunnerName: this.#config.runnerName,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tlogger().debug({\n\t\t\t\t\t\tmsg: \"runner connected\",\n\t\t\t\t\t\tnamespace: this.#config.namespace,\n\t\t\t\t\t\trunnerName: this.#config.runnerName,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\tonDisconnected: () => {\n\t\t\t\tlogger().warn({\n\t\t\t\t\tmsg: \"runner disconnected\",\n\t\t\t\t\tnamespace: this.#config.namespace,\n\t\t\t\t\trunnerName: this.#config.runnerName,\n\t\t\t\t});\n\t\t\t\thasDisconnected = true;\n\t\t\t},\n\t\t\tonShutdown: () => {},\n\t\t\tfetch: this.#runnerFetch.bind(this),\n\t\t\twebsocket: this.#runnerWebSocket.bind(this),\n\t\t\tonActorStart: this.#runnerOnActorStart.bind(this),\n\t\t\tonActorStop: this.#runnerOnActorStop.bind(this),\n\t\t\tlogger: getLogger(\"engine-runner\"),\n\t\t};\n\n\t\t// Create and start runner\n\t\tthis.#runner = new Runner(runnerConfig);\n\t\tthis.#runner.start();\n\t\tlogger().debug({\n\t\t\tmsg: \"engine runner started\",\n\t\t\tendpoint: config.endpoint,\n\t\t\tnamespace: config.namespace,\n\t\t\trunnerName: config.runnerName,\n\t\t});\n\t}\n\n\tasync #loadActorHandler(actorId: string): Promise<ActorHandler> {\n\t\t// Check if actor is already loaded\n\t\tconst handler = this.#actors.get(actorId);\n\t\tif (!handler) throw new Error(`Actor handler does not exist ${actorId}`);\n\t\tif (handler.actorStartPromise) await handler.actorStartPromise.promise;\n\t\tif (!handler.actor) throw new Error(\"Actor should be loaded\");\n\t\treturn handler;\n\t}\n\n\tasync loadActor(actorId: string): Promise<AnyActorInstance> {\n\t\tconst handler = await this.#loadActorHandler(actorId);\n\t\tif (!handler.actor) throw new Error(`Actor ${actorId} failed to load`);\n\t\treturn handler.actor;\n\t}\n\n\tgetGenericConnGlobalState(actorId: string): GenericConnGlobalState {\n\t\tconst handler = this.#actors.get(actorId);\n\t\tif (!handler) {\n\t\t\tthrow new Error(`Actor ${actorId} not loaded`);\n\t\t}\n\t\treturn handler.genericConnGlobalState;\n\t}\n\n\tgetContext(actorId: string): DriverContext {\n\t\treturn {};\n\t}\n\n\tasync readPersistedData(actorId: string): Promise<Uint8Array | undefined> {\n\t\tconst handler = this.#actors.get(actorId);\n\t\tif (!handler) throw new Error(`Actor ${actorId} not loaded`);\n\t\tif (handler.persistedData) return handler.persistedData;\n\n\t\tconst [value] = await this.#runner.kvGet(actorId, [KEYS.PERSIST_DATA]);\n\n\t\tif (value !== null) {\n\t\t\thandler.persistedData = value;\n\t\t\treturn value;\n\t\t} else {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tasync writePersistedData(actorId: string, data: Uint8Array): Promise<void> {\n\t\tconst handler = this.#actors.get(actorId);\n\t\tif (!handler) throw new Error(`Actor ${actorId} not loaded`);\n\n\t\thandler.persistedData = data;\n\n\t\tawait this.#runner.kvPut(actorId, [[KEYS.PERSIST_DATA, data]]);\n\t}\n\n\tasync setAlarm(actor: AnyActorInstance, timestamp: number): Promise<void> {\n\t\t// TODO: Set timeout\n\t\t// TODO: Use alarm on sleep\n\t\t// TODO: Send alarm to runner\n\t}\n\n\tasync getDatabase(_actorId: string): Promise<unknown | undefined> {\n\t\treturn undefined;\n\t}\n\n\t// Runner lifecycle callbacks\n\tasync #runnerOnActorStart(\n\t\tactorId: string,\n\t\tgeneration: number,\n\t\tconfig: RunnerActorConfig,\n\t): Promise<void> {\n\t\tlogger().debug({\n\t\t\tmsg: \"runner actor starting\",\n\t\t\tactorId,\n\t\t\tname: config.name,\n\t\t\tkey: config.key,\n\t\t\tgeneration,\n\t\t});\n\n\t\t// Deserialize input\n\t\tlet input: any;\n\t\tif (config.input) {\n\t\t\tinput = cbor.decode(config.input);\n\t\t}\n\n\t\t// Get or create handler\n\t\tlet handler = this.#actors.get(actorId);\n\t\tif (!handler) {\n\t\t\thandler = {\n\t\t\t\tgenericConnGlobalState: new GenericConnGlobalState(),\n\t\t\t\tactorStartPromise: Promise.withResolvers(),\n\t\t\t\tpersistedData: serializeEmptyPersistData(input),\n\t\t\t};\n\t\t\tthis.#actors.set(actorId, handler);\n\t\t}\n\n\t\tconst name = config.name as string;\n\t\tinvariant(config.key, \"actor should have a key\");\n\t\tconst key = deserializeActorKey(config.key);\n\n\t\t// Create actor instance\n\t\tconst definition = lookupInRegistry(\n\t\t\tthis.#registryConfig,\n\t\t\tconfig.name as string, // TODO: Remove cast\n\t\t);\n\t\thandler.actor = definition.instantiate();\n\n\t\t// Start actor\n\t\tconst connDrivers = createGenericConnDrivers(\n\t\t\thandler.genericConnGlobalState,\n\t\t);\n\t\tawait handler.actor.start(\n\t\t\tconnDrivers,\n\t\t\tthis,\n\t\t\tthis.#inlineClient,\n\t\t\tactorId,\n\t\t\tname,\n\t\t\tkey,\n\t\t\t\"unknown\", // TODO: Add regions\n\t\t);\n\n\t\t// Resolve promise if waiting\n\t\thandler.actorStartPromise?.resolve();\n\t\thandler.actorStartPromise = undefined;\n\n\t\tlogger().debug({ msg: \"runner actor started\", actorId, name, key });\n\t}\n\n\tasync #runnerOnActorStop(actorId: string, generation: number): Promise<void> {\n\t\tlogger().debug({ msg: \"runner actor stopping\", actorId, generation });\n\n\t\tconst handler = this.#actors.get(actorId);\n\t\tif (handler?.actor) {\n\t\t\tawait handler.actor._stop();\n\t\t\tthis.#actors.delete(actorId);\n\t\t}\n\n\t\tlogger().debug({ msg: \"runner actor stopped\", actorId });\n\t}\n\n\tasync #runnerFetch(actorId: string, request: Request): Promise<Response> {\n\t\tlogger().debug({\n\t\t\tmsg: \"runner fetch\",\n\t\t\tactorId,\n\t\t\turl: request.url,\n\t\t\tmethod: request.method,\n\t\t});\n\t\treturn await this.#actorRouter.fetch(request, { actorId });\n\t}\n\n\tasync #runnerWebSocket(\n\t\tactorId: string,\n\t\twebsocketRaw: any,\n\t\trequest: Request,\n\t): Promise<void> {\n\t\tconst websocket = websocketRaw as UniversalWebSocket;\n\n\t\tlogger().debug({ msg: \"runner websocket\", actorId, url: request.url });\n\n\t\tconst url = new URL(request.url);\n\n\t\t// Parse headers\n\t\tconst encodingRaw = request.headers.get(HEADER_ENCODING);\n\t\tconst connParamsRaw = request.headers.get(HEADER_CONN_PARAMS);\n\t\tconst authDataRaw = request.headers.get(HEADER_AUTH_DATA);\n\n\t\tconst encoding = EncodingSchema.parse(encodingRaw);\n\t\tconst connParams = connParamsRaw ? JSON.parse(connParamsRaw) : undefined;\n\t\tconst authData = authDataRaw ? JSON.parse(authDataRaw) : undefined;\n\n\t\t// Fetch WS handler\n\t\t//\n\t\t// We store the promise since we need to add WebSocket event listeners immediately that will wait for the promise to resolve\n\t\tlet wsHandlerPromise: Promise<UpgradeWebSocketArgs>;\n\t\tif (url.pathname === PATH_CONNECT_WEBSOCKET) {\n\t\t\twsHandlerPromise = handleWebSocketConnect(\n\t\t\t\trequest,\n\t\t\t\tthis.#runConfig,\n\t\t\t\tthis,\n\t\t\t\tactorId,\n\t\t\t\tencoding,\n\t\t\t\tconnParams,\n\t\t\t\tauthData,\n\t\t\t);\n\t\t} else if (url.pathname.startsWith(PATH_RAW_WEBSOCKET_PREFIX)) {\n\t\t\twsHandlerPromise = handleRawWebSocketHandler(\n\t\t\t\trequest,\n\t\t\t\turl.pathname + url.search,\n\t\t\t\tthis,\n\t\t\t\tactorId,\n\t\t\t\tauthData,\n\t\t\t);\n\t\t} else {\n\t\t\tthrow new Error(`Unreachable path: ${url.pathname}`);\n\t\t}\n\n\t\t// TODO: Add close\n\n\t\t// Connect the Hono WS hook to the adapter\n\t\tconst wsContext = new WSContext(websocket);\n\n\t\twsHandlerPromise.catch((err) => {\n\t\t\tlogger().error({ msg: \"building websocket handlers errored\", err });\n\t\t\twsContext.close(1011, `${err}`);\n\t\t});\n\n\t\tif (websocket.readyState === 1) {\n\t\t\twsHandlerPromise.then((x) => x.onOpen?.(new Event(\"open\"), wsContext));\n\t\t} else {\n\t\t\twebsocket.addEventListener(\"open\", (event) => {\n\t\t\t\twsHandlerPromise.then((x) => x.onOpen?.(event, wsContext));\n\t\t\t});\n\t\t}\n\n\t\twebsocket.addEventListener(\"message\", (event) => {\n\t\t\twsHandlerPromise.then((x) => x.onMessage?.(event, wsContext));\n\t\t});\n\n\t\twebsocket.addEventListener(\"close\", (event) => {\n\t\t\twsHandlerPromise.then((x) => x.onClose?.(event, wsContext));\n\t\t});\n\n\t\twebsocket.addEventListener(\"error\", (event) => {\n\t\t\twsHandlerPromise.then((x) => x.onError?.(event, wsContext));\n\t\t});\n\t}\n\n\tasync sleep(actorId: string) {\n\t\tthis.#runner.sleepActor(actorId);\n\t}\n\n\tasync shutdown(immediate: boolean): Promise<void> {\n\t\tlogger().info({ msg: \"stopping engine actor driver\" });\n\t\tawait this.#runner.shutdown(immediate);\n\t}\n}\n","export const KEYS = {\n\tPERSIST_DATA: Uint8Array.from([1]),\n};\n","import { getLogger } from \"@/common/log\";\n\nexport function logger() {\n\treturn getLogger(\"driver-engine\");\n}\n","import type { Hono } from \"hono\";\nimport { z } from \"zod\";\nimport { getEnvUniversal } from \"@/utils\";\n\nexport const ConfigSchema = z\n\t.object({\n\t\tapp: z.custom<Hono>().optional(),\n\t\tendpoint: z\n\t\t\t.string()\n\t\t\t.default(\n\t\t\t\t() => getEnvUniversal(\"RIVET_ENGINE\") ?? \"http://localhost:6420\",\n\t\t\t),\n\t\tpegboardEndpoint: z.string().optional(),\n\t\tnamespace: z\n\t\t\t.string()\n\t\t\t.default(() => getEnvUniversal(\"RIVET_NAMESPACE\") ?? \"default\"),\n\t\trunnerName: z\n\t\t\t.string()\n\t\t\t.default(() => getEnvUniversal(\"RIVET_RUNNER\") ?? \"rivetkit\"),\n\t\t// TODO: Automatically attempt to determine key by common env vars (e.g. k8s pod name)\n\t\trunnerKey: z\n\t\t\t.string()\n\t\t\t.default(\n\t\t\t\t() => getEnvUniversal(\"RIVET_RUNNER_KEY\") ?? crypto.randomUUID(),\n\t\t\t),\n\t\ttotalSlots: z.number().default(100_000),\n\t})\n\t.default({});\n\nexport type InputConfig = z.input<typeof ConfigSchema>;\nexport type Config = z.infer<typeof ConfigSchema>;\n","import type { Client } from \"@/client/client\";\nimport type { ManagerDriver } from \"@/manager/driver\";\nimport type { RegistryConfig } from \"@/registry/config\";\nimport type { DriverConfig, RunConfig } from \"@/registry/run-config\";\nimport { RemoteManagerDriver } from \"@/remote-manager-driver/mod\";\nimport { EngineActorDriver } from \"./actor-driver\";\nimport { ConfigSchema, type InputConfig } from \"./config\";\n\nexport { EngineActorDriver } from \"./actor-driver\";\nexport { type Config, ConfigSchema, type InputConfig } from \"./config\";\n\nexport function createEngineDriver(inputConfig?: InputConfig): DriverConfig {\n\tconst config = ConfigSchema.parse(inputConfig);\n\n\treturn {\n\t\tname: \"engine\",\n\t\tmanager: (_registryConfig, runConfig) => {\n\t\t\treturn new RemoteManagerDriver(runConfig);\n\t\t},\n\t\tactor: (\n\t\t\tregistryConfig: RegistryConfig,\n\t\t\trunConfig: RunConfig,\n\t\t\tmanagerDriver: ManagerDriver,\n\t\t\tinlineClient: Client<any>,\n\t\t) => {\n\t\t\treturn new EngineActorDriver(\n\t\t\t\tregistryConfig,\n\t\t\t\trunConfig,\n\t\t\t\tmanagerDriver,\n\t\t\t\tinlineClient,\n\t\t\t\tconfig,\n\t\t\t);\n\t\t},\n\t};\n}\n","import type { GenericConnGlobalState } from \"@/actor/generic-conn-driver\";\nimport { loggerWithoutContext } from \"@/actor/log\";\nimport type { AnyClient } from \"@/client/client\";\nimport type {\n\tActorDriver,\n\tAnyActorInstance,\n\tManagerDriver,\n} from \"@/driver-helpers/mod\";\nimport type { RegistryConfig, RunConfig } from \"@/mod\";\nimport { bufferToArrayBuffer } from \"@/utils\";\nimport type { FileSystemGlobalState } from \"./global-state\";\n\nexport type ActorDriverContext = Record<never, never>;\n\n/**\n * File System implementation of the Actor Driver\n */\nexport class FileSystemActorDriver implements ActorDriver {\n\t#registryConfig: RegistryConfig;\n\t#runConfig: RunConfig;\n\t#managerDriver: ManagerDriver;\n\t#inlineClient: AnyClient;\n\t#state: FileSystemGlobalState;\n\n\tconstructor(\n\t\tregistryConfig: RegistryConfig,\n\t\trunConfig: RunConfig,\n\t\tmanagerDriver: ManagerDriver,\n\t\tinlineClient: AnyClient,\n\t\tstate: FileSystemGlobalState,\n\t) {\n\t\tthis.#registryConfig = registryConfig;\n\t\tthis.#runConfig = runConfig;\n\t\tthis.#managerDriver = managerDriver;\n\t\tthis.#inlineClient = inlineClient;\n\t\tthis.#state = state;\n\t}\n\n\tasync loadActor(actorId: string): Promise<AnyActorInstance> {\n\t\treturn this.#state.startActor(\n\t\t\tthis.#registryConfig,\n\t\t\tthis.#runConfig,\n\t\t\tthis.#inlineClient,\n\t\t\tthis,\n\t\t\tactorId,\n\t\t);\n\t}\n\n\tgetGenericConnGlobalState(actorId: string): GenericConnGlobalState {\n\t\treturn this.#state.getActorOrError(actorId).genericConnGlobalState;\n\t}\n\n\t/**\n\t * Get the current storage directory path\n\t */\n\tget storagePath(): string {\n\t\treturn this.#state.storagePath;\n\t}\n\n\tgetContext(_actorId: string): ActorDriverContext {\n\t\treturn {};\n\t}\n\n\tasync readPersistedData(actorId: string): Promise<Uint8Array | undefined> {\n\t\treturn new Uint8Array(\n\t\t\t(await this.#state.loadActorStateOrError(actorId)).persistedData,\n\t\t);\n\t}\n\n\tasync writePersistedData(actorId: string, data: Uint8Array): Promise<void> {\n\t\tconst state = await this.#state.loadActorStateOrError(actorId);\n\n\t\t// Save state to disk\n\t\tawait this.#state.writeActor(actorId, {\n\t\t\t...state,\n\t\t\tpersistedData: bufferToArrayBuffer(data),\n\t\t});\n\t}\n\n\tasync setAlarm(actor: AnyActorInstance, timestamp: number): Promise<void> {\n\t\tawait this.#state.setActorAlarm(actor.id, timestamp);\n\t}\n\n\tgetDatabase(actorId: string): Promise<unknown | undefined> {\n\t\treturn this.#state.createDatabase(actorId);\n\t}\n\n\tsleep(actorId: string): Promise<void> {\n\t\treturn this.#state.sleepActor(actorId);\n\t}\n}\n","import * as crypto from \"node:crypto\";\nimport * as fsSync from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport invariant from \"invariant\";\nimport { lookupInRegistry } from \"@/actor/definition\";\nimport { ActorAlreadyExists } from \"@/actor/errors\";\nimport {\n\tcreateGenericConnDrivers,\n\tGenericConnGlobalState,\n} from \"@/actor/generic-conn-driver\";\nimport type { AnyActorInstance } from \"@/actor/instance\";\nimport type { ActorKey } from \"@/actor/mod\";\nimport { generateRandomString } from \"@/actor/utils\";\nimport type { AnyClient } from \"@/client/client\";\nimport {\n\ttype ActorDriver,\n\tserializeEmptyPersistData,\n} from \"@/driver-helpers/mod\";\nimport type { RegistryConfig } from \"@/registry/config\";\nimport type { RunConfig } from \"@/registry/run-config\";\nimport type * as schema from \"@/schemas/file-system-driver/mod\";\nimport {\n\tACTOR_ALARM_VERSIONED,\n\tACTOR_STATE_VERSIONED,\n} from \"@/schemas/file-system-driver/versioned\";\nimport {\n\tbufferToArrayBuffer,\n\ttype LongTimeoutHandle,\n\tSinglePromiseQueue,\n\tsetLongTimeout,\n\tstringifyError,\n} from \"@/utils\";\nimport { logger } from \"./log\";\nimport {\n\tensureDirectoryExists,\n\tensureDirectoryExistsSync,\n\tgetStoragePath,\n} from \"./utils\";\n\n// Actor handler to track running instances\n\ninterface ActorEntry {\n\tid: string;\n\n\tstate?: schema.ActorState;\n\t/** Promise for loading the actor state. */\n\tloadPromise?: Promise<ActorEntry>;\n\n\tactor?: AnyActorInstance;\n\t/** Promise for starting the actor. */\n\tstartPromise?: PromiseWithResolvers<void>;\n\n\tgenericConnGlobalState: GenericConnGlobalState;\n\n\talarmTimeout?: LongTimeoutHandle;\n\t/** The timestamp currently scheduled for this actor's alarm (ms since epoch). */\n\talarmTimestamp?: number;\n\n\t/** Resolver for pending write operations that need to be notified when any write completes */\n\tpendingWriteResolver?: PromiseWithResolvers<void>;\n\n\t/** If the actor has been removed by destroy or sleep. */\n\tremoved: boolean;\n}\n\n/**\n * Global state for the file system driver\n */\nexport class FileSystemGlobalState {\n\t#storagePath: string;\n\t#stateDir: string;\n\t#dbsDir: string;\n\t#alarmsDir: string;\n\n\t#persist: boolean;\n\t#actors = new Map<string, ActorEntry>();\n\t#actorCountOnStartup: number = 0;\n\n\t#runnerParams?: {\n\t\tregistryConfig: RegistryConfig;\n\t\trunConfig: RunConfig;\n\t\tinlineClient: AnyClient;\n\t\tactorDriver: ActorDriver;\n\t};\n\n\tget persist(): boolean {\n\t\treturn this.#persist;\n\t}\n\n\tget storagePath() {\n\t\treturn this.#storagePath;\n\t}\n\n\tget actorCountOnStartup() {\n\t\treturn this.#actorCountOnStartup;\n\t}\n\n\tconstructor(persist: boolean = true, customPath?: string) {\n\t\tthis.#persist = persist;\n\t\tthis.#storagePath = persist ? getStoragePath(customPath) : \"/tmp\";\n\t\tthis.#stateDir = path.join(this.#storagePath, \"state\");\n\t\tthis.#dbsDir = path.join(this.#storagePath, \"databases\");\n\t\tthis.#alarmsDir = path.join(this.#storagePath, \"alarms\");\n\n\t\tif (this.#persist) {\n\t\t\t// Ensure storage directories exist synchronously during initialization\n\t\t\tensureDirectoryExistsSync(this.#stateDir);\n\t\t\tensureDirectoryExistsSync(this.#dbsDir);\n\t\t\tensureDirectoryExistsSync(this.#alarmsDir);\n\n\t\t\ttry {\n\t\t\t\tconst actorIds = fsSync.readdirSync(this.#stateDir);\n\t\t\t\tthis.#actorCountOnStartup = actorIds.length;\n\t\t\t} catch (error) {\n\t\t\t\tlogger().error({ msg: \"failed to count actors\", error });\n\t\t\t}\n\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"file system driver ready\",\n\t\t\t\tdir: this.#storagePath,\n\t\t\t\tactorCount: this.#actorCountOnStartup,\n\t\t\t});\n\n\t\t\t// Cleanup stale temp files on startup\n\t\t\ttry {\n\t\t\t\tthis.#cleanupTempFilesSync();\n\t\t\t} catch (err) {\n\t\t\t\tlogger().error({ msg: \"failed to cleanup temp files\", error: err });\n\t\t\t}\n\t\t} else {\n\t\t\tlogger().debug({ msg: \"memory driver ready\" });\n\t\t}\n\t}\n\n\tgetActorStatePath(actorId: string): string {\n\t\treturn path.join(this.#stateDir, actorId);\n\t}\n\n\tgetActorDbPath(actorId: string): string {\n\t\treturn path.join(this.#dbsDir, `${actorId}.db`);\n\t}\n\n\tgetActorAlarmPath(actorId: string): string {\n\t\treturn path.join(this.#alarmsDir, actorId);\n\t}\n\n\tasync *getActorsIterator(params: {\n\t\tcursor?: string;\n\t}): AsyncGenerator<schema.ActorState> {\n\t\tlet actorIds = Array.from(this.#actors.keys()).sort();\n\n\t\t// Check if state directory exists first\n\t\tif (fsSync.existsSync(this.#stateDir)) {\n\t\t\tactorIds = fsSync\n\t\t\t\t.readdirSync(this.#stateDir)\n\t\t\t\t.filter((id) => !id.includes(\".tmp\"))\n\t\t\t\t.sort();\n\t\t}\n\n\t\tconst startIndex = params.cursor ? actorIds.indexOf(params.cursor) + 1 : 0;\n\n\t\tfor (let i = startIndex; i < actorIds.length; i++) {\n\t\t\tconst actorId = actorIds[i];\n\t\t\tif (!actorId) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst state = await this.loadActorStateOrError(actorId);\n\t\t\t\tyield state;\n\t\t\t} catch (error) {\n\t\t\t\tlogger().error({ msg: \"failed to load actor state\", actorId, error });\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Ensures an entry exists for this actor.\n\t *\n\t * Used for #createActor and #loadActor.\n\t */\n\t#upsertEntry(actorId: string): ActorEntry {\n\t\tlet entry = this.#actors.get(actorId);\n\t\tif (entry) {\n\t\t\treturn entry;\n\t\t}\n\n\t\tentry = {\n\t\t\tid: actorId,\n\t\t\tgenericConnGlobalState: new GenericConnGlobalState(),\n\t\t\tremoved: false,\n\t\t};\n\t\tthis.#actors.set(actorId, entry);\n\t\treturn entry;\n\t}\n\n\t/**\n\t * Creates a new actor and writes to file system.\n\t */\n\tasync createActor(\n\t\tactorId: string,\n\t\tname: string,\n\t\tkey: ActorKey,\n\t\tinput: unknown | undefined,\n\t): Promise<ActorEntry> {\n\t\t// TODO: Does not check if actor already exists on fs\n\n\t\tif (this.#actors.has(actorId)) {\n\t\t\tthrow new ActorAlreadyExists(name, key);\n\t\t}\n\n\t\tconst entry = this.#upsertEntry(actorId);\n\t\tentry.state = {\n\t\t\tactorId,\n\t\t\tname,\n\t\t\tkey,\n\t\t\tcreatedAt: BigInt(Date.now()),\n\t\t\tpersistedData: bufferToArrayBuffer(serializeEmptyPersistData(input)),\n\t\t};\n\t\tawait this.writeActor(actorId, entry.state);\n\t\treturn entry;\n\t}\n\n\t/**\n\t * Loads the actor from disk or returns the existing actor entry. This will return an entry even if the actor does not actually exist.\n\t */\n\tasync loadActor(actorId: string): Promise<ActorEntry> {\n\t\tconst entry = this.#upsertEntry(actorId);\n\n\t\t// Check if already loaded\n\t\tif (entry.state) {\n\t\t\treturn entry;\n\t\t}\n\n\t\t// If not persisted, then don't load from FS\n\t\tif (!this.#persist) {\n\t\t\treturn entry;\n\t\t}\n\n\t\t// If state is currently being loaded, wait for it\n\t\tif (entry.loadPromise) {\n\t\t\tawait entry.loadPromise;\n\t\t\treturn entry;\n\t\t}\n\n\t\t// Start loading state\n\t\tentry.loadPromise = this.loadActorState(entry);\n\t\treturn entry.loadPromise;\n\t}\n\n\tprivate async loadActorState(entry: ActorEntry) {\n\t\tconst stateFilePath = this.getActorStatePath(entry.id);\n\n\t\t// Read & parse file\n\t\ttry {\n\t\t\tconst stateData = await fs.readFile(stateFilePath);\n\n\t\t\t// Cache the loaded state in handler\n\t\t\tentry.state = ACTOR_STATE_VERSIONED.deserializeWithEmbeddedVersion(\n\t\t\t\tnew Uint8Array(stateData),\n\t\t\t);\n\n\t\t\treturn entry;\n\t\t} catch (innerError: any) {\n\t\t\t// File does not exist, meaning the actor does not exist\n\t\t\tif (innerError.code === \"ENOENT\") {\n\t\t\t\tentry.loadPromise = undefined;\n\t\t\t\treturn entry;\n\t\t\t}\n\n\t\t\t// For other errors, throw\n\t\t\tconst error = new Error(`Failed to load actor state: ${innerError}`);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync loadOrCreateActor(\n\t\tactorId: string,\n\t\tname: string,\n\t\tkey: ActorKey,\n\t\tinput: unknown | undefined,\n\t): Promise<ActorEntry> {\n\t\t// Attempt to load actor\n\t\tconst entry = await this.loadActor(actorId);\n\n\t\t// If no state for this actor, then create & write state\n\t\tif (!entry.state) {\n\t\t\tentry.state = {\n\t\t\t\tactorId,\n\t\t\t\tname,\n\t\t\t\tkey: key as readonly string[],\n\t\t\t\tcreatedAt: BigInt(Date.now()),\n\t\t\t\tpersistedData: bufferToArrayBuffer(serializeEmptyPersistData(input)),\n\t\t\t};\n\t\t\tawait this.writeActor(actorId, entry.state);\n\t\t}\n\t\treturn entry;\n\t}\n\n\tasync sleepActor(actorId: string) {\n\t\tinvariant(\n\t\t\tthis.#persist,\n\t\t\t\"cannot sleep actor with memory driver, must use file system driver\",\n\t\t);\n\n\t\tconst actor = this.#actors.get(actorId);\n\t\tinvariant(actor, `tried to sleep ${actorId}, does not exist`);\n\n\t\t// Wait for actor to fully start before stopping it to avoid race conditions\n\t\tif (actor.loadPromise) await actor.loadPromise.catch();\n\t\tif (actor.startPromise?.promise) await actor.startPromise.promise.catch();\n\n\t\t// Mark as removed\n\t\tactor.removed = true;\n\n\t\t// Stop actor\n\t\tinvariant(actor.actor, \"actor should be loaded\");\n\t\tawait actor.actor._stop();\n\n\t\t// Remove from map after stop is complete\n\t\tthis.#actors.delete(actorId);\n\t}\n\n\t/**\n\t * Save actor state to disk.\n\t */\n\tasync writeActor(actorId: string, state: schema.ActorState): Promise<void> {\n\t\tif (!this.#persist) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst entry = this.#actors.get(actorId);\n\t\tinvariant(entry, \"actor entry does not exist\");\n\n\t\tawait this.#performWrite(actorId, state);\n\t}\n\n\tasync setActorAlarm(actorId: string, timestamp: number) {\n\t\tconst entry = this.#actors.get(actorId);\n\t\tinvariant(entry, \"actor entry does not exist\");\n\n\t\t// Persist alarm to disk\n\t\tif (this.#persist) {\n\t\t\tconst alarmPath = this.getActorAlarmPath(actorId);\n\t\t\tconst tempPath = `${alarmPath}.tmp.${crypto.randomUUID()}`;\n\t\t\ttry {\n\t\t\t\tawait ensureDirectoryExists(path.dirname(alarmPath));\n\t\t\t\tconst alarmData: schema.ActorAlarm = {\n\t\t\t\t\tactorId,\n\t\t\t\t\ttimestamp: BigInt(timestamp),\n\t\t\t\t};\n\t\t\t\tconst data =\n\t\t\t\t\tACTOR_ALARM_VERSIONED.serializeWithEmbeddedVersion(alarmData);\n\t\t\t\tawait fs.writeFile(tempPath, data);\n\t\t\t\tawait fs.rename(tempPath, alarmPath);\n\t\t\t} catch (error) {\n\t\t\t\ttry {\n\t\t\t\t\tawait fs.unlink(tempPath);\n\t\t\t\t} catch {}\n\t\t\t\tlogger().error({ msg: \"failed to write alarm\", actorId, error });\n\t\t\t\tthrow new Error(`Failed to write alarm: ${error}`);\n\t\t\t}\n\t\t}\n\n\t\t// Schedule timeout\n\t\tthis.#scheduleAlarmTimeout(actorId, timestamp);\n\t}\n\n\t/**\n\t * Perform the actual write operation with atomic writes\n\t */\n\tasync #performWrite(\n\t\tactorId: string,\n\t\tstate: schema.ActorState,\n\t): Promise<void> {\n\t\tconst dataPath = this.getActorStatePath(actorId);\n\t\t// Generate unique temp filename to prevent any race conditions\n\t\tconst tempPath = `${dataPath}.tmp.${crypto.randomUUID()}`;\n\n\t\ttry {\n\t\t\t// Create directory if needed\n\t\t\tawait ensureDirectoryExists(path.dirname(dataPath));\n\n\t\t\t// Convert to BARE types for serialization\n\t\t\tconst bareState: schema.ActorState = {\n\t\t\t\tactorId: state.actorId,\n\t\t\t\tname: state.name,\n\t\t\t\tkey: state.key,\n\t\t\t\tcreatedAt: state.createdAt,\n\t\t\t\tpersistedData: state.persistedData,\n\t\t\t};\n\n\t\t\t// Perform atomic write\n\t\t\tconst serializedState =\n\t\t\t\tACTOR_STATE_VERSIONED.serializeWithEmbeddedVersion(bareState);\n\t\t\tawait fs.writeFile(tempPath, serializedState);\n\t\t\tawait fs.rename(tempPath, dataPath);\n\t\t} catch (error) {\n\t\t\t// Cleanup temp file on error\n\t\t\ttry {\n\t\t\t\tawait fs.unlink(tempPath);\n\t\t\t} catch {\n\t\t\t\t// Ignore cleanup errors\n\t\t\t}\n\t\t\tlogger().error({ msg: \"failed to save actor state\", actorId, error });\n\t\t\tthrow new Error(`Failed to save actor state: ${error}`);\n\t\t}\n\t}\n\n\t/**\n\t * Call this method after the actor driver has been initiated.\n\t *\n\t * This will trigger all initial alarms from the file system.\n\t *\n\t * This needs to be sync since DriverConfig.actor is sync\n\t */\n\tonRunnerStart(\n\t\tregistryConfig: RegistryConfig,\n\t\trunConfig: RunConfig,\n\t\tinlineClient: AnyClient,\n\t\tactorDriver: ActorDriver,\n\t) {\n\t\tif (this.#runnerParams) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Save runner params for future use\n\t\tthis.#runnerParams = {\n\t\t\tregistryConfig,\n\t\t\trunConfig,\n\t\t\tinlineClient,\n\t\t\tactorDriver,\n\t\t};\n\n\t\t// Load alarms from disk and schedule timeouts\n\t\ttry {\n\t\t\tthis.#loadAlarmsSync();\n\t\t} catch (err) {\n\t\t\tlogger().error({ msg: \"failed to load alarms on startup\", error: err });\n\t\t}\n\t}\n\n\tasync startActor(\n\t\tregistryConfig: RegistryConfig,\n\t\trunConfig: RunConfig,\n\t\tinlineClient: AnyClient,\n\t\tactorDriver: ActorDriver,\n\t\tactorId: string,\n\t): Promise<AnyActorInstance> {\n\t\t// Get the actor metadata\n\t\tconst entry = await this.loadActor(actorId);\n\t\tif (!entry.state) {\n\t\t\tthrow new Error(\n\t\t\t\t`Actor does not exist and cannot be started: \"${actorId}\"`,\n\t\t\t);\n\t\t}\n\n\t\t// Actor already starting\n\t\tif (entry.startPromise) {\n\t\t\tawait entry.startPromise.promise;\n\t\t\tinvariant(entry.actor, \"actor should have loaded\");\n\t\t\treturn entry.actor;\n\t\t}\n\n\t\t// Actor already loaded\n\t\tif (entry.actor) {\n\t\t\treturn entry.actor;\n\t\t}\n\n\t\t// Create start promise\n\t\tentry.startPromise = Promise.withResolvers();\n\n\t\ttry {\n\t\t\t// Create actor\n\t\t\tconst definition = lookupInRegistry(registryConfig, entry.state.name);\n\t\t\tentry.actor = definition.instantiate();\n\n\t\t\t// Start actor\n\t\t\tconst connDrivers = createGenericConnDrivers(\n\t\t\t\tentry.genericConnGlobalState,\n\t\t\t);\n\t\t\tawait entry.actor.start(\n\t\t\t\tconnDrivers,\n\t\t\t\tactorDriver,\n\t\t\t\tinlineClient,\n\t\t\t\tactorId,\n\t\t\t\tentry.state.name,\n\t\t\t\tentry.state.key as string[],\n\t\t\t\t\"unknown\",\n\t\t\t);\n\n\t\t\t// Finish\n\t\t\tentry.startPromise.resolve();\n\t\t\tentry.startPromise = undefined;\n\n\t\t\treturn entry.actor;\n\t\t} catch (innerError) {\n\t\t\tconst error = new Error(\n\t\t\t\t`Failed to start actor ${actorId}: ${innerError}`,\n\t\t\t\t{ cause: innerError },\n\t\t\t);\n\t\t\tentry.startPromise?.reject(error);\n\t\t\tentry.startPromise = undefined;\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync loadActorStateOrError(actorId: string): Promise<schema.ActorState> {\n\t\tconst state = (await this.loadActor(actorId)).state;\n\t\tif (!state) throw new Error(`Actor does not exist: ${actorId}`);\n\t\treturn state;\n\t}\n\n\tgetActorOrError(actorId: string): ActorEntry {\n\t\tconst entry = this.#actors.get(actorId);\n\t\tif (!entry) throw new Error(`No entry for actor: ${actorId}`);\n\t\treturn entry;\n\t}\n\n\tasync createDatabase(actorId: string): Promise<string | undefined> {\n\t\treturn this.getActorDbPath(actorId);\n\t}\n\n\t/**\n\t * Load all persisted alarms from disk and schedule their timers.\n\t */\n\t#loadAlarmsSync(): void {\n\t\ttry {\n\t\t\tconst files = fsSync.existsSync(this.#alarmsDir)\n\t\t\t\t? fsSync.readdirSync(this.#alarmsDir)\n\t\t\t\t: [];\n\t\t\tfor (const file of files) {\n\t\t\t\t// Skip temp files\n\t\t\t\tif (file.includes(\".tmp.\")) continue;\n\t\t\t\tconst fullPath = path.join(this.#alarmsDir, file);\n\t\t\t\ttry {\n\t\t\t\t\tconst buf = fsSync.readFileSync(fullPath);\n\t\t\t\t\tconst alarmData =\n\t\t\t\t\t\tACTOR_ALARM_VERSIONED.deserializeWithEmbeddedVersion(\n\t\t\t\t\t\t\tnew Uint8Array(buf),\n\t\t\t\t\t\t);\n\t\t\t\t\tconst timestamp = Number(alarmData.timestamp);\n\t\t\t\t\tif (Number.isFinite(timestamp)) {\n\t\t\t\t\t\tthis.#scheduleAlarmTimeout(alarmData.actorId, timestamp);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger().debug({ msg: \"invalid alarm file contents\", file });\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\tlogger().error({\n\t\t\t\t\t\tmsg: \"failed to read alarm file\",\n\t\t\t\t\t\tfile,\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} catch (err) {\n\t\t\tlogger().error({ msg: \"failed to list alarms directory\", error: err });\n\t\t}\n\t}\n\n\t/**\n\t * Schedule an alarm timer for an actor without writing to disk.\n\t */\n\t#scheduleAlarmTimeout(actorId: string, timestamp: number) {\n\t\tconst entry = this.#upsertEntry(actorId);\n\n\t\t// If there's already an earlier alarm scheduled, do not override it.\n\t\tif (\n\t\t\tentry.alarmTimestamp !== undefined &&\n\t\t\ttimestamp >= entry.alarmTimestamp\n\t\t) {\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"skipping alarm schedule (later than existing)\",\n\t\t\t\tactorId,\n\t\t\t\ttimestamp,\n\t\t\t\tcurrent: entry.alarmTimestamp,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tlogger().debug({ msg: \"scheduling alarm\", actorId, timestamp });\n\n\t\t// Cancel existing timeout and update the current scheduled timestamp\n\t\tentry.alarmTimeout?.abort();\n\t\tentry.alarmTimestamp = timestamp;\n\n\t\tconst delay = Math.max(0, timestamp - Date.now());\n\t\tentry.alarmTimeout = setLongTimeout(async () => {\n\t\t\t// Clear currently scheduled timestamp as this alarm is firing now\n\t\t\tentry.alarmTimestamp = undefined;\n\t\t\t// On trigger: remove persisted alarm file\n\t\t\tif (this.#persist) {\n\t\t\t\ttry {\n\t\t\t\t\tawait fs.unlink(this.getActorAlarmPath(actorId));\n\t\t\t\t} catch (err: any) {\n\t\t\t\t\tif (err?.code !== \"ENOENT\") {\n\t\t\t\t\t\tlogger().debug({\n\t\t\t\t\t\t\tmsg: \"failed to remove alarm file\",\n\t\t\t\t\t\t\tactorId,\n\t\t\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tlogger().debug({ msg: \"triggering alarm\", actorId, timestamp });\n\n\t\t\t\t// Ensure actor state exists and start actor if needed\n\t\t\t\tconst loaded = await this.loadActor(actorId);\n\t\t\t\tif (!loaded.state) throw new Error(`Actor does not exist: ${actorId}`);\n\n\t\t\t\t// Start actor if not already running\n\t\t\t\tconst runnerParams = this.#runnerParams;\n\t\t\t\tinvariant(runnerParams, \"missing runner params\");\n\t\t\t\tif (!loaded.actor) {\n\t\t\t\t\tawait this.startActor(\n\t\t\t\t\t\trunnerParams.registryConfig,\n\t\t\t\t\t\trunnerParams.runConfig,\n\t\t\t\t\t\trunnerParams.inlineClient,\n\t\t\t\t\t\trunnerParams.actorDriver,\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tinvariant(loaded.actor, \"actor should be loaded after wake\");\n\t\t\t\tawait loaded.actor._onAlarm();\n\t\t\t} catch (err) {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"failed to handle alarm\",\n\t\t\t\t\tactorId,\n\t\t\t\t\terror: stringifyError(err),\n\t\t\t\t});\n\t\t\t}\n\t\t}, delay);\n\t}\n\n\tgetOrCreateInspectorAccessToken(): string {\n\t\tconst tokenPath = path.join(this.#storagePath, \"inspector-token\");\n\t\tif (fsSync.existsSync(tokenPath)) {\n\t\t\treturn fsSync.readFileSync(tokenPath, \"utf-8\");\n\t\t}\n\n\t\tconst newToken = generateRandomString();\n\t\tfsSync.writeFileSync(tokenPath, newToken);\n\t\treturn newToken;\n\t}\n\n\t/**\n\t * Cleanup stale temp files on startup (synchronous)\n\t */\n\t#cleanupTempFilesSync(): void {\n\t\ttry {\n\t\t\tconst files = fsSync.readdirSync(this.#stateDir);\n\t\t\tconst tempFiles = files.filter((f) => f.includes(\".tmp.\"));\n\n\t\t\tconst oneHourAgo = Date.now() - 3600000; // 1 hour in ms\n\n\t\t\tfor (const tempFile of tempFiles) {\n\t\t\t\ttry {\n\t\t\t\t\tconst fullPath = path.join(this.#stateDir, tempFile);\n\t\t\t\t\tconst stat = fsSync.statSync(fullPath);\n\n\t\t\t\t\t// Remove if older than 1 hour\n\t\t\t\t\tif (stat.mtimeMs < oneHourAgo) {\n\t\t\t\t\t\tfsSync.unlinkSync(fullPath);\n\t\t\t\t\t\tlogger().info({\n\t\t\t\t\t\t\tmsg: \"cleaned up stale temp file\",\n\t\t\t\t\t\t\tfile: tempFile,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\tlogger().debug({\n\t\t\t\t\t\tmsg: \"failed to cleanup temp file\",\n\t\t\t\t\t\tfile: tempFile,\n\t\t\t\t\t\terror: err,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tlogger().error({\n\t\t\t\tmsg: \"failed to read actors directory for cleanup\",\n\t\t\t\terror: err,\n\t\t\t});\n\t\t}\n\t}\n}\n","import * as bare from \"@bare-ts/lib\"\n\nconst config = /* @__PURE__ */ bare.Config({})\n\nexport type u64 = bigint\nexport type uint = bigint\n\nfunction read0(bc: bare.ByteCursor): readonly string[] {\n const len = bare.readUintSafe(bc)\n if (len === 0) { return [] }\n const result = [bare.readString(bc)]\n for (let i = 1; i < len; i++) {\n result[i] = bare.readString(bc)\n }\n return result\n}\n\nfunction write0(bc: bare.ByteCursor, x: readonly string[]): void {\n bare.writeUintSafe(bc, x.length)\n for (let i = 0; i < x.length; i++) {\n bare.writeString(bc, x[i])\n }\n}\n\nexport type ActorState = {\n readonly actorId: string,\n readonly name: string,\n readonly key: readonly string[],\n readonly persistedData: ArrayBuffer,\n readonly createdAt: u64,\n}\n\nexport function readActorState(bc: bare.ByteCursor): ActorState {\n return {\n actorId: bare.readString(bc),\n name: bare.readString(bc),\n key: read0(bc),\n persistedData: bare.readData(bc),\n createdAt: bare.readU64(bc),\n }\n}\n\nexport function writeActorState(bc: bare.ByteCursor, x: ActorState): void {\n bare.writeString(bc, x.actorId)\n bare.writeString(bc, x.name)\n write0(bc, x.key)\n bare.writeData(bc, x.persistedData)\n bare.writeU64(bc, x.createdAt)\n}\n\nexport function encodeActorState(x: ActorState): Uint8Array {\n const bc = new bare.ByteCursor(\n new Uint8Array(config.initialBufferLength),\n config\n )\n writeActorState(bc, x)\n return new Uint8Array(bc.view.buffer, bc.view.byteOffset, bc.offset)\n}\n\nexport function decodeActorState(bytes: Uint8Array): ActorState {\n const bc = new bare.ByteCursor(bytes, config)\n const result = readActorState(bc)\n if (bc.offset < bc.view.byteLength) {\n throw new bare.BareError(bc.offset, \"remaining bytes\")\n }\n return result\n}\n\nexport type ActorAlarm = {\n readonly actorId: string,\n readonly timestamp: uint,\n}\n\nexport function readActorAlarm(bc: bare.ByteCursor): ActorAlarm {\n return {\n actorId: bare.readString(bc),\n timestamp: bare.readUint(bc),\n }\n}\n\nexport function writeActorAlarm(bc: bare.ByteCursor, x: ActorAlarm): void {\n bare.writeString(bc, x.actorId)\n bare.writeUint(bc, x.timestamp)\n}\n\nexport function encodeActorAlarm(x: ActorAlarm): Uint8Array {\n const bc = new bare.ByteCursor(\n new Uint8Array(config.initialBufferLength),\n config\n )\n writeActorAlarm(bc, x)\n return new Uint8Array(bc.view.buffer, bc.view.byteOffset, bc.offset)\n}\n\nexport function decodeActorAlarm(bytes: Uint8Array): ActorAlarm {\n const bc = new bare.ByteCursor(bytes, config)\n const result = readActorAlarm(bc)\n if (bc.offset < bc.view.byteLength) {\n throw new bare.BareError(bc.offset, \"remaining bytes\")\n }\n return result\n}\n","import {\n\tcreateVersionedDataHandler,\n\ttype MigrationFn,\n} from \"@/common/versioned-data\";\nimport * as v1 from \"../../../dist/schemas/file-system-driver/v1\";\n\nexport const CURRENT_VERSION = 1;\n\nexport type CurrentActorState = v1.ActorState;\nexport type CurrentActorAlarm = v1.ActorAlarm;\n\nconst migrations = new Map<number, MigrationFn<any, any>>();\n\nexport const ACTOR_STATE_VERSIONED =\n\tcreateVersionedDataHandler<CurrentActorState>({\n\t\tcurrentVersion: CURRENT_VERSION,\n\t\tmigrations,\n\t\tserializeVersion: (data) => v1.encodeActorState(data),\n\t\tdeserializeVersion: (bytes) => v1.decodeActorState(bytes),\n\t});\n\nexport const ACTOR_ALARM_VERSIONED =\n\tcreateVersionedDataHandler<CurrentActorAlarm>({\n\t\tcurrentVersion: CURRENT_VERSION,\n\t\tmigrations,\n\t\tserializeVersion: (data) => v1.encodeActorAlarm(data),\n\t\tdeserializeVersion: (bytes) => v1.decodeActorAlarm(bytes),\n\t});\n","import { getLogger } from \"@/common/log\";\n\nexport function logger() {\n\treturn getLogger(\"driver-fs\");\n}\n","import * as crypto from \"node:crypto\";\nimport * as fsSync from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport type { ActorKey } from \"@/actor/mod\";\n\n/**\n * Generate a deterministic actor ID from name and key\n */\nexport function generateActorId(name: string, key: ActorKey): string {\n\t// Generate deterministic key string\n\tconst jsonString = JSON.stringify([name, key]);\n\n\t// Hash to ensure safe file system names\n\tconst hash = crypto\n\t\t.createHash(\"sha256\")\n\t\t.update(jsonString)\n\t\t.digest(\"hex\")\n\t\t.substring(0, 16);\n\n\treturn hash;\n}\n\n/**\n * Create a hash for a path, normalizing it first\n */\nfunction createHashForPath(dirPath: string): string {\n\t// Normalize the path first\n\tconst normalizedPath = path.normalize(dirPath);\n\n\t// Extract the last path component for readability\n\tconst lastComponent = path.basename(normalizedPath);\n\n\t// Create SHA-256 hash\n\tconst hash = crypto\n\t\t.createHash(\"sha256\")\n\t\t.update(normalizedPath)\n\t\t.digest(\"hex\")\n\t\t.substring(0, 8); // Take first 8 characters for brevity\n\n\treturn `${lastComponent}-${hash}`;\n}\n\n/**\n * Get the storage path for the current working directory or a specified path\n */\nexport function getStoragePath(customPath?: string): string {\n\tconst dataPath = getDataPath(\"rivetkit\");\n\tconst pathToHash = customPath || process.cwd();\n\tconst dirHash = createHashForPath(pathToHash);\n\treturn path.join(dataPath, dirHash);\n}\n\n/**\n * Check if a path exists\n */\nexport async function pathExists(path: string): Promise<boolean> {\n\ttry {\n\t\tawait fs.access(path);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Ensure a directory exists, creating it if necessary\n */\nexport async function ensureDirectoryExists(\n\tdirectoryPath: string,\n): Promise<void> {\n\tif (!(await pathExists(directoryPath))) {\n\t\tawait fs.mkdir(directoryPath, { recursive: true });\n\t}\n}\n\n/**\n * Ensure a directory exists synchronously - only used during initialization\n * All other operations use the async version\n */\nexport function ensureDirectoryExistsSync(directoryPath: string): void {\n\tif (!fsSync.existsSync(directoryPath)) {\n\t\tfsSync.mkdirSync(directoryPath, { recursive: true });\n\t}\n}\n\n/**\n * Returns platform-specific data directory\n */\nfunction getDataPath(appName: string): string {\n\tconst platform = process.platform;\n\tconst homeDir = os.homedir();\n\n\tswitch (platform) {\n\t\tcase \"win32\":\n\t\t\treturn path.join(\n\t\t\t\tprocess.env.APPDATA || path.join(homeDir, \"AppData\", \"Roaming\"),\n\t\t\t\tappName,\n\t\t\t);\n\t\tcase \"darwin\":\n\t\t\treturn path.join(homeDir, \"Library\", \"Application Support\", appName);\n\t\tdefault: // linux and others\n\t\t\treturn path.join(\n\t\t\t\tprocess.env.XDG_DATA_HOME || path.join(homeDir, \".local\", \"share\"),\n\t\t\t\tappName,\n\t\t\t);\n\t}\n}\n","import type { Context as HonoContext } from \"hono\";\nimport invariant from \"invariant\";\nimport { type ActorRouter, createActorRouter } from \"@/actor/router\";\nimport {\n\thandleRawWebSocketHandler,\n\thandleWebSocketConnect,\n} from \"@/actor/router-endpoints\";\nimport { createClientWithDriver } from \"@/client/client\";\nimport { InlineWebSocketAdapter2 } from \"@/common/inline-websocket-adapter2\";\nimport { noopNext } from \"@/common/utils\";\nimport type {\n\tActorDriver,\n\tActorOutput,\n\tCreateInput,\n\tGetForIdInput,\n\tGetOrCreateWithKeyInput,\n\tGetWithKeyInput,\n\tManagerDriver,\n} from \"@/driver-helpers/mod\";\nimport { ManagerInspector } from \"@/inspector/manager\";\nimport { type Actor, ActorFeature, type ActorId } from \"@/inspector/mod\";\nimport type { ManagerDisplayInformation } from \"@/manager/driver\";\nimport {\n\ttype DriverConfig,\n\ttype Encoding,\n\tPATH_CONNECT_WEBSOCKET,\n\tPATH_RAW_WEBSOCKET_PREFIX,\n\ttype RegistryConfig,\n\ttype RunConfig,\n\ttype UniversalWebSocket,\n} from \"@/mod\";\nimport type * as schema from \"@/schemas/file-system-driver/mod\";\nimport type { FileSystemGlobalState } from \"./global-state\";\nimport { logger } from \"./log\";\nimport { generateActorId } from \"./utils\";\n\nexport class FileSystemManagerDriver implements ManagerDriver {\n\t#registryConfig: RegistryConfig;\n\t#runConfig: RunConfig;\n\t#state: FileSystemGlobalState;\n\t#driverConfig: DriverConfig;\n\n\t#actorDriver: ActorDriver;\n\t#actorRouter: ActorRouter;\n\n\tinspector?: ManagerInspector;\n\n\tconstructor(\n\t\tregistryConfig: RegistryConfig,\n\t\trunConfig: RunConfig,\n\t\tstate: FileSystemGlobalState,\n\t\tdriverConfig: DriverConfig,\n\t) {\n\t\tthis.#registryConfig = registryConfig;\n\t\tthis.#runConfig = runConfig;\n\t\tthis.#state = state;\n\t\tthis.#driverConfig = driverConfig;\n\n\t\tif (runConfig.inspector.enabled) {\n\t\t\tif (!this.#runConfig.inspector.token()) {\n\t\t\t\tthis.#runConfig.inspector.token = () =>\n\t\t\t\t\tthis.#state.getOrCreateInspectorAccessToken();\n\t\t\t}\n\t\t\tconst startedAt = new Date().toISOString();\n\t\t\tfunction transformActor(actorState: schema.ActorState): Actor {\n\t\t\t\treturn {\n\t\t\t\t\tid: actorState.actorId as ActorId,\n\t\t\t\t\tname: actorState.name,\n\t\t\t\t\tkey: actorState.key as string[],\n\t\t\t\t\tstartedAt: startedAt,\n\t\t\t\t\tcreatedAt: new Date(Number(actorState.createdAt)).toISOString(),\n\t\t\t\t\tfeatures: [\n\t\t\t\t\t\tActorFeature.State,\n\t\t\t\t\t\tActorFeature.Connections,\n\t\t\t\t\t\tActorFeature.Console,\n\t\t\t\t\t\tActorFeature.EventsMonitoring,\n\t\t\t\t\t\tActorFeature.Database,\n\t\t\t\t\t],\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tthis.inspector = new ManagerInspector(() => {\n\t\t\t\treturn {\n\t\t\t\t\tgetAllActors: async ({ cursor, limit }) => {\n\t\t\t\t\t\tconst itr = this.#state.getActorsIterator({ cursor });\n\t\t\t\t\t\tconst actors: Actor[] = [];\n\n\t\t\t\t\t\tfor await (const actor of itr) {\n\t\t\t\t\t\t\tactors.push(transformActor(actor));\n\t\t\t\t\t\t\tif (limit && actors.length >= limit) {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn actors;\n\t\t\t\t\t},\n\t\t\t\t\tgetActorById: async (id) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await this.#state.loadActorStateOrError(id);\n\t\t\t\t\t\t\treturn transformActor(result);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tgetBuilds: async () => {\n\t\t\t\t\t\treturn Object.keys(this.#registryConfig.use).map((name) => ({\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t}));\n\t\t\t\t\t},\n\t\t\t\t\tcreateActor: async (input) => {\n\t\t\t\t\t\tconst { actorId } = await this.createActor(input);\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await this.#state.loadActorStateOrError(actorId);\n\t\t\t\t\t\t\treturn transformActor(result);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t});\n\t\t}\n\n\t\t// Actors run on the same node as the manager, so we create a dummy actor router that we route requests to\n\t\tconst inlineClient = createClientWithDriver(this);\n\t\tthis.#actorDriver = this.#driverConfig.actor(\n\t\t\tregistryConfig,\n\t\t\trunConfig,\n\t\t\tthis,\n\t\t\tinlineClient,\n\t\t);\n\t\tthis.#actorRouter = createActorRouter(this.#runConfig, this.#actorDriver);\n\t}\n\n\tasync sendRequest(actorId: string, actorRequest: Request): Promise<Response> {\n\t\treturn await this.#actorRouter.fetch(actorRequest, {\n\t\t\tactorId,\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// Handle raw WebSocket paths\n\t\tconst pathOnly = path.split(\"?\")[0];\n\t\tconst normalizedPath = pathOnly.startsWith(\"/\") ? pathOnly : `/${pathOnly}`;\n\t\tif (normalizedPath === PATH_CONNECT_WEBSOCKET) {\n\t\t\t// Handle standard connect\n\t\t\tconst wsHandler = await handleWebSocketConnect(\n\t\t\t\tundefined,\n\t\t\t\tthis.#runConfig,\n\t\t\t\tthis.#actorDriver,\n\t\t\t\tactorId,\n\t\t\t\tencoding,\n\t\t\t\tparams,\n\t\t\t\tundefined,\n\t\t\t);\n\t\t\treturn new InlineWebSocketAdapter2(wsHandler);\n\t\t} else if (\n\t\t\tnormalizedPath.startsWith(PATH_RAW_WEBSOCKET_PREFIX) ||\n\t\t\tnormalizedPath === \"/raw/websocket\"\n\t\t) {\n\t\t\t// Handle websocket proxy\n\t\t\t// Use the full path with query parameters\n\t\t\tconst wsHandler = await handleRawWebSocketHandler(\n\t\t\t\tundefined,\n\t\t\t\tpath,\n\t\t\t\tthis.#actorDriver,\n\t\t\t\tactorId,\n\t\t\t\tundefined,\n\t\t\t);\n\t\t\treturn new InlineWebSocketAdapter2(wsHandler);\n\t\t} else {\n\t\t\tthrow new Error(`Unreachable path: ${path}`);\n\t\t}\n\t}\n\n\tasync proxyRequest(\n\t\tc: HonoContext,\n\t\tactorRequest: Request,\n\t\tactorId: string,\n\t): Promise<Response> {\n\t\treturn await this.#actorRouter.fetch(actorRequest, {\n\t\t\tactorId,\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\tconnParams: unknown,\n\t): Promise<Response> {\n\t\tconst upgradeWebSocket = this.#runConfig.getUpgradeWebSocket?.();\n\t\tinvariant(upgradeWebSocket, \"missing getUpgradeWebSocket\");\n\n\t\t// Handle raw WebSocket paths\n\t\tconst pathOnly = path.split(\"?\")[0];\n\t\tconst normalizedPath = pathOnly.startsWith(\"/\") ? pathOnly : `/${pathOnly}`;\n\t\tif (normalizedPath === PATH_CONNECT_WEBSOCKET) {\n\t\t\t// Handle standard connect\n\t\t\tconst wsHandler = await handleWebSocketConnect(\n\t\t\t\tc.req.raw,\n\t\t\t\tthis.#runConfig,\n\t\t\t\tthis.#actorDriver,\n\t\t\t\tactorId,\n\t\t\t\tencoding,\n\t\t\t\tconnParams,\n\t\t\t\tundefined,\n\t\t\t);\n\t\t\treturn upgradeWebSocket(() => wsHandler)(c, noopNext());\n\t\t} else if (\n\t\t\tnormalizedPath.startsWith(PATH_RAW_WEBSOCKET_PREFIX) ||\n\t\t\tnormalizedPath === \"/raw/websocket\"\n\t\t) {\n\t\t\t// Handle websocket proxy\n\t\t\t// Use the full path with query parameters\n\t\t\tconst wsHandler = await handleRawWebSocketHandler(\n\t\t\t\tc.req.raw,\n\t\t\t\tpath,\n\t\t\t\tthis.#actorDriver,\n\t\t\t\tactorId,\n\t\t\t\tundefined,\n\t\t\t);\n\t\t\treturn upgradeWebSocket(() => wsHandler)(c, noopNext());\n\t\t} else {\n\t\t\tthrow new Error(`Unreachable path: ${path}`);\n\t\t}\n\t}\n\n\tasync getForId({ actorId }: GetForIdInput): Promise<ActorOutput | undefined> {\n\t\t// Validate the actor exists\n\t\tconst actor = await this.#state.loadActor(actorId);\n\t\tif (!actor.state) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\ttry {\n\t\t\t// Load actor state\n\t\t\treturn {\n\t\t\t\tactorId,\n\t\t\t\tname: actor.state.name,\n\t\t\t\tkey: actor.state.key as string[],\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tlogger().error({ msg: \"failed to read actor state\", actorId, error });\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tasync getWithKey({\n\t\tname,\n\t\tkey,\n\t}: GetWithKeyInput): Promise<ActorOutput | undefined> {\n\t\t// Generate the deterministic actor ID\n\t\tconst actorId = generateActorId(name, key);\n\n\t\t// Check if actor exists\n\t\tconst actor = await this.#state.loadActor(actorId);\n\t\tif (actor.state) {\n\t\t\treturn {\n\t\t\t\tactorId,\n\t\t\t\tname,\n\t\t\t\tkey,\n\t\t\t};\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\tasync getOrCreateWithKey(\n\t\tinput: GetOrCreateWithKeyInput,\n\t): Promise<ActorOutput> {\n\t\t// Generate the deterministic actor ID\n\t\tconst actorId = generateActorId(input.name, input.key);\n\n\t\t// Use the atomic getOrCreateActor method\n\t\tconst actorEntry = await this.#state.loadOrCreateActor(\n\t\t\tactorId,\n\t\t\tinput.name,\n\t\t\tinput.key,\n\t\t\tinput.input,\n\t\t);\n\t\tinvariant(actorEntry.state, \"must have state\");\n\n\t\treturn {\n\t\t\tactorId: actorEntry.state.actorId,\n\t\t\tname: actorEntry.state.name,\n\t\t\tkey: actorEntry.state.key as string[],\n\t\t};\n\t}\n\n\tasync createActor({ name, key, input }: CreateInput): Promise<ActorOutput> {\n\t\t// Generate the deterministic actor ID\n\t\tconst actorId = generateActorId(name, key);\n\n\t\tawait this.#state.createActor(actorId, name, key, input);\n\n\t\treturn {\n\t\t\tactorId,\n\t\t\tname,\n\t\t\tkey,\n\t\t};\n\t}\n\n\tdisplayInformation(): ManagerDisplayInformation {\n\t\treturn {\n\t\t\tname: this.#state.persist ? \"File System\" : \"Memory\",\n\t\t\tproperties: {\n\t\t\t\t...(this.#state.persist ? { Data: this.#state.storagePath } : {}),\n\t\t\t\tInstances: this.#state.actorCountOnStartup.toString(),\n\t\t\t},\n\t\t};\n\t}\n\n\textraStartupLog() {\n\t\treturn {\n\t\t\tinstances: this.#state.actorCountOnStartup,\n\t\t\tdata: this.#state.storagePath,\n\t\t};\n\t}\n}\n","import { sValidator } from \"@hono/standard-validator\";\nimport { Hono } from \"hono\";\nimport invariant from \"invariant\";\nimport type { CreateInput } from \"@/manager/driver\";\nimport { inspectorLogger } from \"./log\";\nimport { type Actor, type Builds, CreateActorSchema } from \"./protocol/common\";\n\nexport type ManagerInspectorRouterEnv = {\n\tVariables: {\n\t\tinspector: ManagerInspector;\n\t};\n};\n\n/**\n * Create a router for the Manager Inspector.\n * @internal\n */\nexport function createManagerInspectorRouter() {\n\treturn new Hono<ManagerInspectorRouterEnv>()\n\t\t.get(\"/ping\", (c) => {\n\t\t\treturn c.json({ message: \"pong\" }, 200);\n\t\t})\n\t\t.get(\"/actors\", async (c) => {\n\t\t\tconst limit = Number.parseInt(c.req.query(\"limit\") ?? \"\") || undefined;\n\t\t\tconst cursor = c.req.query(\"cursor\") || undefined;\n\n\t\t\tif (!limit || (limit && limit <= 0)) {\n\t\t\t\treturn c.json(\"Invalid limit\", 400);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst actors = await c.var.inspector.accessors.getAllActors({\n\t\t\t\t\tlimit,\n\t\t\t\t\tcursor,\n\t\t\t\t});\n\t\t\t\treturn c.json(actors, 200);\n\t\t\t} catch (error) {\n\t\t\t\tinspectorLogger().error({ msg: \"Failed to fetch actors\", error });\n\t\t\t\treturn c.json(\"Failed to fetch actors\", 500);\n\t\t\t}\n\t\t})\n\n\t\t.post(\"/actors\", sValidator(\"json\", CreateActorSchema), async (c) => {\n\t\t\tconst actor = await c.var.inspector.accessors.createActor(\n\t\t\t\tc.req.valid(\"json\"),\n\t\t\t);\n\t\t\treturn c.json(actor, 201);\n\t\t})\n\t\t.get(\"/builds\", async (c) => {\n\t\t\tconst builds = await c.var.inspector.accessors.getBuilds();\n\t\t\treturn c.json(builds, 200);\n\t\t})\n\t\t.get(\"/actor/:id\", async (c) => {\n\t\t\tconst id = c.req.param(\"id\");\n\t\t\tconst actor = await c.var.inspector.accessors.getActorById(id);\n\t\t\tif (!actor) {\n\t\t\t\treturn c.json({ error: \"Actor not found\" }, 404);\n\t\t\t}\n\t\t\treturn c.json(actor, 200);\n\t\t})\n\t\t.get(\"/bootstrap\", async (c) => {\n\t\t\tconst actors = await c.var.inspector.accessors.getAllActors({\n\t\t\t\tlimit: 10,\n\t\t\t});\n\t\t\treturn c.json({ actors }, 200);\n\t\t});\n}\n\ninterface ManagerInspectorAccessors {\n\tgetAllActors: (param: { cursor?: string; limit: number }) => Promise<Actor[]>;\n\tgetActorById: (id: string) => Promise<Actor | null>;\n\tgetBuilds: () => Promise<Builds>;\n\tcreateActor: (input: CreateInput) => Promise<Actor | null>;\n}\n\n/**\n * Provides a unified interface for inspecting actor external and internal state.\n */\nexport class ManagerInspector {\n\tpublic readonly accessors: ManagerInspectorAccessors;\n\n\tconstructor(accessors: () => ManagerInspectorAccessors) {\n\t\tthis.accessors = accessors();\n\t\tinspectorLogger().debug({ msg: \"Manager Inspector enabled and ready\" });\n\t}\n}\n","import type { DriverConfig } from \"@/registry/run-config\";\nimport { FileSystemActorDriver } from \"./actor\";\nimport { FileSystemGlobalState } from \"./global-state\";\nimport { FileSystemManagerDriver } from \"./manager\";\n\nexport { FileSystemActorDriver } from \"./actor\";\nexport { FileSystemGlobalState } from \"./global-state\";\nexport { FileSystemManagerDriver } from \"./manager\";\nexport { getStoragePath } from \"./utils\";\n\nexport function createFileSystemOrMemoryDriver(\n\tpersist: boolean = true,\n\tcustomPath?: string,\n): DriverConfig {\n\tconst state = new FileSystemGlobalState(persist, customPath);\n\tconst driverConfig: DriverConfig = {\n\t\tname: persist ? \"file-system\" : \"memory\",\n\t\tmanager: (registryConfig, runConfig) =>\n\t\t\tnew FileSystemManagerDriver(\n\t\t\t\tregistryConfig,\n\t\t\t\trunConfig,\n\t\t\t\tstate,\n\t\t\t\tdriverConfig,\n\t\t\t),\n\t\tactor: (registryConfig, runConfig, managerDriver, inlineClient) => {\n\t\t\tconst actorDriver = new FileSystemActorDriver(\n\t\t\t\tregistryConfig,\n\t\t\t\trunConfig,\n\t\t\t\tmanagerDriver,\n\t\t\t\tinlineClient,\n\t\t\t\tstate,\n\t\t\t);\n\n\t\t\tstate.onRunnerStart(registryConfig, runConfig, inlineClient, actorDriver);\n\n\t\t\treturn actorDriver;\n\t\t},\n\t};\n\treturn driverConfig;\n}\n\nexport function createFileSystemDriver(opts?: { path?: string }): DriverConfig {\n\treturn createFileSystemOrMemoryDriver(true, opts?.path);\n}\n\nexport function createMemoryDriver(): DriverConfig {\n\treturn createFileSystemOrMemoryDriver(false);\n}\n","import { UserError } from \"@/actor/errors\";\nimport { loggerWithoutContext } from \"@/actor/log\";\nimport { createEngineDriver } from \"@/drivers/engine/mod\";\nimport { createFileSystemOrMemoryDriver } from \"@/drivers/file-system/mod\";\nimport type { DriverConfig, RunConfig } from \"@/registry/run-config\";\nimport { getEnvUniversal } from \"@/utils\";\n\n/**\n * Chooses the appropriate driver based on the run configuration.\n */\nexport function chooseDefaultDriver(runConfig: RunConfig): DriverConfig {\n\tconst engineEndpoint = runConfig.endpoint ?? getEnvUniversal(\"RIVET_ENGINE\");\n\n\tif (engineEndpoint && runConfig.driver) {\n\t\tthrow new UserError(\n\t\t\t\"Cannot specify both 'engine' and 'driver' in configuration\",\n\t\t);\n\t}\n\n\tif (runConfig.driver) {\n\t\treturn runConfig.driver;\n\t}\n\n\tif (engineEndpoint) {\n\t\tloggerWithoutContext().debug({\n\t\t\tmsg: \"using rivet engine driver\",\n\t\t\tendpoint: engineEndpoint,\n\t\t});\n\t\treturn createEngineDriver({ endpoint: engineEndpoint });\n\t}\n\n\tloggerWithoutContext().debug({ msg: \"using default file system driver\" });\n\treturn createFileSystemOrMemoryDriver(true);\n}\n","import { createRoute, OpenAPIHono } from \"@hono/zod-openapi\";\nimport * as cbor from \"cbor-x\";\nimport { Hono } from \"hono\";\nimport { cors as corsMiddleware } from \"hono/cors\";\nimport { createMiddleware } from \"hono/factory\";\nimport type { WSContext } from \"hono/ws\";\nimport invariant from \"invariant\";\nimport { z } from \"zod\";\nimport {\n\tActorNotFound,\n\tFeatureNotImplemented,\n\tMissingActorHeader,\n\tUnsupported,\n\tWebSocketsNotEnabled,\n} from \"@/actor/errors\";\nimport type { Encoding } from \"@/client/mod\";\nimport {\n\thandleRouteError,\n\thandleRouteNotFound,\n\tloggerMiddleware,\n} from \"@/common/router\";\nimport { deconstructError, noopNext } from \"@/common/utils\";\nimport { HEADER_ACTOR_ID } from \"@/driver-helpers/mod\";\nimport type {\n\tTestInlineDriverCallRequest,\n\tTestInlineDriverCallResponse,\n} from \"@/driver-test-suite/test-inline-client-driver\";\nimport { createManagerInspectorRouter } from \"@/inspector/manager\";\nimport { secureInspector } from \"@/inspector/utils\";\nimport {\n\ttype ActorsCreateRequest,\n\tActorsCreateRequestSchema,\n\tActorsCreateResponseSchema,\n} from \"@/manager-api/routes/actors-create\";\nimport { ActorsDeleteResponseSchema } from \"@/manager-api/routes/actors-delete\";\nimport { ActorsGetResponseSchema } from \"@/manager-api/routes/actors-get\";\nimport { ActorsGetByIdResponseSchema } from \"@/manager-api/routes/actors-get-by-id\";\nimport {\n\ttype ActorsGetOrCreateByIdRequest,\n\tActorsGetOrCreateByIdRequestSchema,\n\tActorsGetOrCreateByIdResponseSchema,\n} from \"@/manager-api/routes/actors-get-or-create-by-id\";\nimport { RivetIdSchema } from \"@/manager-api/routes/common\";\nimport type { UniversalWebSocket, UpgradeWebSocketArgs } from \"@/mod\";\nimport type { RegistryConfig } from \"@/registry/config\";\nimport type { RunConfig } from \"@/registry/run-config\";\nimport { stringifyError } from \"@/utils\";\nimport type { ManagerDriver } from \"./driver\";\nimport { logger } from \"./log\";\n\nfunction buildOpenApiResponses<T>(schema: T, validateBody: boolean) {\n\treturn {\n\t\t200: {\n\t\t\tdescription: \"Success\",\n\t\t\tcontent: validateBody\n\t\t\t\t? {\n\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\tschema,\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t: {},\n\t\t},\n\t\t400: {\n\t\t\tdescription: \"User error\",\n\t\t},\n\t\t500: {\n\t\t\tdescription: \"Internal error\",\n\t\t},\n\t};\n}\n\nexport function createManagerRouter(\n\tregistryConfig: RegistryConfig,\n\trunConfig: RunConfig,\n\tmanagerDriver: ManagerDriver,\n\tvalidateBody: boolean,\n): { router: Hono; openapi: OpenAPIHono } {\n\tconst router = new OpenAPIHono({ strict: false }).basePath(\n\t\trunConfig.basePath,\n\t);\n\n\trouter.use(\"*\", loggerMiddleware(logger()));\n\n\tconst cors = runConfig.cors\n\t\t? corsMiddleware(runConfig.cors)\n\t\t: createMiddleware((_c, next) => next());\n\n\t// Actor proxy middleware - intercept requests with x-rivet-target=actor\n\trouter.use(\"*\", cors, async (c, next) => {\n\t\tconst target = c.req.header(\"x-rivet-target\");\n\t\tconst actorId = c.req.header(\"x-rivet-actor\");\n\n\t\tif (target === \"actor\") {\n\t\t\tif (!actorId) {\n\t\t\t\tthrow new MissingActorHeader();\n\t\t\t}\n\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"proxying request to actor\",\n\t\t\t\tactorId,\n\t\t\t\tpath: c.req.path,\n\t\t\t\tmethod: c.req.method,\n\t\t\t});\n\n\t\t\t// Handle WebSocket upgrade\n\t\t\tif (c.req.header(\"upgrade\") === \"websocket\") {\n\t\t\t\tconst upgradeWebSocket = runConfig.getUpgradeWebSocket?.();\n\t\t\t\tif (!upgradeWebSocket) {\n\t\t\t\t\tthrow new WebSocketsNotEnabled();\n\t\t\t\t}\n\n\t\t\t\t// For WebSocket, use the driver's proxyWebSocket method\n\t\t\t\t// Extract any additional headers that might be needed\n\t\t\t\tconst encoding =\n\t\t\t\t\tc.req.header(\"X-RivetKit-Encoding\") ||\n\t\t\t\t\tc.req.header(\"x-rivet-encoding\") ||\n\t\t\t\t\t\"json\";\n\t\t\t\tconst connParams =\n\t\t\t\t\tc.req.header(\"X-RivetKit-Conn-Params\") ||\n\t\t\t\t\tc.req.header(\"x-rivet-conn-params\");\n\t\t\t\tconst authData =\n\t\t\t\t\tc.req.header(\"X-RivetKit-Auth-Data\") ||\n\t\t\t\t\tc.req.header(\"x-rivet-auth-data\");\n\n\t\t\t\t// Include query string if present\n\t\t\t\tconst pathWithQuery = c.req.url.includes(\"?\")\n\t\t\t\t\t? c.req.path + c.req.url.substring(c.req.url.indexOf(\"?\"))\n\t\t\t\t\t: c.req.path;\n\n\t\t\t\treturn await managerDriver.proxyWebSocket(\n\t\t\t\t\tc,\n\t\t\t\t\tpathWithQuery,\n\t\t\t\t\tactorId,\n\t\t\t\t\tencoding as any, // Will be validated by driver\n\t\t\t\t\tconnParams ? JSON.parse(connParams) : undefined,\n\t\t\t\t\tauthData ? JSON.parse(authData) : undefined,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Handle regular HTTP requests\n\t\t\t// Preserve all headers except the routing headers\n\t\t\tconst proxyHeaders = new Headers(c.req.raw.headers);\n\t\t\tproxyHeaders.delete(\"x-rivet-target\");\n\t\t\tproxyHeaders.delete(\"x-rivet-actor\");\n\n\t\t\t// Build the proxy request with the actor URL format\n\t\t\tconst url = new URL(c.req.url);\n\t\t\tconst proxyUrl = new URL(`http://actor${url.pathname}${url.search}`);\n\n\t\t\tconst proxyRequest = new Request(proxyUrl, {\n\t\t\t\tmethod: c.req.raw.method,\n\t\t\t\theaders: proxyHeaders,\n\t\t\t\tbody: c.req.raw.body,\n\t\t\t\tsignal: c.req.raw.signal,\n\t\t\t});\n\n\t\t\treturn await managerDriver.proxyRequest(c, proxyRequest, actorId);\n\t\t}\n\n\t\treturn next();\n\t});\n\n\t// GET /\n\trouter.get(\"/\", cors, (c) => {\n\t\treturn c.text(\n\t\t\t\"This is a RivetKit server.\\n\\nLearn more at https://rivetkit.org\",\n\t\t);\n\t});\n\n\t// GET /actors/by-id\n\t{\n\t\tconst route = createRoute({\n\t\t\tmiddleware: [cors],\n\t\t\tmethod: \"get\",\n\t\t\tpath: \"/actors/by-id\",\n\t\t\trequest: {\n\t\t\t\tquery: z.object({\n\t\t\t\t\tname: z.string(),\n\t\t\t\t\tkey: z.string(),\n\t\t\t\t}),\n\t\t\t},\n\t\t\tresponses: buildOpenApiResponses(\n\t\t\t\tActorsGetByIdResponseSchema,\n\t\t\t\tvalidateBody,\n\t\t\t),\n\t\t});\n\n\t\trouter.openapi(route, async (c) => {\n\t\t\tconst { name, key } = c.req.valid(\"query\");\n\n\t\t\t// Get actor by key from the driver\n\t\t\tconst actorOutput = await managerDriver.getWithKey({\n\t\t\t\tc,\n\t\t\t\tname,\n\t\t\t\tkey: [key], // Convert string to ActorKey array\n\t\t\t});\n\n\t\t\treturn c.json({\n\t\t\t\tactor_id: actorOutput?.actorId || null,\n\t\t\t});\n\t\t});\n\t}\n\n\t// PUT /actors/by-id\n\t{\n\t\tconst route = createRoute({\n\t\t\tcors: [cors],\n\t\t\tmethod: \"put\",\n\t\t\tpath: \"/actors/by-id\",\n\t\t\trequest: {\n\t\t\t\tbody: {\n\t\t\t\t\tcontent: validateBody\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: ActorsGetOrCreateByIdRequestSchema,\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},\n\t\t\t},\n\t\t\tresponses: buildOpenApiResponses(\n\t\t\t\tActorsGetOrCreateByIdResponseSchema,\n\t\t\t\tvalidateBody,\n\t\t\t),\n\t\t});\n\n\t\trouter.openapi(route, async (c) => {\n\t\t\tconst body = validateBody\n\t\t\t\t? await c.req.json<ActorsGetOrCreateByIdRequest>()\n\t\t\t\t: await c.req.json();\n\n\t\t\t// Parse and validate the request body if validation is enabled\n\t\t\tif (validateBody) {\n\t\t\t\tActorsGetOrCreateByIdRequestSchema.parse(body);\n\t\t\t}\n\n\t\t\t// Check if actor already exists\n\t\t\tconst existingActor = await managerDriver.getWithKey({\n\t\t\t\tc,\n\t\t\t\tname: body.name,\n\t\t\t\tkey: [body.key], // Convert string to ActorKey array\n\t\t\t});\n\n\t\t\tif (existingActor) {\n\t\t\t\treturn c.json({\n\t\t\t\t\tactor_id: existingActor.actorId,\n\t\t\t\t\tcreated: false,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Create new actor\n\t\t\tconst newActor = await managerDriver.getOrCreateWithKey({\n\t\t\t\tc,\n\t\t\t\tname: body.name,\n\t\t\t\tkey: [body.key], // Convert string to ActorKey array\n\t\t\t\tinput: body.input\n\t\t\t\t\t? cbor.decode(Buffer.from(body.input, \"base64\"))\n\t\t\t\t\t: undefined,\n\t\t\t\tregion: undefined, // Not provided in the request schema\n\t\t\t});\n\n\t\t\treturn c.json({\n\t\t\t\tactor_id: newActor.actorId,\n\t\t\t\tcreated: true,\n\t\t\t});\n\t\t});\n\t}\n\n\t// GET /actors/{actor_id}\n\t{\n\t\tconst route = createRoute({\n\t\t\tmiddleware: [cors],\n\t\t\tmethod: \"get\",\n\t\t\tpath: \"/actors/{actor_id}\",\n\t\t\trequest: {\n\t\t\t\tparams: z.object({\n\t\t\t\t\tactor_id: RivetIdSchema,\n\t\t\t\t}),\n\t\t\t},\n\t\t\tresponses: buildOpenApiResponses(ActorsGetResponseSchema, validateBody),\n\t\t});\n\n\t\trouter.openapi(route, async (c) => {\n\t\t\tconst { actor_id } = c.req.valid(\"param\");\n\n\t\t\t// Get actor by ID from the driver\n\t\t\tconst actorOutput = await managerDriver.getForId({\n\t\t\t\tc,\n\t\t\t\tname: \"\", // TODO: The API doesn't provide the name, this may need to be resolved\n\t\t\t\tactorId: actor_id,\n\t\t\t});\n\n\t\t\tif (!actorOutput) {\n\t\t\t\tthrow new ActorNotFound(actor_id);\n\t\t\t}\n\n\t\t\t// Transform ActorOutput to match ActorSchema\n\t\t\t// Note: Some fields are not available from the driver and need defaults\n\t\t\tconst actor = {\n\t\t\t\tactor_id: actorOutput.actorId,\n\t\t\t\tname: actorOutput.name,\n\t\t\t\tkey: actorOutput.key,\n\t\t\t\tnamespace_id: \"default\", // Assert default namespace\n\t\t\t\trunner_name_selector: \"rivetkit\", // Assert rivetkit runner\n\t\t\t\tcreate_ts: Date.now(), // Not available from driver\n\t\t\t\tconnectable_ts: null,\n\t\t\t\tdestroy_ts: null,\n\t\t\t\tsleep_ts: null,\n\t\t\t\tstart_ts: null,\n\t\t\t};\n\n\t\t\treturn c.json({ actor });\n\t\t});\n\t}\n\n\t// POST /actors\n\t{\n\t\tconst route = createRoute({\n\t\t\tmiddleware: [cors],\n\t\t\tmethod: \"post\",\n\t\t\tpath: \"/actors\",\n\t\t\trequest: {\n\t\t\t\tbody: {\n\t\t\t\t\tcontent: validateBody\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: ActorsCreateRequestSchema,\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},\n\t\t\t},\n\t\t\tresponses: buildOpenApiResponses(\n\t\t\t\tActorsCreateResponseSchema,\n\t\t\t\tvalidateBody,\n\t\t\t),\n\t\t});\n\n\t\trouter.openapi(route, async (c) => {\n\t\t\tconst body = validateBody\n\t\t\t\t? await c.req.json<ActorsCreateRequest>()\n\t\t\t\t: await c.req.json();\n\n\t\t\t// Parse and validate the request body if validation is enabled\n\t\t\tif (validateBody) {\n\t\t\t\tActorsCreateRequestSchema.parse(body);\n\t\t\t}\n\n\t\t\t// Create actor using the driver\n\t\t\tconst actorOutput = await managerDriver.createActor({\n\t\t\t\tc,\n\t\t\t\tname: body.name,\n\t\t\t\tkey: [body.key || crypto.randomUUID()], // Generate key if not provided, convert to ActorKey array\n\t\t\t\tinput: body.input\n\t\t\t\t\t? cbor.decode(Buffer.from(body.input, \"base64\"))\n\t\t\t\t\t: undefined,\n\t\t\t\tregion: undefined, // Not provided in the request schema\n\t\t\t});\n\n\t\t\t// Transform ActorOutput to match ActorSchema\n\t\t\tconst actor = {\n\t\t\t\tactor_id: actorOutput.actorId,\n\t\t\t\tname: actorOutput.name,\n\t\t\t\tkey: actorOutput.key,\n\t\t\t\tnamespace_id: \"default\", // Assert default namespace\n\t\t\t\trunner_name_selector: \"rivetkit\", // Assert rivetkit runner\n\t\t\t\tcreate_ts: Date.now(),\n\t\t\t\tconnectable_ts: null,\n\t\t\t\tdestroy_ts: null,\n\t\t\t\tsleep_ts: null,\n\t\t\t\tstart_ts: null,\n\t\t\t};\n\n\t\t\treturn c.json({ actor });\n\t\t});\n\t}\n\n\t// TODO:\n\t// // DELETE /actors/{actor_id}\n\t// {\n\t// \tconst route = createRoute({\n\t// \t\tmiddleware: [cors],\n\t// \t\tmethod: \"delete\",\n\t// \t\tpath: \"/actors/{actor_id}\",\n\t// \t\trequest: {\n\t// \t\t\tparams: z.object({\n\t// \t\t\t\tactor_id: RivetIdSchema,\n\t// \t\t\t}),\n\t// \t\t},\n\t// \t\tresponses: buildOpenApiResponses(\n\t// \t\t\tActorsDeleteResponseSchema,\n\t// \t\t\tvalidateBody,\n\t// \t\t),\n\t// \t});\n\t//\n\t// \trouter.openapi(route, async (c) => {\n\t// \t\tconst { actor_id } = c.req.valid(\"param\");\n\t//\n\t// \t});\n\t// }\n\n\tif (registryConfig.test.enabled) {\n\t\t// Add HTTP endpoint to test the inline client\n\t\t//\n\t\t// We have to do this in a router since this needs to run in the same server as the RivetKit registry. Some test contexts to not run in the same server.\n\t\trouter.post(\".test/inline-driver/call\", async (c) => {\n\t\t\t// TODO: use openapi instead\n\t\t\tconst buffer = await c.req.arrayBuffer();\n\t\t\tconst { encoding, transport, method, args }: TestInlineDriverCallRequest =\n\t\t\t\tcbor.decode(new Uint8Array(buffer));\n\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"received inline request\",\n\t\t\t\tencoding,\n\t\t\t\ttransport,\n\t\t\t\tmethod,\n\t\t\t\targs,\n\t\t\t});\n\n\t\t\t// Forward inline driver request\n\t\t\tlet response: TestInlineDriverCallResponse<unknown>;\n\t\t\ttry {\n\t\t\t\tconst output = await ((managerDriver as any)[method] as any)(...args);\n\t\t\t\tresponse = { ok: output };\n\t\t\t} catch (rawErr) {\n\t\t\t\tconst err = deconstructError(rawErr, logger(), {}, true);\n\t\t\t\tresponse = { err };\n\t\t\t}\n\n\t\t\treturn c.body(cbor.encode(response));\n\t\t});\n\n\t\trouter.get(\".test/inline-driver/connect-websocket/*\", async (c) => {\n\t\t\tconst upgradeWebSocket = runConfig.getUpgradeWebSocket?.();\n\t\t\tinvariant(upgradeWebSocket, \"websockets not supported on this platform\");\n\n\t\t\treturn upgradeWebSocket(async (c: any) => {\n\t\t\t\tconst {\n\t\t\t\t\tpath,\n\t\t\t\t\tactorId,\n\t\t\t\t\tparams: paramsRaw,\n\t\t\t\t\tencodingKind,\n\t\t\t\t} = c.req.query() as {\n\t\t\t\t\tpath: string;\n\t\t\t\t\tactorId: string;\n\t\t\t\t\tparams?: string;\n\t\t\t\t\tencodingKind: Encoding;\n\t\t\t\t};\n\t\t\t\tconst params =\n\t\t\t\t\tparamsRaw !== undefined ? JSON.parse(paramsRaw) : undefined;\n\n\t\t\t\tlogger().debug({\n\t\t\t\t\tmsg: \"received test inline driver websocket\",\n\t\t\t\t\tactorId,\n\t\t\t\t\tparams,\n\t\t\t\t\tencodingKind,\n\t\t\t\t\tpath: path,\n\t\t\t\t});\n\n\t\t\t\t// Connect to the actor using the inline client driver - this returns a Promise<WebSocket>\n\t\t\t\tconst clientWsPromise = managerDriver.openWebSocket(\n\t\t\t\t\tpath,\n\t\t\t\t\tactorId,\n\t\t\t\t\tencodingKind,\n\t\t\t\t\tparams,\n\t\t\t\t);\n\n\t\t\t\treturn await createTestWebSocketProxy(clientWsPromise, \"standard\");\n\t\t\t})(c, noopNext());\n\t\t});\n\n\t\trouter.all(\".test/inline-driver/send-request/*\", async (c) => {\n\t\t\t// Extract parameters from headers\n\t\t\tconst actorId = c.req.header(HEADER_ACTOR_ID);\n\n\t\t\tif (!actorId) {\n\t\t\t\treturn c.text(\"Missing required headers\", 400);\n\t\t\t}\n\n\t\t\t// Extract the path after /send-request/\n\t\t\tconst pathOnly =\n\t\t\t\tc.req.path.split(\"/.test/inline-driver/send-request/\")[1] || \"\";\n\n\t\t\t// Include query string\n\t\t\tconst url = new URL(c.req.url);\n\t\t\tconst pathWithQuery = pathOnly + url.search;\n\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"received test inline driver raw http\",\n\t\t\t\tactorId,\n\t\t\t\tpath: pathWithQuery,\n\t\t\t\tmethod: c.req.method,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\t// Forward the request using the inline client driver\n\t\t\t\tconst response = await managerDriver.sendRequest(\n\t\t\t\t\tactorId,\n\t\t\t\t\tnew Request(`http://actor/${pathWithQuery}`, {\n\t\t\t\t\t\tmethod: c.req.method,\n\t\t\t\t\t\theaders: c.req.raw.headers,\n\t\t\t\t\t\tbody: c.req.raw.body,\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\t// Return the response directly\n\t\t\t\treturn response;\n\t\t\t} catch (error) {\n\t\t\t\tlogger().error({\n\t\t\t\t\tmsg: \"error in test inline raw http\",\n\t\t\t\t\terror: stringifyError(error),\n\t\t\t\t});\n\n\t\t\t\t// Return error response\n\t\t\t\tconst err = deconstructError(error, logger(), {}, true);\n\t\t\t\treturn c.json(\n\t\t\t\t\t{\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tcode: err.code,\n\t\t\t\t\t\t\tmessage: err.message,\n\t\t\t\t\t\t\tmetadata: err.metadata,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\terr.statusCode,\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t}\n\n\tmanagerDriver.modifyManagerRouter?.(\n\t\tregistryConfig,\n\t\trouter as unknown as Hono,\n\t);\n\n\tif (runConfig.inspector?.enabled) {\n\t\tif (!managerDriver.inspector) {\n\t\t\tthrow new Unsupported(\"inspector\");\n\t\t}\n\t\trouter.route(\n\t\t\t\"/inspect\",\n\t\t\tnew Hono<{ Variables: { inspector: any } }>()\n\t\t\t\t.use(corsMiddleware(runConfig.inspector.cors))\n\t\t\t\t.use(secureInspector(runConfig))\n\t\t\t\t.use((c, next) => {\n\t\t\t\t\tc.set(\"inspector\", managerDriver.inspector!);\n\t\t\t\t\treturn next();\n\t\t\t\t})\n\t\t\t\t.route(\"/\", createManagerInspectorRouter()),\n\t\t);\n\t}\n\n\t// Error handling\n\trouter.notFound(handleRouteNotFound);\n\trouter.onError(handleRouteError);\n\n\treturn { router: router as Hono, openapi: router };\n}\n/**\n * Creates a WebSocket proxy for test endpoints that forwards messages between server and client WebSockets\n */\nasync function createTestWebSocketProxy(\n\tclientWsPromise: Promise<UniversalWebSocket>,\n\tconnectionType: string,\n): Promise<UpgradeWebSocketArgs> {\n\t// Store a reference to the resolved WebSocket\n\tlet clientWs: UniversalWebSocket | null = null;\n\ttry {\n\t\t// Resolve the client WebSocket promise\n\t\tlogger().debug({ msg: \"awaiting client websocket promise\" });\n\t\tconst ws = await clientWsPromise;\n\t\tclientWs = ws;\n\t\tlogger().debug({\n\t\t\tmsg: \"client websocket promise resolved\",\n\t\t\tconstructor: ws?.constructor.name,\n\t\t});\n\n\t\t// Wait for ws to open\n\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\tconst onOpen = () => {\n\t\t\t\tlogger().debug({ msg: \"test websocket connection opened\" });\n\t\t\t\tresolve();\n\t\t\t};\n\t\t\tconst onError = (error: any) => {\n\t\t\t\tlogger().error({ msg: \"test websocket connection failed\", error });\n\t\t\t\treject(\n\t\t\t\t\tnew Error(`Failed to open WebSocket: ${error.message || error}`),\n\t\t\t\t);\n\t\t\t};\n\t\t\tws.addEventListener(\"open\", onOpen);\n\t\t\tws.addEventListener(\"error\", onError);\n\t\t});\n\t} catch (error) {\n\t\tlogger().error({\n\t\t\tmsg: `failed to establish client ${connectionType} websocket connection`,\n\t\t\terror,\n\t\t});\n\t\treturn {\n\t\t\tonOpen: (_evt, serverWs) => {\n\t\t\t\tserverWs.close(1011, \"Failed to establish connection\");\n\t\t\t},\n\t\t\tonMessage: () => {},\n\t\t\tonError: () => {},\n\t\t\tonClose: () => {},\n\t\t};\n\t}\n\n\t// Create WebSocket proxy handlers to relay messages between client and server\n\treturn {\n\t\tonOpen: (_evt: any, serverWs: WSContext) => {\n\t\t\tlogger().debug({\n\t\t\t\tmsg: `test ${connectionType} websocket connection opened`,\n\t\t\t});\n\n\t\t\t// Check WebSocket type\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"clientWs info\",\n\t\t\t\tconstructor: clientWs.constructor.name,\n\t\t\t\thasAddEventListener: typeof clientWs.addEventListener === \"function\",\n\t\t\t\treadyState: clientWs.readyState,\n\t\t\t});\n\n\t\t\t// Add message handler to forward messages from client to server\n\t\t\tclientWs.addEventListener(\"message\", (clientEvt: MessageEvent) => {\n\t\t\t\tlogger().debug({\n\t\t\t\t\tmsg: `test ${connectionType} websocket connection message from client`,\n\t\t\t\t\tdataType: typeof clientEvt.data,\n\t\t\t\t\tisBlob: clientEvt.data instanceof Blob,\n\t\t\t\t\tisArrayBuffer: clientEvt.data instanceof ArrayBuffer,\n\t\t\t\t\tdataConstructor: clientEvt.data?.constructor?.name,\n\t\t\t\t\tdataStr:\n\t\t\t\t\t\ttypeof clientEvt.data === \"string\"\n\t\t\t\t\t\t\t? clientEvt.data.substring(0, 100)\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t});\n\n\t\t\t\tif (serverWs.readyState === 1) {\n\t\t\t\t\t// OPEN\n\t\t\t\t\t// Handle Blob data\n\t\t\t\t\tif (clientEvt.data instanceof Blob) {\n\t\t\t\t\t\tclientEvt.data\n\t\t\t\t\t\t\t.arrayBuffer()\n\t\t\t\t\t\t\t.then((buffer) => {\n\t\t\t\t\t\t\t\tlogger().debug({\n\t\t\t\t\t\t\t\t\tmsg: \"converted client blob to arraybuffer, sending to server\",\n\t\t\t\t\t\t\t\t\tbufferSize: buffer.byteLength,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tserverWs.send(buffer as any);\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.catch((error) => {\n\t\t\t\t\t\t\t\tlogger().error({\n\t\t\t\t\t\t\t\t\tmsg: \"failed to convert blob to arraybuffer\",\n\t\t\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger().debug({\n\t\t\t\t\t\t\tmsg: \"sending client data directly to server\",\n\t\t\t\t\t\t\tdataType: typeof clientEvt.data,\n\t\t\t\t\t\t\tdataLength:\n\t\t\t\t\t\t\t\ttypeof clientEvt.data === \"string\"\n\t\t\t\t\t\t\t\t\t? clientEvt.data.length\n\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tserverWs.send(clientEvt.data as any);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Add close handler to close server when client closes\n\t\t\tclientWs.addEventListener(\"close\", (clientEvt: any) => {\n\t\t\t\tlogger().debug({\n\t\t\t\t\tmsg: `test ${connectionType} websocket connection closed`,\n\t\t\t\t});\n\n\t\t\t\tif (serverWs.readyState !== 3) {\n\t\t\t\t\t// Not CLOSED\n\t\t\t\t\tserverWs.close(clientEvt.code, clientEvt.reason);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Add error handler\n\t\t\tclientWs.addEventListener(\"error\", () => {\n\t\t\t\tlogger().debug({\n\t\t\t\t\tmsg: `test ${connectionType} websocket connection error`,\n\t\t\t\t});\n\n\t\t\t\tif (serverWs.readyState !== 3) {\n\t\t\t\t\t// Not CLOSED\n\t\t\t\t\tserverWs.close(1011, \"Error in client websocket\");\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t\tonMessage: (evt: { data: any }) => {\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"received message from server\",\n\t\t\t\tdataType: typeof evt.data,\n\t\t\t\tisBlob: evt.data instanceof Blob,\n\t\t\t\tisArrayBuffer: evt.data instanceof ArrayBuffer,\n\t\t\t\tdataConstructor: evt.data?.constructor?.name,\n\t\t\t\tdataStr:\n\t\t\t\t\ttypeof evt.data === \"string\" ? evt.data.substring(0, 100) : undefined,\n\t\t\t});\n\n\t\t\t// Forward messages from server websocket to client websocket\n\t\t\tif (clientWs.readyState === 1) {\n\t\t\t\t// OPEN\n\t\t\t\t// Handle Blob data\n\t\t\t\tif (evt.data instanceof Blob) {\n\t\t\t\t\tevt.data\n\t\t\t\t\t\t.arrayBuffer()\n\t\t\t\t\t\t.then((buffer) => {\n\t\t\t\t\t\t\tlogger().debug({\n\t\t\t\t\t\t\t\tmsg: \"converted blob to arraybuffer, sending\",\n\t\t\t\t\t\t\t\tbufferSize: buffer.byteLength,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tclientWs.send(buffer);\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.catch((error) => {\n\t\t\t\t\t\t\tlogger().error({\n\t\t\t\t\t\t\t\tmsg: \"failed to convert blob to arraybuffer\",\n\t\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tlogger().debug({\n\t\t\t\t\t\tmsg: \"sending data directly\",\n\t\t\t\t\t\tdataType: typeof evt.data,\n\t\t\t\t\t\tdataLength:\n\t\t\t\t\t\t\ttypeof evt.data === \"string\" ? evt.data.length : undefined,\n\t\t\t\t\t});\n\t\t\t\t\tclientWs.send(evt.data);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tonClose: (\n\t\t\tevent: {\n\t\t\t\twasClean: boolean;\n\t\t\t\tcode: number;\n\t\t\t\treason: string;\n\t\t\t},\n\t\t\tserverWs: WSContext,\n\t\t) => {\n\t\t\tlogger().debug({\n\t\t\t\tmsg: `server ${connectionType} websocket closed`,\n\t\t\t\twasClean: event.wasClean,\n\t\t\t\tcode: event.code,\n\t\t\t\treason: event.reason,\n\t\t\t});\n\n\t\t\t// HACK: Close socket in order to fix bug with Cloudflare leaving WS in closing state\n\t\t\t// https://github.com/cloudflare/workerd/issues/2569\n\t\t\tserverWs.close(1000, \"hack_force_close\");\n\n\t\t\t// Close the client websocket when the server websocket closes\n\t\t\tif (\n\t\t\t\tclientWs &&\n\t\t\t\tclientWs.readyState !== clientWs.CLOSED &&\n\t\t\t\tclientWs.readyState !== clientWs.CLOSING\n\t\t\t) {\n\t\t\t\t// Don't pass code/message since this may affect how close events are triggered\n\t\t\t\tclientWs.close(1000, event.reason);\n\t\t\t}\n\t\t},\n\t\tonError: (error: unknown) => {\n\t\t\tlogger().error({\n\t\t\t\tmsg: `error in server ${connectionType} websocket`,\n\t\t\t\terror,\n\t\t\t});\n\n\t\t\t// Close the client websocket on error\n\t\t\tif (\n\t\t\t\tclientWs &&\n\t\t\t\tclientWs.readyState !== clientWs.CLOSED &&\n\t\t\t\tclientWs.readyState !== clientWs.CLOSING\n\t\t\t) {\n\t\t\t\tclientWs.close(1011, \"Error in server websocket\");\n\t\t\t}\n\t\t},\n\t};\n}\n","import { z } from \"zod\";\nimport { ActorSchema } from \"./common\";\n\nexport const ActorsCreateRequestSchema = z.object({\n\tname: z.string(),\n\trunner_name_selector: z.string(),\n\tcrash_policy: z.string(),\n\tkey: z.string().nullable().optional(),\n\tinput: z.string().nullable().optional(),\n});\nexport type ActorsCreateRequest = z.infer<typeof ActorsCreateRequestSchema>;\n\nexport const ActorsCreateResponseSchema = z.object({\n\tactor: ActorSchema,\n});\nexport type ActorsCreateResponse = z.infer<typeof ActorsCreateResponseSchema>;\n","import { z } from \"zod\";\n\nexport const RivetIdSchema = z.string();\nexport type RivetId = z.infer<typeof RivetIdSchema>;\n\nexport const ActorSchema = z.object({\n\tactor_id: RivetIdSchema,\n\tname: z.string(),\n\tkey: z.string(),\n\tnamespace_id: RivetIdSchema,\n\trunner_name_selector: z.string(),\n\tcreate_ts: z.number(),\n\tconnectable_ts: z.number().nullable().optional(),\n\tdestroy_ts: z.number().nullable().optional(),\n\tsleep_ts: z.number().nullable().optional(),\n\tstart_ts: z.number().nullable().optional(),\n});\nexport type Actor = z.infer<typeof ActorSchema>;\n","import { z } from \"zod\";\nimport { ActorSchema } from \"./common\";\n\nexport const ActorsGetResponseSchema = z.object({\n\tactor: ActorSchema,\n});\nexport type ActorsGetResponse = z.infer<typeof ActorsGetResponseSchema>;\n","import { z } from \"zod\";\nimport { RivetIdSchema } from \"./common\";\n\nexport const ActorsGetByIdResponseSchema = z.object({\n\tactor_id: RivetIdSchema.nullable().optional(),\n});\nexport type ActorsGetByIdResponse = z.infer<typeof ActorsGetByIdResponseSchema>;\n","import { z } from \"zod\";\nimport { ActorSchema, RivetIdSchema } from \"./common\";\n\nexport const ActorsGetOrCreateResponseSchema = z.object({\n\tactor: ActorSchema,\n\tcreated: z.boolean(),\n});\nexport type ActorsGetOrCreateResponse = z.infer<\n\ttypeof ActorsGetOrCreateResponseSchema\n>;\n\nexport const ActorsGetOrCreateByIdResponseSchema = z.object({\n\tactor_id: RivetIdSchema,\n\tcreated: z.boolean(),\n});\nexport type ActorsGetOrCreateByIdResponse = z.infer<\n\ttypeof ActorsGetOrCreateByIdResponseSchema\n>;\n\nexport const ActorsGetOrCreateByIdRequestSchema = z.object({\n\tname: z.string(),\n\tkey: z.string(),\n\trunner_name_selector: z.string(),\n\tcrash_policy: z.string(),\n\tinput: z.string().nullable().optional(),\n});\nexport type ActorsGetOrCreateByIdRequest = z.infer<\n\ttypeof ActorsGetOrCreateByIdRequestSchema\n>;\n","//! These configs configs hold anything that's not platform-specific about running actors.\n\nimport { z } from \"zod\";\nimport type { ActorDefinition, AnyActorDefinition } from \"@/actor/definition\";\n\nexport const ActorsSchema = z.record(\n\tz.string(),\n\tz.custom<ActorDefinition<any, any, any, any, any, any, any>>(),\n);\nexport type RegistryActors = z.infer<typeof ActorsSchema>;\n\nexport const TestConfigSchema = z.object({ enabled: z.boolean() });\nexport type TestConfig = z.infer<typeof TestConfigSchema>;\n\n/** Base config used for the actor config across all platforms. */\nexport const RegistryConfigSchema = z.object({\n\tuse: z.record(z.string(), z.custom<AnyActorDefinition>()),\n\n\t// TODO: Find a better way of passing around the test config\n\t/**\n\t * Test configuration.\n\t *\n\t * DO NOT MANUALLY ENABLE. THIS IS USED INTERNALLY.\n\t * @internal\n\t **/\n\ttest: TestConfigSchema.optional().default({ enabled: false }),\n});\nexport type RegistryConfig = z.infer<typeof RegistryConfigSchema>;\nexport type RegistryConfigInput<A extends RegistryActors> = Omit<\n\tz.input<typeof RegistryConfigSchema>,\n\t\"use\"\n> & { use: A };\n","import { getLogger } from \"@/common/log\";\n\nexport function logger() {\n\treturn getLogger(\"registry\");\n}\n","import { Hono } from \"hono\";\nimport { getEnvUniversal } from \"@/utils\";\nimport { logger } from \"./log\";\n\nexport async function crossPlatformServe(\n\trivetKitRouter: Hono<any>,\n\tuserRouter: Hono | undefined,\n) {\n\tconst app = userRouter ?? new Hono();\n\n\t// Import @hono/node-server\n\tlet serve: any;\n\ttry {\n\t\tconst dep = await import(\"@hono/node-server\");\n\t\tserve = dep.serve;\n\t} catch (err) {\n\t\tlogger().error(\n\t\t\t\"failed to import @hono/node-server. please run 'npm install @hono/node-server @hono/node-ws'\",\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\t// Mount registry\n\t// app.route(\"/registry\", rivetKitRouter);\n\tapp.route(\"/\", rivetKitRouter);\n\n\t// Import @hono/node-ws\n\tlet createNodeWebSocket: any;\n\ttry {\n\t\tconst dep = await import(\"@hono/node-ws\");\n\t\tcreateNodeWebSocket = dep.createNodeWebSocket;\n\t} catch (err) {\n\t\tlogger().error(\n\t\t\t\"failed to import @hono/node-ws. please run 'npm install @hono/node-server @hono/node-ws'\",\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\t// Inject WS\n\tconst { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({\n\t\tapp,\n\t});\n\n\t// Start server\n\tconst port = 6420;\n\tconst server = serve({ fetch: app.fetch, port }, () =>\n\t\tlogger().info({ msg: \"server listening\", port }),\n\t);\n\tinjectWebSocket(server);\n\n\treturn { upgradeWebSocket };\n}\n","import type { Hono } from \"hono\";\nimport { type Client, createClientWithDriver } from \"@/client/client\";\nimport { configureBaseLogger, configureDefaultLogger } from \"@/common/log\";\nimport { chooseDefaultDriver } from \"@/drivers/default\";\nimport { getInspectorUrl } from \"@/inspector/utils\";\nimport { createManagerRouter } from \"@/manager/router\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport {\n\ttype RegistryActors,\n\ttype RegistryConfig,\n\ttype RegistryConfigInput,\n\tRegistryConfigSchema,\n} from \"./config\";\nimport { logger } from \"./log\";\nimport {\n\ttype DriverConfig,\n\ttype RunConfig,\n\ttype RunConfigInput,\n\tRunConfigSchema,\n} from \"./run-config\";\nimport { crossPlatformServe } from \"./serve\";\n\ninterface ServerOutput<A extends Registry<any>> {\n\t/** Client to communicate with the actors. */\n\tclient: Client<A>;\n\t/** Fetch handler to manually route requests to the Rivet manager API. */\n\tfetch: (request: Request, ...args: any) => Response | Promise<Response>;\n}\n\nexport class Registry<A extends RegistryActors> {\n\t#config: RegistryConfig;\n\n\tpublic get config(): RegistryConfig {\n\t\treturn this.#config;\n\t}\n\n\tconstructor(config: RegistryConfig) {\n\t\tthis.#config = config;\n\t}\n\n\t/**\n\t * Runs the registry for a server.\n\t */\n\tpublic start(inputConfig?: RunConfigInput): ServerOutput<this> {\n\t\tconst config = RunConfigSchema.parse(inputConfig);\n\n\t\t// Configure logger\n\t\tif (config.logging?.baseLogger) {\n\t\t\t// Use provided base logger\n\t\t\tconfigureBaseLogger(config.logging.baseLogger);\n\t\t} else {\n\t\t\t// Configure default logger with log level from config\n\t\t\t// getPinoLevel will handle env variable priority\n\t\t\tconfigureDefaultLogger(config.logging?.level);\n\t\t}\n\n\t\t// Choose the driver based on configuration\n\t\tconst driver = chooseDefaultDriver(config);\n\n\t\t// TODO: Find cleaner way of disabling by default\n\t\tif (driver.name === \"engine\") {\n\t\t\tconfig.inspector.enabled = false;\n\t\t\tconfig.disableServer = true;\n\t\t}\n\t\tif (driver.name === \"cloudflare-workers\") {\n\t\t\tconfig.inspector.enabled = false;\n\t\t\tconfig.disableServer = true;\n\t\t\tconfig.disableActorDriver = true;\n\t\t\tconfig.noWelcome = true;\n\t\t}\n\n\t\t// Configure getUpgradeWebSocket lazily so we can assign it in crossPlatformServe\n\t\tlet upgradeWebSocket: any;\n\t\tif (!config.getUpgradeWebSocket) {\n\t\t\tconfig.getUpgradeWebSocket = () => upgradeWebSocket!;\n\t\t}\n\n\t\t// Create router\n\t\tconst managerDriver = driver.manager(this.#config, config);\n\t\tconst { router: hono } = createManagerRouter(\n\t\t\tthis.#config,\n\t\t\tconfig,\n\t\t\tmanagerDriver,\n\t\t\tfalse,\n\t\t);\n\n\t\t// Create client\n\t\tconst client = createClientWithDriver<this>(managerDriver, config);\n\n\t\tconst driverLog = managerDriver.extraStartupLog?.() ?? {};\n\t\tlogger().info({\n\t\t\tmsg: \"rivetkit ready\",\n\t\t\tdriver: driver.name,\n\t\t\tdefinitions: Object.keys(this.#config.use).length,\n\t\t\t...driverLog,\n\t\t});\n\t\tif (config.inspector?.enabled && managerDriver.inspector) {\n\t\t\tlogger().info({ msg: \"inspector ready\", url: getInspectorUrl(config) });\n\t\t}\n\n\t\t// Print welcome information\n\t\tif (!config.noWelcome) {\n\t\t\tconst displayInfo = managerDriver.displayInformation();\n\t\t\tconsole.log();\n\t\t\tconsole.log(` RivetKit ${pkg.version} (${displayInfo.name})`);\n\t\t\tconsole.log(` - Endpoint: http://127.0.0.1:6420`);\n\t\t\tfor (const [k, v] of Object.entries(displayInfo.properties)) {\n\t\t\t\tconst padding = \" \".repeat(Math.max(0, 13 - k.length));\n\t\t\t\tconsole.log(` - ${k}:${padding}${v}`);\n\t\t\t}\n\t\t\tif (config.inspector?.enabled && managerDriver.inspector) {\n\t\t\t\tconsole.log(` - Inspector: ${getInspectorUrl(config)}`);\n\t\t\t}\n\t\t\tconsole.log();\n\t\t}\n\n\t\t// HACK: We need to find a better way to let the driver itself decide when to start the actor driver\n\t\t// Create runner\n\t\t//\n\t\t// Even though we do not use the return value, this is required to start the code that will handle incoming actors\n\t\tif (!config.disableActorDriver) {\n\t\t\tconst _actorDriver = driver.actor(\n\t\t\t\tthis.#config,\n\t\t\t\tconfig,\n\t\t\t\tmanagerDriver,\n\t\t\t\tclient,\n\t\t\t);\n\t\t}\n\n\t\t// Start server\n\t\tif (!config.disableServer) {\n\t\t\t(async () => {\n\t\t\t\tconst out = await crossPlatformServe(hono, undefined);\n\t\t\t\tupgradeWebSocket = out.upgradeWebSocket;\n\t\t\t})();\n\t\t}\n\n\t\treturn {\n\t\t\tclient,\n\t\t\tfetch: hono.fetch.bind(hono),\n\t\t};\n\t}\n}\n\nexport function setup<A extends RegistryActors>(\n\tinput: RegistryConfigInput<A>,\n): Registry<A> {\n\tconst config = RegistryConfigSchema.parse(input);\n\treturn new Registry(config);\n}\n\nexport type { RegistryConfig, RegistryActors, RunConfig, DriverConfig };\nexport { RegistryConfigSchema };\n"]}
|