@voice-ai-labs/web-sdk 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -4
- package/dist/client/agents.d.ts +7 -1
- package/dist/client/agents.d.ts.map +1 -1
- package/dist/client/agents.js +8 -0
- package/dist/client/agents.js.map +1 -1
- package/dist/client/analytics.d.ts +3 -3
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +4 -4
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/base.d.ts +4 -0
- package/dist/client/base.d.ts.map +1 -1
- package/dist/client/base.js +33 -0
- package/dist/client/base.js.map +1 -1
- package/dist/client/tts.d.ts +21 -1
- package/dist/client/tts.d.ts.map +1 -1
- package/dist/client/tts.js +39 -0
- package/dist/client/tts.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +321 -159
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +321 -159
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +93 -9
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -10702,7 +10702,7 @@ function getMatch(exp, ua) {
|
|
|
10702
10702
|
}
|
|
10703
10703
|
function getOSVersion(ua) {
|
|
10704
10704
|
return ua.includes('mac os') ? getMatch(/\(.+?(\d+_\d+(:?_\d+)?)/, ua, 1).replace(/_/g, '.') : undefined;
|
|
10705
|
-
}var version$1 = "2.17.
|
|
10705
|
+
}var version$1 = "2.17.3";const version = version$1;
|
|
10706
10706
|
const protocolVersion = 16;/** Base error that all LiveKit specific custom errors inherit from. */
|
|
10707
10707
|
class LivekitError extends Error {
|
|
10708
10708
|
constructor(code, message, options) {
|
|
@@ -10918,7 +10918,7 @@ var RoomEvent;
|
|
|
10918
10918
|
RoomEvent["Reconnected"] = "reconnected";
|
|
10919
10919
|
/**
|
|
10920
10920
|
* When disconnected from room. This fires when room.disconnect() is called or
|
|
10921
|
-
* when an unrecoverable connection issue had
|
|
10921
|
+
* when an unrecoverable connection issue had occurred.
|
|
10922
10922
|
*
|
|
10923
10923
|
* DisconnectReason can be used to determine why the participant was disconnected. Notable reasons are
|
|
10924
10924
|
* - DUPLICATE_IDENTITY: another client with the same identity has joined the room
|
|
@@ -12628,6 +12628,10 @@ function getEmptyAudioStreamTrack() {
|
|
|
12628
12628
|
}
|
|
12629
12629
|
return emptyAudioStreamTrack.clone();
|
|
12630
12630
|
}
|
|
12631
|
+
/** An object that represents a serialized version of a `new Promise((resolve, reject) => {})`
|
|
12632
|
+
* constructor. Wait for a promise resolution with `await future.promise` and explicitly resolve or
|
|
12633
|
+
* reject the inner promise with `future.resolve(...)` or `future.reject(...)`.
|
|
12634
|
+
*/
|
|
12631
12635
|
class Future {
|
|
12632
12636
|
get isResolved() {
|
|
12633
12637
|
return this._isResolved;
|
|
@@ -12920,6 +12924,7 @@ class BaseKeyProvider extends eventsExports.EventEmitter {
|
|
|
12920
12924
|
constructor() {
|
|
12921
12925
|
let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
12922
12926
|
super();
|
|
12927
|
+
this.latestManuallySetKeyIndex = 0;
|
|
12923
12928
|
/**
|
|
12924
12929
|
* Callback being invoked after a key has been ratcheted.
|
|
12925
12930
|
* Can happen when:
|
|
@@ -12956,11 +12961,17 @@ class BaseKeyProvider extends eventsExports.EventEmitter {
|
|
|
12956
12961
|
throw new Error('participant identity needs to be passed for encryption key if sharedKey option is false');
|
|
12957
12962
|
}
|
|
12958
12963
|
this.keyInfoMap.set("".concat(participantIdentity !== null && participantIdentity !== void 0 ? participantIdentity : 'shared', "-").concat(keyIndex !== null && keyIndex !== void 0 ? keyIndex : 0), keyInfo);
|
|
12959
|
-
|
|
12964
|
+
if (keyIndex !== undefined) {
|
|
12965
|
+
this.latestManuallySetKeyIndex = keyIndex;
|
|
12966
|
+
}
|
|
12967
|
+
this.emit(KeyProviderEvent.SetKey, keyInfo, keyIndex !== undefined);
|
|
12960
12968
|
}
|
|
12961
12969
|
getKeys() {
|
|
12962
12970
|
return Array.from(this.keyInfoMap.values());
|
|
12963
12971
|
}
|
|
12972
|
+
getLatestManuallySetKeyIndex() {
|
|
12973
|
+
return this.latestManuallySetKeyIndex;
|
|
12974
|
+
}
|
|
12964
12975
|
getOptions() {
|
|
12965
12976
|
return this.options;
|
|
12966
12977
|
}
|
|
@@ -13008,14 +13019,14 @@ class E2EEManager extends eventsExports.EventEmitter {
|
|
|
13008
13019
|
case 'initAck':
|
|
13009
13020
|
if (data.enabled) {
|
|
13010
13021
|
this.keyProvider.getKeys().forEach(keyInfo => {
|
|
13011
|
-
this.postKey(keyInfo);
|
|
13022
|
+
this.postKey(keyInfo, false);
|
|
13012
13023
|
});
|
|
13013
13024
|
}
|
|
13014
13025
|
break;
|
|
13015
13026
|
case 'enable':
|
|
13016
13027
|
if (data.enabled) {
|
|
13017
13028
|
this.keyProvider.getKeys().forEach(keyInfo => {
|
|
13018
|
-
this.postKey(keyInfo);
|
|
13029
|
+
this.postKey(keyInfo, false);
|
|
13019
13030
|
});
|
|
13020
13031
|
}
|
|
13021
13032
|
if (this.encryptionEnabled !== data.enabled && data.participantIdentity === ((_a = this.room) === null || _a === void 0 ? void 0 : _a.localParticipant.identity)) {
|
|
@@ -13140,8 +13151,10 @@ class E2EEManager extends eventsExports.EventEmitter {
|
|
|
13140
13151
|
if (!this.room) {
|
|
13141
13152
|
throw new TypeError("expected room to be present on signal connect");
|
|
13142
13153
|
}
|
|
13154
|
+
const latestKeyIndex = keyProvider.getLatestManuallySetKeyIndex();
|
|
13143
13155
|
keyProvider.getKeys().forEach(keyInfo => {
|
|
13144
|
-
|
|
13156
|
+
var _a;
|
|
13157
|
+
this.postKey(keyInfo, latestKeyIndex === ((_a = keyInfo.keyIndex) !== null && _a !== void 0 ? _a : 0));
|
|
13145
13158
|
});
|
|
13146
13159
|
this.setParticipantCryptorEnabled(this.room.localParticipant.isE2EEEnabled, this.room.localParticipant.identity);
|
|
13147
13160
|
});
|
|
@@ -13163,7 +13176,7 @@ class E2EEManager extends eventsExports.EventEmitter {
|
|
|
13163
13176
|
};
|
|
13164
13177
|
this.worker.postMessage(msg);
|
|
13165
13178
|
});
|
|
13166
|
-
keyProvider.on(KeyProviderEvent.SetKey, keyInfo => this.postKey(keyInfo)).on(KeyProviderEvent.RatchetRequest, (participantId, keyIndex) => this.postRatchetRequest(participantId, keyIndex));
|
|
13179
|
+
keyProvider.on(KeyProviderEvent.SetKey, (keyInfo, updateCurrentKeyIndex) => this.postKey(keyInfo, updateCurrentKeyIndex !== null && updateCurrentKeyIndex !== void 0 ? updateCurrentKeyIndex : true)).on(KeyProviderEvent.RatchetRequest, (participantId, keyIndex) => this.postRatchetRequest(participantId, keyIndex));
|
|
13167
13180
|
}
|
|
13168
13181
|
encryptData(data) {
|
|
13169
13182
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -13224,7 +13237,7 @@ class E2EEManager extends eventsExports.EventEmitter {
|
|
|
13224
13237
|
};
|
|
13225
13238
|
this.worker.postMessage(msg);
|
|
13226
13239
|
}
|
|
13227
|
-
postKey(_ref) {
|
|
13240
|
+
postKey(_ref, updateCurrentKeyIndex) {
|
|
13228
13241
|
let {
|
|
13229
13242
|
key,
|
|
13230
13243
|
participantIdentity,
|
|
@@ -13240,7 +13253,8 @@ class E2EEManager extends eventsExports.EventEmitter {
|
|
|
13240
13253
|
participantIdentity: participantIdentity,
|
|
13241
13254
|
isPublisher: participantIdentity === ((_a = this.room) === null || _a === void 0 ? void 0 : _a.localParticipant.identity),
|
|
13242
13255
|
key,
|
|
13243
|
-
keyIndex
|
|
13256
|
+
keyIndex,
|
|
13257
|
+
updateCurrentKeyIndex
|
|
13244
13258
|
}
|
|
13245
13259
|
};
|
|
13246
13260
|
this.worker.postMessage(msg);
|
|
@@ -15356,48 +15370,106 @@ function requireLib() {
|
|
|
15356
15370
|
lib.parseImageAttributes = parser.parseImageAttributes;
|
|
15357
15371
|
lib.parseSimulcastStreamList = parser.parseSimulcastStreamList;
|
|
15358
15372
|
return lib;
|
|
15359
|
-
}var libExports = requireLib()
|
|
15360
|
-
|
|
15361
|
-
|
|
15362
|
-
|
|
15363
|
-
|
|
15364
|
-
|
|
15365
|
-
|
|
15366
|
-
|
|
15367
|
-
|
|
15368
|
-
|
|
15369
|
-
|
|
15370
|
-
|
|
15371
|
-
|
|
15372
|
-
|
|
15373
|
-
|
|
15374
|
-
|
|
15375
|
-
|
|
15376
|
-
|
|
15377
|
-
|
|
15378
|
-
|
|
15379
|
-
|
|
15380
|
-
|
|
15381
|
-
|
|
15382
|
-
|
|
15383
|
-
|
|
15384
|
-
|
|
15385
|
-
|
|
15386
|
-
|
|
15387
|
-
|
|
15388
|
-
|
|
15389
|
-
|
|
15390
|
-
|
|
15391
|
-
|
|
15392
|
-
|
|
15373
|
+
}var libExports = requireLib();/**
|
|
15374
|
+
* Originally from ts-debounce (https://github.com/chodorowicz/ts-debounce)
|
|
15375
|
+
* with the following license:
|
|
15376
|
+
*
|
|
15377
|
+
* MIT License
|
|
15378
|
+
*
|
|
15379
|
+
* Copyright (c) 2017 Jakub Chodorowicz
|
|
15380
|
+
*
|
|
15381
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
15382
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
15383
|
+
* in the Software without restriction, including without limitation the rights
|
|
15384
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15385
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
15386
|
+
* furnished to do so, subject to the following conditions:
|
|
15387
|
+
*
|
|
15388
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
15389
|
+
* copies or substantial portions of the Software.
|
|
15390
|
+
*
|
|
15391
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15392
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15393
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
15394
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
15395
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
15396
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
15397
|
+
* SOFTWARE.
|
|
15398
|
+
*
|
|
15399
|
+
* Modified to use CriticalTimers for reliable timer execution.
|
|
15400
|
+
*/
|
|
15401
|
+
/* eslint-disable @typescript-eslint/no-this-alias, @typescript-eslint/no-unused-expressions, @typescript-eslint/no-shadow */
|
|
15402
|
+
function debounce(func) {
|
|
15403
|
+
let waitMilliseconds = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 50;
|
|
15404
|
+
let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
15405
|
+
var _a, _b;
|
|
15406
|
+
let timeoutId;
|
|
15407
|
+
const isImmediate = (_a = options.isImmediate) !== null && _a !== void 0 ? _a : false;
|
|
15408
|
+
const callback = (_b = options.callback) !== null && _b !== void 0 ? _b : false;
|
|
15409
|
+
const maxWait = options.maxWait;
|
|
15410
|
+
let lastInvokeTime = Date.now();
|
|
15411
|
+
let promises = [];
|
|
15412
|
+
function nextInvokeTimeout() {
|
|
15413
|
+
if (maxWait !== undefined) {
|
|
15414
|
+
const timeSinceLastInvocation = Date.now() - lastInvokeTime;
|
|
15415
|
+
if (timeSinceLastInvocation + waitMilliseconds >= maxWait) {
|
|
15416
|
+
return maxWait - timeSinceLastInvocation;
|
|
15417
|
+
}
|
|
15418
|
+
}
|
|
15419
|
+
return waitMilliseconds;
|
|
15420
|
+
}
|
|
15421
|
+
const debouncedFunction = function () {
|
|
15422
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
15423
|
+
args[_key] = arguments[_key];
|
|
15424
|
+
}
|
|
15425
|
+
const context = this;
|
|
15426
|
+
return new Promise((resolve, reject) => {
|
|
15427
|
+
const invokeFunction = function () {
|
|
15428
|
+
timeoutId = undefined;
|
|
15429
|
+
lastInvokeTime = Date.now();
|
|
15430
|
+
if (!isImmediate) {
|
|
15431
|
+
const result = func.apply(context, args);
|
|
15432
|
+
callback && callback(result);
|
|
15433
|
+
// biome-ignore lint/suspicious/useIterableCallbackReturn: vendored code
|
|
15434
|
+
promises.forEach(_ref => {
|
|
15435
|
+
let {
|
|
15436
|
+
resolve
|
|
15437
|
+
} = _ref;
|
|
15438
|
+
return resolve(result);
|
|
15439
|
+
});
|
|
15440
|
+
promises = [];
|
|
15441
|
+
}
|
|
15442
|
+
};
|
|
15443
|
+
const shouldCallNow = isImmediate && timeoutId === undefined;
|
|
15444
|
+
if (timeoutId !== undefined) {
|
|
15445
|
+
CriticalTimers.clearTimeout(timeoutId);
|
|
15446
|
+
}
|
|
15447
|
+
timeoutId = CriticalTimers.setTimeout(invokeFunction, nextInvokeTimeout());
|
|
15448
|
+
if (shouldCallNow) {
|
|
15449
|
+
const result = func.apply(context, args);
|
|
15450
|
+
callback && callback(result);
|
|
15451
|
+
return resolve(result);
|
|
15452
|
+
}
|
|
15453
|
+
promises.push({
|
|
15454
|
+
resolve,
|
|
15455
|
+
reject
|
|
15393
15456
|
});
|
|
15394
15457
|
});
|
|
15395
15458
|
};
|
|
15396
|
-
|
|
15397
|
-
|
|
15398
|
-
|
|
15399
|
-
}
|
|
15400
|
-
|
|
15459
|
+
debouncedFunction.cancel = function (reason) {
|
|
15460
|
+
if (timeoutId !== undefined) {
|
|
15461
|
+
CriticalTimers.clearTimeout(timeoutId);
|
|
15462
|
+
}
|
|
15463
|
+
// biome-ignore lint/suspicious/useIterableCallbackReturn: vendored code
|
|
15464
|
+
promises.forEach(_ref2 => {
|
|
15465
|
+
let {
|
|
15466
|
+
reject
|
|
15467
|
+
} = _ref2;
|
|
15468
|
+
return reject(reason);
|
|
15469
|
+
});
|
|
15470
|
+
promises = [];
|
|
15471
|
+
};
|
|
15472
|
+
return debouncedFunction;
|
|
15401
15473
|
}/* The svc codec (av1/vp9) would use a very low bitrate at the begining and
|
|
15402
15474
|
increase slowly by the bandwidth estimator until it reach the target bitrate. The
|
|
15403
15475
|
process commonly cost more than 10 seconds cause subscriber will get blur video at
|
|
@@ -15433,7 +15505,7 @@ class PCTransport extends eventsExports.EventEmitter {
|
|
|
15433
15505
|
this.remoteStereoMids = [];
|
|
15434
15506
|
this.remoteNackMids = [];
|
|
15435
15507
|
// debounced negotiate interface
|
|
15436
|
-
this.negotiate =
|
|
15508
|
+
this.negotiate = debounce(onError => __awaiter(this, void 0, void 0, function* () {
|
|
15437
15509
|
this.emit(PCEvents.NegotiationStarted);
|
|
15438
15510
|
try {
|
|
15439
15511
|
yield this.createAndSendOffer();
|
|
@@ -16760,7 +16832,7 @@ class LocalTrack extends Track {
|
|
|
16760
16832
|
this.pendingDeviceChange = false;
|
|
16761
16833
|
this._isUpstreamPaused = false;
|
|
16762
16834
|
this.handleTrackMuteEvent = () => this.debouncedTrackMuteHandler().catch(() => this.log.debug('track mute bounce got cancelled by an unmute event', this.logContext));
|
|
16763
|
-
this.debouncedTrackMuteHandler =
|
|
16835
|
+
this.debouncedTrackMuteHandler = debounce(() => __awaiter(this, void 0, void 0, function* () {
|
|
16764
16836
|
yield this.pauseUpstream();
|
|
16765
16837
|
}), 5000);
|
|
16766
16838
|
this.handleTrackUnmuteEvent = () => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -16832,7 +16904,7 @@ class LocalTrack extends Track {
|
|
|
16832
16904
|
getSourceTrackSettings() {
|
|
16833
16905
|
return this._mediaStreamTrack.getSettings();
|
|
16834
16906
|
}
|
|
16835
|
-
setMediaStreamTrack(newTrack, force) {
|
|
16907
|
+
setMediaStreamTrack(newTrack, force, isUnmuting) {
|
|
16836
16908
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16837
16909
|
var _a;
|
|
16838
16910
|
if (newTrack === this._mediaStreamTrack && !force) {
|
|
@@ -16889,7 +16961,8 @@ class LocalTrack extends Track {
|
|
|
16889
16961
|
this._mediaStreamTrack = newTrack;
|
|
16890
16962
|
if (newTrack) {
|
|
16891
16963
|
// sync muted state with the enabled state of the newly provided track
|
|
16892
|
-
|
|
16964
|
+
// if restarting as part of an unmute, set enabled to true directly to avoid mute cycling
|
|
16965
|
+
this._mediaStreamTrack.enabled = isUnmuting ? true : !this.isMuted;
|
|
16893
16966
|
// when a valid track is replace, we'd want to start producing
|
|
16894
16967
|
yield this.resumeUpstream();
|
|
16895
16968
|
this.attachedElements.forEach(el => {
|
|
@@ -17002,7 +17075,7 @@ class LocalTrack extends Track {
|
|
|
17002
17075
|
}
|
|
17003
17076
|
});
|
|
17004
17077
|
}
|
|
17005
|
-
restart(constraints) {
|
|
17078
|
+
restart(constraints, isUnmuting) {
|
|
17006
17079
|
return __awaiter(this, void 0, void 0, function* () {
|
|
17007
17080
|
this.manuallyStopped = false;
|
|
17008
17081
|
const unlock = yield this.trackChangeLock.lock();
|
|
@@ -17051,7 +17124,7 @@ class LocalTrack extends Track {
|
|
|
17051
17124
|
}
|
|
17052
17125
|
newTrack.addEventListener('ended', this.handleEnded);
|
|
17053
17126
|
this.log.debug('re-acquired MediaStreamTrack', this.logContext);
|
|
17054
|
-
yield this.setMediaStreamTrack(newTrack);
|
|
17127
|
+
yield this.setMediaStreamTrack(newTrack, false, isUnmuting);
|
|
17055
17128
|
this._constraints = constraints;
|
|
17056
17129
|
this.pendingDeviceChange = false;
|
|
17057
17130
|
this.emit(TrackEvent.Restarted, this);
|
|
@@ -17434,7 +17507,7 @@ class LocalTrack extends Track {
|
|
|
17434
17507
|
}
|
|
17435
17508
|
if (this.source === Track.Source.Microphone && (this.stopOnMute || this._mediaStreamTrack.readyState === 'ended' || this.pendingDeviceChange) && !this.isUserProvided) {
|
|
17436
17509
|
this.log.debug('reacquiring mic track', this.logContext);
|
|
17437
|
-
yield this.
|
|
17510
|
+
yield this.restart(undefined, true);
|
|
17438
17511
|
}
|
|
17439
17512
|
yield _super.unmute.call(this);
|
|
17440
17513
|
return this;
|
|
@@ -17457,14 +17530,14 @@ class LocalTrack extends Track {
|
|
|
17457
17530
|
yield this.restart(constraints);
|
|
17458
17531
|
});
|
|
17459
17532
|
}
|
|
17460
|
-
restart(constraints) {
|
|
17533
|
+
restart(constraints, isUnmuting) {
|
|
17461
17534
|
const _super = Object.create(null, {
|
|
17462
17535
|
restart: {
|
|
17463
17536
|
get: () => super.restart
|
|
17464
17537
|
}
|
|
17465
17538
|
});
|
|
17466
17539
|
return __awaiter(this, void 0, void 0, function* () {
|
|
17467
|
-
const track = yield _super.restart.call(this, constraints);
|
|
17540
|
+
const track = yield _super.restart.call(this, constraints, isUnmuting);
|
|
17468
17541
|
this.checkForSilence();
|
|
17469
17542
|
return track;
|
|
17470
17543
|
});
|
|
@@ -18097,7 +18170,7 @@ class LocalVideoTrack extends LocalTrack {
|
|
|
18097
18170
|
}
|
|
18098
18171
|
if (this.source === Track.Source.Camera && !this.isUserProvided) {
|
|
18099
18172
|
this.log.debug('reacquiring camera track', this.logContext);
|
|
18100
|
-
yield this.
|
|
18173
|
+
yield this.restart(undefined, true);
|
|
18101
18174
|
}
|
|
18102
18175
|
yield _super.unmute.call(this);
|
|
18103
18176
|
return this;
|
|
@@ -19989,12 +20062,11 @@ function applyUserDataCompat(newObj, oldObj) {
|
|
|
19989
20062
|
throw new DataStreamError("Extra chunk(s) received - expected ".concat(this.totalByteSize, " bytes of data total, received ").concat(this.bytesReceived, " bytes"), DataStreamErrorReason.LengthExceeded);
|
|
19990
20063
|
}
|
|
19991
20064
|
}
|
|
19992
|
-
constructor(info, stream, totalByteSize
|
|
20065
|
+
constructor(info, stream, totalByteSize) {
|
|
19993
20066
|
this.reader = stream;
|
|
19994
20067
|
this.totalByteSize = totalByteSize;
|
|
19995
20068
|
this._info = info;
|
|
19996
20069
|
this.bytesReceived = 0;
|
|
19997
|
-
this.outOfBandFailureRejectingFuture = outOfBandFailureRejectingFuture;
|
|
19998
20070
|
}
|
|
19999
20071
|
}
|
|
20000
20072
|
class ByteStreamReader extends BaseStreamReader {
|
|
@@ -20007,50 +20079,44 @@ class ByteStreamReader extends BaseStreamReader {
|
|
|
20007
20079
|
}
|
|
20008
20080
|
[Symbol.asyncIterator]() {
|
|
20009
20081
|
const reader = this.reader.getReader();
|
|
20010
|
-
|
|
20011
|
-
|
|
20012
|
-
|
|
20013
|
-
if (this.signal) {
|
|
20014
|
-
const signal = this.signal;
|
|
20015
|
-
onAbort = () => {
|
|
20016
|
-
var _a;
|
|
20017
|
-
(_a = rejectingSignalFuture.reject) === null || _a === void 0 ? void 0 : _a.call(rejectingSignalFuture, signal.reason);
|
|
20018
|
-
};
|
|
20019
|
-
signal.addEventListener('abort', onAbort);
|
|
20020
|
-
activeSignal = signal;
|
|
20021
|
-
}
|
|
20082
|
+
// Suppress unhandled rejection on reader.closed — errors are
|
|
20083
|
+
// already propagated through reader.read() to the consumer.
|
|
20084
|
+
reader.closed.catch(() => {});
|
|
20022
20085
|
const cleanup = () => {
|
|
20023
20086
|
reader.releaseLock();
|
|
20024
|
-
if (activeSignal && onAbort) {
|
|
20025
|
-
activeSignal.removeEventListener('abort', onAbort);
|
|
20026
|
-
}
|
|
20027
20087
|
this.signal = undefined;
|
|
20028
20088
|
};
|
|
20029
20089
|
return {
|
|
20030
20090
|
next: () => __awaiter(this, void 0, void 0, function* () {
|
|
20031
|
-
var _a, _b;
|
|
20032
20091
|
try {
|
|
20033
|
-
const
|
|
20034
|
-
|
|
20035
|
-
|
|
20036
|
-
}
|
|
20037
|
-
|
|
20038
|
-
|
|
20039
|
-
|
|
20040
|
-
|
|
20041
|
-
|
|
20042
|
-
|
|
20043
|
-
|
|
20092
|
+
const signal = this.signal;
|
|
20093
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
20094
|
+
throw signal.reason;
|
|
20095
|
+
}
|
|
20096
|
+
const result = yield new Promise((resolve, reject) => {
|
|
20097
|
+
if (signal) {
|
|
20098
|
+
const onAbort = () => reject(signal.reason);
|
|
20099
|
+
signal.addEventListener('abort', onAbort, {
|
|
20100
|
+
once: true
|
|
20101
|
+
});
|
|
20102
|
+
reader.read().then(resolve, reject).finally(() => {
|
|
20103
|
+
signal.removeEventListener('abort', onAbort);
|
|
20104
|
+
});
|
|
20105
|
+
} else {
|
|
20106
|
+
reader.read().then(resolve, reject);
|
|
20107
|
+
}
|
|
20108
|
+
});
|
|
20109
|
+
if (result.done) {
|
|
20044
20110
|
this.validateBytesReceived(true);
|
|
20045
20111
|
return {
|
|
20046
20112
|
done: true,
|
|
20047
20113
|
value: undefined
|
|
20048
20114
|
};
|
|
20049
20115
|
} else {
|
|
20050
|
-
this.handleChunkReceived(value);
|
|
20116
|
+
this.handleChunkReceived(result.value);
|
|
20051
20117
|
return {
|
|
20052
20118
|
done: false,
|
|
20053
|
-
value: value.content
|
|
20119
|
+
value: result.value.content
|
|
20054
20120
|
};
|
|
20055
20121
|
}
|
|
20056
20122
|
} catch (err) {
|
|
@@ -20121,8 +20187,8 @@ class TextStreamReader extends BaseStreamReader {
|
|
|
20121
20187
|
* A TextStreamReader instance can be used as an AsyncIterator that returns the entire string
|
|
20122
20188
|
* that has been received up to the current point in time.
|
|
20123
20189
|
*/
|
|
20124
|
-
constructor(info, stream, totalChunkCount
|
|
20125
|
-
super(info, stream, totalChunkCount
|
|
20190
|
+
constructor(info, stream, totalChunkCount) {
|
|
20191
|
+
super(info, stream, totalChunkCount);
|
|
20126
20192
|
this.receivedChunks = new Map();
|
|
20127
20193
|
}
|
|
20128
20194
|
handleChunkReceived(chunk) {
|
|
@@ -20146,55 +20212,49 @@ class TextStreamReader extends BaseStreamReader {
|
|
|
20146
20212
|
*/
|
|
20147
20213
|
[Symbol.asyncIterator]() {
|
|
20148
20214
|
const reader = this.reader.getReader();
|
|
20215
|
+
// Suppress unhandled rejection on reader.closed — errors are
|
|
20216
|
+
// already propagated through reader.read() to the consumer.
|
|
20217
|
+
reader.closed.catch(() => {});
|
|
20149
20218
|
const decoder = new TextDecoder('utf-8', {
|
|
20150
20219
|
fatal: true
|
|
20151
20220
|
});
|
|
20152
|
-
|
|
20153
|
-
let activeSignal = null;
|
|
20154
|
-
let onAbort = null;
|
|
20155
|
-
if (this.signal) {
|
|
20156
|
-
const signal = this.signal;
|
|
20157
|
-
onAbort = () => {
|
|
20158
|
-
var _a;
|
|
20159
|
-
(_a = rejectingSignalFuture.reject) === null || _a === void 0 ? void 0 : _a.call(rejectingSignalFuture, signal.reason);
|
|
20160
|
-
};
|
|
20161
|
-
signal.addEventListener('abort', onAbort);
|
|
20162
|
-
activeSignal = signal;
|
|
20163
|
-
}
|
|
20221
|
+
const signal = this.signal;
|
|
20164
20222
|
const cleanup = () => {
|
|
20165
20223
|
reader.releaseLock();
|
|
20166
|
-
if (activeSignal && onAbort) {
|
|
20167
|
-
activeSignal.removeEventListener('abort', onAbort);
|
|
20168
|
-
}
|
|
20169
20224
|
this.signal = undefined;
|
|
20170
20225
|
};
|
|
20171
20226
|
return {
|
|
20172
20227
|
next: () => __awaiter(this, void 0, void 0, function* () {
|
|
20173
|
-
var _a, _b;
|
|
20174
20228
|
try {
|
|
20175
|
-
|
|
20176
|
-
|
|
20177
|
-
|
|
20178
|
-
|
|
20179
|
-
|
|
20180
|
-
|
|
20181
|
-
|
|
20182
|
-
|
|
20183
|
-
|
|
20184
|
-
|
|
20185
|
-
|
|
20229
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
20230
|
+
throw signal.reason;
|
|
20231
|
+
}
|
|
20232
|
+
const result = yield new Promise((resolve, reject) => {
|
|
20233
|
+
if (signal) {
|
|
20234
|
+
const onAbort = () => reject(signal.reason);
|
|
20235
|
+
signal.addEventListener('abort', onAbort, {
|
|
20236
|
+
once: true
|
|
20237
|
+
});
|
|
20238
|
+
reader.read().then(resolve, reject).finally(() => {
|
|
20239
|
+
signal.removeEventListener('abort', onAbort);
|
|
20240
|
+
});
|
|
20241
|
+
} else {
|
|
20242
|
+
reader.read().then(resolve, reject);
|
|
20243
|
+
}
|
|
20244
|
+
});
|
|
20245
|
+
if (result.done) {
|
|
20186
20246
|
this.validateBytesReceived(true);
|
|
20187
20247
|
return {
|
|
20188
20248
|
done: true,
|
|
20189
20249
|
value: undefined
|
|
20190
20250
|
};
|
|
20191
20251
|
} else {
|
|
20192
|
-
this.handleChunkReceived(value);
|
|
20252
|
+
this.handleChunkReceived(result.value);
|
|
20193
20253
|
let decodedResult;
|
|
20194
20254
|
try {
|
|
20195
|
-
decodedResult = decoder.decode(value.content);
|
|
20255
|
+
decodedResult = decoder.decode(result.value.content);
|
|
20196
20256
|
} catch (err) {
|
|
20197
|
-
throw new DataStreamError("Cannot decode datastream chunk ".concat(value.chunkIndex, " as text: ").concat(err), DataStreamErrorReason.DecodeFailed);
|
|
20257
|
+
throw new DataStreamError("Cannot decode datastream chunk ".concat(result.value.chunkIndex, " as text: ").concat(err), DataStreamErrorReason.DecodeFailed);
|
|
20198
20258
|
}
|
|
20199
20259
|
return {
|
|
20200
20260
|
done: false,
|
|
@@ -20291,18 +20351,17 @@ class TextStreamReader extends BaseStreamReader {
|
|
|
20291
20351
|
this.textStreamControllers.clear();
|
|
20292
20352
|
}
|
|
20293
20353
|
validateParticipantHasNoActiveDataStreams(participantIdentity) {
|
|
20294
|
-
var _a, _b, _c, _d;
|
|
20295
20354
|
// Terminate any in flight data stream receives from the given participant
|
|
20296
20355
|
const textStreamsBeingSentByDisconnectingParticipant = Array.from(this.textStreamControllers.entries()).filter(entry => entry[1].sendingParticipantIdentity === participantIdentity);
|
|
20297
20356
|
const byteStreamsBeingSentByDisconnectingParticipant = Array.from(this.byteStreamControllers.entries()).filter(entry => entry[1].sendingParticipantIdentity === participantIdentity);
|
|
20298
20357
|
if (textStreamsBeingSentByDisconnectingParticipant.length > 0 || byteStreamsBeingSentByDisconnectingParticipant.length > 0) {
|
|
20299
20358
|
const abnormalEndError = new DataStreamError("Participant ".concat(participantIdentity, " unexpectedly disconnected in the middle of sending data"), DataStreamErrorReason.AbnormalEnd);
|
|
20300
20359
|
for (const [id, controller] of byteStreamsBeingSentByDisconnectingParticipant) {
|
|
20301
|
-
|
|
20360
|
+
controller.controller.error(abnormalEndError);
|
|
20302
20361
|
this.byteStreamControllers.delete(id);
|
|
20303
20362
|
}
|
|
20304
20363
|
for (const [id, controller] of textStreamsBeingSentByDisconnectingParticipant) {
|
|
20305
|
-
|
|
20364
|
+
controller.controller.error(abnormalEndError);
|
|
20306
20365
|
this.textStreamControllers.delete(id);
|
|
20307
20366
|
}
|
|
20308
20367
|
}
|
|
@@ -20331,10 +20390,6 @@ class TextStreamReader extends BaseStreamReader {
|
|
|
20331
20390
|
return;
|
|
20332
20391
|
}
|
|
20333
20392
|
let streamController;
|
|
20334
|
-
const outOfBandFailureRejectingFuture = new Future();
|
|
20335
|
-
outOfBandFailureRejectingFuture.promise.catch(err => {
|
|
20336
|
-
this.log.error(err);
|
|
20337
|
-
});
|
|
20338
20393
|
const info = {
|
|
20339
20394
|
id: streamHeader.streamId,
|
|
20340
20395
|
name: (_a = streamHeader.contentHeader.value.name) !== null && _a !== void 0 ? _a : 'unknown',
|
|
@@ -20355,12 +20410,11 @@ class TextStreamReader extends BaseStreamReader {
|
|
|
20355
20410
|
info,
|
|
20356
20411
|
controller: streamController,
|
|
20357
20412
|
startTime: Date.now(),
|
|
20358
|
-
sendingParticipantIdentity: participantIdentity
|
|
20359
|
-
outOfBandFailureRejectingFuture
|
|
20413
|
+
sendingParticipantIdentity: participantIdentity
|
|
20360
20414
|
});
|
|
20361
20415
|
}
|
|
20362
20416
|
});
|
|
20363
|
-
streamHandlerCallback(new ByteStreamReader(info, stream, bigIntToNumber(streamHeader.totalLength)
|
|
20417
|
+
streamHandlerCallback(new ByteStreamReader(info, stream, bigIntToNumber(streamHeader.totalLength)), {
|
|
20364
20418
|
identity: participantIdentity
|
|
20365
20419
|
});
|
|
20366
20420
|
} else if (streamHeader.contentHeader.case === 'textHeader') {
|
|
@@ -20370,10 +20424,6 @@ class TextStreamReader extends BaseStreamReader {
|
|
|
20370
20424
|
return;
|
|
20371
20425
|
}
|
|
20372
20426
|
let streamController;
|
|
20373
|
-
const outOfBandFailureRejectingFuture = new Future();
|
|
20374
|
-
outOfBandFailureRejectingFuture.promise.catch(err => {
|
|
20375
|
-
this.log.error(err);
|
|
20376
|
-
});
|
|
20377
20427
|
const info = {
|
|
20378
20428
|
id: streamHeader.streamId,
|
|
20379
20429
|
mimeType: streamHeader.mimeType,
|
|
@@ -20394,12 +20444,11 @@ class TextStreamReader extends BaseStreamReader {
|
|
|
20394
20444
|
info,
|
|
20395
20445
|
controller: streamController,
|
|
20396
20446
|
startTime: Date.now(),
|
|
20397
|
-
sendingParticipantIdentity: participantIdentity
|
|
20398
|
-
outOfBandFailureRejectingFuture
|
|
20447
|
+
sendingParticipantIdentity: participantIdentity
|
|
20399
20448
|
});
|
|
20400
20449
|
}
|
|
20401
20450
|
});
|
|
20402
|
-
streamHandlerCallback(new TextStreamReader(info, stream, bigIntToNumber(streamHeader.totalLength)
|
|
20451
|
+
streamHandlerCallback(new TextStreamReader(info, stream, bigIntToNumber(streamHeader.totalLength)), {
|
|
20403
20452
|
identity: participantIdentity
|
|
20404
20453
|
});
|
|
20405
20454
|
}
|
|
@@ -21079,7 +21128,7 @@ class RemoteVideoTrack extends RemoteTrack {
|
|
|
21079
21128
|
}
|
|
21080
21129
|
this.prevStats = stats;
|
|
21081
21130
|
});
|
|
21082
|
-
this.debouncedHandleResize =
|
|
21131
|
+
this.debouncedHandleResize = debounce(() => {
|
|
21083
21132
|
this.updateDimensions();
|
|
21084
21133
|
}, REACTION_DELAY);
|
|
21085
21134
|
this.adaptiveStreamSettings = adaptiveStreamSettings;
|
|
@@ -22066,6 +22115,8 @@ class Participant extends eventsExports.EventEmitter {
|
|
|
22066
22115
|
this.handleClosing = () => {
|
|
22067
22116
|
var _a, _b, _c, _d, _e, _f;
|
|
22068
22117
|
if (this.reconnectFuture) {
|
|
22118
|
+
// @throws-transformer ignore - introduced due to adding Throws into Future, investigate this
|
|
22119
|
+
// further
|
|
22069
22120
|
this.reconnectFuture.promise.catch(e => this.log.warn(e.message, this.logContext));
|
|
22070
22121
|
(_b = (_a = this.reconnectFuture) === null || _a === void 0 ? void 0 : _a.reject) === null || _b === void 0 ? void 0 : _b.call(_a, new Error('Got disconnected during reconnection attempt'));
|
|
22071
22122
|
this.reconnectFuture = undefined;
|
|
@@ -24423,7 +24474,7 @@ class Room extends eventsExports.EventEmitter {
|
|
|
24423
24474
|
}
|
|
24424
24475
|
if (nextUrl && !((_b = this.abortController) === null || _b === void 0 ? void 0 : _b.signal.aborted)) {
|
|
24425
24476
|
this.log.info("Initial connection failed with ConnectionError: ".concat(error.message, ". Retrying with another region: ").concat(nextUrl), this.logContext);
|
|
24426
|
-
this.recreateEngine();
|
|
24477
|
+
this.recreateEngine(true);
|
|
24427
24478
|
yield connectFn(resolve, reject, nextUrl);
|
|
24428
24479
|
} else {
|
|
24429
24480
|
this.handleDisconnect(this.options.stopLocalTrackOnUnpublish, getDisconnectReasonFromConnectionError(error));
|
|
@@ -24508,7 +24559,7 @@ class Room extends eventsExports.EventEmitter {
|
|
|
24508
24559
|
if (this.state === ConnectionState.Reconnecting || this.isResuming || ((_a = this.engine) === null || _a === void 0 ? void 0 : _a.pendingReconnect)) {
|
|
24509
24560
|
this.log.info('Reconnection attempt replaced by new connection attempt', this.logContext);
|
|
24510
24561
|
// make sure we close and recreate the existing engine in order to get rid of any potentially ongoing reconnection attempts
|
|
24511
|
-
this.recreateEngine();
|
|
24562
|
+
this.recreateEngine(true);
|
|
24512
24563
|
} else {
|
|
24513
24564
|
// create engine if previously disconnected
|
|
24514
24565
|
this.maybeCreateEngine();
|
|
@@ -25621,9 +25672,13 @@ class Room extends eventsExports.EventEmitter {
|
|
|
25621
25672
|
setupLocalParticipantEvents() {
|
|
25622
25673
|
this.localParticipant.on(ParticipantEvent.ParticipantMetadataChanged, this.onLocalParticipantMetadataChanged).on(ParticipantEvent.ParticipantNameChanged, this.onLocalParticipantNameChanged).on(ParticipantEvent.AttributesChanged, this.onLocalAttributesChanged).on(ParticipantEvent.TrackMuted, this.onLocalTrackMuted).on(ParticipantEvent.TrackUnmuted, this.onLocalTrackUnmuted).on(ParticipantEvent.LocalTrackPublished, this.onLocalTrackPublished).on(ParticipantEvent.LocalTrackUnpublished, this.onLocalTrackUnpublished).on(ParticipantEvent.ConnectionQualityChanged, this.onLocalConnectionQualityChanged).on(ParticipantEvent.MediaDevicesError, this.onMediaDevicesError).on(ParticipantEvent.AudioStreamAcquired, this.startAudio).on(ParticipantEvent.ChatMessage, this.onLocalChatMessageSent).on(ParticipantEvent.ParticipantPermissionsChanged, this.onLocalParticipantPermissionsChanged);
|
|
25623
25674
|
}
|
|
25624
|
-
recreateEngine() {
|
|
25625
|
-
|
|
25626
|
-
(
|
|
25675
|
+
recreateEngine(sendLeave) {
|
|
25676
|
+
const oldEngine = this.engine;
|
|
25677
|
+
if (sendLeave && oldEngine && !oldEngine.client.isDisconnected) {
|
|
25678
|
+
oldEngine.client.sendLeave().finally(() => oldEngine.close());
|
|
25679
|
+
} else {
|
|
25680
|
+
oldEngine === null || oldEngine === void 0 ? void 0 : oldEngine.close();
|
|
25681
|
+
}
|
|
25627
25682
|
/* @ts-ignore */
|
|
25628
25683
|
this.engine = undefined;
|
|
25629
25684
|
this.isResuming = false;
|
|
@@ -26289,7 +26344,39 @@ var DataTrackDepacketizerDropReason;
|
|
|
26289
26344
|
DataTrackDepacketizerDropReason[DataTrackDepacketizerDropReason["UnknownFrame"] = 1] = "UnknownFrame";
|
|
26290
26345
|
DataTrackDepacketizerDropReason[DataTrackDepacketizerDropReason["BufferFull"] = 2] = "BufferFull";
|
|
26291
26346
|
DataTrackDepacketizerDropReason[DataTrackDepacketizerDropReason["Incomplete"] = 3] = "Incomplete";
|
|
26292
|
-
})(DataTrackDepacketizerDropReason || (DataTrackDepacketizerDropReason = {}));var
|
|
26347
|
+
})(DataTrackDepacketizerDropReason || (DataTrackDepacketizerDropReason = {}));var DataTrackPublishErrorReason;
|
|
26348
|
+
(function (DataTrackPublishErrorReason) {
|
|
26349
|
+
/**
|
|
26350
|
+
* Local participant does not have permission to publish data tracks.
|
|
26351
|
+
*
|
|
26352
|
+
* Ensure the participant's token contains the `canPublishData` grant.
|
|
26353
|
+
*/
|
|
26354
|
+
DataTrackPublishErrorReason[DataTrackPublishErrorReason["NotAllowed"] = 0] = "NotAllowed";
|
|
26355
|
+
/** A track with the same name is already published by the local participant. */
|
|
26356
|
+
DataTrackPublishErrorReason[DataTrackPublishErrorReason["DuplicateName"] = 1] = "DuplicateName";
|
|
26357
|
+
/** Request to publish the track took long to complete. */
|
|
26358
|
+
DataTrackPublishErrorReason[DataTrackPublishErrorReason["Timeout"] = 2] = "Timeout";
|
|
26359
|
+
/** No additional data tracks can be published by the local participant. */
|
|
26360
|
+
DataTrackPublishErrorReason[DataTrackPublishErrorReason["LimitReached"] = 3] = "LimitReached";
|
|
26361
|
+
/** Cannot publish data track when the room is disconnected. */
|
|
26362
|
+
DataTrackPublishErrorReason[DataTrackPublishErrorReason["Disconnected"] = 4] = "Disconnected";
|
|
26363
|
+
// NOTE: this was introduced by web / there isn't a corresponding case in the rust version.
|
|
26364
|
+
DataTrackPublishErrorReason[DataTrackPublishErrorReason["Cancelled"] = 5] = "Cancelled";
|
|
26365
|
+
})(DataTrackPublishErrorReason || (DataTrackPublishErrorReason = {}));
|
|
26366
|
+
var DataTrackPushFrameErrorReason;
|
|
26367
|
+
(function (DataTrackPushFrameErrorReason) {
|
|
26368
|
+
/** Track is no longer published. */
|
|
26369
|
+
DataTrackPushFrameErrorReason[DataTrackPushFrameErrorReason["TrackUnpublished"] = 0] = "TrackUnpublished";
|
|
26370
|
+
/** Frame was dropped. */
|
|
26371
|
+
// NOTE: this should become a web specific error, the rust version of this "dropped" error means
|
|
26372
|
+
// something different and will be renamed to "QueueFull".
|
|
26373
|
+
DataTrackPushFrameErrorReason[DataTrackPushFrameErrorReason["Dropped"] = 1] = "Dropped";
|
|
26374
|
+
})(DataTrackPushFrameErrorReason || (DataTrackPushFrameErrorReason = {}));
|
|
26375
|
+
var DataTrackOutgoingPipelineErrorReason;
|
|
26376
|
+
(function (DataTrackOutgoingPipelineErrorReason) {
|
|
26377
|
+
DataTrackOutgoingPipelineErrorReason[DataTrackOutgoingPipelineErrorReason["Packetizer"] = 0] = "Packetizer";
|
|
26378
|
+
DataTrackOutgoingPipelineErrorReason[DataTrackOutgoingPipelineErrorReason["Encryption"] = 1] = "Encryption";
|
|
26379
|
+
})(DataTrackOutgoingPipelineErrorReason || (DataTrackOutgoingPipelineErrorReason = {}));getLogger(LoggerNames.DataTracks);var CheckStatus;
|
|
26293
26380
|
(function (CheckStatus) {
|
|
26294
26381
|
CheckStatus[CheckStatus["IDLE"] = 0] = "IDLE";
|
|
26295
26382
|
CheckStatus[CheckStatus["RUNNING"] = 1] = "RUNNING";
|
|
@@ -27316,6 +27403,39 @@ class BaseClient {
|
|
|
27316
27403
|
});
|
|
27317
27404
|
return this.handleResponse(response);
|
|
27318
27405
|
}
|
|
27406
|
+
/**
|
|
27407
|
+
* Perform GET request that returns binary data (Blob)
|
|
27408
|
+
*/
|
|
27409
|
+
async getForBlob(path, params) {
|
|
27410
|
+
const url = new URL(`${this.apiUrl}${path}`);
|
|
27411
|
+
if (params) {
|
|
27412
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
27413
|
+
if (value !== undefined && value !== null) {
|
|
27414
|
+
if (Array.isArray(value)) {
|
|
27415
|
+
value.forEach(v => url.searchParams.append(key, String(v)));
|
|
27416
|
+
}
|
|
27417
|
+
else {
|
|
27418
|
+
url.searchParams.append(key, String(value));
|
|
27419
|
+
}
|
|
27420
|
+
}
|
|
27421
|
+
});
|
|
27422
|
+
}
|
|
27423
|
+
const response = await fetch(url.toString(), {
|
|
27424
|
+
method: 'GET',
|
|
27425
|
+
headers: this.getHeaders(),
|
|
27426
|
+
});
|
|
27427
|
+
if (!response.ok) {
|
|
27428
|
+
let errorData = null;
|
|
27429
|
+
try {
|
|
27430
|
+
errorData = await response.json();
|
|
27431
|
+
}
|
|
27432
|
+
catch {
|
|
27433
|
+
// Not JSON
|
|
27434
|
+
}
|
|
27435
|
+
throw new VoiceAIError(errorData?.error || errorData?.detail || `Request failed with status ${response.status}`, response.status, errorData?.code);
|
|
27436
|
+
}
|
|
27437
|
+
return response.blob();
|
|
27438
|
+
}
|
|
27319
27439
|
/**
|
|
27320
27440
|
* Perform POST request
|
|
27321
27441
|
*/
|
|
@@ -27621,6 +27741,14 @@ class AgentClient extends BaseClient {
|
|
|
27621
27741
|
async getStatus(agentId) {
|
|
27622
27742
|
return super.get(`/connection/agent-status/${encodeURIComponent(agentId)}`);
|
|
27623
27743
|
}
|
|
27744
|
+
/**
|
|
27745
|
+
* Create an outbound call for an agent.
|
|
27746
|
+
*
|
|
27747
|
+
* Requires backend-side credentials (service token or dev API key).
|
|
27748
|
+
*/
|
|
27749
|
+
async createOutboundCall(options) {
|
|
27750
|
+
return this.post('/calls/outbound', options);
|
|
27751
|
+
}
|
|
27624
27752
|
/**
|
|
27625
27753
|
* Assign a knowledge base to an agent for RAG
|
|
27626
27754
|
*
|
|
@@ -27714,19 +27842,19 @@ class AnalyticsClient extends BaseClient {
|
|
|
27714
27842
|
/**
|
|
27715
27843
|
* Get transcript download URL for a call
|
|
27716
27844
|
*
|
|
27717
|
-
* @param
|
|
27845
|
+
* @param callId - The call identifier
|
|
27718
27846
|
* @returns Object with transcript URL
|
|
27719
27847
|
*
|
|
27720
27848
|
* @example
|
|
27721
27849
|
* ```typescript
|
|
27722
|
-
* const { url } = await client.analytics.getTranscriptUrl(
|
|
27850
|
+
* const { url } = await client.analytics.getTranscriptUrl("call_12345");
|
|
27723
27851
|
*
|
|
27724
27852
|
* // Download transcript
|
|
27725
27853
|
* window.open(url, '_blank');
|
|
27726
27854
|
* ```
|
|
27727
27855
|
*/
|
|
27728
|
-
async getTranscriptUrl(
|
|
27729
|
-
return this.get(`/agent/call-history/${
|
|
27856
|
+
async getTranscriptUrl(callId) {
|
|
27857
|
+
return this.get(`/agent/call-history/${callId}/transcript`);
|
|
27730
27858
|
}
|
|
27731
27859
|
/**
|
|
27732
27860
|
* Get agent stats summary
|
|
@@ -28270,6 +28398,45 @@ class TTSClient extends BaseClient {
|
|
|
28270
28398
|
async deleteVoice(voiceId) {
|
|
28271
28399
|
return this.httpDelete(`/tts/voice/${encodeURIComponent(voiceId)}`);
|
|
28272
28400
|
}
|
|
28401
|
+
// ==========================================================================
|
|
28402
|
+
// PRONUNCIATION DICTIONARY MANAGEMENT
|
|
28403
|
+
// ==========================================================================
|
|
28404
|
+
async listPronunciationDictionaries() {
|
|
28405
|
+
return this.get('/tts/pronunciation-dictionaries');
|
|
28406
|
+
}
|
|
28407
|
+
async getPronunciationDictionary(dictionaryId) {
|
|
28408
|
+
return this.get(`/tts/pronunciation-dictionaries/${encodeURIComponent(dictionaryId)}`);
|
|
28409
|
+
}
|
|
28410
|
+
async createPronunciationDictionaryFromFile(options) {
|
|
28411
|
+
const formData = new FormData();
|
|
28412
|
+
formData.append('file', options.file);
|
|
28413
|
+
formData.append('name', options.name);
|
|
28414
|
+
if (options.language !== undefined) {
|
|
28415
|
+
formData.append('language', options.language);
|
|
28416
|
+
}
|
|
28417
|
+
return this.postFormData('/tts/pronunciation-dictionaries/add-from-file', formData);
|
|
28418
|
+
}
|
|
28419
|
+
async createPronunciationDictionaryFromRules(options) {
|
|
28420
|
+
return this.post('/tts/pronunciation-dictionaries/add-from-rules', options);
|
|
28421
|
+
}
|
|
28422
|
+
async updatePronunciationDictionary(dictionaryId, options) {
|
|
28423
|
+
return this.patch(`/tts/pronunciation-dictionaries/${encodeURIComponent(dictionaryId)}`, options);
|
|
28424
|
+
}
|
|
28425
|
+
async deletePronunciationDictionary(dictionaryId) {
|
|
28426
|
+
return this.httpDelete(`/tts/pronunciation-dictionaries/${encodeURIComponent(dictionaryId)}`);
|
|
28427
|
+
}
|
|
28428
|
+
async downloadPronunciationDictionaryVersion(dictionaryId, version) {
|
|
28429
|
+
return this.getForBlob(`/tts/pronunciation-dictionaries/${encodeURIComponent(dictionaryId)}/${version}/download`);
|
|
28430
|
+
}
|
|
28431
|
+
async setPronunciationDictionaryRules(dictionaryId, rules) {
|
|
28432
|
+
return this.post(`/tts/pronunciation-dictionaries/${encodeURIComponent(dictionaryId)}/set-rules`, { rules });
|
|
28433
|
+
}
|
|
28434
|
+
async addPronunciationDictionaryRules(dictionaryId, rules) {
|
|
28435
|
+
return this.post(`/tts/pronunciation-dictionaries/${encodeURIComponent(dictionaryId)}/add-rules`, { rules });
|
|
28436
|
+
}
|
|
28437
|
+
async removePronunciationDictionaryRules(dictionaryId, ruleIds) {
|
|
28438
|
+
return this.post(`/tts/pronunciation-dictionaries/${encodeURIComponent(dictionaryId)}/remove-rules`, { rule_ids: ruleIds });
|
|
28439
|
+
}
|
|
28273
28440
|
}
|
|
28274
28441
|
|
|
28275
28442
|
/**
|
|
@@ -29171,19 +29338,14 @@ class VoiceAI {
|
|
|
29171
29338
|
? '/connection/test-connection-details'
|
|
29172
29339
|
: '/connection/connection-details';
|
|
29173
29340
|
const endpoint = `${url}${endpointPath}`;
|
|
29341
|
+
if (!options.agentId) {
|
|
29342
|
+
throw new Error('agentId is required.');
|
|
29343
|
+
}
|
|
29174
29344
|
const requestData = {};
|
|
29175
29345
|
if (options.agentId)
|
|
29176
29346
|
requestData.agent_id = options.agentId;
|
|
29177
|
-
if (options.
|
|
29178
|
-
requestData.
|
|
29179
|
-
}
|
|
29180
|
-
else if (options.metadata) {
|
|
29181
|
-
requestData.metadata = options.metadata;
|
|
29182
|
-
}
|
|
29183
|
-
if (options.environment) {
|
|
29184
|
-
requestData.environment = typeof options.environment === 'string'
|
|
29185
|
-
? options.environment
|
|
29186
|
-
: JSON.stringify(options.environment);
|
|
29347
|
+
if (options.dynamicVariables) {
|
|
29348
|
+
requestData.dynamic_variables = options.dynamicVariables;
|
|
29187
29349
|
}
|
|
29188
29350
|
const apiKey = options.apiKey || this.apiKey;
|
|
29189
29351
|
this.effectiveApiKey = apiKey;
|