@rivetkit/cloudflare-workers
Version:
Cloudflare Workers adapter for RivetKit actors
1 lines • 59.4 kB
Source Map (JSON)
{"version":3,"sources":["/home/runner/work/rivet/rivet/rivetkit-typescript/packages/cloudflare-workers/dist/mod.cjs","../src/actor-handler-do.ts","../src/actor-driver.ts","../src/actor-id.ts","../src/actor-kv.ts","../src/global-kv.ts","../src/handler.ts","../src/config.ts","../src/manager-driver.ts","../src/log.ts","../src/util.ts","../src/websocket.ts"],"names":["env","invariant"],"mappings":"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","file":"/home/runner/work/rivet/rivet/rivetkit-typescript/packages/cloudflare-workers/dist/mod.cjs","sourcesContent":[null,"import { DurableObject, env } from \"cloudflare:workers\";\nimport type { ExecutionContext } from \"hono\";\nimport invariant from \"invariant\";\nimport type { ActorKey, ActorRouter, Registry, RunConfig } from \"rivetkit\";\nimport { createActorRouter, createClientWithDriver } from \"rivetkit\";\nimport type { ActorDriver, ManagerDriver } from \"rivetkit/driver-helpers\";\nimport { getInitialActorKvState } from \"rivetkit/driver-helpers\";\nimport { stringifyError } from \"rivetkit/utils\";\nimport {\n\tActorGlobalState,\n\tCloudflareDurableObjectGlobalState,\n\tcreateCloudflareActorsActorDriverBuilder,\n} from \"./actor-driver\";\nimport { buildActorId, parseActorId } from \"./actor-id\";\nimport { kvPut } from \"./actor-kv\";\nimport { GLOBAL_KV_KEYS } from \"./global-kv\";\nimport type { Bindings } from \"./handler\";\nimport { getCloudflareAmbientEnv } from \"./handler\";\nimport { logger } from \"./log\";\n\nexport interface ActorHandlerInterface extends DurableObject {\n\tcreate(req: ActorInitRequest): Promise<ActorInitResponse>;\n\tgetMetadata(): Promise<\n\t\t| {\n\t\t\t\tactorId: string;\n\t\t\t\tname: string;\n\t\t\t\tkey: ActorKey;\n\t\t\t\tdestroying: boolean;\n\t\t }\n\t\t| undefined\n\t>;\n}\n\nexport interface ActorInitRequest {\n\tname: string;\n\tkey: ActorKey;\n\tinput?: unknown;\n\tallowExisting: boolean;\n}\nexport type ActorInitResponse =\n\t| { success: { actorId: string; created: boolean } }\n\t| { error: { actorAlreadyExists: true } };\n\nexport type DurableObjectConstructor = new (\n\t...args: ConstructorParameters<typeof DurableObject<Bindings>>\n) => DurableObject<Bindings>;\n\nexport function createActorDurableObject(\n\tregistry: Registry<any>,\n\trootRunConfig: RunConfig,\n): DurableObjectConstructor {\n\tconst globalState = new CloudflareDurableObjectGlobalState();\n\n\t// Configure to use the runner role instead of server role\n\tconst runConfig = Object.assign({}, rootRunConfig, { role: \"runner\" });\n\n\t/**\n\t * Startup steps:\n\t * 1. If not already created call `initialize`, otherwise check KV to ensure it's initialized\n\t * 2. Load actor\n\t * 3. Start service requests\n\t */\n\treturn class ActorHandler\n\t\textends DurableObject<Bindings>\n\t\timplements ActorHandlerInterface\n\t{\n\t\t/**\n\t\t * This holds a strong reference to ActorGlobalState.\n\t\t * CloudflareDurableObjectGlobalState holds a weak reference so we can\n\t\t * access it elsewhere.\n\t\t **/\n\t\t#state: ActorGlobalState;\n\n\t\tconstructor(\n\t\t\t...args: ConstructorParameters<typeof DurableObject<Bindings>>\n\t\t) {\n\t\t\tsuper(...args);\n\n\t\t\t// Initialize SQL table for key-value storage\n\t\t\t//\n\t\t\t// We do this instead of using the native KV storage so we can store blob keys. The native CF KV API only supports string keys.\n\t\t\tthis.ctx.storage.sql.exec(`\n\t\t\t\tCREATE TABLE IF NOT EXISTS _rivetkit_kv_storage(\n\t\t\t\t\tkey BLOB PRIMARY KEY,\n\t\t\t\t\tvalue BLOB\n\t\t\t\t);\n\t\t\t`);\n\n\t\t\t// Initialize SQL table for actor metadata\n\t\t\t//\n\t\t\t// id always equals 1 in order to ensure that there's always exactly 1 row in this table\n\t\t\tthis.ctx.storage.sql.exec(`\n\t\t\t\tCREATE TABLE IF NOT EXISTS _rivetkit_metadata(\n\t\t\t\t\tid INTEGER PRIMARY KEY CHECK (id = 1),\n\t\t\t\t\tname TEXT NOT NULL,\n\t\t\t\t\tkey TEXT NOT NULL,\n\t\t\t\t\tdestroyed INTEGER DEFAULT 0,\n\t\t\t\t\tgeneration INTEGER DEFAULT 0\n\t\t\t\t);\n\t\t\t`);\n\n\t\t\t// Get or create the actor state from the global WeakMap\n\t\t\tconst state = globalState.getActorState(this.ctx);\n\t\t\tif (state) {\n\t\t\t\tthis.#state = state;\n\t\t\t} else {\n\t\t\t\tthis.#state = new ActorGlobalState();\n\t\t\t\tglobalState.setActorState(this.ctx, this.#state);\n\t\t\t}\n\t\t}\n\n\t\tasync #loadActor() {\n\t\t\tinvariant(this.#state, \"State should be initialized\");\n\n\t\t\t// Check if initialized\n\t\t\tif (!this.#state.initialized) {\n\t\t\t\t// Query SQL for initialization data\n\t\t\t\tconst cursor = this.ctx.storage.sql.exec(\n\t\t\t\t\t\"SELECT name, key, destroyed, generation FROM _rivetkit_metadata WHERE id = 1\",\n\t\t\t\t);\n\t\t\t\tconst result = cursor.raw().next();\n\n\t\t\t\tif (!result.done && result.value) {\n\t\t\t\t\tconst name = result.value[0] as string;\n\t\t\t\t\tconst key = JSON.parse(\n\t\t\t\t\t\tresult.value[1] as string,\n\t\t\t\t\t) as ActorKey;\n\t\t\t\t\tconst destroyed = result.value[2] as number;\n\t\t\t\t\tconst generation = result.value[3] as number;\n\n\t\t\t\t\t// Only initialize if not destroyed\n\t\t\t\t\tif (!destroyed) {\n\t\t\t\t\t\tlogger().debug({\n\t\t\t\t\t\t\tmsg: \"already initialized\",\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t\tgeneration,\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tthis.#state.initialized = { name, key, generation };\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger().debug(\"actor is destroyed, cannot load\");\n\t\t\t\t\t\tthrow new Error(\"Actor is destroyed\");\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger().debug(\"not initialized\");\n\t\t\t\t\tthrow new Error(\"Actor is not initialized\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check if already loaded\n\t\t\tif (this.#state.actor) {\n\t\t\t\t// Assert that the cached actor has the correct generation\n\t\t\t\t// This will catch any cases where #state.actor has a stale generation\n\t\t\t\tinvariant(\n\t\t\t\t\t!this.#state.initialized ||\n\t\t\t\t\t\tthis.#state.actor.generation ===\n\t\t\t\t\t\t\tthis.#state.initialized.generation,\n\t\t\t\t\t`Stale actor cached: actor generation ${this.#state.actor.generation} != initialized generation ${this.#state.initialized?.generation}. This should not happen.`,\n\t\t\t\t);\n\t\t\t\treturn this.#state.actor;\n\t\t\t}\n\n\t\t\tif (!this.#state.initialized) throw new Error(\"Not initialized\");\n\n\t\t\t// Register DO with global state first\n\t\t\t// HACK: This leaks the DO context, but DO does not provide a native way\n\t\t\t// of knowing when the DO shuts down. We're making a broad assumption\n\t\t\t// that DO will boot a new isolate frequenlty enough that this is not an issue.\n\t\t\tconst actorId = this.ctx.id.toString();\n\t\t\tglobalState.setDOState(actorId, { ctx: this.ctx, env: env });\n\n\t\t\t// Configure actor driver\n\t\t\tinvariant(runConfig.driver, \"runConfig.driver\");\n\t\t\trunConfig.driver.actor =\n\t\t\t\tcreateCloudflareActorsActorDriverBuilder(globalState);\n\n\t\t\t// Create manager driver (we need this for the actor router)\n\t\t\tconst managerDriver = runConfig.driver.manager(\n\t\t\t\tregistry.config,\n\t\t\t\trunConfig,\n\t\t\t);\n\n\t\t\t// Create inline client\n\t\t\tconst inlineClient = createClientWithDriver(\n\t\t\t\tmanagerDriver,\n\t\t\t\trunConfig,\n\t\t\t);\n\n\t\t\t// Create actor driver\n\t\t\tconst actorDriver = runConfig.driver.actor(\n\t\t\t\tregistry.config,\n\t\t\t\trunConfig,\n\t\t\t\tmanagerDriver,\n\t\t\t\tinlineClient,\n\t\t\t);\n\n\t\t\t// Create actor router\n\t\t\tconst actorRouter = createActorRouter(\n\t\t\t\trunConfig,\n\t\t\t\tactorDriver,\n\t\t\t\tfalse,\n\t\t\t);\n\n\t\t\t// Save actor with generation\n\t\t\tthis.#state.actor = {\n\t\t\t\tactorRouter,\n\t\t\t\tactorDriver,\n\t\t\t\tgeneration: this.#state.initialized.generation,\n\t\t\t};\n\n\t\t\t// Build actor ID with generation for loading\n\t\t\tconst actorIdWithGen = buildActorId(\n\t\t\t\tactorId,\n\t\t\t\tthis.#state.initialized.generation,\n\t\t\t);\n\n\t\t\t// Initialize the actor instance with proper metadata\n\t\t\t// This ensures the actor driver knows about this actor\n\t\t\tawait actorDriver.loadActor(actorIdWithGen);\n\n\t\t\treturn this.#state.actor;\n\t\t}\n\n\t\t/** RPC called to get actor metadata without creating it */\n\t\tasync getMetadata(): Promise<\n\t\t\t| {\n\t\t\t\t\tactorId: string;\n\t\t\t\t\tname: string;\n\t\t\t\t\tkey: ActorKey;\n\t\t\t\t\tdestroying: boolean;\n\t\t\t }\n\t\t\t| undefined\n\t\t> {\n\t\t\t// Query the metadata\n\t\t\tconst cursor = this.ctx.storage.sql.exec(\n\t\t\t\t\"SELECT name, key, destroyed, generation FROM _rivetkit_metadata WHERE id = 1\",\n\t\t\t);\n\t\t\tconst result = cursor.raw().next();\n\n\t\t\tif (!result.done && result.value) {\n\t\t\t\tconst name = result.value[0] as string;\n\t\t\t\tconst key = JSON.parse(result.value[1] as string) as ActorKey;\n\t\t\t\tconst destroyed = result.value[2] as number;\n\t\t\t\tconst generation = result.value[3] as number;\n\n\t\t\t\t// Check if destroyed\n\t\t\t\tif (destroyed) {\n\t\t\t\t\tlogger().debug({\n\t\t\t\t\t\tmsg: \"getMetadata: actor is destroyed\",\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tgeneration,\n\t\t\t\t\t});\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\t// Build actor ID with generation\n\t\t\t\tconst doId = this.ctx.id.toString();\n\t\t\t\tconst actorId = buildActorId(doId, generation);\n\t\t\t\tconst destroying =\n\t\t\t\t\tglobalState.getActorState(this.ctx)?.destroying ?? false;\n\n\t\t\t\tlogger().debug({\n\t\t\t\t\tmsg: \"getMetadata: found actor metadata\",\n\t\t\t\t\tactorId,\n\t\t\t\t\tname,\n\t\t\t\t\tkey,\n\t\t\t\t\tgeneration,\n\t\t\t\t\tdestroying,\n\t\t\t\t});\n\n\t\t\t\treturn { actorId, name, key, destroying };\n\t\t\t}\n\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"getMetadata: no metadata found\",\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\t/** RPC called by the manager to create a DO. Can optionally allow existing actors. */\n\t\tasync create(req: ActorInitRequest): Promise<ActorInitResponse> {\n\t\t\t// Check if actor exists\n\t\t\tconst checkCursor = this.ctx.storage.sql.exec(\n\t\t\t\t\"SELECT destroyed, generation FROM _rivetkit_metadata WHERE id = 1\",\n\t\t\t);\n\t\t\tconst checkResult = checkCursor.raw().next();\n\n\t\t\tlet created = false;\n\t\t\tlet generation = 0;\n\n\t\t\tif (!checkResult.done && checkResult.value) {\n\t\t\t\tconst destroyed = checkResult.value[0] as number;\n\t\t\t\tgeneration = checkResult.value[1] as number;\n\n\t\t\t\tif (!destroyed) {\n\t\t\t\t\t// Actor exists and is not destroyed\n\t\t\t\t\tif (!req.allowExisting) {\n\t\t\t\t\t\t// Fail if not allowing existing actors\n\t\t\t\t\t\tlogger().debug({\n\t\t\t\t\t\t\tmsg: \"create failed: actor already exists\",\n\t\t\t\t\t\t\tname: req.name,\n\t\t\t\t\t\t\tkey: req.key,\n\t\t\t\t\t\t\tgeneration,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn { error: { actorAlreadyExists: true } };\n\t\t\t\t\t}\n\n\t\t\t\t\t// Return existing actor\n\t\t\t\t\tlogger().debug({\n\t\t\t\t\t\tmsg: \"actor already exists\",\n\t\t\t\t\t\tkey: req.key,\n\t\t\t\t\t\tgeneration,\n\t\t\t\t\t});\n\t\t\t\t\tconst doId = this.ctx.id.toString();\n\t\t\t\t\tconst actorId = buildActorId(doId, generation);\n\t\t\t\t\treturn { success: { actorId, created: false } };\n\t\t\t\t}\n\n\t\t\t\t// Actor exists but is destroyed - resurrect with incremented generation\n\t\t\t\tgeneration = generation + 1;\n\t\t\t\tcreated = true;\n\n\t\t\t\t// Clear stale actor from previous generation\n\t\t\t\t// This is necessary because the DO instance may still be in memory\n\t\t\t\t// with the old #state.actor field from before the destroy\n\t\t\t\tif (this.#state) {\n\t\t\t\t\tthis.#state.actor = undefined;\n\t\t\t\t}\n\n\t\t\t\tlogger().debug({\n\t\t\t\t\tmsg: \"resurrecting destroyed actor\",\n\t\t\t\t\tkey: req.key,\n\t\t\t\t\toldGeneration: generation - 1,\n\t\t\t\t\tnewGeneration: generation,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// No actor exists - will create with generation 0\n\t\t\t\tgeneration = 0;\n\t\t\t\tcreated = true;\n\t\t\t\tlogger().debug({\n\t\t\t\t\tmsg: \"creating new actor\",\n\t\t\t\t\tkey: req.key,\n\t\t\t\t\tgeneration,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Perform upsert - either inserts new or updates destroyed actor\n\t\t\tthis.ctx.storage.sql.exec(\n\t\t\t\t`INSERT INTO _rivetkit_metadata (id, name, key, destroyed, generation)\n\t\t\t\tVALUES (1, ?, ?, 0, ?)\n\t\t\t\tON CONFLICT(id) DO UPDATE SET\n\t\t\t\t\tname = excluded.name,\n\t\t\t\t\tkey = excluded.key,\n\t\t\t\t\tdestroyed = 0,\n\t\t\t\t\tgeneration = excluded.generation`,\n\t\t\t\treq.name,\n\t\t\t\tJSON.stringify(req.key),\n\t\t\t\tgeneration,\n\t\t\t);\n\n\t\t\tthis.#state.initialized = {\n\t\t\t\tname: req.name,\n\t\t\t\tkey: req.key,\n\t\t\t\tgeneration,\n\t\t\t};\n\n\t\t\t// Build actor ID with generation\n\t\t\tconst doId = this.ctx.id.toString();\n\t\t\tconst actorId = buildActorId(doId, generation);\n\n\t\t\t// Initialize storage and update KV when created or resurrected\n\t\t\tif (created) {\n\t\t\t\t// Initialize persist data in KV storage\n\t\t\t\tinitializeActorKvStorage(this.ctx.storage.sql, req.input);\n\n\t\t\t\t// Update metadata in the background\n\t\t\t\tconst env = getCloudflareAmbientEnv();\n\t\t\t\tconst actorData = { name: req.name, key: req.key, generation };\n\t\t\t\tthis.ctx.waitUntil(\n\t\t\t\t\tenv.ACTOR_KV.put(\n\t\t\t\t\t\tGLOBAL_KV_KEYS.actorMetadata(actorId),\n\t\t\t\t\t\tJSON.stringify(actorData),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Preemptively load actor so the lifecycle hooks are called\n\t\t\tawait this.#loadActor();\n\n\t\t\tlogger().debug({\n\t\t\t\tmsg: created\n\t\t\t\t\t? \"actor created/resurrected\"\n\t\t\t\t\t: \"returning existing actor\",\n\t\t\t\tactorId,\n\t\t\t\tcreated,\n\t\t\t\tgeneration,\n\t\t\t});\n\n\t\t\treturn { success: { actorId, created } };\n\t\t}\n\n\t\tasync fetch(request: Request): Promise<Response> {\n\t\t\tconst { actorRouter, generation } = await this.#loadActor();\n\n\t\t\t// Build actor ID with generation\n\t\t\tconst doId = this.ctx.id.toString();\n\t\t\tconst actorId = buildActorId(doId, generation);\n\n\t\t\treturn await actorRouter.fetch(request, {\n\t\t\t\tactorId,\n\t\t\t});\n\t\t}\n\n\t\tasync alarm(): Promise<void> {\n\t\t\tconst { actorDriver, generation } = await this.#loadActor();\n\n\t\t\t// Build actor ID with generation\n\t\t\tconst doId = this.ctx.id.toString();\n\t\t\tconst actorId = buildActorId(doId, generation);\n\n\t\t\t// Load the actor instance and trigger alarm\n\t\t\tconst actor = await actorDriver.loadActor(actorId);\n\t\t\tawait actor.onAlarm();\n\t\t}\n\t};\n}\n\nfunction initializeActorKvStorage(\n\tsql: SqlStorage,\n\tinput: unknown | undefined,\n): void {\n\tconst initialKvState = getInitialActorKvState(input);\n\tfor (const [key, value] of initialKvState) {\n\t\tkvPut(sql, key, value);\n\t}\n}\n","import invariant from \"invariant\";\nimport type {\n\tActorKey,\n\tActorRouter,\n\tAnyActorInstance as CoreAnyActorInstance,\n\tRegistryConfig,\n\tRunConfig,\n} from \"rivetkit\";\nimport { lookupInRegistry } from \"rivetkit\";\nimport type { Client } from \"rivetkit/client\";\nimport type {\n\tActorDriver,\n\tAnyActorInstance,\n\tManagerDriver,\n} from \"rivetkit/driver-helpers\";\nimport { promiseWithResolvers } from \"rivetkit/utils\";\nimport { parseActorId } from \"./actor-id\";\nimport { kvDelete, kvGet, kvListPrefix, kvPut } from \"./actor-kv\";\nimport { GLOBAL_KV_KEYS } from \"./global-kv\";\nimport { getCloudflareAmbientEnv } from \"./handler\";\n\ninterface DurableObjectGlobalState {\n\tctx: DurableObjectState;\n\tenv: unknown;\n}\n\n/**\n * Cloudflare DO can have multiple DO running within the same global scope.\n *\n * This allows for storing the actor context globally and looking it up by ID in `CloudflareActorsActorDriver`.\n */\nexport class CloudflareDurableObjectGlobalState {\n\t// Map of actor ID -> DO state\n\t#dos: Map<string, DurableObjectGlobalState> = new Map();\n\n\t// WeakMap of DO state -> ActorGlobalState for proper GC\n\t#actors: WeakMap<DurableObjectState, ActorGlobalState> = new WeakMap();\n\n\tgetDOState(doId: string): DurableObjectGlobalState {\n\t\tconst state = this.#dos.get(doId);\n\t\tinvariant(\n\t\t\tstate !== undefined,\n\t\t\t\"durable object state not in global state\",\n\t\t);\n\t\treturn state;\n\t}\n\n\tsetDOState(doId: string, state: DurableObjectGlobalState) {\n\t\tthis.#dos.set(doId, state);\n\t}\n\n\tgetActorState(ctx: DurableObjectState): ActorGlobalState | undefined {\n\t\treturn this.#actors.get(ctx);\n\t}\n\n\tsetActorState(ctx: DurableObjectState, actorState: ActorGlobalState): void {\n\t\tthis.#actors.set(ctx, actorState);\n\t}\n}\n\nexport interface DriverContext {\n\tstate: DurableObjectState;\n}\n\ninterface InitializedData {\n\tname: string;\n\tkey: ActorKey;\n\tgeneration: number;\n}\n\ninterface LoadedActor {\n\tactorRouter: ActorRouter;\n\tactorDriver: ActorDriver;\n\tgeneration: number;\n}\n\n// Actor global state to track running instances\nexport class ActorGlobalState {\n\t// Initialization state\n\tinitialized?: InitializedData;\n\n\t// Loaded actor state\n\tactor?: LoadedActor;\n\tactorInstance?: AnyActorInstance;\n\tactorPromise?: ReturnType<typeof promiseWithResolvers<void>>;\n\n\t/**\n\t * Indicates if `startDestroy` has been called.\n\t *\n\t * This is stored in memory instead of SQLite since the destroy may be cancelled.\n\t *\n\t * See the corresponding `destroyed` property in SQLite metadata.\n\t */\n\tdestroying: boolean = false;\n\n\treset() {\n\t\tthis.initialized = undefined;\n\t\tthis.actor = undefined;\n\t\tthis.actorInstance = undefined;\n\t\tthis.actorPromise = undefined;\n\t\tthis.destroying = false;\n\t}\n}\n\nexport class CloudflareActorsActorDriver implements ActorDriver {\n\t#registryConfig: RegistryConfig;\n\t#runConfig: RunConfig;\n\t#managerDriver: ManagerDriver;\n\t#inlineClient: Client<any>;\n\t#globalState: CloudflareDurableObjectGlobalState;\n\n\tconstructor(\n\t\tregistryConfig: RegistryConfig,\n\t\trunConfig: RunConfig,\n\t\tmanagerDriver: ManagerDriver,\n\t\tinlineClient: Client<any>,\n\t\tglobalState: CloudflareDurableObjectGlobalState,\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.#globalState = globalState;\n\t}\n\n\t#getDOCtx(actorId: string) {\n\t\t// Parse actor ID to get DO ID\n\t\tconst [doId] = parseActorId(actorId);\n\t\treturn this.#globalState.getDOState(doId).ctx;\n\t}\n\n\tasync loadActor(actorId: string): Promise<AnyActorInstance> {\n\t\t// Parse actor ID to get DO ID and generation\n\t\tconst [doId, expectedGeneration] = parseActorId(actorId);\n\n\t\t// Get the DO state\n\t\tconst doState = this.#globalState.getDOState(doId);\n\n\t\t// Check if actor is already loaded\n\t\tlet actorState = this.#globalState.getActorState(doState.ctx);\n\t\tif (actorState?.actorInstance) {\n\t\t\t// Actor is already loaded, return it\n\t\t\treturn actorState.actorInstance;\n\t\t}\n\n\t\t// Create new actor state if it doesn't exist\n\t\tif (!actorState) {\n\t\t\tactorState = new ActorGlobalState();\n\t\t\tactorState.actorPromise = promiseWithResolvers();\n\t\t\tthis.#globalState.setActorState(doState.ctx, actorState);\n\t\t} else if (actorState.actorPromise) {\n\t\t\t// Another request is already loading this actor, wait for it\n\t\t\tawait actorState.actorPromise.promise;\n\t\t\tif (!actorState.actorInstance) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Actor ${actorId} failed to load in concurrent request`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn actorState.actorInstance;\n\t\t}\n\n\t\t// Load actor metadata\n\t\tconst sql = doState.ctx.storage.sql;\n\t\tconst cursor = sql.exec(\n\t\t\t\"SELECT name, key, destroyed, generation FROM _rivetkit_metadata LIMIT 1\",\n\t\t);\n\t\tconst result = cursor.raw().next();\n\n\t\tif (result.done || !result.value) {\n\t\t\tthrow new Error(\n\t\t\t\t`Actor ${actorId} is not initialized - missing metadata`,\n\t\t\t);\n\t\t}\n\n\t\tconst name = result.value[0] as string;\n\t\tconst key = JSON.parse(result.value[1] as string) as string[];\n\t\tconst destroyed = result.value[2] as number;\n\t\tconst generation = result.value[3] as number;\n\n\t\t// Check if actor is destroyed\n\t\tif (destroyed) {\n\t\t\tthrow new Error(`Actor ${actorId} is destroyed`);\n\t\t}\n\n\t\t// Check if generation matches\n\t\tif (generation !== expectedGeneration) {\n\t\t\tthrow new Error(\n\t\t\t\t`Actor ${actorId} generation mismatch - expected ${expectedGeneration}, got ${generation}`,\n\t\t\t);\n\t\t}\n\n\t\t// Create actor instance\n\t\tconst definition = lookupInRegistry(this.#registryConfig, name);\n\t\tactorState.actorInstance = definition.instantiate();\n\n\t\t// Start actor\n\t\tawait actorState.actorInstance.start(\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: Support regions in Cloudflare\n\t\t);\n\n\t\t// Finish\n\t\tactorState.actorPromise?.resolve();\n\t\tactorState.actorPromise = undefined;\n\n\t\treturn actorState.actorInstance;\n\t}\n\n\tgetContext(actorId: string): DriverContext {\n\t\t// Parse actor ID to get DO ID\n\t\tconst [doId] = parseActorId(actorId);\n\t\tconst state = this.#globalState.getDOState(doId);\n\t\treturn { state: state.ctx };\n\t}\n\n\tasync setAlarm(actor: AnyActorInstance, timestamp: number): Promise<void> {\n\t\tawait this.#getDOCtx(actor.id).storage.setAlarm(timestamp);\n\t}\n\n\tasync getDatabase(actorId: string): Promise<unknown | undefined> {\n\t\treturn this.#getDOCtx(actorId).storage.sql;\n\t}\n\n\t// Batch KV operations\n\tasync kvBatchPut(\n\t\tactorId: string,\n\t\tentries: [Uint8Array, Uint8Array][],\n\t): Promise<void> {\n\t\tconst sql = this.#getDOCtx(actorId).storage.sql;\n\n\t\tfor (const [key, value] of entries) {\n\t\t\tkvPut(sql, key, value);\n\t\t}\n\t}\n\n\tasync kvBatchGet(\n\t\tactorId: string,\n\t\tkeys: Uint8Array[],\n\t): Promise<(Uint8Array | null)[]> {\n\t\tconst sql = this.#getDOCtx(actorId).storage.sql;\n\n\t\tconst results: (Uint8Array | null)[] = [];\n\t\tfor (const key of keys) {\n\t\t\tresults.push(kvGet(sql, key));\n\t\t}\n\n\t\treturn results;\n\t}\n\n\tasync kvBatchDelete(actorId: string, keys: Uint8Array[]): Promise<void> {\n\t\tconst sql = this.#getDOCtx(actorId).storage.sql;\n\n\t\tfor (const key of keys) {\n\t\t\tkvDelete(sql, key);\n\t\t}\n\t}\n\n\tasync kvListPrefix(\n\t\tactorId: string,\n\t\tprefix: Uint8Array,\n\t): Promise<[Uint8Array, Uint8Array][]> {\n\t\tconst sql = this.#getDOCtx(actorId).storage.sql;\n\n\t\treturn kvListPrefix(sql, prefix);\n\t}\n\n\tstartDestroy(actorId: string): void {\n\t\t// Parse actor ID to get DO ID and generation\n\t\tconst [doId, generation] = parseActorId(actorId);\n\n\t\t// Get the DO state\n\t\tconst doState = this.#globalState.getDOState(doId);\n\t\tconst actorState = this.#globalState.getActorState(doState.ctx);\n\n\t\t// Actor not loaded, nothing to destroy\n\t\tif (!actorState?.actorInstance) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if already destroying\n\t\tif (actorState.destroying) {\n\t\t\treturn;\n\t\t}\n\t\tactorState.destroying = true;\n\n\t\t// Spawn onStop in background\n\t\tthis.#callOnStopAsync(actorId, doId, actorState.actorInstance);\n\t}\n\n\tasync #callOnStopAsync(\n\t\tactorId: string,\n\t\tdoId: string,\n\t\tactor: CoreAnyActorInstance,\n\t) {\n\t\t// Stop\n\t\tawait actor.onStop(\"destroy\");\n\n\t\t// Remove state\n\t\tconst doState = this.#globalState.getDOState(doId);\n\t\tconst sql = doState.ctx.storage.sql;\n\t\tsql.exec(\"UPDATE _rivetkit_metadata SET destroyed = 1 WHERE 1=1\");\n\t\tsql.exec(\"DELETE FROM _rivetkit_kv_storage\");\n\n\t\t// Clear any scheduled alarms\n\t\tawait doState.ctx.storage.deleteAlarm();\n\n\t\t// Delete from ACTOR_KV in the background - use full actorId including generation\n\t\tconst env = getCloudflareAmbientEnv();\n\t\tdoState.ctx.waitUntil(\n\t\t\tenv.ACTOR_KV.delete(GLOBAL_KV_KEYS.actorMetadata(actorId)),\n\t\t);\n\n\t\t// Reset global state using the DO context\n\t\tconst actorHandle = this.#globalState.getActorState(doState.ctx);\n\t\tactorHandle?.reset();\n\t}\n}\n\nexport function createCloudflareActorsActorDriverBuilder(\n\tglobalState: CloudflareDurableObjectGlobalState,\n) {\n\treturn (\n\t\tregistryConfig: RegistryConfig,\n\t\trunConfig: RunConfig,\n\t\tmanagerDriver: ManagerDriver,\n\t\tinlineClient: Client<any>,\n\t) => {\n\t\treturn new CloudflareActorsActorDriver(\n\t\t\tregistryConfig,\n\t\t\trunConfig,\n\t\t\tmanagerDriver,\n\t\t\tinlineClient,\n\t\t\tglobalState,\n\t\t);\n\t};\n}\n","/**\n * Actor ID utilities for managing actor IDs with generation tracking.\n *\n * Actor IDs are formatted as: `{doId}:{generation}`\n * This allows tracking actor resurrection and preventing stale references.\n */\n\n/**\n * Build an actor ID from a Durable Object ID and generation number.\n * @param doId The Durable Object ID\n * @param generation The generation number (increments on resurrection)\n * @returns The formatted actor ID\n */\nexport function buildActorId(doId: string, generation: number): string {\n\treturn `${doId}:${generation}`;\n}\n\n/**\n * Parse an actor ID into its components.\n * @param actorId The actor ID to parse\n * @returns A tuple of [doId, generation]\n * @throws Error if the actor ID format is invalid\n */\nexport function parseActorId(actorId: string): [string, number] {\n\tconst parts = actorId.split(\":\");\n\tif (parts.length !== 2) {\n\t\tthrow new Error(`Invalid actor ID format: ${actorId}`);\n\t}\n\n\tconst [doId, generationStr] = parts;\n\tconst generation = parseInt(generationStr, 10);\n\n\tif (Number.isNaN(generation)) {\n\t\tthrow new Error(`Invalid generation number in actor ID: ${actorId}`);\n\t}\n\n\treturn [doId, generation];\n}\n","export function kvGet(sql: SqlStorage, key: Uint8Array): Uint8Array | null {\n\tconst cursor = sql.exec(\n\t\t\"SELECT value FROM _rivetkit_kv_storage WHERE key = ?\",\n\t\tkey,\n\t);\n\tconst result = cursor.raw().next();\n\n\tif (!result.done && result.value) {\n\t\treturn toUint8Array(result.value[0]);\n\t}\n\treturn null;\n}\n\nexport function kvPut(\n\tsql: SqlStorage,\n\tkey: Uint8Array,\n\tvalue: Uint8Array,\n): void {\n\tsql.exec(\n\t\t\"INSERT OR REPLACE INTO _rivetkit_kv_storage (key, value) VALUES (?, ?)\",\n\t\tkey,\n\t\tvalue,\n\t);\n}\n\nexport function kvDelete(sql: SqlStorage, key: Uint8Array): void {\n\tsql.exec(\"DELETE FROM _rivetkit_kv_storage WHERE key = ?\", key);\n}\n\nexport function kvListPrefix(\n\tsql: SqlStorage,\n\tprefix: Uint8Array,\n): [Uint8Array, Uint8Array][] {\n\tconst cursor = sql.exec(\"SELECT key, value FROM _rivetkit_kv_storage\");\n\tconst entries: [Uint8Array, Uint8Array][] = [];\n\n\tfor (const row of cursor.raw()) {\n\t\tconst key = toUint8Array(row[0]);\n\t\tconst value = toUint8Array(row[1]);\n\n\t\t// Check if key starts with prefix\n\t\tif (hasPrefix(key, prefix)) {\n\t\t\tentries.push([key, value]);\n\t\t}\n\t}\n\n\treturn entries;\n}\n\n// Helper function to convert SqlStorageValue to Uint8Array\nfunction toUint8Array(\n\tvalue: string | number | ArrayBuffer | Uint8Array | null,\n): Uint8Array {\n\tif (value instanceof Uint8Array) {\n\t\treturn value;\n\t}\n\tif (value instanceof ArrayBuffer) {\n\t\treturn new Uint8Array(value);\n\t}\n\tthrow new Error(\n\t\t`Unexpected SQL value type: ${typeof value} (${value?.constructor?.name})`,\n\t);\n}\n\nfunction hasPrefix(arr: Uint8Array, prefix: Uint8Array): boolean {\n\tif (prefix.length > arr.length) return false;\n\tfor (let i = 0; i < prefix.length; i++) {\n\t\tif (arr[i] !== prefix[i]) return false;\n\t}\n\treturn true;\n}\n","/** KV keys for using Workers KV to store actor metadata globally. */\nexport const GLOBAL_KV_KEYS = {\n\tactorMetadata: (actorId: string): string => {\n\t\treturn `actor:${actorId}:metadata`;\n\t},\n};\n","import { env } from \"cloudflare:workers\";\nimport type { Client, Registry, RunConfig } from \"rivetkit\";\nimport {\n\ttype ActorHandlerInterface,\n\tcreateActorDurableObject,\n\ttype DurableObjectConstructor,\n} from \"./actor-handler-do\";\nimport { type Config, ConfigSchema, type InputConfig } from \"./config\";\nimport { CloudflareActorsManagerDriver } from \"./manager-driver\";\nimport { upgradeWebSocket } from \"./websocket\";\n\n/** Cloudflare Workers env */\nexport interface Bindings {\n\tACTOR_KV: KVNamespace;\n\tACTOR_DO: DurableObjectNamespace<ActorHandlerInterface>;\n}\n\n/**\n * Stores the env for the current request. Required since some contexts like the inline client driver does not have access to the Hono context.\n *\n * Use getCloudflareAmbientEnv unless using CF_AMBIENT_ENV.run.\n */\nexport function getCloudflareAmbientEnv(): Bindings {\n\treturn env as unknown as Bindings;\n}\n\nexport interface InlineOutput<A extends Registry<any>> {\n\t/** Client to communicate with the actors. */\n\tclient: Client<A>;\n\n\t/** Fetch handler to manually route requests to the Rivet manager API. */\n\tfetch: (request: Request, ...args: any) => Response | Promise<Response>;\n\n\tconfig: Config;\n\n\tActorHandler: DurableObjectConstructor;\n}\n\nexport interface HandlerOutput {\n\thandler: ExportedHandler<Bindings>;\n\tActorHandler: DurableObjectConstructor;\n}\n\n/**\n * Creates an inline client for accessing Rivet Actors privately without a public manager API.\n *\n * If you want to expose a public manager API, either:\n *\n * - Use `createHandler` to expose the Rivet API on `/rivet`\n * - Forward Rivet API requests to `InlineOutput::fetch`\n */\nexport function createInlineClient<R extends Registry<any>>(\n\tregistry: R,\n\tinputConfig?: InputConfig,\n): InlineOutput<R> {\n\t// HACK: Cloudflare does not support using `crypto.randomUUID()` before start, so we pass a default value\n\t//\n\t// Runner key is not used on Cloudflare\n\tinputConfig = { ...inputConfig, runnerKey: \"\" };\n\n\t// Parse config\n\tconst config = ConfigSchema.parse(inputConfig);\n\n\t// Create config\n\tconst runConfig = {\n\t\t...config,\n\t\tdriver: {\n\t\t\tname: \"cloudflare-workers\",\n\t\t\tmanager: () => new CloudflareActorsManagerDriver(),\n\t\t\t// HACK: We can't build the actor driver until we're inside the Durable Object\n\t\t\tactor: undefined as any,\n\t\t},\n\t\tgetUpgradeWebSocket: () => upgradeWebSocket,\n\t} satisfies RunConfig;\n\n\t// Create Durable Object\n\tconst ActorHandler = createActorDurableObject(registry, runConfig);\n\n\t// Create server\n\tconst { client, fetch } = registry.start(runConfig);\n\n\treturn { client, fetch, config, ActorHandler };\n}\n\n/**\n * Creates a handler to be exported from a Cloudflare Worker.\n *\n * This will automatically expose the Rivet manager API on `/rivet`.\n *\n * This includes a `fetch` handler and `ActorHandler` Durable Object.\n */\nexport function createHandler<R extends Registry<any>>(\n\tregistry: R,\n\tinputConfig?: InputConfig,\n): HandlerOutput {\n\tconst { client, fetch, config, ActorHandler } = createInlineClient(\n\t\tregistry,\n\t\tinputConfig,\n\t);\n\n\t// Create Cloudflare handler\n\tconst handler = {\n\t\tfetch: async (request, cfEnv, ctx) => {\n\t\t\tconst url = new URL(request.url);\n\n\t\t\t// Inject Rivet env\n\t\t\tconst env = Object.assign({ RIVET: client }, cfEnv);\n\n\t\t\t// Mount Rivet manager API\n\t\t\tif (url.pathname.startsWith(config.managerPath)) {\n\t\t\t\tconst strippedPath = url.pathname.substring(\n\t\t\t\t\tconfig.managerPath.length,\n\t\t\t\t);\n\t\t\t\turl.pathname = strippedPath;\n\t\t\t\tconst modifiedRequest = new Request(url.toString(), request);\n\t\t\t\treturn fetch(modifiedRequest, env, ctx);\n\t\t\t}\n\n\t\t\tif (config.fetch) {\n\t\t\t\treturn config.fetch(request, env, ctx);\n\t\t\t} else {\n\t\t\t\treturn new Response(\n\t\t\t\t\t\"This is a RivetKit server.\\n\\nLearn more at https://rivetkit.org\\n\",\n\t\t\t\t\t{ status: 200 },\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t} satisfies ExportedHandler<Bindings>;\n\n\treturn { handler, ActorHandler };\n}\n","import type { Client } from \"rivetkit\";\nimport { RunConfigSchema } from \"rivetkit/driver-helpers\";\nimport { z } from \"zod\";\n\nconst ConfigSchemaBase = RunConfigSchema.removeDefault()\n\t.omit({ driver: true, getUpgradeWebSocket: true })\n\t.extend({\n\t\t/** Path that the Rivet manager API will be mounted. */\n\t\tmanagerPath: z.string().optional().default(\"/rivet\"),\n\n\t\tfetch: z\n\t\t\t.custom<\n\t\t\t\tExportedHandlerFetchHandler<{ RIVET: Client<any> }, unknown>\n\t\t\t>()\n\t\t\t.optional(),\n\t});\nexport const ConfigSchema = ConfigSchemaBase.default(() =>\n\tConfigSchemaBase.parse({}),\n);\nexport type InputConfig = z.input<typeof ConfigSchema>;\nexport type Config = z.infer<typeof ConfigSchema>;\n","import type { Context as HonoContext } from \"hono\";\nimport type { Encoding, UniversalWebSocket } from \"rivetkit\";\nimport {\n\ttype ActorOutput,\n\ttype CreateInput,\n\ttype GetForIdInput,\n\ttype GetOrCreateWithKeyInput,\n\ttype GetWithKeyInput,\n\tgenerateRandomString,\n\ttype ListActorsInput,\n\ttype ManagerDisplayInformation,\n\ttype ManagerDriver,\n\tWS_PROTOCOL_ACTOR,\n\tWS_PROTOCOL_CONN_PARAMS,\n\tWS_PROTOCOL_ENCODING,\n\tWS_PROTOCOL_STANDARD,\n\tWS_PROTOCOL_TARGET,\n} from \"rivetkit/driver-helpers\";\nimport {\n\tActorDuplicateKey,\n\tActorNotFound,\n\tInternalError,\n} from \"rivetkit/errors\";\nimport { assertUnreachable } from \"rivetkit/utils\";\nimport { parseActorId } from \"./actor-id\";\nimport { getCloudflareAmbientEnv } from \"./handler\";\nimport { logger } from \"./log\";\nimport type { Bindings } from \"./mod\";\nimport { serializeNameAndKey } from \"./util\";\n\nconst STANDARD_WEBSOCKET_HEADERS = [\n\t\"connection\",\n\t\"upgrade\",\n\t\"sec-websocket-key\",\n\t\"sec-websocket-version\",\n\t\"sec-websocket-protocol\",\n\t\"sec-websocket-extensions\",\n];\n\nexport class CloudflareActorsManagerDriver implements ManagerDriver {\n\tasync sendRequest(\n\t\tactorId: string,\n\t\tactorRequest: Request,\n\t): Promise<Response> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\t// Parse actor ID to get DO ID\n\t\tconst [doId] = parseActorId(actorId);\n\n\t\tlogger().debug({\n\t\t\tmsg: \"sending request to durable object\",\n\t\t\tactorId,\n\t\t\tdoId,\n\t\t\tmethod: actorRequest.method,\n\t\t\turl: actorRequest.url,\n\t\t});\n\n\t\tconst id = env.ACTOR_DO.idFromString(doId);\n\t\tconst stub = env.ACTOR_DO.get(id);\n\n\t\treturn await stub.fetch(actorRequest);\n\t}\n\n\tasync openWebSocket(\n\t\tpath: string,\n\t\tactorId: string,\n\t\tencoding: Encoding,\n\t\tparams: unknown,\n\t): Promise<UniversalWebSocket> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\t// Parse actor ID to get DO ID\n\t\tconst [doId] = parseActorId(actorId);\n\n\t\tlogger().debug({\n\t\t\tmsg: \"opening websocket to durable object\",\n\t\t\tactorId,\n\t\t\tdoId,\n\t\t\tpath,\n\t\t});\n\n\t\t// Make a fetch request to the Durable Object with WebSocket upgrade\n\t\tconst id = env.ACTOR_DO.idFromString(doId);\n\t\tconst stub = env.ACTOR_DO.get(id);\n\n\t\tconst protocols: string[] = [];\n\t\tprotocols.push(WS_PROTOCOL_STANDARD);\n\t\tprotocols.push(`${WS_PROTOCOL_TARGET}actor`);\n\t\tprotocols.push(`${WS_PROTOCOL_ACTOR}${encodeURIComponent(actorId)}`);\n\t\tprotocols.push(`${WS_PROTOCOL_ENCODING}${encoding}`);\n\t\tif (params) {\n\t\t\tprotocols.push(\n\t\t\t\t`${WS_PROTOCOL_CONN_PARAMS}${encodeURIComponent(JSON.stringify(params))}`,\n\t\t\t);\n\t\t}\n\n\t\tconst headers: Record<string, string> = {\n\t\t\tUpgrade: \"websocket\",\n\t\t\tConnection: \"Upgrade\",\n\t\t\t\"sec-websocket-protocol\": protocols.join(\", \"),\n\t\t};\n\n\t\t// Use the path parameter to determine the URL\n\t\tconst normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n\t\tconst url = `http://actor${normalizedPath}`;\n\n\t\tlogger().debug({ msg: \"rewriting websocket url\", from: path, to: url });\n\n\t\tconst response = await stub.fetch(url, {\n\t\t\theaders,\n\t\t});\n\t\tconst webSocket = response.webSocket;\n\n\t\tif (!webSocket) {\n\t\t\tthrow new InternalError(\n\t\t\t\t`missing websocket connection in response from DO\\n\\nStatus: ${response.status}\\nResponse: ${await response.text()}`,\n\t\t\t);\n\t\t}\n\n\t\tlogger().debug({\n\t\t\tmsg: \"durable object websocket connection open\",\n\t\t\tactorId,\n\t\t});\n\n\t\twebSocket.accept();\n\n\t\t// TODO: Is this still needed?\n\t\t// HACK: Cloudflare does not call onopen automatically, so we need\n\t\t// to call this on the next tick\n\t\tsetTimeout(() => {\n\t\t\tconst event = new Event(\"open\");\n\t\t\t(webSocket as any).onopen?.(event);\n\t\t\t(webSocket as any).dispatchEvent(event);\n\t\t}, 0);\n\n\t\treturn webSocket as unknown as UniversalWebSocket;\n\t}\n\n\tasync proxyRequest(\n\t\tc: HonoContext<{ Bindings: Bindings }>,\n\t\tactorRequest: Request,\n\t\tactorId: string,\n\t): Promise<Response> {\n\t\t// Parse actor ID to get DO ID\n\t\tconst [doId] = parseActorId(actorId);\n\n\t\tlogger().debug({\n\t\t\tmsg: \"forwarding request to durable object\",\n\t\t\tactorId,\n\t\t\tdoId,\n\t\t\tmethod: actorRequest.method,\n\t\t\turl: actorRequest.url,\n\t\t});\n\n\t\tconst id = c.env.ACTOR_DO.idFromString(doId);\n\t\tconst stub = c.env.ACTOR_DO.get(id);\n\n\t\treturn await stub.fetch(actorRequest);\n\t}\n\n\tasync proxyWebSocket(\n\t\tc: HonoContext<{ Bindings: Bindings }>,\n\t\tpath: string,\n\t\tactorId: string,\n\t\tencoding: Encoding,\n\t\tparams: unknown,\n\t): Promise<Response> {\n\t\tlogger().debug({\n\t\t\tmsg: \"forwarding websocket to durable object\",\n\t\t\tactorId,\n\t\t\tpath,\n\t\t});\n\n\t\t// Validate upgrade\n\t\tconst upgradeHeader = c.req.header(\"Upgrade\");\n\t\tif (!upgradeHeader || upgradeHeader !== \"websocket\") {\n\t\t\treturn new Response(\"Expected Upgrade: websocket\", {\n\t\t\t\tstatus: 426,\n\t\t\t});\n\t\t}\n\n\t\tconst newUrl = new URL(`http://actor${path}`);\n\t\tconst actorRequest = new Request(newUrl, c.req.raw);\n\n\t\tlogger().debug({\n\t\t\tmsg: \"rewriting websocket url\",\n\t\t\tfrom: c.req.url,\n\t\t\tto: actorRequest.url,\n\t\t});\n\n\t\t// Always build fresh request to prevent forwarding unwanted headers\n\t\t// HACK: Since we can't build a new request, we need to remove\n\t\t// non-standard headers manually\n\t\tconst headerKeys: string[] = [];\n\t\tactorRequest.headers.forEach((v, k) => {\n\t\t\theaderKeys.push(k);\n\t\t});\n\t\tfor (const k of headerKeys) {\n\t\t\tif (!STANDARD_WEBSOCKET_HEADERS.includes(k)) {\n\t\t\t\tactorRequest.headers.delete(k);\n\t\t\t}\n\t\t}\n\n\t\t// Build protocols for WebSocket connection\n\t\tconst protocols: string[] = [];\n\t\tprotocols.push(WS_PROTOCOL_STANDARD);\n\t\tprotocols.push(`${WS_PROTOCOL_TARGET}actor`);\n\t\tprotocols.push(`${WS_PROTOCOL_ACTOR}${encodeURIComponent(actorId)}`);\n\t\tprotocols.push(`${WS_PROTOCOL_ENCODING}${encoding}`);\n\t\tif (params) {\n\t\t\tprotocols.push(\n\t\t\t\t`${WS_PROTOCOL_CONN_PARAMS}${encodeURIComponent(JSON.stringify(params))}`,\n\t\t\t);\n\t\t}\n\t\tactorRequest.headers.set(\n\t\t\t\"sec-websocket-protocol\",\n\t\t\tprotocols.join(\", \"),\n\t\t);\n\n\t\t// Parse actor ID to get DO ID\n\t\tconst [doId] = parseActorId(actorId);\n\t\tconst id = c.env.ACTOR_DO.idFromString(doId);\n\t\tconst stub = c.env.ACTOR_DO.get(id);\n\n\t\treturn await stub.fetch(actorRequest);\n\t}\n\n\tasync getForId({\n\t\tc,\n\t\tactorId,\n\t}: GetForIdInput<{ Bindings: Bindings }>): Promise<\n\t\tActorOutput | undefined\n\t> {\n\t\tconst env = getCloudflareAmbientEnv();\n\n\t\t// Parse actor ID to get DO ID and expected generation\n\t\tconst [doId, expectedGeneration] = parseActorId(actorId);\n\n\t\t// Get the Durable Object stub\n\t\tconst id = env.ACTOR_DO.idFromString(doId);\n\t\tconst stub = env.ACTOR_DO.get(id);\n\n\t\t// Call the DO's getMetadata method\n\t\tconst result = await stub.getMetadata();\n\n\t\tif (!result) {\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"getForId: actor not found\",\n\t\t\t\tactorId,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Check if the actor IDs match in order to check if the generation matches\n\t\tif (result.actorId !== actorId) {\n\t\t\tlogger().debug({\n\t\t\t\tmsg: \"getForId: generation mismatch\",\n\t\t\t\trequestedActorId: actorId,\n\t\t\t\tactualActorId: result.actorId,\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (result.destroying) {\n\t\t\tthrow new ActorNotFound(actorId);\n\t\t}\n\n\t\treturn {\n\t\t\tactorId: result.actorId,\n\t\t\tname: result.name,\n\t\t\tkey: result.key,\n\t\t};\n\t}\n\n\tasync getWithKey({\n\t\tc,\n\t\