agents 0.22.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 (186) hide show
  1. package/README.md +20 -1
  2. package/dist/{agent-routing-CnkaHb-v.d.ts → agent-routing-DE5zmCQ8.d.ts} +1038 -394
  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-DtXMTDGM.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.map +1 -1
  15. package/dist/capability-runner-Be_-PLR1.d.ts +459 -0
  16. package/dist/channel-Bnm4S7T2.d.ts +491 -0
  17. package/dist/channels/ai-sdk.d.ts +46 -0
  18. package/dist/channels/ai-sdk.js +120 -0
  19. package/dist/channels/ai-sdk.js.map +1 -0
  20. package/dist/channels/email.d.ts +95 -0
  21. package/dist/channels/email.js +323 -0
  22. package/dist/channels/email.js.map +1 -0
  23. package/dist/channels/index.d.ts +233 -0
  24. package/dist/channels/index.js +608 -0
  25. package/dist/channels/index.js.map +1 -0
  26. package/dist/channels/slack.d.ts +140 -0
  27. package/dist/channels/slack.js +614 -0
  28. package/dist/channels/slack.js.map +1 -0
  29. package/dist/channels/tanstack-ai.d.ts +39 -0
  30. package/dist/channels/tanstack-ai.js +17 -0
  31. package/dist/channels/tanstack-ai.js.map +1 -0
  32. package/dist/channels/telegram.d.ts +106 -0
  33. package/dist/channels/telegram.js +427 -0
  34. package/dist/channels/telegram.js.map +1 -0
  35. package/dist/channels/voice.d.ts +45 -0
  36. package/dist/channels/voice.js +122 -0
  37. package/dist/channels/voice.js.map +1 -0
  38. package/dist/chat/index.d.ts +2325 -2019
  39. package/dist/chat/index.js +888 -518
  40. package/dist/chat/index.js.map +1 -1
  41. package/dist/chat-sdk/index.d.ts +7 -7
  42. package/dist/chat-sdk/index.js +1 -1
  43. package/dist/client.d.ts +1 -1
  44. package/dist/context/index.d.ts +216 -0
  45. package/dist/context/index.js +454 -0
  46. package/dist/context/index.js.map +1 -0
  47. package/dist/{current-agent-CuMErtly.d.ts → current-agent-Da_C9a3b.d.ts} +90 -107
  48. package/dist/current-agent-DhoDkSnH.js.map +1 -1
  49. package/dist/{diagnostics-CaBjfz4J.js → diagnostics-BzvaX2UT.js} +5 -1
  50. package/dist/diagnostics-BzvaX2UT.js.map +1 -0
  51. package/dist/diagnostics-C4jcz3VK.js +360 -0
  52. package/dist/diagnostics-C4jcz3VK.js.map +1 -0
  53. package/dist/index-BB0kqhIz.d.ts +101 -0
  54. package/dist/index-BVVgDSdq.d.ts +1 -0
  55. package/dist/index-XDkuQ7zm.d.ts +89 -0
  56. package/dist/{index-DcSAZKsB.d.ts → index-YSKgfgg9.d.ts} +3 -1
  57. package/dist/index.d.ts +91 -82
  58. package/dist/index.js +3 -2
  59. package/dist/ingress-BfetZbMO.js +83 -0
  60. package/dist/ingress-BfetZbMO.js.map +1 -0
  61. package/dist/internal-CYlgHl1l.js +59 -0
  62. package/dist/internal-CYlgHl1l.js.map +1 -0
  63. package/dist/internal_context.d.ts +1 -1
  64. package/dist/lifecycle/index.d.ts +35 -17
  65. package/dist/lifecycle/index.js +1 -1
  66. package/dist/lifecycle-CMRGjZdw.js +1299 -0
  67. package/dist/lifecycle-CMRGjZdw.js.map +1 -0
  68. package/dist/mcp/client/index.d.ts +20 -20
  69. package/dist/mcp/index.d.ts +35 -35
  70. package/dist/mcp/index.js +1 -1
  71. package/dist/observability/index.d.ts +1 -1
  72. package/dist/observability/index.js +1 -1
  73. package/dist/react.d.ts +4 -4
  74. package/dist/{retries-CAvxtG9d.d.ts → retries-D9Ds-1lz.d.ts} +17 -6
  75. package/dist/retries.d.ts +8 -6
  76. package/dist/retries.js +13 -1
  77. package/dist/retries.js.map +1 -1
  78. package/dist/routing/index.d.ts +137 -0
  79. package/dist/routing/index.js +244 -0
  80. package/dist/routing/index.js.map +1 -0
  81. package/dist/sanitize-D9TujEK8.js +79 -0
  82. package/dist/sanitize-D9TujEK8.js.map +1 -0
  83. package/dist/scheduler-DD9NdYbF.js +665 -0
  84. package/dist/scheduler-DD9NdYbF.js.map +1 -0
  85. package/dist/{scheduler-DQoTGoAW.d.ts → scheduler-Dwh85ZGl.d.ts} +21 -22
  86. package/dist/schedules/index.d.ts +1 -1
  87. package/dist/schedules/index.js +1 -1
  88. package/dist/sentence-chunker-BAidJ4DA.d.ts +68 -0
  89. package/dist/serializable.d.ts +1 -1
  90. package/dist/sessions/index.d.ts +441 -0
  91. package/dist/sessions/index.js +2063 -0
  92. package/dist/sessions/index.js.map +1 -0
  93. package/dist/skills/index.d.ts +99 -0
  94. package/dist/skills/index.js +254 -5
  95. package/dist/skills/index.js.map +1 -1
  96. package/dist/{src-5W6JNKVb.js → src-DlSHshb2.js} +1460 -1110
  97. package/dist/src-DlSHshb2.js.map +1 -0
  98. package/dist/streams/index.d.ts +120 -0
  99. package/dist/streams/index.js +107 -0
  100. package/dist/streams/index.js.map +1 -0
  101. package/dist/streams-D6tJ0NN9.d.ts +370 -0
  102. package/dist/streams-DZKgAj9b.js +709 -0
  103. package/dist/streams-DZKgAj9b.js.map +1 -0
  104. package/dist/sub-routing.d.ts +12 -12
  105. package/dist/surface-bZZJqBka.js +17 -0
  106. package/dist/surface-bZZJqBka.js.map +1 -0
  107. package/dist/tasks/index.d.ts +64 -0
  108. package/dist/tasks/index.js +2 -0
  109. package/dist/tasks-BRJ5zgya.d.ts +517 -0
  110. package/dist/tasks-ylZgBjhj.js +1656 -0
  111. package/dist/tasks-ylZgBjhj.js.map +1 -0
  112. package/dist/text-segment-joiner-BtAFQSA_.js +57 -0
  113. package/dist/text-segment-joiner-BtAFQSA_.js.map +1 -0
  114. package/dist/text-stream-CpdiKrJB.js +272 -0
  115. package/dist/text-stream-CpdiKrJB.js.map +1 -0
  116. package/dist/tokens-nHAKcN6M.js +52 -0
  117. package/dist/tokens-nHAKcN6M.js.map +1 -0
  118. package/dist/tool-schema-CBjGPrsQ.js +31 -0
  119. package/dist/tool-schema-CBjGPrsQ.js.map +1 -0
  120. package/dist/types-B7LojTe4.d.ts +202 -0
  121. package/dist/types-_Faxb570.d.ts +439 -0
  122. package/dist/voice/client.d.ts +226 -0
  123. package/dist/voice/client.js +932 -0
  124. package/dist/voice/client.js.map +1 -0
  125. package/dist/voice/errors.d.ts +43 -0
  126. package/dist/voice/errors.js +41 -0
  127. package/dist/voice/errors.js.map +1 -0
  128. package/dist/voice/index.d.ts +271 -0
  129. package/dist/voice/index.js +1812 -0
  130. package/dist/voice/index.js.map +1 -0
  131. package/dist/voice/react.d.ts +167 -0
  132. package/dist/voice/react.js +234 -0
  133. package/dist/voice/react.js.map +1 -0
  134. package/dist/voice/sfu.d.ts +71 -0
  135. package/dist/voice/sfu.js +157 -0
  136. package/dist/voice/sfu.js.map +1 -0
  137. package/dist/voice/text.d.ts +6 -0
  138. package/dist/voice/text.js +2 -0
  139. package/dist/voice/types.d.ts +58 -0
  140. package/dist/voice/types.js +18 -0
  141. package/dist/voice/types.js.map +1 -0
  142. package/dist/voice/workers-ai.d.ts +136 -0
  143. package/dist/voice/workers-ai.js +568 -0
  144. package/dist/voice/workers-ai.js.map +1 -0
  145. package/dist/websockets/index.d.ts +192 -0
  146. package/dist/websockets/index.js +2 -0
  147. package/dist/websockets-DUfRHPRq.js +502 -0
  148. package/dist/websockets-DUfRHPRq.js.map +1 -0
  149. package/dist/workflow-types.d.ts +25 -25
  150. package/dist/workflows.d.ts +21 -21
  151. package/dist/workflows.js +1 -1
  152. package/docs/agent-class.md +2 -2
  153. package/docs/agent-tools.md +2 -1
  154. package/docs/channels.md +323 -0
  155. package/docs/chat-agents.md +6 -13
  156. package/docs/context.md +131 -0
  157. package/docs/index.md +15 -12
  158. package/docs/lifecycle.md +102 -55
  159. package/docs/long-running-agents.md +2 -2
  160. package/docs/mcp-servers.md +5 -1
  161. package/docs/resumable-streaming.md +1 -1
  162. package/docs/routing.md +105 -0
  163. package/docs/sessions.md +237 -871
  164. package/docs/streams.md +213 -0
  165. package/docs/sub-agents.md +184 -124
  166. package/docs/tasks.md +246 -0
  167. package/docs/voice.md +745 -0
  168. package/package.json +115 -13
  169. package/dist/capability-runner-CvHGZqUu.d.ts +0 -150
  170. package/dist/compaction-helpers-iiKMr2TQ.js +0 -340
  171. package/dist/compaction-helpers-iiKMr2TQ.js.map +0 -1
  172. package/dist/compaction-helpers-wUz6M3us.d.ts +0 -621
  173. package/dist/diagnostics-CaBjfz4J.js.map +0 -1
  174. package/dist/durable-object-lifecycle-D6nNQJJd.js +0 -862
  175. package/dist/durable-object-lifecycle-D6nNQJJd.js.map +0 -1
  176. package/dist/experimental/memory/session/index.d.ts +0 -671
  177. package/dist/experimental/memory/session/index.js +0 -2379
  178. package/dist/experimental/memory/session/index.js.map +0 -1
  179. package/dist/experimental/memory/utils/index.d.ts +0 -96
  180. package/dist/experimental/memory/utils/index.js +0 -79
  181. package/dist/experimental/memory/utils/index.js.map +0 -1
  182. package/dist/scheduler-CR9RHGos.js +0 -857
  183. package/dist/scheduler-CR9RHGos.js.map +0 -1
  184. package/dist/src-5W6JNKVb.js.map +0 -1
  185. package/dist/tool-output-truncation-CNnnGZQ3.js +0 -98
  186. package/dist/tool-output-truncation-CNnnGZQ3.js.map +0 -1
