@cuekit-ai/react 1.3.4 → 1.5.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.
@@ -8836,6 +8836,23 @@ var SignalRequestError = class extends LivekitError {
8836
8836
  this.reasonName = typeof reason === "string" ? reason : RequestResponse_Reason[reason];
8837
8837
  }
8838
8838
  };
8839
+ var DataStreamErrorReason;
8840
+ (function(DataStreamErrorReason2) {
8841
+ DataStreamErrorReason2[DataStreamErrorReason2["AlreadyOpened"] = 0] = "AlreadyOpened";
8842
+ DataStreamErrorReason2[DataStreamErrorReason2["AbnormalEnd"] = 1] = "AbnormalEnd";
8843
+ DataStreamErrorReason2[DataStreamErrorReason2["DecodeFailed"] = 2] = "DecodeFailed";
8844
+ DataStreamErrorReason2[DataStreamErrorReason2["LengthExceeded"] = 3] = "LengthExceeded";
8845
+ DataStreamErrorReason2[DataStreamErrorReason2["Incomplete"] = 4] = "Incomplete";
8846
+ DataStreamErrorReason2[DataStreamErrorReason2["HandlerAlreadyRegistered"] = 7] = "HandlerAlreadyRegistered";
8847
+ })(DataStreamErrorReason || (DataStreamErrorReason = {}));
8848
+ var DataStreamError = class extends LivekitError {
8849
+ constructor(message, reason) {
8850
+ super(16, message);
8851
+ this.name = "DataStreamError";
8852
+ this.reason = reason;
8853
+ this.reasonName = DataStreamErrorReason[reason];
8854
+ }
8855
+ };
8839
8856
  var MediaDeviceFailure;
