agents 0.30.1 → 0.32.0
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 +2 -1
- package/dist/{agent-routing-CDbpVjYq.d.ts → agent-routing-vVMA7m8Y.d.ts} +69 -608
- package/dist/agent-routing.d.ts +1 -1
- package/dist/agent-tool-types.d.ts +1 -1
- package/dist/{agent-tools-C8DH8Yii.d.ts → agent-tools-gGXXkf1z.d.ts} +2 -2
- package/dist/agent-tools.d.ts +1 -1
- package/dist/agent-tools.js +0 -1
- package/dist/agent-tools.js.map +1 -1
- package/dist/{ai-iXw0uOGj.d.ts → ai-CDn3Abax.d.ts} +30 -4
- package/dist/{ai-sdk-DRPh2rRa.js → ai-sdk-Kon40i0q.js} +2 -36
- package/dist/ai-sdk-Kon40i0q.js.map +1 -0
- package/dist/browser/ai.d.ts +1 -1
- package/dist/browser/ai.js +16 -3
- package/dist/browser/ai.js.map +1 -1
- package/dist/browser/index.d.ts +64 -16
- package/dist/browser/index.js +4 -4
- package/dist/browser/tools/ai-sdk.d.ts +7 -5
- package/dist/browser/tools/ai-sdk.js +4 -4
- package/dist/browser/tools/ai-sdk.js.map +1 -1
- package/dist/browser/tools/pi.d.ts +9 -15
- package/dist/browser/tools/pi.js +6 -14
- package/dist/browser/tools/pi.js.map +1 -1
- package/dist/browser/tools/tanstack-ai.d.ts +48 -25
- package/dist/browser/tools/tanstack-ai.js +8 -4
- package/dist/browser/tools/tanstack-ai.js.map +1 -1
- package/dist/{browser-DccPw_wW.js → browser-1eUbPvC2.js} +413 -14
- package/dist/browser-1eUbPvC2.js.map +1 -0
- package/dist/{browser-DlXhSAdf.d.ts → browser-D9RNpJuT.d.ts} +254 -20
- package/dist/browser-tool-BhjCcNVE.d.ts +71 -0
- package/dist/browser-tool-DRan7Lk6.js +497 -0
- package/dist/browser-tool-DRan7Lk6.js.map +1 -0
- package/dist/capability-id-B3J8Nok_.js +13 -0
- package/dist/capability-id-B3J8Nok_.js.map +1 -0
- package/dist/catalog-BpOejOsE.js +239 -0
- package/dist/catalog-BpOejOsE.js.map +1 -0
- package/dist/catalog-BpiVV1OF.d.ts +173 -0
- package/dist/chat/index.d.ts +2 -2
- package/dist/chat-sdk/index.d.ts +3 -3
- package/dist/chat-sdk/index.js +1 -1
- package/dist/client-4OlMIJx-.js.map +1 -1
- package/dist/{client-BnYbNT3z.js → client-DMWujQJ1.js} +68 -244
- package/dist/client-DMWujQJ1.js.map +1 -0
- package/dist/{client-C27CtRZr.d.ts → client-eSfgYvd3.d.ts} +9 -7
- package/dist/client.d.ts +1 -1
- package/dist/{cloudflare-Dzvc7V2N.js → cloudflare-CUUm_9q9.js} +26 -4
- package/dist/cloudflare-CUUm_9q9.js.map +1 -0
- package/dist/{connector-DAXBOIIi.js → connector-CM-uuxKM.js} +96 -8
- package/dist/connector-CM-uuxKM.js.map +1 -0
- package/dist/{connector-20DJ6p4k.d.ts → connector-DZ71EjE-.d.ts} +109 -9
- package/dist/{do-oauth-client-provider-DfsUcpc3.d.ts → do-oauth-client-provider-DtNqv7oj.d.ts} +26 -2
- package/dist/{index-YSKgfgg9.d.ts → emitter-BJZtCVjQ.d.ts} +6 -140
- package/dist/emitter-DPOVcCln.js +15 -0
- package/dist/emitter-DPOVcCln.js.map +1 -0
- package/dist/experimental/channels/web/index.js +1 -1
- package/dist/experimental/webmcp.js +1 -1
- package/dist/{handler-stateless-Bly_nSH3.js → handler-stateless-B5hU3dxK.js} +35 -2
- package/dist/handler-stateless-B5hU3dxK.js.map +1 -0
- package/dist/{handler-stateless-DxYpJ_XF.d.ts → handler-stateless-C90kD5_R.d.ts} +3 -47
- package/dist/harness/container/index.d.ts +15 -15
- package/dist/harness/container/index.js +0 -1
- package/dist/harness/container/index.js.map +1 -1
- package/dist/harness/container/runtime/index.js +2 -2
- package/dist/harness/opencode/index.js +0 -1
- package/dist/harness/opencode/index.js.map +1 -1
- package/dist/harness/pi/index.d.ts +15 -7
- package/dist/harness/pi/index.js +74 -151
- package/dist/harness/pi/index.js.map +1 -1
- package/dist/harness/think/index.d.ts +2 -1
- package/dist/{images-xaDv2Fqe.js → images-CfuRCjwq.js} +1 -5
- package/dist/images-CfuRCjwq.js.map +1 -0
- package/dist/{index-DCxk3OSJ.d.ts → index-8k4qsX1T.d.ts} +2 -28
- package/dist/index.d.ts +15 -16
- package/dist/index.js +3 -3
- package/dist/internal-hosts-Kfp5A392.d.ts +230 -0
- package/dist/internal-kmw70xwR.js.map +1 -1
- package/dist/invoker-BC1SZ3q1.js +26 -0
- package/dist/invoker-BC1SZ3q1.js.map +1 -0
- package/dist/invoker-DoLFPJZV.d.ts +21 -0
- package/dist/markdown-BZ-VLtA1.js +86 -0
- package/dist/markdown-BZ-VLtA1.js.map +1 -0
- package/dist/mcp/client/do-oauth-client-provider.d.ts +4 -2
- package/dist/mcp/client/do-oauth-client-provider.js +15 -1
- package/dist/mcp/client/do-oauth-client-provider.js.map +1 -1
- package/dist/mcp/client/index.d.ts +15 -1
- package/dist/mcp/client/index.js +2 -2
- package/dist/mcp/client/x402.d.ts +7 -5
- package/dist/mcp/client/x402.js +34 -1
- package/dist/mcp/client/x402.js.map +1 -1
- package/dist/mcp/index.d.ts +561 -27
- package/dist/mcp/index.js +180 -3
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/server/index.d.ts +1 -1
- package/dist/mcp/server/index.js +1 -1
- package/dist/models/ai-sdk/index.d.ts +2 -2
- package/dist/models/ai-sdk/index.js +1 -1
- package/dist/models/opencode/index.d.ts +2 -2
- package/dist/models/opencode/index.js +1 -1
- package/dist/models/pi-ai/index.d.ts +3 -28
- package/dist/models/pi-ai/index.js +160 -18
- package/dist/models/pi-ai/index.js.map +1 -1
- package/dist/observability/ai/index.js +1 -2
- package/dist/observability/ai/index.js.map +1 -1
- package/dist/observability/index.d.ts +170 -9
- package/dist/observability/index.js +386 -11
- package/dist/observability/index.js.map +1 -1
- package/dist/protocol-BEgrJYC5.d.ts +29 -29
- package/dist/react.d.ts +2 -2
- package/dist/resource-B59OV2a2.js +325 -0
- package/dist/resource-B59OV2a2.js.map +1 -0
- package/dist/routing/index.d.ts +1 -1
- package/dist/script-CFDLTk5b.d.ts +91 -0
- package/dist/script-workspace-BpdAYq1R.d.ts +41 -0
- package/dist/serializable.d.ts +1 -1
- package/dist/{session-store-yvwq1f9x.js → session-7CDgVE0z.js} +455 -33
- package/dist/session-7CDgVE0z.js.map +1 -0
- package/dist/{session-store-_IK6dV-w.d.ts → session-store-B7Ca-u1t.d.ts} +8 -1
- package/dist/settings-Dk2il2Hf.js.map +1 -1
- package/dist/skill-DRBcIBjC.d.ts +221 -0
- package/dist/skills/index.d.ts +275 -36
- package/dist/skills/index.js +265 -1534
- package/dist/skills/index.js.map +1 -1
- package/dist/skills/runner.d.ts +37 -0
- package/dist/skills/runner.js +912 -0
- package/dist/skills/runner.js.map +1 -0
- package/dist/skills/tools/ai-sdk.d.ts +36 -0
- package/dist/skills/tools/ai-sdk.js +94 -0
- package/dist/skills/tools/ai-sdk.js.map +1 -0
- package/dist/source-9RQzlEhM.d.ts +112 -0
- package/dist/{src-DfLzdwlK.js → src-DoGNJ4Ud.js} +21 -6
- package/dist/src-DoGNJ4Ud.js.map +1 -0
- package/dist/sub-routing.d.ts +12 -12
- package/dist/tool-CTp72Jb_.d.ts +10 -10
- package/dist/tool-CxKsvxjm.js.map +1 -1
- package/dist/tool-DkT_DJBm.js.map +1 -1
- package/dist/tool-DoVberpN.d.ts +22 -22
- package/dist/tool-helpers-BI7ifO2S.js +255 -0
- package/dist/tool-helpers-BI7ifO2S.js.map +1 -0
- package/dist/{transport-CPh7YGiw.d.ts → transport-5moD2pW5.d.ts} +1 -43
- package/dist/types-D2naO3rA.d.ts +49 -0
- package/dist/vite.d.ts +2 -2
- package/dist/vite.js +10 -258
- package/dist/vite.js.map +1 -1
- package/dist/voice/index.d.ts +1 -1
- package/dist/websockets/index.js +1 -1
- package/dist/{websockets-CyoeosdO.js → websockets-C6SJtWCJ.js} +1 -2
- package/dist/{websockets-CyoeosdO.js.map → websockets-C6SJtWCJ.js.map} +1 -1
- package/dist/workflow-types.d.ts +1 -1
- package/dist/workflows.d.ts +1 -1
- package/dist/workflows.js +0 -1
- package/dist/workflows.js.map +1 -1
- package/docs/browse-the-web.md +247 -413
- package/docs/harnesses/pi.md +36 -30
- package/docs/index.md +4 -4
- package/docs/mcp-client.md +25 -1
- package/docs/mcp-servers.md +26 -7
- package/docs/models-pi-ai.md +9 -11
- package/docs/models.md +1 -8
- package/docs/observability.md +5 -3
- package/docs/securing-mcp-servers.md +113 -302
- package/package.json +31 -17
- package/dist/ai-sdk-DRPh2rRa.js.map +0 -1
- package/dist/browser-DccPw_wW.js.map +0 -1
- package/dist/browser-tool-B1mhifin.js +0 -616
- package/dist/browser-tool-B1mhifin.js.map +0 -1
- package/dist/browser-tool-Cxjk5sgG.d.ts +0 -92
- package/dist/client-BnYbNT3z.js.map +0 -1
- package/dist/cloudflare-Dzvc7V2N.js.map +0 -1
- package/dist/connector-DAXBOIIi.js.map +0 -1
- package/dist/handler-stateless-Bly_nSH3.js.map +0 -1
- package/dist/images-xaDv2Fqe.js.map +0 -1
- package/dist/index-iv9FTXX9.d.ts +0 -311
- package/dist/invoker-CG0_p_Wq.d.ts +0 -20
- package/dist/invoker-CHMnoxIA.js +0 -57
- package/dist/invoker-CHMnoxIA.js.map +0 -1
- package/dist/session-store-yvwq1f9x.js.map +0 -1
- package/dist/skills/compile.d.ts +0 -40
- package/dist/skills/compile.js +0 -65
- package/dist/skills/compile.js.map +0 -1
- package/dist/src-DfLzdwlK.js.map +0 -1
- package/dist/tool-helpers-O5BDVEAY.js +0 -58
- package/dist/tool-helpers-O5BDVEAY.js.map +0 -1
- package/skills-module.d.ts +0 -22
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websockets-CyoeosdO.js","names":["RpcTarget","RpcTarget"],"sources":["../src/websockets/connection-flags.ts","../src/websockets/connection.ts","../src/websockets/callables-target.ts","../src/websockets/transport.ts","../src/websockets/websockets.ts"],"sourcesContent":["import type { Connection } from \"../lifecycle\";\n\n/**\n * Internal per-connection flags, stored inside the connection's own state\n * under `_cf_`-prefixed keys so they ride the hibernation attachment (or a\n * bridged connection's synced state) and survive a wake. The state wrapper\n * installed by {@link ensureConnectionWrapped} hides them from\n * `connection.state` and preserves them across user `setState` calls.\n *\n * Owned by the WebSockets capability; `Agent` and framework mixins reach it\n * through the capability or, for their own keys, through\n * {@link registerInternalConnectionKeys}.\n */\n\n/** A readonly connection may not update host state. */\nexport const CF_READONLY_KEY = \"_cf_readonly\";\n\n/**\n * A no-protocol connection receives no protocol text frames (identity,\n * state sync, MCP servers) — neither on connect nor via broadcasts.\n */\nexport const CF_NO_PROTOCOL_KEY = \"_cf_no_protocol\";\n\nconst internalKeys = new Set<string>([CF_READONLY_KEY, CF_NO_PROTOCOL_KEY]);\n\n/**\n * Register additional `_cf_`-prefixed keys a host or mixin stores in\n * connection state, so they are hidden from `connection.state` and kept\n * across user `setState` calls like the capability's own flags.\n */\nexport function registerInternalConnectionKeys(...keys: string[]): void {\n for (const key of keys) internalKeys.add(key);\n}\n\nfunction rawHasInternalKeys(raw: Record<string, unknown>): boolean {\n for (const key of Object.keys(raw)) {\n if (internalKeys.has(key)) return true;\n }\n return false;\n}\n\n/** A copy of `raw` without internal keys, or null when no user keys remain. */\nfunction stripInternalKeys(\n raw: Record<string, unknown>\n): Record<string, unknown> | null {\n const result: Record<string, unknown> = {};\n let hasUserKeys = false;\n for (const key of Object.keys(raw)) {\n if (!internalKeys.has(key)) {\n result[key] = raw[key];\n hasUserKeys = true;\n }\n }\n return hasUserKeys ? result : null;\n}\n\n/** A copy containing only the internal keys present in `raw`. */\nfunction extractInternalFlags(\n raw: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(raw)) {\n if (internalKeys.has(key)) result[key] = raw[key];\n }\n return result;\n}\n\ntype RawAccessors = {\n getRaw: () => Record<string, unknown> | null;\n setRaw: (state: unknown) => unknown;\n};\n\n/**\n * Per-connection raw accessors, keyed by the live connection object. The\n * map is in-memory: after hibernation it is empty, and every entry point\n * re-wraps the connection on first use.\n */\nconst rawStateAccessors = new WeakMap<Connection, RawAccessors>();\n\n/**\n * Wrap `connection.state` / `connection.setState` so internal flags are\n * hidden from user code and preserved when user code sets state.\n * Idempotent, and safe to call after hibernation.\n */\nexport function ensureConnectionWrapped(connection: Connection): void {\n if (rawStateAccessors.has(connection)) return;\n\n // Hibernating connections expose attachment-backed state as a\n // configurable accessor. Virtual (bridged) connections use a data\n // property, so both projections are retained below.\n const descriptor = Object.getOwnPropertyDescriptor(connection, \"state\");\n\n let getRaw: RawAccessors[\"getRaw\"];\n let setRaw: RawAccessors[\"setRaw\"];\n\n if (descriptor?.get) {\n // Accessor property: bind the original getter. It reads the serialized\n // attachment, so it always returns the latest value after setState.\n getRaw = descriptor.get.bind(connection) as RawAccessors[\"getRaw\"];\n setRaw = connection.setState.bind(connection);\n } else {\n // Data property: track the raw value in a closure. Reading\n // `connection.state` after the override would hit the filtered getter.\n let rawState = (connection.state ?? null) as Record<string, unknown> | null;\n getRaw = () => rawState;\n setRaw = (state: unknown) => {\n rawState = state as Record<string, unknown> | null;\n return rawState;\n };\n }\n\n rawStateAccessors.set(connection, { getRaw, setRaw });\n\n Object.defineProperty(connection, \"state\", {\n configurable: true,\n enumerable: true,\n get() {\n const raw = getRaw();\n if (raw != null && typeof raw === \"object\" && rawHasInternalKeys(raw)) {\n return stripInternalKeys(raw);\n }\n return raw;\n }\n });\n\n Object.defineProperty(connection, \"setState\", {\n configurable: true,\n writable: true,\n value(stateOrFn: unknown | ((prev: unknown) => unknown)) {\n const raw = getRaw();\n const flags =\n raw != null && typeof raw === \"object\"\n ? extractInternalFlags(raw as Record<string, unknown>)\n : {};\n const hasFlags = Object.keys(flags).length > 0;\n\n let newUserState: unknown;\n if (typeof stateOrFn === \"function\") {\n // The callback sees only user-visible state.\n const userVisible = hasFlags\n ? stripInternalKeys(raw as Record<string, unknown>)\n : raw;\n newUserState = (stateOrFn as (prev: unknown) => unknown)(userVisible);\n } else {\n newUserState = stateOrFn;\n }\n\n if (hasFlags) {\n if (newUserState != null && typeof newUserState === \"object\") {\n return setRaw({\n ...(newUserState as Record<string, unknown>),\n ...flags\n });\n }\n // User set null: keep just the flags.\n return setRaw(flags);\n }\n return setRaw(newUserState);\n }\n });\n}\n\n/** The raw connection state, internal flags included. */\nexport function getConnectionRawState(\n connection: Connection\n): Record<string, unknown> | null {\n ensureConnectionWrapped(connection);\n return rawStateAccessors.get(connection)!.getRaw();\n}\n\n/** Read an internal flag from the raw connection state. */\nexport function getConnectionFlag(\n connection: Connection,\n key: string\n): unknown {\n ensureConnectionWrapped(connection);\n return rawStateAccessors.get(connection)!.getRaw()?.[key];\n}\n\n/**\n * Write an internal flag to the raw connection state. `undefined` removes\n * the key rather than storing a dead value; the last key removed leaves\n * `null`.\n */\nexport function setConnectionFlag(\n connection: Connection,\n key: string,\n value: unknown\n): void {\n ensureConnectionWrapped(connection);\n const accessors = rawStateAccessors.get(connection)!;\n const raw = accessors.getRaw() ?? {};\n if (value === undefined) {\n const { [key]: _, ...rest } = raw;\n accessors.setRaw(Object.keys(rest).length > 0 ? rest : null);\n } else {\n accessors.setRaw({ ...raw, [key]: value });\n }\n}\n\nexport function isConnectionReadonly(connection: Connection): boolean {\n return !!getConnectionFlag(connection, CF_READONLY_KEY);\n}\n\nexport function setConnectionReadonly(\n connection: Connection,\n readonly: boolean\n): void {\n setConnectionFlag(connection, CF_READONLY_KEY, readonly ? true : undefined);\n}\n\nexport function isConnectionProtocolEnabled(connection: Connection): boolean {\n return !getConnectionFlag(connection, CF_NO_PROTOCOL_KEY);\n}\n\nexport function setConnectionProtocolEnabled(\n connection: Connection,\n enabled: boolean\n): void {\n setConnectionFlag(connection, CF_NO_PROTOCOL_KEY, enabled ? undefined : true);\n}\n","// Polyfill WebSocket status code constants for environments that don't have them\n// in order to support libraries that expect standards-compatible WebSocket\n// implementations (e.g. PartySocket)\n\nimport type {\n Connection,\n ConnectionSetStateFn,\n ConnectionState,\n LifecycleSockets\n} from \"../lifecycle\";\n\nif (!(\"OPEN\" in WebSocket)) {\n const WebSocketStatus = {\n // @ts-expect-error\n CONNECTING: WebSocket.READY_STATE_CONNECTING,\n // @ts-expect-error\n OPEN: WebSocket.READY_STATE_OPEN,\n // @ts-expect-error\n CLOSING: WebSocket.READY_STATE_CLOSING,\n // @ts-expect-error\n CLOSED: WebSocket.READY_STATE_CLOSED\n };\n\n Object.assign(WebSocket, WebSocketStatus);\n // @ts-expect-error\n Object.assign(WebSocket.prototype, WebSocketStatus);\n}\n\n/**\n * Store both platform attachments and user attachments in different namespaces\n */\ntype ConnectionAttachments = {\n __pk: {\n id: string;\n tags: string[];\n uri?: string;\n };\n __user?: unknown;\n};\n\nfunction tryGetManagedWebSocketMeta(\n ws: WebSocket\n): ConnectionAttachments[\"__pk\"] | null {\n try {\n // Avoid AttachmentCache.get() here: externally accepted sockets\n // can have an attachment without the managed __pk namespace.\n const attachment = WebSocket.prototype.deserializeAttachment.call(\n ws\n ) as unknown;\n if (!attachment || typeof attachment !== \"object\") {\n return null;\n }\n if (!(\"__pk\" in attachment)) {\n return null;\n }\n const pk = (attachment as ConnectionAttachments).__pk as unknown;\n if (!pk || typeof pk !== \"object\") {\n return null;\n }\n const { id, tags } = pk as {\n id?: unknown;\n tags?: unknown;\n };\n if (typeof id !== \"string\") {\n return null;\n }\n const { uri } = pk as { uri?: unknown };\n return {\n id,\n tags: Array.isArray(tags) ? tags : [],\n uri: typeof uri === \"string\" ? uri : undefined\n } satisfies ConnectionAttachments[\"__pk\"];\n } catch {\n return null;\n }\n}\n\nexport function isManagedWebSocket(ws: WebSocket): boolean {\n return tryGetManagedWebSocketMeta(ws) !== null;\n}\n\n/**\n * Cache websocket attachments to avoid having to rehydrate them on every property access.\n */\nclass AttachmentCache {\n #cache = new WeakMap<WebSocket, ConnectionAttachments>();\n\n get(ws: WebSocket): ConnectionAttachments {\n let attachment = this.#cache.get(ws);\n if (!attachment) {\n attachment = WebSocket.prototype.deserializeAttachment.call(\n ws\n ) as ConnectionAttachments;\n if (attachment !== undefined) {\n this.#cache.set(ws, attachment);\n } else {\n throw new Error(\"Missing managed WebSocket lifecycle attachment\");\n }\n }\n\n return attachment;\n }\n\n set(ws: WebSocket, attachment: ConnectionAttachments) {\n this.#cache.set(ws, attachment);\n WebSocket.prototype.serializeAttachment.call(ws, attachment);\n }\n}\n\nconst attachments = new AttachmentCache();\nconst connections = new WeakSet<Connection>();\nconst isWrapped = (ws: WebSocket): ws is Connection => {\n return connections.has(ws as Connection);\n};\n\n/**\n * Wraps a WebSocket with Connection fields that rehydrate the\n * socket attachments lazily only when requested.\n */\nexport const createConnection = (ws: WebSocket | Connection): Connection => {\n if (isWrapped(ws)) {\n return ws;\n }\n\n // if state was set on the socket before initializing the connection,\n // capture it here so we can persist it again\n let initialState;\n if (\"state\" in ws) {\n initialState = ws.state;\n delete ws.state;\n }\n\n const connection = Object.defineProperties(ws, {\n id: {\n configurable: true,\n get() {\n return attachments.get(ws).__pk.id;\n }\n },\n uri: {\n configurable: true,\n get() {\n return attachments.get(ws).__pk.uri ?? null;\n }\n },\n tags: {\n configurable: true,\n get() {\n // Default to [] for connections accepted before tags were stored\n return attachments.get(ws).__pk.tags ?? [];\n }\n },\n state: {\n configurable: true,\n get() {\n const attachment = attachments.get(ws);\n return (attachment.__user ?? null) as ConnectionState<unknown>;\n }\n },\n setState: {\n configurable: true,\n value: function setState<T>(setState: T | ConnectionSetStateFn<T>) {\n const state =\n setState instanceof Function\n ? setState((this as Connection<T>).state)\n : setState;\n attachments.set(ws, {\n ...attachments.get(ws),\n __user: state ?? null\n });\n return state as ConnectionState<T>;\n }\n }\n }) as Connection;\n\n if (initialState) {\n connection.setState(initialState);\n }\n\n connections.add(connection);\n return connection;\n};\n\nclass ConnectionIterator<T> implements IterableIterator<Connection<T>> {\n private index = 0;\n #sockets: WebSocket[] | undefined;\n constructor(\n private sockets: LifecycleSockets,\n private tag?: string\n ) {}\n\n [Symbol.iterator](): IterableIterator<Connection<T>> {\n return this;\n }\n\n next(): IteratorResult<Connection<T>, number | undefined> {\n const sockets =\n this.#sockets ?? (this.#sockets = this.sockets.get(this.tag));\n\n let socket: WebSocket;\n while ((socket = sockets[this.index++])) {\n // Only yield open sockets.\n if (socket.readyState === WebSocket.OPEN) {\n // Durable Objects hibernation APIs allow storing arbitrary sockets via\n // `state.acceptWebSocket()`. Ignore sockets without our attachment.\n if (!isManagedWebSocket(socket)) {\n continue;\n }\n const value = createConnection(socket) as Connection<T>;\n return { done: false, value };\n }\n }\n\n // reached the end of the iteratee\n return { done: true, value: undefined };\n }\n}\n\n/**\n * Deduplicate and validate connection tags.\n * Returns the final tag array (always includes the connection id as the first tag).\n */\nexport function prepareTags(\n connectionId: string,\n userTags: string[]\n): string[] {\n const tags = [connectionId, ...userTags.filter((t) => t !== connectionId)];\n\n // validate tags against documented restrictions\n // https://developers.cloudflare.com/durable-objects/api/hibernatable-websockets-api/#state-methods-for-websockets\n if (tags.length > 10) {\n throw new Error(\n \"A connection can only have 10 tags, including the default id tag.\"\n );\n }\n\n for (const tag of tags) {\n if (typeof tag !== \"string\") {\n throw new Error(`A connection tag must be a string. Received: ${tag}`);\n }\n if (tag === \"\") {\n throw new Error(\"A connection tag must not be an empty string.\");\n }\n if (tag.length > 256) {\n throw new Error(\"A connection tag must not exceed 256 characters\");\n }\n }\n\n return tags;\n}\n\n/** The platform-backed manager for hibernating WebSockets. */\nexport class ConnectionManager<TState = unknown> {\n constructor(private controller: LifecycleSockets) {}\n\n getConnection<T = TState>(id: string) {\n // TODO: Should we cache the connections?\n const sockets = this.controller.get(id);\n const matching = sockets.filter((ws) => {\n return tryGetManagedWebSocketMeta(ws)?.id === id;\n });\n\n if (matching.length === 0) return undefined;\n if (matching.length === 1)\n return createConnection(matching[0]) as Connection<T>;\n\n throw new Error(\n `More than one connection found for id ${id}. Did you mean to use getConnections(tag) instead?`\n );\n }\n\n getConnections<T = TState>(tag?: string | undefined) {\n return new ConnectionIterator<T>(this.controller, tag);\n }\n\n accept(connection: Connection, options: { tags: string[] }) {\n const tags = prepareTags(connection.id, options.tags);\n\n this.controller.accept(connection, tags);\n attachments.set(connection, {\n __pk: {\n id: connection.id,\n tags,\n uri: connection.uri ?? undefined\n },\n __user: null\n });\n\n return createConnection(connection);\n }\n}\n","import { RpcTarget } from \"cloudflare:workers\";\nimport { CAPNWEB_TRANSPORT_SEND } from \"./transport-protocol\";\n\n/** A named remote method ready to be exposed on a callables root. */\nexport type CallableInvoker = (...args: unknown[]) => unknown;\n\n/**\n * The single exposure policy for callable names. `Object.prototype` and\n * `RpcTarget.prototype` members are unreachable over Cap'n Web anyway\n * and are silently excluded; `then` is rejected loudly because exposing\n * it would make the remote stub thenable.\n */\nfunction assertExposable(name: string): boolean {\n if (name === \"then\") {\n throw new Error(\n 'A callables target cannot expose a method named \"then\" — it would make the remote stub thenable'\n );\n }\n if (name === CAPNWEB_TRANSPORT_SEND) {\n throw new Error(\n `A callables target cannot expose \"${CAPNWEB_TRANSPORT_SEND}\"; it is the transport's frame pipe`\n );\n }\n return !(\n name === \"constructor\" ||\n name in Object.prototype ||\n name in RpcTarget.prototype\n );\n}\n\n/**\n * The exposable prototype methods of a callables target, each bound to\n * invoke on the real instance (so private fields and `this` behave).\n *\n * Cap'n Web resolves methods on the prototype chain and rejects own\n * instance properties, so only prototype methods participate. The\n * nearest declaration wins for overridden names.\n *\n * @param target - The callables target to enumerate.\n * @returns Method names mapped to invokers on the target.\n */\nexport function exposableMethods(\n target: RpcTarget\n): ReadonlyMap<string, CallableInvoker> {\n const methods = new Map<string, CallableInvoker>();\n const seen = new Set<string>();\n let prototype: object | null = Object.getPrototypeOf(target);\n while (\n prototype &&\n prototype !== RpcTarget.prototype &&\n prototype !== Object.prototype\n ) {\n for (const name of Object.getOwnPropertyNames(prototype)) {\n if (seen.has(name)) continue;\n seen.add(name);\n if (!assertExposable(name)) continue;\n const descriptor = Object.getOwnPropertyDescriptor(prototype, name);\n if (!descriptor || typeof descriptor.value !== \"function\") continue;\n // SAFETY: `typeof descriptor.value === \"function\"` was checked\n // above; TypeScript cannot narrow a descriptor's `value` field.\n const method = descriptor.value as CallableInvoker;\n methods.set(name, (...args) => Reflect.apply(method, target, args));\n }\n prototype = Object.getPrototypeOf(prototype);\n }\n return methods;\n}\n\n/**\n * Build a Cap'n Web session root exposing exactly the given methods.\n *\n * Cap'n Web resolves methods on the prototype chain, rejects own\n * instance properties, and breaks on Proxy-wrapped roots — so the root\n * is a private `RpcTarget` subclass whose prototype carries the methods\n * and nothing else.\n */\nexport function buildRoot(\n methods: ReadonlyMap<string, CallableInvoker>\n): RpcTarget {\n class Root extends RpcTarget {}\n for (const [name, invoke] of methods) {\n Object.defineProperty(Root.prototype, name, {\n value: invoke,\n writable: true,\n configurable: true,\n enumerable: false\n });\n }\n return new Root();\n}\n","import { newWebSocketRpcSession, type RpcStub } from \"capnweb\";\nimport type {\n Connection,\n ConnectionContext,\n ConnectionSetStateFn,\n ConnectionState\n} from \"../lifecycle\";\nimport { buildRoot, type CallableInvoker } from \"./callables-target\";\nimport { prepareTags } from \"./connection\";\nimport {\n CAPNWEB_TRANSPORT_SEND,\n type TransportClientEvents,\n type TransportMessage\n} from \"./transport-protocol\";\n\n/**\n * A non-hibernating connection with the public `Connection` contract,\n * backed by a Cap'n Web session instead of a hibernating socket. It lives\n * only in memory and disappears with the isolate.\n */\nclass CapnWebConnection extends EventTarget {\n readonly CONNECTING = WebSocket.CONNECTING;\n readonly OPEN = WebSocket.OPEN;\n readonly CLOSING = WebSocket.CLOSING;\n readonly CLOSED = WebSocket.CLOSED;\n readyState: number = WebSocket.OPEN;\n state: ConnectionState<unknown> = null;\n tags: readonly string[] = [];\n\n constructor(\n readonly id: string,\n readonly uri: string,\n private readonly pipe: {\n send(message: TransportMessage): void;\n close(code?: number, reason?: string): void;\n }\n ) {\n super();\n }\n\n send(message: TransportMessage): void {\n if (this.readyState !== WebSocket.OPEN) {\n throw new TypeError(\"WebSocket send() after close\");\n }\n this.pipe.send(message);\n }\n\n close(code?: number, reason?: string): void {\n if (this.readyState >= WebSocket.CLOSING) return;\n this.pipe.close(code, reason);\n this.readyState = WebSocket.CLOSING;\n }\n\n setState<T = unknown>(\n next: T | ConnectionSetStateFn<T> | null\n ): ConnectionState<T> {\n const state =\n typeof next === \"function\"\n ? (next as ConnectionSetStateFn<T>)(this.state as ConnectionState<T>)\n : next;\n this.state = state as ConnectionState<unknown>;\n return state as ConnectionState<T>;\n }\n}\n\n/** One live transport session. */\nexport type CapnWebSession = {\n readonly connection: Connection;\n /** Tear the session down; runs the close handler once. */\n dispose(): void;\n};\n\n/** What the capability supplies to run one session. */\nexport type CapnWebSessionOptions = {\n readonly request: Request;\n readonly connectionId: string;\n readonly tags: (\n connection: Connection,\n ctx: ConnectionContext\n ) => string[] | Promise<string[]>;\n readonly onConnect: (\n connection: Connection,\n ctx: ConnectionContext\n ) => Promise<void>;\n readonly onMessage: (\n connection: Connection,\n message: TransportMessage\n ) => Promise<void>;\n readonly onClose: (\n connection: Connection,\n code: number,\n reason: string,\n wasClean: boolean\n ) => Promise<void>;\n readonly onError: (connection: Connection, error: unknown) => Promise<void>;\n /**\n * Native methods served on the session root beside the frame pipe. Each\n * invoker already runs inside the host boundary for this connection.\n * Results pass by Cap'n Web semantics: an `RpcTarget` becomes a live\n * stub, a `ReadableStream` streams, and calls pipeline.\n */\n readonly callables: (\n connection: Connection\n ) => ReadonlyMap<string, CallableInvoker>;\n /**\n * Called once the connection exists, before `onConnect`, so it is already\n * visible in `getConnections()` while the connect handler runs — the same\n * ordering as a hibernating socket, which is accepted before `onConnect`.\n */\n readonly onOpen: (session: CapnWebSession) => void;\n /** Called exactly once when the session ends, before `onClose`. */\n readonly onDispose: (session: CapnWebSession) => void;\n};\n\n/**\n * Accept a Cap'n Web transport upgrade.\n *\n * The session root carries the frame pipe plus the host's native\n * callables. The client's protocol frames arrive through the pipe and are\n * handed to `onMessage`; the host's frames go out through the client's\n * `message` callback; `useAgent().stub` calls hit the callables directly.\n * The socket is a plain in-memory `WebSocketPair`, so it pins the Durable\n * Object and does not survive hibernation.\n */\nexport async function openCapnWebSession(\n options: CapnWebSessionOptions\n): Promise<{ response: Response; session: CapnWebSession }> {\n const { request, connectionId } = options;\n const pair = new WebSocketPair();\n const server = pair[0];\n server.accept();\n\n let client: RpcStub<TransportClientEvents> | undefined;\n let closed = false;\n let close = { code: 1000, reason: \"\", wasClean: true };\n\n const connection = new CapnWebConnection(connectionId, request.url, {\n send: (message) => {\n void client?.message(message).catch((error: unknown) => {\n if (!closed) console.error(\"Cap'n Web frame delivery failed:\", error);\n });\n },\n close: (code = 1000, reason = \"\") => {\n // Same contract as WebSocket.close(): a reserved code or an oversize\n // reason throws before anything changes, and the socket stays open\n // and tracked. Only a started handshake finishes the session.\n server.close(code, reason);\n close = { code, reason, wasClean: true };\n void finish();\n }\n }) as unknown as Connection & CapnWebConnection;\n\n const session: CapnWebSession = {\n connection,\n dispose: () => connection.close(1001, \"Session replaced\")\n };\n\n const finish = async () => {\n if (closed) return;\n closed = true;\n connection.readyState = WebSocket.CLOSED;\n try {\n client?.[Symbol.dispose]();\n } catch {\n // The session already ended with the socket.\n }\n options.onDispose(session);\n await options.onClose(connection, close.code, close.reason, close.wasClean);\n };\n\n const rootMethods = new Map<string, CallableInvoker>(\n options.callables(connection)\n );\n rootMethods.set(CAPNWEB_TRANSPORT_SEND, (message) =>\n options.onMessage(connection, message as TransportMessage)\n );\n client = newWebSocketRpcSession<TransportClientEvents>(\n server,\n buildRoot(rootMethods)\n );\n\n server.addEventListener(\n \"close\",\n (event) => {\n close = {\n code: event.code,\n reason: event.reason,\n wasClean: event.wasClean\n };\n void finish();\n },\n { once: true }\n );\n server.addEventListener(\n \"error\",\n (event) => {\n if (closed) return;\n close = { ...close, wasClean: false };\n const error =\n event instanceof ErrorEvent\n ? (event.error ?? new Error(event.message))\n : new Error(\"Cap'n Web transport socket error\");\n void options\n .onError(connection, error)\n .catch((handlerError: unknown) => {\n console.error(\"Cap'n Web onError handler failed:\", handlerError);\n })\n .finally(finish);\n },\n { once: true }\n );\n\n const ctx = { request };\n // Same limits as the hibernating wire (count, emptiness, length), so a\n // handler sees one tag policy whichever transport the client chose.\n connection.tags = prepareTags(\n connectionId,\n await options.tags(connection, ctx)\n );\n options.onOpen(session);\n try {\n await options.onConnect(connection, ctx);\n } catch (error) {\n connection.close(1011, \"onConnect failed\");\n throw error;\n }\n\n return {\n response: new Response(null, { status: 101, webSocket: pair[1] }),\n session\n };\n}\n","import { RpcTarget } from \"cloudflare:workers\";\nimport { nanoid } from \"nanoid\";\nimport {\n LifecycleCapability,\n type CapabilityWebSocketUpgradeContext,\n type Connection,\n type ConnectionContext,\n type ConnectionSetStateFn,\n type ConnectionState\n} from \"../lifecycle\";\nimport { MessageType } from \"../types\";\nimport { camelCaseToKebabCase } from \"../utils\";\nimport {\n ConnectionManager,\n createConnection,\n isManagedWebSocket\n} from \"./connection\";\nimport {\n ensureConnectionWrapped,\n isConnectionProtocolEnabled,\n isConnectionReadonly,\n setConnectionProtocolEnabled,\n setConnectionReadonly\n} from \"./connection-flags\";\nimport { exposableMethods, type CallableInvoker } from \"./callables-target\";\nimport type {\n SyncedState,\n WebSocketHandlers,\n WebSocketMessage,\n WebSocketsOptions\n} from \"./options\";\nimport { openCapnWebSession, type CapnWebSession } from \"./transport\";\nimport { isCapnWebTransportUpgrade } from \"./transport-protocol\";\n\n/**\n * Reserved close codes the runtime synthesizes when there was no real\n * Close frame from the peer (1005 NoStatusReceived, 1006 AbnormalClosure,\n * 1015 TLSHandshake). They cannot appear in an outgoing Close frame, and\n * there is no peer left to receive a reciprocation.\n */\nfunction isReservedCloseCode(code: number): boolean {\n return code === 1005 || code === 1006 || code === 1015;\n}\n\n/**\n * Reciprocate a peer-initiated Close frame to complete the handshake, as\n * the Hibernation API contract requires. Best-effort: swallows errors\n * from already-closed sockets or invalid codes/reasons, and skips\n * reciprocation entirely for reserved codes (dead transport).\n */\nfunction reciprocateClose(ws: WebSocket, code: number, reason: string): void {\n if (isReservedCloseCode(code)) return;\n try {\n ws.close(code, reason);\n } catch {\n // Already closed, oversize reason, or another unrecoverable\n // invariant — the handshake is either done or out of our control.\n }\n}\n\n/** The `rpc` request frame `useAgent().call` and `AgentClient.call` send. */\ntype RpcRequest = {\n readonly type: \"rpc\";\n readonly id: string;\n readonly method: string;\n readonly args: unknown[];\n};\n\ntype RpcResponse =\n | { type: \"rpc\"; id: string; success: true; done: boolean; result: unknown }\n | { type: \"rpc\"; id: string; success: false; error: string };\n\n/** The `cf_agent_state` frame a client sends to update host state. */\ntype StateFrame = { readonly type: \"cf_agent_state\"; readonly state: unknown };\n\nfunction isStateFrame(value: unknown): value is StateFrame {\n if (typeof value !== \"object\" || value === null) return false;\n const frame = value as Record<string, unknown>;\n return frame.type === MessageType.CF_AGENT_STATE && \"state\" in frame;\n}\n\n/** Parse a text frame; anything that is not JSON is `undefined`. */\nfunction parseJson(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\n\nfunction isRpcRequest(value: unknown): value is RpcRequest {\n if (typeof value !== \"object\" || value === null) return false;\n const frame = value as Record<string, unknown>;\n return (\n frame.type === MessageType.RPC &&\n typeof frame.id === \"string\" &&\n typeof frame.method === \"string\" &&\n Array.isArray(frame.args)\n );\n}\n\n/**\n * Opt-in WebSocket support for Lifecycle Objects.\n *\n * Lifecycle itself does not model WebSockets — hosts that want them\n * install this capability, which owns the connection subsystem end to\n * end: it claims upgrades, dispatches `onConnect`/`onMessage`/`onClose`\n * inside the host invocation boundary, reciprocates close handshakes,\n * and answers `getConnections()`/`getConnection()`.\n *\n * ```ts\n * class Room extends DurableObject<Env> {\n * readonly webSockets = new WebSockets({\n * handlers: {\n * onConnect: (connection) => connection.send(\"welcome\"),\n * onMessage: (connection, message) => { ... }\n * },\n * callables: new RoomCallables()\n * });\n * readonly lifecycle = Lifecycle.install(this).use(this.webSockets);\n * }\n * ```\n *\n * Connections arrive on one of two wires, chosen by the client:\n *\n * - **cf-websocket** (default): accepted with the Hibernation API. Idle\n * clients stay connected while the Durable Object leaves memory.\n * - **capnweb** (`?__agents_transport=capnweb`): protocol frames through\n * one pipe method on a Cap'n Web session whose root also carries the\n * host's callables natively. Non-hibernating — the object stays pinned\n * while the connection is open.\n *\n * Both wires dispatch the same handlers and appear in `getConnections()`.\n * On both, the capability speaks the Agent protocol a plain host needs\n * for `useAgent` and `AgentClient`: it sends the identity frame on\n * connect, and it serves `callables` — as `rpc` JSON frames on the\n * WebSocket wire, and natively on the Cap'n Web session root, where an\n * `RpcTarget` result becomes a live stub and calls pipeline. `call()`\n * and `stub` work against a plain Durable Object exactly as against an\n * `Agent`. Pass a `State` capability as `state` and the hook's\n * `state`/`setState` work too: the current value is pushed on connect\n * and client updates are validated and applied; the state owner\n * broadcasts changes with `broadcastState()`. Per-connection readonly\n * and no-protocol flags live here as well, for every host.\n */\nexport class WebSockets extends LifecycleCapability {\n /** Claims every upgrade, so Lifecycle dispatches it after all others. */\n override readonly claims = \"catch-all\";\n\n readonly #handlers: WebSocketHandlers | undefined;\n /** Handlers added with `use`, run before the configured ones. */\n readonly #added: WebSocketHandlers[] = [];\n readonly #getConnectionTags: WebSocketsOptions[\"getConnectionTags\"];\n readonly #protocol: WebSocketsOptions[\"protocol\"];\n readonly #readonly: WebSocketsOptions[\"readonly\"];\n readonly #state: SyncedState | undefined;\n /**\n * Connections inside their connect sequence, before the state push.\n * `broadcastState()` skips them: reading state for the push can seed the\n * initial value, whose change broadcast would otherwise reach a\n * connection that is about to receive the same value directly.\n */\n readonly #connecting = new Set<Connection>();\n readonly #callables: ReadonlyMap<string, CallableInvoker>;\n readonly #sessions = new Map<string, CapnWebSession>();\n #manager: ConnectionManager | undefined;\n\n constructor(options: WebSocketsOptions = {}) {\n super(\"websockets\");\n this.#handlers = options.handlers;\n this.#getConnectionTags = options.getConnectionTags;\n this.#protocol = options.protocol ?? true;\n this.#readonly = options.readonly;\n this.#state = options.state;\n this.#callables = options.callables\n ? exposableMethods(options.callables)\n : new Map();\n }\n\n // ── Lifecycle capability hooks ─────────────────────────────────────────\n\n /**\n * Claim every upgrade, never declining: a Cap'n Web transport upgrade\n * becomes a session, everything else a tracked hibernating connection,\n * whether or not handlers or callables are configured. Handlers only add\n * behavior on connect, message, close, and error.\n */\n onWebSocketUpgrade({\n request\n }: CapabilityWebSocketUpgradeContext): Promise<Response> {\n return isCapnWebTransportUpgrade(request)\n ? this.#acceptCapnWebSession(request)\n : this.#acceptConnection(request);\n }\n\n /** Dispatch a platform message wake for a capability-owned socket. */\n async onWebSocketMessage(\n ws: WebSocket,\n message: WebSocketMessage\n ): Promise<boolean> {\n if (!isManagedWebSocket(ws)) return false;\n await this.#message(createConnection(ws), message);\n return true;\n }\n\n /** Dispatch and reciprocate a close wake for an owned socket. */\n async onWebSocketClose(\n ws: WebSocket,\n code: number,\n reason: string,\n wasClean: boolean\n ): Promise<boolean> {\n if (!isManagedWebSocket(ws)) return false;\n try {\n await this.#close(createConnection(ws), code, reason, wasClean);\n } finally {\n reciprocateClose(ws, code, reason);\n }\n return true;\n }\n\n /** Dispatch an error wake for an owned socket. */\n async onWebSocketError(ws: WebSocket, error: unknown): Promise<boolean> {\n if (!isManagedWebSocket(ws)) return false;\n await this.#error(createConnection(ws), error);\n return true;\n }\n\n /**\n * Close every owned connection during explicit host destruction. The\n * capability owns its sockets' lifetimes, so it also owns tearing\n * them down.\n */\n dispose(): void {\n for (const connection of this.getConnections()) {\n try {\n connection.close(1001, \"Durable Object destroyed\");\n } catch {\n // Already closed or mid-handshake — nothing left to tear down.\n }\n }\n }\n\n /**\n * Add handlers for another component sharing these connections, such as\n * a protocol of its own. They run before the configured handlers, and\n * their `onMessage` can claim a message by returning true.\n */\n use(handlers: WebSocketHandlers): void {\n this.#added.push(handlers);\n }\n\n // ── Connections ────────────────────────────────────────────────────────\n\n /** Open connections on either wire, optionally by tag. */\n *getConnections<TState = unknown>(\n tag?: string\n ): IterableIterator<Connection<TState>> {\n for (const { connection } of this.#sessions.values()) {\n if (connection.readyState !== WebSocket.OPEN) continue;\n if (!tag || connection.tags.includes(tag)) {\n yield connection as Connection<TState>;\n }\n }\n yield* this.#connectionManager.getConnections<TState>(tag);\n }\n\n /** One connection on either wire, by id. */\n getConnection<TState = unknown>(id: string): Connection<TState> | undefined {\n const session = this.#sessions.get(id)?.connection;\n if (session && session.readyState === WebSocket.OPEN) {\n return session as Connection<TState>;\n }\n return this.#connectionManager.getConnection<TState>(id);\n }\n\n get #connectionManager(): ConnectionManager {\n this.#manager ??= new ConnectionManager(this.lifecycle.sockets);\n return this.#manager;\n }\n\n // ── Wire-independent protocol ──────────────────────────────────────────\n\n async #connect(\n connection: Connection,\n ctx: ConnectionContext\n ): Promise<void> {\n ensureConnectionWrapped(connection);\n // Flags first, so they are set before the client can respond.\n if (this.#readonly?.(connection, ctx)) {\n setConnectionReadonly(connection, true);\n }\n if (this.#protocol !== false) {\n const enabled =\n typeof this.#protocol === \"function\"\n ? this.#protocol(connection, ctx)\n : true;\n if (enabled) {\n this.sendConnectFrames(connection);\n } else {\n setConnectionProtocolEnabled(connection, false);\n }\n }\n for (const handlers of [...this.#added, this.#handlers]) {\n await this.lifecycle.runInHostContext(\n () => handlers?.onConnect?.(connection, ctx),\n { connection, request: ctx.request }\n );\n }\n }\n\n async #message(\n connection: Connection,\n message: WebSocketMessage\n ): Promise<void> {\n if (\n this.#state &&\n this.#protocol !== false &&\n typeof message === \"string\"\n ) {\n const frame = parseJson(message);\n if (isStateFrame(frame)) {\n // Inside the host boundary, so the host's validator and change\n // hook see the sending connection through the ambient context.\n await this.lifecycle.runInHostContext(\n () => this.applyStateFrame(connection, frame),\n { connection }\n );\n return;\n }\n }\n if (\n this.#callables.size > 0 &&\n (await this.#answerRpc(connection, message))\n ) {\n return;\n }\n for (const handlers of this.#added) {\n const claimed = await this.lifecycle.runInHostContext(\n () => handlers.onMessage?.(connection, message),\n { connection }\n );\n if (claimed === true) return;\n }\n await this.lifecycle.runInHostContext(\n () => this.#handlers?.onMessage?.(connection, message),\n { connection }\n );\n }\n\n #close(\n connection: Connection,\n code: number,\n reason: string,\n wasClean: boolean\n ): Promise<unknown> {\n return this.#each((handlers) =>\n this.lifecycle.runInHostContext(\n () => handlers?.onClose?.(connection, code, reason, wasClean),\n { connection }\n )\n );\n }\n\n #error(connection: Connection, error: unknown): Promise<unknown> {\n return this.#each((handlers) =>\n this.lifecycle.runInHostContext(\n () => handlers?.onError?.(connection, error),\n { connection }\n )\n );\n }\n\n async #each(\n run: (handlers: WebSocketHandlers | undefined) => Promise<unknown>\n ): Promise<void> {\n for (const handlers of [...this.#added, this.#handlers])\n await run(handlers);\n }\n\n // ── Hibernating wire ───────────────────────────────────────────────────\n\n async #acceptConnection(request: Request): Promise<Response> {\n const { 0: clientWebSocket, 1: serverWebSocket } = new WebSocketPair();\n const url = new URL(request.url);\n // `||`, not `??`: an empty `?_pk=` value must fall back to a\n // generated id — an empty connection id would later throw in tag\n // validation and reject the upgrade.\n const connectionId = url.searchParams.get(\"_pk\") || nanoid();\n\n let connection: Connection = Object.assign(serverWebSocket, {\n id: connectionId,\n uri: request.url,\n tags: [] as string[],\n state: null as unknown as ConnectionState<unknown>,\n setState<T = unknown>(setState: T | ConnectionSetStateFn<T>) {\n // Pre-accept shim: hold state on the socket until accept()\n // persists it into the hibernation attachment.\n const state =\n setState instanceof Function\n ? setState(this.state as ConnectionState<T>)\n : setState;\n this.state = state as ConnectionState<T>;\n return this.state as ConnectionState<T>;\n }\n });\n\n const ctx = { request };\n const tags = this.#getConnectionTags\n ? await this.#getConnectionTags(connection, ctx)\n : [];\n\n // Hibernating WebSockets remain connected while the object is evicted.\n connection = this.#connectionManager.accept(connection, { tags });\n await this.#connect(connection, ctx);\n\n return new Response(null, { status: 101, webSocket: clientWebSocket });\n }\n\n // ── Cap'n Web wire ─────────────────────────────────────────────────────\n\n async #acceptCapnWebSession(request: Request): Promise<Response> {\n const connectionId =\n new URL(request.url).searchParams.get(\"_pk\") || nanoid();\n // A reconnect reusing the id replaces the previous session.\n this.#sessions.get(connectionId)?.dispose();\n\n const { response } = await openCapnWebSession({\n request,\n connectionId,\n tags: (connection, ctx) =>\n this.#getConnectionTags?.(connection, ctx) ?? [],\n onConnect: (connection, ctx) => this.#connect(connection, ctx),\n onMessage: (connection, message) => this.#message(connection, message),\n onClose: (connection, code, reason, wasClean) =>\n this.#close(connection, code, reason, wasClean).then(() => undefined),\n onError: (connection, error) =>\n this.#error(connection, error).then(() => undefined),\n callables: (connection) => this.#nativeCallables(connection),\n onOpen: (session) => this.#sessions.set(connectionId, session),\n onDispose: (ended) => {\n if (this.#sessions.get(connectionId) === ended) {\n this.#sessions.delete(connectionId);\n }\n }\n });\n return response;\n }\n\n // ── Protocol frames ────────────────────────────────────────────────────\n //\n // The Agent protocol a client (`useAgent`, `AgentClient`) speaks, owned\n // here for every host. With `protocol: true` the capability drives the\n // connect sequence and consumes state frames itself; with\n // `protocol: false` the host calls these at the moments it chooses.\n\n /**\n * Send the connect sequence: the identity frame, then the current state\n * when one is stored. The identity carries `stateFollows` in that case,\n * so clients resolve `ready` only once the state has landed. Nothing is\n * sent to a no-protocol connection. Identity defaults as for\n * `sendIdentity()`.\n */\n sendConnectFrames(\n connection: Connection,\n identity: { name: string; agent: string } = this.#defaultIdentity()\n ): void {\n if (!isConnectionProtocolEnabled(connection)) return;\n this.#connecting.add(connection);\n try {\n const current = this.#state?.get();\n // Serialized first: a flagged identity must never go out without\n // the state frame the client will wait for.\n const stateFrame =\n current === undefined\n ? undefined\n : JSON.stringify({\n type: MessageType.CF_AGENT_STATE,\n state: current\n });\n this.#sendFrame(connection, {\n type: MessageType.CF_AGENT_IDENTITY,\n name: identity.name,\n agent: identity.agent,\n ...(stateFrame !== undefined && { stateFollows: true })\n });\n if (stateFrame !== undefined) this.#send(connection, stateFrame);\n } finally {\n this.#connecting.delete(connection);\n }\n }\n\n /**\n * Send the identity frame alone, unless the connection is no-protocol.\n * Clients resolve `ready` on it, so a host that also pushes state on\n * connect should use `sendConnectFrames()`. The defaults are the Durable\n * Object's routed name and host class; a host whose public identity\n * differs — an `Agent` facet, whose routed name is an internal encoding\n * of its logical name — passes its own.\n */\n sendIdentity(\n connection: Connection,\n identity: { name: string; agent: string } = this.#defaultIdentity()\n ): void {\n if (!isConnectionProtocolEnabled(connection)) return;\n this.#sendFrame(connection, {\n type: MessageType.CF_AGENT_IDENTITY,\n name: identity.name,\n agent: identity.agent\n });\n }\n\n #defaultIdentity(): { name: string; agent: string } {\n return {\n name: this.lifecycle.name,\n agent: camelCaseToKebabCase(this.lifecycle.className)\n };\n }\n\n /**\n * Send the current state to one connection, unless nothing is stored\n * or the connection is no-protocol. Reading the state may seed the\n * initial value; see `#connecting`.\n */\n sendState(connection: Connection): void {\n if (!this.#state || !isConnectionProtocolEnabled(connection)) return;\n const current = this.#state.get();\n if (current === undefined) return;\n this.#sendFrame(connection, {\n type: MessageType.CF_AGENT_STATE,\n state: current\n });\n }\n\n /**\n * Apply a parsed `cf_agent_state` frame from a client. A readonly\n * connection is refused; a change the host's validator rejects is\n * logged in full server-side and answered with a generic\n * `cf_agent_state_error`. Broadcasting the accepted change is the state\n * owner's call, through its `onChanged` hook. Callers that drive the\n * protocol themselves call this inside their own invocation context;\n * the capability's automatic path does so via `runInHostContext`.\n *\n * @returns Whether the frame was a state frame (handled either way).\n */\n applyStateFrame(connection: Connection, frame: unknown): boolean {\n if (!this.#state || !isStateFrame(frame)) return false;\n if (isConnectionReadonly(connection)) {\n this.#sendFrame(connection, {\n type: MessageType.CF_AGENT_STATE_ERROR,\n error: \"Connection is readonly\"\n });\n return true;\n }\n try {\n // `never` on the port keeps any `State<T>` assignable; the value\n // came off the wire, so the host's validator is what checks it.\n this.#state.set(frame.state as never, connection);\n } catch (error) {\n console.error(\"[WebSockets] State update rejected:\", error);\n this.#sendFrame(connection, {\n type: MessageType.CF_AGENT_STATE_ERROR,\n error: \"State update rejected\"\n });\n }\n return true;\n }\n\n /**\n * Push the current state to every protocol-enabled connection except\n * the one a change came from, which already has the value it sent.\n * Wire a `State`'s `onChanged` to this.\n */\n broadcastState(except?: Connection | \"server\"): void {\n if (!this.#state) return;\n const current = this.#state.get();\n if (current === undefined) return;\n const frame = { type: MessageType.CF_AGENT_STATE, state: current };\n for (const connection of this.getConnections()) {\n // Object identity, not id: `_pk` is client-supplied, so two live\n // sockets can share an id, and excluding by id would starve the\n // other one. `createConnection` returns one wrapper per socket.\n if (connection === except) continue;\n if (this.#connecting.has(connection)) continue;\n if (!isConnectionProtocolEnabled(connection)) continue;\n this.#sendFrame(connection, frame);\n }\n }\n\n // ── Connection flags ───────────────────────────────────────────────────\n\n /** Whether the connection may update host state over the wire. */\n isReadonly(connection: Connection): boolean {\n return isConnectionReadonly(connection);\n }\n\n /** Mark a connection readonly, or writable again. */\n setReadonly(connection: Connection, readonly = true): void {\n setConnectionReadonly(connection, readonly);\n }\n\n /** Whether protocol text frames reach the connection. */\n isProtocolEnabled(connection: Connection): boolean {\n return isConnectionProtocolEnabled(connection);\n }\n\n /** Enable or suppress protocol text frames for a connection. */\n setProtocolEnabled(connection: Connection, enabled: boolean): void {\n setConnectionProtocolEnabled(connection, enabled);\n }\n\n /**\n * Send one protocol frame. Serialization is the caller's contract — every\n * frame built here is plain JSON — while a send failure is tolerated: the\n * peer may have disconnected between the wake and the send.\n */\n #sendFrame(connection: Connection, frame: Record<string, unknown>): void {\n this.#send(connection, JSON.stringify(frame));\n }\n\n /** Write one already-serialized frame, tolerating a closed peer. */\n #send(connection: Connection, text: string): void {\n try {\n connection.send(text);\n } catch {\n // The socket closed between the wake and the send.\n }\n }\n\n // ── Callables ──────────────────────────────────────────────────────────\n\n /**\n * The `callables` target as native Cap'n Web methods for one session:\n * every method dispatches through the host boundary with this\n * connection in scope and emits `rpc`/`rpc:error` events. Return values\n * keep Cap'n Web semantics — an `RpcTarget` comes back as a live stub.\n */\n #nativeCallables(\n connection: Connection\n ): ReadonlyMap<string, CallableInvoker> {\n const methods = new Map<string, CallableInvoker>();\n for (const [name, invoke] of this.#callables) {\n methods.set(name, (...args) =>\n this.#dispatchCallable(name, () => invoke(...args), connection)\n );\n }\n return methods;\n }\n\n /**\n * Answer one `rpc` frame against `callables`. A `ReadableStream`\n * result streams as `done: false` chunks followed by a final\n * `done: true` frame, matching the client's stream callbacks.\n *\n * @returns Whether the message was an `rpc` frame (answered or not).\n */\n async #answerRpc(\n connection: Connection,\n raw: WebSocketMessage\n ): Promise<boolean> {\n if (typeof raw !== \"string\") return false;\n let frame: unknown;\n try {\n frame = JSON.parse(raw);\n } catch {\n return false;\n }\n if (!isRpcRequest(frame)) return false;\n const { id, method, args } = frame;\n\n const invoke = this.#callables.get(method);\n if (!invoke) {\n this.#reply(connection, {\n type: \"rpc\",\n id,\n success: false,\n error: `Method ${method} does not exist`\n });\n return true;\n }\n\n try {\n const result = await this.#dispatchCallable(\n method,\n () => invoke(...args),\n connection\n );\n if (result instanceof RpcTarget) {\n // By-reference results only exist on the Cap'n Web wire; a JSON\n // frame would silently flatten the target to `{}`.\n throw new Error(\n `Method ${method} returns an RpcTarget, which only the capnweb transport can carry`\n );\n }\n if (result instanceof ReadableStream) {\n for await (const chunk of result) {\n this.#reply(connection, {\n type: \"rpc\",\n id,\n success: true,\n done: false,\n result: chunk\n });\n }\n this.#reply(connection, {\n type: \"rpc\",\n id,\n success: true,\n done: true,\n result: undefined\n });\n } else {\n this.#reply(connection, {\n type: \"rpc\",\n id,\n success: true,\n done: true,\n result\n });\n }\n } catch (error) {\n this.#reply(connection, {\n type: \"rpc\",\n id,\n success: false,\n error: error instanceof Error ? error.message : String(error)\n });\n }\n return true;\n }\n\n #reply(connection: Connection, response: RpcResponse): void {\n let text: string;\n try {\n text = JSON.stringify(response);\n } catch (error) {\n // A result that JSON cannot carry (a BigInt, a cycle) must still\n // settle the caller: answer with an error instead of silence.\n text = JSON.stringify({\n type: \"rpc\",\n id: response.id,\n success: false,\n error: `Result is not JSON-serializable: ${\n error instanceof Error ? error.message : String(error)\n }`\n } satisfies RpcResponse);\n }\n this.#send(connection, text);\n }\n\n async #dispatchCallable(\n name: string,\n invoke: () => unknown,\n connection: Connection\n ): Promise<unknown> {\n // Throws with installation guidance when the capability was never\n // installed with Lifecycle.use().\n const services = this.lifecycle;\n try {\n const result = await services.runInHostContext(invoke, { connection });\n services.events.emit(\"rpc\", {\n method: name,\n streaming: result instanceof ReadableStream\n });\n return result;\n } catch (error) {\n services.events.emit(\"rpc:error\", {\n method: name,\n error: error instanceof Error ? error.message : String(error)\n });\n throw error;\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"websockets-C6SJtWCJ.js","names":["RpcTarget","RpcTarget"],"sources":["../src/websockets/connection-flags.ts","../src/websockets/connection.ts","../src/websockets/callables-target.ts","../src/websockets/transport.ts","../src/websockets/websockets.ts"],"sourcesContent":["import type { Connection } from \"../lifecycle\";\n\n/**\n * Internal per-connection flags, stored inside the connection's own state\n * under `_cf_`-prefixed keys so they ride the hibernation attachment (or a\n * bridged connection's synced state) and survive a wake. The state wrapper\n * installed by {@link ensureConnectionWrapped} hides them from\n * `connection.state` and preserves them across user `setState` calls.\n *\n * Owned by the WebSockets capability; `Agent` and framework mixins reach it\n * through the capability or, for their own keys, through\n * {@link registerInternalConnectionKeys}.\n */\n\n/** A readonly connection may not update host state. */\nexport const CF_READONLY_KEY = \"_cf_readonly\";\n\n/**\n * A no-protocol connection receives no protocol text frames (identity,\n * state sync, MCP servers) — neither on connect nor via broadcasts.\n */\nexport const CF_NO_PROTOCOL_KEY = \"_cf_no_protocol\";\n\nconst internalKeys = new Set<string>([CF_READONLY_KEY, CF_NO_PROTOCOL_KEY]);\n\n/**\n * Register additional `_cf_`-prefixed keys a host or mixin stores in\n * connection state, so they are hidden from `connection.state` and kept\n * across user `setState` calls like the capability's own flags.\n */\nexport function registerInternalConnectionKeys(...keys: string[]): void {\n for (const key of keys) internalKeys.add(key);\n}\n\nfunction rawHasInternalKeys(raw: Record<string, unknown>): boolean {\n for (const key of Object.keys(raw)) {\n if (internalKeys.has(key)) return true;\n }\n return false;\n}\n\n/** A copy of `raw` without internal keys, or null when no user keys remain. */\nfunction stripInternalKeys(\n raw: Record<string, unknown>\n): Record<string, unknown> | null {\n const result: Record<string, unknown> = {};\n let hasUserKeys = false;\n for (const key of Object.keys(raw)) {\n if (!internalKeys.has(key)) {\n result[key] = raw[key];\n hasUserKeys = true;\n }\n }\n return hasUserKeys ? result : null;\n}\n\n/** A copy containing only the internal keys present in `raw`. */\nfunction extractInternalFlags(\n raw: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(raw)) {\n if (internalKeys.has(key)) result[key] = raw[key];\n }\n return result;\n}\n\ntype RawAccessors = {\n getRaw: () => Record<string, unknown> | null;\n setRaw: (state: unknown) => unknown;\n};\n\n/**\n * Per-connection raw accessors, keyed by the live connection object. The\n * map is in-memory: after hibernation it is empty, and every entry point\n * re-wraps the connection on first use.\n */\nconst rawStateAccessors = new WeakMap<Connection, RawAccessors>();\n\n/**\n * Wrap `connection.state` / `connection.setState` so internal flags are\n * hidden from user code and preserved when user code sets state.\n * Idempotent, and safe to call after hibernation.\n */\nexport function ensureConnectionWrapped(connection: Connection): void {\n if (rawStateAccessors.has(connection)) return;\n\n // Hibernating connections expose attachment-backed state as a\n // configurable accessor. Virtual (bridged) connections use a data\n // property, so both projections are retained below.\n const descriptor = Object.getOwnPropertyDescriptor(connection, \"state\");\n\n let getRaw: RawAccessors[\"getRaw\"];\n let setRaw: RawAccessors[\"setRaw\"];\n\n if (descriptor?.get) {\n // Accessor property: bind the original getter. It reads the serialized\n // attachment, so it always returns the latest value after setState.\n getRaw = descriptor.get.bind(connection) as RawAccessors[\"getRaw\"];\n setRaw = connection.setState.bind(connection);\n } else {\n // Data property: track the raw value in a closure. Reading\n // `connection.state` after the override would hit the filtered getter.\n let rawState = (connection.state ?? null) as Record<string, unknown> | null;\n getRaw = () => rawState;\n setRaw = (state: unknown) => {\n rawState = state as Record<string, unknown> | null;\n return rawState;\n };\n }\n\n rawStateAccessors.set(connection, { getRaw, setRaw });\n\n Object.defineProperty(connection, \"state\", {\n configurable: true,\n enumerable: true,\n get() {\n const raw = getRaw();\n if (raw != null && typeof raw === \"object\" && rawHasInternalKeys(raw)) {\n return stripInternalKeys(raw);\n }\n return raw;\n }\n });\n\n Object.defineProperty(connection, \"setState\", {\n configurable: true,\n writable: true,\n value(stateOrFn: unknown | ((prev: unknown) => unknown)) {\n const raw = getRaw();\n const flags =\n raw != null && typeof raw === \"object\"\n ? extractInternalFlags(raw as Record<string, unknown>)\n : {};\n const hasFlags = Object.keys(flags).length > 0;\n\n let newUserState: unknown;\n if (typeof stateOrFn === \"function\") {\n // The callback sees only user-visible state.\n const userVisible = hasFlags\n ? stripInternalKeys(raw as Record<string, unknown>)\n : raw;\n newUserState = (stateOrFn as (prev: unknown) => unknown)(userVisible);\n } else {\n newUserState = stateOrFn;\n }\n\n if (hasFlags) {\n if (newUserState != null && typeof newUserState === \"object\") {\n return setRaw({\n ...(newUserState as Record<string, unknown>),\n ...flags\n });\n }\n // User set null: keep just the flags.\n return setRaw(flags);\n }\n return setRaw(newUserState);\n }\n });\n}\n\n/** The raw connection state, internal flags included. */\nexport function getConnectionRawState(\n connection: Connection\n): Record<string, unknown> | null {\n ensureConnectionWrapped(connection);\n return rawStateAccessors.get(connection)!.getRaw();\n}\n\n/** Read an internal flag from the raw connection state. */\nexport function getConnectionFlag(\n connection: Connection,\n key: string\n): unknown {\n ensureConnectionWrapped(connection);\n return rawStateAccessors.get(connection)!.getRaw()?.[key];\n}\n\n/**\n * Write an internal flag to the raw connection state. `undefined` removes\n * the key rather than storing a dead value; the last key removed leaves\n * `null`.\n */\nexport function setConnectionFlag(\n connection: Connection,\n key: string,\n value: unknown\n): void {\n ensureConnectionWrapped(connection);\n const accessors = rawStateAccessors.get(connection)!;\n const raw = accessors.getRaw() ?? {};\n if (value === undefined) {\n const { [key]: _, ...rest } = raw;\n accessors.setRaw(Object.keys(rest).length > 0 ? rest : null);\n } else {\n accessors.setRaw({ ...raw, [key]: value });\n }\n}\n\nexport function isConnectionReadonly(connection: Connection): boolean {\n return !!getConnectionFlag(connection, CF_READONLY_KEY);\n}\n\nexport function setConnectionReadonly(\n connection: Connection,\n readonly: boolean\n): void {\n setConnectionFlag(connection, CF_READONLY_KEY, readonly ? true : undefined);\n}\n\nexport function isConnectionProtocolEnabled(connection: Connection): boolean {\n return !getConnectionFlag(connection, CF_NO_PROTOCOL_KEY);\n}\n\nexport function setConnectionProtocolEnabled(\n connection: Connection,\n enabled: boolean\n): void {\n setConnectionFlag(connection, CF_NO_PROTOCOL_KEY, enabled ? undefined : true);\n}\n","// Polyfill WebSocket status code constants for environments that don't have them\n// in order to support libraries that expect standards-compatible WebSocket\n// implementations (e.g. PartySocket)\n\nimport type {\n Connection,\n ConnectionSetStateFn,\n ConnectionState,\n LifecycleSockets\n} from \"../lifecycle\";\n\nif (!(\"OPEN\" in WebSocket)) {\n const WebSocketStatus = {\n // @ts-expect-error\n CONNECTING: WebSocket.READY_STATE_CONNECTING,\n // @ts-expect-error\n OPEN: WebSocket.READY_STATE_OPEN,\n // @ts-expect-error\n CLOSING: WebSocket.READY_STATE_CLOSING,\n // @ts-expect-error\n CLOSED: WebSocket.READY_STATE_CLOSED\n };\n\n Object.assign(WebSocket, WebSocketStatus);\n // @ts-expect-error\n Object.assign(WebSocket.prototype, WebSocketStatus);\n}\n\n/**\n * Store both platform attachments and user attachments in different namespaces\n */\ntype ConnectionAttachments = {\n __pk: {\n id: string;\n tags: string[];\n uri?: string;\n };\n __user?: unknown;\n};\n\nfunction tryGetManagedWebSocketMeta(\n ws: WebSocket\n): ConnectionAttachments[\"__pk\"] | null {\n try {\n // Avoid AttachmentCache.get() here: externally accepted sockets\n // can have an attachment without the managed __pk namespace.\n const attachment = WebSocket.prototype.deserializeAttachment.call(\n ws\n ) as unknown;\n if (!attachment || typeof attachment !== \"object\") {\n return null;\n }\n if (!(\"__pk\" in attachment)) {\n return null;\n }\n const pk = (attachment as ConnectionAttachments).__pk as unknown;\n if (!pk || typeof pk !== \"object\") {\n return null;\n }\n const { id, tags } = pk as {\n id?: unknown;\n tags?: unknown;\n };\n if (typeof id !== \"string\") {\n return null;\n }\n const { uri } = pk as { uri?: unknown };\n return {\n id,\n tags: Array.isArray(tags) ? tags : [],\n uri: typeof uri === \"string\" ? uri : undefined\n } satisfies ConnectionAttachments[\"__pk\"];\n } catch {\n return null;\n }\n}\n\nexport function isManagedWebSocket(ws: WebSocket): boolean {\n return tryGetManagedWebSocketMeta(ws) !== null;\n}\n\n/**\n * Cache websocket attachments to avoid having to rehydrate them on every property access.\n */\nclass AttachmentCache {\n #cache = new WeakMap<WebSocket, ConnectionAttachments>();\n\n get(ws: WebSocket): ConnectionAttachments {\n let attachment = this.#cache.get(ws);\n if (!attachment) {\n attachment = WebSocket.prototype.deserializeAttachment.call(\n ws\n ) as ConnectionAttachments;\n if (attachment !== undefined) {\n this.#cache.set(ws, attachment);\n } else {\n throw new Error(\"Missing managed WebSocket lifecycle attachment\");\n }\n }\n\n return attachment;\n }\n\n set(ws: WebSocket, attachment: ConnectionAttachments) {\n this.#cache.set(ws, attachment);\n WebSocket.prototype.serializeAttachment.call(ws, attachment);\n }\n}\n\nconst attachments = new AttachmentCache();\nconst connections = new WeakSet<Connection>();\nconst isWrapped = (ws: WebSocket): ws is Connection => {\n return connections.has(ws as Connection);\n};\n\n/**\n * Wraps a WebSocket with Connection fields that rehydrate the\n * socket attachments lazily only when requested.\n */\nexport const createConnection = (ws: WebSocket | Connection): Connection => {\n if (isWrapped(ws)) {\n return ws;\n }\n\n // if state was set on the socket before initializing the connection,\n // capture it here so we can persist it again\n let initialState;\n if (\"state\" in ws) {\n initialState = ws.state;\n delete ws.state;\n }\n\n const connection = Object.defineProperties(ws, {\n id: {\n configurable: true,\n get() {\n return attachments.get(ws).__pk.id;\n }\n },\n uri: {\n configurable: true,\n get() {\n return attachments.get(ws).__pk.uri ?? null;\n }\n },\n tags: {\n configurable: true,\n get() {\n // Default to [] for connections accepted before tags were stored\n return attachments.get(ws).__pk.tags ?? [];\n }\n },\n state: {\n configurable: true,\n get() {\n const attachment = attachments.get(ws);\n return (attachment.__user ?? null) as ConnectionState<unknown>;\n }\n },\n setState: {\n configurable: true,\n value: function setState<T>(setState: T | ConnectionSetStateFn<T>) {\n const state =\n setState instanceof Function\n ? setState((this as Connection<T>).state)\n : setState;\n attachments.set(ws, {\n ...attachments.get(ws),\n __user: state ?? null\n });\n return state as ConnectionState<T>;\n }\n }\n }) as Connection;\n\n if (initialState) {\n connection.setState(initialState);\n }\n\n connections.add(connection);\n return connection;\n};\n\nclass ConnectionIterator<T> implements IterableIterator<Connection<T>> {\n private index = 0;\n #sockets: WebSocket[] | undefined;\n constructor(\n private sockets: LifecycleSockets,\n private tag?: string\n ) {}\n\n [Symbol.iterator](): IterableIterator<Connection<T>> {\n return this;\n }\n\n next(): IteratorResult<Connection<T>, number | undefined> {\n const sockets =\n this.#sockets ?? (this.#sockets = this.sockets.get(this.tag));\n\n let socket: WebSocket;\n while ((socket = sockets[this.index++])) {\n // Only yield open sockets.\n if (socket.readyState === WebSocket.OPEN) {\n // Durable Objects hibernation APIs allow storing arbitrary sockets via\n // `state.acceptWebSocket()`. Ignore sockets without our attachment.\n if (!isManagedWebSocket(socket)) {\n continue;\n }\n const value = createConnection(socket) as Connection<T>;\n return { done: false, value };\n }\n }\n\n // reached the end of the iteratee\n return { done: true, value: undefined };\n }\n}\n\n/**\n * Deduplicate and validate connection tags.\n * Returns the final tag array (always includes the connection id as the first tag).\n */\nexport function prepareTags(\n connectionId: string,\n userTags: string[]\n): string[] {\n const tags = [connectionId, ...userTags.filter((t) => t !== connectionId)];\n\n // validate tags against documented restrictions\n // https://developers.cloudflare.com/durable-objects/api/hibernatable-websockets-api/#state-methods-for-websockets\n if (tags.length > 10) {\n throw new Error(\n \"A connection can only have 10 tags, including the default id tag.\"\n );\n }\n\n for (const tag of tags) {\n if (typeof tag !== \"string\") {\n throw new Error(`A connection tag must be a string. Received: ${tag}`);\n }\n if (tag === \"\") {\n throw new Error(\"A connection tag must not be an empty string.\");\n }\n if (tag.length > 256) {\n throw new Error(\"A connection tag must not exceed 256 characters\");\n }\n }\n\n return tags;\n}\n\n/** The platform-backed manager for hibernating WebSockets. */\nexport class ConnectionManager<TState = unknown> {\n constructor(private controller: LifecycleSockets) {}\n\n getConnection<T = TState>(id: string) {\n // TODO: Should we cache the connections?\n const sockets = this.controller.get(id);\n const matching = sockets.filter((ws) => {\n return tryGetManagedWebSocketMeta(ws)?.id === id;\n });\n\n if (matching.length === 0) return undefined;\n if (matching.length === 1)\n return createConnection(matching[0]) as Connection<T>;\n\n throw new Error(\n `More than one connection found for id ${id}. Did you mean to use getConnections(tag) instead?`\n );\n }\n\n getConnections<T = TState>(tag?: string | undefined) {\n return new ConnectionIterator<T>(this.controller, tag);\n }\n\n accept(connection: Connection, options: { tags: string[] }) {\n const tags = prepareTags(connection.id, options.tags);\n\n this.controller.accept(connection, tags);\n attachments.set(connection, {\n __pk: {\n id: connection.id,\n tags,\n uri: connection.uri ?? undefined\n },\n __user: null\n });\n\n return createConnection(connection);\n }\n}\n","import { RpcTarget } from \"cloudflare:workers\";\nimport { CAPNWEB_TRANSPORT_SEND } from \"./transport-protocol\";\n\n/** A named remote method ready to be exposed on a callables root. */\nexport type CallableInvoker = (...args: unknown[]) => unknown;\n\n/**\n * The single exposure policy for callable names. `Object.prototype` and\n * `RpcTarget.prototype` members are unreachable over Cap'n Web anyway\n * and are silently excluded; `then` is rejected loudly because exposing\n * it would make the remote stub thenable.\n */\nfunction assertExposable(name: string): boolean {\n if (name === \"then\") {\n throw new Error(\n 'A callables target cannot expose a method named \"then\" — it would make the remote stub thenable'\n );\n }\n if (name === CAPNWEB_TRANSPORT_SEND) {\n throw new Error(\n `A callables target cannot expose \"${CAPNWEB_TRANSPORT_SEND}\"; it is the transport's frame pipe`\n );\n }\n return !(\n name === \"constructor\" ||\n name in Object.prototype ||\n name in RpcTarget.prototype\n );\n}\n\n/**\n * The exposable prototype methods of a callables target, each bound to\n * invoke on the real instance (so private fields and `this` behave).\n *\n * Cap'n Web resolves methods on the prototype chain and rejects own\n * instance properties, so only prototype methods participate. The\n * nearest declaration wins for overridden names.\n *\n * @param target - The callables target to enumerate.\n * @returns Method names mapped to invokers on the target.\n */\nexport function exposableMethods(\n target: RpcTarget\n): ReadonlyMap<string, CallableInvoker> {\n const methods = new Map<string, CallableInvoker>();\n const seen = new Set<string>();\n let prototype: object | null = Object.getPrototypeOf(target);\n while (\n prototype &&\n prototype !== RpcTarget.prototype &&\n prototype !== Object.prototype\n ) {\n for (const name of Object.getOwnPropertyNames(prototype)) {\n if (seen.has(name)) continue;\n seen.add(name);\n if (!assertExposable(name)) continue;\n const descriptor = Object.getOwnPropertyDescriptor(prototype, name);\n if (!descriptor || typeof descriptor.value !== \"function\") continue;\n // SAFETY: `typeof descriptor.value === \"function\"` was checked\n // above; TypeScript cannot narrow a descriptor's `value` field.\n const method = descriptor.value as CallableInvoker;\n methods.set(name, (...args) => Reflect.apply(method, target, args));\n }\n prototype = Object.getPrototypeOf(prototype);\n }\n return methods;\n}\n\n/**\n * Build a Cap'n Web session root exposing exactly the given methods.\n *\n * Cap'n Web resolves methods on the prototype chain, rejects own\n * instance properties, and breaks on Proxy-wrapped roots — so the root\n * is a private `RpcTarget` subclass whose prototype carries the methods\n * and nothing else.\n */\nexport function buildRoot(\n methods: ReadonlyMap<string, CallableInvoker>\n): RpcTarget {\n class Root extends RpcTarget {}\n for (const [name, invoke] of methods) {\n Object.defineProperty(Root.prototype, name, {\n value: invoke,\n writable: true,\n configurable: true,\n enumerable: false\n });\n }\n return new Root();\n}\n","import { newWebSocketRpcSession, type RpcStub } from \"capnweb\";\nimport type {\n Connection,\n ConnectionContext,\n ConnectionSetStateFn,\n ConnectionState\n} from \"../lifecycle\";\nimport { buildRoot, type CallableInvoker } from \"./callables-target\";\nimport { prepareTags } from \"./connection\";\nimport {\n CAPNWEB_TRANSPORT_SEND,\n type TransportClientEvents,\n type TransportMessage\n} from \"./transport-protocol\";\n\n/**\n * A non-hibernating connection with the public `Connection` contract,\n * backed by a Cap'n Web session instead of a hibernating socket. It lives\n * only in memory and disappears with the isolate.\n */\nclass CapnWebConnection extends EventTarget {\n readonly CONNECTING = WebSocket.CONNECTING;\n readonly OPEN = WebSocket.OPEN;\n readonly CLOSING = WebSocket.CLOSING;\n readonly CLOSED = WebSocket.CLOSED;\n readyState: number = WebSocket.OPEN;\n state: ConnectionState<unknown> = null;\n tags: readonly string[] = [];\n\n constructor(\n readonly id: string,\n readonly uri: string,\n private readonly pipe: {\n send(message: TransportMessage): void;\n close(code?: number, reason?: string): void;\n }\n ) {\n super();\n }\n\n send(message: TransportMessage): void {\n if (this.readyState !== WebSocket.OPEN) {\n throw new TypeError(\"WebSocket send() after close\");\n }\n this.pipe.send(message);\n }\n\n close(code?: number, reason?: string): void {\n if (this.readyState >= WebSocket.CLOSING) return;\n this.pipe.close(code, reason);\n this.readyState = WebSocket.CLOSING;\n }\n\n setState<T = unknown>(\n next: T | ConnectionSetStateFn<T> | null\n ): ConnectionState<T> {\n const state =\n typeof next === \"function\"\n ? (next as ConnectionSetStateFn<T>)(this.state as ConnectionState<T>)\n : next;\n this.state = state as ConnectionState<unknown>;\n return state as ConnectionState<T>;\n }\n}\n\n/** One live transport session. */\nexport type CapnWebSession = {\n readonly connection: Connection;\n /** Tear the session down; runs the close handler once. */\n dispose(): void;\n};\n\n/** What the capability supplies to run one session. */\nexport type CapnWebSessionOptions = {\n readonly request: Request;\n readonly connectionId: string;\n readonly tags: (\n connection: Connection,\n ctx: ConnectionContext\n ) => string[] | Promise<string[]>;\n readonly onConnect: (\n connection: Connection,\n ctx: ConnectionContext\n ) => Promise<void>;\n readonly onMessage: (\n connection: Connection,\n message: TransportMessage\n ) => Promise<void>;\n readonly onClose: (\n connection: Connection,\n code: number,\n reason: string,\n wasClean: boolean\n ) => Promise<void>;\n readonly onError: (connection: Connection, error: unknown) => Promise<void>;\n /**\n * Native methods served on the session root beside the frame pipe. Each\n * invoker already runs inside the host boundary for this connection.\n * Results pass by Cap'n Web semantics: an `RpcTarget` becomes a live\n * stub, a `ReadableStream` streams, and calls pipeline.\n */\n readonly callables: (\n connection: Connection\n ) => ReadonlyMap<string, CallableInvoker>;\n /**\n * Called once the connection exists, before `onConnect`, so it is already\n * visible in `getConnections()` while the connect handler runs — the same\n * ordering as a hibernating socket, which is accepted before `onConnect`.\n */\n readonly onOpen: (session: CapnWebSession) => void;\n /** Called exactly once when the session ends, before `onClose`. */\n readonly onDispose: (session: CapnWebSession) => void;\n};\n\n/**\n * Accept a Cap'n Web transport upgrade.\n *\n * The session root carries the frame pipe plus the host's native\n * callables. The client's protocol frames arrive through the pipe and are\n * handed to `onMessage`; the host's frames go out through the client's\n * `message` callback; `useAgent().stub` calls hit the callables directly.\n * The socket is a plain in-memory `WebSocketPair`, so it pins the Durable\n * Object and does not survive hibernation.\n */\nexport async function openCapnWebSession(\n options: CapnWebSessionOptions\n): Promise<{ response: Response; session: CapnWebSession }> {\n const { request, connectionId } = options;\n const pair = new WebSocketPair();\n const server = pair[0];\n server.accept();\n\n let client: RpcStub<TransportClientEvents> | undefined;\n let closed = false;\n let close = { code: 1000, reason: \"\", wasClean: true };\n\n const connection = new CapnWebConnection(connectionId, request.url, {\n send: (message) => {\n void client?.message(message).catch((error: unknown) => {\n if (!closed) console.error(\"Cap'n Web frame delivery failed:\", error);\n });\n },\n close: (code = 1000, reason = \"\") => {\n // Same contract as WebSocket.close(): a reserved code or an oversize\n // reason throws before anything changes, and the socket stays open\n // and tracked. Only a started handshake finishes the session.\n server.close(code, reason);\n close = { code, reason, wasClean: true };\n void finish();\n }\n }) as unknown as Connection & CapnWebConnection;\n\n const session: CapnWebSession = {\n connection,\n dispose: () => connection.close(1001, \"Session replaced\")\n };\n\n const finish = async () => {\n if (closed) return;\n closed = true;\n connection.readyState = WebSocket.CLOSED;\n try {\n client?.[Symbol.dispose]();\n } catch {\n // The session already ended with the socket.\n }\n options.onDispose(session);\n await options.onClose(connection, close.code, close.reason, close.wasClean);\n };\n\n const rootMethods = new Map<string, CallableInvoker>(\n options.callables(connection)\n );\n rootMethods.set(CAPNWEB_TRANSPORT_SEND, (message) =>\n options.onMessage(connection, message as TransportMessage)\n );\n client = newWebSocketRpcSession<TransportClientEvents>(\n server,\n buildRoot(rootMethods)\n );\n\n server.addEventListener(\n \"close\",\n (event) => {\n close = {\n code: event.code,\n reason: event.reason,\n wasClean: event.wasClean\n };\n void finish();\n },\n { once: true }\n );\n server.addEventListener(\n \"error\",\n (event) => {\n if (closed) return;\n close = { ...close, wasClean: false };\n const error =\n event instanceof ErrorEvent\n ? (event.error ?? new Error(event.message))\n : new Error(\"Cap'n Web transport socket error\");\n void options\n .onError(connection, error)\n .catch((handlerError: unknown) => {\n console.error(\"Cap'n Web onError handler failed:\", handlerError);\n })\n .finally(finish);\n },\n { once: true }\n );\n\n const ctx = { request };\n // Same limits as the hibernating wire (count, emptiness, length), so a\n // handler sees one tag policy whichever transport the client chose.\n connection.tags = prepareTags(\n connectionId,\n await options.tags(connection, ctx)\n );\n options.onOpen(session);\n try {\n await options.onConnect(connection, ctx);\n } catch (error) {\n connection.close(1011, \"onConnect failed\");\n throw error;\n }\n\n return {\n response: new Response(null, { status: 101, webSocket: pair[1] }),\n session\n };\n}\n","import { RpcTarget } from \"cloudflare:workers\";\nimport { nanoid } from \"nanoid\";\nimport {\n LifecycleCapability,\n type CapabilityWebSocketUpgradeContext,\n type Connection,\n type ConnectionContext,\n type ConnectionSetStateFn,\n type ConnectionState\n} from \"../lifecycle\";\nimport { MessageType } from \"../types\";\nimport { camelCaseToKebabCase } from \"../utils\";\nimport {\n ConnectionManager,\n createConnection,\n isManagedWebSocket\n} from \"./connection\";\nimport {\n ensureConnectionWrapped,\n isConnectionProtocolEnabled,\n isConnectionReadonly,\n setConnectionProtocolEnabled,\n setConnectionReadonly\n} from \"./connection-flags\";\nimport { exposableMethods, type CallableInvoker } from \"./callables-target\";\nimport type {\n SyncedState,\n WebSocketHandlers,\n WebSocketMessage,\n WebSocketsOptions\n} from \"./options\";\nimport { openCapnWebSession, type CapnWebSession } from \"./transport\";\nimport { isCapnWebTransportUpgrade } from \"./transport-protocol\";\n\n/**\n * Reserved close codes the runtime synthesizes when there was no real\n * Close frame from the peer (1005 NoStatusReceived, 1006 AbnormalClosure,\n * 1015 TLSHandshake). They cannot appear in an outgoing Close frame, and\n * there is no peer left to receive a reciprocation.\n */\nfunction isReservedCloseCode(code: number): boolean {\n return code === 1005 || code === 1006 || code === 1015;\n}\n\n/**\n * Reciprocate a peer-initiated Close frame to complete the handshake, as\n * the Hibernation API contract requires. Best-effort: swallows errors\n * from already-closed sockets or invalid codes/reasons, and skips\n * reciprocation entirely for reserved codes (dead transport).\n */\nfunction reciprocateClose(ws: WebSocket, code: number, reason: string): void {\n if (isReservedCloseCode(code)) return;\n try {\n ws.close(code, reason);\n } catch {\n // Already closed, oversize reason, or another unrecoverable\n // invariant — the handshake is either done or out of our control.\n }\n}\n\n/** The `rpc` request frame `useAgent().call` and `AgentClient.call` send. */\ntype RpcRequest = {\n readonly type: \"rpc\";\n readonly id: string;\n readonly method: string;\n readonly args: unknown[];\n};\n\ntype RpcResponse =\n | { type: \"rpc\"; id: string; success: true; done: boolean; result: unknown }\n | { type: \"rpc\"; id: string; success: false; error: string };\n\n/** The `cf_agent_state` frame a client sends to update host state. */\ntype StateFrame = { readonly type: \"cf_agent_state\"; readonly state: unknown };\n\nfunction isStateFrame(value: unknown): value is StateFrame {\n if (typeof value !== \"object\" || value === null) return false;\n const frame = value as Record<string, unknown>;\n return frame.type === MessageType.CF_AGENT_STATE && \"state\" in frame;\n}\n\n/** Parse a text frame; anything that is not JSON is `undefined`. */\nfunction parseJson(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\n\nfunction isRpcRequest(value: unknown): value is RpcRequest {\n if (typeof value !== \"object\" || value === null) return false;\n const frame = value as Record<string, unknown>;\n return (\n frame.type === MessageType.RPC &&\n typeof frame.id === \"string\" &&\n typeof frame.method === \"string\" &&\n Array.isArray(frame.args)\n );\n}\n\n/**\n * Opt-in WebSocket support for Lifecycle Objects.\n *\n * Lifecycle itself does not model WebSockets — hosts that want them\n * install this capability, which owns the connection subsystem end to\n * end: it claims upgrades, dispatches `onConnect`/`onMessage`/`onClose`\n * inside the host invocation boundary, reciprocates close handshakes,\n * and answers `getConnections()`/`getConnection()`.\n *\n * ```ts\n * class Room extends DurableObject<Env> {\n * readonly webSockets = new WebSockets({\n * handlers: {\n * onConnect: (connection) => connection.send(\"welcome\"),\n * onMessage: (connection, message) => { ... }\n * },\n * callables: new RoomCallables()\n * });\n * readonly lifecycle = Lifecycle.install(this).use(this.webSockets);\n * }\n * ```\n *\n * Connections arrive on one of two wires, chosen by the client:\n *\n * - **cf-websocket** (default): accepted with the Hibernation API. Idle\n * clients stay connected while the Durable Object leaves memory.\n * - **capnweb** (`?__agents_transport=capnweb`): protocol frames through\n * one pipe method on a Cap'n Web session whose root also carries the\n * host's callables natively. Non-hibernating — the object stays pinned\n * while the connection is open.\n *\n * Both wires dispatch the same handlers and appear in `getConnections()`.\n * On both, the capability speaks the Agent protocol a plain host needs\n * for `useAgent` and `AgentClient`: it sends the identity frame on\n * connect, and it serves `callables` — as `rpc` JSON frames on the\n * WebSocket wire, and natively on the Cap'n Web session root, where an\n * `RpcTarget` result becomes a live stub and calls pipeline. `call()`\n * and `stub` work against a plain Durable Object exactly as against an\n * `Agent`. Pass a `State` capability as `state` and the hook's\n * `state`/`setState` work too: the current value is pushed on connect\n * and client updates are validated and applied; the state owner\n * broadcasts changes with `broadcastState()`. Per-connection readonly\n * and no-protocol flags live here as well, for every host.\n */\nexport class WebSockets extends LifecycleCapability {\n /** Claims every upgrade, so Lifecycle dispatches it after all others. */\n override readonly claims = \"catch-all\";\n\n readonly #handlers: WebSocketHandlers | undefined;\n /** Handlers added with `use`, run before the configured ones. */\n readonly #added: WebSocketHandlers[] = [];\n readonly #getConnectionTags: WebSocketsOptions[\"getConnectionTags\"];\n readonly #protocol: WebSocketsOptions[\"protocol\"];\n readonly #readonly: WebSocketsOptions[\"readonly\"];\n readonly #state: SyncedState | undefined;\n /**\n * Connections inside their connect sequence, before the state push.\n * `broadcastState()` skips them: reading state for the push can seed the\n * initial value, whose change broadcast would otherwise reach a\n * connection that is about to receive the same value directly.\n */\n readonly #connecting = new Set<Connection>();\n readonly #callables: ReadonlyMap<string, CallableInvoker>;\n readonly #sessions = new Map<string, CapnWebSession>();\n #manager: ConnectionManager | undefined;\n\n constructor(options: WebSocketsOptions = {}) {\n super(\"websockets\");\n this.#handlers = options.handlers;\n this.#getConnectionTags = options.getConnectionTags;\n this.#protocol = options.protocol ?? true;\n this.#readonly = options.readonly;\n this.#state = options.state;\n this.#callables = options.callables\n ? exposableMethods(options.callables)\n : new Map();\n }\n\n // ── Lifecycle capability hooks ─────────────────────────────────────────\n\n /**\n * Claim every upgrade, never declining: a Cap'n Web transport upgrade\n * becomes a session, everything else a tracked hibernating connection,\n * whether or not handlers or callables are configured. Handlers only add\n * behavior on connect, message, close, and error.\n */\n onWebSocketUpgrade({\n request\n }: CapabilityWebSocketUpgradeContext): Promise<Response> {\n return isCapnWebTransportUpgrade(request)\n ? this.#acceptCapnWebSession(request)\n : this.#acceptConnection(request);\n }\n\n /** Dispatch a platform message wake for a capability-owned socket. */\n async onWebSocketMessage(\n ws: WebSocket,\n message: WebSocketMessage\n ): Promise<boolean> {\n if (!isManagedWebSocket(ws)) return false;\n await this.#message(createConnection(ws), message);\n return true;\n }\n\n /** Dispatch and reciprocate a close wake for an owned socket. */\n async onWebSocketClose(\n ws: WebSocket,\n code: number,\n reason: string,\n wasClean: boolean\n ): Promise<boolean> {\n if (!isManagedWebSocket(ws)) return false;\n try {\n await this.#close(createConnection(ws), code, reason, wasClean);\n } finally {\n reciprocateClose(ws, code, reason);\n }\n return true;\n }\n\n /** Dispatch an error wake for an owned socket. */\n async onWebSocketError(ws: WebSocket, error: unknown): Promise<boolean> {\n if (!isManagedWebSocket(ws)) return false;\n await this.#error(createConnection(ws), error);\n return true;\n }\n\n /**\n * Close every owned connection during explicit host destruction. The\n * capability owns its sockets' lifetimes, so it also owns tearing\n * them down.\n */\n dispose(): void {\n for (const connection of this.getConnections()) {\n try {\n connection.close(1001, \"Durable Object destroyed\");\n } catch {\n // Already closed or mid-handshake — nothing left to tear down.\n }\n }\n }\n\n /**\n * Add handlers for another component sharing these connections, such as\n * a protocol of its own. They run before the configured handlers, and\n * their `onMessage` can claim a message by returning true.\n */\n use(handlers: WebSocketHandlers): void {\n this.#added.push(handlers);\n }\n\n // ── Connections ────────────────────────────────────────────────────────\n\n /** Open connections on either wire, optionally by tag. */\n *getConnections<TState = unknown>(\n tag?: string\n ): IterableIterator<Connection<TState>> {\n for (const { connection } of this.#sessions.values()) {\n if (connection.readyState !== WebSocket.OPEN) continue;\n if (!tag || connection.tags.includes(tag)) {\n yield connection as Connection<TState>;\n }\n }\n yield* this.#connectionManager.getConnections<TState>(tag);\n }\n\n /** One connection on either wire, by id. */\n getConnection<TState = unknown>(id: string): Connection<TState> | undefined {\n const session = this.#sessions.get(id)?.connection;\n if (session && session.readyState === WebSocket.OPEN) {\n return session as Connection<TState>;\n }\n return this.#connectionManager.getConnection<TState>(id);\n }\n\n get #connectionManager(): ConnectionManager {\n this.#manager ??= new ConnectionManager(this.lifecycle.sockets);\n return this.#manager;\n }\n\n // ── Wire-independent protocol ──────────────────────────────────────────\n\n async #connect(\n connection: Connection,\n ctx: ConnectionContext\n ): Promise<void> {\n ensureConnectionWrapped(connection);\n // Flags first, so they are set before the client can respond.\n if (this.#readonly?.(connection, ctx)) {\n setConnectionReadonly(connection, true);\n }\n if (this.#protocol !== false) {\n const enabled =\n typeof this.#protocol === \"function\"\n ? this.#protocol(connection, ctx)\n : true;\n if (enabled) {\n this.sendConnectFrames(connection);\n } else {\n setConnectionProtocolEnabled(connection, false);\n }\n }\n for (const handlers of [...this.#added, this.#handlers]) {\n await this.lifecycle.runInHostContext(\n () => handlers?.onConnect?.(connection, ctx),\n { connection, request: ctx.request }\n );\n }\n }\n\n async #message(\n connection: Connection,\n message: WebSocketMessage\n ): Promise<void> {\n if (\n this.#state &&\n this.#protocol !== false &&\n typeof message === \"string\"\n ) {\n const frame = parseJson(message);\n if (isStateFrame(frame)) {\n // Inside the host boundary, so the host's validator and change\n // hook see the sending connection through the ambient context.\n await this.lifecycle.runInHostContext(\n () => this.applyStateFrame(connection, frame),\n { connection }\n );\n return;\n }\n }\n if (\n this.#callables.size > 0 &&\n (await this.#answerRpc(connection, message))\n ) {\n return;\n }\n for (const handlers of this.#added) {\n const claimed = await this.lifecycle.runInHostContext(\n () => handlers.onMessage?.(connection, message),\n { connection }\n );\n if (claimed === true) return;\n }\n await this.lifecycle.runInHostContext(\n () => this.#handlers?.onMessage?.(connection, message),\n { connection }\n );\n }\n\n #close(\n connection: Connection,\n code: number,\n reason: string,\n wasClean: boolean\n ): Promise<unknown> {\n return this.#each((handlers) =>\n this.lifecycle.runInHostContext(\n () => handlers?.onClose?.(connection, code, reason, wasClean),\n { connection }\n )\n );\n }\n\n #error(connection: Connection, error: unknown): Promise<unknown> {\n return this.#each((handlers) =>\n this.lifecycle.runInHostContext(\n () => handlers?.onError?.(connection, error),\n { connection }\n )\n );\n }\n\n async #each(\n run: (handlers: WebSocketHandlers | undefined) => Promise<unknown>\n ): Promise<void> {\n for (const handlers of [...this.#added, this.#handlers])\n await run(handlers);\n }\n\n // ── Hibernating wire ───────────────────────────────────────────────────\n\n async #acceptConnection(request: Request): Promise<Response> {\n const { 0: clientWebSocket, 1: serverWebSocket } = new WebSocketPair();\n const url = new URL(request.url);\n // `||`, not `??`: an empty `?_pk=` value must fall back to a\n // generated id — an empty connection id would later throw in tag\n // validation and reject the upgrade.\n const connectionId = url.searchParams.get(\"_pk\") || nanoid();\n\n let connection: Connection = Object.assign(serverWebSocket, {\n id: connectionId,\n uri: request.url,\n tags: [] as string[],\n state: null as unknown as ConnectionState<unknown>,\n setState<T = unknown>(setState: T | ConnectionSetStateFn<T>) {\n // Pre-accept shim: hold state on the socket until accept()\n // persists it into the hibernation attachment.\n const state =\n setState instanceof Function\n ? setState(this.state as ConnectionState<T>)\n : setState;\n this.state = state as ConnectionState<T>;\n return this.state as ConnectionState<T>;\n }\n });\n\n const ctx = { request };\n const tags = this.#getConnectionTags\n ? await this.#getConnectionTags(connection, ctx)\n : [];\n\n // Hibernating WebSockets remain connected while the object is evicted.\n connection = this.#connectionManager.accept(connection, { tags });\n await this.#connect(connection, ctx);\n\n return new Response(null, { status: 101, webSocket: clientWebSocket });\n }\n\n // ── Cap'n Web wire ─────────────────────────────────────────────────────\n\n async #acceptCapnWebSession(request: Request): Promise<Response> {\n const connectionId =\n new URL(request.url).searchParams.get(\"_pk\") || nanoid();\n // A reconnect reusing the id replaces the previous session.\n this.#sessions.get(connectionId)?.dispose();\n\n const { response } = await openCapnWebSession({\n request,\n connectionId,\n tags: (connection, ctx) =>\n this.#getConnectionTags?.(connection, ctx) ?? [],\n onConnect: (connection, ctx) => this.#connect(connection, ctx),\n onMessage: (connection, message) => this.#message(connection, message),\n onClose: (connection, code, reason, wasClean) =>\n this.#close(connection, code, reason, wasClean).then(() => undefined),\n onError: (connection, error) =>\n this.#error(connection, error).then(() => undefined),\n callables: (connection) => this.#nativeCallables(connection),\n onOpen: (session) => this.#sessions.set(connectionId, session),\n onDispose: (ended) => {\n if (this.#sessions.get(connectionId) === ended) {\n this.#sessions.delete(connectionId);\n }\n }\n });\n return response;\n }\n\n // ── Protocol frames ────────────────────────────────────────────────────\n //\n // The Agent protocol a client (`useAgent`, `AgentClient`) speaks, owned\n // here for every host. With `protocol: true` the capability drives the\n // connect sequence and consumes state frames itself; with\n // `protocol: false` the host calls these at the moments it chooses.\n\n /**\n * Send the connect sequence: the identity frame, then the current state\n * when one is stored. The identity carries `stateFollows` in that case,\n * so clients resolve `ready` only once the state has landed. Nothing is\n * sent to a no-protocol connection. Identity defaults as for\n * `sendIdentity()`.\n */\n sendConnectFrames(\n connection: Connection,\n identity: { name: string; agent: string } = this.#defaultIdentity()\n ): void {\n if (!isConnectionProtocolEnabled(connection)) return;\n this.#connecting.add(connection);\n try {\n const current = this.#state?.get();\n // Serialized first: a flagged identity must never go out without\n // the state frame the client will wait for.\n const stateFrame =\n current === undefined\n ? undefined\n : JSON.stringify({\n type: MessageType.CF_AGENT_STATE,\n state: current\n });\n this.#sendFrame(connection, {\n type: MessageType.CF_AGENT_IDENTITY,\n name: identity.name,\n agent: identity.agent,\n ...(stateFrame !== undefined && { stateFollows: true })\n });\n if (stateFrame !== undefined) this.#send(connection, stateFrame);\n } finally {\n this.#connecting.delete(connection);\n }\n }\n\n /**\n * Send the identity frame alone, unless the connection is no-protocol.\n * Clients resolve `ready` on it, so a host that also pushes state on\n * connect should use `sendConnectFrames()`. The defaults are the Durable\n * Object's routed name and host class; a host whose public identity\n * differs — an `Agent` facet, whose routed name is an internal encoding\n * of its logical name — passes its own.\n */\n sendIdentity(\n connection: Connection,\n identity: { name: string; agent: string } = this.#defaultIdentity()\n ): void {\n if (!isConnectionProtocolEnabled(connection)) return;\n this.#sendFrame(connection, {\n type: MessageType.CF_AGENT_IDENTITY,\n name: identity.name,\n agent: identity.agent\n });\n }\n\n #defaultIdentity(): { name: string; agent: string } {\n return {\n name: this.lifecycle.name,\n agent: camelCaseToKebabCase(this.lifecycle.className)\n };\n }\n\n /**\n * Send the current state to one connection, unless nothing is stored\n * or the connection is no-protocol. Reading the state may seed the\n * initial value; see `#connecting`.\n */\n sendState(connection: Connection): void {\n if (!this.#state || !isConnectionProtocolEnabled(connection)) return;\n const current = this.#state.get();\n if (current === undefined) return;\n this.#sendFrame(connection, {\n type: MessageType.CF_AGENT_STATE,\n state: current\n });\n }\n\n /**\n * Apply a parsed `cf_agent_state` frame from a client. A readonly\n * connection is refused; a change the host's validator rejects is\n * logged in full server-side and answered with a generic\n * `cf_agent_state_error`. Broadcasting the accepted change is the state\n * owner's call, through its `onChanged` hook. Callers that drive the\n * protocol themselves call this inside their own invocation context;\n * the capability's automatic path does so via `runInHostContext`.\n *\n * @returns Whether the frame was a state frame (handled either way).\n */\n applyStateFrame(connection: Connection, frame: unknown): boolean {\n if (!this.#state || !isStateFrame(frame)) return false;\n if (isConnectionReadonly(connection)) {\n this.#sendFrame(connection, {\n type: MessageType.CF_AGENT_STATE_ERROR,\n error: \"Connection is readonly\"\n });\n return true;\n }\n try {\n // `never` on the port keeps any `State<T>` assignable; the value\n // came off the wire, so the host's validator is what checks it.\n this.#state.set(frame.state as never, connection);\n } catch (error) {\n console.error(\"[WebSockets] State update rejected:\", error);\n this.#sendFrame(connection, {\n type: MessageType.CF_AGENT_STATE_ERROR,\n error: \"State update rejected\"\n });\n }\n return true;\n }\n\n /**\n * Push the current state to every protocol-enabled connection except\n * the one a change came from, which already has the value it sent.\n * Wire a `State`'s `onChanged` to this.\n */\n broadcastState(except?: Connection | \"server\"): void {\n if (!this.#state) return;\n const current = this.#state.get();\n if (current === undefined) return;\n const frame = { type: MessageType.CF_AGENT_STATE, state: current };\n for (const connection of this.getConnections()) {\n // Object identity, not id: `_pk` is client-supplied, so two live\n // sockets can share an id, and excluding by id would starve the\n // other one. `createConnection` returns one wrapper per socket.\n if (connection === except) continue;\n if (this.#connecting.has(connection)) continue;\n if (!isConnectionProtocolEnabled(connection)) continue;\n this.#sendFrame(connection, frame);\n }\n }\n\n // ── Connection flags ───────────────────────────────────────────────────\n\n /** Whether the connection may update host state over the wire. */\n isReadonly(connection: Connection): boolean {\n return isConnectionReadonly(connection);\n }\n\n /** Mark a connection readonly, or writable again. */\n setReadonly(connection: Connection, readonly = true): void {\n setConnectionReadonly(connection, readonly);\n }\n\n /** Whether protocol text frames reach the connection. */\n isProtocolEnabled(connection: Connection): boolean {\n return isConnectionProtocolEnabled(connection);\n }\n\n /** Enable or suppress protocol text frames for a connection. */\n setProtocolEnabled(connection: Connection, enabled: boolean): void {\n setConnectionProtocolEnabled(connection, enabled);\n }\n\n /**\n * Send one protocol frame. Serialization is the caller's contract — every\n * frame built here is plain JSON — while a send failure is tolerated: the\n * peer may have disconnected between the wake and the send.\n */\n #sendFrame(connection: Connection, frame: Record<string, unknown>): void {\n this.#send(connection, JSON.stringify(frame));\n }\n\n /** Write one already-serialized frame, tolerating a closed peer. */\n #send(connection: Connection, text: string): void {\n try {\n connection.send(text);\n } catch {\n // The socket closed between the wake and the send.\n }\n }\n\n // ── Callables ──────────────────────────────────────────────────────────\n\n /**\n * The `callables` target as native Cap'n Web methods for one session:\n * every method dispatches through the host boundary with this\n * connection in scope and emits `rpc`/`rpc:error` events. Return values\n * keep Cap'n Web semantics — an `RpcTarget` comes back as a live stub.\n */\n #nativeCallables(\n connection: Connection\n ): ReadonlyMap<string, CallableInvoker> {\n const methods = new Map<string, CallableInvoker>();\n for (const [name, invoke] of this.#callables) {\n methods.set(name, (...args) =>\n this.#dispatchCallable(name, () => invoke(...args), connection)\n );\n }\n return methods;\n }\n\n /**\n * Answer one `rpc` frame against `callables`. A `ReadableStream`\n * result streams as `done: false` chunks followed by a final\n * `done: true` frame, matching the client's stream callbacks.\n *\n * @returns Whether the message was an `rpc` frame (answered or not).\n */\n async #answerRpc(\n connection: Connection,\n raw: WebSocketMessage\n ): Promise<boolean> {\n if (typeof raw !== \"string\") return false;\n let frame: unknown;\n try {\n frame = JSON.parse(raw);\n } catch {\n return false;\n }\n if (!isRpcRequest(frame)) return false;\n const { id, method, args } = frame;\n\n const invoke = this.#callables.get(method);\n if (!invoke) {\n this.#reply(connection, {\n type: \"rpc\",\n id,\n success: false,\n error: `Method ${method} does not exist`\n });\n return true;\n }\n\n try {\n const result = await this.#dispatchCallable(\n method,\n () => invoke(...args),\n connection\n );\n if (result instanceof RpcTarget) {\n // By-reference results only exist on the Cap'n Web wire; a JSON\n // frame would silently flatten the target to `{}`.\n throw new Error(\n `Method ${method} returns an RpcTarget, which only the capnweb transport can carry`\n );\n }\n if (result instanceof ReadableStream) {\n for await (const chunk of result) {\n this.#reply(connection, {\n type: \"rpc\",\n id,\n success: true,\n done: false,\n result: chunk\n });\n }\n this.#reply(connection, {\n type: \"rpc\",\n id,\n success: true,\n done: true,\n result: undefined\n });\n } else {\n this.#reply(connection, {\n type: \"rpc\",\n id,\n success: true,\n done: true,\n result\n });\n }\n } catch (error) {\n this.#reply(connection, {\n type: \"rpc\",\n id,\n success: false,\n error: error instanceof Error ? error.message : String(error)\n });\n }\n return true;\n }\n\n #reply(connection: Connection, response: RpcResponse): void {\n let text: string;\n try {\n text = JSON.stringify(response);\n } catch (error) {\n // A result that JSON cannot carry (a BigInt, a cycle) must still\n // settle the caller: answer with an error instead of silence.\n text = JSON.stringify({\n type: \"rpc\",\n id: response.id,\n success: false,\n error: `Result is not JSON-serializable: ${\n error instanceof Error ? error.message : String(error)\n }`\n } satisfies RpcResponse);\n }\n this.#send(connection, text);\n }\n\n async #dispatchCallable(\n name: string,\n invoke: () => unknown,\n connection: Connection\n ): Promise<unknown> {\n // Throws with installation guidance when the capability was never\n // installed with Lifecycle.use().\n const services = this.lifecycle;\n try {\n const result = await services.runInHostContext(invoke, { connection });\n services.events.emit(\"rpc\", {\n method: name,\n streaming: result instanceof ReadableStream\n });\n return result;\n } catch (error) {\n services.events.emit(\"rpc:error\", {\n method: name,\n error: error instanceof Error ? error.message : String(error)\n });\n throw error;\n }\n }\n}\n"],"mappings":"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"}
|
package/dist/workflow-types.d.ts
CHANGED
package/dist/workflows.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
wt as WorkflowPage,
|
|
21
21
|
xt as WorkflowEventCallback,
|
|
22
22
|
yt as WorkflowCompleteCallback
|
|
23
|
-
} from "./agent-routing-
|
|
23
|
+
} from "./agent-routing-vVMA7m8Y.js";
|
|
24
24
|
import { WorkflowEntrypoint, WorkflowEvent } from "cloudflare:workers";
|
|
25
25
|
|
|
26
26
|
//#region src/workflows.d.ts
|
package/dist/workflows.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { isInternalJsStubProp } from "./utils.js";
|
|
2
2
|
import { getAgentByName } from "./agent-routing.js";
|
|
3
|
-
import "./src-DfLzdwlK.js";
|
|
4
3
|
import { WorkflowRejectedError } from "./workflow-types.js";
|
|
5
4
|
import { WorkflowEntrypoint } from "cloudflare:workers";
|
|
6
5
|
//#region src/workflows.ts
|
package/dist/workflows.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflows.js","names":[],"sources":["../src/workflows.ts"],"sourcesContent":["/**\n * AgentWorkflow - Base class for Workflows that integrate with Agents\n *\n * Extends Cloudflare's WorkflowEntrypoint to provide seamless access to\n * the Agent that started the workflow, enabling bidirectional communication.\n *\n * @example\n * ```typescript\n * import { AgentWorkflow } from 'agents/workflows';\n * import type { MyAgent } from './agent';\n *\n * type TaskParams = { taskId: string; data: string };\n *\n * export class ProcessingWorkflow extends AgentWorkflow<MyAgent, TaskParams> {\n * async run(event: AgentWorkflowEvent<TaskParams>, step: WorkflowStep) {\n * // Access the originating Agent via typed RPC\n * await this.agent.updateTaskStatus(event.payload.taskId, 'processing');\n *\n * const result = await step.do('process', async () => {\n * // ... processing logic\n * return { processed: true };\n * });\n *\n * // Report progress to Agent (typed)\n * await this.reportProgress({ step: 'process', status: 'complete', percent: 0.5 });\n *\n * // Broadcast to connected clients\n * await this.broadcastToClients({ type: 'progress', data: result });\n *\n * return result;\n * }\n * }\n * ```\n */\n\nimport { WorkflowEntrypoint } from \"cloudflare:workers\";\nimport type {\n WorkflowEvent,\n WorkflowStep,\n WorkflowStepEvent\n} from \"cloudflare:workers\";\nimport { getAgentByName, type Agent } from \"./index\";\nimport type {\n AgentWorkflowParams,\n AgentWorkflowStep,\n WorkflowCallback,\n DefaultProgress,\n WaitForApprovalOptions\n} from \"./workflow-types\";\nimport { WorkflowRejectedError } from \"./workflow-types\";\nimport type {\n AgentWorkflowOrigin,\n AgentWorkflowPathStep\n} from \"./workflow-types\";\nimport { isInternalJsStubProp } from \"./utils\";\n\ntype AgentPathInvoker = {\n _cf_invokeAgentPath(\n path: ReadonlyArray<AgentWorkflowPathStep>,\n method: string,\n args: unknown[]\n ): Promise<unknown>;\n};\n\n/**\n * WeakSet to track which prototypes have been wrapped.\n * This prevents re-wrapping on subsequent instantiations of the same class.\n */\nconst wrappedPrototypes = new WeakSet<object>();\n\n/**\n * Base class for Workflows that need access to their originating Agent.\n *\n * @template AgentType - The Agent class type (for typed RPC access)\n * @template Params - User-defined params passed to the workflow (optional)\n * @template ProgressType - Type for progress reporting (defaults to DefaultProgress)\n * @template Env - Environment type (defaults to Cloudflare.Env)\n */\nexport class AgentWorkflow<\n AgentType extends Agent = Agent,\n Params = unknown,\n ProgressType = DefaultProgress,\n Env extends Cloudflare.Env = Cloudflare.Env\n> extends WorkflowEntrypoint<Env, AgentWorkflowParams<Params>> {\n /**\n * The Agent stub - initialized before run() is called.\n * Use this.agent to access the Agent's RPC methods.\n */\n private _agent?: DurableObjectStub<AgentType>;\n\n /**\n * Workflow instance ID\n */\n private _workflowId!: string;\n\n /**\n * Workflow binding name (for callbacks)\n */\n private _workflowName!: string;\n\n /**\n * Instance-level guard to prevent double initialization.\n * Used when a subclass calls super.run() after its own run() was wrapped.\n */\n private __agentInitCalled = false;\n\n /**\n * Guard to prevent double error notification.\n * Set to true when reportError() is called explicitly, so the automatic\n * error catch in the run() wrapper doesn't send a duplicate notification.\n */\n private _errorReported = false;\n\n constructor(ctx: ExecutionContext, env: Env) {\n super(ctx, env);\n\n const proto = Object.getPrototypeOf(this);\n\n // Only wrap if:\n // 1. This prototype defines its own run method (hasOwnProperty)\n // 2. It hasn't been wrapped yet (WeakSet check)\n // This prevents double-wrapping inherited methods and ensures each subclass\n // that defines run() gets wrapped exactly once.\n if (Object.hasOwn(proto, \"run\") && !wrappedPrototypes.has(proto)) {\n const originalRun = proto.run as (\n event: WorkflowEvent<Params>,\n step: AgentWorkflowStep\n ) => Promise<unknown>;\n\n // Replace the prototype's run method with a wrapper that initializes\n // the agent before calling the user's implementation\n proto.run = async function (\n this: AgentWorkflow<AgentType, Params, ProgressType, Env>,\n event: WorkflowEvent<AgentWorkflowParams<Params>>,\n step: WorkflowStep\n ) {\n // Instance-level guard: only init once per instance\n // (prevents double init if super.run() is called from a subclass)\n if (!this.__agentInitCalled) {\n const {\n __agentName,\n __agentBinding,\n __workflowName,\n __agentOrigin,\n ...userParams\n } = event.payload;\n\n // Initialize agent connection\n await this._initAgent(\n __agentName,\n __agentBinding,\n __workflowName,\n __agentOrigin,\n event.instanceId\n );\n this.__agentInitCalled = true;\n\n try {\n // Pass cleaned event and wrapped step to user's implementation\n const cleanedEvent = {\n ...event,\n payload: userParams as Params\n } as WorkflowEvent<Params>;\n\n const wrappedStep = this.extendStep(\n this._wrapStep(step),\n cleanedEvent\n );\n\n return await this._runWithErrorReporting(\n originalRun,\n cleanedEvent,\n wrappedStep\n );\n } finally {\n this._disposeAgent();\n }\n }\n\n // If already initialized (e.g., called via super.run()),\n // just call the original with the event as-is.\n return await this._runWithErrorReporting(\n originalRun,\n event as WorkflowEvent<Params>,\n step as AgentWorkflowStep\n );\n };\n\n wrappedPrototypes.add(proto);\n }\n }\n\n /**\n * Initialize the Agent stub from workflow params.\n * Called automatically before run() executes.\n */\n private async _initAgent(\n agentName: string | undefined,\n agentBinding: string | undefined,\n workflowName: string | undefined,\n agentOrigin: AgentWorkflowOrigin | undefined,\n instanceId: string\n ): Promise<void> {\n if (!workflowName || (!agentOrigin && (!agentName || !agentBinding))) {\n throw new Error(\n \"AgentWorkflow requires __agentName, __agentBinding, and __workflowName in params. \" +\n \"Use agent.runWorkflow() to start workflows with proper agent context.\"\n );\n }\n\n this._workflowId = instanceId;\n this._workflowName = workflowName;\n this._errorReported = false;\n\n // The origin payload is durably persisted in workflow params, so a workflow\n // started by an older SDK can resume against newer code (and vice versa).\n // Reject origin versions this build does not understand rather than\n // silently misreading a future shape.\n if (agentOrigin && agentOrigin.version !== 1) {\n throw new Error(\n `AgentWorkflow received an unsupported origin version (${\n (agentOrigin as { version?: unknown }).version\n }). Upgrade the \"agents\" package running this Workflow to match the Agent that started it.`\n );\n }\n\n if (agentOrigin?.kind === \"facet\") {\n this._agent = await this._initFacetAgent(agentOrigin);\n return;\n }\n\n const resolvedAgentName =\n agentOrigin?.kind === \"agent\" ? agentOrigin.name : agentName;\n const resolvedAgentBinding =\n agentOrigin?.kind === \"agent\" ? agentOrigin.binding : agentBinding;\n\n if (!resolvedAgentName || !resolvedAgentBinding) {\n throw new Error(\n \"AgentWorkflow requires a valid Agent origin. Use agent.runWorkflow() to start workflows with proper agent context.\"\n );\n }\n\n // Get the Agent namespace from env\n const namespace = (this.env as Record<string, unknown>)[\n resolvedAgentBinding\n ] as DurableObjectNamespace<AgentType>;\n\n if (!namespace) {\n throw new Error(\n `Agent binding '${resolvedAgentBinding}' not found in environment`\n );\n }\n\n // Get the Agent stub by name\n this._agent = await getAgentByName<Cloudflare.Env, AgentType>(\n namespace,\n resolvedAgentName\n );\n }\n\n private async _initFacetAgent(\n origin: Extract<AgentWorkflowOrigin, { kind: \"facet\" }>\n ): Promise<DurableObjectStub<AgentType>> {\n const root = origin.path[0];\n if (!root) {\n throw new Error(\"AgentWorkflow facet origin requires a non-empty path\");\n }\n\n const namespace = (this.env as Record<string, unknown>)[\n origin.rootBinding\n ] as DurableObjectNamespace<Agent> | undefined;\n\n if (!namespace) {\n throw new Error(\n `Agent binding '${origin.rootBinding}' not found in environment`\n );\n }\n\n const rootAgent = (await getAgentByName<Cloudflare.Env, Agent>(\n namespace,\n root.name\n )) as unknown as AgentPathInvoker;\n\n return new Proxy(\n {},\n {\n get(_target, prop) {\n if (isInternalJsStubProp(prop)) return undefined;\n if (typeof prop !== \"string\") return undefined;\n if (prop === \"fetch\") {\n return () => {\n throw new Error(\n \"AgentWorkflow.agent for sub-agent origins is an RPC-only stub — .fetch() is not supported. Use routeSubAgentRequest() or the /agents/{parent}/{name}/sub/{child}/{name} URL for external HTTP/WS routing.\"\n );\n };\n }\n return async (...args: unknown[]) =>\n rootAgent._cf_invokeAgentPath(origin.path, prop, args);\n }\n }\n ) as DurableObjectStub<AgentType>;\n }\n\n /**\n * Call user workflow code and report unhandled errors to the Agent.\n */\n private async _runWithErrorReporting(\n originalRun: (\n event: WorkflowEvent<Params>,\n step: AgentWorkflowStep\n ) => Promise<unknown>,\n event: WorkflowEvent<Params>,\n step: AgentWorkflowStep\n ): Promise<unknown> {\n try {\n return await originalRun.call(this, event, step);\n } catch (err) {\n await this._autoReportError(err);\n throw err;\n }\n }\n\n /**\n * Dispose the Agent stub owned by this workflow run.\n */\n private _disposeAgent(): void {\n const agent = this._agent;\n this._agent = undefined;\n this.__agentInitCalled = false;\n disposeIfPresent(agent);\n }\n\n /**\n * Wrap WorkflowStep with durable Agent communication methods.\n * Methods added to the wrapped step are idempotent and won't repeat on retry.\n *\n * Note: We add methods directly to the step object to preserve instanceof checks\n * that Cloudflare's runtime may perform on the WorkflowStep class.\n */\n private _wrapStep(step: WorkflowStep): AgentWorkflowStep {\n let stepCounter = 0;\n\n // Cast step to our extended type and add methods directly\n // This preserves the original object identity and instanceof relationship\n const wrappedStep = step as AgentWorkflowStep;\n\n // Add durable Agent methods directly to the step object\n wrappedStep.reportComplete = async <T>(result?: T): Promise<void> => {\n await step.do(`__agent_reportComplete_${stepCounter++}`, async () => {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"complete\",\n result,\n timestamp: Date.now()\n });\n });\n };\n\n wrappedStep.reportError = async (error: Error | string): Promise<void> => {\n const errorMessage = error instanceof Error ? error.message : error;\n this._errorReported = true;\n await step.do(`__agent_reportError_${stepCounter++}`, async () => {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"error\",\n error: errorMessage,\n timestamp: Date.now()\n });\n });\n };\n\n wrappedStep.sendEvent = async <T>(event: T): Promise<void> => {\n await step.do(`__agent_sendEvent_${stepCounter++}`, async () => {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"event\",\n event,\n timestamp: Date.now()\n });\n });\n };\n\n wrappedStep.updateAgentState = async (state: unknown): Promise<void> => {\n await step.do(`__agent_updateState_${stepCounter++}`, async () => {\n await this.agent._workflow_updateState(\"set\", state);\n });\n };\n\n wrappedStep.mergeAgentState = async (\n partialState: Record<string, unknown>\n ): Promise<void> => {\n await step.do(`__agent_mergeState_${stepCounter++}`, async () => {\n await this.agent._workflow_updateState(\"merge\", partialState);\n });\n };\n\n wrappedStep.resetAgentState = async (): Promise<void> => {\n await step.do(`__agent_resetState_${stepCounter++}`, async () => {\n await this.agent._workflow_updateState(\"reset\");\n });\n };\n\n return wrappedStep;\n }\n\n /**\n * Extend the Agent-aware workflow step before user code receives it.\n *\n * Subclasses can override this to add framework-specific step helpers while\n * preserving the underlying WorkflowStep object identity.\n */\n protected extendStep(\n step: AgentWorkflowStep,\n _event: WorkflowEvent<Params>\n ): AgentWorkflowStep {\n return step;\n }\n\n /**\n * Get the Agent stub for RPC calls.\n * Provides typed access to the Agent's methods.\n *\n * @example\n * ```typescript\n * // Call any public method on the Agent\n * await this.agent.updateStatus('processing');\n * const data = await this.agent.getData();\n * ```\n */\n get agent(): DurableObjectStub<AgentType> {\n if (!this._agent) {\n throw new Error(\n \"Agent not initialized. Ensure you're accessing this.agent inside run().\"\n );\n }\n return this._agent;\n }\n\n /**\n * Get the workflow instance ID\n */\n get workflowId(): string {\n return this._workflowId;\n }\n\n /**\n * Get the workflow binding name\n */\n get workflowName(): string {\n return this._workflowName;\n }\n\n /**\n * Automatically report an unhandled error to the Agent.\n * Skipped if reportError() was already called (prevents double notification).\n * Best-effort: notification failures are swallowed so the original error propagates.\n *\n * @param err - The caught error\n */\n private async _autoReportError(err: unknown): Promise<void> {\n if (this._errorReported) {\n return;\n }\n this._errorReported = true;\n const errorMessage = err instanceof Error ? err.message : String(err);\n try {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"error\",\n error: errorMessage,\n timestamp: Date.now()\n });\n } catch (_notifyErr) {\n // Best-effort: don't mask the original error\n }\n }\n\n /**\n * Send a notification to the Agent via RPC.\n *\n * @param callback - Callback payload to send\n */\n protected async notifyAgent(callback: WorkflowCallback): Promise<void> {\n await this.agent._workflow_handleCallback(callback);\n }\n\n /**\n * Report progress to the Agent with typed progress data.\n * Triggers onWorkflowProgress() on the Agent.\n *\n * @param progress - Typed progress data\n *\n * @example\n * ```typescript\n * // Using default progress type\n * await this.reportProgress({ step: 'fetch', status: 'running' });\n * await this.reportProgress({ step: 'fetch', status: 'complete', percent: 0.5 });\n *\n * // With custom progress type\n * await this.reportProgress({ stage: 'extract', recordsProcessed: 100 });\n * ```\n */\n protected async reportProgress(progress: ProgressType): Promise<void> {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"progress\",\n progress: progress as DefaultProgress,\n timestamp: Date.now()\n });\n }\n\n /**\n * Broadcast a message to all connected WebSocket clients via the Agent.\n * This is non-durable and may repeat on workflow retry.\n *\n * @param message - Message to broadcast (will be JSON-stringified)\n */\n protected broadcastToClients(message: unknown): void {\n this.agent._workflow_broadcast(message);\n }\n\n /**\n * Wait for approval from the Agent.\n * Handles rejection by reporting error (durably) and throwing WorkflowRejectedError.\n *\n * @param step - AgentWorkflowStep object\n * @param options - Wait options (timeout, eventType, stepName)\n * @returns Approval payload (throws WorkflowRejectedError if rejected)\n *\n * @example\n * ```typescript\n * const approval = await this.waitForApproval(step, { timeout: '7 days' });\n * // approval contains the payload from approveWorkflow()\n * ```\n */\n protected async waitForApproval<T = unknown>(\n step: AgentWorkflowStep,\n options?: WaitForApprovalOptions\n ): Promise<T> {\n const stepName = options?.stepName ?? \"wait-for-approval\";\n const eventType = options?.eventType ?? \"approval\";\n const timeout = options?.timeout;\n\n // Wait for the approval event\n // Note: Call reportProgress() before this method if you want to update progress\n const event = (await step.waitForEvent(stepName, {\n type: eventType,\n timeout\n })) as WorkflowStepEvent<{\n approved: boolean;\n reason?: string;\n metadata?: T;\n }>;\n\n try {\n const payload = event.payload;\n\n // Check if rejected\n if (!payload.approved) {\n const reason = payload.reason;\n await step.reportError(reason ?? \"Workflow rejected\");\n throw new WorkflowRejectedError(reason, this._workflowId);\n }\n\n // Return the approval metadata as the result\n return payload.metadata as T;\n } finally {\n disposeIfPresent(event);\n }\n }\n}\n\ntype DisposableResource = {\n [Symbol.dispose](): void;\n};\n\nfunction isDisposableResource(value: unknown): value is DisposableResource {\n return (\n !!value &&\n typeof value === \"object\" &&\n Symbol.dispose in value &&\n typeof value[Symbol.dispose] === \"function\"\n );\n}\n\nfunction disposeIfPresent(value: unknown): void {\n if (isDisposableResource(value)) {\n value[Symbol.dispose]();\n }\n}\n\n// Re-export types for convenience\nexport type {\n AgentWorkflowEvent,\n AgentWorkflowStep,\n WorkflowCallback,\n WorkflowCallbackType,\n WorkflowProgressCallback,\n WorkflowCompleteCallback,\n WorkflowErrorCallback,\n WorkflowEventCallback,\n DefaultProgress,\n WaitForApprovalOptions,\n ApprovalEventPayload,\n WorkflowStatus,\n WorkflowTrackingRow,\n RunWorkflowOptions,\n WorkflowEventPayload,\n WorkflowInfo,\n WorkflowQueryCriteria,\n WorkflowPage\n} from \"./workflow-types\";\n\nexport { WorkflowRejectedError } from \"./workflow-types\";\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"workflows.js","names":[],"sources":["../src/workflows.ts"],"sourcesContent":["/**\n * AgentWorkflow - Base class for Workflows that integrate with Agents\n *\n * Extends Cloudflare's WorkflowEntrypoint to provide seamless access to\n * the Agent that started the workflow, enabling bidirectional communication.\n *\n * @example\n * ```typescript\n * import { AgentWorkflow } from 'agents/workflows';\n * import type { MyAgent } from './agent';\n *\n * type TaskParams = { taskId: string; data: string };\n *\n * export class ProcessingWorkflow extends AgentWorkflow<MyAgent, TaskParams> {\n * async run(event: AgentWorkflowEvent<TaskParams>, step: WorkflowStep) {\n * // Access the originating Agent via typed RPC\n * await this.agent.updateTaskStatus(event.payload.taskId, 'processing');\n *\n * const result = await step.do('process', async () => {\n * // ... processing logic\n * return { processed: true };\n * });\n *\n * // Report progress to Agent (typed)\n * await this.reportProgress({ step: 'process', status: 'complete', percent: 0.5 });\n *\n * // Broadcast to connected clients\n * await this.broadcastToClients({ type: 'progress', data: result });\n *\n * return result;\n * }\n * }\n * ```\n */\n\nimport { WorkflowEntrypoint } from \"cloudflare:workers\";\nimport type {\n WorkflowEvent,\n WorkflowStep,\n WorkflowStepEvent\n} from \"cloudflare:workers\";\nimport { getAgentByName, type Agent } from \"./index\";\nimport type {\n AgentWorkflowParams,\n AgentWorkflowStep,\n WorkflowCallback,\n DefaultProgress,\n WaitForApprovalOptions\n} from \"./workflow-types\";\nimport { WorkflowRejectedError } from \"./workflow-types\";\nimport type {\n AgentWorkflowOrigin,\n AgentWorkflowPathStep\n} from \"./workflow-types\";\nimport { isInternalJsStubProp } from \"./utils\";\n\ntype AgentPathInvoker = {\n _cf_invokeAgentPath(\n path: ReadonlyArray<AgentWorkflowPathStep>,\n method: string,\n args: unknown[]\n ): Promise<unknown>;\n};\n\n/**\n * WeakSet to track which prototypes have been wrapped.\n * This prevents re-wrapping on subsequent instantiations of the same class.\n */\nconst wrappedPrototypes = new WeakSet<object>();\n\n/**\n * Base class for Workflows that need access to their originating Agent.\n *\n * @template AgentType - The Agent class type (for typed RPC access)\n * @template Params - User-defined params passed to the workflow (optional)\n * @template ProgressType - Type for progress reporting (defaults to DefaultProgress)\n * @template Env - Environment type (defaults to Cloudflare.Env)\n */\nexport class AgentWorkflow<\n AgentType extends Agent = Agent,\n Params = unknown,\n ProgressType = DefaultProgress,\n Env extends Cloudflare.Env = Cloudflare.Env\n> extends WorkflowEntrypoint<Env, AgentWorkflowParams<Params>> {\n /**\n * The Agent stub - initialized before run() is called.\n * Use this.agent to access the Agent's RPC methods.\n */\n private _agent?: DurableObjectStub<AgentType>;\n\n /**\n * Workflow instance ID\n */\n private _workflowId!: string;\n\n /**\n * Workflow binding name (for callbacks)\n */\n private _workflowName!: string;\n\n /**\n * Instance-level guard to prevent double initialization.\n * Used when a subclass calls super.run() after its own run() was wrapped.\n */\n private __agentInitCalled = false;\n\n /**\n * Guard to prevent double error notification.\n * Set to true when reportError() is called explicitly, so the automatic\n * error catch in the run() wrapper doesn't send a duplicate notification.\n */\n private _errorReported = false;\n\n constructor(ctx: ExecutionContext, env: Env) {\n super(ctx, env);\n\n const proto = Object.getPrototypeOf(this);\n\n // Only wrap if:\n // 1. This prototype defines its own run method (hasOwnProperty)\n // 2. It hasn't been wrapped yet (WeakSet check)\n // This prevents double-wrapping inherited methods and ensures each subclass\n // that defines run() gets wrapped exactly once.\n if (Object.hasOwn(proto, \"run\") && !wrappedPrototypes.has(proto)) {\n const originalRun = proto.run as (\n event: WorkflowEvent<Params>,\n step: AgentWorkflowStep\n ) => Promise<unknown>;\n\n // Replace the prototype's run method with a wrapper that initializes\n // the agent before calling the user's implementation\n proto.run = async function (\n this: AgentWorkflow<AgentType, Params, ProgressType, Env>,\n event: WorkflowEvent<AgentWorkflowParams<Params>>,\n step: WorkflowStep\n ) {\n // Instance-level guard: only init once per instance\n // (prevents double init if super.run() is called from a subclass)\n if (!this.__agentInitCalled) {\n const {\n __agentName,\n __agentBinding,\n __workflowName,\n __agentOrigin,\n ...userParams\n } = event.payload;\n\n // Initialize agent connection\n await this._initAgent(\n __agentName,\n __agentBinding,\n __workflowName,\n __agentOrigin,\n event.instanceId\n );\n this.__agentInitCalled = true;\n\n try {\n // Pass cleaned event and wrapped step to user's implementation\n const cleanedEvent = {\n ...event,\n payload: userParams as Params\n } as WorkflowEvent<Params>;\n\n const wrappedStep = this.extendStep(\n this._wrapStep(step),\n cleanedEvent\n );\n\n return await this._runWithErrorReporting(\n originalRun,\n cleanedEvent,\n wrappedStep\n );\n } finally {\n this._disposeAgent();\n }\n }\n\n // If already initialized (e.g., called via super.run()),\n // just call the original with the event as-is.\n return await this._runWithErrorReporting(\n originalRun,\n event as WorkflowEvent<Params>,\n step as AgentWorkflowStep\n );\n };\n\n wrappedPrototypes.add(proto);\n }\n }\n\n /**\n * Initialize the Agent stub from workflow params.\n * Called automatically before run() executes.\n */\n private async _initAgent(\n agentName: string | undefined,\n agentBinding: string | undefined,\n workflowName: string | undefined,\n agentOrigin: AgentWorkflowOrigin | undefined,\n instanceId: string\n ): Promise<void> {\n if (!workflowName || (!agentOrigin && (!agentName || !agentBinding))) {\n throw new Error(\n \"AgentWorkflow requires __agentName, __agentBinding, and __workflowName in params. \" +\n \"Use agent.runWorkflow() to start workflows with proper agent context.\"\n );\n }\n\n this._workflowId = instanceId;\n this._workflowName = workflowName;\n this._errorReported = false;\n\n // The origin payload is durably persisted in workflow params, so a workflow\n // started by an older SDK can resume against newer code (and vice versa).\n // Reject origin versions this build does not understand rather than\n // silently misreading a future shape.\n if (agentOrigin && agentOrigin.version !== 1) {\n throw new Error(\n `AgentWorkflow received an unsupported origin version (${\n (agentOrigin as { version?: unknown }).version\n }). Upgrade the \"agents\" package running this Workflow to match the Agent that started it.`\n );\n }\n\n if (agentOrigin?.kind === \"facet\") {\n this._agent = await this._initFacetAgent(agentOrigin);\n return;\n }\n\n const resolvedAgentName =\n agentOrigin?.kind === \"agent\" ? agentOrigin.name : agentName;\n const resolvedAgentBinding =\n agentOrigin?.kind === \"agent\" ? agentOrigin.binding : agentBinding;\n\n if (!resolvedAgentName || !resolvedAgentBinding) {\n throw new Error(\n \"AgentWorkflow requires a valid Agent origin. Use agent.runWorkflow() to start workflows with proper agent context.\"\n );\n }\n\n // Get the Agent namespace from env\n const namespace = (this.env as Record<string, unknown>)[\n resolvedAgentBinding\n ] as DurableObjectNamespace<AgentType>;\n\n if (!namespace) {\n throw new Error(\n `Agent binding '${resolvedAgentBinding}' not found in environment`\n );\n }\n\n // Get the Agent stub by name\n this._agent = await getAgentByName<Cloudflare.Env, AgentType>(\n namespace,\n resolvedAgentName\n );\n }\n\n private async _initFacetAgent(\n origin: Extract<AgentWorkflowOrigin, { kind: \"facet\" }>\n ): Promise<DurableObjectStub<AgentType>> {\n const root = origin.path[0];\n if (!root) {\n throw new Error(\"AgentWorkflow facet origin requires a non-empty path\");\n }\n\n const namespace = (this.env as Record<string, unknown>)[\n origin.rootBinding\n ] as DurableObjectNamespace<Agent> | undefined;\n\n if (!namespace) {\n throw new Error(\n `Agent binding '${origin.rootBinding}' not found in environment`\n );\n }\n\n const rootAgent = (await getAgentByName<Cloudflare.Env, Agent>(\n namespace,\n root.name\n )) as unknown as AgentPathInvoker;\n\n return new Proxy(\n {},\n {\n get(_target, prop) {\n if (isInternalJsStubProp(prop)) return undefined;\n if (typeof prop !== \"string\") return undefined;\n if (prop === \"fetch\") {\n return () => {\n throw new Error(\n \"AgentWorkflow.agent for sub-agent origins is an RPC-only stub — .fetch() is not supported. Use routeSubAgentRequest() or the /agents/{parent}/{name}/sub/{child}/{name} URL for external HTTP/WS routing.\"\n );\n };\n }\n return async (...args: unknown[]) =>\n rootAgent._cf_invokeAgentPath(origin.path, prop, args);\n }\n }\n ) as DurableObjectStub<AgentType>;\n }\n\n /**\n * Call user workflow code and report unhandled errors to the Agent.\n */\n private async _runWithErrorReporting(\n originalRun: (\n event: WorkflowEvent<Params>,\n step: AgentWorkflowStep\n ) => Promise<unknown>,\n event: WorkflowEvent<Params>,\n step: AgentWorkflowStep\n ): Promise<unknown> {\n try {\n return await originalRun.call(this, event, step);\n } catch (err) {\n await this._autoReportError(err);\n throw err;\n }\n }\n\n /**\n * Dispose the Agent stub owned by this workflow run.\n */\n private _disposeAgent(): void {\n const agent = this._agent;\n this._agent = undefined;\n this.__agentInitCalled = false;\n disposeIfPresent(agent);\n }\n\n /**\n * Wrap WorkflowStep with durable Agent communication methods.\n * Methods added to the wrapped step are idempotent and won't repeat on retry.\n *\n * Note: We add methods directly to the step object to preserve instanceof checks\n * that Cloudflare's runtime may perform on the WorkflowStep class.\n */\n private _wrapStep(step: WorkflowStep): AgentWorkflowStep {\n let stepCounter = 0;\n\n // Cast step to our extended type and add methods directly\n // This preserves the original object identity and instanceof relationship\n const wrappedStep = step as AgentWorkflowStep;\n\n // Add durable Agent methods directly to the step object\n wrappedStep.reportComplete = async <T>(result?: T): Promise<void> => {\n await step.do(`__agent_reportComplete_${stepCounter++}`, async () => {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"complete\",\n result,\n timestamp: Date.now()\n });\n });\n };\n\n wrappedStep.reportError = async (error: Error | string): Promise<void> => {\n const errorMessage = error instanceof Error ? error.message : error;\n this._errorReported = true;\n await step.do(`__agent_reportError_${stepCounter++}`, async () => {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"error\",\n error: errorMessage,\n timestamp: Date.now()\n });\n });\n };\n\n wrappedStep.sendEvent = async <T>(event: T): Promise<void> => {\n await step.do(`__agent_sendEvent_${stepCounter++}`, async () => {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"event\",\n event,\n timestamp: Date.now()\n });\n });\n };\n\n wrappedStep.updateAgentState = async (state: unknown): Promise<void> => {\n await step.do(`__agent_updateState_${stepCounter++}`, async () => {\n await this.agent._workflow_updateState(\"set\", state);\n });\n };\n\n wrappedStep.mergeAgentState = async (\n partialState: Record<string, unknown>\n ): Promise<void> => {\n await step.do(`__agent_mergeState_${stepCounter++}`, async () => {\n await this.agent._workflow_updateState(\"merge\", partialState);\n });\n };\n\n wrappedStep.resetAgentState = async (): Promise<void> => {\n await step.do(`__agent_resetState_${stepCounter++}`, async () => {\n await this.agent._workflow_updateState(\"reset\");\n });\n };\n\n return wrappedStep;\n }\n\n /**\n * Extend the Agent-aware workflow step before user code receives it.\n *\n * Subclasses can override this to add framework-specific step helpers while\n * preserving the underlying WorkflowStep object identity.\n */\n protected extendStep(\n step: AgentWorkflowStep,\n _event: WorkflowEvent<Params>\n ): AgentWorkflowStep {\n return step;\n }\n\n /**\n * Get the Agent stub for RPC calls.\n * Provides typed access to the Agent's methods.\n *\n * @example\n * ```typescript\n * // Call any public method on the Agent\n * await this.agent.updateStatus('processing');\n * const data = await this.agent.getData();\n * ```\n */\n get agent(): DurableObjectStub<AgentType> {\n if (!this._agent) {\n throw new Error(\n \"Agent not initialized. Ensure you're accessing this.agent inside run().\"\n );\n }\n return this._agent;\n }\n\n /**\n * Get the workflow instance ID\n */\n get workflowId(): string {\n return this._workflowId;\n }\n\n /**\n * Get the workflow binding name\n */\n get workflowName(): string {\n return this._workflowName;\n }\n\n /**\n * Automatically report an unhandled error to the Agent.\n * Skipped if reportError() was already called (prevents double notification).\n * Best-effort: notification failures are swallowed so the original error propagates.\n *\n * @param err - The caught error\n */\n private async _autoReportError(err: unknown): Promise<void> {\n if (this._errorReported) {\n return;\n }\n this._errorReported = true;\n const errorMessage = err instanceof Error ? err.message : String(err);\n try {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"error\",\n error: errorMessage,\n timestamp: Date.now()\n });\n } catch (_notifyErr) {\n // Best-effort: don't mask the original error\n }\n }\n\n /**\n * Send a notification to the Agent via RPC.\n *\n * @param callback - Callback payload to send\n */\n protected async notifyAgent(callback: WorkflowCallback): Promise<void> {\n await this.agent._workflow_handleCallback(callback);\n }\n\n /**\n * Report progress to the Agent with typed progress data.\n * Triggers onWorkflowProgress() on the Agent.\n *\n * @param progress - Typed progress data\n *\n * @example\n * ```typescript\n * // Using default progress type\n * await this.reportProgress({ step: 'fetch', status: 'running' });\n * await this.reportProgress({ step: 'fetch', status: 'complete', percent: 0.5 });\n *\n * // With custom progress type\n * await this.reportProgress({ stage: 'extract', recordsProcessed: 100 });\n * ```\n */\n protected async reportProgress(progress: ProgressType): Promise<void> {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"progress\",\n progress: progress as DefaultProgress,\n timestamp: Date.now()\n });\n }\n\n /**\n * Broadcast a message to all connected WebSocket clients via the Agent.\n * This is non-durable and may repeat on workflow retry.\n *\n * @param message - Message to broadcast (will be JSON-stringified)\n */\n protected broadcastToClients(message: unknown): void {\n this.agent._workflow_broadcast(message);\n }\n\n /**\n * Wait for approval from the Agent.\n * Handles rejection by reporting error (durably) and throwing WorkflowRejectedError.\n *\n * @param step - AgentWorkflowStep object\n * @param options - Wait options (timeout, eventType, stepName)\n * @returns Approval payload (throws WorkflowRejectedError if rejected)\n *\n * @example\n * ```typescript\n * const approval = await this.waitForApproval(step, { timeout: '7 days' });\n * // approval contains the payload from approveWorkflow()\n * ```\n */\n protected async waitForApproval<T = unknown>(\n step: AgentWorkflowStep,\n options?: WaitForApprovalOptions\n ): Promise<T> {\n const stepName = options?.stepName ?? \"wait-for-approval\";\n const eventType = options?.eventType ?? \"approval\";\n const timeout = options?.timeout;\n\n // Wait for the approval event\n // Note: Call reportProgress() before this method if you want to update progress\n const event = (await step.waitForEvent(stepName, {\n type: eventType,\n timeout\n })) as WorkflowStepEvent<{\n approved: boolean;\n reason?: string;\n metadata?: T;\n }>;\n\n try {\n const payload = event.payload;\n\n // Check if rejected\n if (!payload.approved) {\n const reason = payload.reason;\n await step.reportError(reason ?? \"Workflow rejected\");\n throw new WorkflowRejectedError(reason, this._workflowId);\n }\n\n // Return the approval metadata as the result\n return payload.metadata as T;\n } finally {\n disposeIfPresent(event);\n }\n }\n}\n\ntype DisposableResource = {\n [Symbol.dispose](): void;\n};\n\nfunction isDisposableResource(value: unknown): value is DisposableResource {\n return (\n !!value &&\n typeof value === \"object\" &&\n Symbol.dispose in value &&\n typeof value[Symbol.dispose] === \"function\"\n );\n}\n\nfunction disposeIfPresent(value: unknown): void {\n if (isDisposableResource(value)) {\n value[Symbol.dispose]();\n }\n}\n\n// Re-export types for convenience\nexport type {\n AgentWorkflowEvent,\n AgentWorkflowStep,\n WorkflowCallback,\n WorkflowCallbackType,\n WorkflowProgressCallback,\n WorkflowCompleteCallback,\n WorkflowErrorCallback,\n WorkflowEventCallback,\n DefaultProgress,\n WaitForApprovalOptions,\n ApprovalEventPayload,\n WorkflowStatus,\n WorkflowTrackingRow,\n RunWorkflowOptions,\n WorkflowEventPayload,\n WorkflowInfo,\n WorkflowQueryCriteria,\n WorkflowPage\n} from \"./workflow-types\";\n\nexport { WorkflowRejectedError } from \"./workflow-types\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoEA,MAAM,oCAAoB,IAAI,QAAgB;;;;;;;;;AAU9C,IAAa,gBAAb,cAKU,mBAAqD;CA8B7D,YAAY,KAAuB,KAAU;EAC3C,MAAM,KAAK,GAAG;EAVhB,KAAQ,oBAAoB;EAO5B,KAAQ,iBAAiB;EAKvB,MAAM,QAAQ,OAAO,eAAe,IAAI;EAOxC,IAAI,OAAO,OAAO,OAAO,KAAK,KAAK,CAAC,kBAAkB,IAAI,KAAK,GAAG;GAChE,MAAM,cAAc,MAAM;GAO1B,MAAM,MAAM,eAEV,OACA,MACA;IAGA,IAAI,CAAC,KAAK,mBAAmB;KAC3B,MAAM,EACJ,aACA,gBACA,gBACA,eACA,GAAG,eACD,MAAM;KAGV,MAAM,KAAK,WACT,aACA,gBACA,gBACA,eACA,MAAM,UACR;KACA,KAAK,oBAAoB;KAEzB,IAAI;MAEF,MAAM,eAAe;OACnB,GAAG;OACH,SAAS;MACX;MAEA,MAAM,cAAc,KAAK,WACvB,KAAK,UAAU,IAAI,GACnB,YACF;MAEA,OAAO,MAAM,KAAK,uBAChB,aACA,cACA,WACF;KACF,UAAU;MACR,KAAK,cAAc;KACrB;IACF;IAIA,OAAO,MAAM,KAAK,uBAChB,aACA,OACA,IACF;GACF;GAEA,kBAAkB,IAAI,KAAK;EAC7B;CACF;;;;;CAMA,MAAc,WACZ,WACA,cACA,cACA,aACA,YACe;EACf,IAAI,CAAC,gBAAiB,CAAC,gBAAgB,CAAC,aAAa,CAAC,eACpD,MAAM,IAAI,MACR,yJAEF;EAGF,KAAK,cAAc;EACnB,KAAK,gBAAgB;EACrB,KAAK,iBAAiB;EAMtB,IAAI,eAAe,YAAY,YAAY,GACzC,MAAM,IAAI,MACR,yDACG,YAAsC,QACxC,0FACH;EAGF,IAAI,aAAa,SAAS,SAAS;GACjC,KAAK,SAAS,MAAM,KAAK,gBAAgB,WAAW;GACpD;EACF;EAEA,MAAM,oBACJ,aAAa,SAAS,UAAU,YAAY,OAAO;EACrD,MAAM,uBACJ,aAAa,SAAS,UAAU,YAAY,UAAU;EAExD,IAAI,CAAC,qBAAqB,CAAC,sBACzB,MAAM,IAAI,MACR,oHACF;EAIF,MAAM,YAAa,KAAK,IACtB;EAGF,IAAI,CAAC,WACH,MAAM,IAAI,MACR,kBAAkB,qBAAqB,2BACzC;EAIF,KAAK,SAAS,MAAM,eAClB,WACA,iBACF;CACF;CAEA,MAAc,gBACZ,QACuC;EACvC,MAAM,OAAO,OAAO,KAAK;EACzB,IAAI,CAAC,MACH,MAAM,IAAI,MAAM,sDAAsD;EAGxE,MAAM,YAAa,KAAK,IACtB,OAAO;EAGT,IAAI,CAAC,WACH,MAAM,IAAI,MACR,kBAAkB,OAAO,YAAY,2BACvC;EAGF,MAAM,YAAa,MAAM,eACvB,WACA,KAAK,IACP;EAEA,OAAO,IAAI,MACT,CAAC,GACD,EACE,IAAI,SAAS,MAAM;GACjB,IAAI,qBAAqB,IAAI,GAAG,OAAO,KAAA;GACvC,IAAI,OAAO,SAAS,UAAU,OAAO,KAAA;GACrC,IAAI,SAAS,SACX,aAAa;IACX,MAAM,IAAI,MACR,2MACF;GACF;GAEF,OAAO,OAAO,GAAG,SACf,UAAU,oBAAoB,OAAO,MAAM,MAAM,IAAI;EACzD,EACF,CACF;CACF;;;;CAKA,MAAc,uBACZ,aAIA,OACA,MACkB;EAClB,IAAI;GACF,OAAO,MAAM,YAAY,KAAK,MAAM,OAAO,IAAI;EACjD,SAAS,KAAK;GACZ,MAAM,KAAK,iBAAiB,GAAG;GAC/B,MAAM;EACR;CACF;;;;CAKA,gBAA8B;EAC5B,MAAM,QAAQ,KAAK;EACnB,KAAK,SAAS,KAAA;EACd,KAAK,oBAAoB;EACzB,iBAAiB,KAAK;CACxB;;;;;;;;CASA,UAAkB,MAAuC;EACvD,IAAI,cAAc;EAIlB,MAAM,cAAc;EAGpB,YAAY,iBAAiB,OAAU,WAA8B;GACnE,MAAM,KAAK,GAAG,0BAA0B,iBAAiB,YAAY;IACnE,MAAM,KAAK,YAAY;KACrB,cAAc,KAAK;KACnB,YAAY,KAAK;KACjB,MAAM;KACN;KACA,WAAW,KAAK,IAAI;IACtB,CAAC;GACH,CAAC;EACH;EAEA,YAAY,cAAc,OAAO,UAAyC;GACxE,MAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;GAC9D,KAAK,iBAAiB;GACtB,MAAM,KAAK,GAAG,uBAAuB,iBAAiB,YAAY;IAChE,MAAM,KAAK,YAAY;KACrB,cAAc,KAAK;KACnB,YAAY,KAAK;KACjB,MAAM;KACN,OAAO;KACP,WAAW,KAAK,IAAI;IACtB,CAAC;GACH,CAAC;EACH;EAEA,YAAY,YAAY,OAAU,UAA4B;GAC5D,MAAM,KAAK,GAAG,qBAAqB,iBAAiB,YAAY;IAC9D,MAAM,KAAK,YAAY;KACrB,cAAc,KAAK;KACnB,YAAY,KAAK;KACjB,MAAM;KACN;KACA,WAAW,KAAK,IAAI;IACtB,CAAC;GACH,CAAC;EACH;EAEA,YAAY,mBAAmB,OAAO,UAAkC;GACtE,MAAM,KAAK,GAAG,uBAAuB,iBAAiB,YAAY;IAChE,MAAM,KAAK,MAAM,sBAAsB,OAAO,KAAK;GACrD,CAAC;EACH;EAEA,YAAY,kBAAkB,OAC5B,iBACkB;GAClB,MAAM,KAAK,GAAG,sBAAsB,iBAAiB,YAAY;IAC/D,MAAM,KAAK,MAAM,sBAAsB,SAAS,YAAY;GAC9D,CAAC;EACH;EAEA,YAAY,kBAAkB,YAA2B;GACvD,MAAM,KAAK,GAAG,sBAAsB,iBAAiB,YAAY;IAC/D,MAAM,KAAK,MAAM,sBAAsB,OAAO;GAChD,CAAC;EACH;EAEA,OAAO;CACT;;;;;;;CAQA,WACE,MACA,QACmB;EACnB,OAAO;CACT;;;;;;;;;;;;CAaA,IAAI,QAAsC;EACxC,IAAI,CAAC,KAAK,QACR,MAAM,IAAI,MACR,yEACF;EAEF,OAAO,KAAK;CACd;;;;CAKA,IAAI,aAAqB;EACvB,OAAO,KAAK;CACd;;;;CAKA,IAAI,eAAuB;EACzB,OAAO,KAAK;CACd;;;;;;;;CASA,MAAc,iBAAiB,KAA6B;EAC1D,IAAI,KAAK,gBACP;EAEF,KAAK,iBAAiB;EACtB,MAAM,eAAe,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;EACpE,IAAI;GACF,MAAM,KAAK,YAAY;IACrB,cAAc,KAAK;IACnB,YAAY,KAAK;IACjB,MAAM;IACN,OAAO;IACP,WAAW,KAAK,IAAI;GACtB,CAAC;EACH,SAAS,YAAY,CAErB;CACF;;;;;;CAOA,MAAgB,YAAY,UAA2C;EACrE,MAAM,KAAK,MAAM,yBAAyB,QAAQ;CACpD;;;;;;;;;;;;;;;;;CAkBA,MAAgB,eAAe,UAAuC;EACpE,MAAM,KAAK,YAAY;GACrB,cAAc,KAAK;GACnB,YAAY,KAAK;GACjB,MAAM;GACI;GACV,WAAW,KAAK,IAAI;EACtB,CAAC;CACH;;;;;;;CAQA,mBAA6B,SAAwB;EACnD,KAAK,MAAM,oBAAoB,OAAO;CACxC;;;;;;;;;;;;;;;CAgBA,MAAgB,gBACd,MACA,SACY;EACZ,MAAM,WAAW,SAAS,YAAY;EACtC,MAAM,YAAY,SAAS,aAAa;EACxC,MAAM,UAAU,SAAS;EAIzB,MAAM,QAAS,MAAM,KAAK,aAAa,UAAU;GAC/C,MAAM;GACN;EACF,CAAC;EAMD,IAAI;GACF,MAAM,UAAU,MAAM;GAGtB,IAAI,CAAC,QAAQ,UAAU;IACrB,MAAM,SAAS,QAAQ;IACvB,MAAM,KAAK,YAAY,UAAU,mBAAmB;IACpD,MAAM,IAAI,sBAAsB,QAAQ,KAAK,WAAW;GAC1D;GAGA,OAAO,QAAQ;EACjB,UAAU;GACR,iBAAiB,KAAK;EACxB;CACF;AACF;AAMA,SAAS,qBAAqB,OAA6C;CACzE,OACE,CAAC,CAAC,SACF,OAAO,UAAU,YACjB,OAAO,WAAW,SAClB,OAAO,MAAM,OAAO,aAAa;AAErC;AAEA,SAAS,iBAAiB,OAAsB;CAC9C,IAAI,qBAAqB,KAAK,GAC5B,MAAM,OAAO,QAAQ,CAAC;AAE1B"}
|