@@ -0,0 +1,932 @@
1
+ import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "../classPrivateFieldGet2-DZBYAB34.js";
2
+ import { t as _classPrivateMethodInitSpec } from "../classPrivateMethodInitSpec-qMjJ6sHQ.js";
3
+ import { VOICE_PROTOCOL_VERSION } from "./types.js";
4
+ import { toVoiceError } from "./errors.js";
5
+ import { t as ClientDiagnostics } from "../diagnostics-C4jcz3VK.js";
6
+ import { PartySocket } from "partysocket";
7
+ //#region src/voice/client.ts
8
+ function camelCaseToKebabCase(str) {
9
+ if (str === str.toUpperCase() && str !== str.toLowerCase()) return str.toLowerCase().replace(/_/g, "-");
10
+ let kebabified = str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
11
+ kebabified = kebabified.startsWith("-") ? kebabified.slice(1) : kebabified;
12
+ return kebabified.replace(/_/g, "-").replace(/-$/, "");
13
+ }
14
+ const UNSUPPORTED_OUTPUT_DEVICE_ERROR = "Audio output device selection is not supported in this browser.";
15
+ const OUTPUT_DEVICE_SWITCH_ERROR = "Could not switch audio output device.";
16
+ const WORKLET_PROCESSOR = `
17
+ class AudioCaptureProcessor extends AudioWorkletProcessor {
18
+ constructor() {
19
+ super();
20
+ this.buffer = [];
21
+ this.sampleRate = sampleRate;
22
+ this.targetRate = 16000;
23
+ this.ratio = this.sampleRate / this.targetRate;
24
+ }
25
+
26
+ process(inputs) {
27
+ const input = inputs[0];
28
+ if (!input || !input[0]) return true;
29
+
30
+ const channelData = input[0];
31
+
32
+ // Linear interpolation resampling (e.g. 48kHz → 16kHz).
33
+ // Nearest-neighbor (picking every Nth sample) introduces aliasing
34
+ // artifacts, especially on sibilants (s, f, th). Linear interpolation
35
+ // blends adjacent samples, acting as a basic low-pass filter.
36
+ for (let i = 0; i < channelData.length; i += this.ratio) {
37
+ const idx = Math.floor(i);
38
+ const frac = i - idx;
39
+ if (idx + 1 < channelData.length) {
40
+ this.buffer.push(channelData[idx] * (1 - frac) + channelData[idx + 1] * frac);
41
+ } else if (idx < channelData.length) {
42
+ this.buffer.push(channelData[idx]);
43
+ }
44
+ }
45
+
46
+ if (this.buffer.length >= 1600) {
47
+ const chunk = new Float32Array(this.buffer);
48
+ this.port.postMessage({ type: 'audio', samples: chunk }, [chunk.buffer]);
49
+ this.buffer = [];
50
+ }
51
+
52
+ return true;
53
+ }
54
+ }
55
+
56
+ registerProcessor('audio-capture-processor', AudioCaptureProcessor);
57
+ `;
58
+ function floatTo16BitPCM(samples) {
59
+ const buffer = /* @__PURE__ */ new ArrayBuffer(samples.length * 2);
60
+ const view = new DataView(buffer);
61
+ for (let i = 0; i < samples.length; i++) {
62
+ const s = Math.max(-1, Math.min(1, samples[i]));
63
+ view.setInt16(i * 2, s < 0 ? s * 32768 : s * 32767, true);
64
+ }
65
+ return buffer;
66
+ }
67
+ function computeRMS(samples) {
68
+ let sum = 0;
69
+ for (let i = 0; i < samples.length; i++) sum += samples[i] * samples[i];
70
+ return Math.sqrt(sum / samples.length);
71
+ }
72
+ var _socket = /* @__PURE__ */ new WeakMap();
73
+ var _options = /* @__PURE__ */ new WeakMap();
74
+ /**
75
+ * Default VoiceTransport backed by PartySocket (reconnecting WebSocket).
76
+ * Created automatically when no custom transport is provided.
77
+ */
78
+ var WebSocketVoiceTransport = class {
79
+ constructor(options) {
80
+ _classPrivateFieldInitSpec(this, _socket, null);
81
+ _classPrivateFieldInitSpec(this, _options, void 0);
82
+ this.onopen = null;
83
+ this.onclose = null;
84
+ this.onerror = null;
85
+ this.onmessage = null;
86
+ _classPrivateFieldSet2(_options, this, options);
87
+ }
88
+ get connected() {
89
+ return _classPrivateFieldGet2(_socket, this)?.readyState === WebSocket.OPEN;
90
+ }
91
+ sendJSON(data) {
92
+ if (_classPrivateFieldGet2(_socket, this)?.readyState === WebSocket.OPEN) _classPrivateFieldGet2(_socket, this).send(JSON.stringify(data));
93
+ }
94
+ sendBinary(data) {
95
+ if (_classPrivateFieldGet2(_socket, this)?.readyState === WebSocket.OPEN) _classPrivateFieldGet2(_socket, this).send(data);
96
+ }
97
+ connect() {
98
+ if (_classPrivateFieldGet2(_socket, this)) return;
99
+ const socket = new PartySocket({
100
+ party: camelCaseToKebabCase(_classPrivateFieldGet2(_options, this).agent),
101
+ room: _classPrivateFieldGet2(_options, this).name ?? "default",
102
+ host: _classPrivateFieldGet2(_options, this).host ?? window.location.host,
103
+ prefix: "agents",
104
+ query: _classPrivateFieldGet2(_options, this).query
105
+ });
106
+ socket.onopen = () => this.onopen?.();
107
+ socket.onclose = (event) => this.onclose?.(event ? {
108
+ code: event.code,
109
+ reason: event.reason,
110
+ wasClean: event.wasClean
111
+ } : void 0);
112
+ socket.onerror = (event) => this.onerror?.(event);
113
+ socket.onmessage = (event) => {
114
+ this.onmessage?.(event.data);
115
+ };
116
+ _classPrivateFieldSet2(_socket, this, socket);
117
+ }
118
+ disconnect() {
119
+ _classPrivateFieldGet2(_socket, this)?.close();
120
+ _classPrivateFieldSet2(_socket, this, null);
121
+ }
122
+ };
123
+ var _status = /* @__PURE__ */ new WeakMap();
124
+ var _transcript = /* @__PURE__ */ new WeakMap();
125
+ var _metrics = /* @__PURE__ */ new WeakMap();
126
+ var _turnMetrics = /* @__PURE__ */ new WeakMap();
127
+ var _audioLevel = /* @__PURE__ */ new WeakMap();
128
+ var _isMuted = /* @__PURE__ */ new WeakMap();
129
+ var _connected = /* @__PURE__ */ new WeakMap();
130
+ var _error = /* @__PURE__ */ new WeakMap();
131
+ var _outputDeviceError = /* @__PURE__ */ new WeakMap();
132
+ var _lastCustomMessage = /* @__PURE__ */ new WeakMap();
133
+ var _audioFormat = /* @__PURE__ */ new WeakMap();
134
+ var _sampleRate = /* @__PURE__ */ new WeakMap();
135
+ var _interimTranscript = /* @__PURE__ */ new WeakMap();
136
+ var _serverProtocolVersion = /* @__PURE__ */ new WeakMap();
137
+ var _inCall = /* @__PURE__ */ new WeakMap();
138
+ var _callGeneration = /* @__PURE__ */ new WeakMap();
139
+ var _serverCallAcknowledged = /* @__PURE__ */ new WeakMap();
140
+ var _diagnostics = /* @__PURE__ */ new WeakMap();
141
+ var _audioReceivedForCurrentTurn = /* @__PURE__ */ new WeakMap();
142
+ var _diagnosticTurnId = /* @__PURE__ */ new WeakMap();
143
+ var _silenceThreshold = /* @__PURE__ */ new WeakMap();
144
+ var _silenceDurationMs = /* @__PURE__ */ new WeakMap();
145
+ var _interruptThreshold = /* @__PURE__ */ new WeakMap();
146
+ var _interruptChunks = /* @__PURE__ */ new WeakMap();
147
+ var _maxTranscriptMessages = /* @__PURE__ */ new WeakMap();
148
+ var _transport = /* @__PURE__ */ new WeakMap();
149
+ var _options2 = /* @__PURE__ */ new WeakMap();
150
+ var _audioContext = /* @__PURE__ */ new WeakMap();
151
+ var _workletRegistered = /* @__PURE__ */ new WeakMap();
152
+ var _workletNode = /* @__PURE__ */ new WeakMap();
153
+ var _stream = /* @__PURE__ */ new WeakMap();
154
+ var _silenceTimer = /* @__PURE__ */ new WeakMap();
155
+ var _isSpeaking = /* @__PURE__ */ new WeakMap();
156
+ var _playbackQueue = /* @__PURE__ */ new WeakMap();
157
+ var _isPlaying = /* @__PURE__ */ new WeakMap();
158
+ var _isScheduling = /* @__PURE__ */ new WeakMap();
159
+ var _scheduledSources = /* @__PURE__ */ new WeakMap();
160
+ var _playbackCursor = /* @__PURE__ */ new WeakMap();
161
+ var _lastPlaybackEnd = /* @__PURE__ */ new WeakMap();
162
+ var _playbackElement = /* @__PURE__ */ new WeakMap();
163
+ var _playbackDestination = /* @__PURE__ */ new WeakMap();
164
+ var _playbackDestinationPromise = /* @__PURE__ */ new WeakMap();
165
+ var _useDefaultPlaybackDestination = /* @__PURE__ */ new WeakMap();
166
+ var _outputDeviceId = /* @__PURE__ */ new WeakMap();
167
+ var _outputDeviceSwitchGeneration = /* @__PURE__ */ new WeakMap();
168
+ var _playbackOutputGeneration = /* @__PURE__ */ new WeakMap();
169
+ var _playbackGeneration = /* @__PURE__ */ new WeakMap();
170
+ var _interruptChunkCount = /* @__PURE__ */ new WeakMap();
171
+ var _listeners = /* @__PURE__ */ new WeakMap();
172
+ var _VoiceClient_brand = /* @__PURE__ */ new WeakSet();
173
+ var VoiceClient = class {
174
+ constructor(options) {
175
+ _classPrivateMethodInitSpec(this, _VoiceClient_brand);
176
+ _classPrivateFieldInitSpec(this, _status, "idle");
177
+ _classPrivateFieldInitSpec(this, _transcript, []);
178
+ _classPrivateFieldInitSpec(this, _metrics, null);
179
+ _classPrivateFieldInitSpec(this, _turnMetrics, null);
180
+ _classPrivateFieldInitSpec(this, _audioLevel, 0);
181
+ _classPrivateFieldInitSpec(this, _isMuted, false);
182
+ _classPrivateFieldInitSpec(this, _connected, false);
183
+ _classPrivateFieldInitSpec(this, _error, null);
184
+ _classPrivateFieldInitSpec(this, _outputDeviceError, null);
185
+ _classPrivateFieldInitSpec(this, _lastCustomMessage, null);
186
+ _classPrivateFieldInitSpec(this, _audioFormat, null);
187
+ _classPrivateFieldInitSpec(this, _sampleRate, 16e3);
188
+ _classPrivateFieldInitSpec(this, _interimTranscript, null);
189
+ _classPrivateFieldInitSpec(this, _serverProtocolVersion, null);
190
+ _classPrivateFieldInitSpec(this, _inCall, false);
191
+ _classPrivateFieldInitSpec(this, _callGeneration, 0);
192
+ _classPrivateFieldInitSpec(this, _serverCallAcknowledged, false);
193
+ _classPrivateFieldInitSpec(this, _diagnostics, new ClientDiagnostics());
194
+ _classPrivateFieldInitSpec(this, _audioReceivedForCurrentTurn, false);
195
+ _classPrivateFieldInitSpec(this, _diagnosticTurnId, null);
196
+ _classPrivateFieldInitSpec(this, _silenceThreshold, void 0);
197
+ _classPrivateFieldInitSpec(this, _silenceDurationMs, void 0);
198
+ _classPrivateFieldInitSpec(this, _interruptThreshold, void 0);
199
+ _classPrivateFieldInitSpec(this, _interruptChunks, void 0);
200
+ _classPrivateFieldInitSpec(this, _maxTranscriptMessages, void 0);
201
+ _classPrivateFieldInitSpec(this, _transport, null);
202
+ _classPrivateFieldInitSpec(this, _options2, void 0);
203
+ _classPrivateFieldInitSpec(this, _audioContext, null);
204
+ _classPrivateFieldInitSpec(this, _workletRegistered, false);
205
+ _classPrivateFieldInitSpec(this, _workletNode, null);
206
+ _classPrivateFieldInitSpec(this, _stream, null);
207
+ _classPrivateFieldInitSpec(this, _silenceTimer, null);
208
+ _classPrivateFieldInitSpec(this, _isSpeaking, false);
209
+ _classPrivateFieldInitSpec(this, _playbackQueue, []);
210
+ _classPrivateFieldInitSpec(this, _isPlaying, false);
211
+ _classPrivateFieldInitSpec(this, _isScheduling, false);
212
+ _classPrivateFieldInitSpec(this, _scheduledSources, /* @__PURE__ */ new Set());
213
+ _classPrivateFieldInitSpec(this, _playbackCursor, 0);
214
+ _classPrivateFieldInitSpec(this, _lastPlaybackEnd, null);
215
+ _classPrivateFieldInitSpec(this, _playbackElement, null);
216
+ _classPrivateFieldInitSpec(this, _playbackDestination, null);
217
+ _classPrivateFieldInitSpec(this, _playbackDestinationPromise, null);
218
+ _classPrivateFieldInitSpec(this, _useDefaultPlaybackDestination, false);
219
+ _classPrivateFieldInitSpec(this, _outputDeviceId, void 0);
220
+ _classPrivateFieldInitSpec(this, _outputDeviceSwitchGeneration, 0);
221
+ _classPrivateFieldInitSpec(this, _playbackOutputGeneration, 0);
222
+ _classPrivateFieldInitSpec(this, _playbackGeneration, 0);
223
+ _classPrivateFieldInitSpec(this, _interruptChunkCount, 0);
224
+ _classPrivateFieldInitSpec(this, _listeners, /* @__PURE__ */ new Map());
225
+ _classPrivateFieldSet2(_options2, this, options);
226
+ _classPrivateFieldSet2(_silenceThreshold, this, options.silenceThreshold ?? .04);
227
+ _classPrivateFieldSet2(_silenceDurationMs, this, options.silenceDurationMs ?? 500);
228
+ _classPrivateFieldSet2(_interruptThreshold, this, options.interruptThreshold ?? .05);
229
+ _classPrivateFieldSet2(_interruptChunks, this, options.interruptChunks ?? 2);
230
+ _classPrivateFieldSet2(_maxTranscriptMessages, this, options.maxTranscriptMessages ?? 200);
231
+ _classPrivateFieldSet2(_outputDeviceId, this, options.outputDeviceId ?? "default");
232
+ }
233
+ get status() {
234
+ return _classPrivateFieldGet2(_status, this);
235
+ }
236
+ get transcript() {
237
+ return _classPrivateFieldGet2(_transcript, this);
238
+ }
239
+ get metrics() {
240
+ return _classPrivateFieldGet2(_metrics, this);
241
+ }
242
+ /** Last stable terminal summary received for any speech or text turn. */
243
+ get turnMetrics() {
244
+ return _classPrivateFieldGet2(_turnMetrics, this);
245
+ }
246
+ get audioLevel() {
247
+ return _classPrivateFieldGet2(_audioLevel, this);
248
+ }
249
+ get isMuted() {
250
+ return _classPrivateFieldGet2(_isMuted, this);
251
+ }
252
+ get connected() {
253
+ return _classPrivateFieldGet2(_connected, this);
254
+ }
255
+ get error() {
256
+ return _classPrivateFieldGet2(_error, this);
257
+ }
258
+ get outputDeviceError() {
259
+ return _classPrivateFieldGet2(_outputDeviceError, this);
260
+ }
261
+ /**
262
+ * The current interim (partial) transcript from streaming STT.
263
+ * Updates in real time as the user speaks. Cleared when the final
264
+ * transcript is produced or the call reaches a terminal reset.
265
+ * null when no interim text is available.
266
+ */
267
+ get interimTranscript() {
268
+ return _classPrivateFieldGet2(_interimTranscript, this);
269
+ }
270
+ /**
271
+ * The protocol version reported by the server.
272
+ * null until the server sends its welcome message.
273
+ */
274
+ get serverProtocolVersion() {
275
+ return _classPrivateFieldGet2(_serverProtocolVersion, this);
276
+ }
277
+ addEventListener(event, listener) {
278
+ let set = _classPrivateFieldGet2(_listeners, this).get(event);
279
+ if (!set) {
280
+ set = /* @__PURE__ */ new Set();
281
+ _classPrivateFieldGet2(_listeners, this).set(event, set);
282
+ }
283
+ set.add(listener);
284
+ }
285
+ removeEventListener(event, listener) {
286
+ _classPrivateFieldGet2(_listeners, this).get(event)?.delete(listener);
287
+ }
288
+ connect() {
289
+ if (_classPrivateFieldGet2(_transport, this)) return;
290
+ const transport = _classPrivateFieldGet2(_options2, this).transport ?? new WebSocketVoiceTransport({
291
+ agent: _classPrivateFieldGet2(_options2, this).agent,
292
+ name: _classPrivateFieldGet2(_options2, this).name,
293
+ host: _classPrivateFieldGet2(_options2, this).host,
294
+ query: _classPrivateFieldGet2(_options2, this).query
295
+ });
296
+ transport.onopen = () => {
297
+ _classPrivateFieldSet2(_connected, this, true);
298
+ _classPrivateFieldSet2(_error, this, null);
299
+ transport.sendJSON({
300
+ type: "hello",
301
+ protocol_version: 1
302
+ });
303
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "connectionchange", true);
304
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "error", null);
305
+ if (_classPrivateFieldGet2(_inCall, this)) {
306
+ _classPrivateFieldSet2(_serverCallAcknowledged, this, false);
307
+ transport.sendJSON({ type: "start_call" });
308
+ }
309
+ };
310
+ transport.onclose = (info) => {
311
+ _classPrivateFieldGet2(_diagnostics, this).emit("connection.closed", {
312
+ ...info?.code === void 0 ? {} : { code: info.code },
313
+ clean: info?.wasClean ?? false
314
+ });
315
+ _classPrivateFieldSet2(_connected, this, false);
316
+ _assertClassBrand(_VoiceClient_brand, this, _clearInterimTranscript).call(this);
317
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "connectionchange", false);
318
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "connectiondiagnostic", {
319
+ type: "close",
320
+ ...info
321
+ });
322
+ };
323
+ transport.onerror = (cause) => {
324
+ _classPrivateFieldGet2(_diagnostics, this).emit("connection.error", { error: toVoiceError(cause, "Connection failed") });
325
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "connectiondiagnostic", {
326
+ type: "error",
327
+ cause
328
+ });
329
+ _classPrivateFieldSet2(_error, this, "Connection lost. Reconnecting...");
330
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "error", _classPrivateFieldGet2(_error, this));
331
+ };
332
+ transport.onmessage = (data) => {
333
+ if (typeof data === "string") _assertClassBrand(_VoiceClient_brand, this, _handleJSONMessage).call(this, data);
334
+ else if (data instanceof Blob) data.arrayBuffer().then((buffer) => {
335
+ _assertClassBrand(_VoiceClient_brand, this, _recordAudioReceived).call(this, buffer.byteLength);
336
+ _classPrivateFieldGet2(_playbackQueue, this).push(buffer);
337
+ _assertClassBrand(_VoiceClient_brand, this, _processPlaybackQueue).call(this);
338
+ });
339
+ else if (data instanceof ArrayBuffer) {
340
+ _assertClassBrand(_VoiceClient_brand, this, _recordAudioReceived).call(this, data.byteLength);
341
+ _classPrivateFieldGet2(_playbackQueue, this).push(data);
342
+ _assertClassBrand(_VoiceClient_brand, this, _processPlaybackQueue).call(this);
343
+ }
344
+ };
345
+ _classPrivateFieldSet2(_transport, this, transport);
346
+ transport.connect();
347
+ }
348
+ disconnect() {
349
+ this.endCall();
350
+ _classPrivateFieldGet2(_diagnostics, this).emit("connection.disconnecting");
351
+ _classPrivateFieldGet2(_transport, this)?.disconnect();
352
+ _classPrivateFieldSet2(_transport, this, null);
353
+ _classPrivateFieldSet2(_connected, this, false);
354
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "connectionchange", false);
355
+ }
356
+ async startCall() {
357
+ var _this$callGeneration;
358
+ if (!_classPrivateFieldGet2(_transport, this)?.connected) {
359
+ _classPrivateFieldSet2(_error, this, "Cannot start call: not connected. Call connect() first.");
360
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "error", _classPrivateFieldGet2(_error, this));
361
+ return;
362
+ }
363
+ if (_classPrivateFieldGet2(_inCall, this)) return;
364
+ _assertClassBrand(_VoiceClient_brand, this, _clearInterimTranscript).call(this);
365
+ const callGeneration = _classPrivateFieldSet2(_callGeneration, this, (_this$callGeneration = _classPrivateFieldGet2(_callGeneration, this), ++_this$callGeneration));
366
+ _classPrivateFieldSet2(_inCall, this, true);
367
+ _classPrivateFieldSet2(_serverCallAcknowledged, this, false);
368
+ _classPrivateFieldSet2(_error, this, null);
369
+ _classPrivateFieldSet2(_metrics, this, null);
370
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "error", null);
371
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "metricschange", null);
372
+ const startMsg = { type: "start_call" };
373
+ if (_classPrivateFieldGet2(_options2, this).preferredFormat) startMsg.preferred_format = _classPrivateFieldGet2(_options2, this).preferredFormat;
374
+ _classPrivateFieldGet2(_diagnostics, this).emit("call.starting");
375
+ _classPrivateFieldGet2(_transport, this).sendJSON(startMsg);
376
+ const ctx = await _assertClassBrand(_VoiceClient_brand, this, _getAudioContext).call(this);
377
+ if (_assertClassBrand(_VoiceClient_brand, this, _abortStaleCallStartup).call(this, callGeneration)) return;
378
+ await _assertClassBrand(_VoiceClient_brand, this, _getPlaybackDestination).call(this, ctx);
379
+ if (_assertClassBrand(_VoiceClient_brand, this, _abortStaleCallStartup).call(this, callGeneration)) return;
380
+ if (_classPrivateFieldGet2(_options2, this).audioInput) {
381
+ _classPrivateFieldGet2(_diagnostics, this).emit("microphone.starting", { source: "custom" });
382
+ _classPrivateFieldGet2(_options2, this).audioInput.onAudioLevel = (rms) => _assertClassBrand(_VoiceClient_brand, this, _processAudioLevel).call(this, rms);
383
+ _classPrivateFieldGet2(_options2, this).audioInput.onAudioData = (pcm) => {
384
+ if (_classPrivateFieldGet2(_transport, this)?.connected && !_classPrivateFieldGet2(_isMuted, this)) _classPrivateFieldGet2(_transport, this).sendBinary(pcm);
385
+ };
386
+ await _classPrivateFieldGet2(_options2, this).audioInput.start();
387
+ _classPrivateFieldGet2(_diagnostics, this).emit("microphone.ready", { source: "custom" });
388
+ } else await _assertClassBrand(_VoiceClient_brand, this, _startMic).call(this);
389
+ if (!_assertClassBrand(_VoiceClient_brand, this, _abortStaleCallStartup).call(this, callGeneration)) _classPrivateFieldGet2(_diagnostics, this).emit("call.local_ready");
390
+ }
391
+ endCall() {
392
+ var _this$callGeneration2;
393
+ const wasInCall = _classPrivateFieldGet2(_inCall, this);
394
+ _classPrivateFieldSet2(_callGeneration, this, (_this$callGeneration2 = _classPrivateFieldGet2(_callGeneration, this), _this$callGeneration2++, _this$callGeneration2));
395
+ _classPrivateFieldSet2(_inCall, this, false);
396
+ _classPrivateFieldSet2(_serverCallAcknowledged, this, false);
397
+ if (_classPrivateFieldGet2(_transport, this)?.connected) _classPrivateFieldGet2(_transport, this).sendJSON({ type: "end_call" });
398
+ _assertClassBrand(_VoiceClient_brand, this, _stopLocalCall).call(this);
399
+ _assertClassBrand(_VoiceClient_brand, this, _clearInterimTranscript).call(this);
400
+ _classPrivateFieldSet2(_status, this, "idle");
401
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "statuschange", "idle");
402
+ if (wasInCall) _classPrivateFieldGet2(_diagnostics, this).emit("call.ended", { reason: "requested" });
403
+ }
404
+ toggleMute() {
405
+ _classPrivateFieldSet2(_isMuted, this, !_classPrivateFieldGet2(_isMuted, this));
406
+ if (_classPrivateFieldGet2(_isMuted, this)) {
407
+ _classPrivateFieldSet2(_audioLevel, this, 0);
408
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "audiolevelchange", 0);
409
+ }
410
+ if (_classPrivateFieldGet2(_isMuted, this) && _classPrivateFieldGet2(_isSpeaking, this)) {
411
+ _classPrivateFieldSet2(_isSpeaking, this, false);
412
+ if (_classPrivateFieldGet2(_silenceTimer, this)) {
413
+ clearTimeout(_classPrivateFieldGet2(_silenceTimer, this));
414
+ _classPrivateFieldSet2(_silenceTimer, this, null);
415
+ }
416
+ if (_classPrivateFieldGet2(_transport, this)?.connected) _classPrivateFieldGet2(_transport, this).sendJSON({ type: "end_of_speech" });
417
+ }
418
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "mutechange", _classPrivateFieldGet2(_isMuted, this));
419
+ }
420
+ /**
421
+ * Send a text message to the agent. The agent processes it through
422
+ * `onTurn()` (bypassing STT) and responds with text transcript and
423
+ * TTS audio (if in a call) or text-only (if not).
424
+ */
425
+ sendText(text) {
426
+ if (_classPrivateFieldGet2(_transport, this)?.connected) _classPrivateFieldGet2(_transport, this).sendJSON({
427
+ type: "text_message",
428
+ text
429
+ });
430
+ }
431
+ /**
432
+ * Send arbitrary JSON to the agent. Use this for app-level messages
433
+ * that are not part of the voice protocol (e.g. `{ type: "kick_speaker" }`).
434
+ * The server receives these in the consumer's `onMessage()` handler.
435
+ */
436
+ sendJSON(data) {
437
+ if (_classPrivateFieldGet2(_transport, this)?.connected) _classPrivateFieldGet2(_transport, this).sendJSON(data);
438
+ }
439
+ /**
440
+ * Set the preferred audio output device for assistant playback.
441
+ * Unsupported browsers continue playing through the default output.
442
+ */
443
+ async setOutputDevice(outputDeviceId) {
444
+ var _this$outputDeviceSwi;
445
+ _classPrivateFieldSet2(_outputDeviceId, this, outputDeviceId ?? "default");
446
+ const generation = _classPrivateFieldSet2(_outputDeviceSwitchGeneration, this, (_this$outputDeviceSwi = _classPrivateFieldGet2(_outputDeviceSwitchGeneration, this), ++_this$outputDeviceSwi));
447
+ if (_classPrivateFieldGet2(_playbackElement, this)) await _assertClassBrand(_VoiceClient_brand, this, _applyOutputDevice).call(this, _classPrivateFieldGet2(_playbackElement, this), generation);
448
+ }
449
+ /**
450
+ * The last custom (non-voice-protocol) message received from the server.
451
+ * Listen for the `"custommessage"` event to be notified when this changes.
452
+ */
453
+ get lastCustomMessage() {
454
+ return _classPrivateFieldGet2(_lastCustomMessage, this);
455
+ }
456
+ /**
457
+ * The audio format the server declared for binary payloads.
458
+ * Set when the server sends `audio_config` at call start.
459
+ */
460
+ get audioFormat() {
461
+ return _classPrivateFieldGet2(_audioFormat, this);
462
+ }
463
+ /**
464
+ * The sample rate (Hz) the server declared for raw pcm16 payloads.
465
+ * Set when the server sends `audio_config` at call start. Defaults to 16000.
466
+ */
467
+ get sampleRate() {
468
+ return _classPrivateFieldGet2(_sampleRate, this);
469
+ }
470
+ };
471
+ function _emit(event, data) {
472
+ const set = _classPrivateFieldGet2(_listeners, this).get(event);
473
+ if (set) for (const listener of set) listener(data);
474
+ }
475
+ function _trimTranscript() {
476
+ if (_classPrivateFieldGet2(_transcript, this).length > _classPrivateFieldGet2(_maxTranscriptMessages, this)) _classPrivateFieldSet2(_transcript, this, _classPrivateFieldGet2(_transcript, this).slice(-_classPrivateFieldGet2(_maxTranscriptMessages, this)));
477
+ }
478
+ function _setOutputDeviceError(error) {
479
+ if (_classPrivateFieldGet2(_outputDeviceError, this) === error) return;
480
+ _classPrivateFieldSet2(_outputDeviceError, this, error);
481
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "outputdeviceerror", error);
482
+ }
483
+ function _clearInterimTranscript() {
484
+ _classPrivateFieldSet2(_interimTranscript, this, null);
485
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "interimtranscript", null);
486
+ }
487
+ function _isCurrentCallStartup(callGeneration) {
488
+ return _classPrivateFieldGet2(_inCall, this) && _classPrivateFieldGet2(_callGeneration, this) === callGeneration;
489
+ }
490
+ function _abortStaleCallStartup(callGeneration) {
491
+ if (_assertClassBrand(_VoiceClient_brand, this, _isCurrentCallStartup).call(this, callGeneration)) return false;
492
+ if (!_classPrivateFieldGet2(_inCall, this)) _assertClassBrand(_VoiceClient_brand, this, _stopLocalCall).call(this);
493
+ return true;
494
+ }
495
+ function _stopLocalCall() {
496
+ if (_classPrivateFieldGet2(_options2, this).audioInput) {
497
+ _classPrivateFieldGet2(_options2, this).audioInput.stop();
498
+ _classPrivateFieldGet2(_options2, this).audioInput.onAudioLevel = null;
499
+ _classPrivateFieldGet2(_options2, this).audioInput.onAudioData = null;
500
+ } else _assertClassBrand(_VoiceClient_brand, this, _stopMic).call(this);
501
+ _assertClassBrand(_VoiceClient_brand, this, _stopPlayback).call(this);
502
+ _assertClassBrand(_VoiceClient_brand, this, _closeAudioContext).call(this);
503
+ _assertClassBrand(_VoiceClient_brand, this, _resetDetection).call(this);
504
+ }
505
+ function _recordAudioReceived(bytes) {
506
+ if (_classPrivateFieldGet2(_audioReceivedForCurrentTurn, this)) return;
507
+ _classPrivateFieldSet2(_audioReceivedForCurrentTurn, this, true);
508
+ _classPrivateFieldGet2(_diagnostics, this).emit("audio.received", {
509
+ bytes,
510
+ ..._classPrivateFieldGet2(_diagnosticTurnId, this) === null ? {} : { turn_id: _classPrivateFieldGet2(_diagnosticTurnId, this) }
511
+ });
512
+ }
513
+ function _handleJSONMessage(data) {
514
+ let msg;
515
+ try {
516
+ msg = JSON.parse(data);
517
+ } catch {
518
+ return;
519
+ }
520
+ switch (msg.type) {
521
+ case "welcome": {
522
+ const diagnosticsEnabled = (typeof msg.diagnostics === "object" && msg.diagnostics !== null ? msg.diagnostics : null)?.browser_console === true;
523
+ _classPrivateFieldGet2(_diagnostics, this).setEnabled(diagnosticsEnabled);
524
+ if (diagnosticsEnabled) _classPrivateFieldGet2(_diagnostics, this).emit("connection.ready", { protocol_version: msg.protocol_version });
525
+ _classPrivateFieldSet2(_serverProtocolVersion, this, msg.protocol_version);
526
+ if (msg.protocol_version !== 1) console.warn(`[VoiceClient] Protocol version mismatch: client=1, server=${msg.protocol_version}`);
527
+ break;
528
+ }
529
+ case "diagnostic":
530
+ if (typeof msg.event === "string" && typeof msg.timestamp === "number" && Number.isFinite(msg.timestamp)) {
531
+ const data = typeof msg.data === "object" && msg.data !== null ? msg.data : void 0;
532
+ if (msg.event === "audio.first_sent" && typeof data?.turn_id === "string") {
533
+ _classPrivateFieldSet2(_diagnosticTurnId, this, data.turn_id);
534
+ _classPrivateFieldSet2(_audioReceivedForCurrentTurn, this, false);
535
+ }
536
+ _classPrivateFieldGet2(_diagnostics, this).receive({
537
+ event: msg.event,
538
+ timestamp: msg.timestamp,
539
+ ...data === void 0 ? {} : { data }
540
+ });
541
+ }
542
+ break;
543
+ case "audio_config":
544
+ _classPrivateFieldSet2(_serverCallAcknowledged, this, true);
545
+ _classPrivateFieldSet2(_audioFormat, this, msg.format);
546
+ _classPrivateFieldSet2(_sampleRate, this, typeof msg.sampleRate === "number" && msg.sampleRate > 0 ? msg.sampleRate : 16e3);
547
+ break;
548
+ case "status":
549
+ _classPrivateFieldSet2(_status, this, msg.status);
550
+ if (msg.status === "thinking" || msg.status === "speaking") {
551
+ _classPrivateFieldSet2(_audioReceivedForCurrentTurn, this, false);
552
+ if (msg.status === "thinking") _classPrivateFieldSet2(_diagnosticTurnId, this, null);
553
+ }
554
+ if (msg.status === "idle" && _classPrivateFieldGet2(_inCall, this)) {
555
+ var _this$callGeneration4;
556
+ if (!(_classPrivateFieldGet2(_serverCallAcknowledged, this) || _classPrivateFieldGet2(_error, this) !== null)) {
557
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "statuschange", _classPrivateFieldGet2(_status, this));
558
+ break;
559
+ }
560
+ _classPrivateFieldSet2(_callGeneration, this, (_this$callGeneration4 = _classPrivateFieldGet2(_callGeneration, this), _this$callGeneration4++, _this$callGeneration4));
561
+ _classPrivateFieldSet2(_inCall, this, false);
562
+ _classPrivateFieldSet2(_serverCallAcknowledged, this, false);
563
+ _assertClassBrand(_VoiceClient_brand, this, _stopLocalCall).call(this);
564
+ _assertClassBrand(_VoiceClient_brand, this, _clearInterimTranscript).call(this);
565
+ }
566
+ if (msg.status === "listening") {
567
+ _classPrivateFieldSet2(_serverCallAcknowledged, this, true);
568
+ _classPrivateFieldSet2(_error, this, null);
569
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "error", null);
570
+ } else if (msg.status === "thinking" || msg.status === "speaking") _classPrivateFieldSet2(_serverCallAcknowledged, this, true);
571
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "statuschange", _classPrivateFieldGet2(_status, this));
572
+ break;
573
+ case "transcript_interim":
574
+ _classPrivateFieldSet2(_interimTranscript, this, msg.text);
575
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "interimtranscript", _classPrivateFieldGet2(_interimTranscript, this));
576
+ break;
577
+ case "playback_interrupt":
578
+ _assertClassBrand(_VoiceClient_brand, this, _stopPlayback).call(this, "server_interrupt");
579
+ break;
580
+ case "transcript":
581
+ _classPrivateFieldSet2(_interimTranscript, this, null);
582
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "interimtranscript", null);
583
+ if (msg.role === "user" && _classPrivateFieldGet2(_isPlaying, this)) _assertClassBrand(_VoiceClient_brand, this, _stopPlayback).call(this, "user_utterance");
584
+ _classPrivateFieldSet2(_transcript, this, [..._classPrivateFieldGet2(_transcript, this), {
585
+ role: msg.role,
586
+ text: msg.text,
587
+ timestamp: Date.now()
588
+ }]);
589
+ _assertClassBrand(_VoiceClient_brand, this, _trimTranscript).call(this);
590
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "transcriptchange", _classPrivateFieldGet2(_transcript, this));
591
+ break;
592
+ case "transcript_start":
593
+ _classPrivateFieldSet2(_transcript, this, [..._classPrivateFieldGet2(_transcript, this), {
594
+ role: "assistant",
595
+ text: "",
596
+ timestamp: Date.now()
597
+ }]);
598
+ _assertClassBrand(_VoiceClient_brand, this, _trimTranscript).call(this);
599
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "transcriptchange", _classPrivateFieldGet2(_transcript, this));
600
+ break;
601
+ case "transcript_delta": {
602
+ if (_classPrivateFieldGet2(_transcript, this).length === 0) break;
603
+ const updated = [..._classPrivateFieldGet2(_transcript, this)];
604
+ const last = updated[updated.length - 1];
605
+ if (last.role === "assistant") {
606
+ updated[updated.length - 1] = {
607
+ ...last,
608
+ text: last.text + msg.text
609
+ };
610
+ _classPrivateFieldSet2(_transcript, this, updated);
611
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "transcriptchange", _classPrivateFieldGet2(_transcript, this));
612
+ }
613
+ break;
614
+ }
615
+ case "transcript_end": {
616
+ if (_classPrivateFieldGet2(_transcript, this).length === 0) break;
617
+ const updated = [..._classPrivateFieldGet2(_transcript, this)];
618
+ const last = updated[updated.length - 1];
619
+ if (last.role === "assistant") {
620
+ updated[updated.length - 1] = {
621
+ ...last,
622
+ text: msg.text
623
+ };
624
+ _classPrivateFieldSet2(_transcript, this, updated);
625
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "transcriptchange", _classPrivateFieldGet2(_transcript, this));
626
+ }
627
+ break;
628
+ }
629
+ case "metrics":
630
+ _classPrivateFieldSet2(_metrics, this, {
631
+ llm_ms: msg.llm_ms,
632
+ tts_ms: msg.tts_ms,
633
+ first_audio_ms: msg.first_audio_ms,
634
+ total_ms: msg.total_ms
635
+ });
636
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "metricschange", _classPrivateFieldGet2(_metrics, this));
637
+ break;
638
+ case "turn_metrics": {
639
+ const { type: _type, ...payload } = msg;
640
+ const metrics = payload;
641
+ _classPrivateFieldSet2(_turnMetrics, this, metrics);
642
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "turnmetrics", metrics);
643
+ break;
644
+ }
645
+ case "completion_outcome": {
646
+ const outcome = {
647
+ code: msg.code,
648
+ stage: "llm",
649
+ ...msg.finishReason !== void 0 ? { finishReason: msg.finishReason } : {},
650
+ partialOutput: msg.partialOutput
651
+ };
652
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "completionoutcome", outcome);
653
+ break;
654
+ }
655
+ case "error": {
656
+ const voiceError = {
657
+ message: msg.message,
658
+ ...msg.code !== void 0 ? { code: msg.code } : {},
659
+ ...msg.stage !== void 0 ? { stage: msg.stage } : {},
660
+ ...msg.retryable !== void 0 ? { retryable: msg.retryable } : {}
661
+ };
662
+ _classPrivateFieldSet2(_error, this, voiceError.message);
663
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "voiceerror", voiceError);
664
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "error", _classPrivateFieldGet2(_error, this));
665
+ break;
666
+ }
667
+ default:
668
+ _classPrivateFieldSet2(_lastCustomMessage, this, msg);
669
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "custommessage", msg);
670
+ break;
671
+ }
672
+ }
673
+ /** Get or create the shared AudioContext. */
674
+ async function _getAudioContext() {
675
+ if (!_classPrivateFieldGet2(_audioContext, this)) _classPrivateFieldSet2(_audioContext, this, new AudioContext({ sampleRate: 48e3 }));
676
+ if (_classPrivateFieldGet2(_audioContext, this).state === "suspended") await _classPrivateFieldGet2(_audioContext, this).resume();
677
+ return _classPrivateFieldGet2(_audioContext, this);
678
+ }
679
+ /** Close the AudioContext and release resources. */
680
+ function _closeAudioContext() {
681
+ if (_classPrivateFieldGet2(_audioContext, this)) {
682
+ _assertClassBrand(_VoiceClient_brand, this, _closePlaybackOutput).call(this);
683
+ _classPrivateFieldGet2(_audioContext, this).close().catch(() => {});
684
+ _classPrivateFieldSet2(_audioContext, this, null);
685
+ _classPrivateFieldSet2(_workletRegistered, this, false);
686
+ }
687
+ }
688
+ async function _getPlaybackDestination(ctx) {
689
+ if (_classPrivateFieldGet2(_playbackDestinationPromise, this)) return _classPrivateFieldGet2(_playbackDestinationPromise, this);
690
+ if (_classPrivateFieldGet2(_playbackDestination, this)) return _classPrivateFieldGet2(_playbackDestination, this);
691
+ if (_classPrivateFieldGet2(_useDefaultPlaybackDestination, this)) return ctx.destination;
692
+ const outputGeneration = _classPrivateFieldGet2(_playbackOutputGeneration, this);
693
+ const promise = _assertClassBrand(_VoiceClient_brand, this, _initializePlaybackDestination).call(this, ctx, outputGeneration);
694
+ _classPrivateFieldSet2(_playbackDestinationPromise, this, promise);
695
+ try {
696
+ return await promise;
697
+ } finally {
698
+ if (_classPrivateFieldGet2(_playbackDestinationPromise, this) === promise) _classPrivateFieldSet2(_playbackDestinationPromise, this, null);
699
+ }
700
+ }
701
+ async function _initializePlaybackDestination(ctx, outputGeneration) {
702
+ try {
703
+ const destination = ctx.createMediaStreamDestination();
704
+ const audio = new Audio();
705
+ audio.autoplay = true;
706
+ audio.srcObject = destination.stream;
707
+ _classPrivateFieldSet2(_playbackElement, this, audio);
708
+ _classPrivateFieldSet2(_playbackDestination, this, destination);
709
+ await _assertClassBrand(_VoiceClient_brand, this, _applyOutputDevice).call(this, audio, _classPrivateFieldGet2(_outputDeviceSwitchGeneration, this));
710
+ if (!_assertClassBrand(_VoiceClient_brand, this, _isCurrentPlaybackOutput).call(this, audio, outputGeneration)) {
711
+ _assertClassBrand(_VoiceClient_brand, this, _releasePlaybackElement).call(this, audio);
712
+ return ctx.destination;
713
+ }
714
+ await audio.play();
715
+ if (!_assertClassBrand(_VoiceClient_brand, this, _isCurrentPlaybackOutput).call(this, audio, outputGeneration)) {
716
+ _assertClassBrand(_VoiceClient_brand, this, _releasePlaybackElement).call(this, audio);
717
+ return ctx.destination;
718
+ }
719
+ return destination;
720
+ } catch (err) {
721
+ console.warn("[VoiceClient] HTMLAudioElement playback output unavailable; using default AudioContext destination.", err);
722
+ _assertClassBrand(_VoiceClient_brand, this, _closePlaybackOutput).call(this);
723
+ _classPrivateFieldSet2(_useDefaultPlaybackDestination, this, true);
724
+ return ctx.destination;
725
+ }
726
+ }
727
+ function _isCurrentPlaybackOutput(audio, outputGeneration) {
728
+ return _classPrivateFieldGet2(_playbackElement, this) === audio && _classPrivateFieldGet2(_playbackOutputGeneration, this) === outputGeneration;
729
+ }
730
+ async function _applyOutputDevice(audio, generation) {
731
+ const sinkId = _classPrivateFieldGet2(_outputDeviceId, this);
732
+ const setSinkId = audio.setSinkId;
733
+ if (!setSinkId) {
734
+ if (sinkId === "default") {
735
+ _assertClassBrand(_VoiceClient_brand, this, _setOutputDeviceError).call(this, null);
736
+ return;
737
+ }
738
+ _assertClassBrand(_VoiceClient_brand, this, _setOutputDeviceError).call(this, UNSUPPORTED_OUTPUT_DEVICE_ERROR);
739
+ return;
740
+ }
741
+ try {
742
+ await setSinkId.call(audio, sinkId);
743
+ if (generation !== _classPrivateFieldGet2(_outputDeviceSwitchGeneration, this) || sinkId !== _classPrivateFieldGet2(_outputDeviceId, this)) {
744
+ if (_classPrivateFieldGet2(_playbackElement, this) === audio) await _assertClassBrand(_VoiceClient_brand, this, _applyOutputDevice).call(this, audio, _classPrivateFieldGet2(_outputDeviceSwitchGeneration, this));
745
+ return;
746
+ }
747
+ if (_classPrivateFieldGet2(_outputDeviceError, this) === UNSUPPORTED_OUTPUT_DEVICE_ERROR || _classPrivateFieldGet2(_outputDeviceError, this) === OUTPUT_DEVICE_SWITCH_ERROR) _assertClassBrand(_VoiceClient_brand, this, _setOutputDeviceError).call(this, null);
748
+ } catch {
749
+ if (generation !== _classPrivateFieldGet2(_outputDeviceSwitchGeneration, this) || sinkId !== _classPrivateFieldGet2(_outputDeviceId, this)) {
750
+ if (_classPrivateFieldGet2(_playbackElement, this) === audio) await _assertClassBrand(_VoiceClient_brand, this, _applyOutputDevice).call(this, audio, _classPrivateFieldGet2(_outputDeviceSwitchGeneration, this));
751
+ return;
752
+ }
753
+ _assertClassBrand(_VoiceClient_brand, this, _setOutputDeviceError).call(this, OUTPUT_DEVICE_SWITCH_ERROR);
754
+ }
755
+ }
756
+ function _closePlaybackOutput() {
757
+ var _this$playbackOutputG;
758
+ _classPrivateFieldSet2(_playbackOutputGeneration, this, (_this$playbackOutputG = _classPrivateFieldGet2(_playbackOutputGeneration, this), _this$playbackOutputG++, _this$playbackOutputG));
759
+ if (_classPrivateFieldGet2(_playbackElement, this)) {
760
+ _assertClassBrand(_VoiceClient_brand, this, _releasePlaybackElement).call(this, _classPrivateFieldGet2(_playbackElement, this));
761
+ _classPrivateFieldSet2(_playbackElement, this, null);
762
+ }
763
+ _classPrivateFieldSet2(_playbackDestination, this, null);
764
+ _classPrivateFieldSet2(_playbackDestinationPromise, this, null);
765
+ _classPrivateFieldSet2(_useDefaultPlaybackDestination, this, false);
766
+ }
767
+ function _releasePlaybackElement(audio) {
768
+ audio.pause();
769
+ audio.srcObject = null;
770
+ }
771
+ async function _playAudio(audioData, generation) {
772
+ try {
773
+ const ctx = await _assertClassBrand(_VoiceClient_brand, this, _getAudioContext).call(this);
774
+ let audioBuffer;
775
+ if (_classPrivateFieldGet2(_audioFormat, this) === "pcm16") {
776
+ const int16 = new Int16Array(audioData);
777
+ audioBuffer = ctx.createBuffer(1, int16.length, _classPrivateFieldGet2(_sampleRate, this));
778
+ const channel = audioBuffer.getChannelData(0);
779
+ for (let i = 0; i < int16.length; i++) channel[i] = int16[i] / 32768;
780
+ } else audioBuffer = await ctx.decodeAudioData(audioData.slice(0));
781
+ if (generation !== _classPrivateFieldGet2(_playbackGeneration, this)) return;
782
+ if (_classPrivateFieldGet2(_playbackElement, this) && _classPrivateFieldGet2(_scheduledSources, this).size === 0 && _classPrivateFieldGet2(_lastPlaybackEnd, this) !== null && ctx.currentTime - _classPrivateFieldGet2(_lastPlaybackEnd, this) > .3) _assertClassBrand(_VoiceClient_brand, this, _closePlaybackOutput).call(this);
783
+ const destination = await _assertClassBrand(_VoiceClient_brand, this, _getPlaybackDestination).call(this, ctx);
784
+ if (generation !== _classPrivateFieldGet2(_playbackGeneration, this)) return;
785
+ const source = ctx.createBufferSource();
786
+ source.buffer = audioBuffer;
787
+ source.connect(destination);
788
+ _classPrivateFieldGet2(_scheduledSources, this).add(source);
789
+ source.onended = () => {
790
+ _classPrivateFieldGet2(_scheduledSources, this).delete(source);
791
+ if (generation === _classPrivateFieldGet2(_playbackGeneration, this) && !_classPrivateFieldGet2(_isScheduling, this) && _classPrivateFieldGet2(_scheduledSources, this).size === 0 && _classPrivateFieldGet2(_playbackQueue, this).length === 0) {
792
+ _classPrivateFieldSet2(_isPlaying, this, false);
793
+ _classPrivateFieldGet2(_diagnostics, this).emit("playback.completed");
794
+ }
795
+ };
796
+ const startAt = Math.max(ctx.currentTime, _classPrivateFieldGet2(_playbackCursor, this));
797
+ _classPrivateFieldSet2(_playbackCursor, this, startAt + audioBuffer.duration);
798
+ _classPrivateFieldSet2(_lastPlaybackEnd, this, _classPrivateFieldGet2(_playbackCursor, this));
799
+ source.start(startAt);
800
+ } catch (err) {
801
+ _classPrivateFieldGet2(_diagnostics, this).emit("playback.error", { error: toVoiceError(err, "Playback failed") });
802
+ console.error("[VoiceClient] Audio playback error:", err);
803
+ }
804
+ }
805
+ async function _processPlaybackQueue() {
806
+ if (_classPrivateFieldGet2(_isScheduling, this) || _classPrivateFieldGet2(_playbackQueue, this).length === 0) return;
807
+ _classPrivateFieldSet2(_isScheduling, this, true);
808
+ _classPrivateFieldSet2(_isPlaying, this, true);
809
+ _classPrivateFieldGet2(_diagnostics, this).emit("playback.started", { chunks: _classPrivateFieldGet2(_playbackQueue, this).length });
810
+ const generation = _classPrivateFieldGet2(_playbackGeneration, this);
811
+ while (generation === _classPrivateFieldGet2(_playbackGeneration, this) && _classPrivateFieldGet2(_playbackQueue, this).length > 0) {
812
+ const audioData = _classPrivateFieldGet2(_playbackQueue, this).shift();
813
+ await _assertClassBrand(_VoiceClient_brand, this, _playAudio).call(this, audioData, generation);
814
+ }
815
+ if (generation === _classPrivateFieldGet2(_playbackGeneration, this)) {
816
+ _classPrivateFieldSet2(_isScheduling, this, false);
817
+ if (_classPrivateFieldGet2(_scheduledSources, this).size === 0) _classPrivateFieldSet2(_isPlaying, this, false);
818
+ }
819
+ }
820
+ function _stopPlayback(reason = "stopped") {
821
+ var _this$playbackGenerat;
822
+ const wasActive = _classPrivateFieldGet2(_isPlaying, this) || _classPrivateFieldGet2(_isScheduling, this) || _classPrivateFieldGet2(_playbackQueue, this).length > 0 || _classPrivateFieldGet2(_scheduledSources, this).size > 0;
823
+ _classPrivateFieldSet2(_playbackGeneration, this, (_this$playbackGenerat = _classPrivateFieldGet2(_playbackGeneration, this), _this$playbackGenerat++, _this$playbackGenerat));
824
+ const sources = [..._classPrivateFieldGet2(_scheduledSources, this)];
825
+ _classPrivateFieldGet2(_scheduledSources, this).clear();
826
+ for (const source of sources) try {
827
+ source.stop();
828
+ } catch {}
829
+ _classPrivateFieldSet2(_playbackQueue, this, []);
830
+ _classPrivateFieldSet2(_isPlaying, this, false);
831
+ _classPrivateFieldSet2(_isScheduling, this, false);
832
+ _classPrivateFieldSet2(_playbackCursor, this, 0);
833
+ _classPrivateFieldSet2(_lastPlaybackEnd, this, _classPrivateFieldGet2(_audioContext, this) ? _classPrivateFieldGet2(_audioContext, this).currentTime : null);
834
+ if (wasActive) _classPrivateFieldGet2(_diagnostics, this).emit("playback.stopped", { reason });
835
+ }
836
+ async function _startMic() {
837
+ _classPrivateFieldGet2(_diagnostics, this).emit("microphone.starting", { source: "browser" });
838
+ try {
839
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: {
840
+ sampleRate: { ideal: 48e3 },
841
+ channelCount: 1,
842
+ echoCancellation: true,
843
+ noiseSuppression: true,
844
+ autoGainControl: true
845
+ } });
846
+ _classPrivateFieldSet2(_stream, this, stream);
847
+ const ctx = await _assertClassBrand(_VoiceClient_brand, this, _getAudioContext).call(this);
848
+ if (!_classPrivateFieldGet2(_workletRegistered, this)) {
849
+ const blob = new Blob([WORKLET_PROCESSOR], { type: "application/javascript" });
850
+ const workletUrl = URL.createObjectURL(blob);
851
+ await ctx.audioWorklet.addModule(workletUrl);
852
+ URL.revokeObjectURL(workletUrl);
853
+ _classPrivateFieldSet2(_workletRegistered, this, true);
854
+ }
855
+ const source = ctx.createMediaStreamSource(stream);
856
+ const workletNode = new AudioWorkletNode(ctx, "audio-capture-processor");
857
+ _classPrivateFieldSet2(_workletNode, this, workletNode);
858
+ workletNode.port.onmessage = (event) => {
859
+ if (event.data.type === "audio" && !_classPrivateFieldGet2(_isMuted, this)) {
860
+ const samples = event.data.samples;
861
+ const rms = computeRMS(samples);
862
+ const pcm = floatTo16BitPCM(samples);
863
+ if (_classPrivateFieldGet2(_transport, this)?.connected) _classPrivateFieldGet2(_transport, this).sendBinary(pcm);
864
+ _assertClassBrand(_VoiceClient_brand, this, _processAudioLevel).call(this, rms);
865
+ }
866
+ };
867
+ source.connect(workletNode);
868
+ workletNode.connect(ctx.destination);
869
+ _classPrivateFieldGet2(_diagnostics, this).emit("microphone.ready", { source: "browser" });
870
+ } catch (err) {
871
+ _classPrivateFieldGet2(_diagnostics, this).emit("microphone.error", { error: toVoiceError(err, "Microphone failed") });
872
+ console.error("[VoiceClient] Mic error:", err);
873
+ _classPrivateFieldSet2(_error, this, "Microphone access denied. Please allow microphone access and try again.");
874
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "error", _classPrivateFieldGet2(_error, this));
875
+ }
876
+ }
877
+ function _stopMic() {
878
+ const wasActive = _classPrivateFieldGet2(_workletNode, this) !== null || _classPrivateFieldGet2(_stream, this) !== null;
879
+ _classPrivateFieldGet2(_workletNode, this)?.disconnect();
880
+ _classPrivateFieldSet2(_workletNode, this, null);
881
+ _classPrivateFieldGet2(_stream, this)?.getTracks().forEach((track) => track.stop());
882
+ _classPrivateFieldSet2(_stream, this, null);
883
+ if (wasActive) _classPrivateFieldGet2(_diagnostics, this).emit("microphone.stopped");
884
+ _assertClassBrand(_VoiceClient_brand, this, _resetDetection).call(this);
885
+ }
886
+ function _processAudioLevel(rms) {
887
+ if (_classPrivateFieldGet2(_isMuted, this)) return;
888
+ _classPrivateFieldSet2(_audioLevel, this, rms);
889
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "audiolevelchange", rms);
890
+ if (_classPrivateFieldGet2(_isPlaying, this) && rms > _classPrivateFieldGet2(_interruptThreshold, this)) {
891
+ var _this$interruptChunkC;
892
+ _classPrivateFieldSet2(_interruptChunkCount, this, (_this$interruptChunkC = _classPrivateFieldGet2(_interruptChunkCount, this), _this$interruptChunkC++, _this$interruptChunkC));
893
+ if (_classPrivateFieldGet2(_interruptChunkCount, this) >= _classPrivateFieldGet2(_interruptChunks, this)) {
894
+ _classPrivateFieldGet2(_diagnostics, this).emit("speech.interrupt_detected");
895
+ _assertClassBrand(_VoiceClient_brand, this, _stopPlayback).call(this, "speech_interrupt");
896
+ _classPrivateFieldSet2(_interruptChunkCount, this, 0);
897
+ if (_classPrivateFieldGet2(_transport, this)?.connected) _classPrivateFieldGet2(_transport, this).sendJSON({ type: "interrupt" });
898
+ }
899
+ } else _classPrivateFieldSet2(_interruptChunkCount, this, 0);
900
+ if (rms > _classPrivateFieldGet2(_silenceThreshold, this)) {
901
+ if (!_classPrivateFieldGet2(_isSpeaking, this)) {
902
+ _classPrivateFieldSet2(_isSpeaking, this, true);
903
+ _classPrivateFieldGet2(_diagnostics, this).emit("speech.started");
904
+ if (_classPrivateFieldGet2(_transport, this)?.connected) _classPrivateFieldGet2(_transport, this).sendJSON({ type: "start_of_speech" });
905
+ }
906
+ if (_classPrivateFieldGet2(_silenceTimer, this)) {
907
+ clearTimeout(_classPrivateFieldGet2(_silenceTimer, this));
908
+ _classPrivateFieldSet2(_silenceTimer, this, null);
909
+ }
910
+ } else if (_classPrivateFieldGet2(_isSpeaking, this)) {
911
+ if (!_classPrivateFieldGet2(_silenceTimer, this)) _classPrivateFieldSet2(_silenceTimer, this, setTimeout(() => {
912
+ _classPrivateFieldSet2(_isSpeaking, this, false);
913
+ _classPrivateFieldSet2(_silenceTimer, this, null);
914
+ _classPrivateFieldGet2(_diagnostics, this).emit("speech.ended");
915
+ if (_classPrivateFieldGet2(_transport, this)?.connected) _classPrivateFieldGet2(_transport, this).sendJSON({ type: "end_of_speech" });
916
+ }, _classPrivateFieldGet2(_silenceDurationMs, this)));
917
+ }
918
+ }
919
+ function _resetDetection() {
920
+ if (_classPrivateFieldGet2(_silenceTimer, this)) {
921
+ clearTimeout(_classPrivateFieldGet2(_silenceTimer, this));
922
+ _classPrivateFieldSet2(_silenceTimer, this, null);
923
+ }
924
+ _classPrivateFieldSet2(_isSpeaking, this, false);
925
+ _classPrivateFieldSet2(_interruptChunkCount, this, 0);
926
+ _classPrivateFieldSet2(_audioLevel, this, 0);
927
+ _assertClassBrand(_VoiceClient_brand, this, _emit).call(this, "audiolevelchange", 0);
928
+ }
929
+ //#endregion
930
+ export { VOICE_PROTOCOL_VERSION, VoiceClient, WebSocketVoiceTransport };
931
+
932
+ //# sourceMappingURL=client.js.map