agents 0.22.0 → 0.24.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.
Files changed (215) hide show
  1. package/README.md +20 -1
  2. package/dist/{agent-routing-CnkaHb-v.d.ts → agent-routing-B2XLNMxq.d.ts} +1094 -443
  3. package/dist/agent-routing.d.ts +1 -1
  4. package/dist/agent-tool-types.d.ts +26 -26
  5. package/dist/{agent-tools-C0XJqWzB.d.ts → agent-tools-Dj5Mzlw7.d.ts} +7 -7
  6. package/dist/agent-tools.d.ts +21 -21
  7. package/dist/browser/ai.js +4 -1
  8. package/dist/browser/ai.js.map +1 -1
  9. package/dist/browser/tanstack-ai.js.map +1 -1
  10. package/dist/callable-decorator-DP__HhBA.d.ts +72 -0
  11. package/dist/callable-decorator.d.ts +18 -0
  12. package/dist/callable-decorator.js +71 -0
  13. package/dist/callable-decorator.js.map +1 -0
  14. package/dist/{capability-BjSKYpzg.js → capability-B4WbF81e.js} +2 -1
  15. package/dist/capability-B4WbF81e.js.map +1 -0
  16. package/dist/capability-runner-BUBa6Ake.d.ts +484 -0
  17. package/dist/channel-Bnm4S7T2.d.ts +491 -0
  18. package/dist/channels/ai-sdk.d.ts +46 -0
  19. package/dist/channels/ai-sdk.js +120 -0
  20. package/dist/channels/ai-sdk.js.map +1 -0
  21. package/dist/channels/email.d.ts +95 -0
  22. package/dist/channels/email.js +323 -0
  23. package/dist/channels/email.js.map +1 -0
  24. package/dist/channels/index.d.ts +233 -0
  25. package/dist/channels/index.js +608 -0
  26. package/dist/channels/index.js.map +1 -0
  27. package/dist/channels/slack.d.ts +140 -0
  28. package/dist/channels/slack.js +614 -0
  29. package/dist/channels/slack.js.map +1 -0
  30. package/dist/channels/tanstack-ai.d.ts +39 -0
  31. package/dist/channels/tanstack-ai.js +17 -0
  32. package/dist/channels/tanstack-ai.js.map +1 -0
  33. package/dist/channels/telegram.d.ts +106 -0
  34. package/dist/channels/telegram.js +427 -0
  35. package/dist/channels/telegram.js.map +1 -0
  36. package/dist/channels/voice.d.ts +45 -0
  37. package/dist/channels/voice.js +122 -0
  38. package/dist/channels/voice.js.map +1 -0
  39. package/dist/chat/index.d.ts +2319 -2010
  40. package/dist/chat/index.js +892 -518
  41. package/dist/chat/index.js.map +1 -1
  42. package/dist/chat-sdk/index.d.ts +7 -7
  43. package/dist/chat-sdk/index.js +1 -1
  44. package/dist/client-BxdkCuVy.d.ts +411 -0
  45. package/dist/client-C9DAjZIY.js +518 -0
  46. package/dist/client-C9DAjZIY.js.map +1 -0
  47. package/dist/{client-jagG8a9_.js → client-fyQrLGkD.js} +2 -2
  48. package/dist/{client-jagG8a9_.js.map → client-fyQrLGkD.js.map} +1 -1
  49. package/dist/client.d.ts +27 -283
  50. package/dist/client.js +2 -274
  51. package/dist/context/index.d.ts +216 -0
  52. package/dist/context/index.js +454 -0
  53. package/dist/context/index.js.map +1 -0
  54. package/dist/current-agent-C4w86kcN.d.ts +93 -0
  55. package/dist/current-agent-DhoDkSnH.js.map +1 -1
  56. package/dist/{diagnostics-CaBjfz4J.js → diagnostics-BzvaX2UT.js} +5 -1
  57. package/dist/diagnostics-BzvaX2UT.js.map +1 -0
  58. package/dist/diagnostics-C4jcz3VK.js +360 -0
  59. package/dist/diagnostics-C4jcz3VK.js.map +1 -0
  60. package/dist/durable-object-lifecycle-ei7M7lqB.d.ts +157 -0
  61. package/dist/index-BB0kqhIz.d.ts +101 -0
  62. package/dist/index-BVVgDSdq.d.ts +1 -0
  63. package/dist/index-Dlgtd3Mj.d.ts +78 -0
  64. package/dist/index-XDkuQ7zm.d.ts +89 -0
  65. package/dist/{index-DcSAZKsB.d.ts → index-YSKgfgg9.d.ts} +3 -1
  66. package/dist/index.d.ts +92 -83
  67. package/dist/index.js +4 -3
  68. package/dist/ingress-BfetZbMO.js +83 -0
  69. package/dist/ingress-BfetZbMO.js.map +1 -0
  70. package/dist/internal-CYlgHl1l.js +59 -0
  71. package/dist/internal-CYlgHl1l.js.map +1 -0
  72. package/dist/internal_context.d.ts +1 -1
  73. package/dist/lifecycle/index.d.ts +39 -19
  74. package/dist/lifecycle/index.js +2 -2
  75. package/dist/lifecycle-Mm_jQh7r.js +1314 -0
  76. package/dist/lifecycle-Mm_jQh7r.js.map +1 -0
  77. package/dist/mcp/client/index.d.ts +20 -20
  78. package/dist/mcp/client/index.js +1 -1
  79. package/dist/mcp/index.d.ts +35 -35
  80. package/dist/mcp/index.js +2 -2
  81. package/dist/observability/index.d.ts +1 -1
  82. package/dist/observability/index.js +1 -1
  83. package/dist/queue/index.d.ts +123 -0
  84. package/dist/queue/index.js +2 -0
  85. package/dist/queue-BC9F5cUo.js +406 -0
  86. package/dist/queue-BC9F5cUo.js.map +1 -0
  87. package/dist/react.d.ts +34 -16
  88. package/dist/react.js +31 -8
  89. package/dist/react.js.map +1 -1
  90. package/dist/{retries-CAvxtG9d.d.ts → retries-D9B2UCq3.d.ts} +23 -6
  91. package/dist/retries.d.ts +10 -6
  92. package/dist/retries.js +21 -1
  93. package/dist/retries.js.map +1 -1
  94. package/dist/routing/index.d.ts +137 -0
  95. package/dist/routing/index.js +244 -0
  96. package/dist/routing/index.js.map +1 -0
  97. package/dist/sanitize-D9TujEK8.js +79 -0
  98. package/dist/sanitize-D9TujEK8.js.map +1 -0
  99. package/dist/{scheduler-DQoTGoAW.d.ts → scheduler-BGq6M5Kd.d.ts} +20 -21
  100. package/dist/scheduler-D_KHqxBa.js +658 -0
  101. package/dist/scheduler-D_KHqxBa.js.map +1 -0
  102. package/dist/schedules/index.d.ts +1 -1
  103. package/dist/schedules/index.js +1 -1
  104. package/dist/sentence-chunker-BAidJ4DA.d.ts +68 -0
  105. package/dist/serializable.d.ts +1 -1
  106. package/dist/sessions/index.d.ts +441 -0
  107. package/dist/sessions/index.js +2063 -0
  108. package/dist/sessions/index.js.map +1 -0
  109. package/dist/skills/index.d.ts +99 -0
  110. package/dist/skills/index.js +254 -5
  111. package/dist/skills/index.js.map +1 -1
  112. package/dist/{src-5W6JNKVb.js → src-BNU3ZiJM.js} +1524 -1441
  113. package/dist/src-BNU3ZiJM.js.map +1 -0
  114. package/dist/state/index.d.ts +6 -0
  115. package/dist/state/index.js +137 -0
  116. package/dist/state/index.js.map +1 -0
  117. package/dist/streams/index.d.ts +120 -0
  118. package/dist/streams/index.js +107 -0
  119. package/dist/streams/index.js.map +1 -0
  120. package/dist/streams-BcE8JP2X.d.ts +370 -0
  121. package/dist/streams-CCPRV6dt.js +709 -0
  122. package/dist/streams-CCPRV6dt.js.map +1 -0
  123. package/dist/sub-routing.d.ts +12 -12
  124. package/dist/surface-bZZJqBka.js +17 -0
  125. package/dist/surface-bZZJqBka.js.map +1 -0
  126. package/dist/tasks/index.d.ts +64 -0
  127. package/dist/tasks/index.js +2 -0
  128. package/dist/tasks-D4nLqVSI.js +1656 -0
  129. package/dist/tasks-D4nLqVSI.js.map +1 -0
  130. package/dist/tasks-V2lCT8ZV.d.ts +517 -0
  131. package/dist/text-segment-joiner-BtAFQSA_.js +57 -0
  132. package/dist/text-segment-joiner-BtAFQSA_.js.map +1 -0
  133. package/dist/text-stream-CpdiKrJB.js +272 -0
  134. package/dist/text-stream-CpdiKrJB.js.map +1 -0
  135. package/dist/tokens-nHAKcN6M.js +52 -0
  136. package/dist/tokens-nHAKcN6M.js.map +1 -0
  137. package/dist/tool-schema-CBjGPrsQ.js +31 -0
  138. package/dist/tool-schema-CBjGPrsQ.js.map +1 -0
  139. package/dist/transport-protocol-BxyngQ_R.js +25 -0
  140. package/dist/transport-protocol-BxyngQ_R.js.map +1 -0
  141. package/dist/transport-protocol-ZTew5Wso.d.ts +27 -0
  142. package/dist/types-B7LojTe4.d.ts +202 -0
  143. package/dist/types-DCD6BNZH.d.ts +70 -0
  144. package/dist/types-_Faxb570.d.ts +439 -0
  145. package/dist/voice/client.d.ts +226 -0
  146. package/dist/voice/client.js +932 -0
  147. package/dist/voice/client.js.map +1 -0
  148. package/dist/voice/errors.d.ts +43 -0
  149. package/dist/voice/errors.js +41 -0
  150. package/dist/voice/errors.js.map +1 -0
  151. package/dist/voice/index.d.ts +271 -0
  152. package/dist/voice/index.js +1812 -0
  153. package/dist/voice/index.js.map +1 -0
  154. package/dist/voice/react.d.ts +167 -0
  155. package/dist/voice/react.js +234 -0
  156. package/dist/voice/react.js.map +1 -0
  157. package/dist/voice/sfu.d.ts +71 -0
  158. package/dist/voice/sfu.js +157 -0
  159. package/dist/voice/sfu.js.map +1 -0
  160. package/dist/voice/text.d.ts +6 -0
  161. package/dist/voice/text.js +2 -0
  162. package/dist/voice/types.d.ts +58 -0
  163. package/dist/voice/types.js +18 -0
  164. package/dist/voice/types.js.map +1 -0
  165. package/dist/voice/workers-ai.d.ts +136 -0
  166. package/dist/voice/workers-ai.js +568 -0
  167. package/dist/voice/workers-ai.js.map +1 -0
  168. package/dist/websockets/index.d.ts +301 -0
  169. package/dist/websockets/index.js +3 -0
  170. package/dist/websockets-D7IzWbZb.js +1005 -0
  171. package/dist/websockets-D7IzWbZb.js.map +1 -0
  172. package/dist/workflow-types.d.ts +25 -25
  173. package/dist/workflows.d.ts +21 -21
  174. package/dist/workflows.js +1 -1
  175. package/docs/agent-class.md +4 -4
  176. package/docs/agent-tools.md +2 -1
  177. package/docs/channels.md +323 -0
  178. package/docs/chat-agents.md +6 -13
  179. package/docs/client-sdk.md +30 -0
  180. package/docs/context.md +131 -0
  181. package/docs/index.md +16 -13
  182. package/docs/lifecycle.md +179 -57
  183. package/docs/long-running-agents.md +2 -2
  184. package/docs/mcp-servers.md +5 -1
  185. package/docs/queue.md +135 -241
  186. package/docs/resumable-streaming.md +1 -1
  187. package/docs/retries.md +1 -1
  188. package/docs/routing.md +105 -0
  189. package/docs/sessions.md +237 -871
  190. package/docs/streams.md +213 -0
  191. package/docs/sub-agents.md +184 -124
  192. package/docs/tasks.md +246 -0
  193. package/docs/voice.md +745 -0
  194. package/package.json +126 -14
  195. package/dist/capability-BjSKYpzg.js.map +0 -1
  196. package/dist/capability-runner-CvHGZqUu.d.ts +0 -150
  197. package/dist/client.js.map +0 -1
  198. package/dist/compaction-helpers-iiKMr2TQ.js +0 -340
  199. package/dist/compaction-helpers-iiKMr2TQ.js.map +0 -1
  200. package/dist/compaction-helpers-wUz6M3us.d.ts +0 -621
  201. package/dist/current-agent-CuMErtly.d.ts +0 -283
  202. package/dist/diagnostics-CaBjfz4J.js.map +0 -1
  203. package/dist/durable-object-lifecycle-D6nNQJJd.js +0 -862
  204. package/dist/durable-object-lifecycle-D6nNQJJd.js.map +0 -1
  205. package/dist/experimental/memory/session/index.d.ts +0 -671
  206. package/dist/experimental/memory/session/index.js +0 -2379
  207. package/dist/experimental/memory/session/index.js.map +0 -1
  208. package/dist/experimental/memory/utils/index.d.ts +0 -96
  209. package/dist/experimental/memory/utils/index.js +0 -79
  210. package/dist/experimental/memory/utils/index.js.map +0 -1
  211. package/dist/scheduler-CR9RHGos.js +0 -857
  212. package/dist/scheduler-CR9RHGos.js.map +0 -1
  213. package/dist/src-5W6JNKVb.js.map +0 -1
  214. package/dist/tool-output-truncation-CNnnGZQ3.js +0 -98
  215. package/dist/tool-output-truncation-CNnnGZQ3.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workers-ai.js","names":[],"sources":["../../src/voice/workers-ai.ts"],"sourcesContent":["/**\n * Workers AI provider implementations for the voice pipeline.\n *\n * These are convenience classes that wrap the Workers AI binding\n * (env.AI) for STT and TTS. They are not required — any object\n * satisfying the provider interfaces works.\n */\n\nimport { logVoiceError, toVoiceError, VoiceProviderError } from \"./errors\";\nimport type {\n TTSProvider,\n Transcriber,\n TranscriberSession,\n TranscriberSessionOptions\n} from \"./types\";\n\n// --- Loose AI binding type ---\n\n/** Loose type for the Workers AI binding — avoids hard dependency on @cloudflare/workers-types. */\ninterface AiLike {\n run(\n model: string,\n input: Record<string, unknown>,\n options?: Record<string, unknown>\n ): Promise<unknown>;\n}\n\n// --- TTS ---\n\nexport interface WorkersAITTSOptions {\n /** TTS model name. @default \"@cf/deepgram/aura-1\" */\n model?: string;\n /** TTS speaker voice. @default \"asteria\" */\n speaker?: string;\n}\n\n/**\n * Workers AI text-to-speech provider.\n *\n * @example\n * ```ts\n * class MyAgent extends VoiceAgent<Env> {\n * tts = new WorkersAITTS(this.env.AI);\n * }\n * ```\n */\nexport class WorkersAITTS implements TTSProvider {\n #ai: AiLike;\n #model: string;\n #speaker: string;\n\n constructor(ai: AiLike, options?: WorkersAITTSOptions) {\n this.#ai = ai;\n this.#model = options?.model ?? \"@cf/deepgram/aura-1\";\n this.#speaker = options?.speaker ?? \"asteria\";\n }\n\n async synthesize(\n text: string,\n signal?: AbortSignal\n ): Promise<ArrayBuffer | null> {\n const response = (await this.#ai.run(\n this.#model,\n { text, speaker: this.#speaker },\n { returnRawResponse: true, ...(signal ? { signal } : {}) }\n )) as Response;\n\n // Without this check an error body (e.g. a 429 quota JSON) would be\n // forwarded to the client as audio bytes and fail to decode silently.\n if (!response.ok) {\n logVoiceError({\n component: \"WorkersAITTS\",\n stage: \"synthesize\",\n message: \"Workers AI TTS request failed\",\n error: new VoiceProviderError(\"Workers AI TTS request failed\", {\n status: response.status\n })\n });\n return null;\n }\n\n return await response.arrayBuffer();\n }\n}\n\n// --- Flux continuous STT ---\n\nexport interface WorkersAIFluxSTTOptions {\n /** End-of-turn confidence threshold (0.5-0.9). @default 0.7 */\n eotThreshold?: number;\n /**\n * Eager end-of-turn threshold (0.3-0.9). When set, enables\n * EagerEndOfTurn and TurnResumed events for speculative processing.\n */\n eagerEotThreshold?: number;\n /** EOT timeout in milliseconds. @default 5000 */\n eotTimeoutMs?: number;\n /** Keyterms to boost recognition of specialized terminology. */\n keyterms?: string[];\n /** Sample rate in Hz. @default 16000 */\n sampleRate?: number;\n}\n\n/**\n * Workers AI continuous speech-to-text provider using the Flux model.\n *\n * Flux is a conversational STT model with built-in end-of-turn detection.\n * A single session is created per call and receives all audio continuously.\n * The model detects speech boundaries and fires `onUtterance` when a\n * turn is complete — no client-side silence detection needed for STT.\n *\n * Recommended for `withVoice` (conversational voice agents).\n *\n * @example\n * ```ts\n * import { Agent } from \"agents\";\n * import { withVoice, WorkersAIFluxSTT, WorkersAITTS } from \"agents/voice\";\n *\n * const VoiceAgent = withVoice(Agent);\n *\n * class MyAgent extends VoiceAgent<Env> {\n * transcriber = new WorkersAIFluxSTT(this.env.AI);\n * tts = new WorkersAITTS(this.env.AI);\n *\n * async onTurn(transcript, context) { ... }\n * }\n * ```\n */\nexport class WorkersAIFluxSTT implements Transcriber {\n #ai: AiLike;\n #sampleRate: number;\n #eotThreshold: number | undefined;\n #eagerEotThreshold: number | undefined;\n #eotTimeoutMs: number | undefined;\n #keyterms: string[] | undefined;\n\n constructor(ai: AiLike, options?: WorkersAIFluxSTTOptions) {\n this.#ai = ai;\n this.#sampleRate = options?.sampleRate ?? 16000;\n this.#eotThreshold = options?.eotThreshold;\n this.#eagerEotThreshold = options?.eagerEotThreshold;\n this.#eotTimeoutMs = options?.eotTimeoutMs;\n this.#keyterms = options?.keyterms;\n }\n\n createSession(options?: TranscriberSessionOptions): TranscriberSession {\n return new FluxSession(\n this.#ai,\n {\n sampleRate: this.#sampleRate,\n eotThreshold: this.#eotThreshold,\n eagerEotThreshold: this.#eagerEotThreshold,\n eotTimeoutMs: this.#eotTimeoutMs,\n keyterms: this.#keyterms\n },\n options\n );\n }\n}\n\ninterface FluxSessionConfig {\n sampleRate: number;\n eotThreshold?: number;\n eagerEotThreshold?: number;\n eotTimeoutMs?: number;\n keyterms?: string[];\n}\n\ninterface FluxEvent {\n event:\n | \"Update\"\n | \"StartOfTurn\"\n | \"EagerEndOfTurn\"\n | \"TurnResumed\"\n | \"EndOfTurn\";\n sequence_id?: number;\n transcript?: string;\n}\n\n/**\n * Per-call Flux transcription session. Lives for the entire call.\n *\n * Handles multi-turn conversations: on EndOfTurn, fires onUtterance\n * and resets transcript state for the next turn. On StartOfTurn,\n * clears accumulated text. The session stays alive across turns\n * and is only closed on end_call or disconnect.\n */\nclass FluxSession implements TranscriberSession {\n #onInterim: TranscriberSessionOptions[\"onInterim\"];\n #onSpeechStart: TranscriberSessionOptions[\"onSpeechStart\"];\n #onUtterance: TranscriberSessionOptions[\"onUtterance\"];\n #onFatalError: TranscriberSessionOptions[\"onFatalError\"];\n\n #ws: WebSocket | null = null;\n #connected = false;\n #closed = false;\n #fatalReported = false;\n\n #pendingChunks: ArrayBuffer[] = [];\n #currentTranscript = \"\";\n\n #ready: Promise<void>;\n #resolveReady: (() => void) | null = null;\n #rejectReady: ((reason: unknown) => void) | null = null;\n\n constructor(\n ai: AiLike,\n config: FluxSessionConfig,\n options?: TranscriberSessionOptions\n ) {\n this.#onInterim = options?.onInterim;\n this.#onSpeechStart = options?.onSpeechStart;\n this.#onUtterance = options?.onUtterance;\n this.#onFatalError = options?.onFatalError;\n this.#ready = new Promise<void>((resolve, reject) => {\n this.#resolveReady = resolve;\n this.#rejectReady = reject;\n });\n this.#ready.catch(() => {});\n this.#connect(ai, config);\n }\n\n waitUntilReady(): Promise<void> {\n return this.#ready;\n }\n\n async #connect(ai: AiLike, config: FluxSessionConfig): Promise<void> {\n try {\n const input: Record<string, unknown> = {\n encoding: \"linear16\",\n sample_rate: String(config.sampleRate)\n };\n if (config.eotThreshold != null)\n input.eot_threshold = String(config.eotThreshold);\n if (config.eagerEotThreshold != null)\n input.eager_eot_threshold = String(config.eagerEotThreshold);\n if (config.eotTimeoutMs != null)\n input.eot_timeout_ms = String(config.eotTimeoutMs);\n if (config.keyterms?.length) input.keyterm = config.keyterms;\n\n const resp = await ai.run(\"@cf/deepgram/flux\", input, {\n websocket: true\n });\n\n if (this.#closed) {\n const ws = (resp as { webSocket?: WebSocket }).webSocket;\n if (ws) {\n ws.accept();\n ws.close();\n }\n this.#resolveReadiness();\n return;\n }\n\n const ws = (resp as { webSocket?: WebSocket }).webSocket;\n if (!ws) {\n const error = new Error(\n \"Workers AI Flux STT did not return a WebSocket\"\n );\n logVoiceError({\n component: \"FluxSTT\",\n stage: \"connection\",\n message: \"Flux STT WebSocket upgrade failed\",\n error\n });\n this.#reportFatal(error);\n this.#rejectReadiness(error);\n return;\n }\n\n ws.accept();\n this.#ws = ws;\n this.#connected = true;\n\n ws.addEventListener(\"message\", (event: MessageEvent) => {\n this.#handleMessage(event);\n });\n\n ws.addEventListener(\"close\", () => {\n this.#connected = false;\n if (this.#closed) return;\n const error = new Error(\n \"Workers AI Flux STT WebSocket closed unexpectedly\"\n );\n logVoiceError({\n component: \"FluxSTT\",\n stage: \"websocket_close\",\n message: \"Flux STT WebSocket closed unexpectedly\",\n error\n });\n this.#reportFatal(error);\n });\n\n ws.addEventListener(\"error\", (event: Event) => {\n const error = new Error(\"Workers AI Flux STT WebSocket error\", {\n cause: event\n });\n logVoiceError({\n component: \"FluxSTT\",\n stage: \"websocket\",\n message: \"Flux STT WebSocket error\",\n error\n });\n this.#connected = false;\n this.#reportFatal(error);\n });\n\n for (const chunk of this.#pendingChunks) {\n ws.send(chunk);\n }\n this.#pendingChunks = [];\n this.#resolveReadiness();\n } catch (error) {\n const voiceError = toVoiceError(error, \"Flux STT connection failed\");\n logVoiceError({\n component: \"FluxSTT\",\n stage: \"connection\",\n message: \"Flux STT connection failed\",\n error: voiceError\n });\n this.#reportFatal(voiceError);\n this.#rejectReadiness(voiceError);\n }\n }\n\n feed(chunk: ArrayBuffer): void {\n if (this.#closed) return;\n\n if (this.#connected && this.#ws) {\n this.#ws.send(chunk);\n } else {\n this.#pendingChunks.push(chunk);\n }\n }\n\n close(): void {\n if (this.#closed) return;\n this.#closed = true;\n this.#pendingChunks = [];\n if (this.#ws) {\n try {\n this.#ws.close();\n } catch {\n // ignore close errors\n }\n this.#ws = null;\n }\n this.#connected = false;\n this.#resolveReadiness();\n }\n\n #resolveReadiness(): void {\n const resolve = this.#resolveReady;\n if (!resolve) return;\n this.#resolveReady = null;\n this.#rejectReady = null;\n resolve();\n }\n\n #rejectReadiness(reason: unknown): void {\n const reject = this.#rejectReady;\n if (!reject) return;\n this.#resolveReady = null;\n this.#rejectReady = null;\n reject(reason);\n }\n\n #reportFatal(error: Error): void {\n if (this.#closed || this.#fatalReported) return;\n this.#fatalReported = true;\n this.#onFatalError?.(error);\n }\n\n #handleMessage(event: MessageEvent): void {\n if (this.#closed) return;\n\n try {\n const data: FluxEvent =\n typeof event.data === \"string\" ? JSON.parse(event.data) : null;\n\n if (!data || !data.event) return;\n\n const transcript = data.transcript ?? \"\";\n\n switch (data.event) {\n case \"StartOfTurn\":\n this.#currentTranscript = \"\";\n this.#onSpeechStart?.(transcript || undefined);\n if (transcript) {\n this.#currentTranscript = transcript;\n this.#onInterim?.(transcript);\n }\n break;\n\n case \"Update\":\n if (transcript) {\n this.#currentTranscript = transcript;\n this.#onInterim?.(transcript);\n }\n break;\n\n case \"EndOfTurn\": {\n const finalTranscript = transcript || this.#currentTranscript;\n this.#currentTranscript = \"\";\n if (finalTranscript) {\n this.#onUtterance?.(finalTranscript);\n }\n break;\n }\n\n case \"EagerEndOfTurn\":\n if (transcript) {\n this.#currentTranscript = transcript;\n this.#onInterim?.(transcript);\n }\n break;\n\n case \"TurnResumed\":\n this.#currentTranscript = transcript;\n if (transcript) {\n this.#onInterim?.(transcript);\n }\n break;\n }\n } catch {\n // Ignore non-JSON or malformed messages\n }\n }\n}\n\n// --- Nova 3 continuous STT ---\n\nexport interface WorkersAINova3STTOptions {\n /** Language code. @default \"en\" */\n language?: string;\n /** Endpointing silence duration in ms. @default 300 */\n endpointingMs?: number;\n /** Utterance end detection timeout in ms. @default 1000 */\n utteranceEndMs?: number;\n /** Enable smart formatting (numbers, dates, etc.). @default true */\n smartFormat?: boolean;\n /** Enable punctuation. @default true */\n punctuate?: boolean;\n /** Keyterms to boost recognition of specialized terminology. */\n keyterms?: string[];\n /** Sample rate in Hz. @default 16000 */\n sampleRate?: number;\n}\n\n/**\n * Workers AI continuous speech-to-text provider using Nova 3.\n *\n * Nova 3 is a high-accuracy STT model with streaming WebSocket support.\n * A single session is created per call and receives all audio continuously.\n * Server-side VAD events and endpointing handle speech boundary detection.\n *\n * Recommended for `withVoiceInput` (dictation / voice input UIs).\n *\n * @example\n * ```ts\n * import { Agent } from \"agents\";\n * import { withVoiceInput, WorkersAINova3STT } from \"agents/voice\";\n *\n * const InputAgent = withVoiceInput(Agent);\n *\n * class MyAgent extends InputAgent<Env> {\n * transcriber = new WorkersAINova3STT(this.env.AI);\n *\n * onTranscript(text, connection) { ... }\n * }\n * ```\n */\nexport class WorkersAINova3STT implements Transcriber {\n #ai: AiLike;\n #sampleRate: number;\n #language: string;\n #endpointingMs: number;\n #utteranceEndMs: number;\n #smartFormat: boolean;\n #punctuate: boolean;\n #keyterms: string[] | undefined;\n\n constructor(ai: AiLike, options?: WorkersAINova3STTOptions) {\n this.#ai = ai;\n this.#sampleRate = options?.sampleRate ?? 16000;\n this.#language = options?.language ?? \"en\";\n this.#endpointingMs = options?.endpointingMs ?? 300;\n this.#utteranceEndMs = options?.utteranceEndMs ?? 1000;\n this.#smartFormat = options?.smartFormat ?? true;\n this.#punctuate = options?.punctuate ?? true;\n this.#keyterms = options?.keyterms;\n }\n\n createSession(options?: TranscriberSessionOptions): TranscriberSession {\n return new Nova3Session(\n this.#ai,\n {\n sampleRate: this.#sampleRate,\n language: this.#language,\n endpointingMs: this.#endpointingMs,\n utteranceEndMs: this.#utteranceEndMs,\n smartFormat: this.#smartFormat,\n punctuate: this.#punctuate,\n keyterms: this.#keyterms\n },\n options\n );\n }\n}\n\ninterface Nova3SessionConfig {\n sampleRate: number;\n language: string;\n endpointingMs: number;\n utteranceEndMs: number;\n smartFormat: boolean;\n punctuate: boolean;\n keyterms?: string[];\n}\n\ninterface Nova3Result {\n type: string;\n channel?: {\n alternatives?: Array<{\n transcript?: string;\n }>;\n };\n is_final?: boolean;\n speech_final?: boolean;\n}\n\n/**\n * Per-call Nova 3 transcription session. Lives for the entire call.\n *\n * Uses Nova 3's endpointing and VAD events to detect utterance\n * boundaries. When a result arrives with `speech_final: true`,\n * the accumulated finalized segments are emitted as an utterance.\n */\nclass Nova3Session implements TranscriberSession {\n #onInterim: ((text: string) => void) | undefined;\n #onUtterance: ((text: string) => void) | undefined;\n #onFatalError: TranscriberSessionOptions[\"onFatalError\"];\n\n #ws: WebSocket | null = null;\n #connected = false;\n #closed = false;\n #fatalReported = false;\n\n #pendingChunks: ArrayBuffer[] = [];\n #ready: Promise<void>;\n #resolveReady: (() => void) | null = null;\n #rejectReady: ((reason: unknown) => void) | null = null;\n\n #finalizedSegments: string[] = [];\n\n constructor(\n ai: AiLike,\n config: Nova3SessionConfig,\n options?: TranscriberSessionOptions\n ) {\n this.#onInterim = options?.onInterim;\n this.#onUtterance = options?.onUtterance;\n this.#onFatalError = options?.onFatalError;\n this.#ready = new Promise<void>((resolve, reject) => {\n this.#resolveReady = resolve;\n this.#rejectReady = reject;\n });\n this.#ready.catch(() => {});\n this.#connect(ai, config);\n }\n\n waitUntilReady(): Promise<void> {\n return this.#ready;\n }\n\n async #connect(ai: AiLike, config: Nova3SessionConfig): Promise<void> {\n try {\n const input: Record<string, unknown> = {\n encoding: \"linear16\",\n sample_rate: String(config.sampleRate),\n language: config.language,\n interim_results: \"true\",\n vad_events: \"true\",\n endpointing: String(config.endpointingMs),\n utterance_end_ms: String(config.utteranceEndMs),\n smart_format: String(config.smartFormat),\n punctuate: String(config.punctuate)\n };\n if (config.keyterms?.length) input.keyterm = config.keyterms;\n\n const resp = await ai.run(\"@cf/deepgram/nova-3\", input, {\n websocket: true\n });\n\n if (this.#closed) {\n const ws = (resp as { webSocket?: WebSocket }).webSocket;\n if (ws) {\n ws.accept();\n ws.close();\n }\n this.#resolveReadiness();\n return;\n }\n\n const ws = (resp as { webSocket?: WebSocket }).webSocket;\n if (!ws) {\n const error = new Error(\n \"Workers AI Nova-3 STT did not return a WebSocket\"\n );\n logVoiceError({\n component: \"Nova3STT\",\n stage: \"connection\",\n message: \"Nova-3 STT WebSocket upgrade failed\",\n error\n });\n this.#reportFatal(error);\n this.#rejectReadiness(error);\n return;\n }\n\n ws.accept();\n this.#ws = ws;\n this.#connected = true;\n\n ws.addEventListener(\"message\", (event: MessageEvent) => {\n this.#handleMessage(event);\n });\n\n ws.addEventListener(\"close\", () => {\n this.#connected = false;\n if (this.#closed) return;\n const error = new Error(\n \"Workers AI Nova-3 STT WebSocket closed unexpectedly\"\n );\n logVoiceError({\n component: \"Nova3STT\",\n stage: \"websocket_close\",\n message: \"Nova-3 STT WebSocket closed unexpectedly\",\n error\n });\n this.#reportFatal(error);\n });\n\n ws.addEventListener(\"error\", (event: Event) => {\n const error = new Error(\"Workers AI Nova-3 STT WebSocket error\", {\n cause: event\n });\n logVoiceError({\n component: \"Nova3STT\",\n stage: \"websocket\",\n message: \"Nova-3 STT WebSocket error\",\n error\n });\n this.#connected = false;\n this.#reportFatal(error);\n });\n\n for (const chunk of this.#pendingChunks) {\n ws.send(chunk);\n }\n this.#pendingChunks = [];\n this.#resolveReadiness();\n } catch (error) {\n const voiceError = toVoiceError(error, \"Nova-3 STT connection failed\");\n logVoiceError({\n component: \"Nova3STT\",\n stage: \"connection\",\n message: \"Nova-3 STT connection failed\",\n error: voiceError\n });\n this.#reportFatal(voiceError);\n this.#rejectReadiness(voiceError);\n }\n }\n\n feed(chunk: ArrayBuffer): void {\n if (this.#closed) return;\n\n if (this.#connected && this.#ws) {\n this.#ws.send(chunk);\n } else {\n this.#pendingChunks.push(chunk);\n }\n }\n\n close(): void {\n if (this.#closed) return;\n this.#closed = true;\n this.#pendingChunks = [];\n if (this.#ws) {\n try {\n this.#ws.close();\n } catch {\n // ignore close errors\n }\n this.#ws = null;\n }\n this.#connected = false;\n this.#resolveReadiness();\n }\n\n #resolveReadiness(): void {\n const resolve = this.#resolveReady;\n if (!resolve) return;\n this.#resolveReady = null;\n this.#rejectReady = null;\n resolve();\n }\n\n #rejectReadiness(reason: unknown): void {\n const reject = this.#rejectReady;\n if (!reject) return;\n this.#resolveReady = null;\n this.#rejectReady = null;\n reject(reason);\n }\n\n #reportFatal(error: Error): void {\n if (this.#closed || this.#fatalReported) return;\n this.#fatalReported = true;\n this.#onFatalError?.(error);\n }\n\n #handleMessage(event: MessageEvent): void {\n if (this.#closed) return;\n\n try {\n const data: Nova3Result =\n typeof event.data === \"string\" ? JSON.parse(event.data) : null;\n\n if (!data) return;\n\n if (data.type === \"Results\") {\n const transcript = data.channel?.alternatives?.[0]?.transcript ?? \"\";\n\n if (data.is_final && transcript) {\n this.#finalizedSegments.push(transcript);\n }\n\n if (data.speech_final) {\n const fullTranscript = this.#finalizedSegments.join(\" \").trim();\n this.#finalizedSegments = [];\n if (fullTranscript) {\n this.#onUtterance?.(fullTranscript);\n }\n } else if (!data.is_final && transcript) {\n const display =\n this.#finalizedSegments.length > 0\n ? this.#finalizedSegments.join(\" \") + \" \" + transcript\n : transcript;\n this.#onInterim?.(display);\n }\n }\n } catch {\n // Ignore non-JSON or malformed messages\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,301 @@
