@absolutejs/voice 0.0.22-beta.655 → 0.0.22-beta.657
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/angular/index.js +204 -70
- package/dist/client/connection.d.ts +3 -0
- package/dist/client/htmxBootstrap.js +204 -70
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +206 -71
- package/dist/core/types.d.ts +4 -0
- package/dist/embed/index.js +204 -70
- package/dist/embed/voice-widget.js +8 -8
- package/dist/react/index.js +204 -70
- package/dist/svelte/index.js +204 -70
- package/dist/testing/index.js +205 -71
- package/dist/vue/index.js +204 -70
- package/package.json +1 -1
package/dist/client/index.js
CHANGED
|
@@ -110,11 +110,19 @@ var DEFAULT_MAX_RECONNECT_ATTEMPTS = 15;
|
|
|
110
110
|
var DEFAULT_PING_INTERVAL = 30000;
|
|
111
111
|
var DEFAULT_RECONNECT_RESET_AFTER_MS = 30000;
|
|
112
112
|
var DEFAULT_CALL_CONTROL_ACK_TIMEOUT_MS = 5000;
|
|
113
|
+
var DEFAULT_PREPARE_RECONNECT_TIMEOUT_MS = 1e4;
|
|
113
114
|
var MAX_PENDING_CONTROL_MESSAGES = 100;
|
|
114
115
|
var RECONNECT_BASE_DELAY_MS = 500;
|
|
115
116
|
var DEFAULT_RECONNECT_MAX_DELAY_MS = 8000;
|
|
116
117
|
var computeVoiceReconnectDelayMs = (attempt, baseMs, maxDelayMs) => Math.min(maxDelayMs, baseMs * 2 ** (Math.max(1, attempt) - 1));
|
|
117
118
|
var DEFAULT_SCENARIO_QUERY_PARAM = "scenarioId";
|
|
119
|
+
|
|
120
|
+
class VoiceReconnectRejectedError extends Error {
|
|
121
|
+
constructor(message = "Voice authorization could not be renewed.") {
|
|
122
|
+
super(message);
|
|
123
|
+
this.name = "VoiceReconnectRejectedError";
|
|
124
|
+
}
|
|
125
|
+
}
|
|
118
126
|
var noop = () => {};
|
|
119
127
|
var noopAsync = () => Promise.resolve();
|
|
120
128
|
var noopUnsubscribe = () => noop;
|
|
@@ -194,6 +202,9 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
194
202
|
const reconnectMaxDelayMs = options.reconnectMaxDelayMs ?? DEFAULT_RECONNECT_MAX_DELAY_MS;
|
|
195
203
|
const pingInterval = options.pingInterval ?? DEFAULT_PING_INTERVAL;
|
|
196
204
|
const reconnectResetAfterMs = options.reconnectResetAfterMs ?? DEFAULT_RECONNECT_RESET_AFTER_MS;
|
|
205
|
+
let lifecycleGeneration = 0;
|
|
206
|
+
let disposed = false;
|
|
207
|
+
let reconnectPreparationAbort = null;
|
|
197
208
|
const computeReconnectDelayMs = (attempt) => computeVoiceReconnectDelayMs(attempt, RECONNECT_BASE_DELAY_MS, reconnectMaxDelayMs);
|
|
198
209
|
const state = {
|
|
199
210
|
isConnected: false,
|
|
@@ -257,6 +268,9 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
257
268
|
pendingCallControls.clear();
|
|
258
269
|
};
|
|
259
270
|
const scheduleReconnect = () => {
|
|
271
|
+
if (disposed)
|
|
272
|
+
return;
|
|
273
|
+
const scheduledGeneration = lifecycleGeneration;
|
|
260
274
|
state.reconnectAttempts += 1;
|
|
261
275
|
const delayMs = computeReconnectDelayMs(state.reconnectAttempts);
|
|
262
276
|
const nextAttemptAt = Date.now() + delayMs;
|
|
@@ -271,18 +285,44 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
271
285
|
type: "connection"
|
|
272
286
|
});
|
|
273
287
|
state.reconnectTimeout = setTimeout(async () => {
|
|
288
|
+
if (disposed || lifecycleGeneration !== scheduledGeneration)
|
|
289
|
+
return;
|
|
274
290
|
if (state.reconnectAttempts > maxReconnectAttempts) {
|
|
275
291
|
emitTerminalFailure("Voice connection could not be restored.");
|
|
276
292
|
return;
|
|
277
293
|
}
|
|
278
294
|
try {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
295
|
+
if (options.prepareReconnect) {
|
|
296
|
+
const preparationAbort = new AbortController;
|
|
297
|
+
reconnectPreparationAbort = preparationAbort;
|
|
298
|
+
const timeout = setTimeout(() => preparationAbort.abort("Voice reconnect preparation timed out"), options.prepareReconnectTimeoutMs ?? DEFAULT_PREPARE_RECONNECT_TIMEOUT_MS);
|
|
299
|
+
try {
|
|
300
|
+
await Promise.race([
|
|
301
|
+
options.prepareReconnect({
|
|
302
|
+
attempt: state.reconnectAttempts,
|
|
303
|
+
path,
|
|
304
|
+
scenarioId: state.scenarioId,
|
|
305
|
+
sessionId: state.sessionId,
|
|
306
|
+
signal: preparationAbort.signal
|
|
307
|
+
}),
|
|
308
|
+
new Promise((_, reject) => {
|
|
309
|
+
preparationAbort.signal.addEventListener("abort", () => reject(new Error("Voice reconnect preparation timed out.")), { once: true });
|
|
310
|
+
})
|
|
311
|
+
]);
|
|
312
|
+
} finally {
|
|
313
|
+
clearTimeout(timeout);
|
|
314
|
+
if (reconnectPreparationAbort === preparationAbort) {
|
|
315
|
+
reconnectPreparationAbort = null;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
} catch (error) {
|
|
320
|
+
if (disposed || lifecycleGeneration !== scheduledGeneration)
|
|
321
|
+
return;
|
|
322
|
+
if (error instanceof VoiceReconnectRejectedError) {
|
|
323
|
+
emitTerminalFailure(error.message);
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
286
326
|
if (state.reconnectAttempts < maxReconnectAttempts) {
|
|
287
327
|
scheduleReconnect();
|
|
288
328
|
} else {
|
|
@@ -290,10 +330,14 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
290
330
|
}
|
|
291
331
|
return;
|
|
292
332
|
}
|
|
333
|
+
if (disposed || lifecycleGeneration !== scheduledGeneration)
|
|
334
|
+
return;
|
|
293
335
|
connect();
|
|
294
336
|
}, delayMs);
|
|
295
337
|
};
|
|
296
338
|
const connect = () => {
|
|
339
|
+
if (disposed)
|
|
340
|
+
return;
|
|
297
341
|
const ws = new WebSocket(buildWsUrl(path, state.sessionId, state.scenarioId, options.query ?? {}));
|
|
298
342
|
ws.binaryType = "arraybuffer";
|
|
299
343
|
ws.onopen = () => {
|
|
@@ -364,6 +408,7 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
364
408
|
state.ws = null;
|
|
365
409
|
state.isConnected = false;
|
|
366
410
|
clearTimers();
|
|
411
|
+
rejectPendingCallControls("Voice connection interrupted");
|
|
367
412
|
const reconnectable = shouldReconnect && event.code !== WS_NORMAL_CLOSURE && event.code !== WS_UNAUTHORIZED && event.code !== WS_FORBIDDEN && state.reconnectAttempts < maxReconnectAttempts;
|
|
368
413
|
const authorizationFailure = event.code === WS_UNAUTHORIZED || event.code === WS_FORBIDDEN;
|
|
369
414
|
if (authorizationFailure) {
|
|
@@ -394,6 +439,8 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
394
439
|
state.ws = ws;
|
|
395
440
|
};
|
|
396
441
|
const sendSerialized = (value) => {
|
|
442
|
+
if (disposed)
|
|
443
|
+
return;
|
|
397
444
|
if (state.ws?.readyState === WS_OPEN) {
|
|
398
445
|
state.ws.send(value);
|
|
399
446
|
return;
|
|
@@ -429,6 +476,9 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
429
476
|
send({ type: "end_turn" });
|
|
430
477
|
};
|
|
431
478
|
const callControl = (message) => {
|
|
479
|
+
if (state.ws?.readyState !== WS_OPEN) {
|
|
480
|
+
return Promise.reject(new Error(`${message.action} is unavailable while disconnected`));
|
|
481
|
+
}
|
|
432
482
|
const requestId = crypto.randomUUID();
|
|
433
483
|
const { promise, reject, resolve } = Promise.withResolvers();
|
|
434
484
|
const timeout = setTimeout(() => {
|
|
@@ -436,16 +486,21 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
436
486
|
reject(new Error(`${message.action} acknowledgement timed out`));
|
|
437
487
|
}, DEFAULT_CALL_CONTROL_ACK_TIMEOUT_MS);
|
|
438
488
|
pendingCallControls.set(requestId, { reject, resolve, timeout });
|
|
439
|
-
send({
|
|
489
|
+
state.ws.send(JSON.stringify({
|
|
440
490
|
...message,
|
|
441
491
|
requestId,
|
|
442
492
|
type: "call_control"
|
|
443
|
-
});
|
|
493
|
+
}));
|
|
444
494
|
return promise;
|
|
445
495
|
};
|
|
446
496
|
const close = (reason = "client-close") => {
|
|
497
|
+
disposed = true;
|
|
498
|
+
reconnectPreparationAbort?.abort();
|
|
499
|
+
reconnectPreparationAbort = null;
|
|
500
|
+
lifecycleGeneration += 1;
|
|
447
501
|
clearTimers();
|
|
448
502
|
rejectPendingCallControls("Voice connection closed");
|
|
503
|
+
state.pendingMessages.length = 0;
|
|
449
504
|
if (state.ws) {
|
|
450
505
|
const ws = state.ws;
|
|
451
506
|
state.ws = null;
|
|
@@ -458,8 +513,13 @@ var createVoiceConnection = (path, options = {}) => {
|
|
|
458
513
|
listeners.clear();
|
|
459
514
|
};
|
|
460
515
|
const disconnect = () => {
|
|
516
|
+
disposed = true;
|
|
517
|
+
reconnectPreparationAbort?.abort();
|
|
518
|
+
reconnectPreparationAbort = null;
|
|
519
|
+
lifecycleGeneration += 1;
|
|
461
520
|
clearTimers();
|
|
462
521
|
rejectPendingCallControls("Voice connection disconnected");
|
|
522
|
+
state.pendingMessages.length = 0;
|
|
463
523
|
if (state.ws) {
|
|
464
524
|
const ws = state.ws;
|
|
465
525
|
state.ws = null;
|
|
@@ -1629,7 +1689,10 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
1629
1689
|
getSessionId: () => options.browserMedia ? options.browserMedia.getSessionId?.() ?? connection.getSessionId() : connection.getSessionId()
|
|
1630
1690
|
}) : null;
|
|
1631
1691
|
const subscribers = new Set;
|
|
1692
|
+
let disposed = false;
|
|
1632
1693
|
const start = (input) => Promise.resolve().then(() => {
|
|
1694
|
+
if (disposed)
|
|
1695
|
+
return;
|
|
1633
1696
|
if (!input?.sessionId && !input?.scenarioId) {
|
|
1634
1697
|
return;
|
|
1635
1698
|
}
|
|
@@ -1688,6 +1751,7 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
1688
1751
|
return connection.callControl(message);
|
|
1689
1752
|
},
|
|
1690
1753
|
close(reason) {
|
|
1754
|
+
disposed = true;
|
|
1691
1755
|
unsubscribeConnection();
|
|
1692
1756
|
browserMediaReporter?.close();
|
|
1693
1757
|
connection.close(reason);
|
|
@@ -1695,6 +1759,7 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
1695
1759
|
notify();
|
|
1696
1760
|
},
|
|
1697
1761
|
disconnect() {
|
|
1762
|
+
disposed = true;
|
|
1698
1763
|
unsubscribeConnection();
|
|
1699
1764
|
browserMediaReporter?.close();
|
|
1700
1765
|
connection.disconnect();
|
|
@@ -1853,48 +1918,89 @@ var createMicrophoneCapture = (options) => {
|
|
|
1853
1918
|
let sourceNode = null;
|
|
1854
1919
|
let processorNode = null;
|
|
1855
1920
|
let mediaStream = null;
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1921
|
+
let lifecycleGeneration = 0;
|
|
1922
|
+
let startPromise = null;
|
|
1923
|
+
const release = (resources) => {
|
|
1924
|
+
resources.processorNode?.disconnect();
|
|
1925
|
+
resources.sourceNode?.disconnect();
|
|
1926
|
+
resources.mediaStream?.getTracks().forEach((track) => track.stop());
|
|
1927
|
+
resources.audioContext?.close();
|
|
1928
|
+
};
|
|
1929
|
+
const start = () => {
|
|
1930
|
+
if (mediaStream)
|
|
1931
|
+
return Promise.resolve();
|
|
1932
|
+
if (startPromise)
|
|
1933
|
+
return startPromise;
|
|
1934
|
+
const generation = ++lifecycleGeneration;
|
|
1935
|
+
const operation = async () => {
|
|
1936
|
+
if (!options.stream && (typeof navigator === "undefined" || !navigator.mediaDevices?.getUserMedia)) {
|
|
1937
|
+
throw new Error("Browser microphone capture requires navigator.mediaDevices.getUserMedia.");
|
|
1938
|
+
}
|
|
1939
|
+
const AudioContextCtor = (typeof window !== "undefined" ? window.AudioContext ?? window.webkitAudioContext : undefined) ?? AudioContext;
|
|
1940
|
+
if (!AudioContextCtor) {
|
|
1941
|
+
throw new Error("Browser microphone capture requires AudioContext support.");
|
|
1942
|
+
}
|
|
1943
|
+
let pendingAudioContext = null;
|
|
1944
|
+
let pendingMediaStream = null;
|
|
1945
|
+
let pendingProcessorNode = null;
|
|
1946
|
+
let pendingSourceNode = null;
|
|
1947
|
+
try {
|
|
1948
|
+
pendingMediaStream = options.stream ?? await navigator.mediaDevices.getUserMedia({
|
|
1949
|
+
audio: {
|
|
1950
|
+
autoGainControl: true,
|
|
1951
|
+
channelCount: options.channelCount ?? 1,
|
|
1952
|
+
echoCancellation: true,
|
|
1953
|
+
noiseSuppression: true
|
|
1954
|
+
}
|
|
1955
|
+
});
|
|
1956
|
+
if (generation !== lifecycleGeneration) {
|
|
1957
|
+
throw new Error("Microphone capture stopped during startup.");
|
|
1871
1958
|
}
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1959
|
+
pendingAudioContext = new AudioContextCtor;
|
|
1960
|
+
if (pendingAudioContext.state === "suspended") {
|
|
1961
|
+
await pendingAudioContext.resume();
|
|
1962
|
+
}
|
|
1963
|
+
if (generation !== lifecycleGeneration) {
|
|
1964
|
+
throw new Error("Microphone capture stopped during startup.");
|
|
1965
|
+
}
|
|
1966
|
+
pendingSourceNode = pendingAudioContext.createMediaStreamSource(pendingMediaStream);
|
|
1967
|
+
pendingProcessorNode = pendingAudioContext.createScriptProcessor(4096, 1, 1);
|
|
1968
|
+
pendingProcessorNode.onaudioprocess = (event) => {
|
|
1969
|
+
const channel = event.inputBuffer.getChannelData(0);
|
|
1970
|
+
const downsampled = downsampleBuffer(channel, pendingAudioContext?.sampleRate ?? 48000, options.sampleRateHz ?? 16000);
|
|
1971
|
+
const pcm = floatTo16BitPCM(downsampled);
|
|
1972
|
+
options.onLevel?.(getPcmLevel(pcm));
|
|
1973
|
+
options.onAudio(pcm);
|
|
1974
|
+
};
|
|
1975
|
+
pendingSourceNode.connect(pendingProcessorNode);
|
|
1976
|
+
pendingProcessorNode.connect(pendingAudioContext.destination);
|
|
1977
|
+
if (generation !== lifecycleGeneration) {
|
|
1978
|
+
throw new Error("Microphone capture stopped during startup.");
|
|
1979
|
+
}
|
|
1980
|
+
audioContext = pendingAudioContext;
|
|
1981
|
+
mediaStream = pendingMediaStream;
|
|
1982
|
+
processorNode = pendingProcessorNode;
|
|
1983
|
+
sourceNode = pendingSourceNode;
|
|
1984
|
+
} catch (error) {
|
|
1985
|
+
release({
|
|
1986
|
+
audioContext: pendingAudioContext,
|
|
1987
|
+
mediaStream: pendingMediaStream,
|
|
1988
|
+
processorNode: pendingProcessorNode,
|
|
1989
|
+
sourceNode: pendingSourceNode
|
|
1990
|
+
});
|
|
1991
|
+
throw error;
|
|
1876
1992
|
}
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
options.onAudio(pcm);
|
|
1885
|
-
};
|
|
1886
|
-
sourceNode.connect(processorNode);
|
|
1887
|
-
processorNode.connect(audioContext.destination);
|
|
1888
|
-
} catch (error) {
|
|
1889
|
-
stop();
|
|
1890
|
-
throw error;
|
|
1891
|
-
}
|
|
1993
|
+
};
|
|
1994
|
+
const pending = operation().finally(() => {
|
|
1995
|
+
if (startPromise === pending)
|
|
1996
|
+
startPromise = null;
|
|
1997
|
+
});
|
|
1998
|
+
startPromise = pending;
|
|
1999
|
+
return pending;
|
|
1892
2000
|
};
|
|
1893
2001
|
const stop = () => {
|
|
1894
|
-
|
|
1895
|
-
sourceNode
|
|
1896
|
-
mediaStream?.getTracks().forEach((track) => track.stop());
|
|
1897
|
-
audioContext?.close();
|
|
2002
|
+
lifecycleGeneration += 1;
|
|
2003
|
+
release({ audioContext, mediaStream, processorNode, sourceNode });
|
|
1898
2004
|
options.onLevel?.(0);
|
|
1899
2005
|
audioContext = null;
|
|
1900
2006
|
mediaStream = null;
|
|
@@ -2250,6 +2356,9 @@ var createVoiceController = (path, options = {}) => {
|
|
|
2250
2356
|
...options.connection
|
|
2251
2357
|
});
|
|
2252
2358
|
let capture = null;
|
|
2359
|
+
let captureGeneration = 0;
|
|
2360
|
+
let disposed = false;
|
|
2361
|
+
let startRecordingPromise = null;
|
|
2253
2362
|
let state = createInitialState3(stream);
|
|
2254
2363
|
const subscribers = new Set;
|
|
2255
2364
|
const notify = () => {
|
|
@@ -2306,6 +2415,7 @@ var createVoiceController = (path, options = {}) => {
|
|
|
2306
2415
|
return capture;
|
|
2307
2416
|
};
|
|
2308
2417
|
const stopRecording = () => {
|
|
2418
|
+
captureGeneration += 1;
|
|
2309
2419
|
capture?.stop();
|
|
2310
2420
|
capture = null;
|
|
2311
2421
|
state = {
|
|
@@ -2315,39 +2425,63 @@ var createVoiceController = (path, options = {}) => {
|
|
|
2315
2425
|
notify();
|
|
2316
2426
|
};
|
|
2317
2427
|
const startRecording = async () => {
|
|
2428
|
+
if (disposed) {
|
|
2429
|
+
throw new Error("Voice controller is closed.");
|
|
2430
|
+
}
|
|
2318
2431
|
if (state.isRecording) {
|
|
2319
2432
|
return;
|
|
2320
2433
|
}
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2434
|
+
if (startRecordingPromise)
|
|
2435
|
+
return startRecordingPromise;
|
|
2436
|
+
const generation = ++captureGeneration;
|
|
2437
|
+
const activeCapture = ensureCapture();
|
|
2438
|
+
const operation = (async () => {
|
|
2439
|
+
try {
|
|
2440
|
+
state = {
|
|
2441
|
+
...state,
|
|
2442
|
+
recordingError: null
|
|
2443
|
+
};
|
|
2444
|
+
notify();
|
|
2445
|
+
await activeCapture.start();
|
|
2446
|
+
if (disposed || generation !== captureGeneration || capture !== activeCapture) {
|
|
2447
|
+
activeCapture.stop();
|
|
2448
|
+
return;
|
|
2449
|
+
}
|
|
2450
|
+
state = {
|
|
2451
|
+
...state,
|
|
2452
|
+
isRecording: true
|
|
2453
|
+
};
|
|
2454
|
+
notify();
|
|
2455
|
+
} catch (error) {
|
|
2456
|
+
activeCapture.stop();
|
|
2457
|
+
if (generation !== captureGeneration || capture !== activeCapture) {
|
|
2458
|
+
throw error;
|
|
2459
|
+
}
|
|
2460
|
+
capture = null;
|
|
2461
|
+
state = {
|
|
2462
|
+
...state,
|
|
2463
|
+
isRecording: false,
|
|
2464
|
+
recordingError: error instanceof Error ? error.message : String(error)
|
|
2465
|
+
};
|
|
2466
|
+
notify();
|
|
2467
|
+
throw error;
|
|
2468
|
+
}
|
|
2469
|
+
})();
|
|
2470
|
+
const pending = operation.finally(() => {
|
|
2471
|
+
if (startRecordingPromise === pending)
|
|
2472
|
+
startRecordingPromise = null;
|
|
2473
|
+
});
|
|
2474
|
+
startRecordingPromise = pending;
|
|
2475
|
+
return startRecordingPromise;
|
|
2344
2476
|
};
|
|
2345
2477
|
const close = (reason) => {
|
|
2478
|
+
disposed = true;
|
|
2346
2479
|
unsubscribeStream();
|
|
2347
2480
|
stopRecording();
|
|
2348
2481
|
stream.close(reason);
|
|
2349
2482
|
};
|
|
2350
2483
|
const disconnect = () => {
|
|
2484
|
+
disposed = true;
|
|
2351
2485
|
unsubscribeStream();
|
|
2352
2486
|
stopRecording();
|
|
2353
2487
|
stream.disconnect();
|
|
@@ -12840,5 +12974,6 @@ export {
|
|
|
12840
12974
|
bindVoiceReactiveSource,
|
|
12841
12975
|
bindVoiceProviderSimulationControls,
|
|
12842
12976
|
bindVoiceHTMX,
|
|
12843
|
-
bindVoiceBargeIn
|
|
12977
|
+
bindVoiceBargeIn,
|
|
12978
|
+
VoiceReconnectRejectedError
|
|
12844
12979
|
};
|
package/dist/core/types.d.ts
CHANGED
|
@@ -1367,7 +1367,11 @@ export type VoiceConnectionOptions = {
|
|
|
1367
1367
|
path: string;
|
|
1368
1368
|
scenarioId: string | null;
|
|
1369
1369
|
sessionId: string;
|
|
1370
|
+
signal: AbortSignal;
|
|
1370
1371
|
}) => Promise<void> | void;
|
|
1372
|
+
/** Maximum time allowed for one prepareReconnect hook. A hook that exceeds
|
|
1373
|
+
* this deadline is aborted and consumes the attempt. Default 10000. */
|
|
1374
|
+
prepareReconnectTimeoutMs?: number;
|
|
1371
1375
|
pingInterval?: number;
|
|
1372
1376
|
/** Additional query values sent on every initial or reconnecting socket. */
|
|
1373
1377
|
query?: Record<string, string>;
|