@absolutejs/voice 0.0.22-beta.660 → 0.0.22-beta.662

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.
@@ -525,6 +525,8 @@ var serverMessageToAction = (message) => {
525
525
  };
526
526
  case "session":
527
527
  return {
528
+ paused: message.paused,
529
+ pauseExpiresAt: message.pauseExpiresAt,
528
530
  sessionId: message.sessionId,
529
531
  sessionMetadata: message.sessionMetadata,
530
532
  scenarioId: message.scenarioId,
@@ -885,12 +887,6 @@ var createVoiceConnection = (path, options = {}) => {
885
887
  state.reconnectResetTimeout = null;
886
888
  }, reconnectResetAfterMs);
887
889
  }
888
- listeners.forEach((listener) => listener({
889
- scenarioId: state.scenarioId ?? undefined,
890
- sessionId: state.sessionId,
891
- status: "active",
892
- type: "session"
893
- }));
894
890
  state.pingInterval = setInterval(() => {
895
891
  if (ws.readyState === WS_OPEN) {
896
892
  ws.send(JSON.stringify({ type: "ping" }));
@@ -1121,6 +1117,7 @@ var createInitialState = () => ({
1121
1117
  call: null,
1122
1118
  error: null,
1123
1119
  isConnected: false,
1120
+ paused: false,
1124
1121
  partial: "",
1125
1122
  reconnect: createInitialReconnectState(),
1126
1123
  scenarioId: null,
@@ -1257,6 +1254,8 @@ var createVoiceStreamStore = () => {
1257
1254
  state = {
1258
1255
  ...state,
1259
1256
  error: null,
1257
+ paused: action.paused ?? false,
1258
+ pauseExpiresAt: action.pauseExpiresAt,
1260
1259
  scenarioId: action.scenarioId ?? state.scenarioId,
1261
1260
  isConnected: action.status === "active",
1262
1261
  sessionId: action.sessionId,
@@ -1393,6 +1392,12 @@ var createVoiceStream = (path, options = {}) => {
1393
1392
  get partial() {
1394
1393
  return store.getSnapshot().partial;
1395
1394
  },
1395
+ get paused() {
1396
+ return store.getSnapshot().paused;
1397
+ },
1398
+ get pauseExpiresAt() {
1399
+ return store.getSnapshot().pauseExpiresAt;
1400
+ },
1396
1401
  get reconnect() {
1397
1402
  return store.getSnapshot().reconnect;
1398
1403
  },
@@ -1756,6 +1761,8 @@ var createInitialState2 = (stream) => ({
1756
1761
  error: stream.error,
1757
1762
  isConnected: stream.isConnected,
1758
1763
  isRecording: false,
1764
+ paused: stream.paused,
1765
+ pauseExpiresAt: stream.pauseExpiresAt,
1759
1766
  partial: stream.partial,
1760
1767
  reconnect: stream.reconnect,
1761
1768
  recordingError: null,
@@ -1791,6 +1798,8 @@ var createVoiceController = (path, options = {}) => {
1791
1798
  call: stream.call,
1792
1799
  error: stream.error,
1793
1800
  isConnected: stream.isConnected,
1801
+ paused: stream.paused,
1802
+ pauseExpiresAt: stream.pauseExpiresAt,
1794
1803
  partial: stream.partial,
1795
1804
  reconnect: stream.reconnect,
1796
1805
  sessionId: stream.sessionId,
@@ -1938,6 +1947,12 @@ var createVoiceController = (path, options = {}) => {
1938
1947
  get partial() {
1939
1948
  return state.partial;
1940
1949
  },
1950
+ get paused() {
1951
+ return state.paused;
1952
+ },
1953
+ get pauseExpiresAt() {
1954
+ return state.pauseExpiresAt;
1955
+ },
1941
1956
  get reconnect() {
1942
1957
  return state.reconnect;
1943
1958
  },
@@ -20,6 +20,8 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
20
20
  sessionMetadata?: undefined;
21
21
  status?: undefined;
22
22
  turns?: undefined;
23
+ paused?: undefined;
24
+ pauseExpiresAt?: undefined;
23
25
  turn?: undefined;
24
26
  } | {
25
27
  text: string;
@@ -42,6 +44,8 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
42
44
  sessionMetadata?: undefined;
43
45
  status?: undefined;
44
46
  turns?: undefined;
47
+ paused?: undefined;
48
+ pauseExpiresAt?: undefined;
45
49
  turn?: undefined;
46
50
  } | {
47
51
  delta: string;
@@ -64,6 +68,8 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
64
68
  sessionMetadata?: undefined;
65
69
  status?: undefined;
66
70
  turns?: undefined;
71
+ paused?: undefined;
72
+ pauseExpiresAt?: undefined;
67
73
  turn?: undefined;
68
74
  } | {
69
75
  sessionId: string;
@@ -86,6 +92,8 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
86
92
  sessionMetadata?: undefined;
87
93
  status?: undefined;
88
94
  turns?: undefined;
95
+ paused?: undefined;
96
+ pauseExpiresAt?: undefined;
89
97
  turn?: undefined;
90
98
  } | {
91
99
  reconnect: import("..").VoiceReconnectClientState;
@@ -108,6 +116,8 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
108
116
  sessionMetadata?: undefined;
109
117
  status?: undefined;
110
118
  turns?: undefined;
119
+ paused?: undefined;
120
+ pauseExpiresAt?: undefined;
111
121
  turn?: undefined;
112
122
  } | {
113
123
  event: import("..").VoiceCallLifecycleEvent;
@@ -130,6 +140,8 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
130
140
  sessionMetadata?: undefined;
131
141
  status?: undefined;
132
142
  turns?: undefined;
143
+ paused?: undefined;
144
+ pauseExpiresAt?: undefined;
133
145
  turn?: undefined;
134
146
  } | {
135
147
  message: string;
@@ -152,6 +164,8 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
152
164
  sessionMetadata?: undefined;
153
165
  status?: undefined;
154
166
  turns?: undefined;
167
+ paused?: undefined;
168
+ pauseExpiresAt?: undefined;
155
169
  turn?: undefined;
156
170
  } | {
157
171
  transcript: import("..").Transcript;
@@ -174,6 +188,8 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
174
188
  sessionMetadata?: undefined;
175
189
  status?: undefined;
176
190
  turns?: undefined;
191
+ paused?: undefined;
192
+ pauseExpiresAt?: undefined;
177
193
  turn?: undefined;
178
194
  } | {
179
195
  transcript: import("..").Transcript;
@@ -196,6 +212,8 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
196
212
  sessionMetadata?: undefined;
197
213
  status?: undefined;
198
214
  turns?: undefined;
215
+ paused?: undefined;
216
+ pauseExpiresAt?: undefined;
199
217
  turn?: undefined;
200
218
  } | {
201
219
  assistantTexts: string[];
@@ -218,8 +236,12 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
218
236
  message?: undefined;
219
237
  recoverable?: undefined;
220
238
  transcript?: undefined;
239
+ paused?: undefined;
240
+ pauseExpiresAt?: undefined;
221
241
  turn?: undefined;
222
242
  } | {
243
+ paused: boolean | undefined;
244
+ pauseExpiresAt: number | undefined;
223
245
  sessionId: string;
224
246
  sessionMetadata: Record<string, unknown> | undefined;
225
247
  scenarioId: string | undefined;
@@ -263,4 +285,6 @@ export declare const serverMessageToAction: <TResult = unknown>(message: VoiceSe
263
285
  sessionMetadata?: undefined;
264
286
  status?: undefined;
265
287
  turns?: undefined;
288
+ paused?: undefined;
289
+ pauseExpiresAt?: undefined;
266
290
  } | null;
@@ -293,6 +293,8 @@ var serverMessageToAction = (message) => {
293
293
  };
294
294
  case "session":
295
295
  return {
296
+ paused: message.paused,
297
+ pauseExpiresAt: message.pauseExpiresAt,
296
298
  sessionId: message.sessionId,
297
299
  sessionMetadata: message.sessionMetadata,
298
300
  scenarioId: message.scenarioId,
@@ -802,12 +804,6 @@ var createVoiceConnection = (path, options = {}) => {
802
804
  state.reconnectResetTimeout = null;
803
805
  }, reconnectResetAfterMs);
804
806
  }
805
- listeners.forEach((listener) => listener({
806
- scenarioId: state.scenarioId ?? undefined,
807
- sessionId: state.sessionId,
808
- status: "active",
809
- type: "session"
810
- }));
811
807
  state.pingInterval = setInterval(() => {
812
808
  if (ws.readyState === WS_OPEN) {
813
809
  ws.send(JSON.stringify({ type: "ping" }));
@@ -1038,6 +1034,7 @@ var createInitialState = () => ({
1038
1034
  call: null,
1039
1035
  error: null,
1040
1036
  isConnected: false,
1037
+ paused: false,
1041
1038
  partial: "",
1042
1039
  reconnect: createInitialReconnectState(),
1043
1040
  scenarioId: null,
@@ -1174,6 +1171,8 @@ var createVoiceStreamStore = () => {
1174
1171
  state = {
1175
1172
  ...state,
1176
1173
  error: null,
1174
+ paused: action.paused ?? false,
1175
+ pauseExpiresAt: action.pauseExpiresAt,
1177
1176
  scenarioId: action.scenarioId ?? state.scenarioId,
1178
1177
  isConnected: action.status === "active",
1179
1178
  sessionId: action.sessionId,
@@ -1310,6 +1309,12 @@ var createVoiceStream = (path, options = {}) => {
1310
1309
  get partial() {
1311
1310
  return store.getSnapshot().partial;
1312
1311
  },
1312
+ get paused() {
1313
+ return store.getSnapshot().paused;
1314
+ },
1315
+ get pauseExpiresAt() {
1316
+ return store.getSnapshot().pauseExpiresAt;
1317
+ },
1313
1318
  get reconnect() {
1314
1319
  return store.getSnapshot().reconnect;
1315
1320
  },
@@ -1636,6 +1641,8 @@ var createInitialState2 = (stream) => ({
1636
1641
  error: stream.error,
1637
1642
  isConnected: stream.isConnected,
1638
1643
  isRecording: false,
1644
+ paused: stream.paused,
1645
+ pauseExpiresAt: stream.pauseExpiresAt,
1639
1646
  partial: stream.partial,
1640
1647
  reconnect: stream.reconnect,
1641
1648
  recordingError: null,
@@ -1671,6 +1678,8 @@ var createVoiceController = (path, options = {}) => {
1671
1678
  call: stream.call,
1672
1679
  error: stream.error,
1673
1680
  isConnected: stream.isConnected,
1681
+ paused: stream.paused,
1682
+ pauseExpiresAt: stream.pauseExpiresAt,
1674
1683
  partial: stream.partial,
1675
1684
  reconnect: stream.reconnect,
1676
1685
  sessionId: stream.sessionId,
@@ -1818,6 +1827,12 @@ var createVoiceController = (path, options = {}) => {
1818
1827
  get partial() {
1819
1828
  return state.partial;
1820
1829
  },
1830
+ get paused() {
1831
+ return state.paused;
1832
+ },
1833
+ get pauseExpiresAt() {
1834
+ return state.pauseExpiresAt;
1835
+ },
1821
1836
  get reconnect() {
1822
1837
  return state.reconnect;
1823
1838
  },
@@ -366,12 +366,6 @@ var createVoiceConnection = (path, options = {}) => {
366
366
  state.reconnectResetTimeout = null;
367
367
  }, reconnectResetAfterMs);
368
368
  }
369
- listeners.forEach((listener) => listener({
370
- scenarioId: state.scenarioId ?? undefined,
371
- sessionId: state.sessionId,
372
- status: "active",
373
- type: "session"
374
- }));
375
369
  state.pingInterval = setInterval(() => {
376
370
  if (ws.readyState === WS_OPEN) {
377
371
  ws.send(JSON.stringify({ type: "ping" }));
@@ -1396,6 +1390,8 @@ var serverMessageToAction = (message) => {
1396
1390
  };
1397
1391
  case "session":
1398
1392
  return {
1393
+ paused: message.paused,
1394
+ pauseExpiresAt: message.pauseExpiresAt,
1399
1395
  sessionId: message.sessionId,
1400
1396
  sessionMetadata: message.sessionMetadata,
1401
1397
  scenarioId: message.scenarioId,
@@ -1524,6 +1520,7 @@ var createInitialState2 = () => ({
1524
1520
  call: null,
1525
1521
  error: null,
1526
1522
  isConnected: false,
1523
+ paused: false,
1527
1524
  partial: "",
1528
1525
  reconnect: createInitialReconnectState(),
1529
1526
  scenarioId: null,
@@ -1660,6 +1657,8 @@ var createVoiceStreamStore = () => {
1660
1657
  state = {
1661
1658
  ...state,
1662
1659
  error: null,
1660
+ paused: action.paused ?? false,
1661
+ pauseExpiresAt: action.pauseExpiresAt,
1663
1662
  scenarioId: action.scenarioId ?? state.scenarioId,
1664
1663
  isConnected: action.status === "active",
1665
1664
  sessionId: action.sessionId,
@@ -1796,6 +1795,12 @@ var createVoiceStream = (path, options = {}) => {
1796
1795
  get partial() {
1797
1796
  return store.getSnapshot().partial;
1798
1797
  },
1798
+ get paused() {
1799
+ return store.getSnapshot().paused;
1800
+ },
1801
+ get pauseExpiresAt() {
1802
+ return store.getSnapshot().pauseExpiresAt;
1803
+ },
1799
1804
  get reconnect() {
1800
1805
  return store.getSnapshot().reconnect;
1801
1806
  },
@@ -2352,6 +2357,8 @@ var createInitialState3 = (stream) => ({
2352
2357
  error: stream.error,
2353
2358
  isConnected: stream.isConnected,
2354
2359
  isRecording: false,
2360
+ paused: stream.paused,
2361
+ pauseExpiresAt: stream.pauseExpiresAt,
2355
2362
  partial: stream.partial,
2356
2363
  reconnect: stream.reconnect,
2357
2364
  recordingError: null,
@@ -2387,6 +2394,8 @@ var createVoiceController = (path, options = {}) => {
2387
2394
  call: stream.call,
2388
2395
  error: stream.error,
2389
2396
  isConnected: stream.isConnected,
2397
+ paused: stream.paused,
2398
+ pauseExpiresAt: stream.pauseExpiresAt,
2390
2399
  partial: stream.partial,
2391
2400
  reconnect: stream.reconnect,
2392
2401
  sessionId: stream.sessionId,
@@ -2534,6 +2543,12 @@ var createVoiceController = (path, options = {}) => {
2534
2543
  get partial() {
2535
2544
  return state.partial;
2536
2545
  },
2546
+ get paused() {
2547
+ return state.paused;
2548
+ },
2549
+ get pauseExpiresAt() {
2550
+ return state.pauseExpiresAt;
2551
+ },
2537
2552
  get reconnect() {
2538
2553
  return state.reconnect;
2539
2554
  },
@@ -1281,6 +1281,8 @@ export type VoiceClientPingMessage = {
1281
1281
  export type VoiceClientMessage = VoiceClientStartMessage | VoiceClientEndTurnMessage | VoiceClientCloseMessage | VoiceClientCallControlMessage | VoiceClientPingMessage;
1282
1282
  export type VoiceServerSessionMessage = {
1283
1283
  type: "session";
1284
+ paused?: boolean;
1285
+ pauseExpiresAt?: number;
1284
1286
  sessionId: string;
1285
1287
  status: VoiceSessionStatus;
1286
1288
  scenarioId?: string;
@@ -1531,6 +1533,8 @@ export type VoiceHTMXOptions<TSession extends VoiceSessionRecord = VoiceSessionR
1531
1533
  export type VoiceHTMXConfig<TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown> = VoiceHTMXRenderer<TSession, TResult> | VoiceHTMXOptions<TSession, TResult>;
1532
1534
  export type VoiceStreamState<TResult = unknown> = {
1533
1535
  call: VoiceCallLifecycleState | null;
1536
+ paused: boolean;
1537
+ pauseExpiresAt?: number;
1534
1538
  sessionMetadata: Record<string, unknown> | null;
1535
1539
  sessionId: string | null;
1536
1540
  scenarioId: string | null;
@@ -1551,6 +1555,8 @@ export type VoiceStreamState<TResult = unknown> = {
1551
1555
  };
1552
1556
  export type VoiceStream<TResult = unknown> = {
1553
1557
  call: VoiceCallLifecycleState | null;
1558
+ paused: boolean;
1559
+ pauseExpiresAt?: number;
1554
1560
  callControl: (message: Omit<VoiceClientCallControlMessage, "requestId" | "type">) => Promise<void>;
1555
1561
  close: (reason?: string) => void;
1556
1562
  /** Release the transport without terminally completing the server session. */
@@ -1648,6 +1654,8 @@ export type VoiceBargeInBinding = {
1648
1654
  export type VoiceController<TResult = unknown> = {
1649
1655
  bindHTMX: (options: VoiceHTMXBindingOptions) => () => void;
1650
1656
  call: VoiceCallLifecycleState | null;
1657
+ paused: boolean;
1658
+ pauseExpiresAt?: number;
1651
1659
  callControl: (message: Omit<VoiceClientCallControlMessage, "requestId" | "type">) => Promise<void>;
1652
1660
  close: (reason?: string) => void;
1653
1661
  /** Release the transport while leaving the server session resumable. */
@@ -1697,6 +1705,8 @@ export type VoiceHTMXBindingOptions = {
1697
1705
  };
1698
1706
  export type VoiceStoreAction<TResult = unknown> = {
1699
1707
  type: "session";
1708
+ paused?: boolean;
1709
+ pauseExpiresAt?: number;
1700
1710
  sessionId: string;
1701
1711
  sessionMetadata?: Record<string, unknown>;
1702
1712
  scenarioId?: string;
@@ -290,6 +290,8 @@ var serverMessageToAction = (message) => {
290
290
  };
291
291
  case "session":
292
292
  return {
293
+ paused: message.paused,
294
+ pauseExpiresAt: message.pauseExpiresAt,
293
295
  sessionId: message.sessionId,
294
296
  sessionMetadata: message.sessionMetadata,
295
297
  scenarioId: message.scenarioId,
@@ -799,12 +801,6 @@ var createVoiceConnection = (path, options = {}) => {
799
801
  state.reconnectResetTimeout = null;
800
802
  }, reconnectResetAfterMs);
801
803
  }
802
- listeners.forEach((listener) => listener({
803
- scenarioId: state.scenarioId ?? undefined,
804
- sessionId: state.sessionId,
805
- status: "active",
806
- type: "session"
807
- }));
808
804
  state.pingInterval = setInterval(() => {
809
805
  if (ws.readyState === WS_OPEN) {
810
806
  ws.send(JSON.stringify({ type: "ping" }));
@@ -1035,6 +1031,7 @@ var createInitialState = () => ({
1035
1031
  call: null,
1036
1032
  error: null,
1037
1033
  isConnected: false,
1034
+ paused: false,
1038
1035
  partial: "",
1039
1036
  reconnect: createInitialReconnectState(),
1040
1037
  scenarioId: null,
@@ -1171,6 +1168,8 @@ var createVoiceStreamStore = () => {
1171
1168
  state = {
1172
1169
  ...state,
1173
1170
  error: null,
1171
+ paused: action.paused ?? false,
1172
+ pauseExpiresAt: action.pauseExpiresAt,
1174
1173
  scenarioId: action.scenarioId ?? state.scenarioId,
1175
1174
  isConnected: action.status === "active",
1176
1175
  sessionId: action.sessionId,
@@ -1307,6 +1306,12 @@ var createVoiceStream = (path, options = {}) => {
1307
1306
  get partial() {
1308
1307
  return store.getSnapshot().partial;
1309
1308
  },
1309
+ get paused() {
1310
+ return store.getSnapshot().paused;
1311
+ },
1312
+ get pauseExpiresAt() {
1313
+ return store.getSnapshot().pauseExpiresAt;
1314
+ },
1310
1315
  get reconnect() {
1311
1316
  return store.getSnapshot().reconnect;
1312
1317
  },
@@ -1633,6 +1638,8 @@ var createInitialState2 = (stream) => ({
1633
1638
  error: stream.error,
1634
1639
  isConnected: stream.isConnected,
1635
1640
  isRecording: false,
1641
+ paused: stream.paused,
1642
+ pauseExpiresAt: stream.pauseExpiresAt,
1636
1643
  partial: stream.partial,
1637
1644
  reconnect: stream.reconnect,
1638
1645
  recordingError: null,
@@ -1668,6 +1675,8 @@ var createVoiceController = (path, options = {}) => {
1668
1675
  call: stream.call,
1669
1676
  error: stream.error,
1670
1677
  isConnected: stream.isConnected,
1678
+ paused: stream.paused,
1679
+ pauseExpiresAt: stream.pauseExpiresAt,
1671
1680
  partial: stream.partial,
1672
1681
  reconnect: stream.reconnect,
1673
1682
  sessionId: stream.sessionId,
@@ -1815,6 +1824,12 @@ var createVoiceController = (path, options = {}) => {
1815
1824
  get partial() {
1816
1825
  return state.partial;
1817
1826
  },
1827
+ get paused() {
1828
+ return state.paused;
1829
+ },
1830
+ get pauseExpiresAt() {
1831
+ return state.pauseExpiresAt;
1832
+ },
1818
1833
  get reconnect() {
1819
1834
  return state.reconnect;
1820
1835
  },
@@ -1,10 +1,10 @@
1
- (()=>{var{defineProperty:k,getOwnPropertyNames:w0,getOwnPropertyDescriptor:J0}=Object,S0=Object.prototype.hasOwnProperty;function Y0(V){return this[V]}var Z0=(V)=>{var g=(l??=new WeakMap).get(V),C;if(g)return g;if(g=k({},"__esModule",{value:!0}),V&&typeof V==="object"||typeof V==="function"){for(var A of w0(V))if(!S0.call(g,A))k(g,A,{get:Y0.bind(V,A),enumerable:!(C=J0(V,A))||C.enumerable})}return l.set(V,g),g},l;var y0=(V)=>V;function h0(V,g){this[V]=y0.bind(null,g)}var Q0=(V,g)=>{for(var C in g)k(V,C,{get:g[C],enumerable:!0,configurable:!0,set:h0.bind(g,C)})};var _V={};Q0(_V,{mount:()=>$0,default:()=>TV,VOICE_EMBED_VERSION:()=>R0});var K0=(V)=>{if(typeof V!=="string")return V;return document.querySelector(V)},c0=(V,g,C,A)=>{let R=g??V.getAttribute("hx-get")??"";if(!R)return"";let _=new URL(R,window.location.origin);if(A)_.searchParams.set(C,A);else _.searchParams.delete(C);return`${_.pathname}${_.search}${_.hash}`},d=(V,g)=>{if(typeof window>"u"||typeof document>"u")return()=>{};let C=K0(g.element);if(!C)return()=>{};let A=g.eventName??"voice-refresh",R=g.sessionQueryParam??"sessionId",_=()=>{let X=window,H=c0(C,g.route,R,V.sessionId);if(H)C.setAttribute("hx-get",H);X.htmx?.process?.(C),X.htmx?.trigger?.(C,A)},D=V.subscribe(_);return _(),()=>{D()}};var E0=(V)=>Math.max(-1,Math.min(1,V)),q0=(V)=>{let g=new Int16Array(V.length);for(let C=0;C<V.length;C+=1){let A=E0(V[C]??0);g[C]=A<0?A*32768:A*32767}return new Uint8Array(g.buffer)},N0=(V)=>{let g=V instanceof Uint8Array?V:new Uint8Array(V);if(g.byteLength<2)return 0;let C=new Int16Array(g.buffer,g.byteOffset,Math.floor(g.byteLength/2));if(C.length===0)return 0;let A=0;for(let R of C){let _=R/32768;A+=_*_}return Math.min(1,Math.max(0,Math.sqrt(A/C.length)*5.5))},z0=(V,g,C)=>{if(g===C)return V;let A=g/C,R=Math.round(V.length/A),_=new Float32Array(R),D=0,X=0;while(D<_.length){let H=Math.round((D+1)*A),O=0,L=0;for(let W=X;W<H&&W<V.length;W+=1)O+=V[W]??0,L+=1;_[D]=L>0?O/L:0,D+=1,X=H}return _},v=(V)=>{let g=null,C=null,A=null,R=null,_=0,D=null,X=(L)=>{L.processorNode?.disconnect(),L.sourceNode?.disconnect(),L.mediaStream?.getTracks().forEach((W)=>W.stop()),L.audioContext?.close()};return{start:()=>{if(R)return Promise.resolve();if(D)return D;let L=++_,U=(async()=>{if(!V.stream&&(typeof navigator>"u"||!navigator.mediaDevices?.getUserMedia))throw Error("Browser microphone capture requires navigator.mediaDevices.getUserMedia.");let T=(typeof window<"u"?window.AudioContext??window.webkitAudioContext:void 0)??AudioContext;if(!T)throw Error("Browser microphone capture requires AudioContext support.");let J=null,h=null,Z=null,Q=null;try{if(h=V.stream??await navigator.mediaDevices.getUserMedia({audio:{autoGainControl:!0,channelCount:V.channelCount??1,echoCancellation:!0,noiseSuppression:!0}}),L!==_)throw Error("Microphone capture stopped during startup.");if(J=new T,J.state==="suspended")await J.resume();if(L!==_)throw Error("Microphone capture stopped during startup.");if(Q=J.createMediaStreamSource(h),Z=J.createScriptProcessor(4096,1,1),Z.onaudioprocess=(G)=>{let c=G.inputBuffer.getChannelData(0),q=z0(c,J?.sampleRate??48000,V.sampleRateHz??16000),$=q0(q);V.onLevel?.(N0($)),V.onAudio($)},Q.connect(Z),Z.connect(J.destination),L!==_)throw Error("Microphone capture stopped during startup.");g=J,R=h,A=Z,C=Q}catch(G){throw X({audioContext:J,mediaStream:h,processorNode:Z,sourceNode:Q}),G}})().finally(()=>{if(D===U)D=null});return D=U,U},stop:()=>{_+=1,X({audioContext:g,mediaStream:R,processorNode:A,sourceNode:C}),V.onLevel?.(0),g=null,R=null,A=null,C=null}}};var F=(V)=>{if(typeof V==="string"&&V.trim())return V;if(V instanceof Error&&V.message.trim())return V.message;if(V&&typeof V==="object"){let g=V;for(let C of["message","reason","description"]){let A=g[C];if(typeof A==="string"&&A.trim())return A}if("error"in g)return F(g.error);if("cause"in g)return F(g.cause);try{return JSON.stringify(V)}catch{}}return"Unexpected error"},i=(V)=>{switch(V.type){case"audio":return{chunk:Uint8Array.from(atob(V.chunkBase64),(g)=>g.charCodeAt(0)),format:V.format,receivedAt:V.receivedAt,turnId:V.turnId,type:"audio"};case"assistant":return{text:V.text,turnId:V.turnId,type:"assistant"};case"assistant_delta":return{delta:V.delta,turnId:V.turnId,type:"assistant_delta"};case"complete":return{sessionId:V.sessionId,type:"complete"};case"connection":return{reconnect:V.reconnect,type:"connection"};case"call_lifecycle":return{event:V.event,sessionId:V.sessionId,type:"call_lifecycle"};case"error":return{message:F(V.message),recoverable:V.recoverable,type:"error"};case"call_control_ack":return null;case"final":return{transcript:V.transcript,type:"final"};case"partial":return{transcript:V.transcript,type:"partial"};case"replay":return{assistantTexts:V.assistantTexts,call:V.call,partial:V.partial,scenarioId:V.scenarioId,sessionId:V.sessionId,sessionMetadata:V.sessionMetadata,status:V.status,turns:V.turns,type:"replay"};case"session":return{sessionId:V.sessionId,sessionMetadata:V.sessionMetadata,scenarioId:V.scenarioId,status:V.status,type:"session"};case"turn":return{turn:V.turn,type:"turn"};default:return null}};var UV=Math.PI*2;var N=(V,g,C,A)=>{V.push({code:C,message:A,severity:g})};var P0=(V)=>V.length===0?void 0:V.reduce((g,C)=>g+C,0)/V.length,x=(V)=>V.length===0?void 0:Math.max(...V);var K=(V,g)=>{let C=V[g];return typeof C==="number"&&Number.isFinite(C)?C:void 0},j=(V,g)=>{let C=V[g];return typeof C==="boolean"?C:void 0},E=(V,g)=>{let C=V[g];return typeof C==="string"?C:void 0},f=(V)=>String(V.id??E(V,"ssrc")??K(V,"ssrc")??E(V,"trackIdentifier")??E(V,"mid")??"unknown"),o=(V)=>V===void 0?void 0:V*1000;var B0=(V)=>{let g={};for(let[C,A]of Object.entries(V))if(A===null||typeof A==="boolean"||typeof A==="number"||typeof A==="string")g[C]=A;return g};var n=(V={})=>{let g=V.stats??[],C=[],A=g.filter(($)=>$.type==="inbound-rtp"&&E($,"kind")!=="video"),R=g.filter(($)=>$.type==="outbound-rtp"&&E($,"kind")!=="video"),_=g.filter(($)=>$.type==="candidate-pair"),D=g.filter(($)=>($.type==="track"||$.type==="media-source")&&E($,"kind")==="audio"),X=_.filter(($)=>j($,"selected")===!0||j($,"nominated")===!0||E($,"state")==="succeeded").length,H=D.filter(($)=>E($,"readyState")!=="ended"&&E($,"trackState")!=="ended"&&j($,"ended")!==!0).length,O=D.filter(($)=>E($,"readyState")==="ended"||E($,"trackState")==="ended"||j($,"ended")===!0).length,L=A.reduce(($,S)=>$+(K(S,"packetsReceived")??0),0),W=R.reduce(($,S)=>$+(K(S,"packetsSent")??0),0),U=[...A,...R].reduce(($,S)=>$+Math.max(0,K(S,"packetsLost")??0),0),T=L+U,J=T===0?0:U/T,h=A.reduce(($,S)=>$+(K(S,"bytesReceived")??0),0),Z=R.reduce(($,S)=>$+(K(S,"bytesSent")??0),0),Q=x(_.map(($)=>o(K($,"currentRoundTripTime")??K($,"roundTripTime"))).filter(($)=>$!==void 0)),G=x([...A,...R].map(($)=>o(K($,"jitter"))).filter(($)=>$!==void 0)),c=x(A.map(($)=>{let S=K($,"jitterBufferDelay"),b=K($,"jitterBufferEmittedCount");return S!==void 0&&b!==void 0&&b>0?S/b*1000:void 0}).filter(($)=>$!==void 0)),q=D.map(($)=>K($,"audioLevel")).filter(($)=>$!==void 0);if(V.requireConnectedCandidatePair&&_.length>0&&X===0)N(C,"error","media.webrtc_candidate_pair_missing","No active WebRTC candidate pair was observed.");if(V.requireLiveAudioTrack&&H===0)N(C,"error","media.webrtc_audio_track_missing","No live WebRTC audio track was observed.");if(V.maxPacketLossRatio!==void 0&&J>V.maxPacketLossRatio)N(C,"warning","media.webrtc_packet_loss",`Observed WebRTC packet loss ratio ${String(J)} above ${String(V.maxPacketLossRatio)}.`);if(V.maxRoundTripTimeMs!==void 0&&Q!==void 0&&Q>V.maxRoundTripTimeMs)N(C,"warning","media.webrtc_round_trip_time",`Observed WebRTC RTT ${String(Q)}ms above ${String(V.maxRoundTripTimeMs)}ms.`);if(V.maxJitterMs!==void 0&&G!==void 0&&G>V.maxJitterMs)N(C,"warning","media.webrtc_jitter",`Observed WebRTC jitter ${String(G)}ms above ${String(V.maxJitterMs)}ms.`);return{activeCandidatePairs:X,audioLevelAverage:P0(q),bytesReceived:h,bytesSent:Z,checkedAt:Date.now(),endedAudioTracks:O,inboundPackets:L,issues:C,jitterBufferDelayMs:c,jitterMs:G,liveAudioTracks:H,outboundPackets:W,packetLossRatio:J,packetsLost:U,roundTripTimeMs:Q,status:C.some(($)=>$.severity==="error")?"fail":C.length>0?"warn":"pass",totalStats:g.length}},m=async(V)=>{return[...(await V.peerConnection.getStats(V.selector??null)).values()].map(B0)};var u=(V={})=>{let g=V.stats??[],C=V.previousStats??[],A=[],R=new Map(C.map((U)=>[f(U),U])),D=g.filter((U)=>(U.type==="inbound-rtp"||U.type==="outbound-rtp")&&E(U,"kind")!=="video"&&E(U,"mediaType")!=="video").map((U)=>{let T=U.type==="outbound-rtp"?"outbound":"inbound",J=T==="outbound"?"packetsSent":"packetsReceived",h=T==="outbound"?"bytesSent":"bytesReceived",Z=R.get(f(U)),Q=K(U,J),G=Z?K(Z,J):void 0,c=K(U,h),q=Z?K(Z,h):void 0,$=U.timestamp!==void 0&&Z?.timestamp!==void 0?U.timestamp-Z.timestamp:void 0;return{bytesDelta:c!==void 0&&q!==void 0?c-q:void 0,currentPackets:Q,direction:T,id:f(U),packetDelta:Q!==void 0&&G!==void 0?Q-G:void 0,previousPackets:G,timeDeltaMs:$}}),X=D.filter((U)=>U.direction==="inbound"),H=D.filter((U)=>U.direction==="outbound"),O=x(D.map((U)=>U.timeDeltaMs).filter((U)=>U!==void 0)),L=X.filter((U)=>V.maxInboundPacketStallMs!==void 0&&U.timeDeltaMs!==void 0&&U.timeDeltaMs>=V.maxInboundPacketStallMs&&U.packetDelta!==void 0&&U.packetDelta<=0).length,W=H.filter((U)=>V.maxOutboundPacketStallMs!==void 0&&U.timeDeltaMs!==void 0&&U.timeDeltaMs>=V.maxOutboundPacketStallMs&&U.packetDelta!==void 0&&U.packetDelta<=0).length;if(V.requireInboundAudio&&X.length===0)N(A,"error","media.webrtc_inbound_audio_missing","No inbound WebRTC audio RTP stream was observed.");if(V.requireOutboundAudio&&H.length===0)N(A,"error","media.webrtc_outbound_audio_missing","No outbound WebRTC audio RTP stream was observed.");if(V.maxGapMs!==void 0&&O!==void 0&&O>V.maxGapMs)N(A,"warning","media.webrtc_stream_gap",`Observed WebRTC stream sample gap ${String(O)}ms above ${String(V.maxGapMs)}ms.`);if(L>0)N(A,"error","media.webrtc_inbound_stalled",`${String(L)} inbound WebRTC audio stream(s) stopped receiving packets.`);if(W>0)N(A,"error","media.webrtc_outbound_stalled",`${String(W)} outbound WebRTC audio stream(s) stopped sending packets.`);return{checkedAt:Date.now(),inboundAudioStreams:X.length,issues:A,maxObservedGapMs:O,outboundAudioStreams:H.length,stalledInboundStreams:L,stalledOutboundStreams:W,status:A.some((U)=>U.severity==="error")?"fail":A.length>0?"warn":"pass",streams:D,totalStats:g.length}};var M0="/api/voice/browser-media",b0=5000,j0=async(V)=>V.peerConnection??await V.getPeerConnection?.()??null,x0=async(V,g)=>{let C=g.fetch??globalThis.fetch;if(!C)return;await C(g.path??M0,{body:JSON.stringify(V),headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"})},r=(V)=>{let g=null,C=[],A=async()=>{let D=await j0(V);if(!D)return;let X=await m({peerConnection:D}),H=n({...V,stats:X}),O=V.continuity===!1?void 0:u({...V.continuity,previousStats:C,stats:X}),L={at:Date.now(),continuity:O,report:H,scenarioId:V.getScenarioId?.()??null,sessionId:V.getSessionId?.()??null};return C=X,V.onReport?.(L),await x0(L,V),L},R=()=>{A().catch((D)=>{V.onError?.(D)})},_=()=>{if(g)clearInterval(g),g=null};return{close:_,reportOnce:A,stop:_,start:()=>{if(g)return;R(),g=setInterval(R,V.intervalMs??b0)}}};var k0=(V,g,C)=>Math.min(C,g*2**(Math.max(1,V)-1));class s extends Error{constructor(V="Voice authorization could not be renewed."){super(V);this.name="VoiceReconnectRejectedError"}}var P=()=>{},F0=()=>Promise.resolve(),f0=()=>P,l0={callControl:F0,close:P,disconnect:P,endTurn:P,send:P,sendAudio:P,simulateDisconnect:P,subscribe:f0,getReadyState:()=>3,getScenarioId:()=>"",getSessionId:()=>"",start:()=>{}},d0=()=>crypto.randomUUID(),v0=(V,g,C,A)=>{let{hostname:R,port:_,protocol:D}=window.location,X=D==="https:"?"wss:":"ws:",H=_?`:${_}`:"",O=new URL(`${X}//${R}${H}${V}`);if(O.searchParams.set("sessionId",g),C)O.searchParams.set("scenarioId",C);for(let[L,W]of Object.entries(A))if(L!=="sessionId"&&L!=="scenarioId"&&W)O.searchParams.set(L,W);return O.toString()},i0=(V)=>{if(!V||typeof V!=="object"||!("type"in V))return!1;switch(V.type){case"audio":case"assistant":case"call_lifecycle":case"call_control_ack":case"complete":case"connection":case"error":case"final":case"partial":case"pong":case"replay":case"session":case"turn":return!0;default:return!1}},o0=(V)=>{if(typeof V.data!=="string")return null;try{let g=JSON.parse(V.data);return i0(g)?g:null}catch{return null}},a=(V,g={})=>{if(typeof window>"u")return l0;let C=new Set,A=new Map,R=g.reconnect!==!1,_=g.maxReconnectAttempts??15,D=g.reconnectMaxDelayMs??8000,X=g.pingInterval??30000,H=g.reconnectResetAfterMs??30000,O=0,L=!1,W=null,U=(I)=>k0(I,500,D),T={isConnected:!1,pendingMessages:[],scenarioId:g.scenarioId??null,pingInterval:null,reconnectAttempts:0,reconnectResetTimeout:null,reconnectTimeout:null,sessionId:g.sessionId??d0(),ws:null},J=(I)=>{C.forEach((w)=>w(I))},h=(I)=>{C.forEach((w)=>w({message:I,recoverable:!1,type:"error"})),J({reconnect:{attempts:T.reconnectAttempts,maxAttempts:_,status:"exhausted"},type:"connection"})},Z=()=>{if(T.pingInterval)clearInterval(T.pingInterval),T.pingInterval=null;if(T.reconnectTimeout)clearTimeout(T.reconnectTimeout),T.reconnectTimeout=null;if(T.reconnectResetTimeout)clearTimeout(T.reconnectResetTimeout),T.reconnectResetTimeout=null},Q=()=>{if(T.ws?.readyState!==1)return;while(T.pendingMessages.length>0){let I=T.pendingMessages.shift();if(I!==void 0)T.ws.send(I)}},G=(I)=>{for(let w of A.values())clearTimeout(w.timeout),w.reject(Error(I));A.clear()},c=()=>{if(L)return;let I=O;T.reconnectAttempts+=1;let w=U(T.reconnectAttempts),y=Date.now()+w;J({reconnect:{attempts:T.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:_,nextAttemptAt:y,status:"reconnecting"},type:"connection"}),T.reconnectTimeout=setTimeout(async()=>{if(L||O!==I)return;if(T.reconnectAttempts>_){h("Voice connection could not be restored.");return}try{if(g.prepareReconnect){let Y=new AbortController;W=Y;let B=setTimeout(()=>Y.abort("Voice reconnect preparation timed out"),g.prepareReconnectTimeoutMs??1e4);try{await Promise.race([g.prepareReconnect({attempt:T.reconnectAttempts,path:V,scenarioId:T.scenarioId,sessionId:T.sessionId,signal:Y.signal}),new Promise((M,O0)=>{Y.signal.addEventListener("abort",()=>O0(Error("Voice reconnect preparation timed out.")),{once:!0})})])}finally{if(clearTimeout(B),W===Y)W=null}}}catch(Y){if(L||O!==I)return;if(Y instanceof s){h(Y.message);return}if(T.reconnectAttempts<_)c();else h("Voice authorization could not be renewed for reconnect.");return}if(L||O!==I)return;q()},w)},q=()=>{if(L)return;let I=new WebSocket(v0(V,T.sessionId,T.scenarioId,g.query??{}));I.binaryType="arraybuffer",I.onopen=()=>{if(T.ws!==I){I.close(1000);return}let w=T.reconnectAttempts>0;if(T.isConnected=!0,Q(),w)J({reconnect:{attempts:T.reconnectAttempts,lastResumedAt:Date.now(),maxAttempts:_,status:"resumed"},type:"connection"}),T.reconnectResetTimeout=setTimeout(()=>{if(T.ws===I&&I.readyState===1)T.reconnectAttempts=0;T.reconnectResetTimeout=null},H);C.forEach((y)=>y({scenarioId:T.scenarioId??void 0,sessionId:T.sessionId,status:"active",type:"session"})),T.pingInterval=setInterval(()=>{if(I.readyState===1)I.send(JSON.stringify({type:"ping"}))},X)},I.onmessage=(w)=>{if(T.ws!==I)return;let y=o0(w);if(!y)return;if(y.type==="session")T.sessionId=y.sessionId,T.scenarioId=y.scenarioId??T.scenarioId;if(y.type==="call_control_ack"){let Y=A.get(y.requestId);if(Y)if(clearTimeout(Y.timeout),A.delete(y.requestId),y.ok)Y.resolve();else Y.reject(Error(y.message??`${y.action} was not applied`))}C.forEach((Y)=>Y(y))},I.onclose=(w)=>{if(T.ws!==I)return;T.ws=null,T.isConnected=!1,Z(),G("Voice connection interrupted");let y=R&&w.code!==1000&&w.code!==4401&&w.code!==4403&&w.code!==4500&&T.reconnectAttempts<_,Y=w.code===4401||w.code===4403,B=w.code===4500;if(Y)C.forEach((M)=>M({message:w.code===4401?"Voice authorization expired or was rejected.":"Voice authorization was forbidden.",recoverable:!1,type:"error"}));if(B)C.forEach((M)=>M({message:"Voice provider initialization failed.",recoverable:!1,type:"error"}));if(y)c();else if(R&&w.code!==1000){if(Y)J({reconnect:{attempts:T.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:_,status:"exhausted"},type:"connection"});else if(!B)h("Voice connection could not be restored.")}},T.ws=I},$=(I)=>{if(L)return;if(T.ws?.readyState===1){T.ws.send(I);return}if(typeof I!=="string")return;if(T.pendingMessages.length>=100)T.pendingMessages.shift();T.pendingMessages.push(I)},S=(I)=>{$(JSON.stringify(I))},b=(I={})=>{if(I.sessionId&&I.sessionId!==T.sessionId)throw Error("Voice session switching requires a new connection instance.");if(I.sessionId)T.sessionId=I.sessionId;if(I.scenarioId)T.scenarioId=I.scenarioId;S({scenarioId:T.scenarioId??void 0,sessionId:T.sessionId,type:"start"})},I0=(I)=>{$(I)},U0=()=>{S({type:"end_turn"})},L0=(I)=>{if(T.ws?.readyState!==1)return Promise.reject(Error(`${I.action} is unavailable while disconnected`));let w=crypto.randomUUID(),{promise:y,reject:Y,resolve:B}=Promise.withResolvers(),M=setTimeout(()=>{A.delete(w),Y(Error(`${I.action} acknowledgement timed out`))},5000);return A.set(w,{reject:Y,resolve:B,timeout:M}),T.ws.send(JSON.stringify({...I,requestId:w,type:"call_control"})),y},W0=(I="client-close")=>{if(L=!0,W?.abort(),W=null,O+=1,Z(),G("Voice connection closed"),T.pendingMessages.length=0,T.ws){let w=T.ws;if(T.ws=null,w.readyState===1)w.send(JSON.stringify({reason:I,type:"close"}));w.close(1000)}T.isConnected=!1,C.clear()},D0=()=>{if(L=!0,W?.abort(),W=null,O+=1,Z(),G("Voice connection disconnected"),T.pendingMessages.length=0,T.ws){let I=T.ws;T.ws=null,I.close(1000)}T.isConnected=!1,C.clear()},X0=()=>{if(T.ws?.readyState===1)T.ws.close(4000,"absolutejs-voice-reconnect-proof")},G0=(I)=>{return C.add(I),()=>{C.delete(I)}};return q(),{callControl:L0,close:W0,disconnect:D0,endTurn:U0,send:S,sendAudio:I0,simulateDisconnect:X0,start:b,subscribe:G0,getReadyState:()=>T.ws?.readyState??3,getScenarioId:()=>T.scenarioId??"",getSessionId:()=>T.sessionId}};var n0=()=>({attempts:0,maxAttempts:0,status:"idle"}),m0=(V,g)=>{let C=g.trim().replace(/\s+/g," ");if(!C)return V;if(!V)return C;if(V===C||V.endsWith(C))return V;if(C.includes(V))return C;return`${V} ${C}`},u0=(V,g)=>{let C=g.trim().replace(/\s+/g," ");if(!V)return C;if(!C||V.endsWith(C))return V;return`${V} ${C}`},r0=()=>({assistantAudio:[],assistantStreamingText:"",assistantTexts:[],call:null,error:null,isConnected:!1,partial:"",reconnect:n0(),scenarioId:null,sessionId:null,sessionMetadata:null,status:"idle",turns:[]}),p=()=>{let V=r0(),g="",C=new Set,A=()=>{C.forEach((_)=>_())};return{dispatch:(_)=>{switch(_.type){case"audio":V={...V,assistantAudio:[...V.assistantAudio,{chunk:_.chunk,format:_.format,receivedAt:_.receivedAt,turnId:_.turnId}]};break;case"assistant":V={...V,assistantStreamingText:"",assistantTexts:[...V.assistantTexts,_.text]};break;case"assistant_delta":V={...V,assistantStreamingText:`${V.assistantStreamingText}${_.delta}`};break;case"complete":V={...V,sessionId:_.sessionId,status:"completed"};break;case"call_lifecycle":V={...V,call:{...V.call,disposition:_.event.type==="end"?_.event.disposition:V.call?.disposition,endedAt:_.event.type==="end"?_.event.at:V.call?.endedAt,events:[...V.call?.events??[],_.event],lastEventAt:_.event.at,startedAt:V.call?.startedAt??_.event.at},sessionId:_.sessionId};break;case"connected":V={...V,isConnected:!0,reconnect:V.reconnect.status==="reconnecting"?{...V.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:V.reconnect};break;case"connection":V={...V,reconnect:_.reconnect};break;case"disconnected":V={...V,isConnected:!1};break;case"error":V={...V,error:_.message,..._.recoverable===!1?{isConnected:!1,status:"failed"}:{}};break;case"final":g=m0(g,_.transcript.text),V={...V,partial:g};break;case"partial":V={...V,partial:u0(g,_.transcript.text)};break;case"replay":g=_.partial,V={...V,assistantStreamingText:"",assistantTexts:[..._.assistantTexts],call:_.call??null,error:null,isConnected:_.status==="active",partial:_.partial,reconnect:V.reconnect.status==="reconnecting"?{...V.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:V.reconnect,scenarioId:_.scenarioId??V.scenarioId,sessionId:_.sessionId,sessionMetadata:_.sessionMetadata??V.sessionMetadata,status:_.status,turns:[..._.turns]};break;case"session":V={...V,error:null,scenarioId:_.scenarioId??V.scenarioId,isConnected:_.status==="active",sessionId:_.sessionId,sessionMetadata:_.sessionMetadata??V.sessionMetadata,status:_.status};break;case"turn":g="",V={...V,partial:"",turns:[...V.turns,_.turn]};break}A()},getServerSnapshot:()=>V,getSnapshot:()=>V,subscribe:(_)=>{return C.add(_),()=>{C.delete(_)}}}};var t=(V,g={})=>{let C=a(V,g),A=p(),R=g.browserMedia&&typeof window<"u"?r({...g.browserMedia,getScenarioId:()=>g.browserMedia?g.browserMedia.getScenarioId?.()??C.getScenarioId():C.getScenarioId(),getSessionId:()=>g.browserMedia?g.browserMedia.getSessionId?.()??C.getSessionId():C.getSessionId()}):null,_=new Set,D=!1,X=(W)=>Promise.resolve().then(()=>{if(D)return;if(!W?.sessionId&&!W?.scenarioId)return;C.start(W),R?.start()}),H=()=>{_.forEach((W)=>W())},O=()=>{if(!g.reconnectReportPath||typeof fetch>"u")return;let W=A.getSnapshot(),U=JSON.stringify({at:Date.now(),reconnect:W.reconnect,scenarioId:W.scenarioId,sessionId:C.getSessionId(),turnIds:W.turns.map((T)=>T.id)});fetch(g.reconnectReportPath,{body:U,headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"}).catch(()=>{})},L=C.subscribe((W)=>{let U=i(W);if(U){if(A.dispatch(U),W.type==="connection")O();H()}});return{start:X,get assistantAudio(){return A.getSnapshot().assistantAudio},get assistantTexts(){return A.getSnapshot().assistantTexts},get assistantStreamingText(){return A.getSnapshot().assistantStreamingText},get call(){return A.getSnapshot().call},callControl(W){return C.callControl(W)},close(W){D=!0,L(),R?.close(),C.close(W),A.dispatch({type:"disconnected"}),H()},disconnect(){D=!0,L(),R?.close(),C.disconnect(),A.dispatch({type:"disconnected"}),H()},endTurn(){C.endTurn()},get error(){return A.getSnapshot().error},getServerSnapshot(){return A.getServerSnapshot()},getSnapshot(){return A.getSnapshot()},get isConnected(){return A.getSnapshot().isConnected},get partial(){return A.getSnapshot().partial},get reconnect(){return A.getSnapshot().reconnect},get scenarioId(){return A.getSnapshot().scenarioId},sendAudio(W){C.sendAudio(W)},get sessionId(){return C.getSessionId()},get sessionMetadata(){return A.getSnapshot().sessionMetadata},simulateDisconnect(){C.simulateDisconnect()},get status(){return A.getSnapshot().status},subscribe(W){return _.add(W),()=>{_.delete(W)}},get turns(){return A.getSnapshot().turns}}};var e=(V)=>{if(!V||V.enabled===!1)return;return{enabled:!0,maxGain:V.maxGain??3,noiseGateAttenuation:V.noiseGateAttenuation??0.15,noiseGateThreshold:V.noiseGateThreshold??0.006,targetLevel:V.targetLevel??0.08}};var s0={balanced:{qualityProfile:"general",minSilenceMs:400,silenceMs:1400,speechThreshold:0.012,transcriptStabilityMs:1000},fast:{qualityProfile:"general",minSilenceMs:300,silenceMs:700,speechThreshold:0.015,transcriptStabilityMs:450},"long-form":{qualityProfile:"general",minSilenceMs:600,silenceMs:2200,speechThreshold:0.01,transcriptStabilityMs:1500}},a0={"accent-heavy":{silenceMs:1200,speechThreshold:0.01,transcriptStabilityMs:1200},general:{},"noisy-room":{silenceMs:2000,speechThreshold:0.02,transcriptStabilityMs:1600},"short-command":{silenceMs:500,speechThreshold:0.016,transcriptStabilityMs:420}};var V0=(V)=>{let g=V?.profile??"fast",C=V?.qualityProfile??"general",A=s0[g],R=a0[C],_=V?.silenceMs??R.silenceMs??A.silenceMs;return{profile:g,qualityProfile:C,minSilenceMs:Math.min(_,V?.minSilenceMs??R.minSilenceMs??A.minSilenceMs),silenceMs:_,speechThreshold:V?.speechThreshold??R.speechThreshold??A.speechThreshold,transcriptStabilityMs:V?.transcriptStabilityMs??R.transcriptStabilityMs??A.transcriptStabilityMs}};var p0={chat:{audioConditioning:{enabled:!0,maxGain:2.5,noiseGateAttenuation:0,noiseGateThreshold:0.004,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:10,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"balanced",qualityProfile:"short-command"}},default:{capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:10,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"fast",qualityProfile:"general"}},dictation:{audioConditioning:{enabled:!0,maxGain:2.25,noiseGateAttenuation:0.05,noiseGateThreshold:0.003,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:12,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"accent-heavy"}},"guided-intake":{audioConditioning:{enabled:!0,maxGain:2.5,noiseGateAttenuation:0,noiseGateThreshold:0.004,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:12,pingInterval:30000,reconnect:!0},sttLifecycle:"turn-scoped",turnDetection:{profile:"long-form",qualityProfile:"accent-heavy"}},"noisy-room":{audioConditioning:{enabled:!0,maxGain:3,noiseGateAttenuation:0.12,noiseGateThreshold:0.006,targetLevel:0.085},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room",silenceMs:2100,speechThreshold:0.02,transcriptStabilityMs:1650}},"pstn-balanced":{audioConditioning:{enabled:!0,maxGain:2.8,noiseGateAttenuation:0.07,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room",silenceMs:660,speechThreshold:0.012,transcriptStabilityMs:300}},"pstn-fast":{audioConditioning:{enabled:!0,maxGain:2.75,noiseGateAttenuation:0.06,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room",silenceMs:620,speechThreshold:0.012,transcriptStabilityMs:280}},reliability:{audioConditioning:{enabled:!0,maxGain:2.9,noiseGateAttenuation:0.08,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room"}}},g0=(V="default")=>{let g=p0[V];return{audioConditioning:e(g.audioConditioning),capture:{channelCount:g.capture?.channelCount??1,sampleRateHz:g.capture?.sampleRateHz??16000},connection:{...g.connection},name:V,sttLifecycle:g.sttLifecycle??"continuous",turnDetection:V0(g.turnDetection)}};var t0=(V)=>({assistantAudio:[...V.assistantAudio],assistantStreamingText:V.assistantStreamingText,assistantTexts:[...V.assistantTexts],call:V.call,error:V.error,isConnected:V.isConnected,isRecording:!1,partial:V.partial,reconnect:V.reconnect,recordingError:null,sessionId:V.sessionId,sessionMetadata:V.sessionMetadata,scenarioId:V.scenarioId,status:V.status,turns:[...V.turns]}),A0=(V,g={})=>{let C=g0(g.preset),A=t(V,{...C.connection,...g.connection}),R=null,_=0,D=!1,X=null,H=t0(A),O=new Set,L=()=>{for(let G of O)G()},W=()=>{if(H={...H,assistantAudio:[...A.assistantAudio],assistantStreamingText:A.assistantStreamingText,assistantTexts:[...A.assistantTexts],call:A.call,error:A.error,isConnected:A.isConnected,partial:A.partial,reconnect:A.reconnect,sessionId:A.sessionId,sessionMetadata:A.sessionMetadata,scenarioId:A.scenarioId,status:A.status,turns:[...A.turns]},g.autoStopOnComplete!==!1&&H.status==="completed"&&H.isRecording)R?.stop(),R=null,H={...H,isRecording:!1};L()},U=A.subscribe(W);W();let T=()=>{if(R)return R;return R=v({channelCount:g.capture?.channelCount??C.capture.channelCount,onLevel:g.capture?.onLevel,onAudio:(G)=>{if(g.capture?.onAudio){g.capture.onAudio(G,A.sendAudio);return}A.sendAudio(G)},sampleRateHz:g.capture?.sampleRateHz??C.capture.sampleRateHz,...g.capture?.stream?{stream:g.capture.stream}:{}}),R},J=()=>{_+=1,R?.stop(),R=null,H={...H,isRecording:!1},L()},h=async()=>{if(D)throw Error("Voice controller is closed.");if(H.isRecording)return;if(X)return X;let G=++_,c=T(),$=(async()=>{try{if(H={...H,recordingError:null},L(),await c.start(),D||G!==_||R!==c){c.stop();return}H={...H,isRecording:!0},L()}catch(S){if(c.stop(),G!==_||R!==c)throw S;throw R=null,H={...H,isRecording:!1,recordingError:S instanceof Error?S.message:String(S)},L(),S}})().finally(()=>{if(X===$)X=null});return X=$,X};return{close:(G)=>{D=!0,U(),J(),A.close(G)},disconnect:()=>{D=!0,U(),J(),A.disconnect()},startRecording:h,stopRecording:J,get assistantAudio(){return H.assistantAudio},get assistantTexts(){return H.assistantTexts},get assistantStreamingText(){return H.assistantStreamingText},bindHTMX(G){return d(A,G)},get call(){return H.call},callControl:(G)=>A.callControl(G),endTurn:()=>A.endTurn(),get error(){return H.error},getServerSnapshot:()=>H,getSnapshot:()=>H,get isConnected(){return H.isConnected},get isRecording(){return H.isRecording},get partial(){return H.partial},get reconnect(){return H.reconnect},get recordingError(){return H.recordingError},get scenarioId(){return H.scenarioId},sendAudio:(G)=>A.sendAudio(G),get sessionId(){return H.sessionId},get sessionMetadata(){return H.sessionMetadata},simulateDisconnect:()=>A.simulateDisconnect(),get status(){return H.status},subscribe:(G)=>{return O.add(G),()=>{O.delete(G)}},toggleRecording:async()=>{if(H.isRecording){J();return}await h()},get turns(){return H.turns}}};var z=(V)=>String(V).replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&#39;");var C0=(V)=>{if(!V.isConnected)return"idle";if(V.isPlaying)return"speaking";if(V.isRecording&&V.hasActivePartial)return"listening";if(V.isRecording)return"listening";if(V.lastTranscriptAt&&!V.lastAssistantAt)return"thinking";if(V.lastTranscriptAt&&V.lastAssistantAt&&V.lastTranscriptAt>V.lastAssistantAt)return"thinking";return"idle"};var e0={accent:"#3b82f6",background:"#0f172a",errorAccent:"#ef4444",fontFamily:'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',foreground:"#f8fafc",radius:16},VV={callEnded:"Call ended",connecting:"Connecting…",endCall:"End call",idle:"Idle",listening:"Listening",mute:"Mute",speaking:"Speaking",startCall:"Start call",thinking:"Thinking",unmute:"Unmute"},gV=(V,g)=>{switch(V){case"listening":return g.listening;case"speaking":return g.speaking;case"thinking":return g.thinking;case"idle":return g.idle}},_0=(V)=>{let g={...e0,...V.theme},C={...VV,...V.labels},A=V.state.assistantAudio.at(-1)?.receivedAt,R=V.state.turns.at(-1)?.committedAt,_=C0({hasActivePartial:V.state.partial.length>0,isConnected:V.state.isConnected,isPlaying:!1,isRecording:V.state.isRecording,lastAssistantAt:A,lastTranscriptAt:R}),D=!V.state.isConnected&&V.state.status!=="idle"&&!V.state.error,X=V.state.error?"Error":D?C.connecting:V.state.status==="completed"?C.callEnded:gV(_,C);return{agentState:_,classes:{container:`absolute-voice-widget absolute-voice-widget--${_}`,dot:`absolute-voice-widget__dot${V.state.error?" absolute-voice-widget__dot--error":""}`},controls:{canEnd:V.state.isConnected,canMute:V.state.isRecording,canStart:!V.state.isRecording&&V.state.status!=="completed"},errorMessage:V.state.error??void 0,labels:C,partial:V.state.partial||void 0,statusLabel:X,theme:g,title:V.title??"Voice"}},AV=(V)=>typeof V==="number"?`${V}px`:V,T0=(V)=>{let g=V.theme,C=`background:${g.background};border-radius:${AV(g.radius)};color:${g.foreground};font-family:${g.fontFamily};min-width:240px;padding:20px 22px;`,A=`background:${V.errorMessage?g.errorAccent:V.agentState==="idle"?"rgba(148,163,184,0.6)":g.accent};border-radius:50%;height:10px;width:10px;`,R=[];if(V.controls.canStart)R.push(`<button type="button" data-action="start" style="background:${g.accent};border:none;border-radius:12px;color:${g.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${z(V.labels.startCall)}</button>`);if(V.controls.canMute)R.push(`<button type="button" data-action="mute" style="background:transparent;border:1px solid rgba(255,255,255,0.18);border-radius:12px;color:${g.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${z(V.labels.mute)}</button>`);if(V.controls.canEnd)R.push(`<button type="button" data-action="end" style="background:${g.errorAccent};border:none;border-radius:12px;color:${g.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${z(V.labels.endCall)}</button>`);return`<div role="region" aria-live="polite" data-agent-state="${V.agentState}" class="${z(V.classes.container)}" style="${C}">
1
+ (()=>{var{defineProperty:k,getOwnPropertyNames:S0,getOwnPropertyDescriptor:w0}=Object,J0=Object.prototype.hasOwnProperty;function h0(V){return this[V]}var Y0=(V)=>{var A=(l??=new WeakMap).get(V),C;if(A)return A;if(A=k({},"__esModule",{value:!0}),V&&typeof V==="object"||typeof V==="function"){for(var g of S0(V))if(!J0.call(A,g))k(A,g,{get:h0.bind(V,g),enumerable:!(C=w0(V,g))||C.enumerable})}return l.set(V,A),A},l;var Z0=(V)=>V;function y0(V,A){this[V]=Z0.bind(null,A)}var Q0=(V,A)=>{for(var C in A)k(V,C,{get:A[C],enumerable:!0,configurable:!0,set:y0.bind(A,C)})};var _V={};Q0(_V,{mount:()=>$0,default:()=>TV,VOICE_EMBED_VERSION:()=>R0});var E0=(V)=>{if(typeof V!=="string")return V;return document.querySelector(V)},K0=(V,A,C,g)=>{let H=A??V.getAttribute("hx-get")??"";if(!H)return"";let _=new URL(H,window.location.origin);if(g)_.searchParams.set(C,g);else _.searchParams.delete(C);return`${_.pathname}${_.search}${_.hash}`},d=(V,A)=>{if(typeof window>"u"||typeof document>"u")return()=>{};let C=E0(A.element);if(!C)return()=>{};let g=A.eventName??"voice-refresh",H=A.sessionQueryParam??"sessionId",_=()=>{let X=window,R=K0(C,A.route,H,V.sessionId);if(R)C.setAttribute("hx-get",R);X.htmx?.process?.(C),X.htmx?.trigger?.(C,g)},D=V.subscribe(_);return _(),()=>{D()}};var c0=(V)=>Math.max(-1,Math.min(1,V)),q0=(V)=>{let A=new Int16Array(V.length);for(let C=0;C<V.length;C+=1){let g=c0(V[C]??0);A[C]=g<0?g*32768:g*32767}return new Uint8Array(A.buffer)},N0=(V)=>{let A=V instanceof Uint8Array?V:new Uint8Array(V);if(A.byteLength<2)return 0;let C=new Int16Array(A.buffer,A.byteOffset,Math.floor(A.byteLength/2));if(C.length===0)return 0;let g=0;for(let H of C){let _=H/32768;g+=_*_}return Math.min(1,Math.max(0,Math.sqrt(g/C.length)*5.5))},z0=(V,A,C)=>{if(A===C)return V;let g=A/C,H=Math.round(V.length/g),_=new Float32Array(H),D=0,X=0;while(D<_.length){let R=Math.round((D+1)*g),O=0,L=0;for(let W=X;W<R&&W<V.length;W+=1)O+=V[W]??0,L+=1;_[D]=L>0?O/L:0,D+=1,X=R}return _},v=(V)=>{let A=null,C=null,g=null,H=null,_=0,D=null,X=(L)=>{L.processorNode?.disconnect(),L.sourceNode?.disconnect(),L.mediaStream?.getTracks().forEach((W)=>W.stop()),L.audioContext?.close()};return{start:()=>{if(H)return Promise.resolve();if(D)return D;let L=++_,U=(async()=>{if(!V.stream&&(typeof navigator>"u"||!navigator.mediaDevices?.getUserMedia))throw Error("Browser microphone capture requires navigator.mediaDevices.getUserMedia.");let T=(typeof window<"u"?window.AudioContext??window.webkitAudioContext:void 0)??AudioContext;if(!T)throw Error("Browser microphone capture requires AudioContext support.");let w=null,Z=null,Y=null,Q=null;try{if(Z=V.stream??await navigator.mediaDevices.getUserMedia({audio:{autoGainControl:!0,channelCount:V.channelCount??1,echoCancellation:!0,noiseSuppression:!0}}),L!==_)throw Error("Microphone capture stopped during startup.");if(w=new T,w.state==="suspended")await w.resume();if(L!==_)throw Error("Microphone capture stopped during startup.");if(Q=w.createMediaStreamSource(Z),Y=w.createScriptProcessor(4096,1,1),Y.onaudioprocess=(G)=>{let K=G.inputBuffer.getChannelData(0),q=z0(K,w?.sampleRate??48000,V.sampleRateHz??16000),$=q0(q);V.onLevel?.(N0($)),V.onAudio($)},Q.connect(Y),Y.connect(w.destination),L!==_)throw Error("Microphone capture stopped during startup.");A=w,H=Z,g=Y,C=Q}catch(G){throw X({audioContext:w,mediaStream:Z,processorNode:Y,sourceNode:Q}),G}})().finally(()=>{if(D===U)D=null});return D=U,U},stop:()=>{_+=1,X({audioContext:A,mediaStream:H,processorNode:g,sourceNode:C}),V.onLevel?.(0),A=null,H=null,g=null,C=null}}};var F=(V)=>{if(typeof V==="string"&&V.trim())return V;if(V instanceof Error&&V.message.trim())return V.message;if(V&&typeof V==="object"){let A=V;for(let C of["message","reason","description"]){let g=A[C];if(typeof g==="string"&&g.trim())return g}if("error"in A)return F(A.error);if("cause"in A)return F(A.cause);try{return JSON.stringify(V)}catch{}}return"Unexpected error"},i=(V)=>{switch(V.type){case"audio":return{chunk:Uint8Array.from(atob(V.chunkBase64),(A)=>A.charCodeAt(0)),format:V.format,receivedAt:V.receivedAt,turnId:V.turnId,type:"audio"};case"assistant":return{text:V.text,turnId:V.turnId,type:"assistant"};case"assistant_delta":return{delta:V.delta,turnId:V.turnId,type:"assistant_delta"};case"complete":return{sessionId:V.sessionId,type:"complete"};case"connection":return{reconnect:V.reconnect,type:"connection"};case"call_lifecycle":return{event:V.event,sessionId:V.sessionId,type:"call_lifecycle"};case"error":return{message:F(V.message),recoverable:V.recoverable,type:"error"};case"call_control_ack":return null;case"final":return{transcript:V.transcript,type:"final"};case"partial":return{transcript:V.transcript,type:"partial"};case"replay":return{assistantTexts:V.assistantTexts,call:V.call,partial:V.partial,scenarioId:V.scenarioId,sessionId:V.sessionId,sessionMetadata:V.sessionMetadata,status:V.status,turns:V.turns,type:"replay"};case"session":return{paused:V.paused,pauseExpiresAt:V.pauseExpiresAt,sessionId:V.sessionId,sessionMetadata:V.sessionMetadata,scenarioId:V.scenarioId,status:V.status,type:"session"};case"turn":return{turn:V.turn,type:"turn"};default:return null}};var UV=Math.PI*2;var N=(V,A,C,g)=>{V.push({code:C,message:g,severity:A})};var P0=(V)=>V.length===0?void 0:V.reduce((A,C)=>A+C,0)/V.length,x=(V)=>V.length===0?void 0:Math.max(...V);var E=(V,A)=>{let C=V[A];return typeof C==="number"&&Number.isFinite(C)?C:void 0},j=(V,A)=>{let C=V[A];return typeof C==="boolean"?C:void 0},c=(V,A)=>{let C=V[A];return typeof C==="string"?C:void 0},f=(V)=>String(V.id??c(V,"ssrc")??E(V,"ssrc")??c(V,"trackIdentifier")??c(V,"mid")??"unknown"),o=(V)=>V===void 0?void 0:V*1000;var B0=(V)=>{let A={};for(let[C,g]of Object.entries(V))if(g===null||typeof g==="boolean"||typeof g==="number"||typeof g==="string")A[C]=g;return A};var n=(V={})=>{let A=V.stats??[],C=[],g=A.filter(($)=>$.type==="inbound-rtp"&&c($,"kind")!=="video"),H=A.filter(($)=>$.type==="outbound-rtp"&&c($,"kind")!=="video"),_=A.filter(($)=>$.type==="candidate-pair"),D=A.filter(($)=>($.type==="track"||$.type==="media-source")&&c($,"kind")==="audio"),X=_.filter(($)=>j($,"selected")===!0||j($,"nominated")===!0||c($,"state")==="succeeded").length,R=D.filter(($)=>c($,"readyState")!=="ended"&&c($,"trackState")!=="ended"&&j($,"ended")!==!0).length,O=D.filter(($)=>c($,"readyState")==="ended"||c($,"trackState")==="ended"||j($,"ended")===!0).length,L=g.reduce(($,J)=>$+(E(J,"packetsReceived")??0),0),W=H.reduce(($,J)=>$+(E(J,"packetsSent")??0),0),U=[...g,...H].reduce(($,J)=>$+Math.max(0,E(J,"packetsLost")??0),0),T=L+U,w=T===0?0:U/T,Z=g.reduce(($,J)=>$+(E(J,"bytesReceived")??0),0),Y=H.reduce(($,J)=>$+(E(J,"bytesSent")??0),0),Q=x(_.map(($)=>o(E($,"currentRoundTripTime")??E($,"roundTripTime"))).filter(($)=>$!==void 0)),G=x([...g,...H].map(($)=>o(E($,"jitter"))).filter(($)=>$!==void 0)),K=x(g.map(($)=>{let J=E($,"jitterBufferDelay"),b=E($,"jitterBufferEmittedCount");return J!==void 0&&b!==void 0&&b>0?J/b*1000:void 0}).filter(($)=>$!==void 0)),q=D.map(($)=>E($,"audioLevel")).filter(($)=>$!==void 0);if(V.requireConnectedCandidatePair&&_.length>0&&X===0)N(C,"error","media.webrtc_candidate_pair_missing","No active WebRTC candidate pair was observed.");if(V.requireLiveAudioTrack&&R===0)N(C,"error","media.webrtc_audio_track_missing","No live WebRTC audio track was observed.");if(V.maxPacketLossRatio!==void 0&&w>V.maxPacketLossRatio)N(C,"warning","media.webrtc_packet_loss",`Observed WebRTC packet loss ratio ${String(w)} above ${String(V.maxPacketLossRatio)}.`);if(V.maxRoundTripTimeMs!==void 0&&Q!==void 0&&Q>V.maxRoundTripTimeMs)N(C,"warning","media.webrtc_round_trip_time",`Observed WebRTC RTT ${String(Q)}ms above ${String(V.maxRoundTripTimeMs)}ms.`);if(V.maxJitterMs!==void 0&&G!==void 0&&G>V.maxJitterMs)N(C,"warning","media.webrtc_jitter",`Observed WebRTC jitter ${String(G)}ms above ${String(V.maxJitterMs)}ms.`);return{activeCandidatePairs:X,audioLevelAverage:P0(q),bytesReceived:Z,bytesSent:Y,checkedAt:Date.now(),endedAudioTracks:O,inboundPackets:L,issues:C,jitterBufferDelayMs:K,jitterMs:G,liveAudioTracks:R,outboundPackets:W,packetLossRatio:w,packetsLost:U,roundTripTimeMs:Q,status:C.some(($)=>$.severity==="error")?"fail":C.length>0?"warn":"pass",totalStats:A.length}},m=async(V)=>{return[...(await V.peerConnection.getStats(V.selector??null)).values()].map(B0)};var u=(V={})=>{let A=V.stats??[],C=V.previousStats??[],g=[],H=new Map(C.map((U)=>[f(U),U])),D=A.filter((U)=>(U.type==="inbound-rtp"||U.type==="outbound-rtp")&&c(U,"kind")!=="video"&&c(U,"mediaType")!=="video").map((U)=>{let T=U.type==="outbound-rtp"?"outbound":"inbound",w=T==="outbound"?"packetsSent":"packetsReceived",Z=T==="outbound"?"bytesSent":"bytesReceived",Y=H.get(f(U)),Q=E(U,w),G=Y?E(Y,w):void 0,K=E(U,Z),q=Y?E(Y,Z):void 0,$=U.timestamp!==void 0&&Y?.timestamp!==void 0?U.timestamp-Y.timestamp:void 0;return{bytesDelta:K!==void 0&&q!==void 0?K-q:void 0,currentPackets:Q,direction:T,id:f(U),packetDelta:Q!==void 0&&G!==void 0?Q-G:void 0,previousPackets:G,timeDeltaMs:$}}),X=D.filter((U)=>U.direction==="inbound"),R=D.filter((U)=>U.direction==="outbound"),O=x(D.map((U)=>U.timeDeltaMs).filter((U)=>U!==void 0)),L=X.filter((U)=>V.maxInboundPacketStallMs!==void 0&&U.timeDeltaMs!==void 0&&U.timeDeltaMs>=V.maxInboundPacketStallMs&&U.packetDelta!==void 0&&U.packetDelta<=0).length,W=R.filter((U)=>V.maxOutboundPacketStallMs!==void 0&&U.timeDeltaMs!==void 0&&U.timeDeltaMs>=V.maxOutboundPacketStallMs&&U.packetDelta!==void 0&&U.packetDelta<=0).length;if(V.requireInboundAudio&&X.length===0)N(g,"error","media.webrtc_inbound_audio_missing","No inbound WebRTC audio RTP stream was observed.");if(V.requireOutboundAudio&&R.length===0)N(g,"error","media.webrtc_outbound_audio_missing","No outbound WebRTC audio RTP stream was observed.");if(V.maxGapMs!==void 0&&O!==void 0&&O>V.maxGapMs)N(g,"warning","media.webrtc_stream_gap",`Observed WebRTC stream sample gap ${String(O)}ms above ${String(V.maxGapMs)}ms.`);if(L>0)N(g,"error","media.webrtc_inbound_stalled",`${String(L)} inbound WebRTC audio stream(s) stopped receiving packets.`);if(W>0)N(g,"error","media.webrtc_outbound_stalled",`${String(W)} outbound WebRTC audio stream(s) stopped sending packets.`);return{checkedAt:Date.now(),inboundAudioStreams:X.length,issues:g,maxObservedGapMs:O,outboundAudioStreams:R.length,stalledInboundStreams:L,stalledOutboundStreams:W,status:g.some((U)=>U.severity==="error")?"fail":g.length>0?"warn":"pass",streams:D,totalStats:A.length}};var M0="/api/voice/browser-media",b0=5000,j0=async(V)=>V.peerConnection??await V.getPeerConnection?.()??null,x0=async(V,A)=>{let C=A.fetch??globalThis.fetch;if(!C)return;await C(A.path??M0,{body:JSON.stringify(V),headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"})},r=(V)=>{let A=null,C=[],g=async()=>{let D=await j0(V);if(!D)return;let X=await m({peerConnection:D}),R=n({...V,stats:X}),O=V.continuity===!1?void 0:u({...V.continuity,previousStats:C,stats:X}),L={at:Date.now(),continuity:O,report:R,scenarioId:V.getScenarioId?.()??null,sessionId:V.getSessionId?.()??null};return C=X,V.onReport?.(L),await x0(L,V),L},H=()=>{g().catch((D)=>{V.onError?.(D)})},_=()=>{if(A)clearInterval(A),A=null};return{close:_,reportOnce:g,stop:_,start:()=>{if(A)return;H(),A=setInterval(H,V.intervalMs??b0)}}};var k0=(V,A,C)=>Math.min(C,A*2**(Math.max(1,V)-1));class s extends Error{constructor(V="Voice authorization could not be renewed."){super(V);this.name="VoiceReconnectRejectedError"}}var P=()=>{},F0=()=>Promise.resolve(),f0=()=>P,l0={callControl:F0,close:P,disconnect:P,endTurn:P,send:P,sendAudio:P,simulateDisconnect:P,subscribe:f0,getReadyState:()=>3,getScenarioId:()=>"",getSessionId:()=>"",start:()=>{}},d0=()=>crypto.randomUUID(),v0=(V,A,C,g)=>{let{hostname:H,port:_,protocol:D}=window.location,X=D==="https:"?"wss:":"ws:",R=_?`:${_}`:"",O=new URL(`${X}//${H}${R}${V}`);if(O.searchParams.set("sessionId",A),C)O.searchParams.set("scenarioId",C);for(let[L,W]of Object.entries(g))if(L!=="sessionId"&&L!=="scenarioId"&&W)O.searchParams.set(L,W);return O.toString()},i0=(V)=>{if(!V||typeof V!=="object"||!("type"in V))return!1;switch(V.type){case"audio":case"assistant":case"call_lifecycle":case"call_control_ack":case"complete":case"connection":case"error":case"final":case"partial":case"pong":case"replay":case"session":case"turn":return!0;default:return!1}},o0=(V)=>{if(typeof V.data!=="string")return null;try{let A=JSON.parse(V.data);return i0(A)?A:null}catch{return null}},a=(V,A={})=>{if(typeof window>"u")return l0;let C=new Set,g=new Map,H=A.reconnect!==!1,_=A.maxReconnectAttempts??15,D=A.reconnectMaxDelayMs??8000,X=A.pingInterval??30000,R=A.reconnectResetAfterMs??30000,O=0,L=!1,W=null,U=(I)=>k0(I,500,D),T={isConnected:!1,pendingMessages:[],scenarioId:A.scenarioId??null,pingInterval:null,reconnectAttempts:0,reconnectResetTimeout:null,reconnectTimeout:null,sessionId:A.sessionId??d0(),ws:null},w=(I)=>{C.forEach((S)=>S(I))},Z=(I)=>{C.forEach((S)=>S({message:I,recoverable:!1,type:"error"})),w({reconnect:{attempts:T.reconnectAttempts,maxAttempts:_,status:"exhausted"},type:"connection"})},Y=()=>{if(T.pingInterval)clearInterval(T.pingInterval),T.pingInterval=null;if(T.reconnectTimeout)clearTimeout(T.reconnectTimeout),T.reconnectTimeout=null;if(T.reconnectResetTimeout)clearTimeout(T.reconnectResetTimeout),T.reconnectResetTimeout=null},Q=()=>{if(T.ws?.readyState!==1)return;while(T.pendingMessages.length>0){let I=T.pendingMessages.shift();if(I!==void 0)T.ws.send(I)}},G=(I)=>{for(let S of g.values())clearTimeout(S.timeout),S.reject(Error(I));g.clear()},K=()=>{if(L)return;let I=O;T.reconnectAttempts+=1;let S=U(T.reconnectAttempts),y=Date.now()+S;w({reconnect:{attempts:T.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:_,nextAttemptAt:y,status:"reconnecting"},type:"connection"}),T.reconnectTimeout=setTimeout(async()=>{if(L||O!==I)return;if(T.reconnectAttempts>_){Z("Voice connection could not be restored.");return}try{if(A.prepareReconnect){let h=new AbortController;W=h;let B=setTimeout(()=>h.abort("Voice reconnect preparation timed out"),A.prepareReconnectTimeoutMs??1e4);try{await Promise.race([A.prepareReconnect({attempt:T.reconnectAttempts,path:V,scenarioId:T.scenarioId,sessionId:T.sessionId,signal:h.signal}),new Promise((M,O0)=>{h.signal.addEventListener("abort",()=>O0(Error("Voice reconnect preparation timed out.")),{once:!0})})])}finally{if(clearTimeout(B),W===h)W=null}}}catch(h){if(L||O!==I)return;if(h instanceof s){Z(h.message);return}if(T.reconnectAttempts<_)K();else Z("Voice authorization could not be renewed for reconnect.");return}if(L||O!==I)return;q()},S)},q=()=>{if(L)return;let I=new WebSocket(v0(V,T.sessionId,T.scenarioId,A.query??{}));I.binaryType="arraybuffer",I.onopen=()=>{if(T.ws!==I){I.close(1000);return}let S=T.reconnectAttempts>0;if(T.isConnected=!0,Q(),S)w({reconnect:{attempts:T.reconnectAttempts,lastResumedAt:Date.now(),maxAttempts:_,status:"resumed"},type:"connection"}),T.reconnectResetTimeout=setTimeout(()=>{if(T.ws===I&&I.readyState===1)T.reconnectAttempts=0;T.reconnectResetTimeout=null},R);T.pingInterval=setInterval(()=>{if(I.readyState===1)I.send(JSON.stringify({type:"ping"}))},X)},I.onmessage=(S)=>{if(T.ws!==I)return;let y=o0(S);if(!y)return;if(y.type==="session")T.sessionId=y.sessionId,T.scenarioId=y.scenarioId??T.scenarioId;if(y.type==="call_control_ack"){let h=g.get(y.requestId);if(h)if(clearTimeout(h.timeout),g.delete(y.requestId),y.ok)h.resolve();else h.reject(Error(y.message??`${y.action} was not applied`))}C.forEach((h)=>h(y))},I.onclose=(S)=>{if(T.ws!==I)return;T.ws=null,T.isConnected=!1,Y(),G("Voice connection interrupted");let y=H&&S.code!==1000&&S.code!==4401&&S.code!==4403&&S.code!==4500&&T.reconnectAttempts<_,h=S.code===4401||S.code===4403,B=S.code===4500;if(h)C.forEach((M)=>M({message:S.code===4401?"Voice authorization expired or was rejected.":"Voice authorization was forbidden.",recoverable:!1,type:"error"}));if(B)C.forEach((M)=>M({message:"Voice provider initialization failed.",recoverable:!1,type:"error"}));if(y)K();else if(H&&S.code!==1000){if(h)w({reconnect:{attempts:T.reconnectAttempts,lastDisconnectAt:Date.now(),maxAttempts:_,status:"exhausted"},type:"connection"});else if(!B)Z("Voice connection could not be restored.")}},T.ws=I},$=(I)=>{if(L)return;if(T.ws?.readyState===1){T.ws.send(I);return}if(typeof I!=="string")return;if(T.pendingMessages.length>=100)T.pendingMessages.shift();T.pendingMessages.push(I)},J=(I)=>{$(JSON.stringify(I))},b=(I={})=>{if(I.sessionId&&I.sessionId!==T.sessionId)throw Error("Voice session switching requires a new connection instance.");if(I.sessionId)T.sessionId=I.sessionId;if(I.scenarioId)T.scenarioId=I.scenarioId;J({scenarioId:T.scenarioId??void 0,sessionId:T.sessionId,type:"start"})},I0=(I)=>{$(I)},U0=()=>{J({type:"end_turn"})},L0=(I)=>{if(T.ws?.readyState!==1)return Promise.reject(Error(`${I.action} is unavailable while disconnected`));let S=crypto.randomUUID(),{promise:y,reject:h,resolve:B}=Promise.withResolvers(),M=setTimeout(()=>{g.delete(S),h(Error(`${I.action} acknowledgement timed out`))},5000);return g.set(S,{reject:h,resolve:B,timeout:M}),T.ws.send(JSON.stringify({...I,requestId:S,type:"call_control"})),y},W0=(I="client-close")=>{if(L=!0,W?.abort(),W=null,O+=1,Y(),G("Voice connection closed"),T.pendingMessages.length=0,T.ws){let S=T.ws;if(T.ws=null,S.readyState===1)S.send(JSON.stringify({reason:I,type:"close"}));S.close(1000)}T.isConnected=!1,C.clear()},D0=()=>{if(L=!0,W?.abort(),W=null,O+=1,Y(),G("Voice connection disconnected"),T.pendingMessages.length=0,T.ws){let I=T.ws;T.ws=null,I.close(1000)}T.isConnected=!1,C.clear()},X0=()=>{if(T.ws?.readyState===1)T.ws.close(4000,"absolutejs-voice-reconnect-proof")},G0=(I)=>{return C.add(I),()=>{C.delete(I)}};return q(),{callControl:L0,close:W0,disconnect:D0,endTurn:U0,send:J,sendAudio:I0,simulateDisconnect:X0,start:b,subscribe:G0,getReadyState:()=>T.ws?.readyState??3,getScenarioId:()=>T.scenarioId??"",getSessionId:()=>T.sessionId}};var n0=()=>({attempts:0,maxAttempts:0,status:"idle"}),m0=(V,A)=>{let C=A.trim().replace(/\s+/g," ");if(!C)return V;if(!V)return C;if(V===C||V.endsWith(C))return V;if(C.includes(V))return C;return`${V} ${C}`},u0=(V,A)=>{let C=A.trim().replace(/\s+/g," ");if(!V)return C;if(!C||V.endsWith(C))return V;return`${V} ${C}`},r0=()=>({assistantAudio:[],assistantStreamingText:"",assistantTexts:[],call:null,error:null,isConnected:!1,paused:!1,partial:"",reconnect:n0(),scenarioId:null,sessionId:null,sessionMetadata:null,status:"idle",turns:[]}),p=()=>{let V=r0(),A="",C=new Set,g=()=>{C.forEach((_)=>_())};return{dispatch:(_)=>{switch(_.type){case"audio":V={...V,assistantAudio:[...V.assistantAudio,{chunk:_.chunk,format:_.format,receivedAt:_.receivedAt,turnId:_.turnId}]};break;case"assistant":V={...V,assistantStreamingText:"",assistantTexts:[...V.assistantTexts,_.text]};break;case"assistant_delta":V={...V,assistantStreamingText:`${V.assistantStreamingText}${_.delta}`};break;case"complete":V={...V,sessionId:_.sessionId,status:"completed"};break;case"call_lifecycle":V={...V,call:{...V.call,disposition:_.event.type==="end"?_.event.disposition:V.call?.disposition,endedAt:_.event.type==="end"?_.event.at:V.call?.endedAt,events:[...V.call?.events??[],_.event],lastEventAt:_.event.at,startedAt:V.call?.startedAt??_.event.at},sessionId:_.sessionId};break;case"connected":V={...V,isConnected:!0,reconnect:V.reconnect.status==="reconnecting"?{...V.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:V.reconnect};break;case"connection":V={...V,reconnect:_.reconnect};break;case"disconnected":V={...V,isConnected:!1};break;case"error":V={...V,error:_.message,..._.recoverable===!1?{isConnected:!1,status:"failed"}:{}};break;case"final":A=m0(A,_.transcript.text),V={...V,partial:A};break;case"partial":V={...V,partial:u0(A,_.transcript.text)};break;case"replay":A=_.partial,V={...V,assistantStreamingText:"",assistantTexts:[..._.assistantTexts],call:_.call??null,error:null,isConnected:_.status==="active",partial:_.partial,reconnect:V.reconnect.status==="reconnecting"?{...V.reconnect,lastResumedAt:Date.now(),nextAttemptAt:void 0,status:"resumed"}:V.reconnect,scenarioId:_.scenarioId??V.scenarioId,sessionId:_.sessionId,sessionMetadata:_.sessionMetadata??V.sessionMetadata,status:_.status,turns:[..._.turns]};break;case"session":V={...V,error:null,paused:_.paused??!1,pauseExpiresAt:_.pauseExpiresAt,scenarioId:_.scenarioId??V.scenarioId,isConnected:_.status==="active",sessionId:_.sessionId,sessionMetadata:_.sessionMetadata??V.sessionMetadata,status:_.status};break;case"turn":A="",V={...V,partial:"",turns:[...V.turns,_.turn]};break}g()},getServerSnapshot:()=>V,getSnapshot:()=>V,subscribe:(_)=>{return C.add(_),()=>{C.delete(_)}}}};var t=(V,A={})=>{let C=a(V,A),g=p(),H=A.browserMedia&&typeof window<"u"?r({...A.browserMedia,getScenarioId:()=>A.browserMedia?A.browserMedia.getScenarioId?.()??C.getScenarioId():C.getScenarioId(),getSessionId:()=>A.browserMedia?A.browserMedia.getSessionId?.()??C.getSessionId():C.getSessionId()}):null,_=new Set,D=!1,X=(W)=>Promise.resolve().then(()=>{if(D)return;if(!W?.sessionId&&!W?.scenarioId)return;C.start(W),H?.start()}),R=()=>{_.forEach((W)=>W())},O=()=>{if(!A.reconnectReportPath||typeof fetch>"u")return;let W=g.getSnapshot(),U=JSON.stringify({at:Date.now(),reconnect:W.reconnect,scenarioId:W.scenarioId,sessionId:C.getSessionId(),turnIds:W.turns.map((T)=>T.id)});fetch(A.reconnectReportPath,{body:U,headers:{"Content-Type":"application/json"},keepalive:!0,method:"POST"}).catch(()=>{})},L=C.subscribe((W)=>{let U=i(W);if(U){if(g.dispatch(U),W.type==="connection")O();R()}});return{start:X,get assistantAudio(){return g.getSnapshot().assistantAudio},get assistantTexts(){return g.getSnapshot().assistantTexts},get assistantStreamingText(){return g.getSnapshot().assistantStreamingText},get call(){return g.getSnapshot().call},callControl(W){return C.callControl(W)},close(W){D=!0,L(),H?.close(),C.close(W),g.dispatch({type:"disconnected"}),R()},disconnect(){D=!0,L(),H?.close(),C.disconnect(),g.dispatch({type:"disconnected"}),R()},endTurn(){C.endTurn()},get error(){return g.getSnapshot().error},getServerSnapshot(){return g.getServerSnapshot()},getSnapshot(){return g.getSnapshot()},get isConnected(){return g.getSnapshot().isConnected},get partial(){return g.getSnapshot().partial},get paused(){return g.getSnapshot().paused},get pauseExpiresAt(){return g.getSnapshot().pauseExpiresAt},get reconnect(){return g.getSnapshot().reconnect},get scenarioId(){return g.getSnapshot().scenarioId},sendAudio(W){C.sendAudio(W)},get sessionId(){return C.getSessionId()},get sessionMetadata(){return g.getSnapshot().sessionMetadata},simulateDisconnect(){C.simulateDisconnect()},get status(){return g.getSnapshot().status},subscribe(W){return _.add(W),()=>{_.delete(W)}},get turns(){return g.getSnapshot().turns}}};var e=(V)=>{if(!V||V.enabled===!1)return;return{enabled:!0,maxGain:V.maxGain??3,noiseGateAttenuation:V.noiseGateAttenuation??0.15,noiseGateThreshold:V.noiseGateThreshold??0.006,targetLevel:V.targetLevel??0.08}};var s0={balanced:{qualityProfile:"general",minSilenceMs:400,silenceMs:1400,speechThreshold:0.012,transcriptStabilityMs:1000},fast:{qualityProfile:"general",minSilenceMs:300,silenceMs:700,speechThreshold:0.015,transcriptStabilityMs:450},"long-form":{qualityProfile:"general",minSilenceMs:600,silenceMs:2200,speechThreshold:0.01,transcriptStabilityMs:1500}},a0={"accent-heavy":{silenceMs:1200,speechThreshold:0.01,transcriptStabilityMs:1200},general:{},"noisy-room":{silenceMs:2000,speechThreshold:0.02,transcriptStabilityMs:1600},"short-command":{silenceMs:500,speechThreshold:0.016,transcriptStabilityMs:420}};var V0=(V)=>{let A=V?.profile??"fast",C=V?.qualityProfile??"general",g=s0[A],H=a0[C],_=V?.silenceMs??H.silenceMs??g.silenceMs;return{profile:A,qualityProfile:C,minSilenceMs:Math.min(_,V?.minSilenceMs??H.minSilenceMs??g.minSilenceMs),silenceMs:_,speechThreshold:V?.speechThreshold??H.speechThreshold??g.speechThreshold,transcriptStabilityMs:V?.transcriptStabilityMs??H.transcriptStabilityMs??g.transcriptStabilityMs}};var p0={chat:{audioConditioning:{enabled:!0,maxGain:2.5,noiseGateAttenuation:0,noiseGateThreshold:0.004,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:10,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"balanced",qualityProfile:"short-command"}},default:{capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:10,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"fast",qualityProfile:"general"}},dictation:{audioConditioning:{enabled:!0,maxGain:2.25,noiseGateAttenuation:0.05,noiseGateThreshold:0.003,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:12,pingInterval:30000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"accent-heavy"}},"guided-intake":{audioConditioning:{enabled:!0,maxGain:2.5,noiseGateAttenuation:0,noiseGateThreshold:0.004,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:12,pingInterval:30000,reconnect:!0},sttLifecycle:"turn-scoped",turnDetection:{profile:"long-form",qualityProfile:"accent-heavy"}},"noisy-room":{audioConditioning:{enabled:!0,maxGain:3,noiseGateAttenuation:0.12,noiseGateThreshold:0.006,targetLevel:0.085},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room",silenceMs:2100,speechThreshold:0.02,transcriptStabilityMs:1650}},"pstn-balanced":{audioConditioning:{enabled:!0,maxGain:2.8,noiseGateAttenuation:0.07,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room",silenceMs:660,speechThreshold:0.012,transcriptStabilityMs:300}},"pstn-fast":{audioConditioning:{enabled:!0,maxGain:2.75,noiseGateAttenuation:0.06,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room",silenceMs:620,speechThreshold:0.012,transcriptStabilityMs:280}},reliability:{audioConditioning:{enabled:!0,maxGain:2.9,noiseGateAttenuation:0.08,noiseGateThreshold:0.005,targetLevel:0.08},capture:{channelCount:1,sampleRateHz:16000},connection:{maxReconnectAttempts:14,pingInterval:45000,reconnect:!0},sttLifecycle:"continuous",turnDetection:{profile:"long-form",qualityProfile:"noisy-room"}}},A0=(V="default")=>{let A=p0[V];return{audioConditioning:e(A.audioConditioning),capture:{channelCount:A.capture?.channelCount??1,sampleRateHz:A.capture?.sampleRateHz??16000},connection:{...A.connection},name:V,sttLifecycle:A.sttLifecycle??"continuous",turnDetection:V0(A.turnDetection)}};var t0=(V)=>({assistantAudio:[...V.assistantAudio],assistantStreamingText:V.assistantStreamingText,assistantTexts:[...V.assistantTexts],call:V.call,error:V.error,isConnected:V.isConnected,isRecording:!1,paused:V.paused,pauseExpiresAt:V.pauseExpiresAt,partial:V.partial,reconnect:V.reconnect,recordingError:null,sessionId:V.sessionId,sessionMetadata:V.sessionMetadata,scenarioId:V.scenarioId,status:V.status,turns:[...V.turns]}),g0=(V,A={})=>{let C=A0(A.preset),g=t(V,{...C.connection,...A.connection}),H=null,_=0,D=!1,X=null,R=t0(g),O=new Set,L=()=>{for(let G of O)G()},W=()=>{if(R={...R,assistantAudio:[...g.assistantAudio],assistantStreamingText:g.assistantStreamingText,assistantTexts:[...g.assistantTexts],call:g.call,error:g.error,isConnected:g.isConnected,paused:g.paused,pauseExpiresAt:g.pauseExpiresAt,partial:g.partial,reconnect:g.reconnect,sessionId:g.sessionId,sessionMetadata:g.sessionMetadata,scenarioId:g.scenarioId,status:g.status,turns:[...g.turns]},A.autoStopOnComplete!==!1&&R.status==="completed"&&R.isRecording)H?.stop(),H=null,R={...R,isRecording:!1};L()},U=g.subscribe(W);W();let T=()=>{if(H)return H;return H=v({channelCount:A.capture?.channelCount??C.capture.channelCount,onLevel:A.capture?.onLevel,onAudio:(G)=>{if(A.capture?.onAudio){A.capture.onAudio(G,g.sendAudio);return}g.sendAudio(G)},sampleRateHz:A.capture?.sampleRateHz??C.capture.sampleRateHz,...A.capture?.stream?{stream:A.capture.stream}:{}}),H},w=()=>{_+=1,H?.stop(),H=null,R={...R,isRecording:!1},L()},Z=async()=>{if(D)throw Error("Voice controller is closed.");if(R.isRecording)return;if(X)return X;let G=++_,K=T(),$=(async()=>{try{if(R={...R,recordingError:null},L(),await K.start(),D||G!==_||H!==K){K.stop();return}R={...R,isRecording:!0},L()}catch(J){if(K.stop(),G!==_||H!==K)throw J;throw H=null,R={...R,isRecording:!1,recordingError:J instanceof Error?J.message:String(J)},L(),J}})().finally(()=>{if(X===$)X=null});return X=$,X};return{close:(G)=>{D=!0,U(),w(),g.close(G)},disconnect:()=>{D=!0,U(),w(),g.disconnect()},startRecording:Z,stopRecording:w,get assistantAudio(){return R.assistantAudio},get assistantTexts(){return R.assistantTexts},get assistantStreamingText(){return R.assistantStreamingText},bindHTMX(G){return d(g,G)},get call(){return R.call},callControl:(G)=>g.callControl(G),endTurn:()=>g.endTurn(),get error(){return R.error},getServerSnapshot:()=>R,getSnapshot:()=>R,get isConnected(){return R.isConnected},get isRecording(){return R.isRecording},get partial(){return R.partial},get paused(){return R.paused},get pauseExpiresAt(){return R.pauseExpiresAt},get reconnect(){return R.reconnect},get recordingError(){return R.recordingError},get scenarioId(){return R.scenarioId},sendAudio:(G)=>g.sendAudio(G),get sessionId(){return R.sessionId},get sessionMetadata(){return R.sessionMetadata},simulateDisconnect:()=>g.simulateDisconnect(),get status(){return R.status},subscribe:(G)=>{return O.add(G),()=>{O.delete(G)}},toggleRecording:async()=>{if(R.isRecording){w();return}await Z()},get turns(){return R.turns}}};var z=(V)=>String(V).replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&#39;");var C0=(V)=>{if(!V.isConnected)return"idle";if(V.isPlaying)return"speaking";if(V.isRecording&&V.hasActivePartial)return"listening";if(V.isRecording)return"listening";if(V.lastTranscriptAt&&!V.lastAssistantAt)return"thinking";if(V.lastTranscriptAt&&V.lastAssistantAt&&V.lastTranscriptAt>V.lastAssistantAt)return"thinking";return"idle"};var e0={accent:"#3b82f6",background:"#0f172a",errorAccent:"#ef4444",fontFamily:'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',foreground:"#f8fafc",radius:16},VV={callEnded:"Call ended",connecting:"Connecting…",endCall:"End call",idle:"Idle",listening:"Listening",mute:"Mute",speaking:"Speaking",startCall:"Start call",thinking:"Thinking",unmute:"Unmute"},AV=(V,A)=>{switch(V){case"listening":return A.listening;case"speaking":return A.speaking;case"thinking":return A.thinking;case"idle":return A.idle}},_0=(V)=>{let A={...e0,...V.theme},C={...VV,...V.labels},g=V.state.assistantAudio.at(-1)?.receivedAt,H=V.state.turns.at(-1)?.committedAt,_=C0({hasActivePartial:V.state.partial.length>0,isConnected:V.state.isConnected,isPlaying:!1,isRecording:V.state.isRecording,lastAssistantAt:g,lastTranscriptAt:H}),D=!V.state.isConnected&&V.state.status!=="idle"&&!V.state.error,X=V.state.error?"Error":D?C.connecting:V.state.status==="completed"?C.callEnded:AV(_,C);return{agentState:_,classes:{container:`absolute-voice-widget absolute-voice-widget--${_}`,dot:`absolute-voice-widget__dot${V.state.error?" absolute-voice-widget__dot--error":""}`},controls:{canEnd:V.state.isConnected,canMute:V.state.isRecording,canStart:!V.state.isRecording&&V.state.status!=="completed"},errorMessage:V.state.error??void 0,labels:C,partial:V.state.partial||void 0,statusLabel:X,theme:A,title:V.title??"Voice"}},gV=(V)=>typeof V==="number"?`${V}px`:V,T0=(V)=>{let A=V.theme,C=`background:${A.background};border-radius:${gV(A.radius)};color:${A.foreground};font-family:${A.fontFamily};min-width:240px;padding:20px 22px;`,g=`background:${V.errorMessage?A.errorAccent:V.agentState==="idle"?"rgba(148,163,184,0.6)":A.accent};border-radius:50%;height:10px;width:10px;`,H=[];if(V.controls.canStart)H.push(`<button type="button" data-action="start" style="background:${A.accent};border:none;border-radius:12px;color:${A.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${z(V.labels.startCall)}</button>`);if(V.controls.canMute)H.push(`<button type="button" data-action="mute" style="background:transparent;border:1px solid rgba(255,255,255,0.18);border-radius:12px;color:${A.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${z(V.labels.mute)}</button>`);if(V.controls.canEnd)H.push(`<button type="button" data-action="end" style="background:${A.errorAccent};border:none;border-radius:12px;color:${A.foreground};cursor:pointer;font-size:14px;font-weight:500;padding:10px 14px;">${z(V.labels.endCall)}</button>`);return`<div role="region" aria-live="polite" data-agent-state="${V.agentState}" class="${z(V.classes.container)}" style="${C}">
2
2
  <div style="align-items:center;display:flex;gap:10px;margin-bottom:12px;">
3
- <span aria-hidden="true" class="${z(V.classes.dot)}" style="${A}"></span>
3
+ <span aria-hidden="true" class="${z(V.classes.dot)}" style="${g}"></span>
4
4
  <strong style="font-size:15px;">${z(V.title)}</strong>
5
5
  <span style="font-size:13px;margin-left:auto;opacity:0.7;">${z(V.statusLabel)}</span>
6
6
  </div>
7
7
  ${V.partial?`<p style="font-size:13px;margin:8px 0 12px;opacity:0.85;word-break:break-word;">“${z(V.partial)}”</p>`:""}
8
- <div style="display:flex;gap:10px;">${R.join("")}</div>
9
- ${V.errorMessage?`<p style="color:${g.errorAccent};font-size:12px;margin-top:12px;">${z(V.errorMessage)}</p>`:""}
10
- </div>`};var CV=(V)=>{if(typeof V!=="string")return V;let g=document.querySelector(V);if(!g)throw Error(`AbsoluteVoice.mount: no element matches "${V}"`);return g},$0=(V,g={})=>{let C=CV(V),A=A0(g.path??"/voice",g.controllerOptions),R=null,_=null,D=()=>{let H=_0({...g.labels!==void 0?{labels:g.labels}:{},state:{assistantAudio:A.assistantAudio,error:A.error,isConnected:A.isConnected,isRecording:A.isRecording,partial:A.partial,status:A.status,turns:A.turns},...g.theme!==void 0?{theme:g.theme}:{},...g.title!==void 0?{title:g.title}:{}});C.innerHTML=T0(H);for(let O of C.querySelectorAll("button[data-action]")){let{action:L}=O.dataset;O.addEventListener("click",()=>{if(L==="start")A.startRecording();else if(L==="mute")A.stopRecording();else if(L==="end")A.close()})}if(A.error&&A.error!==R)R=A.error,g.onError?.(A.error);if(A.status!==_)_=A.status,g.onStatusChange?.(A.status)},X=A.subscribe(D);if(D(),g.autoStart)A.startRecording();return{controller:A,async end(){await A.close()},mute(){A.stopRecording()},async start(){await A.startRecording()},unmount(){X(),A.close(),C.innerHTML=""}}},R0="0.0.22-beta.516",H0={mount:$0,version:R0};if(typeof globalThis<"u")globalThis.AbsoluteVoice=H0;var TV=H0;})();
8
+ <div style="display:flex;gap:10px;">${H.join("")}</div>
9
+ ${V.errorMessage?`<p style="color:${A.errorAccent};font-size:12px;margin-top:12px;">${z(V.errorMessage)}</p>`:""}
10
+ </div>`};var CV=(V)=>{if(typeof V!=="string")return V;let A=document.querySelector(V);if(!A)throw Error(`AbsoluteVoice.mount: no element matches "${V}"`);return A},$0=(V,A={})=>{let C=CV(V),g=g0(A.path??"/voice",A.controllerOptions),H=null,_=null,D=()=>{let R=_0({...A.labels!==void 0?{labels:A.labels}:{},state:{assistantAudio:g.assistantAudio,error:g.error,isConnected:g.isConnected,isRecording:g.isRecording,partial:g.partial,status:g.status,turns:g.turns},...A.theme!==void 0?{theme:A.theme}:{},...A.title!==void 0?{title:A.title}:{}});C.innerHTML=T0(R);for(let O of C.querySelectorAll("button[data-action]")){let{action:L}=O.dataset;O.addEventListener("click",()=>{if(L==="start")g.startRecording();else if(L==="mute")g.stopRecording();else if(L==="end")g.close()})}if(g.error&&g.error!==H)H=g.error,A.onError?.(g.error);if(g.status!==_)_=g.status,A.onStatusChange?.(g.status)},X=g.subscribe(D);if(D(),A.autoStart)g.startRecording();return{controller:g,async end(){await g.close()},mute(){g.stopRecording()},async start(){await g.startRecording()},unmount(){X(),g.close(),C.innerHTML=""}}},R0="0.0.22-beta.516",H0={mount:$0,version:R0};if(typeof globalThis<"u")globalThis.AbsoluteVoice=H0;var TV=H0;})();
package/dist/index.js CHANGED
@@ -6880,6 +6880,8 @@ var createVoiceSession = (options) => {
6880
6880
  if (session.status === "completed" || session.status === "failed") {
6881
6881
  await options.store.set(options.id, session);
6882
6882
  await send({
6883
+ pauseExpiresAt: session.pause?.expiresAt,
6884
+ paused: Boolean(session.pause),
6883
6885
  sessionId: options.id,
6884
6886
  status: session.status,
6885
6887
  sessionMetadata: session.metadata && typeof session.metadata === "object" ? session.metadata : undefined,
@@ -6915,6 +6917,8 @@ var createVoiceSession = (options) => {
6915
6917
  await sendCallLifecycle(session);
6916
6918
  }
6917
6919
  await send({
6920
+ pauseExpiresAt: session.pause?.expiresAt,
6921
+ paused: callerPaused,
6918
6922
  sessionId: options.id,
6919
6923
  status: session.status,
6920
6924
  sessionMetadata: session.metadata && typeof session.metadata === "object" ? session.metadata : undefined,
@@ -40429,8 +40433,15 @@ var voice = (config) => {
40429
40433
  };
40430
40434
  const createAndConnectSession = async (ws, sessionId, scenarioId) => {
40431
40435
  const identity = socketIdentity(ws);
40432
- const session = await createManagedSession(ws, sessionId, scenarioId);
40433
- const typedSession = session;
40436
+ let session;
40437
+ try {
40438
+ session = await createManagedSession(ws, sessionId, scenarioId);
40439
+ } catch (error) {
40440
+ runtime.logger.warn?.(`[voice] session initialization failed for "${sessionId}": ${error instanceof Error ? error.message : String(error)}`);
40441
+ closedSockets.add(identity);
40442
+ ws.close(4500, "voice session initialization failed");
40443
+ throw error;
40444
+ }
40434
40445
  if (closedSockets.has(identity) || !socketIsOpen(ws) || runtime.activeSockets.get(sessionId) !== identity) {
40435
40446
  ws.close(1000, "superseded");
40436
40447
  throw new Error("Voice socket was superseded during session creation");
@@ -40446,6 +40457,7 @@ var voice = (config) => {
40446
40457
  ws.close(4500, "voice session initialization failed");
40447
40458
  throw error;
40448
40459
  }
40460
+ const typedSession = session;
40449
40461
  if (closedSockets.has(identity) || !socketIsOpen(ws) || runtime.activeSockets.get(sessionId) !== identity) {
40450
40462
  await session.disconnect({
40451
40463
  code: 1000,
@@ -11338,6 +11338,8 @@ var serverMessageToAction = (message) => {
11338
11338
  };
11339
11339
  case "session":
11340
11340
  return {
11341
+ paused: message.paused,
11342
+ pauseExpiresAt: message.pauseExpiresAt,
11341
11343
  sessionId: message.sessionId,
11342
11344
  sessionMetadata: message.sessionMetadata,
11343
11345
  scenarioId: message.scenarioId,
@@ -11698,12 +11700,6 @@ var createVoiceConnection = (path, options = {}) => {
11698
11700
  state.reconnectResetTimeout = null;
11699
11701
  }, reconnectResetAfterMs);
11700
11702
  }
11701
- listeners.forEach((listener) => listener({
11702
- scenarioId: state.scenarioId ?? undefined,
11703
- sessionId: state.sessionId,
11704
- status: "active",
11705
- type: "session"
11706
- }));
11707
11703
  state.pingInterval = setInterval(() => {
11708
11704
  if (ws.readyState === WS_OPEN) {
11709
11705
  ws.send(JSON.stringify({ type: "ping" }));
@@ -11934,6 +11930,7 @@ var createInitialState = () => ({
11934
11930
  call: null,
11935
11931
  error: null,
11936
11932
  isConnected: false,
11933
+ paused: false,
11937
11934
  partial: "",
11938
11935
  reconnect: createInitialReconnectState(),
11939
11936
  scenarioId: null,
@@ -12070,6 +12067,8 @@ var createVoiceStreamStore = () => {
12070
12067
  state = {
12071
12068
  ...state,
12072
12069
  error: null,
12070
+ paused: action.paused ?? false,
12071
+ pauseExpiresAt: action.pauseExpiresAt,
12073
12072
  scenarioId: action.scenarioId ?? state.scenarioId,
12074
12073
  isConnected: action.status === "active",
12075
12074
  sessionId: action.sessionId,
@@ -12206,6 +12205,12 @@ var createVoiceStream = (path, options = {}) => {
12206
12205
  get partial() {
12207
12206
  return store.getSnapshot().partial;
12208
12207
  },
12208
+ get paused() {
12209
+ return store.getSnapshot().paused;
12210
+ },
12211
+ get pauseExpiresAt() {
12212
+ return store.getSnapshot().pauseExpiresAt;
12213
+ },
12209
12214
  get reconnect() {
12210
12215
  return store.getSnapshot().reconnect;
12211
12216
  },
@@ -12801,6 +12806,8 @@ var createInitialState2 = (stream) => ({
12801
12806
  error: stream.error,
12802
12807
  isConnected: stream.isConnected,
12803
12808
  isRecording: false,
12809
+ paused: stream.paused,
12810
+ pauseExpiresAt: stream.pauseExpiresAt,
12804
12811
  partial: stream.partial,
12805
12812
  reconnect: stream.reconnect,
12806
12813
  recordingError: null,
@@ -12836,6 +12843,8 @@ var createVoiceController = (path, options = {}) => {
12836
12843
  call: stream.call,
12837
12844
  error: stream.error,
12838
12845
  isConnected: stream.isConnected,
12846
+ paused: stream.paused,
12847
+ pauseExpiresAt: stream.pauseExpiresAt,
12839
12848
  partial: stream.partial,
12840
12849
  reconnect: stream.reconnect,
12841
12850
  sessionId: stream.sessionId,
@@ -12983,6 +12992,12 @@ var createVoiceController = (path, options = {}) => {
12983
12992
  get partial() {
12984
12993
  return state.partial;
12985
12994
  },
12995
+ get paused() {
12996
+ return state.paused;
12997
+ },
12998
+ get pauseExpiresAt() {
12999
+ return state.pauseExpiresAt;
13000
+ },
12986
13001
  get reconnect() {
12987
13002
  return state.reconnect;
12988
13003
  },
@@ -10,6 +10,8 @@ export declare const useVoiceController: <TResult = unknown>(path: string, optio
10
10
  stopRecording: () => void;
11
11
  toggleRecording: () => Promise<void>;
12
12
  call: import("..").VoiceCallLifecycleState | null;
13
+ paused: boolean;
14
+ pauseExpiresAt?: number;
13
15
  sessionMetadata: Record<string, unknown> | null;
14
16
  sessionId: string | null;
15
17
  scenarioId: string | null;
@@ -6,6 +6,8 @@ export declare const useVoiceStream: <TResult = unknown>(path: string, options?:
6
6
  sendAudio: (audio: Uint8Array | ArrayBuffer) => void;
7
7
  simulateDisconnect: () => void;
8
8
  call: import("..").VoiceCallLifecycleState | null;
9
+ paused: boolean;
10
+ pauseExpiresAt?: number;
9
11
  sessionMetadata: Record<string, unknown> | null;
10
12
  sessionId: string | null;
11
13
  scenarioId: string | null;
@@ -707,6 +707,8 @@ var serverMessageToAction = (message) => {
707
707
  };
708
708
  case "session":
709
709
  return {
710
+ paused: message.paused,
711
+ pauseExpiresAt: message.pauseExpiresAt,
710
712
  sessionId: message.sessionId,
711
713
  sessionMetadata: message.sessionMetadata,
712
714
  scenarioId: message.scenarioId,
@@ -1067,12 +1069,6 @@ var createVoiceConnection = (path, options = {}) => {
1067
1069
  state.reconnectResetTimeout = null;
1068
1070
  }, reconnectResetAfterMs);
1069
1071
  }
1070
- listeners.forEach((listener) => listener({
1071
- scenarioId: state.scenarioId ?? undefined,
1072
- sessionId: state.sessionId,
1073
- status: "active",
1074
- type: "session"
1075
- }));
1076
1072
  state.pingInterval = setInterval(() => {
1077
1073
  if (ws.readyState === WS_OPEN) {
1078
1074
  ws.send(JSON.stringify({ type: "ping" }));
@@ -1303,6 +1299,7 @@ var createInitialState = () => ({
1303
1299
  call: null,
1304
1300
  error: null,
1305
1301
  isConnected: false,
1302
+ paused: false,
1306
1303
  partial: "",
1307
1304
  reconnect: createInitialReconnectState(),
1308
1305
  scenarioId: null,
@@ -1439,6 +1436,8 @@ var createVoiceStreamStore = () => {
1439
1436
  state = {
1440
1437
  ...state,
1441
1438
  error: null,
1439
+ paused: action.paused ?? false,
1440
+ pauseExpiresAt: action.pauseExpiresAt,
1442
1441
  scenarioId: action.scenarioId ?? state.scenarioId,
1443
1442
  isConnected: action.status === "active",
1444
1443
  sessionId: action.sessionId,
@@ -1575,6 +1574,12 @@ var createVoiceStream = (path, options = {}) => {
1575
1574
  get partial() {
1576
1575
  return store.getSnapshot().partial;
1577
1576
  },
1577
+ get paused() {
1578
+ return store.getSnapshot().paused;
1579
+ },
1580
+ get pauseExpiresAt() {
1581
+ return store.getSnapshot().pauseExpiresAt;
1582
+ },
1578
1583
  get reconnect() {
1579
1584
  return store.getSnapshot().reconnect;
1580
1585
  },
@@ -1938,6 +1943,8 @@ var createInitialState2 = (stream) => ({
1938
1943
  error: stream.error,
1939
1944
  isConnected: stream.isConnected,
1940
1945
  isRecording: false,
1946
+ paused: stream.paused,
1947
+ pauseExpiresAt: stream.pauseExpiresAt,
1941
1948
  partial: stream.partial,
1942
1949
  reconnect: stream.reconnect,
1943
1950
  recordingError: null,
@@ -1973,6 +1980,8 @@ var createVoiceController = (path, options = {}) => {
1973
1980
  call: stream.call,
1974
1981
  error: stream.error,
1975
1982
  isConnected: stream.isConnected,
1983
+ paused: stream.paused,
1984
+ pauseExpiresAt: stream.pauseExpiresAt,
1976
1985
  partial: stream.partial,
1977
1986
  reconnect: stream.reconnect,
1978
1987
  sessionId: stream.sessionId,
@@ -2120,6 +2129,12 @@ var createVoiceController = (path, options = {}) => {
2120
2129
  get partial() {
2121
2130
  return state.partial;
2122
2131
  },
2132
+ get paused() {
2133
+ return state.paused;
2134
+ },
2135
+ get pauseExpiresAt() {
2136
+ return state.pauseExpiresAt;
2137
+ },
2123
2138
  get reconnect() {
2124
2139
  return state.reconnect;
2125
2140
  },
@@ -2928,6 +2928,8 @@ var serverMessageToAction = (message) => {
2928
2928
  };
2929
2929
  case "session":
2930
2930
  return {
2931
+ paused: message.paused,
2932
+ pauseExpiresAt: message.pauseExpiresAt,
2931
2933
  sessionId: message.sessionId,
2932
2934
  sessionMetadata: message.sessionMetadata,
2933
2935
  scenarioId: message.scenarioId,
@@ -3288,12 +3290,6 @@ var createVoiceConnection = (path, options = {}) => {
3288
3290
  state.reconnectResetTimeout = null;
3289
3291
  }, reconnectResetAfterMs);
3290
3292
  }
3291
- listeners.forEach((listener) => listener({
3292
- scenarioId: state.scenarioId ?? undefined,
3293
- sessionId: state.sessionId,
3294
- status: "active",
3295
- type: "session"
3296
- }));
3297
3293
  state.pingInterval = setInterval(() => {
3298
3294
  if (ws.readyState === WS_OPEN) {
3299
3295
  ws.send(JSON.stringify({ type: "ping" }));
@@ -3524,6 +3520,7 @@ var createInitialState2 = () => ({
3524
3520
  call: null,
3525
3521
  error: null,
3526
3522
  isConnected: false,
3523
+ paused: false,
3527
3524
  partial: "",
3528
3525
  reconnect: createInitialReconnectState(),
3529
3526
  scenarioId: null,
@@ -3660,6 +3657,8 @@ var createVoiceStreamStore = () => {
3660
3657
  state = {
3661
3658
  ...state,
3662
3659
  error: null,
3660
+ paused: action.paused ?? false,
3661
+ pauseExpiresAt: action.pauseExpiresAt,
3663
3662
  scenarioId: action.scenarioId ?? state.scenarioId,
3664
3663
  isConnected: action.status === "active",
3665
3664
  sessionId: action.sessionId,
@@ -3796,6 +3795,12 @@ var createVoiceStream = (path, options = {}) => {
3796
3795
  get partial() {
3797
3796
  return store.getSnapshot().partial;
3798
3797
  },
3798
+ get paused() {
3799
+ return store.getSnapshot().paused;
3800
+ },
3801
+ get pauseExpiresAt() {
3802
+ return store.getSnapshot().pauseExpiresAt;
3803
+ },
3799
3804
  get reconnect() {
3800
3805
  return store.getSnapshot().reconnect;
3801
3806
  },
@@ -4159,6 +4164,8 @@ var createInitialState3 = (stream) => ({
4159
4164
  error: stream.error,
4160
4165
  isConnected: stream.isConnected,
4161
4166
  isRecording: false,
4167
+ paused: stream.paused,
4168
+ pauseExpiresAt: stream.pauseExpiresAt,
4162
4169
  partial: stream.partial,
4163
4170
  reconnect: stream.reconnect,
4164
4171
  recordingError: null,
@@ -4194,6 +4201,8 @@ var createVoiceController = (path, options = {}) => {
4194
4201
  call: stream.call,
4195
4202
  error: stream.error,
4196
4203
  isConnected: stream.isConnected,
4204
+ paused: stream.paused,
4205
+ pauseExpiresAt: stream.pauseExpiresAt,
4197
4206
  partial: stream.partial,
4198
4207
  reconnect: stream.reconnect,
4199
4208
  sessionId: stream.sessionId,
@@ -4341,6 +4350,12 @@ var createVoiceController = (path, options = {}) => {
4341
4350
  get partial() {
4342
4351
  return state.partial;
4343
4352
  },
4353
+ get paused() {
4354
+ return state.paused;
4355
+ },
4356
+ get pauseExpiresAt() {
4357
+ return state.pauseExpiresAt;
4358
+ },
4344
4359
  get reconnect() {
4345
4360
  return state.reconnect;
4346
4361
  },
@@ -9817,6 +9832,8 @@ var createVoiceSession = (options) => {
9817
9832
  if (session.status === "completed" || session.status === "failed") {
9818
9833
  await options.store.set(options.id, session);
9819
9834
  await send({
9835
+ pauseExpiresAt: session.pause?.expiresAt,
9836
+ paused: Boolean(session.pause),
9820
9837
  sessionId: options.id,
9821
9838
  status: session.status,
9822
9839
  sessionMetadata: session.metadata && typeof session.metadata === "object" ? session.metadata : undefined,
@@ -9852,6 +9869,8 @@ var createVoiceSession = (options) => {
9852
9869
  await sendCallLifecycle(session);
9853
9870
  }
9854
9871
  await send({
9872
+ pauseExpiresAt: session.pause?.expiresAt,
9873
+ paused: callerPaused,
9855
9874
  sessionId: options.id,
9856
9875
  status: session.status,
9857
9876
  sessionMetadata: session.metadata && typeof session.metadata === "object" ? session.metadata : undefined,
package/dist/vue/index.js CHANGED
@@ -10734,6 +10734,8 @@ var serverMessageToAction = (message) => {
10734
10734
  };
10735
10735
  case "session":
10736
10736
  return {
10737
+ paused: message.paused,
10738
+ pauseExpiresAt: message.pauseExpiresAt,
10737
10739
  sessionId: message.sessionId,
10738
10740
  sessionMetadata: message.sessionMetadata,
10739
10741
  scenarioId: message.scenarioId,
@@ -11094,12 +11096,6 @@ var createVoiceConnection = (path, options = {}) => {
11094
11096
  state.reconnectResetTimeout = null;
11095
11097
  }, reconnectResetAfterMs);
11096
11098
  }
11097
- listeners.forEach((listener) => listener({
11098
- scenarioId: state.scenarioId ?? undefined,
11099
- sessionId: state.sessionId,
11100
- status: "active",
11101
- type: "session"
11102
- }));
11103
11099
  state.pingInterval = setInterval(() => {
11104
11100
  if (ws.readyState === WS_OPEN) {
11105
11101
  ws.send(JSON.stringify({ type: "ping" }));
@@ -11330,6 +11326,7 @@ var createInitialState = () => ({
11330
11326
  call: null,
11331
11327
  error: null,
11332
11328
  isConnected: false,
11329
+ paused: false,
11333
11330
  partial: "",
11334
11331
  reconnect: createInitialReconnectState(),
11335
11332
  scenarioId: null,
@@ -11466,6 +11463,8 @@ var createVoiceStreamStore = () => {
11466
11463
  state = {
11467
11464
  ...state,
11468
11465
  error: null,
11466
+ paused: action.paused ?? false,
11467
+ pauseExpiresAt: action.pauseExpiresAt,
11469
11468
  scenarioId: action.scenarioId ?? state.scenarioId,
11470
11469
  isConnected: action.status === "active",
11471
11470
  sessionId: action.sessionId,
@@ -11602,6 +11601,12 @@ var createVoiceStream = (path, options = {}) => {
11602
11601
  get partial() {
11603
11602
  return store.getSnapshot().partial;
11604
11603
  },
11604
+ get paused() {
11605
+ return store.getSnapshot().paused;
11606
+ },
11607
+ get pauseExpiresAt() {
11608
+ return store.getSnapshot().pauseExpiresAt;
11609
+ },
11605
11610
  get reconnect() {
11606
11611
  return store.getSnapshot().reconnect;
11607
11612
  },
@@ -12218,6 +12223,8 @@ var createInitialState2 = (stream) => ({
12218
12223
  error: stream.error,
12219
12224
  isConnected: stream.isConnected,
12220
12225
  isRecording: false,
12226
+ paused: stream.paused,
12227
+ pauseExpiresAt: stream.pauseExpiresAt,
12221
12228
  partial: stream.partial,
12222
12229
  reconnect: stream.reconnect,
12223
12230
  recordingError: null,
@@ -12253,6 +12260,8 @@ var createVoiceController = (path, options = {}) => {
12253
12260
  call: stream.call,
12254
12261
  error: stream.error,
12255
12262
  isConnected: stream.isConnected,
12263
+ paused: stream.paused,
12264
+ pauseExpiresAt: stream.pauseExpiresAt,
12256
12265
  partial: stream.partial,
12257
12266
  reconnect: stream.reconnect,
12258
12267
  sessionId: stream.sessionId,
@@ -12400,6 +12409,12 @@ var createVoiceController = (path, options = {}) => {
12400
12409
  get partial() {
12401
12410
  return state.partial;
12402
12411
  },
12412
+ get paused() {
12413
+ return state.paused;
12414
+ },
12415
+ get pauseExpiresAt() {
12416
+ return state.pauseExpiresAt;
12417
+ },
12403
12418
  get reconnect() {
12404
12419
  return state.reconnect;
12405
12420
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.660",
3
+ "version": "0.0.22-beta.662",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",