1
+ import {
2
+ S as ConnectionContext,
3
+ T as WSMessage,
4
+ r as CapabilityWebSocketUpgradeContext,
5
+ s as LifecycleCapability,
6
+ x as Connection
7
+ } from "../capability-runner-BUBa6Ake.js";
8
+ import {
9
+ a as capnWebTransportUrl,
10
+ n as CAPNWEB_TRANSPORT_QUERY,
11
+ o as isCapnWebTransportUpgrade,
12
+ r as CAPNWEB_TRANSPORT_VALUE,
13
+ t as AgentTransport
14
+ } from "../transport-protocol-ZTew5Wso.js";
15
+ import { RpcTarget } from "cloudflare:workers";
16
+
17
+ //#region src/websockets/options.d.ts
18
+ /**
19
+ * The part of a `State` capability the WebSockets capability uses. A
20
+ * structural port, so any `State<T>` fits without a cast and the
21
+ * capability never depends on the class itself.
22
+ */
23
+ type SyncedState = {
24
+ /** Current state, or `undefined` when nothing is stored. */ get(): unknown /** Validate and persist a change; throws when the host rejects it. */;
25
+ set(nextState: never, source: Connection): void;
26
+ };
27
+ /** A frame delivered on a capability-owned WebSocket connection. */
28
+ type WebSocketMessage = WSMessage;
29
+ /**
30
+ * Connection handlers for the WebSockets capability. Handlers run inside
31
+ * the host invocation boundary with the live connection in ambient
32
+ * context (`getCurrentAgent().connection`).
33
+ *
34
+ * @experimental The API surface may change before stabilizing.
35
+ */
36
+ type WebSocketHandlers = {
37
+ /** Handle a newly accepted hibernating WebSocket connection. */ onConnect?(
38
+ connection: Connection,
39
+ ctx: ConnectionContext
40
+ ): void | Promise<void> /** Handle a message from a hibernating WebSocket connection. */;
41
+ onMessage?(
42
+ connection: Connection,
43
+ message: WebSocketMessage
44
+ ): void | Promise<void> /** Handle a closing hibernating WebSocket connection. */;
45
+ onClose?(
46
+ connection: Connection,
47
+ code: number,
48
+ reason: string,
49
+ wasClean: boolean
50
+ ): void | Promise<void> /** Handle a mid-connection WebSocket error. */;
51
+ onError?(connection: Connection, error: unknown): void | Promise<void>;
52
+ };
53
+ /**
54
+ * Configuration for the WebSockets capability.
55
+ *
56
+ * @experimental The API surface may change before stabilizing.
57
+ */
58
+ interface WebSocketsOptions {
59
+ /**
60
+ * Connection handlers for WebSocket clients. The capability accepts and
61
+ * tracks every WebSocket upgrade either way; handlers add behavior on
62
+ * connect, message, close and error.
63
+ */
64
+ readonly handlers?: WebSocketHandlers;
65
+ /**
66
+ * An `RpcTarget` whose prototype methods are the host's complete remote
67
+ * interface, reached through `useAgent().call` and `.stub`. On the
68
+ * `cf-websocket` wire they are answered as JSON `rpc` frames. On the
69
+ * `capnweb` wire they are native Cap'n Web methods on the session root:
70
+ * an `RpcTarget` result becomes a live stub, a `ReadableStream` streams,
71
+ * and calls pipeline. Methods run through the host invocation boundary
72
+ * with the calling connection in scope. `Agent` answers its own
73
+ * decorated methods on the JSON wire and does not set this.
74
+ */
75
+ readonly callables?: RpcTarget;
76
+ /**
77
+ * Whether a new connection gets the connect-time protocol frames —
78
+ * identity (`cf_agent_identity`), then the current state when `state`
79
+ * is set — and whether protocol frames reach it at all.
80
+ *
81
+ * - `true` (default): every connection.
82
+ * - a function: decided per connection at accept time. `false` marks
83
+ * the connection no-protocol: it gets no protocol text frames, on
84
+ * connect or via `broadcastState()`, but can still send and receive
85
+ * ordinary messages and use callables. For binary-only clients.
86
+ * - `false`: the host drives the connect sequence itself with
87
+ * `sendIdentity()` and `sendState()`, and applies client state frames
88
+ * with `applyStateFrame()` — `Agent` does this, since it must decide
89
+ * whether a connection belongs to a facet before any frame is sent.
90
+ */
91
+ readonly protocol?:
92
+ | boolean
93
+ | ((connection: Connection, ctx: ConnectionContext) => boolean);
94
+ /**
95
+ * Decide at accept time whether a connection is readonly. A readonly
96
+ * connection's `cf_agent_state` frames are refused with
97
+ * `cf_agent_state_error`; everything else works. Also settable later
98
+ * with `setReadonly()`.
99
+ */
100
+ readonly readonly?: (
101
+ connection: Connection,
102
+ ctx: ConnectionContext
103
+ ) => boolean;
104
+ /**
105
+ * A {@link SyncedState} — normally a `State` capability — to sync over
106
+ * connections. The capability pushes the current value to each new
107
+ * connection after identity and applies `cf_agent_state` frames a
108
+ * client sends: a readonly connection is refused, and a change the
109
+ * host's validator rejects is answered with `cf_agent_state_error`.
110
+ * Broadcasting a change is the state owner's call — wire the `State`'s
111
+ * `onChanged` to `broadcastState(source)`. Install the same instance on
112
+ * the lifecycle so it owns storage and validation; without this option
113
+ * state is never sent or accepted over connections.
114
+ */
115
+ readonly state?: SyncedState;
116
+ /**
117
+ * Tags attached to each accepted connection, queryable through
118
+ * `getConnections(tag)`. The connection id is always the first tag.
119
+ */
120
+ readonly getConnectionTags?: (
121
+ connection: Connection,
122
+ ctx: ConnectionContext
123
+ ) => string[] | Promise<string[]>;
124
+ }
125
+ //#endregion
126
+ //#region src/websockets/websockets.d.ts
127
+ /**
128
+ * Opt-in WebSocket support for Lifecycle Objects.
129
+ *
130
+ * Lifecycle itself does not model WebSockets — hosts that want them
131
+ * install this capability, which owns the connection subsystem end to
132
+ * end: it claims upgrades, dispatches `onConnect`/`onMessage`/`onClose`
133
+ * inside the host invocation boundary, reciprocates close handshakes,
134
+ * and answers `getConnections()`/`getConnection()`.
135
+ *
136
+ * ```ts
137
+ * class Room extends DurableObject<Env> {
138
+ * readonly webSockets = new WebSockets({
139
+ * handlers: {
140
+ * onConnect: (connection) => connection.send("welcome"),
141
+ * onMessage: (connection, message) => { ... }
142
+ * },
143
+ * callables: new RoomCallables()
144
+ * });
145
+ * readonly lifecycle = Lifecycle.install(this).use(this.webSockets);
146
+ * }
147
+ * ```
148
+ *
149
+ * Connections arrive on one of two wires, chosen by the client:
150
+ *
151
+ * - **cf-websocket** (default): accepted with the Hibernation API. Idle
152
+ * clients stay connected while the Durable Object leaves memory.
153
+ * - **capnweb** (`?__agents_transport=capnweb`): protocol frames through
154
+ * one pipe method on a Cap'n Web session whose root also carries the
155
+ * host's callables natively. Non-hibernating — the object stays pinned
156
+ * while the connection is open.
157
+ *
158
+ * Both wires dispatch the same handlers and appear in `getConnections()`.
159
+ * On both, the capability speaks the Agent protocol a plain host needs
160
+ * for `useAgent` and `AgentClient`: it sends the identity frame on
161
+ * connect, and it serves `callables` — as `rpc` JSON frames on the
162
+ * WebSocket wire, and natively on the Cap'n Web session root, where an
163
+ * `RpcTarget` result becomes a live stub and calls pipeline. `call()`
164
+ * and `stub` work against a plain Durable Object exactly as against an
165
+ * `Agent`. Pass a `State` capability as `state` and the hook's
166
+ * `state`/`setState` work too: the current value is pushed on connect
167
+ * and client updates are validated and applied; the state owner
168
+ * broadcasts changes with `broadcastState()`. Per-connection readonly
169
+ * and no-protocol flags live here as well, for every host.
170
+ *
171
+ * @experimental The API surface may change before stabilizing.
172
+ */
173
+ declare class WebSockets extends LifecycleCapability {
174
+ #private;
175
+ /** Claims every upgrade, so Lifecycle dispatches it after all others. */
176
+ readonly claims = "catch-all";
177
+ constructor(options?: WebSocketsOptions);
178
+ /**
179
+ * Claim every upgrade, never declining: a Cap'n Web transport upgrade
180
+ * becomes a session, everything else a tracked hibernating connection,
181
+ * whether or not handlers or callables are configured. Handlers only add
182
+ * behavior on connect, message, close, and error.
183
+ */
184
+ onWebSocketUpgrade({
185
+ request
186
+ }: CapabilityWebSocketUpgradeContext): Promise<Response>;
187
+ /** Dispatch a platform message wake for a capability-owned socket. */
188
+ onWebSocketMessage(
189
+ ws: WebSocket,
190
+ message: WebSocketMessage
191
+ ): Promise<boolean>;
192
+ /** Dispatch and reciprocate a close wake for an owned socket. */
193
+ onWebSocketClose(
194
+ ws: WebSocket,
195
+ code: number,
196
+ reason: string,
197
+ wasClean: boolean
198
+ ): Promise<boolean>;
199
+ /** Dispatch an error wake for an owned socket. */
200
+ onWebSocketError(ws: WebSocket, error: unknown): Promise<boolean>;
201
+ /**
202
+ * Close every owned connection during explicit host destruction. The
203
+ * capability owns its sockets' lifetimes, so it also owns tearing
204
+ * them down.
205
+ */
206
+ dispose(): void;
207
+ /** Open connections on either wire, optionally by tag. */
208
+ getConnections<TState = unknown>(
209
+ tag?: string
210
+ ): IterableIterator<Connection<TState>>;
211
+ /** One connection on either wire, by id. */
212
+ getConnection<TState = unknown>(id: string): Connection<TState> | undefined;
213
+ /**
214
+ * Send the identity frame, unless the connection is no-protocol. The
215
+ * defaults are the Durable Object's routed name and host class; a host
216
+ * whose public identity differs — an `Agent` facet, whose routed name
217
+ * is an internal encoding of its logical name — passes its own.
218
+ */
219
+ sendIdentity(
220
+ connection: Connection,
221
+ identity?: {
222
+ name: string;
223
+ agent: string;
224
+ }
225
+ ): void;
226
+ /**
227
+ * Send the current state to one connection, unless nothing is stored
228
+ * or the connection is no-protocol. Reading the state may seed the
229
+ * initial value; see `#connecting`.
230
+ */
231
+ sendState(connection: Connection): void;
232
+ /**
233
+ * Apply a parsed `cf_agent_state` frame from a client. A readonly
234
+ * connection is refused; a change the host's validator rejects is
235
+ * logged in full server-side and answered with a generic
236
+ * `cf_agent_state_error`. Broadcasting the accepted change is the state
237
+ * owner's call, through its `onChanged` hook. Callers that drive the
238
+ * protocol themselves call this inside their own invocation context;
239
+ * the capability's automatic path does so via `runInHostContext`.
240
+ *
241
+ * @returns Whether the frame was a state frame (handled either way).
242
+ */
243
+ applyStateFrame(connection: Connection, frame: unknown): boolean;
244
+ /**
245
+ * Push the current state to every protocol-enabled connection except
246
+ * the one a change came from, which already has the value it sent.
247
+ * Wire a `State`'s `onChanged` to this.
248
+ */
249
+ broadcastState(except?: Connection | "server"): void;
250
+ /** Whether the connection may update host state over the wire. */
251
+ isReadonly(connection: Connection): boolean;
252
+ /** Mark a connection readonly, or writable again. */
253
+ setReadonly(connection: Connection, readonly?: boolean): void;
254
+ /** Whether protocol text frames reach the connection. */
255
+ isProtocolEnabled(connection: Connection): boolean;
256
+ /** Enable or suppress protocol text frames for a connection. */
257
+ setProtocolEnabled(connection: Connection, enabled: boolean): void;
258
+ }
259
+ //#endregion
260
+ //#region src/websockets/connection-flags.d.ts
261
+ /**
262
+ * Internal per-connection flags, stored inside the connection's own state
263
+ * under `_cf_`-prefixed keys so they ride the hibernation attachment (or a
264
+ * bridged connection's synced state) and survive a wake. The state wrapper
265
+ * installed by {@link ensureConnectionWrapped} hides them from
266
+ * `connection.state` and preserves them across user `setState` calls.
267
+ *
268
+ * Owned by the WebSockets capability; `Agent` and framework mixins reach it
269
+ * through the capability or, for their own keys, through
270
+ * {@link registerInternalConnectionKeys}.
271
+ */
272
+ /** A readonly connection may not update host state. */
273
+ declare const CF_READONLY_KEY = "_cf_readonly";
274
+ /**
275
+ * A no-protocol connection receives no protocol text frames (identity,
276
+ * state sync, MCP servers) — neither on connect nor via broadcasts.
277
+ */
278
+ declare const CF_NO_PROTOCOL_KEY = "_cf_no_protocol";
279
+ /**
280
+ * Register additional `_cf_`-prefixed keys a host or mixin stores in
281
+ * connection state, so they are hidden from `connection.state` and kept
282
+ * across user `setState` calls like the capability's own flags.
283
+ */
284
+ declare function registerInternalConnectionKeys(...keys: string[]): void;
285
+ //#endregion
286
+ export {
287
+ type AgentTransport,
288
+ CAPNWEB_TRANSPORT_QUERY,
289
+ CAPNWEB_TRANSPORT_VALUE,
290
+ CF_NO_PROTOCOL_KEY,
291
+ CF_READONLY_KEY,
292
+ type SyncedState,
293
+ type WebSocketHandlers,
294
+ type WebSocketMessage,
295
+ WebSockets,
296
+ type WebSocketsOptions,
297
+ capnWebTransportUrl,
298
+ isCapnWebTransportUpgrade,
299
+ registerInternalConnectionKeys
300
+ };
301
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,3 @@
1
+ import { a as isCapnWebTransportUpgrade, i as capnWebTransportUrl, r as CAPNWEB_TRANSPORT_VALUE, t as CAPNWEB_TRANSPORT_QUERY } from "../transport-protocol-BxyngQ_R.js";
2
+ import { l as registerInternalConnectionKeys, n as CF_NO_PROTOCOL_KEY, r as CF_READONLY_KEY, t as WebSockets } from "../websockets-D7IzWbZb.js";
3
+ export { CAPNWEB_TRANSPORT_QUERY, CAPNWEB_TRANSPORT_VALUE, CF_NO_PROTOCOL_KEY, CF_READONLY_KEY, WebSockets, capnWebTransportUrl, isCapnWebTransportUpgrade, registerInternalConnectionKeys };