8840
8857
  (function(MediaDeviceFailure2) {
8841
8858
  MediaDeviceFailure2["PermissionDenied"] = "PermissionDenied";
@@ -9092,7 +9109,7 @@ function getMatch(exp, ua) {
9092
9109
  function getOSVersion(ua) {
9093
9110
  return ua.includes("mac os") ? getMatch(/\(.+?(\d+_\d+(:?_\d+)?)/, ua, 1).replace(/_/g, ".") : void 0;
9094
9111
  }
9095
- var version$1 = "2.15.4";
9112
+ var version$1 = "2.15.6";
9096
9113
  var version = version$1;
9097
9114
  var protocolVersion = 16;
9098
9115
  var CriticalTimers = class {
@@ -9119,13 +9136,24 @@ var VideoQuality;
9119
9136
  VideoQuality2[VideoQuality2["HIGH"] = 2] = "HIGH";
9120
9137
  })(VideoQuality || (VideoQuality = {}));
9121
9138
  var Track = class _Track extends eventsExports.EventEmitter {
9139
+ /**
9140
+ * indicates current state of stream, it'll indicate `paused` if the track
9141
+ * has been paused by congestion controller
9142
+ */
9143
+ get streamState() {
9144
+ return this._streamState;
9145
+ }
9146
+ /** @internal */
9147
+ setStreamState(value) {
9148
+ this._streamState = value;
9149
+ }
9122
9150
  constructor(mediaTrack, kind) {
9123
9151
  let loggerOptions = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {};
9124
9152
  var _a;
9125
9153
  super();
9126
9154
  this.attachedElements = [];
9127
9155
  this.isMuted = false;
9128
- this.streamState = _Track.StreamState.Active;
9156
+ this._streamState = _Track.StreamState.Active;
9129
9157
  this.isInBackground = false;
9130
9158
  this._currentBitrate = 0;
9131
9159
  this.log = livekitLogger;
@@ -9561,7 +9589,7 @@ function supportsAV1() {
9561
9589
  if (!("getCapabilities" in RTCRtpSender)) {
9562
9590
  return false;
9563
9591
  }
9564
- if (isSafari()) {
9592
+ if (isSafari() || isFireFox()) {
9565
9593
  return false;
9566
9594
  }
9567
9595
  const capabilities = RTCRtpSender.getCapabilities("video");
@@ -9658,9 +9686,9 @@ function isE2EESimulcastSupported() {
9658
9686
  if (browser) {
9659
9687
  if (browser.name !== "Safari" && browser.os !== "iOS") {
9660
9688
  return true;
9661
- } else if (browser.os === "iOS" && browser.osVersion && compareVersions(supportedSafariVersion, browser.osVersion) >= 0) {
9689
+ } else if (browser.os === "iOS" && browser.osVersion && compareVersions(browser.osVersion, supportedSafariVersion) >= 0) {
9662
9690
  return true;
9663
- } else if (browser.name === "Safari" && compareVersions(supportedSafariVersion, browser.version) >= 0) {
9691
+ } else if (browser.name === "Safari" && compareVersions(browser.version, supportedSafariVersion) >= 0) {
9664
9692
  return true;
9665
9693
  } else {
9666
9694
  return false;
@@ -9875,13 +9903,13 @@ function unwrapConstraint(constraint) {
9875
9903
  if (Array.isArray(constraint)) {
9876
9904
  return constraint[0];
9877
9905
  }
9878
- if (constraint.exact) {
9906
+ if (constraint.exact !== void 0) {
9879
9907
  if (Array.isArray(constraint.exact)) {
9880
9908
  return constraint.exact[0];
9881
9909
  }
9882
9910
  return constraint.exact;
9883
9911
  }
9884
- if (constraint.ideal) {
9912
+ if (constraint.ideal !== void 0) {
9885
9913
  if (Array.isArray(constraint.ideal)) {
9886
9914
  return constraint.ideal[0];
9887
9915
  }
@@ -10104,7 +10132,7 @@ function constraintsForOptions(options) {
10104
10132
  function detectSilence(track_1) {
10105
10133
  return __awaiter(this, arguments, void 0, function(track) {
10106
10134
  let timeOffset = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 200;
10107
- return function* () {
10135
+ return (function* () {
10108
10136
  const ctx = getNewAudioContext();
10109
10137
  if (ctx) {
10110
10138
  const analyser = ctx.createAnalyser();
@@ -10120,7 +10148,7 @@ function detectSilence(track_1) {
10120
10148
  return !someNoise;
10121
10149
  }
10122
10150
  return false;
10123
- }();
10151
+ })();
10124
10152
  });
10125
10153
  }
10126
10154
  function getNewAudioContext() {
@@ -10447,6 +10475,20 @@ var E2EEManager = class extends eventsExports.EventEmitter {
10447
10475
  room2.localParticipant.on(ParticipantEvent.LocalSenderCreated, (sender, track) => __awaiter(this, void 0, void 0, function* () {
10448
10476
  this.setupE2EESender(track, sender);
10449
10477
  }));
10478
+ room2.localParticipant.on(ParticipantEvent.LocalTrackPublished, (publication) => {
10479
+ if (!isVideoTrack(publication.track) || !isSafariBased()) {
10480
+ return;
10481
+ }
10482
+ const msg = {
10483
+ kind: "updateCodec",
10484
+ data: {
10485
+ trackId: publication.track.mediaStreamID,
10486
+ codec: mimeTypeToVideoCodecString(publication.trackInfo.codecs[0].mimeType),
10487
+ participantIdentity: this.room.localParticipant.identity
10488
+ }
10489
+ };
10490
+ this.worker.postMessage(msg);
10491
+ });
10450
10492
  keyProvider.on(KeyProviderEvent.SetKey, (keyInfo) => this.postKey(keyInfo)).on(KeyProviderEvent.RatchetRequest, (participantId, keyIndex) => this.postRatchetRequest(participantId, keyIndex));
10451
10493
  }
10452
10494
  postRatchetRequest(participantIdentity, keyIndex) {
@@ -10657,7 +10699,7 @@ var DeviceManager = class _DeviceManager {
10657
10699
  return __awaiter(this, arguments, void 0, function(kind) {
10658
10700
  var _this = this;
10659
10701
  let requestPermissions = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true;
10660
- return function* () {
10702
+ return (function* () {
10661
10703
  var _a;
10662
10704
  if (((_a = _DeviceManager.userMediaPromiseMap) === null || _a === void 0 ? void 0 : _a.size) > 0) {
10663
10705
  livekitLogger.debug("awaiting getUserMedia promise");
@@ -10700,7 +10742,7 @@ var DeviceManager = class _DeviceManager {
10700
10742
  devices = devices.filter((device) => device.kind === kind);
10701
10743
  }
10702
10744
  return devices;
10703
- }();
10745
+ })();
10704
10746
  });
10705
10747
  }
10706
10748
  normalizeDeviceId(kind, deviceId, groupId) {
@@ -11009,7 +11051,7 @@ var SignalClient = class {
11009
11051
  return __awaiter(this, arguments, void 0, function() {
11010
11052
  var _this = this;
11011
11053
  let updateState = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : true;
11012
- return function* () {
11054
+ return (function* () {
11013
11055
  const unlock = yield _this.closingLock.lock();
11014
11056
  try {
11015
11057
  _this.clearPingInterval();
@@ -11041,7 +11083,7 @@ var SignalClient = class {
11041
11083
  }
11042
11084
  unlock();
11043
11085
  }
11044
- }();
11086
+ })();
11045
11087
  });
11046
11088
  }
11047
11089
  // initial offer after joining
@@ -11095,7 +11137,7 @@ var SignalClient = class {
11095
11137
  return __awaiter(this, arguments, void 0, function(metadata, name) {
11096
11138
  var _this2 = this;
11097
11139
  let attributes = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {};
11098
- return function* () {
11140
+ return (function* () {
11099
11141
  const requestId = _this2.getNextRequestId();
11100
11142
  yield _this2.sendRequest({
11101
11143
  case: "updateMetadata",
@@ -11107,7 +11149,7 @@ var SignalClient = class {
11107
11149
  })
11108
11150
  });
11109
11151
  return requestId;
11110
- }();
11152
+ })();
11111
11153
  });
11112
11154
  }
11113
11155
  sendUpdateTrackSettings(settings) {
@@ -11187,7 +11229,7 @@ var SignalClient = class {
11187
11229
  return __awaiter(this, arguments, void 0, function(message) {
11188
11230
  var _this3 = this;
11189
11231
  let fromQueue = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false;
11190
- return function* () {
11232
+ return (function* () {
11191
11233
  const canQueue = !fromQueue && !canPassThroughQueue(message);
11192
11234
  if (canQueue && _this3.state === SignalConnectionState.RECONNECTING) {
11193
11235
  _this3.queuedRequests.push(() => __awaiter(_this3, void 0, void 0, function* () {
@@ -11223,7 +11265,7 @@ var SignalClient = class {
11223
11265
  error: e2
11224
11266
  }));
11225
11267
  }
11226
- }();
11268
+ })();
11227
11269
  });
11228
11270
  }
11229
11271
  handleSignalResponse(res) {
@@ -13172,7 +13214,7 @@ var PCTransportManager = class {
13172
13214
  return __awaiter(this, arguments, void 0, function(pcTransport, abortController) {
13173
13215
  var _this = this;
13174
13216
  let timeout = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : this.peerConnectionTimeout;
13175
- return function* () {
13217
+ return (function* () {
13176
13218
  const connectionState = pcTransport.getConnectionState();
13177
13219
  if (connectionState === "connected") {
13178
13220
  return;
@@ -13202,7 +13244,7 @@ var PCTransportManager = class {
13202
13244
  abortController === null || abortController === void 0 ? void 0 : abortController.signal.removeEventListener("abort", abortHandler);
13203
13245
  resolve();
13204
13246
  }));
13205
- }();
13247
+ })();
13206
13248
  });
13207
13249
  }
13208
13250
  };
@@ -13425,9 +13467,14 @@ var LocalTrack = class extends Track {
13425
13467
  this.providedByUser = userProvidedTrack;
13426
13468
  this.muteLock = new _();
13427
13469
  this.pauseUpstreamLock = new _();
13428
- this.processorLock = new _();
13429
- this.restartLock = new _();
13430
- this.setMediaStreamTrack(mediaTrack, true);
13470
+ this.trackChangeLock = new _();
13471
+ this.trackChangeLock.lock().then((unlock) => __awaiter(this, void 0, void 0, function* () {
13472
+ try {
13473
+ yield this.setMediaStreamTrack(mediaTrack, true);
13474
+ } finally {
13475
+ unlock();
13476
+ }
13477
+ }));
13431
13478
  this._constraints = mediaTrack.getConstraints();
13432
13479
  if (constraints) {
13433
13480
  this._constraints = constraints;
@@ -13496,25 +13543,20 @@ var LocalTrack = class extends Track {
13496
13543
  }
13497
13544
  let processedTrack;
13498
13545
  if (this.processor && newTrack) {
13499
- const unlock = yield this.processorLock.lock();
13500
- try {
13501
- this.log.debug("restarting processor", this.logContext);
13502
- if (this.kind === "unknown") {
13503
- throw TypeError("cannot set processor on track of unknown kind");
13504
- }
13505
- if (this.processorElement) {
13506
- attachToElement(newTrack, this.processorElement);
13507
- this.processorElement.muted = true;
13508
- }
13509
- yield this.processor.restart({
13510
- track: newTrack,
13511
- kind: this.kind,
13512
- element: this.processorElement
13513
- });
13514
- processedTrack = this.processor.processedTrack;
13515
- } finally {
13516
- unlock();
13546
+ this.log.debug("restarting processor", this.logContext);
13547
+ if (this.kind === "unknown") {
13548
+ throw TypeError("cannot set processor on track of unknown kind");
13549
+ }
13550
+ if (this.processorElement) {
13551
+ attachToElement(newTrack, this.processorElement);
13552
+ this.processorElement.muted = true;
13517
13553
  }
13554
+ yield this.processor.restart({
13555
+ track: newTrack,
13556
+ kind: this.kind,
13557
+ element: this.processorElement
13558
+ });
13559
+ processedTrack = this.processor.processedTrack;
13518
13560
  }
13519
13561
  if (this.sender && ((_a = this.sender.transport) === null || _a === void 0 ? void 0 : _a.state) !== "closed") {
13520
13562
  yield this.sender.replaceTrack(processedTrack !== null && processedTrack !== void 0 ? processedTrack : newTrack);
@@ -13536,7 +13578,7 @@ var LocalTrack = class extends Track {
13536
13578
  return __awaiter(this, arguments, void 0, function() {
13537
13579
  var _this = this;
13538
13580
  let timeout = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : DEFAULT_DIMENSIONS_TIMEOUT;
13539
- return function* () {
13581
+ return (function* () {
13540
13582
  var _a;
13541
13583
  if (_this.kind === Track.Kind.Audio) {
13542
13584
  throw new Error("cannot get dimensions for audio tracks");
@@ -13553,7 +13595,7 @@ var LocalTrack = class extends Track {
13553
13595
  yield sleep(50);
13554
13596
  }
13555
13597
  throw new TrackInvalidError("unable to get track dimensions after timeout");
13556
- }();
13598
+ })();
13557
13599
  });
13558
13600
  }
13559
13601
  setDeviceId(deviceId) {
@@ -13576,7 +13618,7 @@ var LocalTrack = class extends Track {
13576
13618
  return __awaiter(this, arguments, void 0, function() {
13577
13619
  var _this2 = this;
13578
13620
  let normalize = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : true;
13579
- return function* () {
13621
+ return (function* () {
13580
13622
  if (_this2.source === Track.Source.ScreenShare) {
13581
13623
  return;
13582
13624
  }
@@ -13586,7 +13628,7 @@ var LocalTrack = class extends Track {
13586
13628
  } = _this2._mediaStreamTrack.getSettings();
13587
13629
  const kind = _this2.kind === Track.Kind.Audio ? "audioinput" : "videoinput";
13588
13630
  return normalize ? DeviceManager.getInstance().normalizeDeviceId(kind, deviceId, groupId) : deviceId;
13589
- }();
13631
+ })();
13590
13632
  });
13591
13633
  }
13592
13634
  mute() {
@@ -13603,30 +13645,35 @@ var LocalTrack = class extends Track {
13603
13645
  }
13604
13646
  replaceTrack(track, userProvidedOrOptions) {
13605
13647
  return __awaiter(this, void 0, void 0, function* () {
13606
- if (!this.sender) {
13607
- throw new TrackInvalidError("unable to replace an unpublished track");
13608
- }
13609
- let userProvidedTrack;
13610
- let stopProcessor;
13611
- if (typeof userProvidedOrOptions === "boolean") {
13612
- userProvidedTrack = userProvidedOrOptions;
13613
- } else if (userProvidedOrOptions !== void 0) {
13614
- userProvidedTrack = userProvidedOrOptions.userProvidedTrack;
13615
- stopProcessor = userProvidedOrOptions.stopProcessor;
13616
- }
13617
- this.providedByUser = userProvidedTrack !== null && userProvidedTrack !== void 0 ? userProvidedTrack : true;
13618
- this.log.debug("replace MediaStreamTrack", this.logContext);
13619
- yield this.setMediaStreamTrack(track);
13620
- if (stopProcessor && this.processor) {
13621
- yield this.stopProcessor();
13648
+ const unlock = yield this.trackChangeLock.lock();
13649
+ try {
13650
+ if (!this.sender) {
13651
+ throw new TrackInvalidError("unable to replace an unpublished track");
13652
+ }
13653
+ let userProvidedTrack;
13654
+ let stopProcessor;
13655
+ if (typeof userProvidedOrOptions === "boolean") {
13656
+ userProvidedTrack = userProvidedOrOptions;
13657
+ } else if (userProvidedOrOptions !== void 0) {
13658
+ userProvidedTrack = userProvidedOrOptions.userProvidedTrack;
13659
+ stopProcessor = userProvidedOrOptions.stopProcessor;
13660
+ }
13661
+ this.providedByUser = userProvidedTrack !== null && userProvidedTrack !== void 0 ? userProvidedTrack : true;
13662
+ this.log.debug("replace MediaStreamTrack", this.logContext);
13663
+ yield this.setMediaStreamTrack(track);
13664
+ if (stopProcessor && this.processor) {
13665
+ yield this.internalStopProcessor();
13666
+ }
13667
+ return this;
13668
+ } finally {
13669
+ unlock();
13622
13670
  }
13623
- return this;
13624
13671
  });
13625
13672
  }
13626
13673
  restart(constraints) {
13627
13674
  return __awaiter(this, void 0, void 0, function* () {
13628
13675
  this.manuallyStopped = false;
13629
- const unlock = yield this.restartLock.lock();
13676
+ const unlock = yield this.trackChangeLock.lock();
13630
13677
  try {
13631
13678
  if (!constraints) {
13632
13679
  constraints = this._constraints;
@@ -13648,9 +13695,9 @@ var LocalTrack = class extends Track {
13648
13695
  facingMode
13649
13696
  } : true;
13650
13697
  } else {
13651
- streamConstraints.audio = deviceId ? {
13698
+ streamConstraints.audio = deviceId ? Object.assign({
13652
13699
  deviceId
13653
- } : true;
13700
+ }, otherConstraints) : true;
13654
13701
  }
13655
13702
  this.attachedElements.forEach((el) => {
13656
13703
  detachTrack(this.mediaStreamTrack, el);
@@ -13659,7 +13706,9 @@ var LocalTrack = class extends Track {
13659
13706
  this._mediaStreamTrack.stop();
13660
13707
  const mediaStream = yield navigator.mediaDevices.getUserMedia(streamConstraints);
13661
13708
  const newTrack = mediaStream.getTracks()[0];
13662
- yield newTrack.applyConstraints(otherConstraints);
13709
+ if (this.kind === Track.Kind.Video) {
13710
+ yield newTrack.applyConstraints(otherConstraints);
13711
+ }
13663
13712
  newTrack.addEventListener("ended", this.handleEnded);
13664
13713
  this.log.debug("re-acquired MediaStreamTrack", this.logContext);
13665
13714
  yield this.setMediaStreamTrack(newTrack);
@@ -13798,9 +13847,9 @@ var LocalTrack = class extends Track {
13798
13847
  return __awaiter(this, arguments, void 0, function(processor) {
13799
13848
  var _this3 = this;
13800
13849
  let showProcessedStreamLocally = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true;
13801
- return function* () {
13850
+ return (function* () {
13802
13851
  var _a;
13803
- const unlock = yield _this3.processorLock.lock();
13852
+ const unlock = yield _this3.trackChangeLock.lock();
13804
13853
  try {
13805
13854
  _this3.log.debug("setting up processor", _this3.logContext);
13806
13855
  const processorElement = document.createElement(_this3.kind);
@@ -13813,7 +13862,7 @@ var LocalTrack = class extends Track {
13813
13862
  yield processor.init(processorOptions);
13814
13863
  _this3.log.debug("processor initialized", _this3.logContext);
13815
13864
  if (_this3.processor) {
13816
- yield _this3.stopProcessor();
13865
+ yield _this3.internalStopProcessor();
13817
13866
  }
13818
13867
  if (_this3.kind === "unknown") {
13819
13868
  throw TypeError("cannot set processor on track of unknown kind");
@@ -13853,7 +13902,7 @@ var LocalTrack = class extends Track {
13853
13902
  } finally {
13854
13903
  unlock();
13855
13904
  }
13856
- }();
13905
+ })();
13857
13906
  });
13858
13907
  }
13859
13908
  getProcessor() {
@@ -13870,21 +13919,40 @@ var LocalTrack = class extends Track {
13870
13919
  return __awaiter(this, arguments, void 0, function() {
13871
13920
  var _this4 = this;
13872
13921
  let keepElement = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : true;
13873
- return function* () {
13922
+ return (function* () {
13923
+ const unlock = yield _this4.trackChangeLock.lock();
13924
+ try {
13925
+ yield _this4.internalStopProcessor(keepElement);
13926
+ } finally {
13927
+ unlock();
13928
+ }
13929
+ })();
13930
+ });
13931
+ }
13932
+ /**
13933
+ * @internal
13934
+ * This method assumes the caller has acquired a trackChangeLock already.
13935
+ * The public facing method for stopping the processor is `stopProcessor` and it wraps this method in the trackChangeLock.
13936
+ */
13937
+ internalStopProcessor() {
13938
+ return __awaiter(this, arguments, void 0, function() {
13939
+ var _this5 = this;
13940
+ let keepElement = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : true;
13941
+ return (function* () {
13874
13942
  var _a, _b;
13875
- if (!_this4.processor) return;
13876
- _this4.log.debug("stopping processor", _this4.logContext);
13877
- (_a = _this4.processor.processedTrack) === null || _a === void 0 ? void 0 : _a.stop();
13878
- yield _this4.processor.destroy();
13879
- _this4.processor = void 0;
13943
+ if (!_this5.processor) return;
13944
+ _this5.log.debug("stopping processor", _this5.logContext);
13945
+ (_a = _this5.processor.processedTrack) === null || _a === void 0 ? void 0 : _a.stop();
13946
+ yield _this5.processor.destroy();
13947
+ _this5.processor = void 0;
13880
13948
  if (!keepElement) {
13881
- (_b = _this4.processorElement) === null || _b === void 0 ? void 0 : _b.remove();
13882
- _this4.processorElement = void 0;
13949
+ (_b = _this5.processorElement) === null || _b === void 0 ? void 0 : _b.remove();
13950
+ _this5.processorElement = void 0;
13883
13951
  }
13884
- yield _this4._mediaStreamTrack.applyConstraints(_this4._constraints);
13885
- yield _this4.setMediaStreamTrack(_this4._mediaStreamTrack, true);
13886
- _this4.emit(TrackEvent.TrackProcessorUpdate);
13887
- }();
13952
+ yield _this5._mediaStreamTrack.applyConstraints(_this5._constraints);
13953
+ yield _this5.setMediaStreamTrack(_this5._mediaStreamTrack, true);
13954
+ _this5.emit(TrackEvent.TrackProcessorUpdate);
13955
+ })();
13888
13956
  });
13889
13957
  }
13890
13958
  /** @internal */
@@ -14072,13 +14140,13 @@ var LocalAudioTrack = class extends LocalTrack {
14072
14140
  setProcessor(processor) {
14073
14141
  return __awaiter(this, void 0, void 0, function* () {
14074
14142
  var _a;
14075
- const unlock = yield this.processorLock.lock();
14143
+ const unlock = yield this.trackChangeLock.lock();
14076
14144
  try {
14077
14145
  if (!isReactNative() && !this.audioContext) {
14078
14146
  throw Error("Audio context needs to be set on LocalAudioTrack in order to enable processors");
14079
14147
  }
14080
14148
  if (this.processor) {
14081
- yield this.stopProcessor();
14149
+ yield this.internalStopProcessor();
14082
14150
  }
14083
14151
  const processorOptions = {
14084
14152
  kind: this.kind,
@@ -14733,7 +14801,7 @@ var LocalVideoTrack = class extends LocalTrack {
14733
14801
  return __awaiter(this, arguments, void 0, function(processor) {
14734
14802
  var _this = this;
14735
14803
  let showProcessedStreamLocally = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true;
14736
- return function* () {
14804
+ return (function* () {
14737
14805
  var _a, e_4, _b, _c;
14738
14806
  var _d, _e;
14739
14807
  yield _super.setProcessor.call(_this, processor, showProcessedStreamLocally);
@@ -14757,7 +14825,7 @@ var LocalVideoTrack = class extends LocalTrack {
14757
14825
  }
14758
14826
  }
14759
14827
  }
14760
- }();
14828
+ })();
14761
14829
  });
14762
14830
  }
14763
14831
  setDegradationPreference(preference) {
@@ -15108,7 +15176,7 @@ var RTCEngine = class extends eventsExports.EventEmitter {
15108
15176
  let {
15109
15177
  channel
15110
15178
  } = _ref;
15111
- return function* () {
15179
+ return (function* () {
15112
15180
  if (!channel) {
15113
15181
  return;
15114
15182
  }
@@ -15121,7 +15189,7 @@ var RTCEngine = class extends eventsExports.EventEmitter {
15121
15189
  }
15122
15190
  _this.log.debug("on data channel ".concat(channel.id, ", ").concat(channel.label), _this.logContext);
15123
15191
  channel.onmessage = _this.handleDataMessage;
15124
- }();
15192
+ })();
15125
15193
  });
15126
15194
  this.handleDataMessage = (message) => __awaiter(this, void 0, void 0, function* () {
15127
15195
  var _a2, _b;
@@ -16004,7 +16072,7 @@ var RTCEngine = class extends eventsExports.EventEmitter {
16004
16072
  return __awaiter(this, arguments, void 0, function(kind) {
16005
16073
  var _this2 = this;
16006
16074
  let subscriber = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : this.subscriberPrimary;
16007
- return function* () {
16075
+ return (function* () {
16008
16076
  var _a;
16009
16077
  if (!_this2.pcManager) {
16010
16078
  throw new UnexpectedConnectionState("PC manager is closed");
@@ -16037,7 +16105,7 @@ var RTCEngine = class extends eventsExports.EventEmitter {
16037
16105
  yield sleep(50);
16038
16106
  }
16039
16107
  throw new ConnectionError("could not establish ".concat(transportName, " connection, state: ").concat(transport.getICEConnectionState()), ConnectionErrorReason.InternalError);
16040
- }();
16108
+ })();
16041
16109
  });
16042
16110
  }
16043
16111
  ensurePublisherConnected(kind) {
@@ -16294,30 +16362,72 @@ var BaseStreamReader = class {
16294
16362
  get info() {
16295
16363
  return this._info;
16296
16364
  }
16297
- constructor(info, stream, totalByteSize) {
16365
+ /** @internal */
16366
+ validateBytesReceived() {
16367
+ let doneReceiving = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : false;
16368
+ if (typeof this.totalByteSize !== "number" || this.totalByteSize === 0) {
16369
+ return;
16370
+ }
16371
+ if (doneReceiving && this.bytesReceived < this.totalByteSize) {
16372
+ throw new DataStreamError("Not enough chunk(s) received - expected ".concat(this.totalByteSize, " bytes of data total, only received ").concat(this.bytesReceived, " bytes"), DataStreamErrorReason.Incomplete);
16373
+ } else if (this.bytesReceived > this.totalByteSize) {
16374
+ throw new DataStreamError("Extra chunk(s) received - expected ".concat(this.totalByteSize, " bytes of data total, received ").concat(this.bytesReceived, " bytes"), DataStreamErrorReason.LengthExceeded);
16375
+ }
16376
+ }
16377
+ constructor(info, stream, totalByteSize, outOfBandFailureRejectingFuture) {
16298
16378
  this.reader = stream;
16299
16379
  this.totalByteSize = totalByteSize;
16300
16380
  this._info = info;
16301
16381
  this.bytesReceived = 0;
16382
+ this.outOfBandFailureRejectingFuture = outOfBandFailureRejectingFuture;
16302
16383
  }
16303
16384
  };
16304
16385
  var ByteStreamReader = class extends BaseStreamReader {
16305
16386
  handleChunkReceived(chunk) {
16306
16387
  var _a;
16307
16388
  this.bytesReceived += chunk.content.byteLength;
16389
+ this.validateBytesReceived();
16308
16390
  const currentProgress = this.totalByteSize ? this.bytesReceived / this.totalByteSize : void 0;
16309
16391
  (_a = this.onProgress) === null || _a === void 0 ? void 0 : _a.call(this, currentProgress);
16310
16392
  }
16311
16393
  [Symbol.asyncIterator]() {
16312
16394
  const reader = this.reader.getReader();
16395
+ let rejectingSignalFuture = new Future();
16396
+ let activeSignal = null;
16397
+ let onAbort = null;
16398
+ if (this.signal) {
16399
+ const signal = this.signal;
16400
+ onAbort = () => {
16401
+ var _a;
16402
+ (_a = rejectingSignalFuture.reject) === null || _a === void 0 ? void 0 : _a.call(rejectingSignalFuture, signal.reason);
16403
+ };
16404
+ signal.addEventListener("abort", onAbort);
16405
+ activeSignal = signal;
16406
+ }
16407
+ const cleanup = () => {
16408
+ reader.releaseLock();
16409
+ if (activeSignal && onAbort) {
16410
+ activeSignal.removeEventListener("abort", onAbort);
16411
+ }
16412
+ this.signal = void 0;
16413
+ };
16313
16414
  return {
16314
16415
  next: () => __awaiter(this, void 0, void 0, function* () {
16416
+ var _a, _b;
16315
16417
  try {
16316
16418
  const {
16317
16419
  done,
16318
16420
  value
16319
- } = yield reader.read();
16421
+ } = yield Promise.race([
16422
+ reader.read(),
16423
+ // Rejects if this.signal is aborted
16424
+ rejectingSignalFuture.promise,
16425
+ // Rejects if something external says it should, like a participant disconnecting, etc
16426
+ (_b = (_a = this.outOfBandFailureRejectingFuture) === null || _a === void 0 ? void 0 : _a.promise) !== null && _b !== void 0 ? _b : new Promise(() => {
16427
+ })
16428
+ ]);
16320
16429
  if (done) {
16430
+ this.validateBytesReceived(true);
16321
16431
  return {
16322
16432
  done: true,
16323
16433
  value: void 0
@@ -16329,16 +16439,16 @@ var ByteStreamReader = class extends BaseStreamReader {
16329
16439
  value: value.content
16330
16440
  };
16331
16441
  }
16332
- } catch (error) {
16333
- return {
16334
- done: true,
16335
- value: void 0
16336
- };
16442
+ } catch (err) {
16443
+ cleanup();
16444
+ throw err;
16337
16445
  }
16338
16446
  }),
16447
+ // note: `return` runs only for premature exits, see:
16448
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#errors_during_iteration
16339
16449
  return() {
16340
16450
  return __awaiter(this, void 0, void 0, function* () {
16341
- reader.releaseLock();
16451
+ cleanup();
16342
16452
  return {
16343
16453
  done: true,
16344
16454
  value: void 0
@@ -16347,29 +16457,45 @@ var ByteStreamReader = class extends BaseStreamReader {
16347
16457
  }
16348
16458
  };
16349
16459
  }
16460
+ /**
16461
+ * Injects an AbortSignal, which if aborted, will terminate the currently active
16462
+ * stream iteration operation.
16463
+ *
16464
+ * Note that when using AbortSignal.timeout(...), the timeout applies across
16465
+ * the whole iteration operation, not just one individual chunk read.
16466
+ */
16467
+ withAbortSignal(signal) {
16468
+ this.signal = signal;
16469
+ return this;
16470
+ }
16350
16471
  readAll() {
16351
- return __awaiter(this, void 0, void 0, function* () {
16352
- var _a, e_1, _b, _c;
16353
- let chunks = /* @__PURE__ */ new Set();
16354
- try {
16355
- for (var _d = true, _e = __asyncValues(this), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
16356
- _c = _f.value;
16357
- _d = false;
16358
- const chunk = _c;
16359
- chunks.add(chunk);
16360
- }
16361
- } catch (e_1_1) {
16362
- e_1 = {
16363
- error: e_1_1
16364
- };
16365
- } finally {
16472
+ return __awaiter(this, arguments, void 0, function() {
16473
+ var _this = this;
16474
+ let opts = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
16475
+ return (function* () {
16476
+ var _a, e_1, _b, _c;
16477
+ let chunks = /* @__PURE__ */ new Set();
16478
+ const iterator = opts.signal ? _this.withAbortSignal(opts.signal) : _this;
16366
16479
  try {
16367
- if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
16480
+ for (var _d = true, iterator_1 = __asyncValues(iterator), iterator_1_1; iterator_1_1 = yield iterator_1.next(), _a = iterator_1_1.done, !_a; _d = true) {
16481
+ _c = iterator_1_1.value;
16482
+ _d = false;
16483
+ const chunk = _c;
16484
+ chunks.add(chunk);
16485
+ }
16486
+ } catch (e_1_1) {
16487
+ e_1 = {
16488
+ error: e_1_1
16489
+ };
16368
16490
  } finally {
16369
- if (e_1) throw e_1.error;
16491
+ try {
16492
+ if (!_d && !_a && (_b = iterator_1.return)) yield _b.call(iterator_1);
16493
+ } finally {
16494
+ if (e_1) throw e_1.error;
16495
+ }
16370
16496
  }
16371
- }
16372
- return Array.from(chunks);
16497
+ return Array.from(chunks);
16498
+ })();
16373
16499
  });
16374
16500
  }
16375
16501
  };
@@ -16378,8 +16504,8 @@ var TextStreamReader = class extends BaseStreamReader {
16378
16504
  * A TextStreamReader instance can be used as an AsyncIterator that returns the entire string
16379
16505
  * that has been received up to the current point in time.
16380
16506
  */
16381
- constructor(info, stream, totalChunkCount) {
16382
- super(info, stream, totalChunkCount);
16507
+ constructor(info, stream, totalChunkCount, outOfBandFailureRejectingFuture) {
16508
+ super(info, stream, totalChunkCount, outOfBandFailureRejectingFuture);
16383
16509
  this.receivedChunks = /* @__PURE__ */ new Map();
16384
16510
  }
16385
16511
  handleChunkReceived(chunk) {
@@ -16391,6 +16517,7 @@ var TextStreamReader = class extends BaseStreamReader {
16391
16517
  }
16392
16518
  this.receivedChunks.set(index, chunk);
16393
16519
  this.bytesReceived += chunk.content.byteLength;
16520
+ this.validateBytesReceived();
16394
16521
  const currentProgress = this.totalByteSize ? this.bytesReceived / this.totalByteSize : void 0;
16395
16522
  (_a = this.onProgress) === null || _a === void 0 ? void 0 : _a.call(this, currentProgress);
16396
16523
  }
@@ -16401,36 +16528,72 @@ var TextStreamReader = class extends BaseStreamReader {
16401
16528
  */
16402
16529
  [Symbol.asyncIterator]() {
16403
16530
  const reader = this.reader.getReader();
16404
- const decoder = new TextDecoder();
16531
+ const decoder = new TextDecoder("utf-8", {
16532
+ fatal: true
16533
+ });
16534
+ let rejectingSignalFuture = new Future();
16535
+ let activeSignal = null;
16536
+ let onAbort = null;
16537
+ if (this.signal) {
16538
+ const signal = this.signal;
16539
+ onAbort = () => {
16540
+ var _a;
16541
+ (_a = rejectingSignalFuture.reject) === null || _a === void 0 ? void 0 : _a.call(rejectingSignalFuture, signal.reason);
16542
+ };
16543
+ signal.addEventListener("abort", onAbort);
16544
+ activeSignal = signal;
16545
+ }
16546
+ const cleanup = () => {
16547
+ reader.releaseLock();
16548
+ if (activeSignal && onAbort) {
16549
+ activeSignal.removeEventListener("abort", onAbort);
16550
+ }
16551
+ this.signal = void 0;
16552
+ };
16405
16553
  return {
16406
16554
  next: () => __awaiter(this, void 0, void 0, function* () {
16555
+ var _a, _b;
16407
16556
  try {
16408
16557
  const {
16409
16558
  done,
16410
16559
  value
16411
- } = yield reader.read();
16560
+ } = yield Promise.race([
16561
+ reader.read(),
16562
+ // Rejects if this.signal is aborted
16563
+ rejectingSignalFuture.promise,
16564
+ // Rejects if something external says it should, like a participant disconnecting, etc
16565
+ (_b = (_a = this.outOfBandFailureRejectingFuture) === null || _a === void 0 ? void 0 : _a.promise) !== null && _b !== void 0 ? _b : new Promise(() => {
16566
+ })
16567
+ ]);
16412
16568
  if (done) {
16569
+ this.validateBytesReceived(true);
16413
16570
  return {
16414
16571
  done: true,
16415
16572
  value: void 0
16416
16573
  };
16417
16574
  } else {
16418
16575
  this.handleChunkReceived(value);
16576
+ let decodedResult;
16577
+ try {
16578
+ decodedResult = decoder.decode(value.content);
16579
+ } catch (err) {
16580
+ throw new DataStreamError("Cannot decode datastream chunk ".concat(value.chunkIndex, " as text: ").concat(err), DataStreamErrorReason.DecodeFailed);
16581
+ }
16419
16582
  return {
16420
16583
  done: false,
16421
- value: decoder.decode(value.content)
16584
+ value: decodedResult
16422
16585
  };
16423
16586
  }
16424
- } catch (error) {
16425
- return {
16426
- done: true,
16427
- value: void 0
16428
- };
16587
+ } catch (err) {
16588
+ cleanup();
16589
+ throw err;
16429
16590
  }
16430
16591
  }),
16592
+ // note: `return` runs only for premature exits, see:
16593
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#errors_during_iteration
16431
16594
  return() {
16432
16595
  return __awaiter(this, void 0, void 0, function* () {
16433
- reader.releaseLock();
16596
+ cleanup();
16434
16597
  return {
16435
16598
  done: true,
16436
16599
  value: void 0
@@ -16439,145 +16602,600 @@ var TextStreamReader = class extends BaseStreamReader {
16439
16602
  }
16440
16603
  };
16441
16604
  }
16605
+ /**
16606
+ * Injects an AbortSignal, which if aborted, will terminate the currently active
16607
+ * stream iteration operation.
16608
+ *
16609
+ * Note that when using AbortSignal.timeout(...), the timeout applies across
16610
+ * the whole iteration operation, not just one individual chunk read.
16611
+ */
16612
+ withAbortSignal(signal) {
16613
+ this.signal = signal;
16614
+ return this;
16615
+ }
16442
16616
  readAll() {
16443
- return __awaiter(this, void 0, void 0, function* () {
16444
- var _a, e_2, _b, _c;
16445
- let finalString = "";
16446
- try {
16447
- for (var _d = true, _e = __asyncValues(this), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
16448
- _c = _f.value;
16449
- _d = false;
16450
- const chunk = _c;
16451
- finalString += chunk;
16452
- }
16453
- } catch (e_2_1) {
16454
- e_2 = {
16455
- error: e_2_1
16456
- };
16457
- } finally {
16617
+ return __awaiter(this, arguments, void 0, function() {
16618
+ var _this2 = this;
16619
+ let opts = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
16620
+ return (function* () {
16621
+ var _a, e_2, _b, _c;
16622
+ let finalString = "";
16623
+ const iterator = opts.signal ? _this2.withAbortSignal(opts.signal) : _this2;
16458
16624
  try {
16459
- if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
16625
+ for (var _d = true, iterator_2 = __asyncValues(iterator), iterator_2_1; iterator_2_1 = yield iterator_2.next(), _a = iterator_2_1.done, !_a; _d = true) {
16626
+ _c = iterator_2_1.value;
16627
+ _d = false;
16628
+ const chunk = _c;
16629
+ finalString += chunk;
16630
+ }
16631
+ } catch (e_2_1) {
16632
+ e_2 = {
16633
+ error: e_2_1
16634
+ };
16460
16635
  } finally {
16461
- if (e_2) throw e_2.error;
16636
+ try {
16637
+ if (!_d && !_a && (_b = iterator_2.return)) yield _b.call(iterator_2);
16638
+ } finally {
16639
+ if (e_2) throw e_2.error;
16640
+ }
16462
16641
  }
16463
- }
16464
- return finalString;
16642
+ return finalString;
16643
+ })();
16465
16644
  });
16466
16645
  }
16467
16646
  };
16468
- var BaseStreamWriter = class {
16469
- constructor(writableStream, info, onClose) {
16470
- this.writableStream = writableStream;
16471
- this.defaultWriter = writableStream.getWriter();
16472
- this.onClose = onClose;
16473
- this.info = info;
16474
- }
16475
- write(chunk) {
16476
- return this.defaultWriter.write(chunk);
16477
- }
16478
- close() {
16479
- return __awaiter(this, void 0, void 0, function* () {
16480
- var _a;
16481
- yield this.defaultWriter.close();
16482
- this.defaultWriter.releaseLock();
16483
- (_a = this.onClose) === null || _a === void 0 ? void 0 : _a.call(this);
16484
- });
16647
+ var IncomingDataStreamManager = class {
16648
+ constructor() {
16649
+ this.log = livekitLogger;
16650
+ this.byteStreamControllers = /* @__PURE__ */ new Map();
16651
+ this.textStreamControllers = /* @__PURE__ */ new Map();
16652
+ this.byteStreamHandlers = /* @__PURE__ */ new Map();
16653
+ this.textStreamHandlers = /* @__PURE__ */ new Map();
16485
16654
  }
16486
- };
16487
- var TextStreamWriter = class extends BaseStreamWriter {
16488
- };
16489
- var ByteStreamWriter = class extends BaseStreamWriter {
16490
- };
16491
- var RemoteTrack = class extends Track {
16492
- constructor(mediaTrack, sid, kind, receiver, loggerOptions) {
16493
- super(mediaTrack, kind, loggerOptions);
16494
- this.sid = sid;
16495
- this.receiver = receiver;
16655
+ registerTextStreamHandler(topic, callback) {
16656
+ if (this.textStreamHandlers.has(topic)) {
16657
+ throw new DataStreamError('A text stream handler for topic "'.concat(topic, '" has already been set.'), DataStreamErrorReason.HandlerAlreadyRegistered);
16658
+ }
16659
+ this.textStreamHandlers.set(topic, callback);
16496
16660
  }
16497
- get isLocal() {
16498
- return false;
16661
+ unregisterTextStreamHandler(topic) {
16662
+ this.textStreamHandlers.delete(topic);
16499
16663
  }
16500
- /** @internal */
16501
- setMuted(muted) {
16502
- if (this.isMuted !== muted) {
16503
- this.isMuted = muted;
16504
- this._mediaStreamTrack.enabled = !muted;
16505
- this.emit(muted ? TrackEvent.Muted : TrackEvent.Unmuted, this);
16664
+ registerByteStreamHandler(topic, callback) {
16665
+ if (this.byteStreamHandlers.has(topic)) {
16666
+ throw new DataStreamError('A byte stream handler for topic "'.concat(topic, '" has already been set.'), DataStreamErrorReason.HandlerAlreadyRegistered);
16506
16667
  }
16668
+ this.byteStreamHandlers.set(topic, callback);
16507
16669
  }
16508
- /** @internal */
16509
- setMediaStream(stream) {
16510
- this.mediaStream = stream;
16511
- const onRemoveTrack = (event) => {
16512
- if (event.track === this._mediaStreamTrack) {
16513
- stream.removeEventListener("removetrack", onRemoveTrack);
16514
- if (this.receiver && "playoutDelayHint" in this.receiver) {
16515
- this.receiver.playoutDelayHint = void 0;
16516
- }
16517
- this.receiver = void 0;
16518
- this._currentBitrate = 0;
16519
- this.emit(TrackEvent.Ended, this);
16520
- }
16521
- };
16522
- stream.addEventListener("removetrack", onRemoveTrack);
16523
- }
16524
- start() {
16525
- this.startMonitor();
16526
- super.enable();
16670
+ unregisterByteStreamHandler(topic) {
16671
+ this.byteStreamHandlers.delete(topic);
16527
16672
  }
16528
- stop() {
16529
- this.stopMonitor();
16530
- super.disable();
16673
+ clearHandlersAndControllers() {
16674
+ this.byteStreamControllers.clear();
16675
+ this.textStreamControllers.clear();
16676
+ this.byteStreamHandlers.clear();
16677
+ this.textStreamHandlers.clear();
16531
16678
  }
16532
- /**
16533
- * Gets the RTCStatsReport for the RemoteTrack's underlying RTCRtpReceiver
16534
- * See https://developer.mozilla.org/en-US/docs/Web/API/RTCStatsReport
16535
- *
16536
- * @returns Promise<RTCStatsReport> | undefined
16537
- */
16538
- getRTCStatsReport() {
16539
- return __awaiter(this, void 0, void 0, function* () {
16540
- var _a;
16541
- if (!((_a = this.receiver) === null || _a === void 0 ? void 0 : _a.getStats)) {
16542
- return;
16679
+ validateParticipantHasNoActiveDataStreams(participantIdentity) {
16680
+ var _a, _b, _c, _d;
16681
+ const textStreamsBeingSentByDisconnectingParticipant = Array.from(this.textStreamControllers.entries()).filter((entry) => entry[1].sendingParticipantIdentity === participantIdentity);
16682
+ const byteStreamsBeingSentByDisconnectingParticipant = Array.from(this.byteStreamControllers.entries()).filter((entry) => entry[1].sendingParticipantIdentity === participantIdentity);
16683
+ if (textStreamsBeingSentByDisconnectingParticipant.length > 0 || byteStreamsBeingSentByDisconnectingParticipant.length > 0) {
16684
+ const abnormalEndError = new DataStreamError("Participant ".concat(participantIdentity, " unexpectedly disconnected in the middle of sending data"), DataStreamErrorReason.AbnormalEnd);
16685
+ for (const [id, controller] of byteStreamsBeingSentByDisconnectingParticipant) {
16686
+ (_b = (_a = controller.outOfBandFailureRejectingFuture).reject) === null || _b === void 0 ? void 0 : _b.call(_a, abnormalEndError);
16687
+ this.byteStreamControllers.delete(id);
16543
16688
  }
16544
- const statsReport = yield this.receiver.getStats();
16545
- return statsReport;
16546
- });
16547
- }
16548
- /**
16549
- * Allows to set a playout delay (in seconds) for this track.
16550
- * A higher value allows for more buffering of the track in the browser
16551
- * and will result in a delay of media being played back of `delayInSeconds`
16552
- */
16553
- setPlayoutDelay(delayInSeconds) {
16554
- if (this.receiver) {
16555
- if ("playoutDelayHint" in this.receiver) {
16556
- this.receiver.playoutDelayHint = delayInSeconds;
16557
- } else {
16558
- this.log.warn("Playout delay not supported in this browser");
16689
+ for (const [id, controller] of textStreamsBeingSentByDisconnectingParticipant) {
16690
+ (_d = (_c = controller.outOfBandFailureRejectingFuture).reject) === null || _d === void 0 ? void 0 : _d.call(_c, abnormalEndError);
16691
+ this.textStreamControllers.delete(id);
16559
16692
  }
16560
- } else {
16561
- this.log.warn("Cannot set playout delay, track already ended");
16562
16693
  }
16563
16694
  }
16564
- /**
16565
- * Returns the current playout delay (in seconds) of this track.
16566
- */
16567
- getPlayoutDelay() {
16568
- if (this.receiver) {
16569
- if ("playoutDelayHint" in this.receiver) {
16570
- return this.receiver.playoutDelayHint;
16571
- } else {
16572
- this.log.warn("Playout delay not supported in this browser");
16695
+ handleDataStreamPacket(packet) {
16696
+ return __awaiter(this, void 0, void 0, function* () {
16697
+ switch (packet.value.case) {
16698
+ case "streamHeader":
16699
+ return this.handleStreamHeader(packet.value.value, packet.participantIdentity);
16700
+ case "streamChunk":
16701
+ return this.handleStreamChunk(packet.value.value);
16702
+ case "streamTrailer":
16703
+ return this.handleStreamTrailer(packet.value.value);
16704
+ default:
16705
+ throw new Error('DataPacket of value "'.concat(packet.value.case, '" is not data stream related!'));
16573
16706
  }
16574
- } else {
16575
- this.log.warn("Cannot get playout delay, track already ended");
16576
- }
16577
- return 0;
16707
+ });
16578
16708
  }
16579
- /* @internal */
16580
- startMonitor() {
16709
+ handleStreamHeader(streamHeader, participantIdentity) {
16710
+ return __awaiter(this, void 0, void 0, function* () {
16711
+ var _a;
16712
+ if (streamHeader.contentHeader.case === "byteHeader") {
16713
+ const streamHandlerCallback = this.byteStreamHandlers.get(streamHeader.topic);
16714
+ if (!streamHandlerCallback) {
16715
+ this.log.debug("ignoring incoming byte stream due to no handler for topic", streamHeader.topic);
16716
+ return;
16717
+ }
16718
+ let streamController;
16719
+ const outOfBandFailureRejectingFuture = new Future();
16720
+ const info = {
16721
+ id: streamHeader.streamId,
16722
+ name: (_a = streamHeader.contentHeader.value.name) !== null && _a !== void 0 ? _a : "unknown",
16723
+ mimeType: streamHeader.mimeType,
16724
+ size: streamHeader.totalLength ? Number(streamHeader.totalLength) : void 0,
16725
+ topic: streamHeader.topic,
16726
+ timestamp: bigIntToNumber(streamHeader.timestamp),
16727
+ attributes: streamHeader.attributes
16728
+ };
16729
+ const stream = new ReadableStream({
16730
+ start: (controller) => {
16731
+ streamController = controller;
16732
+ if (this.textStreamControllers.has(streamHeader.streamId)) {
16733
+ throw new DataStreamError("A data stream read is already in progress for a stream with id ".concat(streamHeader.streamId, "."), DataStreamErrorReason.AlreadyOpened);
16734
+ }
16735
+ this.byteStreamControllers.set(streamHeader.streamId, {
16736
+ info,
16737
+ controller: streamController,
16738
+ startTime: Date.now(),
16739
+ sendingParticipantIdentity: participantIdentity,
16740
+ outOfBandFailureRejectingFuture
16741
+ });
16742
+ }
16743
+ });
16744
+ streamHandlerCallback(new ByteStreamReader(info, stream, bigIntToNumber(streamHeader.totalLength), outOfBandFailureRejectingFuture), {
16745
+ identity: participantIdentity
16746
+ });
16747
+ } else if (streamHeader.contentHeader.case === "textHeader") {
16748
+ const streamHandlerCallback = this.textStreamHandlers.get(streamHeader.topic);
16749
+ if (!streamHandlerCallback) {
16750
+ this.log.debug("ignoring incoming text stream due to no handler for topic", streamHeader.topic);
16751
+ return;
16752
+ }
16753
+ let streamController;
16754
+ const outOfBandFailureRejectingFuture = new Future();
16755
+ const info = {
16756
+ id: streamHeader.streamId,
16757
+ mimeType: streamHeader.mimeType,
16758
+ size: streamHeader.totalLength ? Number(streamHeader.totalLength) : void 0,
16759
+ topic: streamHeader.topic,
16760
+ timestamp: Number(streamHeader.timestamp),
16761
+ attributes: streamHeader.attributes
16762
+ };
16763
+ const stream = new ReadableStream({
16764
+ start: (controller) => {
16765
+ streamController = controller;
16766
+ if (this.textStreamControllers.has(streamHeader.streamId)) {
16767
+ throw new DataStreamError("A data stream read is already in progress for a stream with id ".concat(streamHeader.streamId, "."), DataStreamErrorReason.AlreadyOpened);
16768
+ }
16769
+ this.textStreamControllers.set(streamHeader.streamId, {
16770
+ info,
16771
+ controller: streamController,
16772
+ startTime: Date.now(),
16773
+ sendingParticipantIdentity: participantIdentity,
16774
+ outOfBandFailureRejectingFuture
16775
+ });
16776
+ }
16777
+ });
16778
+ streamHandlerCallback(new TextStreamReader(info, stream, bigIntToNumber(streamHeader.totalLength), outOfBandFailureRejectingFuture), {
16779
+ identity: participantIdentity
16780
+ });
16781
+ }
16782
+ });
16783
+ }
16784
+ handleStreamChunk(chunk) {
16785
+ const fileBuffer = this.byteStreamControllers.get(chunk.streamId);
16786
+ if (fileBuffer) {
16787
+ if (chunk.content.length > 0) {
16788
+ fileBuffer.controller.enqueue(chunk);
16789
+ }
16790
+ }
16791
+ const textBuffer = this.textStreamControllers.get(chunk.streamId);
16792
+ if (textBuffer) {
16793
+ if (chunk.content.length > 0) {
16794
+ textBuffer.controller.enqueue(chunk);
16795
+ }
16796
+ }
16797
+ }
16798
+ handleStreamTrailer(trailer) {
16799
+ const textBuffer = this.textStreamControllers.get(trailer.streamId);
16800
+ if (textBuffer) {
16801
+ textBuffer.info.attributes = Object.assign(Object.assign({}, textBuffer.info.attributes), trailer.attributes);
16802
+ textBuffer.controller.close();
16803
+ this.textStreamControllers.delete(trailer.streamId);
16804
+ }
16805
+ const fileBuffer = this.byteStreamControllers.get(trailer.streamId);
16806
+ if (fileBuffer) {
16807
+ {
16808
+ fileBuffer.info.attributes = Object.assign(Object.assign({}, fileBuffer.info.attributes), trailer.attributes);
16809
+ fileBuffer.controller.close();
16810
+ this.byteStreamControllers.delete(trailer.streamId);
16811
+ }
16812
+ }
16813
+ }
16814
+ };
16815
+ var BaseStreamWriter = class {
16816
+ constructor(writableStream, info, onClose) {
16817
+ this.writableStream = writableStream;
16818
+ this.defaultWriter = writableStream.getWriter();
16819
+ this.onClose = onClose;
16820
+ this.info = info;
16821
+ }
16822
+ write(chunk) {
16823
+ return this.defaultWriter.write(chunk);
16824
+ }
16825
+ close() {
16826
+ return __awaiter(this, void 0, void 0, function* () {
16827
+ var _a;
16828
+ yield this.defaultWriter.close();
16829
+ this.defaultWriter.releaseLock();
16830
+ (_a = this.onClose) === null || _a === void 0 ? void 0 : _a.call(this);
16831
+ });
16832
+ }
16833
+ };
16834
+ var TextStreamWriter = class extends BaseStreamWriter {
16835
+ };
16836
+ var ByteStreamWriter = class extends BaseStreamWriter {
16837
+ };
16838
+ var STREAM_CHUNK_SIZE = 15e3;
16839
+ var OutgoingDataStreamManager = class {
16840
+ constructor(engine, log2) {
16841
+ this.engine = engine;
16842
+ this.log = log2;
16843
+ }
16844
+ setupEngine(engine) {
16845
+ this.engine = engine;
16846
+ }
16847
+ /** {@inheritDoc LocalParticipant.sendText} */
16848
+ sendText(text, options) {
16849
+ return __awaiter(this, void 0, void 0, function* () {
16850
+ var _a;
16851
+ const streamId = crypto.randomUUID();
16852
+ const textInBytes = new TextEncoder().encode(text);
16853
+ const totalTextLength = textInBytes.byteLength;
16854
+ const fileIds = (_a = options === null || options === void 0 ? void 0 : options.attachments) === null || _a === void 0 ? void 0 : _a.map(() => crypto.randomUUID());
16855
+ const progresses = new Array(fileIds ? fileIds.length + 1 : 1).fill(0);
16856
+ const handleProgress = (progress, idx) => {
16857
+ var _a2;
16858
+ progresses[idx] = progress;
16859
+ const totalProgress = progresses.reduce((acc, val) => acc + val, 0);
16860
+ (_a2 = options === null || options === void 0 ? void 0 : options.onProgress) === null || _a2 === void 0 ? void 0 : _a2.call(options, totalProgress);
16861
+ };
16862
+ const writer2 = yield this.streamText({
16863
+ streamId,
16864
+ totalSize: totalTextLength,
16865
+ destinationIdentities: options === null || options === void 0 ? void 0 : options.destinationIdentities,
16866
+ topic: options === null || options === void 0 ? void 0 : options.topic,
16867
+ attachedStreamIds: fileIds,
16868
+ attributes: options === null || options === void 0 ? void 0 : options.attributes
16869
+ });
16870
+ yield writer2.write(text);
16871
+ handleProgress(1, 0);
16872
+ yield writer2.close();
16873
+ if ((options === null || options === void 0 ? void 0 : options.attachments) && fileIds) {
16874
+ yield Promise.all(options.attachments.map((file, idx) => __awaiter(this, void 0, void 0, function* () {
16875
+ return this._sendFile(fileIds[idx], file, {
16876
+ topic: options.topic,
16877
+ mimeType: file.type,
16878
+ onProgress: (progress) => {
16879
+ handleProgress(progress, idx + 1);
16880
+ }
16881
+ });
16882
+ })));
16883
+ }
16884
+ return writer2.info;
16885
+ });
16886
+ }
16887
+ /**
16888
+ * @internal
16889
+ * @experimental CAUTION, might get removed in a minor release
16890
+ */
16891
+ streamText(options) {
16892
+ return __awaiter(this, void 0, void 0, function* () {
16893
+ var _a, _b;
16894
+ const streamId = (_a = options === null || options === void 0 ? void 0 : options.streamId) !== null && _a !== void 0 ? _a : crypto.randomUUID();
16895
+ const info = {
16896
+ id: streamId,
16897
+ mimeType: "text/plain",
16898
+ timestamp: Date.now(),
16899
+ topic: (_b = options === null || options === void 0 ? void 0 : options.topic) !== null && _b !== void 0 ? _b : "",
16900
+ size: options === null || options === void 0 ? void 0 : options.totalSize,
16901
+ attributes: options === null || options === void 0 ? void 0 : options.attributes
16902
+ };
16903
+ const header = new DataStream_Header({
16904
+ streamId,
16905
+ mimeType: info.mimeType,
16906
+ topic: info.topic,
16907
+ timestamp: numberToBigInt(info.timestamp),
16908
+ totalLength: numberToBigInt(options === null || options === void 0 ? void 0 : options.totalSize),
16909
+ attributes: info.attributes,
16910
+ contentHeader: {
16911
+ case: "textHeader",
16912
+ value: new DataStream_TextHeader({
16913
+ version: options === null || options === void 0 ? void 0 : options.version,
16914
+ attachedStreamIds: options === null || options === void 0 ? void 0 : options.attachedStreamIds,
16915
+ replyToStreamId: options === null || options === void 0 ? void 0 : options.replyToStreamId,
16916
+ operationType: (options === null || options === void 0 ? void 0 : options.type) === "update" ? DataStream_OperationType.UPDATE : DataStream_OperationType.CREATE
16917
+ })
16918
+ }
16919
+ });
16920
+ const destinationIdentities = options === null || options === void 0 ? void 0 : options.destinationIdentities;
16921
+ const packet = new DataPacket({
16922
+ destinationIdentities,
16923
+ value: {
16924
+ case: "streamHeader",
16925
+ value: header
16926
+ }
16927
+ });
16928
+ yield this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
16929
+ let chunkId = 0;
16930
+ const engine = this.engine;
16931
+ const writableStream = new WritableStream({
16932
+ // Implement the sink
16933
+ write(text) {
16934
+ return __awaiter(this, void 0, void 0, function* () {
16935
+ for (const textByteChunk of splitUtf8(text, STREAM_CHUNK_SIZE)) {
16936
+ yield engine.waitForBufferStatusLow(DataPacket_Kind.RELIABLE);
16937
+ const chunk = new DataStream_Chunk({
16938
+ content: textByteChunk,
16939
+ streamId,
16940
+ chunkIndex: numberToBigInt(chunkId)
16941
+ });
16942
+ const chunkPacket = new DataPacket({
16943
+ destinationIdentities,
16944
+ value: {
16945
+ case: "streamChunk",
16946
+ value: chunk
16947
+ }
16948
+ });
16949
+ yield engine.sendDataPacket(chunkPacket, DataPacket_Kind.RELIABLE);
16950
+ chunkId += 1;
16951
+ }
16952
+ });
16953
+ },
16954
+ close() {
16955
+ return __awaiter(this, void 0, void 0, function* () {
16956
+ const trailer = new DataStream_Trailer({
16957
+ streamId
16958
+ });
16959
+ const trailerPacket = new DataPacket({
16960
+ destinationIdentities,
16961
+ value: {
16962
+ case: "streamTrailer",
16963
+ value: trailer
16964
+ }
16965
+ });
16966
+ yield engine.sendDataPacket(trailerPacket, DataPacket_Kind.RELIABLE);
16967
+ });
16968
+ },
16969
+ abort(err) {
16970
+ console.log("Sink error:", err);
16971
+ }
16972
+ });
16973
+ let onEngineClose = () => __awaiter(this, void 0, void 0, function* () {
16974
+ yield writer2.close();
16975
+ });
16976
+ engine.once(EngineEvent.Closing, onEngineClose);
16977
+ const writer2 = new TextStreamWriter(writableStream, info, () => this.engine.off(EngineEvent.Closing, onEngineClose));
16978
+ return writer2;
16979
+ });
16980
+ }
16981
+ sendFile(file, options) {
16982
+ return __awaiter(this, void 0, void 0, function* () {
16983
+ const streamId = crypto.randomUUID();
16984
+ yield this._sendFile(streamId, file, options);
16985
+ return {
16986
+ id: streamId
16987
+ };
16988
+ });
16989
+ }
16990
+ _sendFile(streamId, file, options) {
16991
+ return __awaiter(this, void 0, void 0, function* () {
16992
+ var _a;
16993
+ const writer2 = yield this.streamBytes({
16994
+ streamId,
16995
+ totalSize: file.size,
16996
+ name: file.name,
16997
+ mimeType: (_a = options === null || options === void 0 ? void 0 : options.mimeType) !== null && _a !== void 0 ? _a : file.type,
16998
+ topic: options === null || options === void 0 ? void 0 : options.topic,
16999
+ destinationIdentities: options === null || options === void 0 ? void 0 : options.destinationIdentities
17000
+ });
17001
+ const reader = file.stream().getReader();
17002
+ while (true) {
17003
+ const {
17004
+ done,
17005
+ value
17006
+ } = yield reader.read();
17007
+ if (done) {
17008
+ break;
17009
+ }
17010
+ yield writer2.write(value);
17011
+ }
17012
+ yield writer2.close();
17013
+ return writer2.info;
17014
+ });
17015
+ }
17016
+ streamBytes(options) {
17017
+ return __awaiter(this, void 0, void 0, function* () {
17018
+ var _a, _b, _c, _d, _e;
17019
+ const streamId = (_a = options === null || options === void 0 ? void 0 : options.streamId) !== null && _a !== void 0 ? _a : crypto.randomUUID();
17020
+ const destinationIdentities = options === null || options === void 0 ? void 0 : options.destinationIdentities;
17021
+ const info = {
17022
+ id: streamId,
17023
+ mimeType: (_b = options === null || options === void 0 ? void 0 : options.mimeType) !== null && _b !== void 0 ? _b : "application/octet-stream",
17024
+ topic: (_c = options === null || options === void 0 ? void 0 : options.topic) !== null && _c !== void 0 ? _c : "",
17025
+ timestamp: Date.now(),
17026
+ attributes: options === null || options === void 0 ? void 0 : options.attributes,
17027
+ size: options === null || options === void 0 ? void 0 : options.totalSize,
17028
+ name: (_d = options === null || options === void 0 ? void 0 : options.name) !== null && _d !== void 0 ? _d : "unknown"
17029
+ };
17030
+ const header = new DataStream_Header({
17031
+ totalLength: numberToBigInt((_e = info.size) !== null && _e !== void 0 ? _e : 0),
17032
+ mimeType: info.mimeType,
17033
+ streamId,
17034
+ topic: info.topic,
17035
+ timestamp: numberToBigInt(Date.now()),
17036
+ attributes: info.attributes,
17037
+ contentHeader: {
17038
+ case: "byteHeader",
17039
+ value: new DataStream_ByteHeader({
17040
+ name: info.name
17041
+ })
17042
+ }
17043
+ });
17044
+ const packet = new DataPacket({
17045
+ destinationIdentities,
17046
+ value: {
17047
+ case: "streamHeader",
17048
+ value: header
17049
+ }
17050
+ });
17051
+ yield this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
17052
+ let chunkId = 0;
17053
+ const writeMutex = new _();
17054
+ const engine = this.engine;
17055
+ const logLocal = this.log;
17056
+ const writableStream = new WritableStream({
17057
+ write(chunk) {
17058
+ return __awaiter(this, void 0, void 0, function* () {
17059
+ const unlock = yield writeMutex.lock();
17060
+ let byteOffset = 0;
17061
+ try {
17062
+ while (byteOffset < chunk.byteLength) {
17063
+ const subChunk = chunk.slice(byteOffset, byteOffset + STREAM_CHUNK_SIZE);
17064
+ yield engine.waitForBufferStatusLow(DataPacket_Kind.RELIABLE);
17065
+ const chunkPacket = new DataPacket({
17066
+ destinationIdentities,
17067
+ value: {
17068
+ case: "streamChunk",
17069
+ value: new DataStream_Chunk({
17070
+ content: subChunk,
17071
+ streamId,
17072
+ chunkIndex: numberToBigInt(chunkId)
17073
+ })
17074
+ }
17075
+ });
17076
+ yield engine.sendDataPacket(chunkPacket, DataPacket_Kind.RELIABLE);
17077
+ chunkId += 1;
17078
+ byteOffset += subChunk.byteLength;
17079
+ }
17080
+ } finally {
17081
+ unlock();
17082
+ }
17083
+ });
17084
+ },
17085
+ close() {
17086
+ return __awaiter(this, void 0, void 0, function* () {
17087
+ const trailer = new DataStream_Trailer({
17088
+ streamId
17089
+ });
17090
+ const trailerPacket = new DataPacket({
17091
+ destinationIdentities,
17092
+ value: {
17093
+ case: "streamTrailer",
17094
+ value: trailer
17095
+ }
17096
+ });
17097
+ yield engine.sendDataPacket(trailerPacket, DataPacket_Kind.RELIABLE);
17098
+ });
17099
+ },
17100
+ abort(err) {
17101
+ logLocal.error("Sink error:", err);
17102
+ }
17103
+ });
17104
+ const byteWriter = new ByteStreamWriter(writableStream, info);
17105
+ return byteWriter;
17106
+ });
17107
+ }
17108
+ };
17109
+ var RemoteTrack = class extends Track {
17110
+ constructor(mediaTrack, sid, kind, receiver, loggerOptions) {
17111
+ super(mediaTrack, kind, loggerOptions);
17112
+ this.sid = sid;
17113
+ this.receiver = receiver;
17114
+ }
17115
+ get isLocal() {
17116
+ return false;
17117
+ }
17118
+ /** @internal */
17119
+ setMuted(muted) {
17120
+ if (this.isMuted !== muted) {
17121
+ this.isMuted = muted;
17122
+ this._mediaStreamTrack.enabled = !muted;
17123
+ this.emit(muted ? TrackEvent.Muted : TrackEvent.Unmuted, this);
17124
+ }
17125
+ }
17126
+ /** @internal */
17127
+ setMediaStream(stream) {
17128
+ this.mediaStream = stream;
17129
+ const onRemoveTrack = (event) => {
17130
+ if (event.track === this._mediaStreamTrack) {
17131
+ stream.removeEventListener("removetrack", onRemoveTrack);
17132
+ if (this.receiver && "playoutDelayHint" in this.receiver) {
17133
+ this.receiver.playoutDelayHint = void 0;
17134
+ }
17135
+ this.receiver = void 0;
17136
+ this._currentBitrate = 0;
17137
+ this.emit(TrackEvent.Ended, this);
17138
+ }
17139
+ };
17140
+ stream.addEventListener("removetrack", onRemoveTrack);
17141
+ }
17142
+ start() {
17143
+ this.startMonitor();
17144
+ super.enable();
17145
+ }
17146
+ stop() {
17147
+ this.stopMonitor();
17148
+ super.disable();
17149
+ }
17150
+ /**
17151
+ * Gets the RTCStatsReport for the RemoteTrack's underlying RTCRtpReceiver
17152
+ * See https://developer.mozilla.org/en-US/docs/Web/API/RTCStatsReport
17153
+ *
17154
+ * @returns Promise<RTCStatsReport> | undefined
17155
+ */
17156
+ getRTCStatsReport() {
17157
+ return __awaiter(this, void 0, void 0, function* () {
17158
+ var _a;
17159
+ if (!((_a = this.receiver) === null || _a === void 0 ? void 0 : _a.getStats)) {
17160
+ return;
17161
+ }
17162
+ const statsReport = yield this.receiver.getStats();
17163
+ return statsReport;
17164
+ });
17165
+ }
17166
+ /**
17167
+ * Allows to set a playout delay (in seconds) for this track.
17168
+ * A higher value allows for more buffering of the track in the browser
17169
+ * and will result in a delay of media being played back of `delayInSeconds`
17170
+ */
17171
+ setPlayoutDelay(delayInSeconds) {
17172
+ if (this.receiver) {
17173
+ if ("playoutDelayHint" in this.receiver) {
17174
+ this.receiver.playoutDelayHint = delayInSeconds;
17175
+ } else {
17176
+ this.log.warn("Playout delay not supported in this browser");
17177
+ }
17178
+ } else {
17179
+ this.log.warn("Cannot set playout delay, track already ended");
17180
+ }
17181
+ }
17182
+ /**
17183
+ * Returns the current playout delay (in seconds) of this track.
17184
+ */
17185
+ getPlayoutDelay() {
17186
+ if (this.receiver) {
17187
+ if ("playoutDelayHint" in this.receiver) {
17188
+ return this.receiver.playoutDelayHint;
17189
+ } else {
17190
+ this.log.warn("Playout delay not supported in this browser");
17191
+ }
17192
+ } else {
17193
+ this.log.warn("Cannot get playout delay, track already ended");
17194
+ }
17195
+ return 0;
17196
+ }
17197
+ /* @internal */
17198
+ startMonitor() {
16581
17199
  if (!this.monitorInterval) {
16582
17200
  this.monitorInterval = setInterval(() => this.monitorReceiver(), monitorFrequency);
16583
17201
  }
@@ -16823,6 +17441,13 @@ var RemoteVideoTrack = class extends RemoteTrack {
16823
17441
  get isAdaptiveStream() {
16824
17442
  return this.adaptiveStreamSettings !== void 0;
16825
17443
  }
17444
+ setStreamState(value) {
17445
+ super.setStreamState(value);
17446
+ console.log("setStreamState", value);
17447
+ if (value === Track.StreamState.Active) {
17448
+ this.updateVisibility();
17449
+ }
17450
+ }
16826
17451
  /**
16827
17452
  * Note: When using adaptiveStream, you need to use remoteVideoTrack.attach() to add the track to a HTMLVideoElement, otherwise your video tracks might never start
16828
17453
  */
@@ -16966,13 +17591,13 @@ var RemoteVideoTrack = class extends RemoteTrack {
16966
17591
  this.updateVisibility();
16967
17592
  });
16968
17593
  }
16969
- updateVisibility() {
17594
+ updateVisibility(forceEmit) {
16970
17595
  var _a, _b;
16971
17596
  const lastVisibilityChange = this.elementInfos.reduce((prev, info) => Math.max(prev, info.visibilityChangedAt || 0), 0);
16972
17597
  const backgroundPause = ((_b = (_a = this.adaptiveStreamSettings) === null || _a === void 0 ? void 0 : _a.pauseVideoInBackground) !== null && _b !== void 0 ? _b : true) ? this.isInBackground : false;
16973
17598
  const isPiPMode = this.elementInfos.some((info) => info.pictureInPicture);
16974
17599
  const isVisible = this.elementInfos.some((info) => info.visible) && !backgroundPause || isPiPMode;
16975
- if (this.lastVisible === isVisible) {
17600
+ if (this.lastVisible === isVisible && !forceEmit) {
16976
17601
  return;
16977
17602
  }
16978
17603
  if (!isVisible && Date.now() - lastVisibilityChange < REACTION_DELAY) {
@@ -17720,10 +18345,9 @@ function trackPermissionToProto(perms) {
17720
18345
  trackSids: perms.allowedTrackSids || []
17721
18346
  });
17722
18347
  }
17723
- var STREAM_CHUNK_SIZE = 15e3;
17724
18348
  var LocalParticipant = class extends Participant {
17725
18349
  /** @internal */
17726
- constructor(sid, identity, engine, options, roomRpcHandlers) {
18350
+ constructor(sid, identity, engine, options, roomRpcHandlers, roomOutgoingDataStreamManager) {
17727
18351
  super(sid, identity, void 0, void 0, void 0, {
17728
18352
  loggerName: options.loggerName,
17729
18353
  loggerContextCb: () => this.engine.logContext
@@ -17949,6 +18573,7 @@ var LocalParticipant = class extends Participant {
17949
18573
  this.activeDeviceMap = /* @__PURE__ */ new Map([["audioinput", "default"], ["videoinput", "default"], ["audiooutput", "default"]]);
17950
18574
  this.pendingSignalRequests = /* @__PURE__ */ new Map();
17951
18575
  this.rpcHandlers = roomRpcHandlers;
18576
+ this.roomOutgoingDataStreamManager = roomOutgoingDataStreamManager;
17952
18577
  }
17953
18578
  get lastCameraError() {
17954
18579
  return this.cameraError;
@@ -18040,7 +18665,7 @@ var LocalParticipant = class extends Participant {
18040
18665
  name,
18041
18666
  attributes
18042
18667
  } = _ref;
18043
- return function* () {
18668
+ return (function* () {
18044
18669
  return new Promise((resolve, reject) => __awaiter(_this, void 0, void 0, function* () {
18045
18670
  var _a2, _b;
18046
18671
  try {
@@ -18075,7 +18700,7 @@ var LocalParticipant = class extends Participant {
18075
18700
  if (e2 instanceof Error) reject(e2);
18076
18701
  }
18077
18702
  }));
18078
- }();
18703
+ })();
18079
18704
  });
18080
18705
  }
18081
18706
  /**
@@ -18344,7 +18969,7 @@ var LocalParticipant = class extends Participant {
18344
18969
  return __awaiter(this, arguments, void 0, function(track, options) {
18345
18970
  var _this2 = this;
18346
18971
  let isRepublish = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : false;
18347
- return function* () {
18972
+ return (function* () {
18348
18973
  var _a, _b, _c, _d;
18349
18974
  if (isLocalAudioTrack(track)) {
18350
18975
  track.setAudioContext(_this2.audioContext);
@@ -18469,7 +19094,7 @@ var LocalParticipant = class extends Participant {
18469
19094
  } finally {
18470
19095
  _this2.pendingPublishPromises.delete(track);
18471
19096
  }
18472
- }();
19097
+ })();
18473
19098
  });
18474
19099
  }
18475
19100
  waitUntilEngineConnected() {
@@ -18951,7 +19576,7 @@ var LocalParticipant = class extends Participant {
18951
19576
  return __awaiter(this, arguments, void 0, function(options) {
18952
19577
  var _this3 = this;
18953
19578
  let restartTracks = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true;
18954
- return function* () {
19579
+ return (function* () {
18955
19580
  if (_this3.republishPromise) {
18956
19581
  yield _this3.republishPromise;
18957
19582
  }
@@ -18985,7 +19610,7 @@ var LocalParticipant = class extends Participant {
18985
19610
  }
18986
19611
  }));
18987
19612
  yield _this3.republishPromise;
18988
- }();
19613
+ })();
18989
19614
  });
18990
19615
  }
18991
19616
  /**
@@ -18999,7 +19624,7 @@ var LocalParticipant = class extends Participant {
18999
19624
  return __awaiter(this, arguments, void 0, function(data) {
19000
19625
  var _this4 = this;
19001
19626
  let options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
19002
- return function* () {
19627
+ return (function* () {
19003
19628
  const kind = options.reliable ? DataPacket_Kind.RELIABLE : DataPacket_Kind.LOSSY;
19004
19629
  const destinationIdentities = options.destinationIdentities;
19005
19630
  const topic = options.topic;
@@ -19016,7 +19641,7 @@ var LocalParticipant = class extends Participant {
19016
19641
  }
19017
19642
  });
19018
19643
  yield _this4.engine.sendDataPacket(packet, kind);
19019
- }();
19644
+ })();
19020
19645
  });
19021
19646
  }
19022
19647
  /**
@@ -19037,308 +19662,97 @@ var LocalParticipant = class extends Participant {
19037
19662
  })
19038
19663
  }
19039
19664
  });
19040
- yield this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
19041
- });
19042
- }
19043
- sendChatMessage(text, options) {
19044
- return __awaiter(this, void 0, void 0, function* () {
19045
- const msg = {
19046
- id: crypto.randomUUID(),
19047
- message: text,
19048
- timestamp: Date.now(),
19049
- attachedFiles: options === null || options === void 0 ? void 0 : options.attachments
19050
- };
19051
- const packet = new DataPacket({
19052
- value: {
19053
- case: "chatMessage",
19054
- value: new ChatMessage(Object.assign(Object.assign({}, msg), {
19055
- timestamp: protoInt64.parse(msg.timestamp)
19056
- }))
19057
- }
19058
- });
19059
- yield this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
19060
- this.emit(ParticipantEvent.ChatMessage, msg);
19061
- return msg;
19062
- });
19063
- }
19064
- editChatMessage(editText, originalMessage) {
19065
- return __awaiter(this, void 0, void 0, function* () {
19066
- const msg = Object.assign(Object.assign({}, originalMessage), {
19067
- message: editText,
19068
- editTimestamp: Date.now()
19069
- });
19070
- const packet = new DataPacket({
19071
- value: {
19072
- case: "chatMessage",
19073
- value: new ChatMessage(Object.assign(Object.assign({}, msg), {
19074
- timestamp: protoInt64.parse(msg.timestamp),
19075
- editTimestamp: protoInt64.parse(msg.editTimestamp)
19076
- }))
19077
- }
19078
- });
19079
- yield this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
19080
- this.emit(ParticipantEvent.ChatMessage, msg);
19081
- return msg;
19082
- });
19083
- }
19084
- sendText(text, options) {
19085
- return __awaiter(this, void 0, void 0, function* () {
19086
- var _a;
19087
- const streamId = crypto.randomUUID();
19088
- const textInBytes = new TextEncoder().encode(text);
19089
- const totalTextLength = textInBytes.byteLength;
19090
- const fileIds = (_a = options === null || options === void 0 ? void 0 : options.attachments) === null || _a === void 0 ? void 0 : _a.map(() => crypto.randomUUID());
19091
- const progresses = new Array(fileIds ? fileIds.length + 1 : 1).fill(0);
19092
- const handleProgress = (progress, idx) => {
19093
- var _a2;
19094
- progresses[idx] = progress;
19095
- const totalProgress = progresses.reduce((acc, val) => acc + val, 0);
19096
- (_a2 = options === null || options === void 0 ? void 0 : options.onProgress) === null || _a2 === void 0 ? void 0 : _a2.call(options, totalProgress);
19097
- };
19098
- const writer2 = yield this.streamText({
19099
- streamId,
19100
- totalSize: totalTextLength,
19101
- destinationIdentities: options === null || options === void 0 ? void 0 : options.destinationIdentities,
19102
- topic: options === null || options === void 0 ? void 0 : options.topic,
19103
- attachedStreamIds: fileIds,
19104
- attributes: options === null || options === void 0 ? void 0 : options.attributes
19105
- });
19106
- yield writer2.write(text);
19107
- handleProgress(1, 0);
19108
- yield writer2.close();
19109
- if ((options === null || options === void 0 ? void 0 : options.attachments) && fileIds) {
19110
- yield Promise.all(options.attachments.map((file, idx) => __awaiter(this, void 0, void 0, function* () {
19111
- return this._sendFile(fileIds[idx], file, {
19112
- topic: options.topic,
19113
- mimeType: file.type,
19114
- onProgress: (progress) => {
19115
- handleProgress(progress, idx + 1);
19116
- }
19117
- });
19118
- })));
19119
- }
19120
- return writer2.info;
19665
+ yield this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
19121
19666
  });
19122
19667
  }
19123
- /**
19124
- * @internal
19125
- * @experimental CAUTION, might get removed in a minor release
19126
- */
19127
- streamText(options) {
19668
+ /** @deprecated Consider migrating to {@link sendText} */
19669
+ sendChatMessage(text, options) {
19128
19670
  return __awaiter(this, void 0, void 0, function* () {
19129
- var _a, _b;
19130
- const streamId = (_a = options === null || options === void 0 ? void 0 : options.streamId) !== null && _a !== void 0 ? _a : crypto.randomUUID();
19131
- const info = {
19132
- id: streamId,
19133
- mimeType: "text/plain",
19671
+ const msg = {
19672
+ id: crypto.randomUUID(),
19673
+ message: text,
19134
19674
  timestamp: Date.now(),
19135
- topic: (_b = options === null || options === void 0 ? void 0 : options.topic) !== null && _b !== void 0 ? _b : "",
19136
- size: options === null || options === void 0 ? void 0 : options.totalSize,
19137
- attributes: options === null || options === void 0 ? void 0 : options.attributes
19675
+ attachedFiles: options === null || options === void 0 ? void 0 : options.attachments
19138
19676
  };
19139
- const header = new DataStream_Header({
19140
- streamId,
19141
- mimeType: info.mimeType,
19142
- topic: info.topic,
19143
- timestamp: numberToBigInt(info.timestamp),
19144
- totalLength: numberToBigInt(options === null || options === void 0 ? void 0 : options.totalSize),
19145
- attributes: info.attributes,
19146
- contentHeader: {
19147
- case: "textHeader",
19148
- value: new DataStream_TextHeader({
19149
- version: options === null || options === void 0 ? void 0 : options.version,
19150
- attachedStreamIds: options === null || options === void 0 ? void 0 : options.attachedStreamIds,
19151
- replyToStreamId: options === null || options === void 0 ? void 0 : options.replyToStreamId,
19152
- operationType: (options === null || options === void 0 ? void 0 : options.type) === "update" ? DataStream_OperationType.UPDATE : DataStream_OperationType.CREATE
19153
- })
19154
- }
19155
- });
19156
- const destinationIdentities = options === null || options === void 0 ? void 0 : options.destinationIdentities;
19157
19677
  const packet = new DataPacket({
19158
- destinationIdentities,
19159
19678
  value: {
19160
- case: "streamHeader",
19161
- value: header
19679
+ case: "chatMessage",
19680
+ value: new ChatMessage(Object.assign(Object.assign({}, msg), {
19681
+ timestamp: protoInt64.parse(msg.timestamp)
19682
+ }))
19162
19683
  }
19163
19684
  });
19164
19685
  yield this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
19165
- let chunkId = 0;
19166
- const localP = this;
19167
- const writableStream = new WritableStream({
19168
- // Implement the sink
19169
- write(text) {
19170
- return __awaiter(this, void 0, void 0, function* () {
19171
- for (const textByteChunk of splitUtf8(text, STREAM_CHUNK_SIZE)) {
19172
- yield localP.engine.waitForBufferStatusLow(DataPacket_Kind.RELIABLE);
19173
- const chunk = new DataStream_Chunk({
19174
- content: textByteChunk,
19175
- streamId,
19176
- chunkIndex: numberToBigInt(chunkId)
19177
- });
19178
- const chunkPacket = new DataPacket({
19179
- destinationIdentities,
19180
- value: {
19181
- case: "streamChunk",
19182
- value: chunk
19183
- }
19184
- });
19185
- yield localP.engine.sendDataPacket(chunkPacket, DataPacket_Kind.RELIABLE);
19186
- chunkId += 1;
19187
- }
19188
- });
19189
- },
19190
- close() {
19191
- return __awaiter(this, void 0, void 0, function* () {
19192
- const trailer = new DataStream_Trailer({
19193
- streamId
19194
- });
19195
- const trailerPacket = new DataPacket({
19196
- destinationIdentities,
19197
- value: {
19198
- case: "streamTrailer",
19199
- value: trailer
19200
- }
19201
- });
19202
- yield localP.engine.sendDataPacket(trailerPacket, DataPacket_Kind.RELIABLE);
19203
- });
19204
- },
19205
- abort(err) {
19206
- console.log("Sink error:", err);
19207
- }
19686
+ this.emit(ParticipantEvent.ChatMessage, msg);
19687
+ return msg;
19688
+ });
19689
+ }
19690
+ /** @deprecated Consider migrating to {@link sendText} */
19691
+ editChatMessage(editText, originalMessage) {
19692
+ return __awaiter(this, void 0, void 0, function* () {
19693
+ const msg = Object.assign(Object.assign({}, originalMessage), {
19694
+ message: editText,
19695
+ editTimestamp: Date.now()
19208
19696
  });
19209
- let onEngineClose = () => __awaiter(this, void 0, void 0, function* () {
19210
- yield writer2.close();
19697
+ const packet = new DataPacket({
19698
+ value: {
19699
+ case: "chatMessage",
19700
+ value: new ChatMessage(Object.assign(Object.assign({}, msg), {
19701
+ timestamp: protoInt64.parse(msg.timestamp),
19702
+ editTimestamp: protoInt64.parse(msg.editTimestamp)
19703
+ }))
19704
+ }
19211
19705
  });
19212
- localP.engine.once(EngineEvent.Closing, onEngineClose);
19213
- const writer2 = new TextStreamWriter(writableStream, info, () => this.engine.off(EngineEvent.Closing, onEngineClose));
19214
- return writer2;
19706
+ yield this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
19707
+ this.emit(ParticipantEvent.ChatMessage, msg);
19708
+ return msg;
19215
19709
  });
19216
19710
  }
19217
- sendFile(file, options) {
19711
+ /**
19712
+ * Sends the given string to participants in the room via the data channel.
19713
+ * For longer messages, consider using {@link streamText} instead.
19714
+ *
19715
+ * @param text The text payload
19716
+ * @param options.topic Topic identifier used to route the stream to appropriate handlers.
19717
+ */
19718
+ sendText(text, options) {
19218
19719
  return __awaiter(this, void 0, void 0, function* () {
19219
- const streamId = crypto.randomUUID();
19220
- yield this._sendFile(streamId, file, options);
19221
- return {
19222
- id: streamId
19223
- };
19720
+ return this.roomOutgoingDataStreamManager.sendText(text, options);
19224
19721
  });
19225
19722
  }
19226
- _sendFile(streamId, file, options) {
19723
+ /**
19724
+ * Creates a new TextStreamWriter which can be used to stream text incrementally
19725
+ * to participants in the room via the data channel.
19726
+ *
19727
+ * @param options.topic Topic identifier used to route the stream to appropriate handlers.
19728
+ *
19729
+ * @internal
19730
+ * @experimental CAUTION, might get removed in a minor release
19731
+ */
19732
+ streamText(options) {
19227
19733
  return __awaiter(this, void 0, void 0, function* () {
19228
- var _a;
19229
- const writer2 = yield this.streamBytes({
19230
- streamId,
19231
- totalSize: file.size,
19232
- name: file.name,
19233
- mimeType: (_a = options === null || options === void 0 ? void 0 : options.mimeType) !== null && _a !== void 0 ? _a : file.type,
19234
- topic: options === null || options === void 0 ? void 0 : options.topic,
19235
- destinationIdentities: options === null || options === void 0 ? void 0 : options.destinationIdentities
19236
- });
19237
- const reader = file.stream().getReader();
19238
- while (true) {
19239
- const {
19240
- done,
19241
- value
19242
- } = yield reader.read();
19243
- if (done) {
19244
- break;
19245
- }
19246
- yield writer2.write(value);
19247
- }
19248
- yield writer2.close();
19249
- return writer2.info;
19734
+ return this.roomOutgoingDataStreamManager.streamText(options);
19735
+ });
19736
+ }
19737
+ /** Send a File to all participants in the room via the data channel.
19738
+ * @param file The File object payload
19739
+ * @param options.topic Topic identifier used to route the stream to appropriate handlers.
19740
+ * @param options.onProgress A callback function used to monitor the upload progress percentage.
19741
+ */
19742
+ sendFile(file, options) {
19743
+ return __awaiter(this, void 0, void 0, function* () {
19744
+ return this.roomOutgoingDataStreamManager.sendFile(file, options);
19250
19745
  });
19251
19746
  }
19747
+ /**
19748
+ * Stream bytes incrementally to participants in the room via the data channel.
19749
+ * For sending files, consider using {@link sendFile} instead.
19750
+ *
19751
+ * @param options.topic Topic identifier used to route the stream to appropriate handlers.
19752
+ */
19252
19753
  streamBytes(options) {
19253
19754
  return __awaiter(this, void 0, void 0, function* () {
19254
- var _a, _b, _c, _d, _e;
19255
- const streamId = (_a = options === null || options === void 0 ? void 0 : options.streamId) !== null && _a !== void 0 ? _a : crypto.randomUUID();
19256
- const destinationIdentities = options === null || options === void 0 ? void 0 : options.destinationIdentities;
19257
- const info = {
19258
- id: streamId,
19259
- mimeType: (_b = options === null || options === void 0 ? void 0 : options.mimeType) !== null && _b !== void 0 ? _b : "application/octet-stream",
19260
- topic: (_c = options === null || options === void 0 ? void 0 : options.topic) !== null && _c !== void 0 ? _c : "",
19261
- timestamp: Date.now(),
19262
- attributes: options === null || options === void 0 ? void 0 : options.attributes,
19263
- size: options === null || options === void 0 ? void 0 : options.totalSize,
19264
- name: (_d = options === null || options === void 0 ? void 0 : options.name) !== null && _d !== void 0 ? _d : "unknown"
19265
- };
19266
- const header = new DataStream_Header({
19267
- totalLength: numberToBigInt((_e = info.size) !== null && _e !== void 0 ? _e : 0),
19268
- mimeType: info.mimeType,
19269
- streamId,
19270
- topic: info.topic,
19271
- timestamp: numberToBigInt(Date.now()),
19272
- attributes: info.attributes,
19273
- contentHeader: {
19274
- case: "byteHeader",
19275
- value: new DataStream_ByteHeader({
19276
- name: info.name
19277
- })
19278
- }
19279
- });
19280
- const packet = new DataPacket({
19281
- destinationIdentities,
19282
- value: {
19283
- case: "streamHeader",
19284
- value: header
19285
- }
19286
- });
19287
- yield this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
19288
- let chunkId = 0;
19289
- const writeMutex = new _();
19290
- const engine = this.engine;
19291
- const log2 = this.log;
19292
- const writableStream = new WritableStream({
19293
- write(chunk) {
19294
- return __awaiter(this, void 0, void 0, function* () {
19295
- const unlock = yield writeMutex.lock();
19296
- let byteOffset = 0;
19297
- try {
19298
- while (byteOffset < chunk.byteLength) {
19299
- const subChunk = chunk.slice(byteOffset, byteOffset + STREAM_CHUNK_SIZE);
19300
- yield engine.waitForBufferStatusLow(DataPacket_Kind.RELIABLE);
19301
- const chunkPacket = new DataPacket({
19302
- destinationIdentities,
19303
- value: {
19304
- case: "streamChunk",
19305
- value: new DataStream_Chunk({
19306
- content: subChunk,
19307
- streamId,
19308
- chunkIndex: numberToBigInt(chunkId)
19309
- })
19310
- }
19311
- });
19312
- yield engine.sendDataPacket(chunkPacket, DataPacket_Kind.RELIABLE);
19313
- chunkId += 1;
19314
- byteOffset += subChunk.byteLength;
19315
- }
19316
- } finally {
19317
- unlock();
19318
- }
19319
- });
19320
- },
19321
- close() {
19322
- return __awaiter(this, void 0, void 0, function* () {
19323
- const trailer = new DataStream_Trailer({
19324
- streamId
19325
- });
19326
- const trailerPacket = new DataPacket({
19327
- destinationIdentities,
19328
- value: {
19329
- case: "streamTrailer",
19330
- value: trailer
19331
- }
19332
- });
19333
- yield engine.sendDataPacket(trailerPacket, DataPacket_Kind.RELIABLE);
19334
- });
19335
- },
19336
- abort(err) {
19337
- log2.error("Sink error:", err);
19338
- }
19339
- });
19340
- const byteWriter = new ByteStreamWriter(writableStream, info);
19341
- return byteWriter;
19755
+ return this.roomOutgoingDataStreamManager.streamBytes(options);
19342
19756
  });
19343
19757
  }
19344
19758
  /**
@@ -19356,7 +19770,7 @@ var LocalParticipant = class extends Participant {
19356
19770
  payload,
19357
19771
  responseTimeout = 1e4
19358
19772
  } = _ref3;
19359
- return function* () {
19773
+ return (function* () {
19360
19774
  const maxRoundTripLatency = 2e3;
19361
19775
  return new Promise((resolve, reject) => __awaiter(_this5, void 0, void 0, function* () {
19362
19776
  var _a2, _b, _c, _d;
@@ -19403,7 +19817,7 @@ var LocalParticipant = class extends Participant {
19403
19817
  participantIdentity: destinationIdentity
19404
19818
  });
19405
19819
  }));
19406
- }();
19820
+ })();
19407
19821
  });
19408
19822
  }
19409
19823
  /**
@@ -20122,10 +20536,6 @@ var Room = class _Room extends eventsExports.EventEmitter {
20122
20536
  this.log = livekitLogger;
20123
20537
  this.bufferedEvents = [];
20124
20538
  this.isResuming = false;
20125
- this.byteStreamControllers = /* @__PURE__ */ new Map();
20126
- this.textStreamControllers = /* @__PURE__ */ new Map();
20127
- this.byteStreamHandlers = /* @__PURE__ */ new Map();
20128
- this.textStreamHandlers = /* @__PURE__ */ new Map();
20129
20539
  this.rpcHandlers = /* @__PURE__ */ new Map();
20130
20540
  this.connect = (url, token2, opts) => __awaiter(this, void 0, void 0, function* () {
20131
20541
  var _a2;
@@ -20340,7 +20750,7 @@ var Room = class _Room extends eventsExports.EventEmitter {
20340
20750
  return __awaiter(_this, [...args_1], void 0, function() {
20341
20751
  var _this2 = this;
20342
20752
  let stopTracks = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : true;
20343
- return function* () {
20753
+ return (function* () {
20344
20754
  var _a2, _b2, _c2, _d;
20345
20755
  const unlock = yield _this2.disconnectLock.lock();
20346
20756
  try {
@@ -20366,7 +20776,7 @@ var Room = class _Room extends eventsExports.EventEmitter {
20366
20776
  } finally {
20367
20777
  unlock();
20368
20778
  }
20369
- }();
20779
+ })();
20370
20780
  });
20371
20781
  };
20372
20782
  this.onPageLeave = () => __awaiter(this, void 0, void 0, function* () {
@@ -20574,8 +20984,8 @@ var Room = class _Room extends eventsExports.EventEmitter {
20574
20984
  return;
20575
20985
  }
20576
20986
  const newStreamState = Track.streamStateFromProto(streamState.state);
20987
+ pub.track.setStreamState(newStreamState);
20577
20988
  if (newStreamState !== pub.track.streamState) {
20578
- pub.track.streamState = newStreamState;
20579
20989
  participant.emit(ParticipantEvent.TrackStreamStateChanged, pub, pub.track.streamState);
20580
20990
  this.emitWhenConnected(RoomEvent.TrackStreamStateChanged, pub, pub.track.streamState, participant);
20581
20991
  }
@@ -20615,12 +21025,8 @@ var Room = class _Room extends eventsExports.EventEmitter {
20615
21025
  this.handleChatMessage(participant, packet.value.value);
20616
21026
  } else if (packet.value.case === "metrics") {
20617
21027
  this.handleMetrics(packet.value.value, participant);
20618
- } else if (packet.value.case === "streamHeader") {
20619
- this.handleStreamHeader(packet.value.value, packet.participantIdentity);
20620
- } else if (packet.value.case === "streamChunk") {
20621
- this.handleStreamChunk(packet.value.value);
20622
- } else if (packet.value.case === "streamTrailer") {
20623
- this.handleStreamTrailer(packet.value.value);
21028
+ } else if (packet.value.case === "streamHeader" || packet.value.case === "streamChunk" || packet.value.case === "streamTrailer") {
21029
+ this.handleDataStream(packet);
20624
21030
  } else if (packet.value.case === "rpcRequest") {
20625
21031
  const rpc = packet.value.value;
20626
21032
  this.handleIncomingRpcRequest(packet.participantIdentity, rpc.id, rpc.method, rpc.payload, rpc.responseTimeoutMs, rpc.version);
@@ -20634,7 +21040,6 @@ var Room = class _Room extends eventsExports.EventEmitter {
20634
21040
  this.emit(RoomEvent.SipDTMFReceived, dtmf, participant);
20635
21041
  participant === null || participant === void 0 ? void 0 : participant.emit(ParticipantEvent.SipDTMFReceived, dtmf);
20636
21042
  };
20637
- this.bufferedSegments = /* @__PURE__ */ new Map();
20638
21043
  this.handleTranscription = (_remoteParticipant, transcription) => {
20639
21044
  const participant = transcription.transcribedParticipantIdentity === this.localParticipant.identity ? this.localParticipant : this.getParticipantByIdentity(transcription.transcribedParticipantIdentity);
20640
21045
  const publication = participant === null || participant === void 0 ? void 0 : participant.trackPublications.get(transcription.trackId);
@@ -20650,6 +21055,10 @@ var Room = class _Room extends eventsExports.EventEmitter {
20650
21055
  this.handleMetrics = (metrics, participant) => {
20651
21056
  this.emit(RoomEvent.MetricsReceived, metrics, participant);
20652
21057
  };
21058
+ this.handleDataStream = (packet) => {
21059
+ this.incomingDataStreamManager.handleDataStreamPacket(packet);
21060
+ };
21061
+ this.bufferedSegments = /* @__PURE__ */ new Map();
20653
21062
  this.handleAudioPlaybackStarted = () => {
20654
21063
  if (this.canPlaybackAudio) {
20655
21064
  return;
@@ -20783,8 +21192,10 @@ var Room = class _Room extends eventsExports.EventEmitter {
20783
21192
  this.options.videoCaptureDefaults = Object.assign(Object.assign({}, videoDefaults), options === null || options === void 0 ? void 0 : options.videoCaptureDefaults);
20784
21193
  this.options.publishDefaults = Object.assign(Object.assign({}, publishDefaults), options === null || options === void 0 ? void 0 : options.publishDefaults);
20785
21194
  this.maybeCreateEngine();
21195
+ this.incomingDataStreamManager = new IncomingDataStreamManager();
21196
+ this.outgoingDataStreamManager = new OutgoingDataStreamManager(this.engine, this.log);
20786
21197
  this.disconnectLock = new _();
20787
- this.localParticipant = new LocalParticipant("", "", this.engine, this.options, this.rpcHandlers);
21198
+ this.localParticipant = new LocalParticipant("", "", this.engine, this.options, this.rpcHandlers, this.outgoingDataStreamManager);
20788
21199
  if (this.options.videoCaptureDefaults.deviceId) {
20789
21200
  this.localParticipant.activeDeviceMap.set("videoinput", unwrapConstraint(this.options.videoCaptureDefaults.deviceId));
20790
21201
  }
@@ -20810,22 +21221,16 @@ var Room = class _Room extends eventsExports.EventEmitter {
20810
21221
  }
20811
21222
  }
20812
21223
  registerTextStreamHandler(topic, callback) {
20813
- if (this.textStreamHandlers.has(topic)) {
20814
- throw new TypeError('A text stream handler for topic "'.concat(topic, '" has already been set.'));
20815
- }
20816
- this.textStreamHandlers.set(topic, callback);
21224
+ return this.incomingDataStreamManager.registerTextStreamHandler(topic, callback);
20817
21225
  }
20818
21226
  unregisterTextStreamHandler(topic) {
20819
- this.textStreamHandlers.delete(topic);
21227
+ return this.incomingDataStreamManager.unregisterTextStreamHandler(topic);
20820
21228
  }
20821
- registerByteStreamHandler(topic, callback) {
20822
- if (this.byteStreamHandlers.has(topic)) {
20823
- throw new TypeError('A byte stream handler for topic "'.concat(topic, '" has already been set.'));
20824
- }
20825
- this.byteStreamHandlers.set(topic, callback);
21229
+ registerByteStreamHandler(topic, callback) {
21230
+ return this.incomingDataStreamManager.registerByteStreamHandler(topic, callback);
20826
21231
  }
20827
21232
  unregisterByteStreamHandler(topic) {
20828
- this.byteStreamHandlers.delete(topic);
21233
+ return this.incomingDataStreamManager.unregisterByteStreamHandler(topic);
20829
21234
  }
20830
21235
  /**
20831
21236
  * Establishes the participant as a receiver for calls of the specified RPC method.
@@ -20867,44 +21272,6 @@ var Room = class _Room extends eventsExports.EventEmitter {
20867
21272
  unregisterRpcMethod(method) {
20868
21273
  this.rpcHandlers.delete(method);
20869
21274
  }
20870
- handleIncomingRpcRequest(callerIdentity, requestId, method, payload, responseTimeout, version2) {
20871
- return __awaiter(this, void 0, void 0, function* () {
20872
- yield this.engine.publishRpcAck(callerIdentity, requestId);
20873
- if (version2 !== 1) {
20874
- yield this.engine.publishRpcResponse(callerIdentity, requestId, null, RpcError.builtIn("UNSUPPORTED_VERSION"));
20875
- return;
20876
- }
20877
- const handler = this.rpcHandlers.get(method);
20878
- if (!handler) {
20879
- yield this.engine.publishRpcResponse(callerIdentity, requestId, null, RpcError.builtIn("UNSUPPORTED_METHOD"));
20880
- return;
20881
- }
20882
- let responseError = null;
20883
- let responsePayload = null;
20884
- try {
20885
- const response = yield handler({
20886
- requestId,
20887
- callerIdentity,
20888
- payload,
20889
- responseTimeout
20890
- });
20891
- if (byteLength(response) > MAX_PAYLOAD_BYTES) {
20892
- responseError = RpcError.builtIn("RESPONSE_PAYLOAD_TOO_LARGE");
20893
- console.warn("RPC Response payload too large for ".concat(method));
20894
- } else {
20895
- responsePayload = response;
20896
- }
20897
- } catch (error) {
20898
- if (error instanceof RpcError) {
20899
- responseError = error;
20900
- } else {
20901
- console.warn("Uncaught error returned by RPC handler for ".concat(method, ". Returning APPLICATION_ERROR instead."), error);
20902
- responseError = RpcError.builtIn("APPLICATION_ERROR");
20903
- }
20904
- }
20905
- yield this.engine.publishRpcResponse(callerIdentity, requestId, responsePayload, responseError);
20906
- });
20907
- }
20908
21275
  /**
20909
21276
  * @experimental
20910
21277
  */
@@ -21069,6 +21436,9 @@ var Room = class _Room extends eventsExports.EventEmitter {
21069
21436
  if (this.e2eeManager) {
21070
21437
  this.e2eeManager.setupEngine(this.engine);
21071
21438
  }
21439
+ if (this.outgoingDataStreamManager) {
21440
+ this.outgoingDataStreamManager.setupEngine(this.engine);
21441
+ }
21072
21442
  }
21073
21443
  /**
21074
21444
  * getLocalDevices abstracts navigator.mediaDevices.enumerateDevices.
@@ -21279,7 +21649,7 @@ var Room = class _Room extends eventsExports.EventEmitter {
21279
21649
  return __awaiter(this, arguments, void 0, function(kind, deviceId) {
21280
21650
  var _this3 = this;
21281
21651
  let exact = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : true;
21282
- return function* () {
21652
+ return (function* () {
21283
21653
  var _a, _b, _c, _d, _e, _f;
21284
21654
  var _g;
21285
21655
  let success = true;
@@ -21353,7 +21723,7 @@ var Room = class _Room extends eventsExports.EventEmitter {
21353
21723
  _this3.emit(RoomEvent.ActiveDeviceChanged, kind, deviceId);
21354
21724
  }
21355
21725
  return success;
21356
- }();
21726
+ })();
21357
21727
  });
21358
21728
  }
21359
21729
  setupLocalParticipantEvents() {
@@ -21415,7 +21785,10 @@ var Room = class _Room extends eventsExports.EventEmitter {
21415
21785
  adaptiveStreamSettings = {};
21416
21786
  }
21417
21787
  }
21418
- participant.addSubscribedMediaTrack(mediaTrack, trackId, stream, receiver, adaptiveStreamSettings);
21788
+ const publication = participant.addSubscribedMediaTrack(mediaTrack, trackId, stream, receiver, adaptiveStreamSettings);
21789
+ if ((publication === null || publication === void 0 ? void 0 : publication.isEncrypted) && !this.e2eeManager) {
21790
+ this.emit(RoomEvent.EncryptionError, new Error("Encrypted ".concat(publication.source, " track received from participant ").concat(participant.sid, ", but room does not have encryption enabled!")));
21791
+ }
21419
21792
  }
21420
21793
  handleDisconnect() {
21421
21794
  let shouldStopTracks = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : true;
@@ -21425,6 +21798,7 @@ var Room = class _Room extends eventsExports.EventEmitter {
21425
21798
  this.isResuming = false;
21426
21799
  this.bufferedEvents = [];
21427
21800
  this.transcriptionReceivedTimes.clear();
21801
+ this.incomingDataStreamManager.clearHandlersAndControllers();
21428
21802
  if (this.state === ConnectionState.Disconnected) {
21429
21803
  return;
21430
21804
  }
@@ -21475,6 +21849,7 @@ var Room = class _Room extends eventsExports.EventEmitter {
21475
21849
  if (!participant) {
21476
21850
  return;
21477
21851
  }
21852
+ this.incomingDataStreamManager.validateParticipantHasNoActiveDataStreams(identity);
21478
21853
  participant.trackPublications.forEach((publication) => {
21479
21854
  participant.unpublishTrack(publication.trackSid, true);
21480
21855
  });
@@ -21482,99 +21857,44 @@ var Room = class _Room extends eventsExports.EventEmitter {
21482
21857
  participant.setDisconnected();
21483
21858
  (_a = this.localParticipant) === null || _a === void 0 ? void 0 : _a.handleParticipantDisconnected(participant.identity);
21484
21859
  }
21485
- handleStreamHeader(streamHeader, participantIdentity) {
21860
+ handleIncomingRpcRequest(callerIdentity, requestId, method, payload, responseTimeout, version2) {
21486
21861
  return __awaiter(this, void 0, void 0, function* () {
21487
- var _a;
21488
- if (streamHeader.contentHeader.case === "byteHeader") {
21489
- const streamHandlerCallback = this.byteStreamHandlers.get(streamHeader.topic);
21490
- if (!streamHandlerCallback) {
21491
- this.log.debug("ignoring incoming byte stream due to no handler for topic", streamHeader.topic);
21492
- return;
21493
- }
21494
- let streamController;
21495
- const info = {
21496
- id: streamHeader.streamId,
21497
- name: (_a = streamHeader.contentHeader.value.name) !== null && _a !== void 0 ? _a : "unknown",
21498
- mimeType: streamHeader.mimeType,
21499
- size: streamHeader.totalLength ? Number(streamHeader.totalLength) : void 0,
21500
- topic: streamHeader.topic,
21501
- timestamp: bigIntToNumber(streamHeader.timestamp),
21502
- attributes: streamHeader.attributes
21503
- };
21504
- const stream = new ReadableStream({
21505
- start: (controller) => {
21506
- streamController = controller;
21507
- this.byteStreamControllers.set(streamHeader.streamId, {
21508
- info,
21509
- controller: streamController,
21510
- startTime: Date.now()
21511
- });
21512
- }
21513
- });
21514
- streamHandlerCallback(new ByteStreamReader(info, stream, bigIntToNumber(streamHeader.totalLength)), {
21515
- identity: participantIdentity
21862
+ yield this.engine.publishRpcAck(callerIdentity, requestId);
21863
+ if (version2 !== 1) {
21864
+ yield this.engine.publishRpcResponse(callerIdentity, requestId, null, RpcError.builtIn("UNSUPPORTED_VERSION"));
21865
+ return;
21866
+ }
21867
+ const handler = this.rpcHandlers.get(method);
21868
+ if (!handler) {
21869
+ yield this.engine.publishRpcResponse(callerIdentity, requestId, null, RpcError.builtIn("UNSUPPORTED_METHOD"));
21870
+ return;
21871
+ }
21872
+ let responseError = null;
21873
+ let responsePayload = null;
21874
+ try {
21875
+ const response = yield handler({
21876
+ requestId,
21877
+ callerIdentity,
21878
+ payload,
21879
+ responseTimeout
21516
21880
  });
21517
- } else if (streamHeader.contentHeader.case === "textHeader") {
21518
- const streamHandlerCallback = this.textStreamHandlers.get(streamHeader.topic);
21519
- if (!streamHandlerCallback) {
21520
- this.log.debug("ignoring incoming text stream due to no handler for topic", streamHeader.topic);
21521
- return;
21881
+ if (byteLength(response) > MAX_PAYLOAD_BYTES) {
21882
+ responseError = RpcError.builtIn("RESPONSE_PAYLOAD_TOO_LARGE");
21883
+ console.warn("RPC Response payload too large for ".concat(method));
21884
+ } else {
21885
+ responsePayload = response;
21886
+ }
21887
+ } catch (error) {
21888
+ if (error instanceof RpcError) {
21889
+ responseError = error;
21890
+ } else {
21891
+ console.warn("Uncaught error returned by RPC handler for ".concat(method, ". Returning APPLICATION_ERROR instead."), error);
21892
+ responseError = RpcError.builtIn("APPLICATION_ERROR");
21522
21893
  }
21523
- let streamController;
21524
- const info = {
21525
- id: streamHeader.streamId,
21526
- mimeType: streamHeader.mimeType,
21527
- size: streamHeader.totalLength ? Number(streamHeader.totalLength) : void 0,
21528
- topic: streamHeader.topic,
21529
- timestamp: Number(streamHeader.timestamp),
21530
- attributes: streamHeader.attributes
21531
- };
21532
- const stream = new ReadableStream({
21533
- start: (controller) => {
21534
- streamController = controller;
21535
- this.textStreamControllers.set(streamHeader.streamId, {
21536
- info,
21537
- controller: streamController,
21538
- startTime: Date.now()
21539
- });
21540
- }
21541
- });
21542
- streamHandlerCallback(new TextStreamReader(info, stream, bigIntToNumber(streamHeader.totalLength)), {
21543
- identity: participantIdentity
21544
- });
21545
21894
  }
21895
+ yield this.engine.publishRpcResponse(callerIdentity, requestId, responsePayload, responseError);
21546
21896
  });
21547
21897
  }
21548
- handleStreamChunk(chunk) {
21549
- const fileBuffer = this.byteStreamControllers.get(chunk.streamId);
21550
- if (fileBuffer) {
21551
- if (chunk.content.length > 0) {
21552
- fileBuffer.controller.enqueue(chunk);
21553
- }
21554
- }
21555
- const textBuffer = this.textStreamControllers.get(chunk.streamId);
21556
- if (textBuffer) {
21557
- if (chunk.content.length > 0) {
21558
- textBuffer.controller.enqueue(chunk);
21559
- }
21560
- }
21561
- }
21562
- handleStreamTrailer(trailer) {
21563
- const textBuffer = this.textStreamControllers.get(trailer.streamId);
21564
- if (textBuffer) {
21565
- textBuffer.info.attributes = Object.assign(Object.assign({}, textBuffer.info.attributes), trailer.attributes);
21566
- textBuffer.controller.close();
21567
- this.textStreamControllers.delete(trailer.streamId);
21568
- }
21569
- const fileBuffer = this.byteStreamControllers.get(trailer.streamId);
21570
- if (fileBuffer) {
21571
- {
21572
- fileBuffer.info.attributes = Object.assign(Object.assign({}, fileBuffer.info.attributes), trailer.attributes);
21573
- fileBuffer.controller.close();
21574
- this.byteStreamControllers.delete(trailer.streamId);
21575
- }
21576
- }
21577
- }
21578
21898
  /**
21579
21899
  * attempt to select the default devices if the previously selected devices are no longer available after a device change event
21580
21900
  */
@@ -22729,15 +23049,24 @@ var GlobalStore = {
22729
23049
  var navigation;
22730
23050
  var navigationHandler = null;
22731
23051
  function setNavigationHandler(handler) {
23052
+ console.log("\u{1F9ED} setNavigationHandler called with:", !!handler);
22732
23053
  navigationHandler = handler;
22733
23054
  }
22734
23055
  function navigate(path, params) {
22735
23056
  const safeParams = params || {};
22736
23057
  const absolutePath = path.startsWith("/") ? path : `/${path}`;
23058
+ console.log("\u{1F9ED} navigate() called with:", {
23059
+ path,
23060
+ absolutePath,
23061
+ safeParams,
23062
+ hasNavigationHandler: !!navigationHandler
23063
+ });
22737
23064
  if (navigationHandler) {
22738
23065
  try {
23066
+ console.log("\u{1F9ED} Using navigationHandler:", absolutePath, safeParams);
22739
23067
  navigationHandler(absolutePath, safeParams);
22740
23068
  } catch (error) {
23069
+ console.error("\u{1F9ED} NavigationHandler error:", error);
22741
23070
  }
22742
23071
  return;
22743
23072
  }
@@ -22752,27 +23081,46 @@ function navigate(path, params) {
22752
23081
  navigation.push(fullPath);
22753
23082
  } else {
22754
23083
  if (typeof window !== "undefined") {
22755
- window.location.href = fullPath;
23084
+ if (window.location.hash && window.location.hash.startsWith("#")) {
23085
+ window.location.hash = fullPath;
23086
+ } else {
23087
+ window.location.href = fullPath;
23088
+ }
22756
23089
  }
22757
23090
  }
22758
23091
  }
22759
23092
  var getCurrentPath = () => {
22760
23093
  if (typeof window === "undefined") return "";
23094
+ if (window.location.hash && window.location.hash.startsWith("#")) {
23095
+ const hashPath = window.location.hash.substring(1);
23096
+ return hashPath.split("?")[0];
23097
+ }
22761
23098
  return window.location.pathname;
22762
23099
  };
22763
23100
  var getSearchParams = () => {
22764
23101
  if (typeof window === "undefined") return new URLSearchParams();
23102
+ if (window.location.hash && window.location.hash.includes("?")) {
23103
+ const queryString = window.location.hash.split("?")[1];
23104
+ return new URLSearchParams(queryString);
23105
+ }
22765
23106
  return new URLSearchParams(window.location.search);
22766
23107
  };
22767
23108
  var safeNavigate = (name, params = {}) => {
23109
+ console.log("\u{1F9ED} safeNavigate called with:", { name, params });
22768
23110
  if (name) {
22769
23111
  navigate(name, params);
22770
23112
  } else {
23113
+ console.log("\u{1F9ED} safeNavigate: no name provided, skipping navigation");
22771
23114
  }
22772
23115
  };
22773
23116
  function getCurrentScreenName() {
22774
23117
  try {
22775
23118
  const path = getCurrentPath();
23119
+ const pathParams = getCurrentPathParams();
23120
+ if (path && Object.keys(pathParams).length > 0) {
23121
+ const paramString = Object.entries(pathParams).map(([key, value]) => `${key}=${value}`).join(",");
23122
+ return `${path}?${paramString}`;
23123
+ }
22776
23124
  return path || "UnknownScreen";
22777
23125
  } catch (e2) {
22778
23126
  return "UnknownScreen";
@@ -22794,6 +23142,45 @@ function getCurrentRouteParams() {
22794
23142
  return {};
22795
23143
  }
22796
23144
  }
23145
+ function getCurrentPathParams() {
23146
+ try {
23147
+ const currentPath = getCurrentPath();
23148
+ const params = {};
23149
+ const numericIdMatch = currentPath.match(/\/(\d+)(?:\/|$)/);
23150
+ if (numericIdMatch) {
23151
+ params.id = numericIdMatch[1];
23152
+ }
23153
+ const uuidMatch = currentPath.match(
23154
+ /\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:\/|$)/i
23155
+ );
23156
+ if (uuidMatch) {
23157
+ params.uuid = uuidMatch[1];
23158
+ }
23159
+ const slugMatch = currentPath.match(/\/([a-z0-9-]+)(?:\/|$)/i);
23160
+ if (slugMatch && !numericIdMatch && !uuidMatch) {
23161
+ params.slug = slugMatch[1];
23162
+ }
23163
+ return params;
23164
+ } catch (e2) {
23165
+ return {};
23166
+ }
23167
+ }
23168
+ function resolveRoutePath(routePath, params) {
23169
+ try {
23170
+ let resolvedPath = routePath;
23171
+ Object.entries(params).forEach(([key, value]) => {
23172
+ const placeholder = `:${key}`;
23173
+ if (resolvedPath.includes(placeholder)) {
23174
+ resolvedPath = resolvedPath.replace(placeholder, value);
23175
+ }
23176
+ });
23177
+ resolvedPath = resolvedPath.replace(/:\w+/g, "");
23178
+ resolvedPath = resolvedPath.replace(/\/+/g, "/");
23179
+ return resolvedPath;
23180
+ } catch (e2) {
23181
+ return routePath;
23182
+ }
23183
+ }
22797
23184
  function onStateChange() {
22798
23185
  const routeName = getCurrentScreenName();
22799
23186
  const params = getCurrentRouteParams();
@@ -22912,13 +23299,23 @@ function getElementPath2(element) {
22912
23299
  }
22913
23300
 
22914
23301
  // src/utils/element-service.ts
22915
- var INTERACTIVE_ELEMENT_SELECTOR = 'a, button, input, textarea, select, [role="button"], [onclick], [data-ansyr-static], [data-ansyr-dynamic]';
23302
+ var INTERACTIVE_ELEMENT_SELECTOR = 'a, button, select, [role="button"], [role="link"], [role="tab"], [onclick], [onmousedown], [onmouseup], [ontouchstart], [ontouchend], [onkeydown], [onkeyup], [onkeypress], [onchange], [onsubmit], [onfocus], [onblur], [data-ansyr-static], [data-ansyr-dynamic]';
23303
+ var elementCache = /* @__PURE__ */ new Map();
23304
+ var cacheTimestamp = 0;
23305
+ var CACHE_TTL = 5e3;
22916
23306
  function getInteractiveElements() {
22917
23307
  const elements = document.querySelectorAll(INTERACTIVE_ELEMENT_SELECTOR);
22918
23308
  return Array.from(new Set(Array.from(elements)));
22919
23309
  }
22920
23310
  function getImmediateText(element) {
22921
23311
  let text = "";
23312
+ const textAttributes = ["label", "text", "placeholder", "title", "alt", "aria-label"];
23313
+ for (const attr of textAttributes) {
23314
+ const value = element.getAttribute(attr);
23315
+ if (value) {
23316
+ text += value + " ";
23317
+ }
23318
+ }
22922
23319
  if (element.childNodes) {
22923
23320
  for (const node of Array.from(element.childNodes)) {
22924
23321
  if (node.nodeType === 3) {
@@ -22928,12 +23325,30 @@ function getImmediateText(element) {
22928
23325
  }
22929
23326
  return text.trim();
22930
23327
  }
22931
- function captureFullDOMStructure() {
22932
- console.log("\u{1F333} Capturing full DOM structure for Cuekit...");
22933
- const interactiveElements = [];
23328
+ function executeAction(action) {
23329
+ console.log("\u{1F3AF} Executing element action:", action);
23330
+ const { action_type, target_element, target } = action;
23331
+ switch (action_type) {
23332
+ case "click":
23333
+ return clickElement(target_element);
23334
+ case "navigate":
23335
+ return navigateToElement(target_element || target);
23336
+ case "input":
23337
+ case "focus":
23338
+ return focusElement(target_element);
23339
+ case "toggle":
23340
+ return toggleElement(target_element);
23341
+ default:
23342
+ console.warn(`\u26A0\uFE0F Unknown action type: ${action_type}`);
23343
+ return false;
23344
+ }
23345
+ }
23346
+ function captureAllInteractiveElements() {
23347
+ console.log("\u{1F333} Capturing ALL interactive elements for Cuekit...");
23348
+ const interactiveElements = {};
22934
23349
  const descriptionsMap = /* @__PURE__ */ new Map();
22935
- document.querySelectorAll("[data-for]").forEach((el) => {
22936
- const targetId = el.getAttribute("data-for");
23350
+ document.querySelectorAll("[data-ansyr-for]").forEach((el) => {
23351
+ const targetId = el.getAttribute("data-ansyr-for");
22937
23352
  if (!targetId) return;
22938
23353
  const tags = [];
22939
23354
  const description = el.getAttribute("data-ansyr-description");
@@ -22948,110 +23363,115 @@ function captureFullDOMStructure() {
22948
23363
  descriptionsMap.set(targetId, [...existingTags, ...tags]);
22949
23364
  }
22950
23365
  });
22951
- const allElements = getInteractiveElements();
22952
- allElements.forEach((element) => {
23366
+ const allInteractiveElements = getInteractiveElements();
23367
+ console.log("\u{1F333} Found", allInteractiveElements.length, "interactive elements");
23368
+ allInteractiveElements.forEach((element) => {
23369
+ if (!(element instanceof HTMLElement)) return;
22953
23370
  const style = getComputedStyle(element);
22954
- if (element.closest("[data-cuekit-ignore]") || !isElementClickable(element) || element.tagName.toLowerCase() === "script" || style.display === "none" || style.visibility === "hidden") {
23371
+ if (element.closest("[data-cuekit-ignore]") || element.tagName.toLowerCase() === "script" || style.display === "none" || style.visibility === "hidden") {
22955
23372
  return;
22956
23373
  }
23374
+ let elementId = null;
22957
23375
  const staticId = element.getAttribute("data-ansyr-static");
22958
23376
  const dynamicId = element.getAttribute("data-ansyr-dynamic");
22959
- const id = staticId || dynamicId;
23377
+ if (staticId) {
23378
+ elementId = staticId;
23379
+ console.log("\u{1F333} Using pre-assigned static ID:", elementId);
23380
+ } else if (dynamicId) {
23381
+ elementId = dynamicId;
23382
+ console.log("\u{1F333} Using pre-assigned dynamic ID:", elementId);
23383
+ } else {
23384
+ elementId = generateStableDOMId(element);
23385
+ console.log("\u{1F333} Calculated stable DOM ID:", elementId);
23386
+ }
23387
+ if (!elementId) {
23388
+ console.log("\u{1F333} No ID could be determined for element:", element);
23389
+ return;
23390
+ }
22960
23391
  const tags = [];
22961
23392
  const directDescription = element.getAttribute("data-ansyr-description");
22962
23393
  if (directDescription) {
22963
23394
  tags.push(directDescription);
22964
23395
  }
22965
- if (id && descriptionsMap.has(id)) {
22966
- tags.push(...descriptionsMap.get(id) || []);
23396
+ if (descriptionsMap.has(elementId)) {
23397
+ tags.push(...descriptionsMap.get(elementId) || []);
22967
23398
  }
22968
- const dto = {
22969
- testID: id || generateStableDOMId(element),
22970
- type: element.tagName.toLowerCase(),
22971
- textContent: getImmediateText(element) || element.textContent?.trim() || "",
22972
- tags
22973
- };
22974
- interactiveElements.push(dto);
23399
+ const textContent = getImmediateText(element) || element.textContent?.trim() || "";
23400
+ interactiveElements[elementId] = [textContent, ...tags];
23401
+ console.log("\u{1F333} Captured element:", {
23402
+ id: elementId,
23403
+ tagName: element.tagName,
23404
+ textContent: textContent.substring(0, 50),
23405
+ hasStaticId: !!staticId,
23406
+ hasDynamicId: !!dynamicId,
23407
+ isCalculated: !staticId && !dynamicId
23408
+ });
22975
23409
  });
22976
23410
  const result = {
22977
23411
  components: interactiveElements
22978
23412
  };
22979
- console.log("\u{1F333} Full DOM structure captured:", result);
23413
+ console.log("\u{1F333} All interactive elements captured:", result);
22980
23414
  return result;
22981
23415
  }
22982
- function isElementClickable(element) {
22983
- const interactiveSelectors = [
22984
- "button",
22985
- "a",
22986
- "input",
22987
- "select",
22988
- "textarea",
22989
- '[role="button"]',
22990
- '[role="link"]',
22991
- '[role="tab"]',
22992
- "[data-onclick-id]",
22993
- "[data-on-press-id]",
22994
- "[onclick]",
22995
- "[onmousedown]",
22996
- "[onmouseup]",
22997
- "[ontouchstart]",
22998
- "[ontouchend]",
22999
- "[onkeydown]",
23000
- "[onkeyup]",
23001
- "[onkeypress]"
23002
- ];
23003
- for (const selector of interactiveSelectors) {
23004
- if (element.matches(selector)) {
23005
- return true;
23006
- }
23007
- }
23008
- const hasClickEvents = element.onclick !== null || element.getAttribute("onclick") !== null;
23009
- const hasInteractiveEvents = element.ontouchstart !== null || element.getAttribute("ontouchstart") !== null || element.ontouchend !== null || element.getAttribute("ontouchend") !== null || element.onkeydown !== null || element.getAttribute("onkeydown") !== null || element.onkeyup !== null || element.getAttribute("onkeyup") !== null || element.onkeypress !== null || element.getAttribute("onkeypress") !== null;
23010
- const hasPointerCursor = element.style.cursor === "pointer" || getComputedStyle(element).cursor === "pointer";
23011
- const hasTabIndex = element.hasAttribute("tabindex") && parseInt(element.getAttribute("tabindex") || "0") >= 0;
23012
- const hasInteractiveDataAttrs = element.hasAttribute("data-clickable") || element.hasAttribute("data-interactive") || element.hasAttribute("data-action") || element.hasAttribute("data-handler");
23013
- const hasInteractiveAria = element.hasAttribute("aria-pressed") || element.hasAttribute("aria-expanded") || element.hasAttribute("aria-selected") || element.hasAttribute("aria-checked");
23014
- return hasClickEvents || hasInteractiveEvents || hasPointerCursor || hasTabIndex || hasInteractiveDataAttrs || hasInteractiveAria;
23416
+ function clearElementCache() {
23417
+ elementCache.clear();
23418
+ cacheTimestamp = 0;
23015
23419
  }
23016
- function executeAction(action) {
23017
- console.log("\u{1F3AF} Executing element action:", action);
23018
- const { action_type, target_element, target } = action;
23019
- switch (action_type) {
23020
- case "click":
23021
- return clickElement(target_element);
23022
- case "navigate":
23023
- return navigateToElement(target_element || target);
23024
- case "input":
23025
- case "focus":
23026
- return focusElement(target_element);
23027
- case "toggle":
23028
- return toggleElement(target_element);
23029
- default:
23030
- console.warn(`\u26A0\uFE0F Unknown action type: ${action_type}`);
23031
- return false;
23420
+ function validateDynamicElements() {
23421
+ if (false) {
23422
+ const elements = document.querySelectorAll("[data-ansyr-dynamic]");
23423
+ const ids = /* @__PURE__ */ new Set();
23424
+ const duplicates = [];
23425
+ elements.forEach((element) => {
23426
+ const id = element.getAttribute("data-ansyr-dynamic");
23427
+ if (id) {
23428
+ if (ids.has(id)) {
23429
+ duplicates.push(id);
23430
+ }
23431
+ ids.add(id);
23432
+ }
23433
+ });
23434
+ if (duplicates.length > 0) {
23435
+ console.warn("\u{1F6A8} CueKit: Duplicate dynamic IDs found:", duplicates);
23436
+ console.warn(
23437
+ "This can cause incorrect element targeting. Ensure each dynamic element has a unique identifier."
23438
+ );
23439
+ }
23032
23440
  }
23033
23441
  }
23034
- function getFullDOMStructure() {
23035
- return captureFullDOMStructure();
23036
- }
23037
23442
  function clickElement(elementId) {
23443
+ console.log("\u{1F5B1}\uFE0F clickElement called with:", elementId);
23038
23444
  if (!elementId) {
23445
+ console.log("\u{1F5B1}\uFE0F clickElement: no elementId provided");
23039
23446
  return false;
23040
23447
  }
23041
23448
  const domElement = findDOMElementById(elementId);
23449
+ console.log("\u{1F5B1}\uFE0F clickElement: found DOM element:", domElement);
23042
23450
  if (domElement) {
23451
+ console.log("\u{1F5B1}\uFE0F clickElement: attempting to click element:", {
23452
+ tagName: domElement.tagName,
23453
+ id: domElement.id,
23454
+ className: domElement.className,
23455
+ textContent: domElement.textContent?.substring(0, 50)
23456
+ });
23043
23457
  domElement.click();
23458
+ console.log("\u{1F5B1}\uFE0F clickElement: click() called successfully");
23044
23459
  return true;
23045
23460
  }
23461
+ console.log("\u{1F5B1}\uFE0F clickElement: element not found");
23046
23462
  return false;
23047
23463
  }
23048
23464
  function navigateToElement(target) {
23465
+ console.log("\u{1F9ED} navigateToElement called with:", target);
23049
23466
  if (!target) {
23467
+ console.log("\u{1F9ED} navigateToElement: no target provided");
23050
23468
  return false;
23051
23469
  }
23052
23470
  if (target.includes("/") || target.startsWith("http")) {
23471
+ console.log("\u{1F9ED} navigateToElement: using safeNavigate for path:", target);
23053
23472
  safeNavigate(target, {});
23054
23473
  } else {
23474
+ console.log("\u{1F9ED} navigateToElement: using handleNavigationAndClick for element:", target);
23055
23475
  handleNavigationAndClick(target, target);
23056
23476
  }
23057
23477
  return true;
@@ -23090,21 +23510,82 @@ function toggleElement(elementId) {
23090
23510
  }
23091
23511
  }
23092
23512
  function findDOMElementById(elementId) {
23513
+ console.log("\u{1F50D} findDOMElementById called with:", elementId);
23093
23514
  if (!elementId) {
23515
+ console.log("\u{1F50D} findDOMElementById: no elementId provided");
23094
23516
  return null;
23095
23517
  }
23096
- const interactiveElements = getInteractiveElements();
23097
- for (const element of interactiveElements) {
23098
- if (element instanceof HTMLElement) {
23518
+ const now = Date.now();
23519
+ if (now - cacheTimestamp < CACHE_TTL && elementCache.has(elementId)) {
23520
+ const cachedElement = elementCache.get(elementId);
23521
+ console.log("\u{1F50D} findDOMElementById: found in cache:", cachedElement);
23522
+ if (document.contains(cachedElement)) {
23523
+ console.log("\u{1F50D} findDOMElementById: returning cached element");
23524
+ return cachedElement;
23525
+ } else {
23526
+ console.log("\u{1F50D} findDOMElementById: cached element no longer in DOM, removing from cache");
23527
+ elementCache.delete(elementId);
23528
+ }
23529
+ }
23530
+ let foundElement = null;
23531
+ console.log(
23532
+ "\u{1F50D} findDOMElementById: checking for static element with selector:",
23533
+ `[data-ansyr-static="${elementId}"]`
23534
+ );
23535
+ const staticElement = document.querySelector(`[data-ansyr-static="${elementId}"]`);
23536
+ if (staticElement instanceof HTMLElement) {
23537
+ console.log("\u{1F50D} findDOMElementById: found static element:", staticElement);
23538
+ foundElement = staticElement;
23539
+ } else {
23540
+ console.log(
23541
+ "\u{1F50D} findDOMElementById: checking for dynamic element with selector:",
23542
+ `[data-ansyr-dynamic="${elementId}"]`
23543
+ );
23544
+ const dynamicElement = document.querySelector(`[data-ansyr-dynamic="${elementId}"]`);
23545
+ if (dynamicElement instanceof HTMLElement) {
23546
+ console.log("\u{1F50D} findDOMElementById: found dynamic element:", dynamicElement);
23547
+ foundElement = dynamicElement;
23548
+ }
23549
+ }
23550
+ if (!foundElement) {
23551
+ console.log(
23552
+ "\u{1F50D} findDOMElementById: no pre-assigned element found, scanning all interactive elements"
23553
+ );
23554
+ const interactiveElements = getInteractiveElements();
23555
+ console.log("\u{1F50D} findDOMElementById: found", interactiveElements.length, "interactive elements");
23556
+ for (const element of interactiveElements) {
23557
+ if (!(element instanceof HTMLElement)) continue;
23099
23558
  const staticId = element.getAttribute("data-ansyr-static");
23100
23559
  const dynamicId = element.getAttribute("data-ansyr-dynamic");
23101
- const currentElementId = staticId || dynamicId || generateStableDOMId(element);
23560
+ let currentElementId = null;
23561
+ if (staticId) {
23562
+ currentElementId = staticId;
23563
+ } else if (dynamicId) {
23564
+ currentElementId = dynamicId;
23565
+ } else {
23566
+ currentElementId = generateStableDOMId(element);
23567
+ }
23102
23568
  if (currentElementId === elementId) {
23103
- return element;
23569
+ console.log("\u{1F50D} findDOMElementById: found element by ID match:", {
23570
+ element,
23571
+ id: currentElementId,
23572
+ hasStaticId: !!staticId,
23573
+ hasDynamicId: !!dynamicId,
23574
+ isCalculated: !staticId && !dynamicId
23575
+ });
23576
+ foundElement = element;
23577
+ break;
23104
23578
  }
23105
23579
  }
23580
+ if (!foundElement) {
23581
+ console.log("\u{1F50D} findDOMElementById: element not found in interactive elements scan");
23582
+ }
23583
+ }
23584
+ if (foundElement) {
23585
+ elementCache.set(elementId, foundElement);
23586
+ cacheTimestamp = now;
23106
23587
  }
23107
- return null;
23588
+ return foundElement;
23108
23589
  }
23109
23590
 
23110
23591
  // src/utils/webrtc-service.ts
@@ -23123,8 +23604,16 @@ function setAudioContainer(newAudioContainerRef) {
23123
23604
  audioContainerRef = newAudioContainerRef;
23124
23605
  }
23125
23606
  function setWebRTCCallbacks(newCallbacks) {
23607
+ console.log("\u{1F4E1} setWebRTCCallbacks called with:", {
23608
+ hasOnNavigationCommand: !!newCallbacks.onNavigationCommand,
23609
+ hasOnConnectionStateChange: !!newCallbacks.onConnectionStateChange,
23610
+ hasOnParticipantUpdate: !!newCallbacks.onParticipantUpdate
23611
+ });
23126
23612
  callbacks = newCallbacks;
23127
23613
  }
23614
+ function getCurrentCallbacks() {
23615
+ return callbacks;
23616
+ }
23128
23617
  async function authenticate(userIdentity, apiKey, appId) {
23129
23618
  try {
23130
23619
  const authPayload = {
@@ -23215,12 +23704,34 @@ function setupEventListeners() {
23215
23704
  track.detach().forEach((element) => element.remove());
23216
23705
  }).on(RoomEvent.DataReceived, (payload, participant) => {
23217
23706
  const decodedPayload = new TextDecoder().decode(payload);
23218
- try {
23219
- const message = JSON.parse(decodedPayload);
23220
- callbacks.onNavigationCommand?.(message);
23221
- } catch (error) {
23222
- const message = decodedPayload;
23223
- callbacks.onNavigationCommand?.({ type: "raw_text", data: message });
23707
+ console.log("\u{1F4E1} WebRTC DataReceived:", { decodedPayload, participant: participant?.identity });
23708
+ if (decodedPayload.includes("|")) {
23709
+ const parts = decodedPayload.split("|");
23710
+ const textPart = parts[0];
23711
+ const jsonPart = parts[1];
23712
+ console.log("\u{1F4E1} WebRTC Pipe-separated message:", { textPart, jsonPart });
23713
+ if (textPart) {
23714
+ callbacks.onNavigationCommand?.({ type: "speech_text", data: textPart });
23715
+ }
23716
+ if (jsonPart) {
23717
+ try {
23718
+ const message = JSON.parse(jsonPart);
23719
+ console.log("\u{1F4E1} WebRTC Parsed JSON message:", message);
23720
+ callbacks.onNavigationCommand?.(message);
23721
+ } catch (error) {
23722
+ console.log("\u{1F4E1} WebRTC JSON parse error for JSON part:", error, "JSON part:", jsonPart);
23723
+ }
23724
+ }
23725
+ } else {
23726
+ try {
23727
+ const message = JSON.parse(decodedPayload);
23728
+ console.log("\u{1F4E1} WebRTC Parsed message:", message);
23729
+ callbacks.onNavigationCommand?.(message);
23730
+ } catch (error) {
23731
+ console.log("\u{1F4E1} WebRTC JSON parse error:", error, "Raw payload:", decodedPayload);
23732
+ const message = decodedPayload;
23733
+ callbacks.onNavigationCommand?.({ type: "raw_text", data: message });
23734
+ }
23224
23735
  }
23225
23736
  }).on(RoomEvent.Disconnected, () => {
23226
23737
  setWebRTCConnectionState({ isConnected: false, isConnecting: false });
@@ -23274,17 +23785,19 @@ async function sendUserCommand(command) {
23274
23785
  await sendData(command);
23275
23786
  }
23276
23787
  async function sendRuntimeData() {
23788
+ console.log("\u{1F9E0} checking room:", room);
23277
23789
  if (!room) {
23278
23790
  return;
23279
23791
  }
23792
+ console.log("\u{1F9E0} Sending runtime data", room);
23280
23793
  try {
23281
- const domStructure = captureFullDOMStructure();
23794
+ const allInteractiveElements = captureAllInteractiveElements();
23282
23795
  const screenName = getCurrentScreenName();
23283
23796
  const response = {
23284
23797
  type: "runtime_data_response",
23285
23798
  data: {
23286
- components: domStructure.components,
23287
- current_screen: screenName
23799
+ components: allInteractiveElements.components,
23800
+ currentRoute: screenName
23288
23801
  }
23289
23802
  };
23290
23803
  await sendData(JSON.stringify(response));
@@ -23349,6 +23862,8 @@ export {
23349
23862
  setWebRTCConfig,
23350
23863
  GlobalStore,
23351
23864
  setNavigationHandler,
23865
+ getCurrentPathParams,
23866
+ resolveRoutePath,
23352
23867
  onStateChange,
23353
23868
  WEBRTC_BACKEND_SERVER_URL,
23354
23869
  RoomEvent,
@@ -23356,12 +23871,14 @@ export {
23356
23871
  Track,
23357
23872
  createAudioAnalyser,
23358
23873
  ConnectionState,
23359
- captureFullDOMStructure,
23360
23874
  executeAction,
23361
- getFullDOMStructure,
23875
+ captureAllInteractiveElements,
23876
+ clearElementCache,
23877
+ validateDynamicElements,
23362
23878
  setServerUrl,
23363
23879
  setAudioContainer,
23364
23880
  setWebRTCCallbacks,
23881
+ getCurrentCallbacks,
23365
23882
  authenticate,
23366
23883
  connectToRoom,
23367
23884
  sendData,