agents 0.21.0 → 0.23.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 (258) hide show
  1. package/README.md +21 -1
  2. package/dist/{agent-tool-types-CzGGB-20.d.ts → agent-routing-DE5zmCQ8.d.ts} +1844 -1336
  3. package/dist/agent-routing.d.ts +14 -0
  4. package/dist/agent-routing.js +187 -0
  5. package/dist/agent-routing.js.map +1 -0
  6. package/dist/agent-tool-types.d.ts +26 -26
  7. package/dist/{agent-tools-zR2d5uij.d.ts → agent-tools-DtXMTDGM.d.ts} +7 -7
  8. package/dist/agent-tools.d.ts +21 -21
  9. package/dist/agent-tools.js +2 -1
  10. package/dist/agent-tools.js.map +1 -1
  11. package/dist/browser/ai.js +6 -2
  12. package/dist/browser/ai.js.map +1 -1
  13. package/dist/browser/tanstack-ai.js.map +1 -1
  14. package/dist/callable-decorator-DP__HhBA.d.ts +72 -0
  15. package/dist/callable-decorator.d.ts +18 -0
  16. package/dist/callable-decorator.js +71 -0
  17. package/dist/callable-decorator.js.map +1 -0
  18. package/dist/capability-BjSKYpzg.js +42 -0
  19. package/dist/capability-BjSKYpzg.js.map +1 -0
  20. package/dist/capability-runner-Be_-PLR1.d.ts +459 -0
  21. package/dist/channel-Bnm4S7T2.d.ts +491 -0
  22. package/dist/channels/ai-sdk.d.ts +46 -0
  23. package/dist/channels/ai-sdk.js +120 -0
  24. package/dist/channels/ai-sdk.js.map +1 -0
  25. package/dist/channels/email.d.ts +95 -0
  26. package/dist/channels/email.js +323 -0
  27. package/dist/channels/email.js.map +1 -0
  28. package/dist/channels/index.d.ts +233 -0
  29. package/dist/channels/index.js +608 -0
  30. package/dist/channels/index.js.map +1 -0
  31. package/dist/channels/slack.d.ts +140 -0
  32. package/dist/channels/slack.js +614 -0
  33. package/dist/channels/slack.js.map +1 -0
  34. package/dist/channels/tanstack-ai.d.ts +39 -0
  35. package/dist/channels/tanstack-ai.js +17 -0
  36. package/dist/channels/tanstack-ai.js.map +1 -0
  37. package/dist/channels/telegram.d.ts +106 -0
  38. package/dist/channels/telegram.js +427 -0
  39. package/dist/channels/telegram.js.map +1 -0
  40. package/dist/channels/voice.d.ts +45 -0
  41. package/dist/channels/voice.js +122 -0
  42. package/dist/channels/voice.js.map +1 -0
  43. package/dist/chat/index.d.ts +2328 -2015
  44. package/dist/chat/index.js +891 -521
  45. package/dist/chat/index.js.map +1 -1
  46. package/dist/chat/react.d.ts +14 -1
  47. package/dist/chat/react.js +82 -52
  48. package/dist/chat/react.js.map +1 -1
  49. package/dist/chat/transport.js +1 -1
  50. package/dist/chat-sdk/index.d.ts +7 -7
  51. package/dist/chat-sdk/index.js +1 -1
  52. package/dist/{client-zqKcsyFa.js → client-jagG8a9_.js} +129 -37
  53. package/dist/client-jagG8a9_.js.map +1 -0
  54. package/dist/client.d.ts +1 -1
  55. package/dist/client.js +1 -1
  56. package/dist/{cloudflare-BduZwmYK.js → cloudflare-Dzvc7V2N.js} +10 -3
  57. package/dist/{cloudflare-BduZwmYK.js.map → cloudflare-Dzvc7V2N.js.map} +1 -1
  58. package/dist/context/index.d.ts +216 -0
  59. package/dist/context/index.js +454 -0
  60. package/dist/context/index.js.map +1 -0
  61. package/dist/current-agent-Da_C9a3b.d.ts +266 -0
  62. package/dist/current-agent-DhoDkSnH.js +51 -0
  63. package/dist/current-agent-DhoDkSnH.js.map +1 -0
  64. package/dist/diagnostics-BzvaX2UT.js +45 -0
  65. package/dist/diagnostics-BzvaX2UT.js.map +1 -0
  66. package/dist/diagnostics-C4jcz3VK.js +360 -0
  67. package/dist/diagnostics-C4jcz3VK.js.map +1 -0
  68. package/dist/{do-oauth-client-provider-VTZj2VtM.d.ts → do-oauth-client-provider-Tmf1vgKz.d.ts} +2 -2
  69. package/dist/{email-CL27preh.d.ts → email-7TatiTnl.d.ts} +38 -9
  70. package/dist/email-send.d.ts +15 -0
  71. package/dist/email-send.js +32 -0
  72. package/dist/email-send.js.map +1 -0
  73. package/dist/email.d.ts +14 -10
  74. package/dist/email.js.map +1 -1
  75. package/dist/{handler-stateless-C_bo-Ytq.d.ts → handler-stateless-DxYpJ_XF.d.ts} +3 -3
  76. package/dist/{handler-stateless-CIkKPETH.js → handler-stateless-VvrWSAVA.js} +5 -5
  77. package/dist/handler-stateless-VvrWSAVA.js.map +1 -0
  78. package/dist/index-BB0kqhIz.d.ts +101 -0
  79. package/dist/index-XDkuQ7zm.d.ts +89 -0
  80. package/dist/{index-BRnybD6X.d.ts → index-YSKgfgg9.d.ts} +21 -31
  81. package/dist/index.d.ts +113 -101
  82. package/dist/index.js +11 -7234
  83. package/dist/ingress-BfetZbMO.js +83 -0
  84. package/dist/ingress-BfetZbMO.js.map +1 -0
  85. package/dist/internal-CYlgHl1l.js +59 -0
  86. package/dist/internal-CYlgHl1l.js.map +1 -0
  87. package/dist/internal_context-BlxFEWfn.d.ts +19 -0
  88. package/dist/internal_context.d.ts +10 -4
  89. package/dist/internal_context.js +1 -10
  90. package/dist/{client-invoker-BNSZxAkv.d.ts → invoker-CG0_p_Wq.d.ts} +2 -2
  91. package/dist/{client-invoker-VNZ7X0nn.js → invoker-CHMnoxIA.js} +2 -2
  92. package/dist/invoker-CHMnoxIA.js.map +1 -0
  93. package/dist/lifecycle/index.d.ts +66 -0
  94. package/dist/lifecycle/index.js +4 -0
  95. package/dist/lifecycle-CMRGjZdw.js +1299 -0
  96. package/dist/lifecycle-CMRGjZdw.js.map +1 -0
  97. package/dist/mcp/{do-oauth-client-provider.d.ts → client/do-oauth-client-provider.d.ts} +1 -1
  98. package/dist/mcp/{do-oauth-client-provider.js → client/do-oauth-client-provider.js} +1 -1
  99. package/dist/mcp/client/do-oauth-client-provider.js.map +1 -0
  100. package/dist/mcp/client/index.d.ts +42 -0
  101. package/dist/mcp/{client.js → client/index.js} +1 -1
  102. package/dist/mcp/{x402.d.ts → client/x402.d.ts} +2 -2
  103. package/dist/mcp/{x402.js → client/x402.js} +2 -2
  104. package/dist/mcp/client/x402.js.map +1 -0
  105. package/dist/mcp/index.d.ts +36 -36
  106. package/dist/mcp/index.js +14 -16
  107. package/dist/mcp/index.js.map +1 -1
  108. package/dist/mcp/{server.d.ts → server/index.d.ts} +1 -1
  109. package/dist/mcp/{server.js → server/index.js} +1 -1
  110. package/dist/observability/ai/index.js +50 -35
  111. package/dist/observability/ai/index.js.map +1 -1
  112. package/dist/observability/index.d.ts +4 -4
  113. package/dist/observability/index.js +3 -50
  114. package/dist/observability/index.js.map +1 -1
  115. package/dist/{protocol-Dqc2MQxo.js → protocol-B0nh6KNf.js} +19 -21
  116. package/dist/protocol-B0nh6KNf.js.map +1 -0
  117. package/dist/react.d.ts +4 -4
  118. package/dist/react.js +1 -1
  119. package/dist/{retries-CAvxtG9d.d.ts → retries-D9Ds-1lz.d.ts} +17 -6
  120. package/dist/retries.d.ts +8 -6
  121. package/dist/retries.js +13 -1
  122. package/dist/retries.js.map +1 -1
  123. package/dist/routing/index.d.ts +137 -0
  124. package/dist/routing/index.js +244 -0
  125. package/dist/routing/index.js.map +1 -0
  126. package/dist/sanitize-D9TujEK8.js +79 -0
  127. package/dist/sanitize-D9TujEK8.js.map +1 -0
  128. package/dist/schedule.d.ts +25 -94
  129. package/dist/schedule.js +1 -98
  130. package/dist/schedule.js.map +1 -1
  131. package/dist/scheduler-DD9NdYbF.js +665 -0
  132. package/dist/scheduler-DD9NdYbF.js.map +1 -0
  133. package/dist/scheduler-Dwh85ZGl.d.ts +223 -0
  134. package/dist/schedules/index.d.ts +22 -0
  135. package/dist/schedules/index.js +2 -0
  136. package/dist/schedules/parser.d.ts +79 -0
  137. package/dist/schedules/parser.js +103 -0
  138. package/dist/schedules/parser.js.map +1 -0
  139. package/dist/sentence-chunker-BAidJ4DA.d.ts +68 -0
  140. package/dist/serializable.d.ts +1 -1
  141. package/dist/sessions/index.d.ts +441 -0
  142. package/dist/sessions/index.js +2063 -0
  143. package/dist/sessions/index.js.map +1 -0
  144. package/dist/skills/index.d.ts +99 -0
  145. package/dist/skills/index.js +254 -5
  146. package/dist/skills/index.js.map +1 -1
  147. package/dist/sql-error-CPY-GXyI.d.ts +12 -0
  148. package/dist/sql-error.d.ts +2 -0
  149. package/dist/sql-error.js +16 -0
  150. package/dist/sql-error.js.map +1 -0
  151. package/dist/src-DlSHshb2.js +6963 -0
  152. package/dist/src-DlSHshb2.js.map +1 -0
  153. package/dist/streams/index.d.ts +120 -0
  154. package/dist/streams/index.js +107 -0
  155. package/dist/streams/index.js.map +1 -0
  156. package/dist/streams-D6tJ0NN9.d.ts +370 -0
  157. package/dist/streams-DZKgAj9b.js +709 -0
  158. package/dist/streams-DZKgAj9b.js.map +1 -0
  159. package/dist/sub-routing.d.ts +12 -12
  160. package/dist/surface-bZZJqBka.js +17 -0
  161. package/dist/surface-bZZJqBka.js.map +1 -0
  162. package/dist/tasks/index.d.ts +64 -0
  163. package/dist/tasks/index.js +2 -0
  164. package/dist/tasks-BRJ5zgya.d.ts +517 -0
  165. package/dist/tasks-ylZgBjhj.js +1656 -0
  166. package/dist/tasks-ylZgBjhj.js.map +1 -0
  167. package/dist/text-segment-joiner-BtAFQSA_.js +57 -0
  168. package/dist/text-segment-joiner-BtAFQSA_.js.map +1 -0
  169. package/dist/text-stream-CpdiKrJB.js +272 -0
  170. package/dist/text-stream-CpdiKrJB.js.map +1 -0
  171. package/dist/tokens-nHAKcN6M.js +52 -0
  172. package/dist/tokens-nHAKcN6M.js.map +1 -0
  173. package/dist/tool-schema-CBjGPrsQ.js +31 -0
  174. package/dist/tool-schema-CBjGPrsQ.js.map +1 -0
  175. package/dist/types-B7LojTe4.d.ts +202 -0
  176. package/dist/types-_Faxb570.d.ts +439 -0
  177. package/dist/voice/client.d.ts +226 -0
  178. package/dist/voice/client.js +932 -0
  179. package/dist/voice/client.js.map +1 -0
  180. package/dist/voice/errors.d.ts +43 -0
  181. package/dist/voice/errors.js +41 -0
  182. package/dist/voice/errors.js.map +1 -0
  183. package/dist/voice/index.d.ts +271 -0
  184. package/dist/voice/index.js +1812 -0
  185. package/dist/voice/index.js.map +1 -0
  186. package/dist/voice/react.d.ts +167 -0
  187. package/dist/voice/react.js +234 -0
  188. package/dist/voice/react.js.map +1 -0
  189. package/dist/voice/sfu.d.ts +71 -0
  190. package/dist/voice/sfu.js +157 -0
  191. package/dist/voice/sfu.js.map +1 -0
  192. package/dist/voice/text.d.ts +6 -0
  193. package/dist/voice/text.js +2 -0
  194. package/dist/voice/types.d.ts +58 -0
  195. package/dist/voice/types.js +18 -0
  196. package/dist/voice/types.js.map +1 -0
  197. package/dist/voice/workers-ai.d.ts +136 -0
  198. package/dist/voice/workers-ai.js +568 -0
  199. package/dist/voice/workers-ai.js.map +1 -0
  200. package/dist/websockets/index.d.ts +192 -0
  201. package/dist/websockets/index.js +2 -0
  202. package/dist/websockets-DUfRHPRq.js +502 -0
  203. package/dist/websockets-DUfRHPRq.js.map +1 -0
  204. package/dist/workflow-types.d.ts +25 -25
  205. package/dist/workflows.d.ts +22 -22
  206. package/dist/workflows.js +2 -1
  207. package/dist/workflows.js.map +1 -1
  208. package/dist/{ws-chat-transport-CIoOBbO7.js → ws-chat-transport-rWwta645.js} +152 -15
  209. package/dist/ws-chat-transport-rWwta645.js.map +1 -0
  210. package/docs/agent-class.md +29 -87
  211. package/docs/agent-tools.md +2 -1
  212. package/docs/channels.md +323 -0
  213. package/docs/chat-agents.md +19 -25
  214. package/docs/context.md +131 -0
  215. package/docs/durable-execution.md +1 -1
  216. package/docs/http-websockets.md +1 -11
  217. package/docs/human-in-the-loop.md +1 -1
  218. package/docs/index.md +16 -12
  219. package/docs/lifecycle.md +370 -0
  220. package/docs/long-running-agents.md +4 -6
  221. package/docs/mcp-client.md +55 -0
  222. package/docs/mcp-servers.md +5 -1
  223. package/docs/observability.md +11 -11
  224. package/docs/resumable-streaming.md +2 -2
  225. package/docs/routing.md +105 -0
  226. package/docs/scheduling.md +175 -15
  227. package/docs/server-driven-messages.md +1 -1
  228. package/docs/sessions.md +237 -871
  229. package/docs/streams.md +213 -0
  230. package/docs/sub-agents.md +185 -125
  231. package/docs/tasks.md +246 -0
  232. package/docs/voice.md +745 -0
  233. package/package.json +144 -33
  234. package/dist/cli/index.js +0 -26
  235. package/dist/cli/index.js.map +0 -1
  236. package/dist/client-invoker-VNZ7X0nn.js.map +0 -1
  237. package/dist/client-zqKcsyFa.js.map +0 -1
  238. package/dist/compaction-helpers-iiKMr2TQ.js +0 -340
  239. package/dist/compaction-helpers-iiKMr2TQ.js.map +0 -1
  240. package/dist/compaction-helpers-wUz6M3us.d.ts +0 -621
  241. package/dist/experimental/memory/session/index.d.ts +0 -670
  242. package/dist/experimental/memory/session/index.js +0 -2374
  243. package/dist/experimental/memory/session/index.js.map +0 -1
  244. package/dist/experimental/memory/utils/index.d.ts +0 -96
  245. package/dist/experimental/memory/utils/index.js +0 -79
  246. package/dist/experimental/memory/utils/index.js.map +0 -1
  247. package/dist/handler-stateless-CIkKPETH.js.map +0 -1
  248. package/dist/index.js.map +0 -1
  249. package/dist/internal_context-Dg4Cgjcu.d.ts +0 -37
  250. package/dist/internal_context.js.map +0 -1
  251. package/dist/mcp/client.d.ts +0 -42
  252. package/dist/mcp/do-oauth-client-provider.js.map +0 -1
  253. package/dist/mcp/x402.js.map +0 -1
  254. package/dist/protocol-Dqc2MQxo.js.map +0 -1
  255. package/dist/tool-output-truncation-CNnnGZQ3.js +0 -98
  256. package/dist/tool-output-truncation-CNnnGZQ3.js.map +0 -1
  257. package/dist/ws-chat-transport-CIoOBbO7.js.map +0 -1
  258. /package/dist/{cli/index.d.ts → index-BVVgDSdq.d.ts} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","names":[],"sources":["../../src/voice/client.ts"],"sourcesContent":["import { PartySocket } from \"partysocket\";\nimport { ClientDiagnostics } from \"./diagnostics\";\nimport { toVoiceError } from \"./errors\";\nimport { VOICE_PROTOCOL_VERSION } from \"./types\";\n\nfunction camelCaseToKebabCase(str: string): string {\n if (str === str.toUpperCase() && str !== str.toLowerCase()) {\n return str.toLowerCase().replace(/_/g, \"-\");\n }\n let kebabified = str.replace(\n /[A-Z]/g,\n (letter) => `-${letter.toLowerCase()}`\n );\n kebabified = kebabified.startsWith(\"-\") ? kebabified.slice(1) : kebabified;\n return kebabified.replace(/_/g, \"-\").replace(/-$/, \"\");\n}\nimport type {\n VoiceStatus,\n VoiceRole,\n VoiceAudioFormat,\n VoiceAudioInput,\n VoiceTransport,\n VoiceTransportCloseInfo,\n VoiceError,\n VoiceCompletionOutcome,\n TranscriptMessage,\n VoicePipelineMetrics,\n VoiceTurnMetrics,\n VoiceDiagnosticEvent\n} from \"./types\";\n\n// Re-export shared types for consumers importing from this module\nexport { VOICE_PROTOCOL_VERSION } from \"./types\";\nexport type {\n VoiceStatus,\n VoiceRole,\n VoiceAudioFormat,\n VoiceAudioInput,\n VoiceTransport,\n VoiceTransportCloseInfo,\n VoiceError,\n VoiceErrorCode,\n VoiceErrorStage,\n VoiceCompletionOutcome,\n VoiceCompletionOutcomeCode,\n VoiceModelFinishReason,\n VoiceDiagnosticsOptions,\n VoiceDiagnosticEvent,\n VoicePipelineMetrics,\n VoiceTurnMetrics,\n VoiceTurnOutcome,\n VoiceTurnSource,\n TranscriptMessage\n} from \"./types\";\n\nexport interface VoiceClientOptions {\n /** Agent name (matches the server-side Durable Object class). */\n agent: string;\n /** Instance name for the agent. @default \"default\" */\n name?: string;\n\n // Connection options (optional — defaults work for same-origin)\n /** Host to connect to. @default window.location.host */\n host?: string;\n\n /** Query parameters appended to the WebSocket URL. */\n query?: Record<string, string | null | undefined>;\n\n /**\n * Custom transport for sending/receiving data.\n * Defaults to a WebSocket transport via PartySocket.\n * Provide a custom implementation for WebRTC, SFU, or other transports.\n */\n transport?: VoiceTransport;\n\n /**\n * Custom audio input source. When provided, VoiceClient does NOT\n * use its built-in AudioWorklet mic capture. The audio input is\n * responsible for capturing and routing audio to the server.\n * It must report audio levels via `onAudioLevel` for silence and\n * interrupt detection to work.\n */\n audioInput?: VoiceAudioInput;\n\n /**\n * Preferred audio format for server responses. Sent in `start_call`\n * as a hint — the server may ignore it if it cannot produce that format.\n * The actual format is declared in the server's `audio_config` message.\n */\n preferredFormat?: VoiceAudioFormat;\n\n // Tuning knobs with sensible defaults\n /** RMS threshold below which audio is considered silence. @default 0.04 */\n silenceThreshold?: number;\n /** How long silence must last before sending end_of_speech (ms). @default 500 */\n silenceDurationMs?: number;\n /** RMS threshold for detecting user speech during agent playback. @default 0.05 */\n interruptThreshold?: number;\n /** Consecutive high-RMS chunks needed to trigger an interrupt. @default 2 */\n interruptChunks?: number;\n /** Maximum transcript messages to keep in memory. @default 200 */\n maxTranscriptMessages?: number;\n\n /**\n * Preferred audio output device for assistant playback.\n * Pass a MediaDeviceInfo.deviceId from an audiooutput device.\n * Unsupported browsers continue playing through the default output.\n * @default \"default\"\n */\n outputDeviceId?: string;\n}\n\ntype AudioElementWithSinkId = HTMLAudioElement & {\n setSinkId?: (sinkId: string) => Promise<void>;\n};\n\nconst UNSUPPORTED_OUTPUT_DEVICE_ERROR =\n \"Audio output device selection is not supported in this browser.\";\nconst OUTPUT_DEVICE_SWITCH_ERROR = \"Could not switch audio output device.\";\n\n/**\n * Low-level browser transport information for diagnosing connection failures.\n * Error causes stay as the raw `unknown` value because browsers do not\n * guarantee useful fields on WebSocket error events. The SDK does not\n * serialize or log this local event; consumers must narrow it before use.\n */\nexport type VoiceConnectionDiagnostic =\n | { type: \"error\"; cause: unknown }\n | ({ type: \"close\" } & VoiceTransportCloseInfo);\n\n/** Maps each event name to the data type passed to its listeners. */\nexport interface VoiceClientEventMap {\n statuschange: VoiceStatus;\n transcriptchange: TranscriptMessage[];\n interimtranscript: string | null;\n metricschange: VoicePipelineMetrics | null;\n turnmetrics: VoiceTurnMetrics;\n audiolevelchange: number;\n connectionchange: boolean;\n connectiondiagnostic: VoiceConnectionDiagnostic;\n voiceerror: VoiceError;\n completionoutcome: VoiceCompletionOutcome;\n error: string | null;\n outputdeviceerror: string | null;\n mutechange: boolean;\n custommessage: unknown;\n}\n\nexport type VoiceClientEvent = keyof VoiceClientEventMap;\n\n// --- Audio helpers (not exported) ---\n\nconst WORKLET_PROCESSOR = `\nclass AudioCaptureProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n this.buffer = [];\n this.sampleRate = sampleRate;\n this.targetRate = 16000;\n this.ratio = this.sampleRate / this.targetRate;\n }\n\n process(inputs) {\n const input = inputs[0];\n if (!input || !input[0]) return true;\n\n const channelData = input[0];\n\n // Linear interpolation resampling (e.g. 48kHz → 16kHz).\n // Nearest-neighbor (picking every Nth sample) introduces aliasing\n // artifacts, especially on sibilants (s, f, th). Linear interpolation\n // blends adjacent samples, acting as a basic low-pass filter.\n for (let i = 0; i < channelData.length; i += this.ratio) {\n const idx = Math.floor(i);\n const frac = i - idx;\n if (idx + 1 < channelData.length) {\n this.buffer.push(channelData[idx] * (1 - frac) + channelData[idx + 1] * frac);\n } else if (idx < channelData.length) {\n this.buffer.push(channelData[idx]);\n }\n }\n\n if (this.buffer.length >= 1600) {\n const chunk = new Float32Array(this.buffer);\n this.port.postMessage({ type: 'audio', samples: chunk }, [chunk.buffer]);\n this.buffer = [];\n }\n\n return true;\n }\n}\n\nregisterProcessor('audio-capture-processor', AudioCaptureProcessor);\n`;\n\nfunction floatTo16BitPCM(samples: Float32Array): ArrayBuffer {\n const buffer = new ArrayBuffer(samples.length * 2);\n const view = new DataView(buffer);\n for (let i = 0; i < samples.length; i++) {\n const s = Math.max(-1, Math.min(1, samples[i]));\n view.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7fff, true);\n }\n return buffer;\n}\n\nfunction computeRMS(samples: Float32Array): number {\n let sum = 0;\n for (let i = 0; i < samples.length; i++) {\n sum += samples[i] * samples[i];\n }\n return Math.sqrt(sum / samples.length);\n}\n\n// --- Default WebSocket transport ---\n\n/**\n * Default VoiceTransport backed by PartySocket (reconnecting WebSocket).\n * Created automatically when no custom transport is provided.\n */\nexport class WebSocketVoiceTransport implements VoiceTransport {\n #socket: PartySocket | null = null;\n #options: {\n agent: string;\n name?: string;\n host?: string;\n query?: Record<string, string | null | undefined>;\n };\n\n onopen: (() => void) | null = null;\n onclose: ((info?: VoiceTransportCloseInfo) => void) | null = null;\n onerror: ((error?: unknown) => void) | null = null;\n onmessage: ((data: string | ArrayBuffer | Blob) => void) | null = null;\n\n constructor(options: {\n agent: string;\n name?: string;\n host?: string;\n query?: Record<string, string | null | undefined>;\n }) {\n this.#options = options;\n }\n\n get connected(): boolean {\n return this.#socket?.readyState === WebSocket.OPEN;\n }\n\n sendJSON(data: Record<string, unknown>): void {\n if (this.#socket?.readyState === WebSocket.OPEN) {\n this.#socket.send(JSON.stringify(data));\n }\n }\n\n sendBinary(data: ArrayBuffer): void {\n if (this.#socket?.readyState === WebSocket.OPEN) {\n this.#socket.send(data);\n }\n }\n\n connect(): void {\n if (this.#socket) return;\n\n const agentNamespace = camelCaseToKebabCase(this.#options.agent);\n\n const socket = new PartySocket({\n party: agentNamespace,\n room: this.#options.name ?? \"default\",\n host: this.#options.host ?? window.location.host,\n prefix: \"agents\",\n query: this.#options.query\n });\n\n socket.onopen = () => this.onopen?.();\n socket.onclose = (event?: CloseEvent) =>\n this.onclose?.(\n event\n ? {\n code: event.code,\n reason: event.reason,\n wasClean: event.wasClean\n }\n : undefined\n );\n socket.onerror = (event) => this.onerror?.(event);\n socket.onmessage = (event: MessageEvent) => {\n this.onmessage?.(event.data);\n };\n\n this.#socket = socket;\n }\n\n disconnect(): void {\n this.#socket?.close();\n this.#socket = null;\n }\n}\n\n// --- VoiceClient ---\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any -- generic listener storage\ntype AnyListener = (data: any) => void;\n\nexport class VoiceClient {\n // Internal state\n #status: VoiceStatus = \"idle\";\n #transcript: TranscriptMessage[] = [];\n #metrics: VoicePipelineMetrics | null = null;\n #turnMetrics: VoiceTurnMetrics | null = null;\n #audioLevel = 0;\n #isMuted = false;\n #connected = false;\n #error: string | null = null;\n #outputDeviceError: string | null = null;\n #lastCustomMessage: unknown = null;\n #audioFormat: VoiceAudioFormat | null = null;\n /** Sample rate for raw pcm16 payloads; set from server `audio_config`. */\n #sampleRate = 16000;\n #interimTranscript: string | null = null;\n #serverProtocolVersion: number | null = null;\n #inCall = false;\n #callGeneration = 0;\n #serverCallAcknowledged = false;\n #diagnostics = new ClientDiagnostics();\n #audioReceivedForCurrentTurn = false;\n #diagnosticTurnId: string | null = null;\n\n // Options (with defaults applied)\n #silenceThreshold: number;\n #silenceDurationMs: number;\n #interruptThreshold: number;\n #interruptChunks: number;\n #maxTranscriptMessages: number;\n\n // Transport\n #transport: VoiceTransport | null = null;\n #options: VoiceClientOptions;\n\n // Audio refs\n #audioContext: AudioContext | null = null;\n #workletRegistered = false;\n #workletNode: AudioWorkletNode | null = null;\n #stream: MediaStream | null = null;\n #silenceTimer: ReturnType<typeof setTimeout> | null = null;\n #isSpeaking = false;\n #playbackQueue: ArrayBuffer[] = [];\n #isPlaying = false;\n #isScheduling = false;\n #scheduledSources = new Set<AudioBufferSourceNode>();\n #playbackCursor = 0;\n // End time (on the AudioContext clock) of the most recently scheduled chunk.\n // Used to detect when the playback bridge has been idle across the gap\n // between turns so it can be rebuilt (see #playAudio).\n #lastPlaybackEnd: number | null = null;\n #playbackElement: HTMLAudioElement | null = null;\n #playbackDestination: MediaStreamAudioDestinationNode | null = null;\n #playbackDestinationPromise: Promise<AudioNode> | null = null;\n #useDefaultPlaybackDestination = false;\n #outputDeviceId: string;\n #outputDeviceSwitchGeneration = 0;\n #playbackOutputGeneration = 0;\n #playbackGeneration = 0;\n #interruptChunkCount = 0;\n\n // Event listeners\n #listeners = new Map<VoiceClientEvent, Set<AnyListener>>();\n\n constructor(options: VoiceClientOptions) {\n this.#options = options;\n this.#silenceThreshold = options.silenceThreshold ?? 0.04;\n this.#silenceDurationMs = options.silenceDurationMs ?? 500;\n this.#interruptThreshold = options.interruptThreshold ?? 0.05;\n this.#interruptChunks = options.interruptChunks ?? 2;\n this.#maxTranscriptMessages = options.maxTranscriptMessages ?? 200;\n this.#outputDeviceId = options.outputDeviceId ?? \"default\";\n }\n\n // --- Public getters ---\n\n get status(): VoiceStatus {\n return this.#status;\n }\n\n get transcript(): TranscriptMessage[] {\n return this.#transcript;\n }\n\n get metrics(): VoicePipelineMetrics | null {\n return this.#metrics;\n }\n\n /** Last stable terminal summary received for any speech or text turn. */\n get turnMetrics(): VoiceTurnMetrics | null {\n return this.#turnMetrics;\n }\n\n get audioLevel(): number {\n return this.#audioLevel;\n }\n\n get isMuted(): boolean {\n return this.#isMuted;\n }\n\n get connected(): boolean {\n return this.#connected;\n }\n\n get error(): string | null {\n return this.#error;\n }\n\n get outputDeviceError(): string | null {\n return this.#outputDeviceError;\n }\n\n /**\n * The current interim (partial) transcript from streaming STT.\n * Updates in real time as the user speaks. Cleared when the final\n * transcript is produced or the call reaches a terminal reset.\n * null when no interim text is available.\n */\n get interimTranscript(): string | null {\n return this.#interimTranscript;\n }\n\n /**\n * The protocol version reported by the server.\n * null until the server sends its welcome message.\n */\n get serverProtocolVersion(): number | null {\n return this.#serverProtocolVersion;\n }\n\n // --- Event system ---\n\n addEventListener<K extends VoiceClientEvent>(\n event: K,\n listener: (data: VoiceClientEventMap[K]) => void\n ): void {\n let set = this.#listeners.get(event);\n if (!set) {\n set = new Set();\n this.#listeners.set(event, set);\n }\n set.add(listener as AnyListener);\n }\n\n removeEventListener<K extends VoiceClientEvent>(\n event: K,\n listener: (data: VoiceClientEventMap[K]) => void\n ): void {\n this.#listeners.get(event)?.delete(listener as AnyListener);\n }\n\n #emit<K extends VoiceClientEvent>(\n event: K,\n data: VoiceClientEventMap[K]\n ): void {\n const set = this.#listeners.get(event);\n if (set) {\n for (const listener of set) {\n listener(data);\n }\n }\n }\n\n #trimTranscript(): void {\n if (this.#transcript.length > this.#maxTranscriptMessages) {\n this.#transcript = this.#transcript.slice(-this.#maxTranscriptMessages);\n }\n }\n\n #setOutputDeviceError(error: string | null): void {\n if (this.#outputDeviceError === error) return;\n this.#outputDeviceError = error;\n this.#emit(\"outputdeviceerror\", error);\n }\n\n #clearInterimTranscript(): void {\n this.#interimTranscript = null;\n this.#emit(\"interimtranscript\", null);\n }\n\n // --- Connection ---\n\n connect(): void {\n if (this.#transport) return;\n\n const transport =\n this.#options.transport ??\n new WebSocketVoiceTransport({\n agent: this.#options.agent,\n name: this.#options.name,\n host: this.#options.host,\n query: this.#options.query\n });\n\n transport.onopen = () => {\n this.#connected = true;\n this.#error = null;\n // Announce our protocol version to the server\n transport.sendJSON({\n type: \"hello\",\n protocol_version: VOICE_PROTOCOL_VERSION\n });\n this.#emit(\"connectionchange\", true);\n this.#emit(\"error\", null);\n\n // Reconnect recovery: if we were in a call when the connection\n // dropped, re-establish it on the new connection. The mic is\n // still running (not stopped on disconnect), so audio resumes\n // flowing as soon as the server processes start_call.\n if (this.#inCall) {\n this.#serverCallAcknowledged = false;\n transport.sendJSON({ type: \"start_call\" });\n }\n };\n\n transport.onclose = (info) => {\n this.#diagnostics.emit(\"connection.closed\", {\n ...(info?.code === undefined ? {} : { code: info.code }),\n clean: info?.wasClean ?? false\n });\n this.#connected = false;\n this.#clearInterimTranscript();\n this.#emit(\"connectionchange\", false);\n this.#emit(\"connectiondiagnostic\", { type: \"close\", ...info });\n };\n\n transport.onerror = (cause) => {\n this.#diagnostics.emit(\"connection.error\", {\n error: toVoiceError(cause, \"Connection failed\")\n });\n this.#emit(\"connectiondiagnostic\", { type: \"error\", cause });\n this.#error = \"Connection lost. Reconnecting...\";\n this.#emit(\"error\", this.#error);\n };\n\n transport.onmessage = (data: string | ArrayBuffer | Blob) => {\n if (typeof data === \"string\") {\n this.#handleJSONMessage(data);\n } else if (data instanceof Blob) {\n data.arrayBuffer().then((buffer) => {\n this.#recordAudioReceived(buffer.byteLength);\n this.#playbackQueue.push(buffer);\n this.#processPlaybackQueue();\n });\n } else if (data instanceof ArrayBuffer) {\n this.#recordAudioReceived(data.byteLength);\n this.#playbackQueue.push(data);\n this.#processPlaybackQueue();\n }\n };\n\n this.#transport = transport;\n transport.connect();\n }\n\n disconnect(): void {\n this.endCall();\n this.#diagnostics.emit(\"connection.disconnecting\");\n this.#transport?.disconnect();\n this.#transport = null;\n this.#connected = false;\n this.#emit(\"connectionchange\", false);\n }\n\n // --- Public actions ---\n\n async startCall(): Promise<void> {\n if (!this.#transport?.connected) {\n this.#error = \"Cannot start call: not connected. Call connect() first.\";\n this.#emit(\"error\", this.#error);\n return;\n }\n if (this.#inCall) return;\n\n this.#clearInterimTranscript();\n const callGeneration = ++this.#callGeneration;\n this.#inCall = true;\n this.#serverCallAcknowledged = false;\n this.#error = null;\n this.#metrics = null;\n this.#emit(\"error\", null);\n this.#emit(\"metricschange\", null);\n const startMsg: Record<string, unknown> = { type: \"start_call\" };\n if (this.#options.preferredFormat) {\n startMsg.preferred_format = this.#options.preferredFormat;\n }\n this.#diagnostics.emit(\"call.starting\");\n this.#transport.sendJSON(startMsg);\n const ctx = await this.#getAudioContext();\n if (this.#abortStaleCallStartup(callGeneration)) return;\n await this.#getPlaybackDestination(ctx);\n if (this.#abortStaleCallStartup(callGeneration)) return;\n if (this.#options.audioInput) {\n this.#diagnostics.emit(\"microphone.starting\", { source: \"custom\" });\n this.#options.audioInput.onAudioLevel = (rms) =>\n this.#processAudioLevel(rms);\n this.#options.audioInput.onAudioData = (pcm) => {\n if (this.#transport?.connected && !this.#isMuted) {\n this.#transport.sendBinary(pcm);\n }\n };\n await this.#options.audioInput.start();\n this.#diagnostics.emit(\"microphone.ready\", { source: \"custom\" });\n } else {\n await this.#startMic();\n }\n if (!this.#abortStaleCallStartup(callGeneration)) {\n this.#diagnostics.emit(\"call.local_ready\");\n }\n }\n\n endCall(): void {\n const wasInCall = this.#inCall;\n this.#callGeneration++;\n this.#inCall = false;\n this.#serverCallAcknowledged = false;\n if (this.#transport?.connected) {\n this.#transport.sendJSON({ type: \"end_call\" });\n }\n this.#stopLocalCall();\n this.#clearInterimTranscript();\n this.#status = \"idle\";\n this.#emit(\"statuschange\", \"idle\");\n if (wasInCall) {\n this.#diagnostics.emit(\"call.ended\", { reason: \"requested\" });\n }\n }\n\n #isCurrentCallStartup(callGeneration: number): boolean {\n return this.#inCall && this.#callGeneration === callGeneration;\n }\n\n #abortStaleCallStartup(callGeneration: number): boolean {\n if (this.#isCurrentCallStartup(callGeneration)) return false;\n if (!this.#inCall) this.#stopLocalCall();\n return true;\n }\n\n #stopLocalCall(): void {\n if (this.#options.audioInput) {\n this.#options.audioInput.stop();\n this.#options.audioInput.onAudioLevel = null;\n this.#options.audioInput.onAudioData = null;\n } else {\n this.#stopMic();\n }\n this.#stopPlayback();\n this.#closeAudioContext();\n this.#resetDetection();\n }\n\n toggleMute(): void {\n this.#isMuted = !this.#isMuted;\n\n // Reset audio level so the UI shows silence while muted.\n if (this.#isMuted) {\n this.#audioLevel = 0;\n this.#emit(\"audiolevelchange\", 0);\n }\n\n // If muting while speaking, flush the current utterance so the server\n // processes accumulated audio instead of waiting forever (deadlock:\n // muted → no audio frames → silence timer never starts → no end_of_speech).\n if (this.#isMuted && this.#isSpeaking) {\n this.#isSpeaking = false;\n if (this.#silenceTimer) {\n clearTimeout(this.#silenceTimer);\n this.#silenceTimer = null;\n }\n if (this.#transport?.connected) {\n this.#transport.sendJSON({ type: \"end_of_speech\" });\n }\n }\n\n this.#emit(\"mutechange\", this.#isMuted);\n }\n\n /**\n * Send a text message to the agent. The agent processes it through\n * `onTurn()` (bypassing STT) and responds with text transcript and\n * TTS audio (if in a call) or text-only (if not).\n */\n sendText(text: string): void {\n if (this.#transport?.connected) {\n this.#transport.sendJSON({ type: \"text_message\", text });\n }\n }\n\n /**\n * Send arbitrary JSON to the agent. Use this for app-level messages\n * that are not part of the voice protocol (e.g. `{ type: \"kick_speaker\" }`).\n * The server receives these in the consumer's `onMessage()` handler.\n */\n sendJSON(data: Record<string, unknown>): void {\n if (this.#transport?.connected) {\n this.#transport.sendJSON(data);\n }\n }\n\n /**\n * Set the preferred audio output device for assistant playback.\n * Unsupported browsers continue playing through the default output.\n */\n async setOutputDevice(outputDeviceId?: string): Promise<void> {\n this.#outputDeviceId = outputDeviceId ?? \"default\";\n const generation = ++this.#outputDeviceSwitchGeneration;\n if (this.#playbackElement) {\n await this.#applyOutputDevice(this.#playbackElement, generation);\n }\n }\n\n /**\n * The last custom (non-voice-protocol) message received from the server.\n * Listen for the `\"custommessage\"` event to be notified when this changes.\n */\n get lastCustomMessage(): unknown {\n return this.#lastCustomMessage;\n }\n\n /**\n * The audio format the server declared for binary payloads.\n * Set when the server sends `audio_config` at call start.\n */\n get audioFormat(): VoiceAudioFormat | null {\n return this.#audioFormat;\n }\n\n /**\n * The sample rate (Hz) the server declared for raw pcm16 payloads.\n * Set when the server sends `audio_config` at call start. Defaults to 16000.\n */\n get sampleRate(): number {\n return this.#sampleRate;\n }\n\n // --- Voice protocol handler ---\n\n #recordAudioReceived(bytes: number): void {\n if (this.#audioReceivedForCurrentTurn) return;\n this.#audioReceivedForCurrentTurn = true;\n this.#diagnostics.emit(\"audio.received\", {\n bytes,\n ...(this.#diagnosticTurnId === null\n ? {}\n : { turn_id: this.#diagnosticTurnId })\n });\n }\n\n #handleJSONMessage(data: string): void {\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(data);\n } catch {\n // Not JSON — ignore (e.g. state sync binary frames)\n return;\n }\n\n switch (msg.type) {\n case \"welcome\": {\n const diagnosticOptions =\n typeof msg.diagnostics === \"object\" && msg.diagnostics !== null\n ? (msg.diagnostics as Record<string, unknown>)\n : null;\n const diagnosticsEnabled = diagnosticOptions?.browser_console === true;\n this.#diagnostics.setEnabled(diagnosticsEnabled);\n if (diagnosticsEnabled) {\n this.#diagnostics.emit(\"connection.ready\", {\n protocol_version: msg.protocol_version as number\n });\n }\n this.#serverProtocolVersion = msg.protocol_version as number;\n if (msg.protocol_version !== VOICE_PROTOCOL_VERSION) {\n console.warn(\n `[VoiceClient] Protocol version mismatch: client=${VOICE_PROTOCOL_VERSION}, server=${msg.protocol_version}`\n );\n }\n break;\n }\n case \"diagnostic\":\n if (\n typeof msg.event === \"string\" &&\n typeof msg.timestamp === \"number\" &&\n Number.isFinite(msg.timestamp)\n ) {\n const data =\n typeof msg.data === \"object\" && msg.data !== null\n ? (msg.data as VoiceDiagnosticEvent[\"data\"])\n : undefined;\n if (\n msg.event === \"audio.first_sent\" &&\n typeof data?.turn_id === \"string\"\n ) {\n this.#diagnosticTurnId = data.turn_id;\n this.#audioReceivedForCurrentTurn = false;\n }\n this.#diagnostics.receive({\n event: msg.event,\n timestamp: msg.timestamp,\n ...(data === undefined ? {} : { data })\n });\n }\n break;\n case \"audio_config\":\n this.#serverCallAcknowledged = true;\n this.#audioFormat = msg.format as VoiceAudioFormat;\n this.#sampleRate =\n typeof msg.sampleRate === \"number\" && msg.sampleRate > 0\n ? msg.sampleRate\n : 16000;\n break;\n case \"status\":\n this.#status = msg.status as VoiceStatus;\n if (msg.status === \"thinking\" || msg.status === \"speaking\") {\n this.#audioReceivedForCurrentTurn = false;\n if (msg.status === \"thinking\") this.#diagnosticTurnId = null;\n }\n if (msg.status === \"idle\" && this.#inCall) {\n const shouldEndLocalCall =\n this.#serverCallAcknowledged || this.#error !== null;\n if (!shouldEndLocalCall) {\n this.#emit(\"statuschange\", this.#status);\n break;\n }\n this.#callGeneration++;\n this.#inCall = false;\n this.#serverCallAcknowledged = false;\n this.#stopLocalCall();\n this.#clearInterimTranscript();\n }\n if (msg.status === \"listening\") {\n this.#serverCallAcknowledged = true;\n this.#error = null;\n this.#emit(\"error\", null);\n } else if (msg.status === \"thinking\" || msg.status === \"speaking\") {\n this.#serverCallAcknowledged = true;\n }\n this.#emit(\"statuschange\", this.#status);\n break;\n case \"transcript_interim\":\n this.#interimTranscript = msg.text as string;\n this.#emit(\"interimtranscript\", this.#interimTranscript);\n break;\n case \"playback_interrupt\":\n this.#stopPlayback(\"server_interrupt\");\n break;\n case \"transcript\":\n // Final transcript arrived — clear interim\n this.#interimTranscript = null;\n this.#emit(\"interimtranscript\", null);\n\n // New user utterance while agent is playing -- stop playback.\n // With continuous STT, the model detects the user's speech\n // server-side, so this arrives before the client's interrupt\n // detection fires.\n if (msg.role === \"user\" && this.#isPlaying) {\n this.#stopPlayback(\"user_utterance\");\n }\n\n this.#transcript = [\n ...this.#transcript,\n {\n role: msg.role as VoiceRole,\n text: msg.text as string,\n timestamp: Date.now()\n }\n ];\n this.#trimTranscript();\n this.#emit(\"transcriptchange\", this.#transcript);\n break;\n case \"transcript_start\":\n this.#transcript = [\n ...this.#transcript,\n { role: \"assistant\", text: \"\", timestamp: Date.now() }\n ];\n this.#trimTranscript();\n this.#emit(\"transcriptchange\", this.#transcript);\n break;\n case \"transcript_delta\": {\n if (this.#transcript.length === 0) break;\n const updated = [...this.#transcript];\n const last = updated[updated.length - 1];\n if (last.role === \"assistant\") {\n updated[updated.length - 1] = {\n ...last,\n text: last.text + (msg.text as string)\n };\n this.#transcript = updated;\n this.#emit(\"transcriptchange\", this.#transcript);\n }\n break;\n }\n case \"transcript_end\": {\n if (this.#transcript.length === 0) break;\n const updated = [...this.#transcript];\n const last = updated[updated.length - 1];\n if (last.role === \"assistant\") {\n updated[updated.length - 1] = {\n ...last,\n text: msg.text as string\n };\n this.#transcript = updated;\n this.#emit(\"transcriptchange\", this.#transcript);\n }\n break;\n }\n case \"metrics\":\n this.#metrics = {\n llm_ms: msg.llm_ms as number,\n tts_ms: msg.tts_ms as number,\n first_audio_ms: msg.first_audio_ms as number,\n total_ms: msg.total_ms as number\n };\n this.#emit(\"metricschange\", this.#metrics);\n break;\n case \"turn_metrics\": {\n const { type: _type, ...payload } = msg;\n const metrics = payload as unknown as VoiceTurnMetrics;\n this.#turnMetrics = metrics;\n this.#emit(\"turnmetrics\", metrics);\n break;\n }\n case \"completion_outcome\": {\n const outcome: VoiceCompletionOutcome = {\n code: msg.code as VoiceCompletionOutcome[\"code\"],\n stage: \"llm\",\n ...(msg.finishReason !== undefined\n ? {\n finishReason:\n msg.finishReason as VoiceCompletionOutcome[\"finishReason\"]\n }\n : {}),\n partialOutput: msg.partialOutput as boolean\n };\n this.#emit(\"completionoutcome\", outcome);\n break;\n }\n case \"error\": {\n const voiceError: VoiceError = {\n message: msg.message as string,\n ...(msg.code !== undefined\n ? { code: msg.code as VoiceError[\"code\"] }\n : {}),\n ...(msg.stage !== undefined\n ? { stage: msg.stage as VoiceError[\"stage\"] }\n : {}),\n ...(msg.retryable !== undefined\n ? { retryable: msg.retryable as boolean }\n : {})\n };\n this.#error = voiceError.message;\n this.#emit(\"voiceerror\", voiceError);\n this.#emit(\"error\", this.#error);\n break;\n }\n default:\n // App-level custom message — surface via event\n this.#lastCustomMessage = msg;\n this.#emit(\"custommessage\", msg);\n break;\n }\n }\n\n // --- Audio context management ---\n\n /** Get or create the shared AudioContext. */\n async #getAudioContext(): Promise<AudioContext> {\n if (!this.#audioContext) {\n this.#audioContext = new AudioContext({ sampleRate: 48000 });\n }\n if (this.#audioContext.state === \"suspended\") {\n await this.#audioContext.resume();\n }\n return this.#audioContext;\n }\n\n /** Close the AudioContext and release resources. */\n #closeAudioContext(): void {\n if (this.#audioContext) {\n this.#closePlaybackOutput();\n this.#audioContext.close().catch(() => {});\n this.#audioContext = null;\n this.#workletRegistered = false;\n }\n }\n\n async #getPlaybackDestination(ctx: AudioContext): Promise<AudioNode> {\n if (this.#playbackDestinationPromise) {\n return this.#playbackDestinationPromise;\n }\n if (this.#playbackDestination) return this.#playbackDestination;\n if (this.#useDefaultPlaybackDestination) return ctx.destination;\n\n const outputGeneration = this.#playbackOutputGeneration;\n const promise = this.#initializePlaybackDestination(ctx, outputGeneration);\n this.#playbackDestinationPromise = promise;\n try {\n return await promise;\n } finally {\n if (this.#playbackDestinationPromise === promise) {\n this.#playbackDestinationPromise = null;\n }\n }\n }\n\n async #initializePlaybackDestination(\n ctx: AudioContext,\n outputGeneration: number\n ): Promise<AudioNode> {\n try {\n const destination = ctx.createMediaStreamDestination();\n const audio = new Audio();\n audio.autoplay = true;\n audio.srcObject = destination.stream;\n this.#playbackElement = audio;\n this.#playbackDestination = destination;\n await this.#applyOutputDevice(audio, this.#outputDeviceSwitchGeneration);\n if (!this.#isCurrentPlaybackOutput(audio, outputGeneration)) {\n this.#releasePlaybackElement(audio);\n return ctx.destination;\n }\n await audio.play();\n if (!this.#isCurrentPlaybackOutput(audio, outputGeneration)) {\n this.#releasePlaybackElement(audio);\n return ctx.destination;\n }\n return destination;\n } catch (err) {\n console.warn(\n \"[VoiceClient] HTMLAudioElement playback output unavailable; using default AudioContext destination.\",\n err\n );\n this.#closePlaybackOutput();\n this.#useDefaultPlaybackDestination = true;\n return ctx.destination;\n }\n }\n\n #isCurrentPlaybackOutput(\n audio: HTMLAudioElement,\n outputGeneration: number\n ): boolean {\n return (\n this.#playbackElement === audio &&\n this.#playbackOutputGeneration === outputGeneration\n );\n }\n\n async #applyOutputDevice(\n audio: HTMLAudioElement,\n generation: number\n ): Promise<void> {\n const sinkId = this.#outputDeviceId;\n const setSinkId = (audio as AudioElementWithSinkId).setSinkId;\n if (!setSinkId) {\n if (sinkId === \"default\") {\n this.#setOutputDeviceError(null);\n return;\n }\n this.#setOutputDeviceError(UNSUPPORTED_OUTPUT_DEVICE_ERROR);\n return;\n }\n\n try {\n await setSinkId.call(audio, sinkId);\n if (\n generation !== this.#outputDeviceSwitchGeneration ||\n sinkId !== this.#outputDeviceId\n ) {\n if (this.#playbackElement === audio) {\n await this.#applyOutputDevice(\n audio,\n this.#outputDeviceSwitchGeneration\n );\n }\n return;\n }\n if (\n this.#outputDeviceError === UNSUPPORTED_OUTPUT_DEVICE_ERROR ||\n this.#outputDeviceError === OUTPUT_DEVICE_SWITCH_ERROR\n ) {\n this.#setOutputDeviceError(null);\n }\n } catch {\n if (\n generation !== this.#outputDeviceSwitchGeneration ||\n sinkId !== this.#outputDeviceId\n ) {\n if (this.#playbackElement === audio) {\n await this.#applyOutputDevice(\n audio,\n this.#outputDeviceSwitchGeneration\n );\n }\n return;\n }\n this.#setOutputDeviceError(OUTPUT_DEVICE_SWITCH_ERROR);\n }\n }\n\n #closePlaybackOutput(): void {\n this.#playbackOutputGeneration++;\n if (this.#playbackElement) {\n this.#releasePlaybackElement(this.#playbackElement);\n this.#playbackElement = null;\n }\n this.#playbackDestination = null;\n this.#playbackDestinationPromise = null;\n this.#useDefaultPlaybackDestination = false;\n }\n\n #releasePlaybackElement(audio: HTMLAudioElement): void {\n audio.pause();\n audio.srcObject = null;\n }\n\n // --- Audio playback ---\n\n async #playAudio(audioData: ArrayBuffer, generation: number): Promise<void> {\n try {\n const ctx = await this.#getAudioContext();\n\n let audioBuffer: AudioBuffer;\n if (this.#audioFormat === \"pcm16\") {\n // Raw 16-bit LE mono PCM — sample rate comes from server audio_config\n const int16 = new Int16Array(audioData);\n audioBuffer = ctx.createBuffer(1, int16.length, this.#sampleRate);\n const channel = audioBuffer.getChannelData(0);\n for (let i = 0; i < int16.length; i++) {\n channel[i] = int16[i] / 32768;\n }\n } else {\n // mp3, wav, opus — let the browser decode\n audioBuffer = await ctx.decodeAudioData(audioData.slice(0));\n }\n if (generation !== this.#playbackGeneration) return;\n\n // Assistant playback is routed through a MediaStreamAudioDestinationNode\n // -> HTMLAudioElement bridge (so a selected output device can be honored\n // via HTMLMediaElement.setSinkId). That bridge is a live playout path:\n // when it is reused for a new turn after sitting idle through the gap\n // between turns, the element resumes the fresh burst at the wrong rate and\n // the new turn plays back noticeably slow (it then re-converges to normal\n // over the turn). A freshly created element does not show this, so once\n // the bridge has fully drained and been idle past a short threshold, tear\n // it down; #getPlaybackDestination rebuilds a fresh element for this turn.\n // The scheduledSources.size === 0 guard means this never fires mid-turn:\n // chunks within a turn are scheduled ahead on the cursor, keeping at least\n // one source live until the turn finishes.\n const BRIDGE_IDLE_REBUILD_SECONDS = 0.3;\n if (\n this.#playbackElement &&\n this.#scheduledSources.size === 0 &&\n this.#lastPlaybackEnd !== null &&\n ctx.currentTime - this.#lastPlaybackEnd > BRIDGE_IDLE_REBUILD_SECONDS\n ) {\n this.#closePlaybackOutput();\n }\n\n const destination = await this.#getPlaybackDestination(ctx);\n if (generation !== this.#playbackGeneration) return;\n\n const source = ctx.createBufferSource();\n source.buffer = audioBuffer;\n source.connect(destination);\n this.#scheduledSources.add(source);\n source.onended = () => {\n this.#scheduledSources.delete(source);\n if (\n generation === this.#playbackGeneration &&\n !this.#isScheduling &&\n this.#scheduledSources.size === 0 &&\n this.#playbackQueue.length === 0\n ) {\n this.#isPlaying = false;\n this.#diagnostics.emit(\"playback.completed\");\n }\n };\n\n // Schedule on the audio clock, butted against the previous chunk.\n // Starting at currentTime only after the previous chunk's `ended`\n // event leaves a few ms of silence at every chunk seam, audible as\n // a periodic click during agent speech.\n const startAt = Math.max(ctx.currentTime, this.#playbackCursor);\n this.#playbackCursor = startAt + audioBuffer.duration;\n this.#lastPlaybackEnd = this.#playbackCursor;\n source.start(startAt);\n } catch (err) {\n this.#diagnostics.emit(\"playback.error\", {\n error: toVoiceError(err, \"Playback failed\")\n });\n console.error(\"[VoiceClient] Audio playback error:\", err);\n }\n }\n\n async #processPlaybackQueue(): Promise<void> {\n if (this.#isScheduling || this.#playbackQueue.length === 0) return;\n this.#isScheduling = true;\n this.#isPlaying = true;\n this.#diagnostics.emit(\"playback.started\", {\n chunks: this.#playbackQueue.length\n });\n const generation = this.#playbackGeneration;\n\n while (\n generation === this.#playbackGeneration &&\n this.#playbackQueue.length > 0\n ) {\n const audioData = this.#playbackQueue.shift()!;\n await this.#playAudio(audioData, generation);\n }\n\n if (generation === this.#playbackGeneration) {\n this.#isScheduling = false;\n if (this.#scheduledSources.size === 0) {\n this.#isPlaying = false;\n }\n }\n }\n\n #stopPlayback(reason = \"stopped\"): void {\n const wasActive =\n this.#isPlaying ||\n this.#isScheduling ||\n this.#playbackQueue.length > 0 ||\n this.#scheduledSources.size > 0;\n this.#playbackGeneration++;\n const sources = [...this.#scheduledSources];\n this.#scheduledSources.clear();\n for (const source of sources) {\n try {\n source.stop();\n } catch {\n // The source may already have ended or been stopped by another signal.\n }\n }\n this.#playbackQueue = [];\n this.#isPlaying = false;\n this.#isScheduling = false;\n this.#playbackCursor = 0;\n // An interrupt (barge-in or a user transcript) stops playback abruptly, so\n // the bridge goes idle from now, not from the cut chunk's scheduled end.\n // Record the current audio-clock time as the idle start so the next turn's\n // rebuild check in #playAudio still fires after interrupt -> long pause ->\n // new turn. Nulling this here would disable that check and let the slow-\n // playback symptom reappear on the post-interrupt turn.\n this.#lastPlaybackEnd = this.#audioContext\n ? this.#audioContext.currentTime\n : null;\n if (wasActive) {\n this.#diagnostics.emit(\"playback.stopped\", { reason });\n }\n }\n\n // --- Mic capture ---\n\n async #startMic(): Promise<void> {\n this.#diagnostics.emit(\"microphone.starting\", { source: \"browser\" });\n try {\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: {\n sampleRate: { ideal: 48000 },\n channelCount: 1,\n echoCancellation: true,\n noiseSuppression: true,\n autoGainControl: true\n }\n });\n this.#stream = stream;\n\n const ctx = await this.#getAudioContext();\n\n // Only register the worklet processor once per AudioContext.\n // Calling addModule twice with the same processor name throws.\n if (!this.#workletRegistered) {\n const blob = new Blob([WORKLET_PROCESSOR], {\n type: \"application/javascript\"\n });\n const workletUrl = URL.createObjectURL(blob);\n await ctx.audioWorklet.addModule(workletUrl);\n URL.revokeObjectURL(workletUrl);\n this.#workletRegistered = true;\n }\n\n const source = ctx.createMediaStreamSource(stream);\n const workletNode = new AudioWorkletNode(ctx, \"audio-capture-processor\");\n this.#workletNode = workletNode;\n\n workletNode.port.onmessage = (event: MessageEvent) => {\n if (event.data.type === \"audio\" && !this.#isMuted) {\n const samples = event.data.samples as Float32Array;\n const rms = computeRMS(samples);\n\n // Send PCM to agent\n const pcm = floatTo16BitPCM(samples);\n if (this.#transport?.connected) {\n this.#transport.sendBinary(pcm);\n }\n\n this.#processAudioLevel(rms);\n }\n };\n\n source.connect(workletNode);\n workletNode.connect(ctx.destination);\n this.#diagnostics.emit(\"microphone.ready\", { source: \"browser\" });\n } catch (err) {\n this.#diagnostics.emit(\"microphone.error\", {\n error: toVoiceError(err, \"Microphone failed\")\n });\n console.error(\"[VoiceClient] Mic error:\", err);\n this.#error =\n \"Microphone access denied. Please allow microphone access and try again.\";\n this.#emit(\"error\", this.#error);\n }\n }\n\n #stopMic(): void {\n const wasActive = this.#workletNode !== null || this.#stream !== null;\n this.#workletNode?.disconnect();\n this.#workletNode = null;\n this.#stream?.getTracks().forEach((track) => track.stop());\n this.#stream = null;\n if (wasActive) this.#diagnostics.emit(\"microphone.stopped\");\n this.#resetDetection();\n }\n\n // --- Audio level processing (shared between built-in mic and custom audioInput) ---\n\n #processAudioLevel(rms: number): void {\n // When muted, ignore incoming audio levels. This prevents false\n // speech detection when a custom audioInput keeps reporting levels.\n // The built-in mic already gates on !#isMuted before calling here,\n // but audioInput implementations don't know about mute state.\n if (this.#isMuted) return;\n\n this.#audioLevel = rms;\n this.#emit(\"audiolevelchange\", rms);\n\n // Interruption detection: user speaking during agent playback\n if (this.#isPlaying && rms > this.#interruptThreshold) {\n this.#interruptChunkCount++;\n if (this.#interruptChunkCount >= this.#interruptChunks) {\n this.#diagnostics.emit(\"speech.interrupt_detected\");\n this.#stopPlayback(\"speech_interrupt\");\n this.#interruptChunkCount = 0;\n if (this.#transport?.connected) {\n this.#transport.sendJSON({ type: \"interrupt\" });\n }\n }\n } else {\n this.#interruptChunkCount = 0;\n }\n\n // Silence detection\n if (rms > this.#silenceThreshold) {\n if (!this.#isSpeaking) {\n this.#isSpeaking = true;\n this.#diagnostics.emit(\"speech.started\");\n // Notify server that speech started (for streaming STT)\n if (this.#transport?.connected) {\n this.#transport.sendJSON({ type: \"start_of_speech\" });\n }\n }\n if (this.#silenceTimer) {\n clearTimeout(this.#silenceTimer);\n this.#silenceTimer = null;\n }\n } else if (this.#isSpeaking) {\n if (!this.#silenceTimer) {\n this.#silenceTimer = setTimeout(() => {\n this.#isSpeaking = false;\n this.#silenceTimer = null;\n this.#diagnostics.emit(\"speech.ended\");\n if (this.#transport?.connected) {\n this.#transport.sendJSON({ type: \"end_of_speech\" });\n }\n }, this.#silenceDurationMs);\n }\n }\n }\n\n #resetDetection(): void {\n if (this.#silenceTimer) {\n clearTimeout(this.#silenceTimer);\n this.#silenceTimer = null;\n }\n this.#isSpeaking = false;\n this.#interruptChunkCount = 0;\n this.#audioLevel = 0;\n this.#emit(\"audiolevelchange\", 0);\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ //#region src/voice/errors.d.ts
