rivetkit 2.0.3 → 2.0.4
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/README.md +11 -0
- package/dist/schemas/actor-persist/v1.ts +21 -24
- package/dist/schemas/client-protocol/v1.ts +6 -0
- package/dist/tsup/actor/errors.cjs +10 -2
- package/dist/tsup/actor/errors.cjs.map +1 -1
- package/dist/tsup/actor/errors.d.cts +17 -4
- package/dist/tsup/actor/errors.d.ts +17 -4
- package/dist/tsup/actor/errors.js +11 -3
- package/dist/tsup/{chunk-6PDXBYI5.js → chunk-3F2YSRJL.js} +8 -23
- package/dist/tsup/chunk-3F2YSRJL.js.map +1 -0
- package/dist/tsup/chunk-4CXBCT26.cjs +250 -0
- package/dist/tsup/chunk-4CXBCT26.cjs.map +1 -0
- package/dist/tsup/chunk-4R73YDN3.cjs +20 -0
- package/dist/tsup/chunk-4R73YDN3.cjs.map +1 -0
- package/dist/tsup/{chunk-OGAPU3UG.cjs → chunk-6LJT3QRL.cjs} +39 -25
- package/dist/tsup/chunk-6LJT3QRL.cjs.map +1 -0
- package/dist/tsup/{chunk-6WKQDDUD.cjs → chunk-GICQ3YCU.cjs} +143 -141
- package/dist/tsup/chunk-GICQ3YCU.cjs.map +1 -0
- package/dist/tsup/{chunk-FLMTTN27.js → chunk-H26RP6GD.js} +15 -8
- package/dist/tsup/chunk-H26RP6GD.js.map +1 -0
- package/dist/tsup/chunk-HI3HWJRC.js +20 -0
- package/dist/tsup/chunk-HI3HWJRC.js.map +1 -0
- package/dist/tsup/{chunk-4NSUQZ2H.js → chunk-HLLF4B4Q.js} +116 -114
- package/dist/tsup/chunk-HLLF4B4Q.js.map +1 -0
- package/dist/tsup/{chunk-FCCPJNMA.cjs → chunk-IH6CKNDW.cjs} +12 -27
- package/dist/tsup/chunk-IH6CKNDW.cjs.map +1 -0
- package/dist/tsup/chunk-LV2S3OU3.js +250 -0
- package/dist/tsup/chunk-LV2S3OU3.js.map +1 -0
- package/dist/tsup/{chunk-R2OPSKIV.cjs → chunk-LWNKVZG5.cjs} +20 -13
- package/dist/tsup/chunk-LWNKVZG5.cjs.map +1 -0
- package/dist/tsup/{chunk-INGJP237.js → chunk-NFU2BBT5.js} +102 -43
- package/dist/tsup/chunk-NFU2BBT5.js.map +1 -0
- package/dist/tsup/{chunk-3H7O2A7I.js → chunk-PQY7KKTL.js} +33 -19
- package/dist/tsup/chunk-PQY7KKTL.js.map +1 -0
- package/dist/tsup/{chunk-PO4VLDWA.js → chunk-QK72M5JB.js} +3 -5
- package/dist/tsup/chunk-QK72M5JB.js.map +1 -0
- package/dist/tsup/{chunk-TZJKSBUQ.cjs → chunk-QNNXFOQV.cjs} +3 -5
- package/dist/tsup/chunk-QNNXFOQV.cjs.map +1 -0
- package/dist/tsup/{chunk-GIR3AFFI.cjs → chunk-SBHHJ6QS.cjs} +102 -43
- package/dist/tsup/chunk-SBHHJ6QS.cjs.map +1 -0
- package/dist/tsup/chunk-TQ62L3X7.js +325 -0
- package/dist/tsup/chunk-TQ62L3X7.js.map +1 -0
- package/dist/tsup/chunk-VO7ZRVVD.cjs +6293 -0
- package/dist/tsup/chunk-VO7ZRVVD.cjs.map +1 -0
- package/dist/tsup/chunk-WHBPJNGW.cjs +325 -0
- package/dist/tsup/chunk-WHBPJNGW.cjs.map +1 -0
- package/dist/tsup/chunk-XJQHKJ4P.js +6293 -0
- package/dist/tsup/chunk-XJQHKJ4P.js.map +1 -0
- package/dist/tsup/client/mod.cjs +10 -10
- package/dist/tsup/client/mod.d.cts +7 -13
- package/dist/tsup/client/mod.d.ts +7 -13
- package/dist/tsup/client/mod.js +9 -9
- package/dist/tsup/common/log.cjs +12 -4
- package/dist/tsup/common/log.cjs.map +1 -1
- package/dist/tsup/common/log.d.cts +23 -17
- package/dist/tsup/common/log.d.ts +23 -17
- package/dist/tsup/common/log.js +15 -7
- package/dist/tsup/common/websocket.cjs +5 -5
- package/dist/tsup/common/websocket.js +4 -4
- package/dist/tsup/{common-CpqORuCq.d.cts → common-CXCe7s6i.d.cts} +2 -2
- package/dist/tsup/{common-CpqORuCq.d.ts → common-CXCe7s6i.d.ts} +2 -2
- package/dist/tsup/{connection-BwUMoe6n.d.ts → connection-BI-6UIBJ.d.ts} +196 -226
- package/dist/tsup/{connection-BR_Ve4ku.d.cts → connection-Dyd4NLGW.d.cts} +196 -226
- package/dist/tsup/driver-helpers/mod.cjs +6 -9
- package/dist/tsup/driver-helpers/mod.cjs.map +1 -1
- package/dist/tsup/driver-helpers/mod.d.cts +5 -6
- package/dist/tsup/driver-helpers/mod.d.ts +5 -6
- package/dist/tsup/driver-helpers/mod.js +6 -9
- package/dist/tsup/driver-test-suite/mod.cjs +155 -1363
- package/dist/tsup/driver-test-suite/mod.cjs.map +1 -1
- package/dist/tsup/driver-test-suite/mod.d.cts +11 -5
- package/dist/tsup/driver-test-suite/mod.d.ts +11 -5
- package/dist/tsup/driver-test-suite/mod.js +876 -2084
- package/dist/tsup/driver-test-suite/mod.js.map +1 -1
- package/dist/tsup/inspector/mod.cjs +6 -8
- package/dist/tsup/inspector/mod.cjs.map +1 -1
- package/dist/tsup/inspector/mod.d.cts +3 -3
- package/dist/tsup/inspector/mod.d.ts +3 -3
- package/dist/tsup/inspector/mod.js +8 -10
- package/dist/tsup/mod.cjs +9 -15
- package/dist/tsup/mod.cjs.map +1 -1
- package/dist/tsup/mod.d.cts +47 -42
- package/dist/tsup/mod.d.ts +47 -42
- package/dist/tsup/mod.js +10 -16
- package/dist/tsup/{router-endpoints-DAbqVFx2.d.ts → router-endpoints-BTe_Rsdn.d.cts} +2 -3
- package/dist/tsup/{router-endpoints-AYkXG8Tl.d.cts → router-endpoints-CBSrKHmo.d.ts} +2 -3
- package/dist/tsup/test/mod.cjs +10 -14
- package/dist/tsup/test/mod.cjs.map +1 -1
- package/dist/tsup/test/mod.d.cts +4 -5
- package/dist/tsup/test/mod.d.ts +4 -5
- package/dist/tsup/test/mod.js +9 -13
- package/dist/tsup/{utils-CT0cv4jd.d.ts → utils-fwx3o3K9.d.cts} +1 -0
- package/dist/tsup/{utils-CT0cv4jd.d.cts → utils-fwx3o3K9.d.ts} +1 -0
- package/dist/tsup/utils.cjs +3 -3
- package/dist/tsup/utils.d.cts +1 -1
- package/dist/tsup/utils.d.ts +1 -1
- package/dist/tsup/utils.js +2 -2
- package/package.json +4 -4
- package/src/actor/action.ts +1 -5
- package/src/actor/config.ts +27 -295
- package/src/actor/connection.ts +9 -12
- package/src/actor/context.ts +1 -4
- package/src/actor/definition.ts +7 -11
- package/src/actor/errors.ts +97 -35
- package/src/actor/generic-conn-driver.ts +28 -16
- package/src/actor/instance.ts +177 -133
- package/src/actor/log.ts +4 -13
- package/src/actor/mod.ts +0 -5
- package/src/actor/protocol/old.ts +42 -26
- package/src/actor/protocol/serde.ts +1 -1
- package/src/actor/router-endpoints.ts +41 -38
- package/src/actor/router.ts +20 -18
- package/src/actor/unstable-react.ts +1 -1
- package/src/actor/utils.ts +6 -2
- package/src/client/actor-common.ts +1 -1
- package/src/client/actor-conn.ts +152 -91
- package/src/client/actor-handle.ts +85 -25
- package/src/client/actor-query.ts +65 -0
- package/src/client/client.ts +29 -98
- package/src/client/config.ts +44 -0
- package/src/client/errors.ts +1 -0
- package/src/client/log.ts +2 -4
- package/src/client/mod.ts +16 -12
- package/src/client/raw-utils.ts +82 -25
- package/src/client/utils.ts +5 -3
- package/src/common/fake-event-source.ts +10 -9
- package/src/common/inline-websocket-adapter2.ts +39 -30
- package/src/common/log.ts +176 -101
- package/src/common/logfmt.ts +21 -30
- package/src/common/router.ts +12 -19
- package/src/common/utils.ts +27 -13
- package/src/common/websocket.ts +0 -1
- package/src/driver-helpers/mod.ts +1 -1
- package/src/driver-test-suite/log.ts +1 -3
- package/src/driver-test-suite/mod.ts +86 -60
- package/src/driver-test-suite/tests/actor-handle.ts +33 -0
- package/src/driver-test-suite/tests/manager-driver.ts +5 -3
- package/src/driver-test-suite/tests/raw-http-direct-registry.ts +227 -226
- package/src/driver-test-suite/tests/raw-websocket-direct-registry.ts +393 -392
- package/src/driver-test-suite/tests/request-access.ts +112 -126
- package/src/driver-test-suite/utils.ts +13 -10
- package/src/drivers/default.ts +7 -4
- package/src/drivers/engine/actor-driver.ts +22 -13
- package/src/drivers/engine/config.ts +2 -10
- package/src/drivers/engine/kv.ts +1 -1
- package/src/drivers/engine/log.ts +1 -3
- package/src/drivers/engine/mod.ts +2 -3
- package/src/drivers/file-system/actor.ts +1 -1
- package/src/drivers/file-system/global-state.ts +33 -20
- package/src/drivers/file-system/log.ts +1 -3
- package/src/drivers/file-system/manager.ts +31 -8
- package/src/inspector/config.ts +9 -4
- package/src/inspector/log.ts +1 -1
- package/src/inspector/manager.ts +2 -2
- package/src/inspector/utils.ts +1 -1
- package/src/manager/driver.ts +10 -2
- package/src/manager/hono-websocket-adapter.ts +21 -12
- package/src/manager/log.ts +2 -4
- package/src/manager/mod.ts +1 -1
- package/src/manager/router.ts +277 -1657
- package/src/manager-api/routes/actors-create.ts +16 -0
- package/src/manager-api/routes/actors-delete.ts +4 -0
- package/src/manager-api/routes/actors-get-by-id.ts +7 -0
- package/src/manager-api/routes/actors-get-or-create-by-id.ts +29 -0
- package/src/manager-api/routes/actors-get.ts +7 -0
- package/src/manager-api/routes/common.ts +18 -0
- package/src/mod.ts +0 -2
- package/src/registry/config.ts +1 -1
- package/src/registry/log.ts +2 -4
- package/src/registry/mod.ts +57 -24
- package/src/registry/run-config.ts +31 -33
- package/src/registry/serve.ts +4 -5
- package/src/remote-manager-driver/actor-http-client.ts +72 -0
- package/src/remote-manager-driver/actor-websocket-client.ts +63 -0
- package/src/remote-manager-driver/api-endpoints.ts +79 -0
- package/src/remote-manager-driver/api-utils.ts +43 -0
- package/src/remote-manager-driver/log.ts +5 -0
- package/src/remote-manager-driver/mod.ts +274 -0
- package/src/{drivers/engine → remote-manager-driver}/ws-proxy.ts +24 -14
- package/src/serde.ts +8 -2
- package/src/test/log.ts +1 -3
- package/src/test/mod.ts +17 -16
- package/dist/tsup/chunk-2CRLFV6Z.cjs +0 -202
- package/dist/tsup/chunk-2CRLFV6Z.cjs.map +0 -1
- package/dist/tsup/chunk-3H7O2A7I.js.map +0 -1
- package/dist/tsup/chunk-42I3OZ3Q.js +0 -15
- package/dist/tsup/chunk-42I3OZ3Q.js.map +0 -1
- package/dist/tsup/chunk-4NSUQZ2H.js.map +0 -1
- package/dist/tsup/chunk-6PDXBYI5.js.map +0 -1
- package/dist/tsup/chunk-6WKQDDUD.cjs.map +0 -1
- package/dist/tsup/chunk-CTBOSFUH.cjs +0 -116
- package/dist/tsup/chunk-CTBOSFUH.cjs.map +0 -1
- package/dist/tsup/chunk-EGVZZFE2.js +0 -2857
- package/dist/tsup/chunk-EGVZZFE2.js.map +0 -1
- package/dist/tsup/chunk-FCCPJNMA.cjs.map +0 -1
- package/dist/tsup/chunk-FLMTTN27.js.map +0 -1
- package/dist/tsup/chunk-GIR3AFFI.cjs.map +0 -1
- package/dist/tsup/chunk-INGJP237.js.map +0 -1
- package/dist/tsup/chunk-KJCJLKRM.js +0 -116
- package/dist/tsup/chunk-KJCJLKRM.js.map +0 -1
- package/dist/tsup/chunk-KUPQZYUQ.cjs +0 -15
- package/dist/tsup/chunk-KUPQZYUQ.cjs.map +0 -1
- package/dist/tsup/chunk-O2MBYIXO.cjs +0 -2857
- package/dist/tsup/chunk-O2MBYIXO.cjs.map +0 -1
- package/dist/tsup/chunk-OGAPU3UG.cjs.map +0 -1
- package/dist/tsup/chunk-OV6AYD4S.js +0 -4406
- package/dist/tsup/chunk-OV6AYD4S.js.map +0 -1
- package/dist/tsup/chunk-PO4VLDWA.js.map +0 -1
- package/dist/tsup/chunk-R2OPSKIV.cjs.map +0 -1
- package/dist/tsup/chunk-TZJKSBUQ.cjs.map +0 -1
- package/dist/tsup/chunk-UBUC5C3G.cjs +0 -189
- package/dist/tsup/chunk-UBUC5C3G.cjs.map +0 -1
- package/dist/tsup/chunk-UIM22YJL.cjs +0 -4406
- package/dist/tsup/chunk-UIM22YJL.cjs.map +0 -1
- package/dist/tsup/chunk-URVFQMYI.cjs +0 -230
- package/dist/tsup/chunk-URVFQMYI.cjs.map +0 -1
- package/dist/tsup/chunk-UVUPOS46.js +0 -230
- package/dist/tsup/chunk-UVUPOS46.js.map +0 -1
- package/dist/tsup/chunk-VRRHBNJC.js +0 -189
- package/dist/tsup/chunk-VRRHBNJC.js.map +0 -1
- package/dist/tsup/chunk-XFSS33EQ.js +0 -202
- package/dist/tsup/chunk-XFSS33EQ.js.map +0 -1
- package/src/client/http-client-driver.ts +0 -326
- package/src/driver-test-suite/test-inline-client-driver.ts +0 -402
- package/src/driver-test-suite/tests/actor-auth.ts +0 -591
- package/src/drivers/engine/api-endpoints.ts +0 -128
- package/src/drivers/engine/api-utils.ts +0 -70
- package/src/drivers/engine/manager-driver.ts +0 -391
- package/src/inline-client-driver/log.ts +0 -7
- package/src/inline-client-driver/mod.ts +0 -385
- package/src/manager/auth.ts +0 -121
- /package/src/{drivers/engine → actor}/keys.test.ts +0 -0
- /package/src/{drivers/engine → actor}/keys.ts +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/nathan/rivetkit/packages/rivetkit/dist/tsup/chunk-UIM22YJL.cjs","../../src/actor/config.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/common/inline-websocket-adapter2.ts","../../src/drivers/engine/actor-driver.ts","../../src/drivers/engine/keys.ts","../../src/drivers/engine/kv.ts","../../src/drivers/engine/log.ts","../../src/drivers/engine/config.ts","../../src/drivers/engine/manager-driver.ts","../../src/drivers/engine/api-utils.ts","../../src/drivers/engine/api-endpoints.ts","../../src/drivers/engine/ws-proxy.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/inline-client-driver/mod.ts","../../src/inline-client-driver/log.ts","../../src/inspector/manager.ts","../../src/drivers/file-system/mod.ts","../../src/drivers/default.ts","../../src/manager/router.ts","../../src/manager/auth.ts","../../src/registry/config.ts","../../src/registry/log.ts","../../src/registry/serve.ts","../../src/registry/mod.ts"],"names":["actor","logger","path","crypto","c","config","invariant","LOGGER_NAME","WebSocket","event","transformActor","Hono","_a","z"],"mappings":"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","file":"/Users/nathan/rivetkit/packages/rivetkit/dist/tsup/chunk-UIM22YJL.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\tundefined\n>;\n\nexport interface ActorTypes<\n\tTState,\n\tTConnParams,\n\tTConnState,\n\tTVars,\n\tTInput,\n\tTAuthData,\n\tTDatabase extends AnyDatabaseProvider,\n> {\n\tstate?: TState;\n\tconnParams?: TConnParams;\n\tconnState?: TConnState;\n\tvars?: TVars;\n\tinput?: TInput;\n\tauthData?: TAuthData;\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\tonAuth: z.function().optional(),\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<\n\tTState,\n\tTConnParams,\n\tTConnState,\n\tTVars,\n\tTInput,\n\tTAuthData,\n\tTDatabase,\n> =\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\tTAuthData,\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<\n\tTState,\n\tTConnParams,\n\tTConnState,\n\tTVars,\n\tTInput,\n\tTAuthData,\n\tTDatabase,\n> =\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\n// Creates auth config\n//\n// This must have only one or the other or else TAuthData will not be able to be inferred\ntype OnAuth<TConnParams, TAuthData> =\n\t| {\n\t\t\t/**\n\t\t\t * Called on the HTTP server before clients can interact with the actor.\n\t\t\t *\n\t\t\t * Only called for public endpoints. Calls to actors from within the backend\n\t\t\t * do not trigger this handler.\n\t\t\t *\n\t\t\t * Data returned from this handler will be available on `c.conn.auth`.\n\t\t\t *\n\t\t\t * This function is required for any public HTTP endpoint access. Use this hook\n\t\t\t * to validate client credentials and return authentication data that will be\n\t\t\t * available on connections. This runs on the HTTP server (not the actor)\n\t\t\t * in order to reduce load on the actor & prevent denial of server attacks\n\t\t\t * against individual actors.\n\t\t\t *\n\t\t\t * If you need access to actor state for authentication, use onBeforeConnect\n\t\t\t * with an empty onAuth function instead.\n\t\t\t *\n\t\t\t * You can also provide your own authentication middleware on your router if you\n\t\t\t * choose, then use onAuth to pass the authentication data (e.g. user ID) to the\n\t\t\t * actor itself.\n\t\t\t *\n\t\t\t * @param opts Authentication options including request and intent\n\t\t\t * @returns Authentication data to attach to connections (must be serializable)\n\t\t\t * @throws Throw an error to deny access to the actor\n\t\t\t */\n\t\t\tonAuth: (\n\t\t\t\topts: OnAuthOptions,\n\t\t\t\tparams: TConnParams,\n\t\t\t) => TAuthData | Promise<TAuthData>;\n\t }\n\t| Record<never, never>;\n\nexport interface Actions<\n\tTState,\n\tTConnParams,\n\tTConnState,\n\tTVars,\n\tTInput,\n\tTAuthData,\n\tTDatabase extends AnyDatabaseProvider,\n> {\n\t[Action: string]: (\n\t\tc: ActionContext<\n\t\t\tTState,\n\t\t\tTConnParams,\n\t\t\tTConnState,\n\t\t\tTVars,\n\t\t\tTInput,\n\t\t\tTAuthData,\n\t\t\tTDatabase\n\t\t>,\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\nexport interface OnAuthOptions {\n\trequest: Request;\n\t/**\n\t * @experimental\n\t */\n\tintents: Set<AuthIntent>;\n}\n\ninterface BaseActorConfig<\n\tTState,\n\tTConnParams,\n\tTConnState,\n\tTVars,\n\tTInput,\n\tTAuthData,\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\tTAuthData,\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<\n\t\t\tTState,\n\t\t\tTConnParams,\n\t\t\tTConnState,\n\t\t\tTVars,\n\t\t\tTInput,\n\t\t\tTAuthData,\n\t\t\tTDatabase\n\t\t>,\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<\n\t\t\tTState,\n\t\t\tTConnParams,\n\t\t\tTConnState,\n\t\t\tTVars,\n\t\t\tTInput,\n\t\t\tTAuthData,\n\t\t\tTDatabase\n\t\t>,\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<\n\t\t\tTState,\n\t\t\tTConnParams,\n\t\t\tTConnState,\n\t\t\tTVars,\n\t\t\tTInput,\n\t\t\tTAuthData,\n\t\t\tTDatabase\n\t\t>,\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<\n\t\t\tTState,\n\t\t\tTConnParams,\n\t\t\tTConnState,\n\t\t\tTVars,\n\t\t\tTInput,\n\t\t\tTAuthData,\n\t\t\tTDatabase\n\t\t>,\n\t\tnewState: TState,\n\t) => void;\n\n\t/**\n\t * Called before a client connects to the actor.\n\t *\n\t * Unlike onAuth, this handler is still called for both internal and\n\t * public clients.\n\t *\n\t * Use this hook to determine if a connection should be accepted\n\t * and to initialize connection-specific state. Unlike onAuth, this runs\n\t * on the actor and has access to actor state, but uses slightly\n\t * more resources on the actor rather than authenticating with onAuth.\n\t *\n\t * For authentication without actor state access, prefer onAuth.\n\t *\n\t * For authentication with actor state, use onBeforeConnect with an empty\n\t * onAuth handler.\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<\n\t\t\tTState,\n\t\t\tTConnParams,\n\t\t\tTConnState,\n\t\t\tTVars,\n\t\t\tTInput,\n\t\t\tTAuthData,\n\t\t\tTDatabase\n\t\t>,\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<\n\t\t\tTState,\n\t\t\tTConnParams,\n\t\t\tTConnState,\n\t\t\tTVars,\n\t\t\tTInput,\n\t\t\tTAuthData,\n\t\t\tTDatabase\n\t\t>,\n\t\tconn: Conn<\n\t\t\tTState,\n\t\t\tTConnParams,\n\t\t\tTConnState,\n\t\t\tTVars,\n\t\t\tTInput,\n\t\t\tTAuthData,\n\t\t\tTDatabase\n\t\t>,\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<\n\t\t\tTState,\n\t\t\tTConnParams,\n\t\t\tTConnState,\n\t\t\tTVars,\n\t\t\tTInput,\n\t\t\tTAuthData,\n\t\t\tTDatabase\n\t\t>,\n\t\tconn: Conn<\n\t\t\tTState,\n\t\t\tTConnParams,\n\t\t\tTConnState,\n\t\t\tTVars,\n\t\t\tTInput,\n\t\t\tTAuthData,\n\t\t\tTDatabase\n\t\t>,\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<\n\t\t\tTState,\n\t\t\tTConnParams,\n\t\t\tTConnState,\n\t\t\tTVars,\n\t\t\tTInput,\n\t\t\tTAuthData,\n\t\t\tTDatabase\n\t\t>,\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<\n\t\t\tTState,\n\t\t\tTConnParams,\n\t\t\tTConnState,\n\t\t\tTVars,\n\t\t\tTInput,\n\t\t\tTAuthData,\n\t\t\tTDatabase\n\t\t>,\n\t\trequest: Request,\n\t\topts: { auth: TAuthData },\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<\n\t\t\tTState,\n\t\t\tTConnParams,\n\t\t\tTConnState,\n\t\t\tTVars,\n\t\t\tTInput,\n\t\t\tTAuthData,\n\t\t\tTDatabase\n\t\t>,\n\t\twebsocket: UniversalWebSocket,\n\t\topts: { request: Request; auth: TAuthData },\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\tTAuthData,\n\tTDatabase extends AnyDatabaseProvider,\n> = Omit<\n\tz.infer<typeof ActorConfigSchema>,\n\t| \"actions\"\n\t| \"onAuth\"\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\tTAuthData,\n\t\tTDatabase,\n\t\tActions<\n\t\t\tTState,\n\t\t\tTConnParams,\n\t\t\tTConnState,\n\t\t\tTVars,\n\t\t\tTInput,\n\t\t\tTAuthData,\n\t\t\tTDatabase\n\t\t>\n\t> &\n\tOnAuth<TConnParams, TAuthData> &\n\tCreateState<\n\t\tTState,\n\t\tTConnParams,\n\t\tTConnState,\n\t\tTVars,\n\t\tTInput,\n\t\tTAuthData,\n\t\tTDatabase\n\t> &\n\tCreateConnState<\n\t\tTState,\n\t\tTConnParams,\n\t\tTConnState,\n\t\tTVars,\n\t\tTInput,\n\t\tTAuthData,\n\t\tTDatabase\n\t> &\n\tCreateVars<\n\t\tTState,\n\t\tTConnParams,\n\t\tTConnState,\n\t\tTVars,\n\t\tTInput,\n\t\tTAuthData,\n\t\tTDatabase\n\t> &\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\tTAuthData = 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\tTAuthData,\n\t\tTDatabase\n\t> = Record<never, never>,\n> = {\n\ttypes?: ActorTypes<\n\t\tTState,\n\t\tTConnParams,\n\t\tTConnState,\n\t\tTVars,\n\t\tTInput,\n\t\tTAuthData,\n\t\tTDatabase\n\t>;\n} & Omit<\n\tz.input<typeof ActorConfigSchema>,\n\t| \"actions\"\n\t| \"onAuth\"\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\tTAuthData,\n\t\tTDatabase,\n\t\tTActions\n\t> &\n\tOnAuth<TConnParams, TAuthData> &\n\tCreateState<\n\t\tTState,\n\t\tTConnParams,\n\t\tTConnState,\n\t\tTVars,\n\t\tTInput,\n\t\tTAuthData,\n\t\tTDatabase\n\t> &\n\tCreateConnState<\n\t\tTState,\n\t\tTConnParams,\n\t\tTConnState,\n\t\tTVars,\n\t\tTInput,\n\t\tTAuthData,\n\t\tTDatabase\n\t> &\n\tCreateVars<\n\t\tTState,\n\t\tTConnParams,\n\t\tTConnState,\n\t\tTVars,\n\t\tTInput,\n\t\tTAuthData,\n\t\tTDatabase\n\t> &\n\tActorDatabaseConfig<TDatabase>;\n\n// For testing type definitions:\nexport function test<\n\tTState,\n\tTConnParams,\n\tTConnState,\n\tTVars,\n\tTInput,\n\tTAuthData,\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\tTAuthData,\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\tTAuthData,\n\t\tTDatabase,\n\t\tTActions\n\t>,\n): ActorConfig<\n\tTState,\n\tTConnParams,\n\tTConnState,\n\tTVars,\n\tTInput,\n\tTAuthData,\n\tTDatabase\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\tTAuthData,\n\t\tTDatabase\n\t>;\n\treturn config;\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 { logger } 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\tlogger().warn(\"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\tlogger().debug(\"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\tlogger().debug(\"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\tlogger().debug(\"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\tlogger().debug(\"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\tlogger().warn(\"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\tlogger().warn(\"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\t_actor: 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\tlogger().warn(\"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\t_actor: 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\tlogger().warn(\"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\t_actor: 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\tlogger().warn(\"missing sse stream for disconnect\", { connId: conn.id });\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\t_actor: 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\tlogger().warn(\"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 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 { logger } 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(logger()));\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});\n\n\t\tlogger().debug(\"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\tlogger().debug(\"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(secureInspector(runConfig), async (c, next) => {\n\t\t\t\t\tconst inspector = (await actorDriver.loadActor(c.env.actorId))\n\t\t\t\t\t\t.inspector;\n\t\t\t\t\tinvariant(inspector, \"inspector not supported on this platform\");\n\n\t\t\t\t\tc.set(\"inspector\", inspector);\n\t\t\t\t\tawait next();\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(\n\t\thandleRouteError.bind(undefined, {\n\t\t\t// All headers to this endpoint are considered secure, so we can enable the expose internal error header for requests from the internal client\n\t\t\tenableExposeInternalError: true,\n\t\t}),\n\t);\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 { 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(\"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 interface HandleRouterErrorOpts {\n\tenableExposeInternalError?: boolean;\n}\n\nexport function handleRouteError(\n\topts: HandleRouterErrorOpts,\n\terror: unknown,\n\tc: HonoContext,\n) {\n\tconst exposeInternalError =\n\t\topts.enableExposeInternalError && getRequestExposeInternalError(c.req.raw);\n\n\tconst { statusCode, 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 (err) {\n\t\tlogger().debug(\"failed to extract encoding\", {\n\t\t\terror: stringifyError(err),\n\t\t});\n\t\tencoding = \"json\";\n\t}\n\n\tconst output = serializeWithEncoding(\n\t\tencoding,\n\t\t{\n\t\t\tcode,\n\t\t\tmessage,\n\t\t\tmetadata: bufferToArrayBuffer(cbor.encode(metadata)),\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://studio.rivet.gg\");\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\tTAuthData,\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\tTAuthData,\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\tTAuthData,\n\t\tTDatabase,\n\t\tTActions\n\t>,\n): ActorDefinition<\n\tTState,\n\tTConnParams,\n\tTConnState,\n\tTVars,\n\tTInput,\n\tTAuthData,\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\tTAuthData,\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 { 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 const LOGGER_NAME = \"fake-event-source2\";\n\nexport function logger() {\n\treturn getLogger(LOGGER_NAME);\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(\"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(\"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(\"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(\"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(\"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(\"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(\"fake websocket initializing\");\n\n\t\t\t// Call the handler's onOpen method\n\t\t\tlogger().debug(\"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(\"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(\"socket no longer open, dropping queued messages\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlogger().debug(\n\t\t\t\t\t`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(\"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(\"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(\"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(\"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(`error in ${type} event listener`, { error: err });\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tlogger().debug(`no ${type} listeners registered, buffering event`);\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(\"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(\"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(\"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(\"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(\"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(\"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(\"error in error event\", { error: err });\n\t\t}\n\n\t\t// Log the error\n\t\tlogger().error(\"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 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 { EncodingSchema } from \"@/actor/protocol/serde\";\nimport type { Client } from \"@/client/client\";\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 { deserializeActorKey } from \"./keys\";\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(\"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(\"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(\"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\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};\n\n\t\t// Create and start runner\n\t\tthis.#runner = new Runner(runnerConfig);\n\t\tthis.#runner.start();\n\t\tlogger().debug(\"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(\"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(\"runner actor started\", { actorId, name, key });\n\t}\n\n\tasync #runnerOnActorStop(actorId: string, generation: number): Promise<void> {\n\t\tlogger().debug(\"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(\"runner actor stopped\", { actorId });\n\t}\n\n\tasync #runnerFetch(actorId: string, request: Request): Promise<Response> {\n\t\tlogger().debug(\"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(\"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(\"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(\"stopping engine actor driver\");\n\t\tawait this.#runner.shutdown(immediate);\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","export const KEYS = {\n\tPERSIST_DATA: Uint8Array.from([1, 1]),\n};\n","import { getLogger } from \"@/common/log\";\n\nexport const LOGGER_NAME = \"driver-engine\";\n\nexport function logger() {\n\treturn getLogger(LOGGER_NAME);\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:7080\",\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 ot 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\taddresses: z\n\t\t\t.record(\n\t\t\t\tz.object({\n\t\t\t\t\thost: z.string(),\n\t\t\t\t\tport: z.number(),\n\t\t\t\t}),\n\t\t\t)\n\t\t\t.default({ main: { host: \"127.0.0.1\", port: 5051 } }),\n\t})\n\t.default({});\n\nexport type InputConfig = z.input<typeof ConfigSchema>;\nexport type Config = z.infer<typeof ConfigSchema>;\n","import * as cbor from \"cbor-x\";\nimport type { Context as HonoContext } from \"hono\";\nimport invariant from \"invariant\";\nimport { ActorAlreadyExists } from \"@/actor/errors\";\nimport {\n\tHEADER_AUTH_DATA,\n\tHEADER_CONN_PARAMS,\n\tHEADER_ENCODING,\n\tHEADER_EXPOSE_INTERNAL_ERROR,\n} from \"@/actor/router-endpoints\";\nimport { generateRandomString } from \"@/actor/utils\";\nimport { importWebSocket } from \"@/common/websocket\";\nimport type {\n\tActorOutput,\n\tCreateInput,\n\tGetForIdInput,\n\tGetOrCreateWithKeyInput,\n\tGetWithKeyInput,\n\tManagerDriver,\n} from \"@/driver-helpers/mod\";\nimport { type Encoding, noopNext, type RunConfig } from \"@/mod\";\nimport {\n\tcreateActor,\n\tdestroyActor,\n\tgetActor,\n\tgetActorById,\n\tgetOrCreateActorById,\n} from \"./api-endpoints\";\nimport { EngineApiError } from \"./api-utils\";\nimport type { Config } from \"./config\";\nimport { deserializeActorKey, serializeActorKey } from \"./keys\";\nimport { logger } from \"./log\";\nimport { createWebSocketProxy } from \"./ws-proxy\";\n\nexport class EngineManagerDriver implements ManagerDriver {\n\t#config: Config;\n\t#runConfig: RunConfig;\n\t#importWebSocketPromise: Promise<typeof WebSocket>;\n\n\tconstructor(config: Config, runConfig: RunConfig) {\n\t\tthis.#config = config;\n\t\tthis.#runConfig = runConfig;\n\t\tif (!this.#runConfig.inspector.token()) {\n\t\t\tconst token = generateRandomString();\n\t\t\tthis.#runConfig.inspector.token = () => token;\n\t\t}\n\t\tthis.#importWebSocketPromise = importWebSocket();\n\t}\n\n\tasync sendRequest(actorId: string, actorRequest: Request): Promise<Response> {\n\t\tlogger().debug(\"sending request to actor via guard\", {\n\t\t\tactorId,\n\t\t\tmethod: actorRequest.method,\n\t\t\turl: actorRequest.url,\n\t\t});\n\n\t\treturn this.#forwardHttpRequest(actorRequest, actorId);\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<WebSocket> {\n\t\tconst WebSocket = await this.#importWebSocketPromise;\n\n\t\t// WebSocket connections go through guard\n\t\tconst guardUrl = `${this.#config.endpoint}${path}`;\n\n\t\tlogger().debug(\"opening websocket to actor via guard\", {\n\t\t\tactorId,\n\t\t\tpath,\n\t\t\tguardUrl,\n\t\t});\n\n\t\t// Create WebSocket connection\n\t\tconst ws = new WebSocket(guardUrl, {\n\t\t\theaders: buildGuardHeadersForWebSocket(actorId, encoding, params),\n\t\t});\n\n\t\tlogger().debug(\"websocket connection opened\", { actorId });\n\n\t\treturn ws;\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\tlogger().debug(\"forwarding request to actor via guard\", {\n\t\t\tactorId,\n\t\t\tmethod: actorRequest.method,\n\t\t\turl: actorRequest.url,\n\t\t\thasBody: !!actorRequest.body,\n\t\t});\n\n\t\treturn this.#forwardHttpRequest(actorRequest, actorId);\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.#runConfig.getUpgradeWebSocket?.();\n\t\tinvariant(upgradeWebSocket, \"missing getUpgradeWebSocket\");\n\n\t\tconst guardUrl = `${this.#config.endpoint}${path}`;\n\t\tconst wsGuardUrl = guardUrl.replace(\"http://\", \"ws://\");\n\n\t\tlogger().debug(\"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\textraStartupLog() {\n\t\treturn {\n\t\t\tengine: this.#config.endpoint,\n\t\t\tnamespace: this.#config.namespace,\n\t\t\trunner: this.#config.runnerName,\n\t\t\taddress: Object.values(this.#config.addresses)\n\t\t\t\t.map((v) => `${v.host}:${v.port}`)\n\t\t\t\t.join(\", \"),\n\t\t};\n\t}\n\n\tasync getForId({\n\t\tc,\n\t\tname,\n\t\tactorId,\n\t}: GetForIdInput): Promise<ActorOutput | undefined> {\n\t\t// 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(\"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(\"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(\"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\t\"getOrCreateWithKey: getting or creating actor via engine api\",\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tkey,\n\t\t\t},\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(\"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\t// Check if actor with the same name and key already exists\n\t\tconst existingActor = await this.getWithKey({ c, name, key });\n\t\tif (existingActor) {\n\t\t\tthrow new ActorAlreadyExists(name, key);\n\t\t}\n\n\t\tlogger().info(\"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(\"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(\"destroying actor via engine api\", { actorId });\n\n\t\tawait destroyActor(this.#config, actorId);\n\n\t\tlogger().info(\"actor destroyed\", { actorId });\n\t}\n\n\tasync #forwardHttpRequest(\n\t\tactorRequest: Request,\n\t\tactorId: string,\n\t): Promise<Response> {\n\t\t// Route through guard port\n\t\tconst url = new URL(actorRequest.url);\n\t\tconst guardUrl = `${this.#config.endpoint}${url.pathname}${url.search}`;\n\n\t\t// Handle body properly based on method and presence\n\t\tlet bodyToSend: ArrayBuffer | null = null;\n\t\tconst guardHeaders = buildGuardHeadersForHttp(actorRequest, actorId);\n\n\t\tif (\n\t\t\tactorRequest.body &&\n\t\t\tactorRequest.method !== \"GET\" &&\n\t\t\tactorRequest.method !== \"HEAD\"\n\t\t) {\n\t\t\tif (actorRequest.bodyUsed) {\n\t\t\t\tthrow new Error(\"Request body has already been consumed\");\n\t\t\t}\n\n\t\t\t// TODO: This buffers the entire request in memory every time. We\n\t\t\t// need to properly implement streaming bodies.\n\t\t\t// Clone and read the body to ensure it can be sent\n\t\t\tconst clonedRequest = actorRequest.clone();\n\t\t\tbodyToSend = await clonedRequest.arrayBuffer();\n\n\t\t\t// If this is a streaming request, we need to convert the headers\n\t\t\t// for the basic array buffer\n\t\t\tguardHeaders.delete(\"transfer-encoding\");\n\t\t\tguardHeaders.set(\n\t\t\t\t\"content-length\",\n\t\t\t\tString((bodyToSend as ArrayBuffer).byteLength),\n\t\t\t);\n\t\t}\n\n\t\tconst guardRequest = new Request(guardUrl, {\n\t\t\tmethod: actorRequest.method,\n\t\t\theaders: guardHeaders,\n\t\t\tbody: bodyToSend,\n\t\t});\n\n\t\treturn mutableResponse(await fetch(guardRequest));\n\t}\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\nfunction 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_EXPOSE_INTERNAL_ERROR] = \"true\";\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 { 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\n// Helper function for making API calls\nexport async function apiCall<TInput = unknown, TOutput = unknown>(\n\tendpoint: string,\n\tnamespace: string,\n\tmethod: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\",\n\tpath: string,\n\tbody?: TInput,\n): Promise<TOutput> {\n\tconst url = `${endpoint}${path}${path.includes(\"?\") ? \"&\" : \"?\"}namespace=${encodeURIComponent(namespace)}`;\n\n\tconst options: RequestInit = {\n\t\tmethod,\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t},\n\t};\n\n\tif (body !== undefined && method !== \"GET\") {\n\t\toptions.body = JSON.stringify(body);\n\t}\n\n\tlogger().debug(\"making api call\", { method, url });\n\n\tconst response = await fetch(url, options);\n\n\tif (!response.ok) {\n\t\tconst errorText = await response.text();\n\t\tlogger().error(\"api call failed\", {\n\t\t\tstatus: response.status,\n\t\t\tstatusText: response.statusText,\n\t\t\terror: errorText,\n\t\t\tmethod,\n\t\t\tpath,\n\t\t});\n\n\t\t// Try to parse error response\n\t\ttry {\n\t\t\tconst errorData = JSON.parse(errorText);\n\t\t\tif (errorData.kind === \"error\" && errorData.group && errorData.code) {\n\t\t\t\tthrow new EngineApiError(\n\t\t\t\t\terrorData.group,\n\t\t\t\t\terrorData.code,\n\t\t\t\t\terrorData.message,\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (parseError) {\n\t\t\t// If parsing fails or it's not our expected error format, continue\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t`API call failed: ${response.status} ${response.statusText}`,\n\t\t);\n\t}\n\n\treturn response.json() as Promise<TOutput>;\n}\n","import { apiCall } from \"./api-utils\";\nimport type { Config } from \"./config\";\nimport { serializeActorKey } from \"./keys\";\n\n// MARK: Common types\nexport type RivetId = string;\n\nexport interface Actor {\n\tactor_id: RivetId;\n\tname: string;\n\tkey: string;\n\tnamespace_id: RivetId;\n\trunner_name_selector: string;\n\tcreate_ts: number;\n\tconnectable_ts?: number | null;\n\tdestroy_ts?: number | null;\n\tsleep_ts?: number | null;\n\tstart_ts?: number | null;\n}\n\nexport interface ActorsGetResponse {\n\tactor: Actor;\n}\n\nexport interface ActorsGetByIdResponse {\n\tactor_id?: RivetId | null;\n}\n\nexport interface ActorsGetOrCreateResponse {\n\tactor: Actor;\n\tcreated: boolean;\n}\n\nexport interface ActorsGetOrCreateByIdResponse {\n\tactor_id: RivetId;\n\tcreated: boolean;\n}\n\nexport interface ActorsCreateRequest {\n\tname: string;\n\trunner_name_selector: string;\n\tcrash_policy: string;\n\tkey?: string | null;\n\tinput?: string | null;\n}\n\nexport interface ActorsCreateResponse {\n\tactor: Actor;\n}\n\n// MARK: Get actor\nexport async function getActor(\n\tconfig: Config,\n\tactorId: RivetId,\n): Promise<ActorsGetResponse> {\n\treturn apiCall<never, ActorsGetResponse>(\n\t\tconfig.endpoint,\n\t\tconfig.namespace,\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: Config,\n\tname: string,\n\tkey: string[],\n): Promise<ActorsGetByIdResponse> {\n\tconst serializedKey = serializeActorKey(key);\n\treturn apiCall<never, ActorsGetByIdResponse>(\n\t\tconfig.endpoint,\n\t\tconfig.namespace,\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 interface ActorsGetOrCreateByIdRequest {\n\tname: string;\n\tkey: string;\n\trunner_name_selector: string;\n\tcrash_policy: string;\n\tinput?: string | null;\n}\n\nexport async function getOrCreateActorById(\n\tconfig: Config,\n\trequest: ActorsGetOrCreateByIdRequest,\n): Promise<ActorsGetOrCreateByIdResponse> {\n\treturn apiCall<ActorsGetOrCreateByIdRequest, ActorsGetOrCreateByIdResponse>(\n\t\tconfig.endpoint,\n\t\tconfig.namespace,\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: Config,\n\trequest: ActorsCreateRequest,\n): Promise<ActorsCreateResponse> {\n\treturn apiCall<ActorsCreateRequest, ActorsCreateResponse>(\n\t\tconfig.endpoint,\n\t\tconfig.namespace,\n\t\t\"POST\",\n\t\t`/actors`,\n\t\trequest,\n\t);\n}\n\n// MARK: Destroy actor\nexport type ActorsDeleteResponse = {};\n\nexport async function destroyActor(\n\tconfig: Config,\n\tactorId: RivetId,\n): Promise<ActorsDeleteResponse> {\n\treturn apiCall<never, ActorsDeleteResponse>(\n\t\tconfig.endpoint,\n\t\tconfig.namespace,\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 invariant from \"invariant\";\nimport type { CloseEvent } from \"ws\";\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(\"client websocket connected\", { targetUrl });\n\n\t\t\tif (clientWs.readyState !== 1) {\n\t\t\t\tlogger().warn(\"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(\"target websocket connected\", { targetUrl });\n\n\t\t\t\t\tif (clientWs.readyState !== 1) {\n\t\t\t\t\t\tlogger().warn(\"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(\"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(\"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(\"target websocket error\", { targetUrl, error });\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(\"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(\"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(\"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(\"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(\"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 { 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 { EngineActorDriver } from \"./actor-driver\";\nimport { ConfigSchema, type InputConfig } from \"./config\";\nimport { EngineManagerDriver } from \"./manager-driver\";\n\nexport { EngineActorDriver } from \"./actor-driver\";\nexport { type Config, ConfigSchema, type InputConfig } from \"./config\";\nexport { EngineManagerDriver } from \"./manager-driver\";\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 EngineManagerDriver(config, 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 { logger } 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 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(\"failed to count actors\", { error });\n\t\t\t}\n\n\t\t\tlogger().debug(\"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(\"failed to cleanup temp files\", { error: err });\n\t\t\t}\n\t\t} else {\n\t\t\tlogger().debug(\"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(\"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(\"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(\"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\tlogger().warn(\"already called onRunnerStart\");\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(\"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(`Actor does exist and cannot be started: ${actorId}`);\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(\"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(\"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(\"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(\"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(\"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(\"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(\"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(\"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(\"cleaned up stale temp file\", { file: tempFile });\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\tlogger().debug(\"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(\"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 const LOGGER_NAME = \"driver-fs\";\n\nexport function logger() {\n\treturn getLogger(LOGGER_NAME);\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 { createInlineClientDriver } from \"@/inline-client-driver/mod\";\nimport { ManagerInspector } from \"@/inspector/manager\";\nimport { type Actor, ActorFeature, type ActorId } from \"@/inspector/mod\";\nimport {\n\ttype DriverConfig,\n\ttype Encoding,\n\tPATH_CONNECT_WEBSOCKET,\n\tPATH_RAW_WEBSOCKET_PREFIX,\n\ttype RegistryConfig,\n\ttype RunConfig,\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(createInlineClientDriver(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<WebSocket> {\n\t\t// TODO:\n\n\t\t// Handle raw WebSocket paths\n\t\tif (path === 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 (path.startsWith(PATH_RAW_WEBSOCKET_PREFIX)) {\n\t\t\t// Handle websocket proxy\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\tauthData: 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\tif (path === 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\tauthData,\n\t\t\t);\n\n\t\t\treturn upgradeWebSocket(() => wsHandler)(c, noopNext());\n\t\t} else if (path.startsWith(PATH_RAW_WEBSOCKET_PREFIX)) {\n\t\t\t// Handle websocket proxy\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\tauthData,\n\t\t\t);\n\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(\"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\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 * as cbor from \"cbor-x\";\nimport type { Context as HonoContext } from \"hono\";\nimport invariant from \"invariant\";\nimport onChange from \"on-change\";\nimport type { WebSocket } from \"ws\";\nimport * as errors from \"@/actor/errors\";\nimport type { Encoding } from \"@/actor/protocol/serde\";\nimport {\n\tPATH_CONNECT_WEBSOCKET,\n\tPATH_RAW_WEBSOCKET_PREFIX,\n} from \"@/actor/router\";\nimport {\n\tHEADER_CONN_ID,\n\tHEADER_CONN_PARAMS,\n\tHEADER_CONN_TOKEN,\n\tHEADER_ENCODING,\n\tHEADER_EXPOSE_INTERNAL_ERROR,\n} from \"@/actor/router-endpoints\";\nimport { assertUnreachable } from \"@/actor/utils\";\nimport type { ClientDriver } from \"@/client/client\";\nimport { ActorError as ClientActorError } from \"@/client/errors\";\nimport { sendHttpRequest } from \"@/client/utils\";\nimport { importEventSource } from \"@/common/eventsource\";\nimport type { UniversalEventSource } from \"@/common/eventsource-interface\";\nimport { deconstructError } from \"@/common/utils\";\nimport type { ManagerDriver } from \"@/manager/driver\";\nimport type { ActorQuery } from \"@/manager/protocol/query\";\nimport type { RunConfig } from \"@/mod\";\nimport type * as protocol from \"@/schemas/client-protocol/mod\";\nimport {\n\tHTTP_ACTION_REQUEST_VERSIONED,\n\tHTTP_ACTION_RESPONSE_VERSIONED,\n\tTO_CLIENT_VERSIONED,\n\tTO_SERVER_VERSIONED,\n} from \"@/schemas/client-protocol/versioned\";\nimport { bufferToArrayBuffer, httpUserAgent } from \"@/utils\";\nimport { logger } from \"./log\";\n\n/**\n * Client driver that calls the manager driver inline.\n *\n * This is only applicable to standalone & coordinated topologies.\n *\n * This driver can access private resources.\n *\n * This driver serves a double purpose as:\n * - Providing the client for the internal requests\n * - Provide the driver for the manager HTTP router (see manager/router.ts)\n */\nexport function createInlineClientDriver(\n\tmanagerDriver: ManagerDriver,\n): ClientDriver {\n\tconst driver: ClientDriver = {\n\t\taction: async <Args extends Array<unknown> = unknown[], Response = unknown>(\n\t\t\tc: HonoContext | undefined,\n\t\t\tactorQuery: ActorQuery,\n\t\t\tencoding: Encoding,\n\t\t\tparams: unknown,\n\t\t\tactionName: string,\n\t\t\targs: Args,\n\t\t\topts: { signal?: AbortSignal },\n\t\t): Promise<Response> => {\n\t\t\ttry {\n\t\t\t\t// Get the actor ID\n\t\t\t\tconst { actorId } = await queryActor(c, actorQuery, managerDriver);\n\t\t\t\tlogger().debug(\"found actor for action\", { actorId });\n\t\t\t\tinvariant(actorId, \"Missing actor ID\");\n\n\t\t\t\t// Invoke the action\n\t\t\t\tlogger().debug(\"handling action\", { actionName, encoding });\n\t\t\t\tconst responseData = await sendHttpRequest<\n\t\t\t\t\tprotocol.HttpActionRequest,\n\t\t\t\t\tprotocol.HttpActionResponse\n\t\t\t\t>({\n\t\t\t\t\turl: `http://actor/action/${encodeURIComponent(actionName)}`,\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t[HEADER_ENCODING]: encoding,\n\t\t\t\t\t\t...(params !== undefined\n\t\t\t\t\t\t\t? { [HEADER_CONN_PARAMS]: JSON.stringify(params) }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t[HEADER_EXPOSE_INTERNAL_ERROR]: \"true\",\n\t\t\t\t\t},\n\t\t\t\t\tbody: {\n\t\t\t\t\t\targs: bufferToArrayBuffer(cbor.encode(args)),\n\t\t\t\t\t} satisfies protocol.HttpActionRequest,\n\t\t\t\t\tencoding: encoding,\n\t\t\t\t\tcustomFetch: managerDriver.sendRequest.bind(managerDriver, actorId),\n\t\t\t\t\tsignal: opts?.signal,\n\t\t\t\t\trequestVersionedDataHandler: HTTP_ACTION_REQUEST_VERSIONED,\n\t\t\t\t\tresponseVersionedDataHandler: HTTP_ACTION_RESPONSE_VERSIONED,\n\t\t\t\t});\n\n\t\t\t\treturn cbor.decode(new Uint8Array(responseData.output));\n\t\t\t} catch (err) {\n\t\t\t\t// Standardize to ClientActorError instead of the native backend error\n\t\t\t\tconst { code, message, metadata } = deconstructError(\n\t\t\t\t\terr,\n\t\t\t\t\tlogger(),\n\t\t\t\t\t{},\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t\tconst x = new ClientActorError(code, message, metadata);\n\t\t\t\tthrow new ClientActorError(code, message, metadata);\n\t\t\t}\n\t\t},\n\n\t\tresolveActorId: async (\n\t\t\tc: HonoContext | undefined,\n\t\t\tactorQuery: ActorQuery,\n\t\t\t_encodingKind: Encoding,\n\t\t): Promise<string> => {\n\t\t\t// Get the actor ID\n\t\t\tconst { actorId } = await queryActor(c, actorQuery, managerDriver);\n\t\t\tlogger().debug(\"resolved actor\", { actorId });\n\t\t\tinvariant(actorId, \"missing actor ID\");\n\n\t\t\treturn actorId;\n\t\t},\n\n\t\tconnectWebSocket: async (\n\t\t\tc: HonoContext | undefined,\n\t\t\tactorQuery: ActorQuery,\n\t\t\tencodingKind: Encoding,\n\t\t\tparams?: unknown,\n\t\t): Promise<WebSocket> => {\n\t\t\t// Get the actor ID\n\t\t\tconst { actorId } = await queryActor(c, actorQuery, managerDriver);\n\t\t\tlogger().debug(\"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(\"opening websocket\", { actorId, encoding: encodingKind });\n\n\t\t\t// Open WebSocket\n\t\t\tconst ws = await managerDriver.openWebSocket(\n\t\t\t\tPATH_CONNECT_WEBSOCKET,\n\t\t\t\tactorId,\n\t\t\t\tencodingKind,\n\t\t\t\tparams,\n\t\t\t);\n\n\t\t\t// Node & browser WebSocket types are incompatible\n\t\t\treturn ws as any;\n\t\t},\n\n\t\tconnectSse: async (\n\t\t\tc: HonoContext | undefined,\n\t\t\tactorQuery: ActorQuery,\n\t\t\tencodingKind: Encoding,\n\t\t\tparams: unknown,\n\t\t): Promise<UniversalEventSource> => {\n\t\t\t// Get the actor ID\n\t\t\tconst { actorId } = await queryActor(c, actorQuery, managerDriver);\n\t\t\tlogger().debug(\"found actor for sse connection\", { actorId });\n\t\t\tinvariant(actorId, \"Missing actor ID\");\n\n\t\t\tlogger().debug(\"opening sse connection\", {\n\t\t\t\tactorId,\n\t\t\t\tencoding: encodingKind,\n\t\t\t});\n\n\t\t\tconst EventSourceClass = await importEventSource();\n\n\t\t\tconst eventSource = new EventSourceClass(\"http://actor/connect/sse\", {\n\t\t\t\tfetch: (input, init) => {\n\t\t\t\t\treturn fetch(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]: encodingKind,\n\t\t\t\t\t\t\t...(params !== undefined\n\t\t\t\t\t\t\t\t? { [HEADER_CONN_PARAMS]: JSON.stringify(params) }\n\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t\t[HEADER_EXPOSE_INTERNAL_ERROR]: \"true\",\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t}) as UniversalEventSource;\n\n\t\t\treturn eventSource;\n\t\t},\n\n\t\tsendHttpMessage: async (\n\t\t\tc: HonoContext | undefined,\n\t\t\tactorId: string,\n\t\t\tencoding: Encoding,\n\t\t\tconnectionId: string,\n\t\t\tconnectionToken: string,\n\t\t\tmessage: protocol.ToServer,\n\t\t): Promise<void> => {\n\t\t\tlogger().debug(\"sending http message\", { actorId, connectionId });\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]: encoding,\n\t\t\t\t\t[HEADER_CONN_ID]: connectionId,\n\t\t\t\t\t[HEADER_CONN_TOKEN]: connectionToken,\n\t\t\t\t\t[HEADER_EXPOSE_INTERNAL_ERROR]: \"true\",\n\t\t\t\t},\n\t\t\t\tbody: message,\n\t\t\t\tencoding,\n\t\t\t\tskipParseResponse: true,\n\t\t\t\tcustomFetch: managerDriver.sendRequest.bind(managerDriver, actorId),\n\t\t\t\trequestVersionedDataHandler: TO_SERVER_VERSIONED,\n\t\t\t\tresponseVersionedDataHandler: TO_CLIENT_VERSIONED,\n\t\t\t});\n\t\t},\n\n\t\trawHttpRequest: async (\n\t\t\tc: HonoContext | undefined,\n\t\t\tactorQuery: ActorQuery,\n\t\t\tencoding: Encoding,\n\t\t\tparams: unknown,\n\t\t\tpath: string,\n\t\t\tinit: RequestInit,\n\t\t): Promise<Response> => {\n\t\t\ttry {\n\t\t\t\t// Get the actor ID\n\t\t\t\tconst { actorId } = await queryActor(c, actorQuery, managerDriver);\n\t\t\t\tlogger().debug(\"found actor for raw http\", { actorId });\n\t\t\t\tinvariant(actorId, \"Missing actor ID\");\n\n\t\t\t\t// Build the URL with normalized path\n\t\t\t\tconst normalizedPath = path.startsWith(\"/\") ? path.slice(1) : path;\n\t\t\t\tconst url = new URL(`http://actor/raw/http/${normalizedPath}`);\n\n\t\t\t\t// Forward conn params if provided\n\t\t\t\tconst proxyRequestHeaders = new Headers(init.headers);\n\t\t\t\tif (params) {\n\t\t\t\t\tproxyRequestHeaders.set(HEADER_CONN_PARAMS, JSON.stringify(params));\n\t\t\t\t}\n\n\t\t\t\t// Forward the request to the actor\n\t\t\t\tconst proxyRequest = new Request(url, {\n\t\t\t\t\t...init,\n\t\t\t\t\theaders: proxyRequestHeaders,\n\t\t\t\t});\n\n\t\t\t\treturn await managerDriver.sendRequest(actorId, proxyRequest);\n\t\t\t} catch (err) {\n\t\t\t\t// Standardize to ClientActorError instead of the native backend error\n\t\t\t\tconst { code, message, metadata } = deconstructError(\n\t\t\t\t\terr,\n\t\t\t\t\tlogger(),\n\t\t\t\t\t{},\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t\tthrow new ClientActorError(code, message, metadata);\n\t\t\t}\n\t\t},\n\n\t\trawWebSocket: async (\n\t\t\tc: HonoContext | undefined,\n\t\t\tactorQuery: ActorQuery,\n\t\t\tencoding: Encoding,\n\t\t\tparams: unknown,\n\t\t\tpath: string,\n\t\t\tprotocols: string | string[] | undefined,\n\t\t): Promise<WebSocket> => {\n\t\t\t// Get the actor ID\n\t\t\tconst { actorId } = await queryActor(c, actorQuery, managerDriver);\n\t\t\tlogger().debug(\"found actor for action\", { actorId });\n\t\t\tinvariant(actorId, \"Missing actor ID\");\n\n\t\t\t// Normalize path to match raw HTTP behavior\n\t\t\tconst normalizedPath = path.startsWith(\"/\") ? path.slice(1) : path;\n\t\t\tlogger().debug(\"opening websocket\", {\n\t\t\t\tactorId,\n\t\t\t\tencoding,\n\t\t\t\tpath: normalizedPath,\n\t\t\t});\n\n\t\t\t// Open WebSocket\n\t\t\tconst ws = await managerDriver.openWebSocket(\n\t\t\t\t`${PATH_RAW_WEBSOCKET_PREFIX}${normalizedPath}`,\n\t\t\t\tactorId,\n\t\t\t\tencoding,\n\t\t\t\tparams,\n\t\t\t);\n\n\t\t\t// Node & browser WebSocket types are incompatible\n\t\t\treturn ws as any;\n\t\t},\n\t};\n\n\treturn driver;\n}\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\tdriver: ManagerDriver,\n): Promise<{ actorId: string }> {\n\tlogger().debug(\"querying actor\", { query });\n\tlet actorOutput: { actorId: string };\n\tif (\"getForId\" in query) {\n\t\tconst output = await driver.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 driver.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 driver.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 driver.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(\"actor query result\", {\n\t\tactorId: actorOutput.actorId,\n\t});\n\treturn { actorId: actorOutput.actorId };\n}\n\n/**\n * Removes the on-change library's proxy recursively from a value so we can clone it with `structuredClone`.\n */\nfunction unproxyRecursive<T>(objProxied: T): T {\n\tconst obj = onChange.target<any>(objProxied);\n\n\t// Short circuit if this object was proxied\n\t//\n\t// If the reference is different, then this value was proxied and no\n\t// nested values are proxied\n\tif (obj !== objProxied) return obj;\n\n\t// Handle null/undefined\n\tif (!obj || typeof obj !== \"object\") {\n\t\treturn obj;\n\t}\n\n\t// Handle arrays\n\tif (Array.isArray(obj)) {\n\t\treturn obj.map((x) => unproxyRecursive<any>(x)) as T;\n\t}\n\n\t// Handle objects\n\tconst result: any = {};\n\tfor (const key in obj) {\n\t\tresult[key] = unproxyRecursive<any>(obj[key]);\n\t}\n\n\treturn result;\n}\n","import { getLogger } from \"@/common//log\";\n\nexport const LOGGER_NAME = \"inline-client-driver\";\n\nexport function logger() {\n\treturn getLogger(LOGGER_NAME);\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(\"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(\"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 { logger } 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.engine || 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\tlogger().debug(\"using rivet engine driver\", { endpoint: engineEndpoint });\n\t\treturn createEngineDriver({ endpoint: engineEndpoint });\n\t}\n\n\tlogger().debug(\"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 {\n\tHono,\n\ttype Context as HonoContext,\n\ttype MiddlewareHandler,\n} from \"hono\";\nimport { cors } from \"hono/cors\";\nimport { streamSSE } from \"hono/streaming\";\nimport type { WSContext } from \"hono/ws\";\nimport invariant from \"invariant\";\nimport type { CloseEvent, MessageEvent, WebSocket } from \"ws\";\nimport { z } from \"zod\";\nimport * as errors from \"@/actor/errors\";\nimport type { Transport } from \"@/actor/protocol/old\";\nimport type { Encoding } from \"@/actor/protocol/serde\";\nimport {\n\tPATH_CONNECT_WEBSOCKET,\n\tPATH_RAW_WEBSOCKET_PREFIX,\n} from \"@/actor/router\";\nimport {\n\tALLOWED_PUBLIC_HEADERS,\n\tgetRequestEncoding,\n\tgetRequestQuery,\n\tHEADER_ACTOR_ID,\n\tHEADER_ACTOR_QUERY,\n\tHEADER_AUTH_DATA,\n\tHEADER_CONN_ID,\n\tHEADER_CONN_PARAMS,\n\tHEADER_CONN_TOKEN,\n\tHEADER_ENCODING,\n} from \"@/actor/router-endpoints\";\nimport type { ClientDriver } from \"@/client/client\";\nimport {\n\thandleRouteError,\n\thandleRouteNotFound,\n\tloggerMiddleware,\n} from \"@/common/router\";\nimport {\n\ttype DeconstructedError,\n\tdeconstructError,\n\tnoopNext,\n\tstringifyError,\n} from \"@/common/utils\";\nimport { createManagerInspectorRouter } from \"@/inspector/manager\";\nimport { secureInspector } from \"@/inspector/utils\";\nimport type { UpgradeWebSocketArgs } from \"@/mod\";\nimport type { RegistryConfig } from \"@/registry/config\";\nimport type { RunConfig } from \"@/registry/run-config\";\nimport type * as protocol from \"@/schemas/client-protocol/mod\";\nimport {\n\tHTTP_RESOLVE_RESPONSE_VERSIONED,\n\tTO_CLIENT_VERSIONED,\n} from \"@/schemas/client-protocol/versioned\";\nimport { serializeWithEncoding } from \"@/serde\";\nimport { bufferToArrayBuffer } from \"@/utils\";\nimport { authenticateEndpoint } from \"./auth\";\nimport type { ManagerDriver } from \"./driver\";\nimport { logger } from \"./log\";\nimport type { ActorQuery } from \"./protocol/query\";\nimport {\n\tActorQuerySchema,\n\tConnectRequestSchema,\n\tConnectWebSocketRequestSchema,\n\tConnMessageRequestSchema,\n\tResolveRequestSchema,\n} from \"./protocol/query\";\n\n/**\n * Parse WebSocket protocol headers for query and connection parameters\n */\nfunction parseWebSocketProtocols(protocols: string | undefined): {\n\tqueryRaw: string | undefined;\n\tencodingRaw: string | undefined;\n\tconnParamsRaw: string | undefined;\n} {\n\tlet queryRaw: string | undefined;\n\tlet encodingRaw: string | undefined;\n\tlet connParamsRaw: string | undefined;\n\n\tif (protocols) {\n\t\tconst protocolList = protocols.split(\",\").map((p) => p.trim());\n\t\tfor (const protocol of protocolList) {\n\t\t\tif (protocol.startsWith(\"query.\")) {\n\t\t\t\tqueryRaw = decodeURIComponent(protocol.substring(\"query.\".length));\n\t\t\t} else if (protocol.startsWith(\"encoding.\")) {\n\t\t\t\tencodingRaw = protocol.substring(\"encoding.\".length);\n\t\t\t} else if (protocol.startsWith(\"conn_params.\")) {\n\t\t\t\tconnParamsRaw = decodeURIComponent(\n\t\t\t\t\tprotocol.substring(\"conn_params.\".length),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { queryRaw, encodingRaw, connParamsRaw };\n}\n\nconst OPENAPI_ENCODING = z.string().openapi({\n\tdescription: \"The encoding format to use for the response (json, cbor)\",\n\texample: \"json\",\n});\n\nconst OPENAPI_ACTOR_QUERY = z.string().openapi({\n\tdescription: \"Actor query information\",\n});\n\nconst OPENAPI_CONN_PARAMS = z.string().openapi({\n\tdescription: \"Connection parameters\",\n});\n\nconst OPENAPI_ACTOR_ID = z.string().openapi({\n\tdescription: \"Actor ID (used in some endpoints)\",\n\texample: \"actor-123456\",\n});\n\nconst OPENAPI_CONN_ID = z.string().openapi({\n\tdescription: \"Connection ID\",\n\texample: \"conn-123456\",\n});\n\nconst OPENAPI_CONN_TOKEN = z.string().openapi({\n\tdescription: \"Connection token\",\n});\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\n/**\n * Only use `validateBody` to `true` if you need to export OpenAPI JSON.\n *\n * If left enabled for production, this will cause errors. We disable JSON validation since:\n * - It prevents us from proxying requests, since validating the body requires consuming the body so we can't forward the body\n * - We validate all types at the actor router layer since most requests are proxied\n */\nexport function createManagerRouter(\n\tregistryConfig: RegistryConfig,\n\trunConfig: RunConfig,\n\tinlineClientDriver: ClientDriver,\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\tif (runConfig.cors || runConfig.inspector?.cors) {\n\t\trouter.use(\"*\", async (c, next) => {\n\t\t\t// Don't apply to WebSocket routes\n\t\t\t// HACK: This could be insecure if we had a varargs path. We have to check the path suffix for WS since we don't know the path that this router was mounted.\n\t\t\t// HACK: Checking \"/websocket/\" is not safe, but there is no other way to handle this if we don't know the base path this is\n\t\t\t// mounted on\n\t\t\tconst path = c.req.path;\n\t\t\tif (\n\t\t\t\tpath.endsWith(\"/actors/connect/websocket\") ||\n\t\t\t\tpath.includes(\"/actors/raw/websocket/\") ||\n\t\t\t\t// inspectors implement their own CORS handling\n\t\t\t\tpath.endsWith(\"/inspect\") ||\n\t\t\t\tpath.endsWith(\"/actors/inspect\")\n\t\t\t) {\n\t\t\t\treturn next();\n\t\t\t}\n\n\t\t\treturn cors({\n\t\t\t\t...(runConfig.cors ?? {}),\n\t\t\t\t...(runConfig.inspector?.cors ?? {}),\n\t\t\t\torigin: (origin, c) => {\n\t\t\t\t\tconst inspectorOrigin = runConfig.inspector?.cors?.origin;\n\n\t\t\t\t\tif (inspectorOrigin !== undefined) {\n\t\t\t\t\t\tif (typeof inspectorOrigin === \"function\") {\n\t\t\t\t\t\t\tconst allowed = inspectorOrigin(origin, c);\n\t\t\t\t\t\t\tif (allowed) return allowed;\n\t\t\t\t\t\t\t// Proceed to next CORS config if none provided\n\t\t\t\t\t\t} else if (Array.isArray(inspectorOrigin)) {\n\t\t\t\t\t\t\treturn inspectorOrigin.includes(origin) ? origin : undefined;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn inspectorOrigin;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (runConfig.cors?.origin !== undefined) {\n\t\t\t\t\t\tif (typeof runConfig.cors.origin === \"function\") {\n\t\t\t\t\t\t\tconst allowed = runConfig.cors.origin(origin, c);\n\t\t\t\t\t\t\tif (allowed) return allowed;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn runConfig.cors.origin as string;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn null;\n\t\t\t\t},\n\t\t\t\tallowMethods: (origin, c) => {\n\t\t\t\t\tconst inspectorMethods = runConfig.inspector?.cors?.allowMethods;\n\t\t\t\t\tif (inspectorMethods) {\n\t\t\t\t\t\tif (typeof inspectorMethods === \"function\") {\n\t\t\t\t\t\t\treturn inspectorMethods(origin, c);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn inspectorMethods;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (runConfig.cors?.allowMethods) {\n\t\t\t\t\t\tif (typeof runConfig.cors.allowMethods === \"function\") {\n\t\t\t\t\t\t\treturn runConfig.cors.allowMethods(origin, c);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn runConfig.cors.allowMethods;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn [];\n\t\t\t\t},\n\t\t\t\tallowHeaders: [\n\t\t\t\t\t...(runConfig.cors?.allowHeaders ?? []),\n\t\t\t\t\t...(runConfig.inspector?.cors?.allowHeaders ?? []),\n\t\t\t\t\t...ALLOWED_PUBLIC_HEADERS,\n\t\t\t\t\t\"Content-Type\",\n\t\t\t\t\t\"User-Agent\",\n\t\t\t\t],\n\t\t\t\tcredentials:\n\t\t\t\t\trunConfig.cors?.credentials ??\n\t\t\t\t\trunConfig.inspector?.cors?.credentials ??\n\t\t\t\t\ttrue,\n\t\t\t})(c, next);\n\t\t});\n\t}\n\n\t// GET /\n\trouter.get(\"/\", (c: HonoContext) => {\n\t\treturn c.text(\n\t\t\t\"This is an RivetKit registry.\\n\\nLearn more at https://rivetkit.org\",\n\t\t);\n\t});\n\n\t// POST /actors/resolve\n\t{\n\t\tconst ResolveQuerySchema = z\n\t\t\t.object({\n\t\t\t\tquery: z.any().openapi({\n\t\t\t\t\texample: { getForId: { actorId: \"actor-123\" } },\n\t\t\t\t}),\n\t\t\t})\n\t\t\t.openapi(\"ResolveQuery\");\n\n\t\tconst ResolveResponseSchema = z\n\t\t\t.object({\n\t\t\t\ti: z.string().openapi({\n\t\t\t\t\texample: \"actor-123\",\n\t\t\t\t}),\n\t\t\t})\n\t\t\t.openapi(\"ResolveResponse\");\n\n\t\tconst resolveRoute = createRoute({\n\t\t\tmethod: \"post\",\n\t\t\tpath: \"/actors/resolve\",\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: ResolveQuerySchema,\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\theaders: z.object({\n\t\t\t\t\t[HEADER_ACTOR_QUERY]: OPENAPI_ACTOR_QUERY,\n\t\t\t\t}),\n\t\t\t},\n\t\t\tresponses: buildOpenApiResponses(ResolveResponseSchema, validateBody),\n\t\t});\n\n\t\trouter.openapi(resolveRoute, (c) =>\n\t\t\thandleResolveRequest(c, registryConfig, managerDriver),\n\t\t);\n\t}\n\n\t// GET /actors/connect/websocket\n\t{\n\t\t// HACK: WebSockets don't work with mounts, so we need to dynamically match the trailing path\n\t\trouter.use(\"*\", (c, next) => {\n\t\t\tif (c.req.path.endsWith(\"/actors/connect/websocket\")) {\n\t\t\t\treturn handleWebSocketConnectRequest(\n\t\t\t\t\tc,\n\t\t\t\t\tregistryConfig,\n\t\t\t\t\trunConfig,\n\t\t\t\t\tmanagerDriver,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn next();\n\t\t});\n\n\t\t// This route is a noop, just used to generate docs\n\t\tconst wsRoute = createRoute({\n\t\t\tmethod: \"get\",\n\t\t\tpath: \"/actors/connect/websocket\",\n\t\t\tresponses: {\n\t\t\t\t101: {\n\t\t\t\t\tdescription: \"WebSocket upgrade\",\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\n\t\trouter.openapi(wsRoute, () => {\n\t\t\tthrow new Error(\"Should be unreachable\");\n\t\t});\n\t}\n\n\t// GET /actors/connect/sse\n\t{\n\t\tconst sseRoute = createRoute({\n\t\t\tmethod: \"get\",\n\t\t\tpath: \"/actors/connect/sse\",\n\t\t\trequest: {\n\t\t\t\theaders: z.object({\n\t\t\t\t\t[HEADER_ENCODING]: OPENAPI_ENCODING,\n\t\t\t\t\t[HEADER_ACTOR_QUERY]: OPENAPI_ACTOR_QUERY,\n\t\t\t\t\t[HEADER_CONN_PARAMS]: OPENAPI_CONN_PARAMS.optional(),\n\t\t\t\t}),\n\t\t\t},\n\t\t\tresponses: {\n\t\t\t\t200: {\n\t\t\t\t\tdescription: \"SSE stream\",\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\"text/event-stream\": {\n\t\t\t\t\t\t\tschema: z.unknown(),\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\trouter.openapi(sseRoute, (c) =>\n\t\t\thandleSseConnectRequest(c, registryConfig, runConfig, managerDriver),\n\t\t);\n\t}\n\n\t// POST /actors/action/:action\n\t{\n\t\tconst ActionParamsSchema = z\n\t\t\t.object({\n\t\t\t\taction: z.string().openapi({\n\t\t\t\t\tparam: {\n\t\t\t\t\t\tname: \"action\",\n\t\t\t\t\t\tin: \"path\",\n\t\t\t\t\t},\n\t\t\t\t\texample: \"myAction\",\n\t\t\t\t}),\n\t\t\t})\n\t\t\t.openapi(\"ActionParams\");\n\n\t\tconst ActionRequestSchema = z\n\t\t\t.object({\n\t\t\t\tquery: z.any().openapi({\n\t\t\t\t\texample: { getForId: { actorId: \"actor-123\" } },\n\t\t\t\t}),\n\t\t\t\tbody: z\n\t\t\t\t\t.any()\n\t\t\t\t\t.optional()\n\t\t\t\t\t.openapi({\n\t\t\t\t\t\texample: { param1: \"value1\", param2: 123 },\n\t\t\t\t\t}),\n\t\t\t})\n\t\t\t.openapi(\"ActionRequest\");\n\n\t\tconst ActionResponseSchema = z.any().openapi(\"ActionResponse\");\n\n\t\tconst actionRoute = createRoute({\n\t\t\tmethod: \"post\",\n\t\t\tpath: \"/actors/actions/{action}\",\n\t\t\trequest: {\n\t\t\t\tparams: ActionParamsSchema,\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: ActionRequestSchema,\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\theaders: z.object({\n\t\t\t\t\t[HEADER_ENCODING]: OPENAPI_ENCODING,\n\t\t\t\t\t[HEADER_CONN_PARAMS]: OPENAPI_CONN_PARAMS.optional(),\n\t\t\t\t}),\n\t\t\t},\n\t\t\tresponses: buildOpenApiResponses(ActionResponseSchema, validateBody),\n\t\t});\n\n\t\trouter.openapi(actionRoute, (c) =>\n\t\t\thandleActionRequest(c, registryConfig, runConfig, managerDriver),\n\t\t);\n\t}\n\n\t// POST /actors/message\n\t{\n\t\tconst ConnectionMessageRequestSchema = z\n\t\t\t.object({\n\t\t\t\tmessage: z.any().openapi({\n\t\t\t\t\texample: { type: \"message\", content: \"Hello, actor!\" },\n\t\t\t\t}),\n\t\t\t})\n\t\t\t.openapi(\"ConnectionMessageRequest\");\n\n\t\tconst ConnectionMessageResponseSchema = z\n\t\t\t.any()\n\t\t\t.openapi(\"ConnectionMessageResponse\");\n\n\t\tconst messageRoute = createRoute({\n\t\t\tmethod: \"post\",\n\t\t\tpath: \"/actors/message\",\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: ConnectionMessageRequestSchema,\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\theaders: z.object({\n\t\t\t\t\t[HEADER_ACTOR_ID]: OPENAPI_ACTOR_ID,\n\t\t\t\t\t[HEADER_CONN_ID]: OPENAPI_CONN_ID,\n\t\t\t\t\t[HEADER_ENCODING]: OPENAPI_ENCODING,\n\t\t\t\t\t[HEADER_CONN_TOKEN]: OPENAPI_CONN_TOKEN,\n\t\t\t\t}),\n\t\t\t},\n\t\t\tresponses: buildOpenApiResponses(\n\t\t\t\tConnectionMessageResponseSchema,\n\t\t\t\tvalidateBody,\n\t\t\t),\n\t\t});\n\n\t\trouter.openapi(messageRoute, (c) =>\n\t\t\thandleMessageRequest(c, registryConfig, runConfig, managerDriver),\n\t\t);\n\t}\n\n\t// Raw HTTP endpoints - /actors/raw/http/*\n\t{\n\t\tconst RawHttpRequestBodySchema = z.any().optional().openapi({\n\t\t\tdescription: \"Raw request body (can be any content type)\",\n\t\t});\n\n\t\tconst RawHttpResponseSchema = z.any().openapi({\n\t\t\tdescription: \"Raw response from actor's onFetch handler\",\n\t\t});\n\n\t\t// Define common route config\n\t\tconst rawHttpRouteConfig = {\n\t\t\tpath: \"/actors/raw/http/*\",\n\t\t\trequest: {\n\t\t\t\theaders: z.object({\n\t\t\t\t\t[HEADER_ACTOR_QUERY]: OPENAPI_ACTOR_QUERY.optional(),\n\t\t\t\t\t[HEADER_CONN_PARAMS]: OPENAPI_CONN_PARAMS.optional(),\n\t\t\t\t}),\n\t\t\t\tbody: {\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\"*/*\": {\n\t\t\t\t\t\t\tschema: RawHttpRequestBodySchema,\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\tresponses: {\n\t\t\t\t200: {\n\t\t\t\t\tdescription: \"Success - response from actor's onFetch handler\",\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\"*/*\": {\n\t\t\t\t\t\t\tschema: RawHttpResponseSchema,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t404: {\n\t\t\t\t\tdescription: \"Actor does not have an onFetch handler\",\n\t\t\t\t},\n\t\t\t\t500: {\n\t\t\t\t\tdescription: \"Internal server error or invalid response from actor\",\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\n\t\t// Create routes for each HTTP method\n\t\tconst httpMethods = [\n\t\t\t\"get\",\n\t\t\t\"post\",\n\t\t\t\"put\",\n\t\t\t\"delete\",\n\t\t\t\"patch\",\n\t\t\t\"head\",\n\t\t\t\"options\",\n\t\t] as const;\n\t\tfor (const method of httpMethods) {\n\t\t\tconst route = createRoute({\n\t\t\t\tmethod,\n\t\t\t\t...rawHttpRouteConfig,\n\t\t\t});\n\n\t\t\trouter.openapi(route, async (c) => {\n\t\t\t\treturn handleRawHttpRequest(\n\t\t\t\t\tc,\n\t\t\t\t\tregistryConfig,\n\t\t\t\t\trunConfig,\n\t\t\t\t\tmanagerDriver,\n\t\t\t\t);\n\t\t\t});\n\t\t}\n\t}\n\n\t// Raw WebSocket endpoint - /actors/raw/websocket/*\n\t{\n\t\t// HACK: WebSockets don't work with mounts, so we need to dynamically match the trailing path\n\t\trouter.use(\"*\", async (c, next) => {\n\t\t\tif (c.req.path.includes(\"/raw/websocket/\")) {\n\t\t\t\treturn handleRawWebSocketRequest(\n\t\t\t\t\tc,\n\t\t\t\t\tregistryConfig,\n\t\t\t\t\trunConfig,\n\t\t\t\t\tmanagerDriver,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn next();\n\t\t});\n\n\t\t// This route is a noop, just used to generate docs\n\t\tconst rawWebSocketRoute = createRoute({\n\t\t\tmethod: \"get\",\n\t\t\tpath: \"/actors/raw/websocket/*\",\n\t\t\trequest: {},\n\t\t\tresponses: {\n\t\t\t\t101: {\n\t\t\t\t\tdescription: \"WebSocket upgrade successful\",\n\t\t\t\t},\n\t\t\t\t400: {\n\t\t\t\t\tdescription: \"WebSockets not enabled or invalid request\",\n\t\t\t\t},\n\t\t\t\t404: {\n\t\t\t\t\tdescription: \"Actor does not have an onWebSocket handler\",\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\n\t\trouter.openapi(rawWebSocketRoute, () => {\n\t\t\tthrow new Error(\"Should be unreachable\");\n\t\t});\n\t}\n\n\tif (runConfig.inspector?.enabled) {\n\t\trouter.route(\n\t\t\t\"/actors/inspect\",\n\t\t\tnew Hono()\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\tuniversalActorProxy({\n\t\t\t\t\t\tregistryConfig,\n\t\t\t\t\t\trunConfig,\n\t\t\t\t\t\tdriver: managerDriver,\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t\t.all(\"/\", (c) =>\n\t\t\t\t\t// this should be handled by the actor proxy, but just in case\n\t\t\t\t\tc.text(\"Unreachable.\", 404),\n\t\t\t\t),\n\t\t);\n\t\trouter.route(\n\t\t\t\"/inspect\",\n\t\t\tnew Hono()\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 = managerDriver.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\tawait next();\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t\t.route(\"/\", createManagerInspectorRouter()),\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(\"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 ((inlineClientDriver as any)[method] as any)(\n\t\t\t\t\t...args,\n\t\t\t\t);\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\tactorQuery: actorQueryRaw,\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\tactorQuery: 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 actorQuery = JSON.parse(actorQueryRaw);\n\t\t\t\tconst params =\n\t\t\t\t\tparamsRaw !== undefined ? JSON.parse(paramsRaw) : undefined;\n\n\t\t\t\tlogger().debug(\"received test inline driver websocket\", {\n\t\t\t\t\tactorQuery,\n\t\t\t\t\tparams,\n\t\t\t\t\tencodingKind,\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 = inlineClientDriver.connectWebSocket(\n\t\t\t\t\tundefined,\n\t\t\t\t\tactorQuery,\n\t\t\t\t\tencodingKind,\n\t\t\t\t\tparams,\n\t\t\t\t\tundefined,\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.get(\".test/inline-driver/raw-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\tactorQuery: actorQueryRaw,\n\t\t\t\t\tparams: paramsRaw,\n\t\t\t\t\tencodingKind,\n\t\t\t\t\tpath,\n\t\t\t\t\tprotocols: protocolsRaw,\n\t\t\t\t} = c.req.query() as {\n\t\t\t\t\tactorQuery: string;\n\t\t\t\t\tparams?: string;\n\t\t\t\t\tencodingKind: Encoding;\n\t\t\t\t\tpath: string;\n\t\t\t\t\tprotocols?: string;\n\t\t\t\t};\n\t\t\t\tconst actorQuery = JSON.parse(actorQueryRaw);\n\t\t\t\tconst params =\n\t\t\t\t\tparamsRaw !== undefined ? JSON.parse(paramsRaw) : undefined;\n\t\t\t\tconst protocols =\n\t\t\t\t\tprotocolsRaw !== undefined ? JSON.parse(protocolsRaw) : undefined;\n\n\t\t\t\tlogger().debug(\"received test inline driver raw websocket\", {\n\t\t\t\t\tactorQuery,\n\t\t\t\t\tparams,\n\t\t\t\t\tencodingKind,\n\t\t\t\t\tpath,\n\t\t\t\t\tprotocols,\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\tlogger().debug(\"calling inlineClientDriver.rawWebSocket\");\n\t\t\t\tconst clientWsPromise = inlineClientDriver.rawWebSocket(\n\t\t\t\t\tundefined,\n\t\t\t\t\tactorQuery,\n\t\t\t\t\tencodingKind,\n\t\t\t\t\tparams,\n\t\t\t\t\tpath,\n\t\t\t\t\tprotocols,\n\t\t\t\t\tundefined,\n\t\t\t\t);\n\n\t\t\t\tlogger().debug(\"calling createTestWebSocketProxy\");\n\t\t\t\treturn await createTestWebSocketProxy(clientWsPromise, \"raw\");\n\t\t\t})(c, noopNext());\n\t\t});\n\n\t\t// Raw HTTP endpoint for test inline driver\n\t\trouter.all(\".test/inline-driver/raw-http/*\", async (c) => {\n\t\t\t// Extract parameters from headers\n\t\t\tconst actorQueryHeader = c.req.header(HEADER_ACTOR_QUERY);\n\t\t\tconst paramsHeader = c.req.header(HEADER_CONN_PARAMS);\n\t\t\tconst encodingHeader = c.req.header(HEADER_ENCODING);\n\n\t\t\tif (!actorQueryHeader || !encodingHeader) {\n\t\t\t\treturn c.text(\"Missing required headers\", 400);\n\t\t\t}\n\n\t\t\tconst actorQuery = JSON.parse(actorQueryHeader);\n\t\t\tconst params = paramsHeader ? JSON.parse(paramsHeader) : undefined;\n\t\t\tconst encoding = encodingHeader as Encoding;\n\n\t\t\t// Extract the path after /raw-http/\n\t\t\tconst fullPath = c.req.path;\n\t\t\tconst pathOnly =\n\t\t\t\tfullPath.split(\"/.test/inline-driver/raw-http/\")[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(\"received test inline driver raw http\", {\n\t\t\t\tactorQuery,\n\t\t\t\tparams,\n\t\t\t\tencoding,\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 inlineClientDriver.rawHttpRequest(\n\t\t\t\t\tundefined,\n\t\t\t\t\tactorQuery,\n\t\t\t\t\tencoding,\n\t\t\t\t\tparams,\n\t\t\t\t\tpathWithQuery,\n\t\t\t\t\t{\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\tundefined,\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(\"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\t// Mount on both / and /registry\n\t//\n\t// We do this because the default requests are to `/registry/*`.\n\t//\n\t// If using `app.fetch` directly in a non-hono router, paths\n\t// might not be truncated so they'll come to this router as\n\t// `/registry/*`. If mounted correctly in Hono, requests will\n\t// come in at the root as `/*`.\n\tconst mountedRouter = new Hono();\n\tmountedRouter.route(\"/\", router);\n\tmountedRouter.route(\"/registry\", router);\n\n\t// IMPORTANT: These must be on `mountedRouter` instead of `router` or else they will not be called.\n\tmountedRouter.notFound(handleRouteNotFound);\n\tmountedRouter.onError(handleRouteError.bind(undefined, {}));\n\n\treturn { router: mountedRouter, openapi: router };\n}\n\nexport interface TestInlineDriverCallRequest {\n\tencoding: Encoding;\n\ttransport: Transport;\n\tmethod: string;\n\targs: unknown[];\n}\n\nexport type TestInlineDriverCallResponse<T> =\n\t| {\n\t\t\tok: T;\n\t }\n\t| {\n\t\t\terr: DeconstructedError;\n\t };\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,\n\tquery: ActorQuery,\n\tdriver: ManagerDriver,\n): Promise<{ actorId: string }> {\n\tlogger().debug(\"querying actor\", { query });\n\tlet actorOutput: { actorId: string };\n\tif (\"getForId\" in query) {\n\t\tconst output = await driver.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 driver.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 driver.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 driver.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(\"actor query result\", {\n\t\tactorId: actorOutput.actorId,\n\t});\n\treturn { actorId: actorOutput.actorId };\n}\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<WebSocket>,\n\tconnectionType: string,\n): Promise<UpgradeWebSocketArgs> {\n\t// Store a reference to the resolved WebSocket\n\tlet clientWs: WebSocket | null = null;\n\ttry {\n\t\t// Resolve the client WebSocket promise\n\t\tlogger().debug(\"awaiting client websocket promise\");\n\t\tconst ws = await clientWsPromise;\n\t\tclientWs = ws;\n\t\tlogger().debug(\"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(\"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(\"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\t`failed to establish client ${connectionType} websocket connection`,\n\t\t\t{ error },\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(`test ${connectionType} websocket connection opened`);\n\n\t\t\t// Check WebSocket type\n\t\t\tlogger().debug(\"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\t`test ${connectionType} websocket connection message from client`,\n\t\t\t\t\t{\n\t\t\t\t\t\tdataType: typeof clientEvt.data,\n\t\t\t\t\t\tisBlob: clientEvt.data instanceof Blob,\n\t\t\t\t\t\tisArrayBuffer: clientEvt.data instanceof ArrayBuffer,\n\t\t\t\t\t\tdataConstructor: clientEvt.data?.constructor?.name,\n\t\t\t\t\t\tdataStr:\n\t\t\t\t\t\t\ttypeof clientEvt.data === \"string\"\n\t\t\t\t\t\t\t\t? clientEvt.data.substring(0, 100)\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t},\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\t\"converted client blob to arraybuffer, sending to server\",\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tbufferSize: buffer.byteLength,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\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(\"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(\"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: CloseEvent) => {\n\t\t\t\tlogger().debug(`test ${connectionType} websocket connection closed`);\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(`test ${connectionType} websocket connection error`);\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(\"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(\"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(\"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(\"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(`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(`error in server ${connectionType} websocket`, { error });\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\n/**\n * Handle SSE connection request\n */\nasync function handleSseConnectRequest(\n\tc: HonoContext,\n\tregistryConfig: RegistryConfig,\n\t_runConfig: RunConfig,\n\tdriver: ManagerDriver,\n): Promise<Response> {\n\tlet encoding: Encoding | undefined;\n\ttry {\n\t\tencoding = getRequestEncoding(c.req);\n\t\tlogger().debug(\"sse connection request received\", { encoding });\n\n\t\tconst params = ConnectRequestSchema.safeParse({\n\t\t\tquery: getRequestQuery(c),\n\t\t\tencoding: c.req.header(HEADER_ENCODING),\n\t\t\tconnParams: c.req.header(HEADER_CONN_PARAMS),\n\t\t});\n\n\t\tif (!params.success) {\n\t\t\tlogger().error(\"invalid connection parameters\", {\n\t\t\t\terror: params.error,\n\t\t\t});\n\t\t\tthrow new errors.InvalidRequest(params.error);\n\t\t}\n\n\t\tconst query = params.data.query;\n\n\t\t// Parse connection parameters for authentication\n\t\tconst connParams = params.data.connParams\n\t\t\t? JSON.parse(params.data.connParams)\n\t\t\t: undefined;\n\n\t\t// Authenticate the request\n\t\tconst authData = await authenticateEndpoint(\n\t\t\tc,\n\t\t\tdriver,\n\t\t\tregistryConfig,\n\t\t\tquery,\n\t\t\t[\"connect\"],\n\t\t\tconnParams,\n\t\t);\n\n\t\t// Get the actor ID\n\t\tconst { actorId } = await queryActor(c, query, driver);\n\t\tinvariant(actorId, \"Missing actor ID\");\n\t\tlogger().debug(\"sse connection to actor\", { actorId });\n\n\t\t// Handle based on mode\n\t\tlogger().debug(\"using custom proxy mode for sse connection\");\n\t\tconst url = new URL(\"http://actor/connect/sse\");\n\n\t\t// Always build fresh request to prevent forwarding unwanted headers\n\t\tconst proxyRequestHeaderes = new Headers();\n\t\tproxyRequestHeaderes.set(HEADER_ENCODING, params.data.encoding);\n\t\tif (params.data.connParams) {\n\t\t\tproxyRequestHeaderes.set(HEADER_CONN_PARAMS, params.data.connParams);\n\t\t}\n\t\tif (authData) {\n\t\t\tproxyRequestHeaderes.set(HEADER_AUTH_DATA, JSON.stringify(authData));\n\t\t}\n\n\t\tconst proxyRequest = new Request(url, { headers: proxyRequestHeaderes });\n\n\t\treturn await driver.proxyRequest(c, proxyRequest, actorId);\n\t} catch (error) {\n\t\t// If we receive an error during setup, we send the error and close the socket immediately\n\t\t//\n\t\t// We have to return the error over SSE since SSE clients cannot read vanilla HTTP responses\n\n\t\tconst { code, message, metadata } = deconstructError(error, logger(), {\n\t\t\tsseEvent: \"setup\",\n\t\t});\n\n\t\treturn streamSSE(c, async (stream) => {\n\t\t\ttry {\n\t\t\t\tif (encoding) {\n\t\t\t\t\t// Serialize and send the connection error\n\t\t\t\t\tconst errorMsg: protocol.ToClient = {\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\ttag: \"Error\",\n\t\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\t\tcode,\n\t\t\t\t\t\t\t\tmessage,\n\t\t\t\t\t\t\t\tmetadata: bufferToArrayBuffer(cbor.encode(metadata)),\n\t\t\t\t\t\t\t\tactionId: null,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\n\t\t\t\t\t// Send the error message to the client\n\t\t\t\t\tconst serialized = serializeWithEncoding(\n\t\t\t\t\t\tencoding,\n\t\t\t\t\t\terrorMsg,\n\t\t\t\t\t\tTO_CLIENT_VERSIONED,\n\t\t\t\t\t);\n\t\t\t\t\tawait stream.writeSSE({\n\t\t\t\t\t\tdata:\n\t\t\t\t\t\t\ttypeof serialized === \"string\"\n\t\t\t\t\t\t\t\t? serialized\n\t\t\t\t\t\t\t\t: Buffer.from(serialized).toString(\"base64\"),\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\t// We don't know the encoding, send an error and close\n\t\t\t\t\tawait stream.writeSSE({\n\t\t\t\t\t\tdata: code,\n\t\t\t\t\t\tevent: \"error\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (serializeError) {\n\t\t\t\tlogger().error(\"failed to send error to sse client\", {\n\t\t\t\t\terror: serializeError,\n\t\t\t\t});\n\t\t\t\tawait stream.writeSSE({\n\t\t\t\t\tdata: \"internal error during error handling\",\n\t\t\t\t\tevent: \"error\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Stream will exit completely once function exits\n\t\t});\n\t}\n}\n\n/**\n * Handle WebSocket connection request\n */\nasync function handleWebSocketConnectRequest(\n\tc: HonoContext,\n\tregistryConfig: RegistryConfig,\n\trunConfig: RunConfig,\n\tdriver: ManagerDriver,\n): Promise<Response> {\n\tconst upgradeWebSocket = runConfig.getUpgradeWebSocket?.();\n\tif (!upgradeWebSocket) {\n\t\treturn c.text(\n\t\t\t\"WebSockets are not enabled for this driver. Use SSE instead.\",\n\t\t\t400,\n\t\t);\n\t}\n\n\tlet encoding: Encoding | undefined;\n\ttry {\n\t\tlogger().debug(\"websocket connection request received\");\n\n\t\t// Parse configuration from Sec-WebSocket-Protocol header\n\t\t//\n\t\t// We use this instead of query parameters since this is more secure than\n\t\t// query parameters. Query parameters often get logged.\n\t\t//\n\t\t// Browsers don't support using headers, so this is the only way to\n\t\t// pass data securely.\n\t\tconst protocols = c.req.header(\"sec-websocket-protocol\");\n\t\tconst { queryRaw, encodingRaw, connParamsRaw } =\n\t\t\tparseWebSocketProtocols(protocols);\n\n\t\t// Parse query\n\t\tlet queryUnvalidated: unknown;\n\t\ttry {\n\t\t\tqueryUnvalidated = JSON.parse(queryRaw!);\n\t\t} catch (error) {\n\t\t\tlogger().error(\"invalid query json\", { error });\n\t\t\tthrow new errors.InvalidQueryJSON(error);\n\t\t}\n\n\t\t// Parse conn params\n\t\tlet connParamsUnvalidated: unknown = null;\n\t\ttry {\n\t\t\tif (connParamsRaw) {\n\t\t\t\tconnParamsUnvalidated = JSON.parse(connParamsRaw!);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tlogger().error(\"invalid conn params\", { error });\n\t\t\tthrow new errors.InvalidParams(\n\t\t\t\t`Invalid params JSON: ${stringifyError(error)}`,\n\t\t\t);\n\t\t}\n\n\t\t// We can't use the standard headers with WebSockets\n\t\t//\n\t\t// All other information will be sent over the socket itself, since that data needs to be E2EE\n\t\tconst params = ConnectWebSocketRequestSchema.safeParse({\n\t\t\tquery: queryUnvalidated,\n\t\t\tencoding: encodingRaw,\n\t\t\tconnParams: connParamsUnvalidated,\n\t\t});\n\t\tif (!params.success) {\n\t\t\tlogger().error(\"invalid connection parameters\", {\n\t\t\t\terror: params.error,\n\t\t\t});\n\t\t\tthrow new errors.InvalidRequest(params.error);\n\t\t}\n\t\tencoding = params.data.encoding;\n\n\t\t// Authenticate endpoint\n\t\tconst authData = await authenticateEndpoint(\n\t\t\tc,\n\t\t\tdriver,\n\t\t\tregistryConfig,\n\t\t\tparams.data.query,\n\t\t\t[\"connect\"],\n\t\t\tconnParamsRaw,\n\t\t);\n\n\t\t// Get the actor ID\n\t\tconst { actorId } = await queryActor(c, params.data.query, driver);\n\t\tlogger().debug(\"found actor for websocket connection\", {\n\t\t\tactorId,\n\t\t});\n\t\tinvariant(actorId, \"missing actor id\");\n\n\t\t// Proxy the WebSocket connection to the actor\n\t\t//\n\t\t// The proxyWebSocket handler will:\n\t\t// 1. Validate the WebSocket upgrade request\n\t\t// 2. Forward the request to the actor with the appropriate path\n\t\t// 3. Handle the WebSocket pair and proxy messages between client and actor\n\t\treturn await driver.proxyWebSocket(\n\t\t\tc,\n\t\t\tPATH_CONNECT_WEBSOCKET,\n\t\t\tactorId,\n\t\t\tparams.data.encoding,\n\t\t\tparams.data.connParams,\n\t\t\tauthData,\n\t\t);\n\t} catch (error) {\n\t\t// If we receive an error during setup, we send the error and close the socket immediately\n\t\t//\n\t\t// We have to return the error over WS since WebSocket clients cannot read vanilla HTTP responses\n\n\t\tconst { code, message, metadata } = deconstructError(error, logger(), {\n\t\t\twsEvent: \"setup\",\n\t\t});\n\n\t\treturn await upgradeWebSocket(() => ({\n\t\t\tonOpen: (_evt: unknown, ws: WSContext) => {\n\t\t\t\tif (encoding) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Serialize and send the connection error\n\t\t\t\t\t\tconst errorMsg: protocol.ToClient = {\n\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\ttag: \"Error\",\n\t\t\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\t\t\tcode,\n\t\t\t\t\t\t\t\t\tmessage,\n\t\t\t\t\t\t\t\t\tmetadata: bufferToArrayBuffer(cbor.encode(metadata)),\n\t\t\t\t\t\t\t\t\tactionId: null,\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\n\t\t\t\t\t\t// Send the error message to the client\n\t\t\t\t\t\tconst serialized = serializeWithEncoding(\n\t\t\t\t\t\t\tencoding,\n\t\t\t\t\t\t\terrorMsg,\n\t\t\t\t\t\t\tTO_CLIENT_VERSIONED,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tws.send(serialized);\n\n\t\t\t\t\t\t// Close the connection with an error code\n\t\t\t\t\t\tws.close(1011, code);\n\t\t\t\t\t} catch (serializeError) {\n\t\t\t\t\t\tlogger().error(\"failed to send error to websocket client\", {\n\t\t\t\t\t\t\terror: serializeError,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tws.close(1011, \"internal error during error handling\");\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// We don't know the encoding so we send what we can\n\t\t\t\t\tws.close(1011, code);\n\t\t\t\t}\n\t\t\t},\n\t\t}))(c, noopNext());\n\t}\n}\n\n/**\n * Handle a connection message request to a actor\n *\n * There is no authentication handler on this request since the connection\n * token is used to authenticate the message.\n */\nasync function handleMessageRequest(\n\tc: HonoContext,\n\t_registryConfig: RegistryConfig,\n\t_runConfig: RunConfig,\n\tdriver: ManagerDriver,\n): Promise<Response> {\n\tlogger().debug(\"connection message request received\");\n\ttry {\n\t\tconst params = ConnMessageRequestSchema.safeParse({\n\t\t\tactorId: c.req.header(HEADER_ACTOR_ID),\n\t\t\tconnId: c.req.header(HEADER_CONN_ID),\n\t\t\tencoding: c.req.header(HEADER_ENCODING),\n\t\t\tconnToken: c.req.header(HEADER_CONN_TOKEN),\n\t\t});\n\t\tif (!params.success) {\n\t\t\tlogger().error(\"invalid connection parameters\", {\n\t\t\t\terror: params.error,\n\t\t\t});\n\t\t\tthrow new errors.InvalidRequest(params.error);\n\t\t}\n\t\tconst { actorId, connId, encoding, connToken } = params.data;\n\n\t\t// TODO: This endpoint can be used to exhause resources (DoS attack) on an actor if you know the actor ID:\n\t\t// 1. Get the actor ID (usually this is reasonably secure, but we don't assume actor ID is sensitive)\n\t\t// 2. Spam messages to the actor (the conn token can be invalid)\n\t\t// 3. The actor will be exhausted processing messages — even if the token is invalid\n\t\t//\n\t\t// The solution is we need to move the authorization of the connection token to this request handler\n\t\t// AND include the actor ID in the connection token so we can verify that it has permission to send\n\t\t// a message to that actor. This would require changing the token to a JWT so we can include a secure\n\t\t// payload, but this requires managing a private key & managing key rotations.\n\t\t//\n\t\t// All other solutions (e.g. include the actor name as a header or include the actor name in the actor ID)\n\t\t// have exploits that allow the caller to send messages to arbitrary actors.\n\t\t//\n\t\t// Currently, we assume this is not a critical problem because requests will likely get rate\n\t\t// limited before enough messages are passed to the actor to exhaust resources.\n\n\t\tconst url = new URL(\"http://actor/connections/message\");\n\n\t\t// Always build fresh request to prevent forwarding unwanted headers\n\t\tconst proxyRequestHeaders = new Headers();\n\t\tproxyRequestHeaders.set(HEADER_ENCODING, encoding);\n\t\tproxyRequestHeaders.set(HEADER_CONN_ID, connId);\n\t\tproxyRequestHeaders.set(HEADER_CONN_TOKEN, connToken);\n\n\t\tconst proxyRequest = new Request(url, {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: c.req.raw.body,\n\t\t\tduplex: \"half\",\n\t\t\theaders: proxyRequestHeaders,\n\t\t});\n\n\t\treturn await driver.proxyRequest(c, proxyRequest, actorId);\n\t} catch (error) {\n\t\tlogger().error(\"error proxying connection message\", { error });\n\n\t\t// Use ProxyError if it's not already an ActorError\n\t\tif (!errors.ActorError.isActorError(error)) {\n\t\t\tthrow new errors.ProxyError(\"connection message\", error);\n\t\t} else {\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n\n/**\n * Handle an action request to a actor\n */\nasync function handleActionRequest(\n\tc: HonoContext,\n\tregistryConfig: RegistryConfig,\n\t_runConfig: RunConfig,\n\tdriver: ManagerDriver,\n): Promise<Response> {\n\ttry {\n\t\tconst actionName = c.req.param(\"action\");\n\t\tlogger().debug(\"action call received\", { actionName });\n\n\t\tconst params = ConnectRequestSchema.safeParse({\n\t\t\tquery: getRequestQuery(c),\n\t\t\tencoding: c.req.header(HEADER_ENCODING),\n\t\t\tconnParams: c.req.header(HEADER_CONN_PARAMS),\n\t\t});\n\n\t\tif (!params.success) {\n\t\t\tlogger().error(\"invalid connection parameters\", {\n\t\t\t\terror: params.error,\n\t\t\t});\n\t\t\tthrow new errors.InvalidRequest(params.error);\n\t\t}\n\n\t\t// Parse connection parameters for authentication\n\t\tconst connParams = params.data.connParams\n\t\t\t? JSON.parse(params.data.connParams)\n\t\t\t: undefined;\n\n\t\t// Authenticate the request\n\t\tconst authData = await authenticateEndpoint(\n\t\t\tc,\n\t\t\tdriver,\n\t\t\tregistryConfig,\n\t\t\tparams.data.query,\n\t\t\t[\"action\"],\n\t\t\tconnParams,\n\t\t);\n\n\t\t// Get the actor ID\n\t\tconst { actorId } = await queryActor(c, params.data.query, driver);\n\t\tlogger().debug(\"found actor for action\", { actorId });\n\t\tinvariant(actorId, \"Missing actor ID\");\n\n\t\tconst url = new URL(\n\t\t\t`http://actor/action/${encodeURIComponent(actionName)}`,\n\t\t);\n\n\t\t// Always build fresh request to prevent forwarding unwanted headers\n\t\tconst proxyRequestHeaders = new Headers();\n\t\tproxyRequestHeaders.set(HEADER_ENCODING, params.data.encoding);\n\t\tif (params.data.connParams) {\n\t\t\tproxyRequestHeaders.set(HEADER_CONN_PARAMS, params.data.connParams);\n\t\t}\n\t\tif (authData) {\n\t\t\tproxyRequestHeaders.set(HEADER_AUTH_DATA, JSON.stringify(authData));\n\t\t}\n\n\t\tconst proxyRequest = new Request(url, {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: c.req.raw.body,\n\t\t\theaders: proxyRequestHeaders,\n\t\t});\n\n\t\treturn await driver.proxyRequest(c, proxyRequest, actorId);\n\t} catch (error) {\n\t\tlogger().error(\"error in action handler\", { error: stringifyError(error) });\n\n\t\t// Use ProxyError if it's not already an ActorError\n\t\tif (!errors.ActorError.isActorError(error)) {\n\t\t\tthrow new errors.ProxyError(\"Action call\", error);\n\t\t} else {\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n\n/**\n * Handle the resolve request to get a actor ID from a query\n */\nasync function handleResolveRequest(\n\tc: HonoContext,\n\tregistryConfig: RegistryConfig,\n\tdriver: ManagerDriver,\n): Promise<Response> {\n\tconst encoding = getRequestEncoding(c.req);\n\tlogger().debug(\"resolve request encoding\", { encoding });\n\n\tconst params = ResolveRequestSchema.safeParse({\n\t\tquery: getRequestQuery(c),\n\t\tconnParams: c.req.header(HEADER_CONN_PARAMS),\n\t});\n\tif (!params.success) {\n\t\tlogger().error(\"invalid connection parameters\", {\n\t\t\terror: params.error,\n\t\t});\n\t\tthrow new errors.InvalidRequest(params.error);\n\t}\n\n\t// Parse connection parameters for authentication\n\tconst connParams = params.data.connParams\n\t\t? JSON.parse(params.data.connParams)\n\t\t: undefined;\n\n\tconst query = params.data.query;\n\n\t// Authenticate the request\n\tawait authenticateEndpoint(c, driver, registryConfig, query, [], connParams);\n\n\t// Get the actor ID\n\tconst { actorId } = await queryActor(c, query, driver);\n\tlogger().debug(\"resolved actor\", { actorId });\n\tinvariant(actorId, \"Missing actor ID\");\n\n\t// Format response according to protocol\n\tconst response: protocol.HttpResolveResponse = {\n\t\tactorId,\n\t};\n\tconst serialized = serializeWithEncoding(\n\t\tencoding,\n\t\tresponse,\n\t\tHTTP_RESOLVE_RESPONSE_VERSIONED,\n\t);\n\treturn c.body(serialized);\n}\n\n/**\n * Handle raw HTTP requests to an actor\n */\nasync function handleRawHttpRequest(\n\tc: HonoContext,\n\tregistryConfig: RegistryConfig,\n\t_runConfig: RunConfig,\n\tdriver: ManagerDriver,\n): Promise<Response> {\n\ttry {\n\t\tconst subpath = c.req.path.split(\"/raw/http/\")[1] || \"\";\n\t\tlogger().debug(\"raw http request received\", { subpath });\n\n\t\t// Get actor query from header (consistent with other endpoints)\n\t\tconst queryHeader = c.req.header(HEADER_ACTOR_QUERY);\n\t\tif (!queryHeader) {\n\t\t\tthrow new errors.InvalidRequest(\"Missing actor query header\");\n\t\t}\n\t\tconst query: ActorQuery = JSON.parse(queryHeader);\n\n\t\t// Parse connection parameters for authentication\n\t\tconst connParamsHeader = c.req.header(HEADER_CONN_PARAMS);\n\t\tconst connParams = connParamsHeader\n\t\t\t? JSON.parse(connParamsHeader)\n\t\t\t: undefined;\n\n\t\t// Authenticate the request\n\t\tconst authData = await authenticateEndpoint(\n\t\t\tc,\n\t\t\tdriver,\n\t\t\tregistryConfig,\n\t\t\tquery,\n\t\t\t[\"action\"],\n\t\t\tconnParams,\n\t\t);\n\n\t\t// Get the actor ID\n\t\tconst { actorId } = await queryActor(c, query, driver);\n\t\tlogger().debug(\"found actor for raw http\", { actorId });\n\t\tinvariant(actorId, \"Missing actor ID\");\n\n\t\t// Preserve the original URL's query parameters\n\t\tconst originalUrl = new URL(c.req.url);\n\t\tconst url = new URL(\n\t\t\t`http://actor/raw/http/${subpath}${originalUrl.search}`,\n\t\t);\n\n\t\t// Forward the request to the actor\n\n\t\tlogger().debug(\"rewriting http url\", {\n\t\t\tfrom: c.req.url,\n\t\t\tto: url,\n\t\t});\n\n\t\tconst proxyRequestHeaders = new Headers(c.req.raw.headers);\n\t\tif (connParams) {\n\t\t\tproxyRequestHeaders.set(HEADER_CONN_PARAMS, JSON.stringify(connParams));\n\t\t}\n\t\tif (authData) {\n\t\t\tproxyRequestHeaders.set(HEADER_AUTH_DATA, JSON.stringify(authData));\n\t\t}\n\n\t\tconst proxyRequest = new Request(url, {\n\t\t\tmethod: c.req.method,\n\t\t\theaders: proxyRequestHeaders,\n\t\t\tbody: c.req.raw.body,\n\t\t});\n\n\t\treturn await driver.proxyRequest(c, proxyRequest, actorId);\n\t} catch (error) {\n\t\tlogger().error(\"error in raw http handler\", {\n\t\t\terror: stringifyError(error),\n\t\t});\n\n\t\t// Use ProxyError if it's not already an ActorError\n\t\tif (!errors.ActorError.isActorError(error)) {\n\t\t\tthrow new errors.ProxyError(\"Raw HTTP request\", error);\n\t\t} else {\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n\n/**\n * Handle raw WebSocket requests to an actor\n */\nasync function handleRawWebSocketRequest(\n\tc: HonoContext,\n\tregistryConfig: RegistryConfig,\n\trunConfig: RunConfig,\n\tdriver: ManagerDriver,\n): Promise<Response> {\n\tconst upgradeWebSocket = runConfig.getUpgradeWebSocket?.();\n\tif (!upgradeWebSocket) {\n\t\treturn c.text(\"WebSockets are not enabled for this driver.\", 400);\n\t}\n\n\ttry {\n\t\tconst subpath = c.req.path.split(\"/raw/websocket/\")[1] || \"\";\n\t\tlogger().debug(\"raw websocket request received\", { subpath });\n\n\t\t// Parse protocols from Sec-WebSocket-Protocol header\n\t\tconst protocols = c.req.header(\"sec-websocket-protocol\");\n\t\tconst {\n\t\t\tqueryRaw: queryFromProtocol,\n\t\t\tconnParamsRaw: connParamsFromProtocol,\n\t\t} = parseWebSocketProtocols(protocols);\n\n\t\tif (!queryFromProtocol) {\n\t\t\tthrow new errors.InvalidRequest(\"Missing query in WebSocket protocol\");\n\t\t}\n\t\tconst query = JSON.parse(queryFromProtocol);\n\n\t\t// Parse connection parameters from protocol\n\t\tlet connParams: unknown;\n\t\tif (connParamsFromProtocol) {\n\t\t\tconnParams = JSON.parse(connParamsFromProtocol);\n\t\t}\n\n\t\t// Authenticate the request\n\t\tconst authData = await authenticateEndpoint(\n\t\t\tc,\n\t\t\tdriver,\n\t\t\tregistryConfig,\n\t\t\tquery,\n\t\t\t[\"action\"],\n\t\t\tconnParams,\n\t\t);\n\n\t\t// Get the actor ID\n\t\tconst { actorId } = await queryActor(c, query, driver);\n\t\tlogger().debug(\"found actor for raw websocket\", { actorId });\n\t\tinvariant(actorId, \"Missing actor ID\");\n\n\t\tlogger().debug(\"using custom proxy mode for raw websocket\");\n\n\t\t// Preserve the original URL's query parameters\n\t\tconst originalUrl = new URL(c.req.url);\n\t\tconst proxyPath = `${PATH_RAW_WEBSOCKET_PREFIX}${subpath}${originalUrl.search}`;\n\n\t\tlogger().debug(\"manager router proxyWebSocket\", {\n\t\t\toriginalUrl: c.req.url,\n\t\t\tsubpath,\n\t\t\tsearch: originalUrl.search,\n\t\t\tproxyPath,\n\t\t});\n\n\t\t// For raw WebSocket, we need to use proxyWebSocket instead of proxyRequest\n\t\treturn await driver.proxyWebSocket(\n\t\t\tc,\n\t\t\tproxyPath,\n\t\t\tactorId,\n\t\t\t\"json\", // Default encoding for raw WebSocket\n\t\t\tconnParams,\n\t\t\tauthData,\n\t\t);\n\t} catch (error) {\n\t\t// If we receive an error during setup, we send the error and close the socket immediately\n\t\t//\n\t\t// We have to return the error over WS since WebSocket clients cannot read vanilla HTTP responses\n\n\t\tconst { code } = deconstructError(error, logger(), {\n\t\t\twsEvent: \"setup\",\n\t\t});\n\n\t\treturn await upgradeWebSocket(() => ({\n\t\t\tonOpen: (_evt: unknown, ws: WSContext) => {\n\t\t\t\t// Close with message so we can see the error on the client\n\t\t\t\tws.close(1011, code);\n\t\t\t},\n\t\t}))(c, noopNext());\n\t}\n}\n\nfunction universalActorProxy({\n\tregistryConfig,\n\trunConfig,\n\tdriver,\n}: {\n\tregistryConfig: RegistryConfig;\n\trunConfig: RunConfig;\n\tdriver: ManagerDriver;\n}): MiddlewareHandler {\n\treturn async (c, _next) => {\n\t\tif (c.req.header(\"upgrade\") === \"websocket\") {\n\t\t\treturn handleRawWebSocketRequest(c, registryConfig, runConfig, driver);\n\t\t} else {\n\t\t\tconst queryHeader = c.req.header(HEADER_ACTOR_QUERY);\n\t\t\tif (!queryHeader) {\n\t\t\t\tthrow new errors.InvalidRequest(\"Missing actor query header\");\n\t\t\t}\n\t\t\tconst query = ActorQuerySchema.parse(JSON.parse(queryHeader));\n\n\t\t\tconst { actorId } = await queryActor(c, query, driver);\n\n\t\t\tconst url = new URL(c.req.url);\n\t\t\turl.hostname = \"actor\";\n\t\t\turl.pathname = url.pathname\n\t\t\t\t.replace(new RegExp(`^${runConfig.basePath}`, \"\"), \"\")\n\t\t\t\t.replace(/^\\/?registry\\/actors/, \"\")\n\t\t\t\t.replace(/^\\/?actors/, \"\"); // Remove /registry prefix if present\n\n\t\t\tconst proxyRequest = new Request(url, {\n\t\t\t\tmethod: c.req.method,\n\t\t\t\theaders: c.req.raw.headers,\n\t\t\t\tbody: c.req.raw.body,\n\t\t\t});\n\t\t\treturn await driver.proxyRequest(c, proxyRequest, actorId);\n\t\t}\n\t};\n}\n","import type { Context as HonoContext } from \"hono\";\nimport type { AuthIntent } from \"@/actor/config\";\nimport type { AnyActorDefinition } from \"@/actor/definition\";\nimport * as errors from \"@/actor/errors\";\nimport type { RegistryConfig } from \"@/registry/config\";\nimport { stringifyError } from \"@/utils\";\nimport type { ManagerDriver } from \"./driver\";\nimport { logger } from \"./log\";\nimport type { ActorQuery } from \"./protocol/query\";\n\n/**\n * Get authentication intents from a actor query\n */\nexport function getIntentsFromQuery(query: ActorQuery): Set<AuthIntent> {\n\tconst intents = new Set<AuthIntent>();\n\n\tif (\"getForId\" in query) {\n\t\tintents.add(\"get\");\n\t} else if (\"getForKey\" in query) {\n\t\tintents.add(\"get\");\n\t} else if (\"getOrCreateForKey\" in query) {\n\t\tintents.add(\"get\");\n\t\tintents.add(\"create\");\n\t} else if (\"create\" in query) {\n\t\tintents.add(\"create\");\n\t}\n\n\treturn intents;\n}\n\n/**\n * Get actor name from a actor query\n */\nexport async function getActorNameFromQuery(\n\tc: HonoContext,\n\tdriver: ManagerDriver,\n\tquery: ActorQuery,\n): Promise<string> {\n\tif (\"getForId\" in query) {\n\t\t// TODO: This will have a duplicate call to getForId between this and queryActor\n\t\tconst output = await driver.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\treturn output.name;\n\t} else if (\"getForKey\" in query) {\n\t\treturn query.getForKey.name;\n\t} else if (\"getOrCreateForKey\" in query) {\n\t\treturn query.getOrCreateForKey.name;\n\t} else if (\"create\" in query) {\n\t\treturn query.create.name;\n\t} else {\n\t\tthrow new errors.InvalidRequest(\"Invalid query format\");\n\t}\n}\n\n/**\n * Authenticate a request using the actor's onAuth function\n */\nexport async function authenticateRequest(\n\tc: HonoContext,\n\tactorDefinition: AnyActorDefinition,\n\tintents: Set<AuthIntent>,\n\tparams: unknown,\n): Promise<unknown> {\n\tif (!(\"onAuth\" in actorDefinition.config)) {\n\t\tthrow new errors.Forbidden(\n\t\t\t\"Actor requires authentication but no onAuth handler is defined (https://rivet.gg/docs/actors/authentication/). Provide an empty handler to disable auth: `onAuth: () => {}`\",\n\t\t);\n\t}\n\n\ttry {\n\t\tconst dataOrPromise = actorDefinition.config.onAuth(\n\t\t\t{\n\t\t\t\trequest: c.req.raw,\n\t\t\t\tintents,\n\t\t\t},\n\t\t\tparams,\n\t\t);\n\t\tif (dataOrPromise instanceof Promise) {\n\t\t\treturn await dataOrPromise;\n\t\t} else {\n\t\t\treturn dataOrPromise;\n\t\t}\n\t} catch (error) {\n\t\tlogger().info(\"authentication error\", { error: stringifyError(error) });\n\t\tthrow error;\n\t}\n}\n\n/**\n * Simplified authentication for endpoints that combines all auth steps\n */\nexport async function authenticateEndpoint(\n\tc: HonoContext,\n\tdriver: ManagerDriver,\n\tregistryConfig: RegistryConfig,\n\tquery: ActorQuery,\n\tadditionalIntents: AuthIntent[],\n\tparams: unknown,\n): Promise<unknown> {\n\t// Get base intents from query\n\tconst intents = getIntentsFromQuery(query);\n\n\t// Add endpoint-specific intents\n\tfor (const intent of additionalIntents) {\n\t\tintents.add(intent);\n\t}\n\n\t// Get actor definition\n\tconst actorName = await getActorNameFromQuery(c, driver, query);\n\tconst actorDefinition = registryConfig.use[actorName];\n\tif (!actorDefinition) {\n\t\tthrow new errors.ActorNotFound(actorName);\n\t}\n\n\t// Authenticate\n\treturn await authenticateRequest(c, actorDefinition, intents, params);\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, 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 const LOGGER_NAME = \"registry\";\n\nexport function logger() {\n\treturn getLogger(LOGGER_NAME);\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\tapp.route(\"/registry\", 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 = Number.parseInt(\n\t\tgetEnvUniversal(\"PORT\") ?? getEnvUniversal(\"PORT_HTTP\") ?? \"8080\",\n\t);\n\tconst server = serve({ fetch: app.fetch, port }, () =>\n\t\tlogger().info(\"server listening\", { port }),\n\t);\n\tinjectWebSocket(server);\n\n\treturn { upgradeWebSocket };\n}\n","import type { Hono } from \"hono\";\nimport { createActorRouter } from \"@/actor/router\";\nimport { type Client, createClientWithDriver } from \"@/client/client\";\nimport { chooseDefaultDriver } from \"@/drivers/default\";\nimport { createInlineClientDriver } from \"@/inline-client-driver/mod\";\nimport { getInspectorUrl } from \"@/inspector/utils\";\nimport { createManagerRouter } from \"@/manager/router\";\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\tclient: Client<A>;\n\thono: Hono;\n\thandler: (req: Request) => Promise<Response>;\n\tserve: (hono?: Hono) => void;\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 createServer(inputConfig?: RunConfigInput): ServerOutput<this> {\n\t\tconst config = RunConfigSchema.parse(inputConfig);\n\n\t\t// Choose the driver based on configuration\n\t\tconst driver = chooseDefaultDriver(config);\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 clientDriver = createInlineClientDriver(managerDriver);\n\t\tconst { router: hono } = createManagerRouter(\n\t\t\tthis.#config,\n\t\t\tconfig,\n\t\t\tclientDriver,\n\t\t\tmanagerDriver,\n\t\t\tfalse,\n\t\t);\n\n\t\t// Create client\n\t\tconst client = createClientWithDriver<this>(clientDriver);\n\n\t\tconst driverLog = managerDriver.extraStartupLog?.() ?? {};\n\t\tlogger().info(\"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) {\n\t\t\tlogger().info(\"inspector ready\", {\n\t\t\t\turl: getInspectorUrl(config),\n\t\t\t});\n\t\t}\n\n\t\t// Create runner\n\t\tif (config.role === \"all\" || config.role === \"runner\") {\n\t\t\tconst inlineClient = createClientWithDriver(\n\t\t\t\tcreateInlineClientDriver(managerDriver),\n\t\t\t);\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\tinlineClient,\n\t\t\t);\n\t\t\t// TODO: What do we do with the actor driver here?\n\t\t}\n\n\t\treturn {\n\t\t\tclient,\n\t\t\thono,\n\t\t\thandler: async (req: Request) => await hono.fetch(req),\n\t\t\tserve: async (app) => {\n\t\t\t\tconst out = await crossPlatformServe(hono, app);\n\t\t\t\tupgradeWebSocket = out.upgradeWebSocket;\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Runs the registry as a standalone server.\n\t */\n\tpublic async runServer(inputConfig?: RunConfigInput) {\n\t\tconst { serve } = this.createServer(inputConfig);\n\t\tserve();\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"]}
|