2
+ interface VoiceProviderErrorOptions {
3
+ code?: string | number;
4
+ status?: number;
5
+ closeCode?: number;
6
+ closeReason?: string;
7
+ wasClean?: boolean;
8
+ }
9
+ /**
10
+ * Error raised at a voice provider boundary. Only known, content-free provider
11
+ * metadata belongs here. Provider response bodies and raw events must stay out.
12
+ */
13
+ declare class VoiceProviderError extends Error {
14
+ readonly code?: string | number;
15
+ readonly status?: number;
16
+ readonly closeCode?: number;
17
+ readonly closeReason?: string;
18
+ readonly wasClean?: boolean;
19
+ constructor(message: string, options?: VoiceProviderErrorOptions);
20
+ }
21
+ interface VoiceErrorLogOptions {
22
+ component: string;
23
+ stage: string;
24
+ message: string;
25
+ error: Error;
26
+ connectionId?: string;
27
+ }
28
+ /** Convert a value caught from an external boundary without inspecting it. */
29
+ declare function toVoiceError(error: unknown, fallback: string): Error;
30
+ /** Return a bounded direct message suitable for the existing string wire API. */
31
+ declare function voiceErrorMessage(error: Error, fallback: string): string;
32
+ /** Emit one structured object so Workers Logs can extract diagnostic fields. */
33
+ declare function logVoiceError(options: VoiceErrorLogOptions): void;
34
+ //#endregion
35
+ export {
36
+ VoiceErrorLogOptions,
37
+ VoiceProviderError,
38
+ VoiceProviderErrorOptions,
39
+ logVoiceError,
40
+ toVoiceError,
41
+ voiceErrorMessage
42
+ };
43
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1,41 @@
1
+ //#region src/voice/errors.ts
2
+ const MAX_CLIENT_MESSAGE_LENGTH = 300;
3
+ /**
4
+ * Error raised at a voice provider boundary. Only known, content-free provider
5
+ * metadata belongs here. Provider response bodies and raw events must stay out.
6
+ */
7
+ var VoiceProviderError = class extends Error {
8
+ constructor(message, options = {}) {
9
+ super(message);
10
+ this.name = "VoiceProviderError";
11
+ if (options.code !== void 0) this.code = options.code;
12
+ if (options.status !== void 0) this.status = options.status;
13
+ if (options.closeCode !== void 0) this.closeCode = options.closeCode;
14
+ if (options.closeReason !== void 0) this.closeReason = options.closeReason;
15
+ if (options.wasClean !== void 0) this.wasClean = options.wasClean;
16
+ }
17
+ };
18
+ /** Convert a value caught from an external boundary without inspecting it. */
19
+ function toVoiceError(error, fallback) {
20
+ return error instanceof Error ? error : new Error(fallback);
21
+ }
22
+ /** Return a bounded direct message suitable for the existing string wire API. */
23
+ function voiceErrorMessage(error, fallback) {
24
+ const message = error.message.trim();
25
+ if (!message || message === "[object Object]") return fallback;
26
+ return message.slice(0, MAX_CLIENT_MESSAGE_LENGTH);
27
+ }
28
+ /** Emit one structured object so Workers Logs can extract diagnostic fields. */
29
+ function logVoiceError(options) {
30
+ console.error({
31
+ component: options.component,
32
+ stage: options.stage,
33
+ message: options.message,
34
+ ...options.connectionId ? { connectionId: options.connectionId } : {},
35
+ error: options.error
36
+ });
37
+ }
38
+ //#endregion
39
+ export { VoiceProviderError, logVoiceError, toVoiceError, voiceErrorMessage };
40
+
41
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","names":[],"sources":["../../src/voice/errors.ts"],"sourcesContent":["const MAX_CLIENT_MESSAGE_LENGTH = 300;\n\nexport interface VoiceProviderErrorOptions {\n code?: string | number;\n status?: number;\n closeCode?: number;\n closeReason?: string;\n wasClean?: boolean;\n}\n\n/**\n * Error raised at a voice provider boundary. Only known, content-free provider\n * metadata belongs here. Provider response bodies and raw events must stay out.\n */\nexport class VoiceProviderError extends Error {\n readonly code?: string | number;\n readonly status?: number;\n readonly closeCode?: number;\n readonly closeReason?: string;\n readonly wasClean?: boolean;\n\n constructor(message: string, options: VoiceProviderErrorOptions = {}) {\n super(message);\n this.name = \"VoiceProviderError\";\n if (options.code !== undefined) this.code = options.code;\n if (options.status !== undefined) this.status = options.status;\n if (options.closeCode !== undefined) this.closeCode = options.closeCode;\n if (options.closeReason !== undefined) {\n this.closeReason = options.closeReason;\n }\n if (options.wasClean !== undefined) this.wasClean = options.wasClean;\n }\n}\n\nexport interface VoiceErrorLogOptions {\n component: string;\n stage: string;\n message: string;\n error: Error;\n connectionId?: string;\n}\n\n/** Convert a value caught from an external boundary without inspecting it. */\nexport function toVoiceError(error: unknown, fallback: string): Error {\n return error instanceof Error ? error : new Error(fallback);\n}\n\n/** Return a bounded direct message suitable for the existing string wire API. */\nexport function voiceErrorMessage(error: Error, fallback: string): string {\n const message = error.message.trim();\n if (!message || message === \"[object Object]\") return fallback;\n return message.slice(0, MAX_CLIENT_MESSAGE_LENGTH);\n}\n\n/** Emit one structured object so Workers Logs can extract diagnostic fields. */\nexport function logVoiceError(options: VoiceErrorLogOptions): void {\n console.error({\n component: options.component,\n stage: options.stage,\n message: options.message,\n ...(options.connectionId ? { connectionId: options.connectionId } : {}),\n error: options.error\n });\n}\n"],"mappings":";AAAA,MAAM,4BAA4B;;;;;AAclC,IAAa,qBAAb,cAAwC,MAAM;CAO5C,YAAY,SAAiB,UAAqC,CAAC,GAAG;EACpE,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,IAAI,QAAQ,SAAS,KAAA,GAAW,KAAK,OAAO,QAAQ;EACpD,IAAI,QAAQ,WAAW,KAAA,GAAW,KAAK,SAAS,QAAQ;EACxD,IAAI,QAAQ,cAAc,KAAA,GAAW,KAAK,YAAY,QAAQ;EAC9D,IAAI,QAAQ,gBAAgB,KAAA,GAC1B,KAAK,cAAc,QAAQ;EAE7B,IAAI,QAAQ,aAAa,KAAA,GAAW,KAAK,WAAW,QAAQ;CAC9D;AACF;;AAWA,SAAgB,aAAa,OAAgB,UAAyB;CACpE,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,QAAQ;AAC5D;;AAGA,SAAgB,kBAAkB,OAAc,UAA0B;CACxE,MAAM,UAAU,MAAM,QAAQ,KAAK;CACnC,IAAI,CAAC,WAAW,YAAY,mBAAmB,OAAO;CACtD,OAAO,QAAQ,MAAM,GAAG,yBAAyB;AACnD;;AAGA,SAAgB,cAAc,SAAqC;CACjE,QAAQ,MAAM;EACZ,WAAW,QAAQ;EACnB,OAAO,QAAQ;EACf,SAAS,QAAQ;EACjB,GAAI,QAAQ,eAAe,EAAE,cAAc,QAAQ,aAAa,IAAI,CAAC;EACrE,OAAO,QAAQ;CACjB,CAAC;AACH"}
@@ -0,0 +1,271 @@
1
+ import { b as Connection } from "../capability-runner-Be_-PLR1.js";
2
+ import { c as Agent } from "../agent-routing-DE5zmCQ8.js";
3
+ import {
4
+ C as VoiceTransport,
5
+ D as VoiceTurnSource,
6
+ E as VoiceTurnOutcome,
7
+ S as VoiceStatus,
8
+ T as VoiceTurnMetrics,
9
+ _ as VoiceErrorStage,
10
+ a as TranscriberSessionOptions,
11
+ b as VoiceRole,
12
+ c as VoiceAudioFormat,
13
+ d as VoiceCompletionOutcome,
14
+ f as VoiceCompletionOutcomeCode,
15
+ g as VoiceErrorCode,
16
+ h as VoiceError,
17
+ i as TranscriberSession,
18
+ l as VoiceAudioInput,
19
+ m as VoiceDiagnosticsOptions,
20
+ n as TTSProvider,
21
+ o as TranscriptMessage,
22
+ p as VoiceDiagnosticEvent,
23
+ r as Transcriber,
24
+ s as VOICE_PROTOCOL_VERSION,
25
+ t as StreamingTTSProvider,
26
+ u as VoiceClientMessage,
27
+ v as VoiceModelFinishReason,
28
+ w as VoiceTransportCloseInfo,
29
+ x as VoiceServerMessage,
30
+ y as VoicePipelineMetrics
31
+ } from "../types-_Faxb570.js";
32
+ import {
33
+ n as TextSource,
34
+ r as iterateText,
35
+ t as SentenceChunker
36
+ } from "../sentence-chunker-BAidJ4DA.js";
37
+ import {
38
+ SFUConfig,
39
+ addSFUTracks,
40
+ createSFUSession,
41
+ createSFUWebSocketAdapter,
42
+ decodeVarint,
43
+ downsample48kStereoTo16kMono,
44
+ encodePayloadToProtobuf,
45
+ encodeVarint,
46
+ extractPayloadFromProtobuf,
47
+ renegotiateSFUSession,
48
+ sfuFetch,
49
+ upsample16kMonoTo48kStereo
50
+ } from "./sfu.js";
51
+ import {
52
+ WorkersAIFluxSTT,
53
+ WorkersAIFluxSTTOptions,
54
+ WorkersAINova3STT,
55
+ WorkersAINova3STTOptions,
56
+ WorkersAITTS,
57
+ WorkersAITTSOptions
58
+ } from "./workers-ai.js";
59
+
60
+ //#region src/voice/voice-input.d.ts
61
+ type Constructor$1<T = object> = new (...args: any[]) => T;
62
+ type AgentLike$1 = Constructor$1<Pick<Agent<Cloudflare.Env>, "keepAlive">>;
63
+ /** Configuration options for the voice input mixin. */
64
+ interface VoiceInputOptions {
65
+ /** Optional diagnostic output. Diagnostic event names and metadata are not stable API. */
66
+ diagnostics?: VoiceDiagnosticsOptions;
67
+ }
68
+ /** Public surface of the voice input mixin, used as an explicit return type to satisfy TS6 declaration emit. */
69
+ interface VoiceInputMixinMembers {
70
+ transcriber?: Transcriber;
71
+ onTranscript(text: string, connection: Connection): void | Promise<void>;
72
+ createTranscriber(connection: Connection): Transcriber | null;
73
+ beforeCallStart(connection: Connection): boolean | Promise<boolean>;
74
+ onCallStart(connection: Connection): void | Promise<void>;
75
+ onCallEnd(connection: Connection): void | Promise<void>;
76
+ onInterrupt(connection: Connection): void | Promise<void>;
77
+ afterTranscribe(
78
+ transcript: string,
79
+ connection: Connection
80
+ ): string | null | Promise<string | null>;
81
+ }
82
+ type VoiceInputMixinReturn<TBase extends AgentLike$1> = TBase &
83
+ (new (...args: any[]) => VoiceInputMixinMembers);
84
+ /**
85
+ * Voice-to-text input mixin. Adds STT-only voice input to an Agent class.
86
+ *
87
+ * Subclasses must set a `transcriber` property (or override `createTranscriber`).
88
+ * No TTS provider is needed. Override `onTranscript` to handle each
89
+ * transcribed utterance.
90
+ *
91
+ * @param Base - The Agent class to extend (e.g. `Agent`).
92
+ * @param voiceInputOptions - Optional pipeline configuration.
93
+ *
94
+ * @example
95
+ * ```typescript
96
+ * import { Agent } from "../index";
97
+ * import { withVoiceInput, WorkersAINova3STT } from "agents/voice";
98
+ *
99
+ * const InputAgent = withVoiceInput(Agent);
100
+ *
101
+ * class MyAgent extends InputAgent<Env> {
102
+ * transcriber = new WorkersAINova3STT(this.env.AI);
103
+ *
104
+ * onTranscript(text, connection) {
105
+ * console.log("User said:", text);
106
+ * }
107
+ * }
108
+ * ```
109
+ */
110
+ declare function withVoiceInput<TBase extends AgentLike$1>(
111
+ Base: TBase,
112
+ voiceInputOptions?: VoiceInputOptions
113
+ ): VoiceInputMixinReturn<TBase>;
114
+ //#endregion
115
+ //#region src/voice/index.d.ts
116
+ /** Context passed to the `onTurn()` hook. */
117
+ interface VoiceTurnContext {
118
+ connection: Connection;
119
+ /** Completed conversation history before the current transcript. */
120
+ messages: Array<{
121
+ role: VoiceRole;
122
+ content: string;
123
+ }>;
124
+ signal: AbortSignal;
125
+ }
126
+ /** Configuration options for the voice mixin. Passed to `withVoice()`. */
127
+ interface VoiceAgentOptions {
128
+ /** Max conversation history messages loaded for context. @default 20 */
129
+ historyLimit?: number;
130
+ /** Audio format used for binary audio payloads sent to the client. @default "mp3" */
131
+ audioFormat?: VoiceAudioFormat;
132
+ /**
133
+ * Sample rate (Hz) of raw PCM audio payloads sent to the client.
134
+ * Declared in the `audio_config` message so the client can play `pcm16`
135
+ * at the provider's native rate (e.g. 24000 for Gemini TTS).
136
+ * Encoded formats (mp3/wav/opus) carry their own rate and ignore this.
137
+ * @default 16000
138
+ */
139
+ sampleRate?: number;
140
+ /** Max conversation messages to keep in SQLite. Oldest are pruned. @default 1000 */
141
+ maxMessageCount?: number;
142
+ /** Optional diagnostic output. Diagnostic event names and metadata are not stable API. */
143
+ diagnostics?: VoiceDiagnosticsOptions;
144
+ }
145
+ type Constructor<T = object> = new (...args: any[]) => T;
146
+ type AgentLike = Constructor<
147
+ Pick<Agent<Cloudflare.Env>, "sql" | "getConnections" | "keepAlive">
148
+ >;
149
+ /** Public surface of the voice mixin, used as an explicit return type to satisfy TS6 declaration emit. */
150
+ interface VoiceAgentMixinMembers {
151
+ transcriber?: Transcriber;
152
+ tts?: (TTSProvider & Partial<StreamingTTSProvider>) | undefined;
153
+ onTurn(transcript: string, context: VoiceTurnContext): Promise<TextSource>;
154
+ createTranscriber(connection: Connection): Transcriber | null;
155
+ beforeCallStart(connection: Connection): boolean | Promise<boolean>;
156
+ onCallStart(connection: Connection): void | Promise<void>;
157
+ onCallEnd(connection: Connection): void | Promise<void>;
158
+ onInterrupt(connection: Connection): void | Promise<void>;
159
+ afterTranscribe(
160
+ transcript: string,
161
+ connection: Connection
162
+ ): string | null | Promise<string | null>;
163
+ beforeSynthesize(
164
+ text: string,
165
+ connection: Connection
166
+ ): string | null | Promise<string | null>;
167
+ afterSynthesize(
168
+ audio: ArrayBuffer | null,
169
+ text: string,
170
+ connection: Connection
171
+ ): ArrayBuffer | null | Promise<ArrayBuffer | null>;
172
+ saveMessage(role: "user" | "assistant", text: string): void;
173
+ getConversationHistory(limit?: number): Array<{
174
+ role: VoiceRole;
175
+ content: string;
176
+ }>;
177
+ forceEndCall(connection: Connection): void;
178
+ speak(connection: Connection, text: string): Promise<void>;
179
+ speakAll(text: string): Promise<void>;
180
+ }
181
+ type VoiceAgentMixinReturn<TBase extends AgentLike> = TBase &
182
+ (new (...args: any[]) => VoiceAgentMixinMembers);
183
+ /**
184
+ * Voice pipeline mixin. Adds the full voice pipeline to an Agent class.
185
+ *
186
+ * Subclasses must set a `transcriber` property (or override `createTranscriber`)
187
+ * and a `tts` provider property. The transcriber session is per-call — created
188
+ * at start_call and closed at end_call. The model handles turn detection.
189
+ *
190
+ * @param Base - The Agent class to extend (e.g. `Agent`).
191
+ * @param voiceOptions - Optional pipeline configuration.
192
+ *
193
+ * @example
194
+ * ```typescript
195
+ * import { Agent } from "../index";
196
+ * import { withVoice, WorkersAIFluxSTT, WorkersAITTS } from "agents/voice";
197
+ *
198
+ * const VoiceAgent = withVoice(Agent);
199
+ *
200
+ * class MyAgent extends VoiceAgent<Env> {
201
+ * transcriber = new WorkersAIFluxSTT(this.env.AI);
202
+ * tts = new WorkersAITTS(this.env.AI);
203
+ *
204
+ * async onTurn(transcript, context) {
205
+ * return "Hello! I heard you say: " + transcript;
206
+ * }
207
+ * }
208
+ * ```
209
+ */
210
+ declare function withVoice<TBase extends AgentLike>(
211
+ Base: TBase,
212
+ voiceOptions?: VoiceAgentOptions
213
+ ): VoiceAgentMixinReturn<TBase>;
214
+ //#endregion
215
+ export {
216
+ type SFUConfig,
217
+ SentenceChunker,
218
+ type StreamingTTSProvider,
219
+ type TTSProvider,
220
+ type TextSource,
221
+ type Transcriber,
222
+ type TranscriberSession,
223
+ type TranscriberSessionOptions,
224
+ type TranscriptMessage,
225
+ VOICE_PROTOCOL_VERSION,
226
+ VoiceAgentMixinMembers,
227
+ VoiceAgentOptions,
228
+ type VoiceAudioFormat,
229
+ type VoiceAudioInput,
230
+ type VoiceClientMessage,
231
+ type VoiceCompletionOutcome,
232
+ type VoiceCompletionOutcomeCode,
233
+ type VoiceDiagnosticEvent,
234
+ type VoiceDiagnosticsOptions,
235
+ type VoiceError,
236
+ type VoiceErrorCode,
237
+ type VoiceErrorStage,
238
+ type VoiceInputOptions,
239
+ type VoiceModelFinishReason,
240
+ type VoicePipelineMetrics,
241
+ type VoiceRole,
242
+ type VoiceServerMessage,
243
+ type VoiceStatus,
244
+ type VoiceTransport,
245
+ type VoiceTransportCloseInfo,
246
+ VoiceTurnContext,
247
+ type VoiceTurnMetrics,
248
+ type VoiceTurnOutcome,
249
+ type VoiceTurnSource,
250
+ WorkersAIFluxSTT,
251
+ type WorkersAIFluxSTTOptions,
252
+ WorkersAINova3STT,
253
+ type WorkersAINova3STTOptions,
254
+ WorkersAITTS,
255
+ type WorkersAITTSOptions,
256
+ addSFUTracks,
257
+ createSFUSession,
258
+ createSFUWebSocketAdapter,
259
+ decodeVarint,
260
+ downsample48kStereoTo16kMono,
261
+ encodePayloadToProtobuf,
262
+ encodeVarint,
263
+ extractPayloadFromProtobuf,
264
+ iterateText,
265
+ renegotiateSFUSession,
266
+ sfuFetch,
267
+ upsample16kMonoTo48kStereo,
268
+ withVoice,
269
+ withVoiceInput
270
+ };
271
+ //# sourceMappingURL=index.d.ts.map