@cuekit-ai/react 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -5363,7 +5363,7 @@ function supportsAV1() {
5363
5363
  if (!("getCapabilities" in RTCRtpSender)) {
5364
5364
  return false;
5365
5365
  }
5366
- if (isSafari()) {
5366
+ if (isSafari() || isFireFox()) {
5367
5367
  return false;
5368
5368
  }
5369
5369
  const capabilities = RTCRtpSender.getCapabilities("video");
@@ -5460,9 +5460,9 @@ function isE2EESimulcastSupported() {
5460
5460
  if (browser) {
5461
5461
  if (browser.name !== "Safari" && browser.os !== "iOS") {
5462
5462
  return true;
5463
- } else if (browser.os === "iOS" && browser.osVersion && compareVersions(supportedSafariVersion, browser.osVersion) >= 0) {
5463
+ } else if (browser.os === "iOS" && browser.osVersion && compareVersions(browser.osVersion, supportedSafariVersion) >= 0) {
5464
5464
  return true;
5465
- } else if (browser.name === "Safari" && compareVersions(supportedSafariVersion, browser.version) >= 0) {
5465
+ } else if (browser.name === "Safari" && compareVersions(browser.version, supportedSafariVersion) >= 0) {
5466
5466
  return true;
5467
5467
  } else {
5468
5468
  return false;
@@ -5641,13 +5641,13 @@ function unwrapConstraint(constraint) {
5641
5641
  if (Array.isArray(constraint)) {
5642
5642
  return constraint[0];
5643
5643
  }
5644
- if (constraint.exact) {
5644
+ if (constraint.exact !== void 0) {
5645
5645
  if (Array.isArray(constraint.exact)) {
5646
5646
  return constraint.exact[0];
5647
5647
  }
5648
5648
  return constraint.exact;
5649
5649
  }
5650
- if (constraint.ideal) {
5650
+ if (constraint.ideal !== void 0) {
5651
5651
  if (Array.isArray(constraint.ideal)) {
5652
5652
  return constraint.ideal[0];
5653
5653
  }
@@ -5870,7 +5870,7 @@ function constraintsForOptions(options) {
5870
5870
  function detectSilence(track_1) {
5871
5871
  return __awaiter(this, arguments, void 0, function(track) {
5872
5872
  let timeOffset = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 200;
5873
- return function* () {
5873
+ return (function* () {
5874
5874
  const ctx = getNewAudioContext();
5875
5875
  if (ctx) {
5876
5876
  const analyser = ctx.createAnalyser();
@@ -5886,7 +5886,7 @@ function detectSilence(track_1) {
5886
5886
  return !someNoise;
5887
5887
  }
5888
5888
  return false;
5889
- }();
5889
+ })();
5890
5890
  });
5891
5891
  }
5892
5892
  function getNewAudioContext() {
@@ -7610,7 +7610,7 @@ function isIPPrivate(address) {
7610
7610
  }
7611
7611
  return false;
7612
7612
  }
7613
- var e, h, o, _, FLOAT32_MAX, FLOAT32_MIN, UINT32_MAX, INT32_MAX, INT32_MIN, enumTypeSymbol, Message, TWO_PWR_32_DBL, decimalFrom1e7WithLeadingZeros, protoInt64, ScalarType, LongType, WireType, BinaryWriter, BinaryReader, encTable, decTable, protoBase64, jsonReadDefaults, jsonWriteDefaults, tokenNull, tokenIgnoredUnknownEnum, unknownFieldsSymbol, readDefaults, writeDefaults, InternalFieldList, fieldJsonName, reservedObjectProperties, reservedMessageProperties, fallback, safeMessageProperty, safeObjectProperty, InternalOneofInfo, proto3, Timestamp, MetricsBatch, TimeSeriesMetric, MetricSample, EventMetric, BackupCodecPolicy$1, TrackType, TrackSource, VideoQuality$1, ConnectionQuality$1, ClientConfigSetting, DisconnectReason, ReconnectReason, SubscriptionError, AudioTrackFeature, Room$1, Codec, ParticipantPermission, ParticipantInfo, ParticipantInfo_State, ParticipantInfo_Kind, ParticipantInfo_KindDetail, Encryption_Type, SimulcastCodecInfo, TrackInfo, VideoLayer, DataPacket, DataPacket_Kind, ActiveSpeakerUpdate, SpeakerInfo, UserPacket, SipDTMF, Transcription, TranscriptionSegment, ChatMessage, RpcRequest, RpcAck, RpcResponse, RpcError$1, ParticipantTracks, ServerInfo, ServerInfo_Edition, ClientInfo, ClientInfo_SDK, ClientConfiguration, VideoConfiguration, DisabledCodecs, TimedVersion, DataStream_OperationType, DataStream_TextHeader, DataStream_ByteHeader, DataStream_Header, DataStream_Chunk, DataStream_Trailer, SignalTarget, StreamState, CandidateProtocol, SignalRequest, SignalResponse, SimulcastCodec, AddTrackRequest, TrickleRequest, MuteTrackRequest, JoinResponse, ReconnectResponse, TrackPublishedResponse, TrackUnpublishedResponse, SessionDescription, ParticipantUpdate, UpdateSubscription, UpdateTrackSettings, UpdateLocalAudioTrack, UpdateLocalVideoTrack, LeaveRequest, LeaveRequest_Action, UpdateVideoLayers, UpdateParticipantMetadata, ICEServer, SpeakersChanged, RoomUpdate, ConnectionQualityInfo, ConnectionQualityUpdate, StreamStateInfo, StreamStateUpdate, SubscribedQuality, SubscribedCodec, SubscribedQualityUpdate, TrackPermission, SubscriptionPermission, SubscriptionPermissionUpdate, RoomMovedResponse, SyncState, DataChannelReceiveState, DataChannelInfo, SimulateScenario, Ping, Pong, RegionSettings, RegionInfo, SubscriptionResponse, RequestResponse, RequestResponse_Reason, TrackSubscribed, loglevel$1, loglevel, hasRequiredLoglevel, loglevelExports, LogLevel, LoggerNames, livekitLogger, livekitLoggers, workerLogger, maxRetryDelay, DEFAULT_RETRY_DELAYS_IN_MS, DefaultReconnectPolicy, events, hasRequiredEvents, eventsExports, logDisabled_, deprecationWarnings_, logging, chromeShim, firefoxShim, safariShim, sdp$1, hasRequiredSdp, sdpExports, SDPUtils, sdp, commonShim, DECRYPTION_FAILURE_TOLERANCE, E2EE_FLAG, SALT, KEY_PROVIDER_DEFAULTS, KeyProviderEvent, KeyHandlerEvent, EncryptionEvent, CryptorEvent, BaseKeyProvider, LivekitError, ConnectionErrorReason, ConnectionError, DeviceUnsupportedError, TrackInvalidError, UnsupportedServer, UnexpectedConnectionState, NegotiationError, PublishTrackError, SignalRequestError, MediaDeviceFailure, CryptorErrorReason, RoomEvent, ParticipantEvent, EngineEvent, TrackEvent, commonVersionIdentifier, browserDetails, browsersList, version$1, version, protocolVersion, CriticalTimers, BACKGROUND_REACTION_DELAY, recycledElements, VideoQuality, Track, VideoPreset, backupCodecs, videoCodecs, BackupCodecPolicy, AudioPresets, VideoPresets, VideoPresets43, ScreenSharePresets, separator, ddExtensionURI, resizeObserver, getResizeObserver, intersectionObserver, getIntersectionObserver, emptyAudioStreamTrack, Future, E2EEManager, defaultId, DeviceManager, QueueTaskStatus, AsyncQueue, passThroughQueueSignals, SignalConnectionState, SignalClient, DataPacketBuffer, TTLMap, lib, parser, grammar, hasRequiredGrammar, hasRequiredParser, writer, hasRequiredWriter, hasRequiredLib, libExports, startBitrateForSVC, debounceInterval, PCEvents, PCTransport, defaultVideoCodec, publishDefaults, audioDefaults, videoDefaults, roomOptionDefaults, roomConnectOptionDefaults, PCTransportState, PCTransportManager, RpcError, MAX_PAYLOAD_BYTES, monitorFrequency, isMediaRecorderAvailable, FallbackRecorder, RecorderBase, LocalTrackRecorder, DEFAULT_DIMENSIONS_TIMEOUT, PRE_CONNECT_BUFFER_TIMEOUT, LocalTrack, LocalAudioTrack, presets169, presets43, presetsScreenShare, defaultSimulcastPresets169, defaultSimulcastPresets43, computeDefaultScreenShareSimulcastPresets, videoRids, ScalabilityMode, refreshSubscribedCodecAfterNewCodec, LocalVideoTrack, lossyDataChannel, reliableDataChannel, minReconnectWait, leaveReconnect, reliabeReceiveStateTTL, PCState, RTCEngine, SignalReconnectError, RegionUrlProvider, BaseStreamReader, ByteStreamReader, TextStreamReader, BaseStreamWriter, TextStreamWriter, ByteStreamWriter, RemoteTrack, RemoteAudioTrack, REACTION_DELAY, RemoteVideoTrack, HTMLElementInfo, TrackPublication, LocalTrackPublication, ConnectionQuality, Participant, STREAM_CHUNK_SIZE, LocalParticipant, RemoteTrackPublication, RemoteParticipant, ConnectionState, connectionReconcileFrequency, Room, CheckStatus, Checker, CloudRegionCheck, TEST_DURATION, ConnectionProtocolCheck, PublishAudioCheck, PublishVideoCheck, ReconnectCheck, TURNCheck, WebRTCCheck, WebSocketCheck, ConnectionCheck;
7613
+ var e, h, o, _, FLOAT32_MAX, FLOAT32_MIN, UINT32_MAX, INT32_MAX, INT32_MIN, enumTypeSymbol, Message, TWO_PWR_32_DBL, decimalFrom1e7WithLeadingZeros, protoInt64, ScalarType, LongType, WireType, BinaryWriter, BinaryReader, encTable, decTable, protoBase64, jsonReadDefaults, jsonWriteDefaults, tokenNull, tokenIgnoredUnknownEnum, unknownFieldsSymbol, readDefaults, writeDefaults, InternalFieldList, fieldJsonName, reservedObjectProperties, reservedMessageProperties, fallback, safeMessageProperty, safeObjectProperty, InternalOneofInfo, proto3, Timestamp, MetricsBatch, TimeSeriesMetric, MetricSample, EventMetric, BackupCodecPolicy$1, TrackType, TrackSource, VideoQuality$1, ConnectionQuality$1, ClientConfigSetting, DisconnectReason, ReconnectReason, SubscriptionError, AudioTrackFeature, Room$1, Codec, ParticipantPermission, ParticipantInfo, ParticipantInfo_State, ParticipantInfo_Kind, ParticipantInfo_KindDetail, Encryption_Type, SimulcastCodecInfo, TrackInfo, VideoLayer, DataPacket, DataPacket_Kind, ActiveSpeakerUpdate, SpeakerInfo, UserPacket, SipDTMF, Transcription, TranscriptionSegment, ChatMessage, RpcRequest, RpcAck, RpcResponse, RpcError$1, ParticipantTracks, ServerInfo, ServerInfo_Edition, ClientInfo, ClientInfo_SDK, ClientConfiguration, VideoConfiguration, DisabledCodecs, TimedVersion, DataStream_OperationType, DataStream_TextHeader, DataStream_ByteHeader, DataStream_Header, DataStream_Chunk, DataStream_Trailer, SignalTarget, StreamState, CandidateProtocol, SignalRequest, SignalResponse, SimulcastCodec, AddTrackRequest, TrickleRequest, MuteTrackRequest, JoinResponse, ReconnectResponse, TrackPublishedResponse, TrackUnpublishedResponse, SessionDescription, ParticipantUpdate, UpdateSubscription, UpdateTrackSettings, UpdateLocalAudioTrack, UpdateLocalVideoTrack, LeaveRequest, LeaveRequest_Action, UpdateVideoLayers, UpdateParticipantMetadata, ICEServer, SpeakersChanged, RoomUpdate, ConnectionQualityInfo, ConnectionQualityUpdate, StreamStateInfo, StreamStateUpdate, SubscribedQuality, SubscribedCodec, SubscribedQualityUpdate, TrackPermission, SubscriptionPermission, SubscriptionPermissionUpdate, RoomMovedResponse, SyncState, DataChannelReceiveState, DataChannelInfo, SimulateScenario, Ping, Pong, RegionSettings, RegionInfo, SubscriptionResponse, RequestResponse, RequestResponse_Reason, TrackSubscribed, loglevel$1, loglevel, hasRequiredLoglevel, loglevelExports, LogLevel, LoggerNames, livekitLogger, livekitLoggers, workerLogger, maxRetryDelay, DEFAULT_RETRY_DELAYS_IN_MS, DefaultReconnectPolicy, events, hasRequiredEvents, eventsExports, logDisabled_, deprecationWarnings_, logging, chromeShim, firefoxShim, safariShim, sdp$1, hasRequiredSdp, sdpExports, SDPUtils, sdp, commonShim, DECRYPTION_FAILURE_TOLERANCE, E2EE_FLAG, SALT, KEY_PROVIDER_DEFAULTS, KeyProviderEvent, KeyHandlerEvent, EncryptionEvent, CryptorEvent, BaseKeyProvider, LivekitError, ConnectionErrorReason, ConnectionError, DeviceUnsupportedError, TrackInvalidError, UnsupportedServer, UnexpectedConnectionState, NegotiationError, PublishTrackError, SignalRequestError, DataStreamErrorReason, DataStreamError, MediaDeviceFailure, CryptorErrorReason, RoomEvent, ParticipantEvent, EngineEvent, TrackEvent, commonVersionIdentifier, browserDetails, browsersList, version$1, version, protocolVersion, CriticalTimers, BACKGROUND_REACTION_DELAY, recycledElements, VideoQuality, Track, VideoPreset, backupCodecs, videoCodecs, BackupCodecPolicy, AudioPresets, VideoPresets, VideoPresets43, ScreenSharePresets, separator, ddExtensionURI, resizeObserver, getResizeObserver, intersectionObserver, getIntersectionObserver, emptyAudioStreamTrack, Future, E2EEManager, defaultId, DeviceManager, QueueTaskStatus, AsyncQueue, passThroughQueueSignals, SignalConnectionState, SignalClient, DataPacketBuffer, TTLMap, lib, parser, grammar, hasRequiredGrammar, hasRequiredParser, writer, hasRequiredWriter, hasRequiredLib, libExports, startBitrateForSVC, debounceInterval, PCEvents, PCTransport, defaultVideoCodec, publishDefaults, audioDefaults, videoDefaults, roomOptionDefaults, roomConnectOptionDefaults, PCTransportState, PCTransportManager, RpcError, MAX_PAYLOAD_BYTES, monitorFrequency, isMediaRecorderAvailable, FallbackRecorder, RecorderBase, LocalTrackRecorder, DEFAULT_DIMENSIONS_TIMEOUT, PRE_CONNECT_BUFFER_TIMEOUT, LocalTrack, LocalAudioTrack, presets169, presets43, presetsScreenShare, defaultSimulcastPresets169, defaultSimulcastPresets43, computeDefaultScreenShareSimulcastPresets, videoRids, ScalabilityMode, refreshSubscribedCodecAfterNewCodec, LocalVideoTrack, lossyDataChannel, reliableDataChannel, minReconnectWait, leaveReconnect, reliabeReceiveStateTTL, PCState, RTCEngine, SignalReconnectError, RegionUrlProvider, BaseStreamReader, ByteStreamReader, TextStreamReader, IncomingDataStreamManager, BaseStreamWriter, TextStreamWriter, ByteStreamWriter, STREAM_CHUNK_SIZE, OutgoingDataStreamManager, RemoteTrack, RemoteAudioTrack, REACTION_DELAY, RemoteVideoTrack, HTMLElementInfo, TrackPublication, LocalTrackPublication, ConnectionQuality, Participant, LocalParticipant, RemoteTrackPublication, RemoteParticipant, ConnectionState, connectionReconcileFrequency, Room, CheckStatus, Checker, CloudRegionCheck, TEST_DURATION, ConnectionProtocolCheck, PublishAudioCheck, PublishVideoCheck, ReconnectCheck, TURNCheck, WebRTCCheck, WebSocketCheck, ConnectionCheck;
7614
7614
  var init_livekit_client_esm = __esm({
7615
7615
  "node_modules/livekit-client/dist/livekit-client.esm.mjs"() {
7616
7616
  "use strict";
@@ -11486,6 +11486,22 @@ var init_livekit_client_esm = __esm({
11486
11486
  this.reasonName = typeof reason === "string" ? reason : RequestResponse_Reason[reason];
11487
11487
  }
11488
11488
  };
11489
+ (function(DataStreamErrorReason2) {
11490
+ DataStreamErrorReason2[DataStreamErrorReason2["AlreadyOpened"] = 0] = "AlreadyOpened";
11491
+ DataStreamErrorReason2[DataStreamErrorReason2["AbnormalEnd"] = 1] = "AbnormalEnd";
11492
+ DataStreamErrorReason2[DataStreamErrorReason2["DecodeFailed"] = 2] = "DecodeFailed";
11493
+ DataStreamErrorReason2[DataStreamErrorReason2["LengthExceeded"] = 3] = "LengthExceeded";
11494
+ DataStreamErrorReason2[DataStreamErrorReason2["Incomplete"] = 4] = "Incomplete";
11495
+ DataStreamErrorReason2[DataStreamErrorReason2["HandlerAlreadyRegistered"] = 7] = "HandlerAlreadyRegistered";
11496
+ })(DataStreamErrorReason || (DataStreamErrorReason = {}));
11497
+ DataStreamError = class extends LivekitError {
11498
+ constructor(message, reason) {
11499
+ super(16, message);
11500
+ this.name = "DataStreamError";
11501
+ this.reason = reason;
11502
+ this.reasonName = DataStreamErrorReason[reason];
11503
+ }
11504
+ };
11489
11505
  (function(MediaDeviceFailure2) {
11490
11506
  MediaDeviceFailure2["PermissionDenied"] = "PermissionDenied";
11491
11507
  MediaDeviceFailure2["NotFound"] = "NotFound";
@@ -11697,7 +11713,7 @@ var init_livekit_client_esm = __esm({
11697
11713
  }
11698
11714
  }
11699
11715
  ];
11700
- version$1 = "2.15.4";
11716
+ version$1 = "2.15.6";
11701
11717
  version = version$1;
11702
11718
  protocolVersion = 16;
11703
11719
  CriticalTimers = class {
@@ -11723,13 +11739,24 @@ var init_livekit_client_esm = __esm({
11723
11739
  VideoQuality2[VideoQuality2["HIGH"] = 2] = "HIGH";
11724
11740
  })(VideoQuality || (VideoQuality = {}));
11725
11741
  Track = class _Track extends eventsExports.EventEmitter {
11742
+ /**
11743
+ * indicates current state of stream, it'll indicate `paused` if the track
11744
+ * has been paused by congestion controller
11745
+ */
11746
+ get streamState() {
11747
+ return this._streamState;
11748
+ }
11749
+ /** @internal */
11750
+ setStreamState(value) {
11751
+ this._streamState = value;
11752
+ }
11726
11753
  constructor(mediaTrack, kind) {
11727
11754
  let loggerOptions = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {};
11728
11755
  var _a;
11729
11756
  super();
11730
11757
  this.attachedElements = [];
11731
11758
  this.isMuted = false;
11732
- this.streamState = _Track.StreamState.Active;
11759
+ this._streamState = _Track.StreamState.Active;
11733
11760
  this.isInBackground = false;
11734
11761
  this._currentBitrate = 0;
11735
11762
  this.log = livekitLogger;
@@ -12262,6 +12289,20 @@ var init_livekit_client_esm = __esm({
12262
12289
  room2.localParticipant.on(ParticipantEvent.LocalSenderCreated, (sender, track) => __awaiter(this, void 0, void 0, function* () {
12263
12290
  this.setupE2EESender(track, sender);
12264
12291
  }));
12292
+ room2.localParticipant.on(ParticipantEvent.LocalTrackPublished, (publication) => {
12293
+ if (!isVideoTrack(publication.track) || !isSafariBased()) {
12294
+ return;
12295
+ }
12296
+ const msg = {
12297
+ kind: "updateCodec",
12298
+ data: {
12299
+ trackId: publication.track.mediaStreamID,
12300
+ codec: mimeTypeToVideoCodecString(publication.trackInfo.codecs[0].mimeType),
12301
+ participantIdentity: this.room.localParticipant.identity
12302
+ }
12303
+ };
12304
+ this.worker.postMessage(msg);
12305
+ });
12265
12306
  keyProvider.on(KeyProviderEvent.SetKey, (keyInfo) => this.postKey(keyInfo)).on(KeyProviderEvent.RatchetRequest, (participantId, keyIndex) => this.postRatchetRequest(participantId, keyIndex));
12266
12307
  }
12267
12308
  postRatchetRequest(participantIdentity, keyIndex) {
@@ -12472,7 +12513,7 @@ var init_livekit_client_esm = __esm({
12472
12513
  return __awaiter(this, arguments, void 0, function(kind) {
12473
12514
  var _this = this;
12474
12515
  let requestPermissions = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true;
12475
- return function* () {
12516
+ return (function* () {
12476
12517
  var _a;
12477
12518
  if (((_a = _DeviceManager.userMediaPromiseMap) === null || _a === void 0 ? void 0 : _a.size) > 0) {
12478
12519
  livekitLogger.debug("awaiting getUserMedia promise");
@@ -12515,7 +12556,7 @@ var init_livekit_client_esm = __esm({
12515
12556
  devices = devices.filter((device) => device.kind === kind);
12516
12557
  }
12517
12558
  return devices;
12518
- }();
12559
+ })();
12519
12560
  });
12520
12561
  }
12521
12562
  normalizeDeviceId(kind, deviceId, groupId) {
@@ -12796,7 +12837,7 @@ var init_livekit_client_esm = __esm({
12796
12837
  return __awaiter(this, arguments, void 0, function() {
12797
12838
  var _this = this;
12798
12839
  let updateState = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : true;
12799
- return function* () {
12840
+ return (function* () {
12800
12841
  const unlock = yield _this.closingLock.lock();
12801
12842
  try {
12802
12843
  _this.clearPingInterval();
@@ -12828,7 +12869,7 @@ var init_livekit_client_esm = __esm({
12828
12869
  }
12829
12870
  unlock();
12830
12871
  }
12831
- }();
12872
+ })();
12832
12873
  });
12833
12874
  }
12834
12875
  // initial offer after joining
@@ -12882,7 +12923,7 @@ var init_livekit_client_esm = __esm({
12882
12923
  return __awaiter(this, arguments, void 0, function(metadata, name2) {
12883
12924
  var _this2 = this;
12884
12925
  let attributes = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {};
12885
- return function* () {
12926
+ return (function* () {
12886
12927
  const requestId = _this2.getNextRequestId();
12887
12928
  yield _this2.sendRequest({
12888
12929
  case: "updateMetadata",
@@ -12894,7 +12935,7 @@ var init_livekit_client_esm = __esm({
12894
12935
  })
12895
12936
  });
12896
12937
  return requestId;
12897
- }();
12938
+ })();
12898
12939
  });
12899
12940
  }
12900
12941
  sendUpdateTrackSettings(settings) {
@@ -12974,7 +13015,7 @@ var init_livekit_client_esm = __esm({
12974
13015
  return __awaiter(this, arguments, void 0, function(message) {
12975
13016
  var _this3 = this;
12976
13017
  let fromQueue = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false;
12977
- return function* () {
13018
+ return (function* () {
12978
13019
  const canQueue = !fromQueue && !canPassThroughQueue(message);
12979
13020
  if (canQueue && _this3.state === SignalConnectionState.RECONNECTING) {
12980
13021
  _this3.queuedRequests.push(() => __awaiter(_this3, void 0, void 0, function* () {
@@ -13010,7 +13051,7 @@ var init_livekit_client_esm = __esm({
13010
13051
  error: e3
13011
13052
  }));
13012
13053
  }
13013
- }();
13054
+ })();
13014
13055
  });
13015
13056
  }
13016
13057
  handleSignalResponse(res) {
@@ -14076,7 +14117,7 @@ var init_livekit_client_esm = __esm({
14076
14117
  return __awaiter(this, arguments, void 0, function(pcTransport, abortController) {
14077
14118
  var _this = this;
14078
14119
  let timeout = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : this.peerConnectionTimeout;
14079
- return function* () {
14120
+ return (function* () {
14080
14121
  const connectionState = pcTransport.getConnectionState();
14081
14122
  if (connectionState === "connected") {
14082
14123
  return;
@@ -14106,7 +14147,7 @@ var init_livekit_client_esm = __esm({
14106
14147
  abortController === null || abortController === void 0 ? void 0 : abortController.signal.removeEventListener("abort", abortHandler);
14107
14148
  resolve();
14108
14149
  }));
14109
- }();
14150
+ })();
14110
14151
  });
14111
14152
  }
14112
14153
  };
@@ -14287,9 +14328,14 @@ var init_livekit_client_esm = __esm({
14287
14328
  this.providedByUser = userProvidedTrack;
14288
14329
  this.muteLock = new _();
14289
14330
  this.pauseUpstreamLock = new _();
14290
- this.processorLock = new _();
14291
- this.restartLock = new _();
14292
- this.setMediaStreamTrack(mediaTrack, true);
14331
+ this.trackChangeLock = new _();
14332
+ this.trackChangeLock.lock().then((unlock) => __awaiter(this, void 0, void 0, function* () {
14333
+ try {
14334
+ yield this.setMediaStreamTrack(mediaTrack, true);
14335
+ } finally {
14336
+ unlock();
14337
+ }
14338
+ }));
14293
14339
  this._constraints = mediaTrack.getConstraints();
14294
14340
  if (constraints) {
14295
14341
  this._constraints = constraints;
@@ -14358,25 +14404,20 @@ var init_livekit_client_esm = __esm({
14358
14404
  }
14359
14405
  let processedTrack;
14360
14406
  if (this.processor && newTrack) {
14361
- const unlock = yield this.processorLock.lock();
14362
- try {
14363
- this.log.debug("restarting processor", this.logContext);
14364
- if (this.kind === "unknown") {
14365
- throw TypeError("cannot set processor on track of unknown kind");
14366
- }
14367
- if (this.processorElement) {
14368
- attachToElement(newTrack, this.processorElement);
14369
- this.processorElement.muted = true;
14370
- }
14371
- yield this.processor.restart({
14372
- track: newTrack,
14373
- kind: this.kind,
14374
- element: this.processorElement
14375
- });
14376
- processedTrack = this.processor.processedTrack;
14377
- } finally {
14378
- unlock();
14407
+ this.log.debug("restarting processor", this.logContext);
14408
+ if (this.kind === "unknown") {
14409
+ throw TypeError("cannot set processor on track of unknown kind");
14379
14410
  }
14411
+ if (this.processorElement) {
14412
+ attachToElement(newTrack, this.processorElement);
14413
+ this.processorElement.muted = true;
14414
+ }
14415
+ yield this.processor.restart({
14416
+ track: newTrack,
14417
+ kind: this.kind,
14418
+ element: this.processorElement
14419
+ });
14420
+ processedTrack = this.processor.processedTrack;
14380
14421
  }
14381
14422
  if (this.sender && ((_a = this.sender.transport) === null || _a === void 0 ? void 0 : _a.state) !== "closed") {
14382
14423
  yield this.sender.replaceTrack(processedTrack !== null && processedTrack !== void 0 ? processedTrack : newTrack);
@@ -14398,7 +14439,7 @@ var init_livekit_client_esm = __esm({
14398
14439
  return __awaiter(this, arguments, void 0, function() {
14399
14440
  var _this = this;
14400
14441
  let timeout = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : DEFAULT_DIMENSIONS_TIMEOUT;
14401
- return function* () {
14442
+ return (function* () {
14402
14443
  var _a;
14403
14444
  if (_this.kind === Track.Kind.Audio) {
14404
14445
  throw new Error("cannot get dimensions for audio tracks");
@@ -14415,7 +14456,7 @@ var init_livekit_client_esm = __esm({
14415
14456
  yield sleep(50);
14416
14457
  }
14417
14458
  throw new TrackInvalidError("unable to get track dimensions after timeout");
14418
- }();
14459
+ })();
14419
14460
  });
14420
14461
  }
14421
14462
  setDeviceId(deviceId) {
@@ -14438,7 +14479,7 @@ var init_livekit_client_esm = __esm({
14438
14479
  return __awaiter(this, arguments, void 0, function() {
14439
14480
  var _this2 = this;
14440
14481
  let normalize3 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : true;
14441
- return function* () {
14482
+ return (function* () {
14442
14483
  if (_this2.source === Track.Source.ScreenShare) {
14443
14484
  return;
14444
14485
  }
@@ -14448,7 +14489,7 @@ var init_livekit_client_esm = __esm({
14448
14489
  } = _this2._mediaStreamTrack.getSettings();
14449
14490
  const kind = _this2.kind === Track.Kind.Audio ? "audioinput" : "videoinput";
14450
14491
  return normalize3 ? DeviceManager.getInstance().normalizeDeviceId(kind, deviceId, groupId) : deviceId;
14451
- }();
14492
+ })();
14452
14493
  });
14453
14494
  }
14454
14495
  mute() {
@@ -14465,30 +14506,35 @@ var init_livekit_client_esm = __esm({
14465
14506
  }
14466
14507
  replaceTrack(track, userProvidedOrOptions) {
14467
14508
  return __awaiter(this, void 0, void 0, function* () {
14468
- if (!this.sender) {
14469
- throw new TrackInvalidError("unable to replace an unpublished track");
14470
- }
14471
- let userProvidedTrack;
14472
- let stopProcessor;
14473
- if (typeof userProvidedOrOptions === "boolean") {
14474
- userProvidedTrack = userProvidedOrOptions;
14475
- } else if (userProvidedOrOptions !== void 0) {
14476
- userProvidedTrack = userProvidedOrOptions.userProvidedTrack;
14477
- stopProcessor = userProvidedOrOptions.stopProcessor;
14478
- }
14479
- this.providedByUser = userProvidedTrack !== null && userProvidedTrack !== void 0 ? userProvidedTrack : true;
14480
- this.log.debug("replace MediaStreamTrack", this.logContext);
14481
- yield this.setMediaStreamTrack(track);
14482
- if (stopProcessor && this.processor) {
14483
- yield this.stopProcessor();
14509
+ const unlock = yield this.trackChangeLock.lock();
14510
+ try {
14511
+ if (!this.sender) {
14512
+ throw new TrackInvalidError("unable to replace an unpublished track");
14513
+ }
14514
+ let userProvidedTrack;
14515
+ let stopProcessor;
14516
+ if (typeof userProvidedOrOptions === "boolean") {
14517
+ userProvidedTrack = userProvidedOrOptions;
14518
+ } else if (userProvidedOrOptions !== void 0) {
14519
+ userProvidedTrack = userProvidedOrOptions.userProvidedTrack;
14520
+ stopProcessor = userProvidedOrOptions.stopProcessor;
14521
+ }
14522
+ this.providedByUser = userProvidedTrack !== null && userProvidedTrack !== void 0 ? userProvidedTrack : true;
14523
+ this.log.debug("replace MediaStreamTrack", this.logContext);
14524
+ yield this.setMediaStreamTrack(track);
14525
+ if (stopProcessor && this.processor) {
14526
+ yield this.internalStopProcessor();
14527
+ }
14528
+ return this;
14529
+ } finally {
14530
+ unlock();
14484
14531
  }
14485
- return this;
14486
14532
  });
14487
14533
  }
14488
14534
  restart(constraints) {
14489
14535
  return __awaiter(this, void 0, void 0, function* () {
14490
14536
  this.manuallyStopped = false;
14491
- const unlock = yield this.restartLock.lock();
14537
+ const unlock = yield this.trackChangeLock.lock();
14492
14538
  try {
14493
14539
  if (!constraints) {
14494
14540
  constraints = this._constraints;
@@ -14510,9 +14556,9 @@ var init_livekit_client_esm = __esm({
14510
14556
  facingMode
14511
14557
  } : true;
14512
14558
  } else {
14513
- streamConstraints.audio = deviceId ? {
14559
+ streamConstraints.audio = deviceId ? Object.assign({
14514
14560
  deviceId
14515
- } : true;
14561
+ }, otherConstraints) : true;
14516
14562
  }
14517
14563
  this.attachedElements.forEach((el) => {
14518
14564
  detachTrack(this.mediaStreamTrack, el);
@@ -14521,7 +14567,9 @@ var init_livekit_client_esm = __esm({
14521
14567
  this._mediaStreamTrack.stop();
14522
14568
  const mediaStream = yield navigator.mediaDevices.getUserMedia(streamConstraints);
14523
14569
  const newTrack = mediaStream.getTracks()[0];
14524
- yield newTrack.applyConstraints(otherConstraints);
14570
+ if (this.kind === Track.Kind.Video) {
14571
+ yield newTrack.applyConstraints(otherConstraints);
14572
+ }
14525
14573
  newTrack.addEventListener("ended", this.handleEnded);
14526
14574
  this.log.debug("re-acquired MediaStreamTrack", this.logContext);
14527
14575
  yield this.setMediaStreamTrack(newTrack);
@@ -14660,9 +14708,9 @@ var init_livekit_client_esm = __esm({
14660
14708
  return __awaiter(this, arguments, void 0, function(processor) {
14661
14709
  var _this3 = this;
14662
14710
  let showProcessedStreamLocally = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true;
14663
- return function* () {
14711
+ return (function* () {
14664
14712
  var _a;
14665
- const unlock = yield _this3.processorLock.lock();
14713
+ const unlock = yield _this3.trackChangeLock.lock();
14666
14714
  try {
14667
14715
  _this3.log.debug("setting up processor", _this3.logContext);
14668
14716
  const processorElement = document.createElement(_this3.kind);
@@ -14675,7 +14723,7 @@ var init_livekit_client_esm = __esm({
14675
14723
  yield processor.init(processorOptions);
14676
14724
  _this3.log.debug("processor initialized", _this3.logContext);
14677
14725
  if (_this3.processor) {
14678
- yield _this3.stopProcessor();
14726
+ yield _this3.internalStopProcessor();
14679
14727
  }
14680
14728
  if (_this3.kind === "unknown") {
14681
14729
  throw TypeError("cannot set processor on track of unknown kind");
@@ -14715,7 +14763,7 @@ var init_livekit_client_esm = __esm({
14715
14763
  } finally {
14716
14764
  unlock();
14717
14765
  }
14718
- }();
14766
+ })();
14719
14767
  });
14720
14768
  }
14721
14769
  getProcessor() {
@@ -14732,21 +14780,40 @@ var init_livekit_client_esm = __esm({
14732
14780
  return __awaiter(this, arguments, void 0, function() {
14733
14781
  var _this4 = this;
14734
14782
  let keepElement = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : true;
14735
- return function* () {
14783
+ return (function* () {
14784
+ const unlock = yield _this4.trackChangeLock.lock();
14785
+ try {
14786
+ yield _this4.internalStopProcessor(keepElement);
14787
+ } finally {
14788
+ unlock();
14789
+ }
14790
+ })();
14791
+ });
14792
+ }
14793
+ /**
14794
+ * @internal
14795
+ * This method assumes the caller has acquired a trackChangeLock already.
14796
+ * The public facing method for stopping the processor is `stopProcessor` and it wraps this method in the trackChangeLock.
14797
+ */
14798
+ internalStopProcessor() {
14799
+ return __awaiter(this, arguments, void 0, function() {
14800
+ var _this5 = this;
14801
+ let keepElement = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : true;
14802
+ return (function* () {
14736
14803
  var _a, _b;
14737
- if (!_this4.processor) return;
14738
- _this4.log.debug("stopping processor", _this4.logContext);
14739
- (_a = _this4.processor.processedTrack) === null || _a === void 0 ? void 0 : _a.stop();
14740
- yield _this4.processor.destroy();
14741
- _this4.processor = void 0;
14804
+ if (!_this5.processor) return;
14805
+ _this5.log.debug("stopping processor", _this5.logContext);
14806
+ (_a = _this5.processor.processedTrack) === null || _a === void 0 ? void 0 : _a.stop();
14807
+ yield _this5.processor.destroy();
14808
+ _this5.processor = void 0;
14742
14809
  if (!keepElement) {
14743
- (_b = _this4.processorElement) === null || _b === void 0 ? void 0 : _b.remove();
14744
- _this4.processorElement = void 0;
14810
+ (_b = _this5.processorElement) === null || _b === void 0 ? void 0 : _b.remove();
14811
+ _this5.processorElement = void 0;
14745
14812
  }
14746
- yield _this4._mediaStreamTrack.applyConstraints(_this4._constraints);
14747
- yield _this4.setMediaStreamTrack(_this4._mediaStreamTrack, true);
14748
- _this4.emit(TrackEvent.TrackProcessorUpdate);
14749
- }();
14813
+ yield _this5._mediaStreamTrack.applyConstraints(_this5._constraints);
14814
+ yield _this5.setMediaStreamTrack(_this5._mediaStreamTrack, true);
14815
+ _this5.emit(TrackEvent.TrackProcessorUpdate);
14816
+ })();
14750
14817
  });
14751
14818
  }
14752
14819
  /** @internal */
@@ -14934,13 +15001,13 @@ var init_livekit_client_esm = __esm({
14934
15001
  setProcessor(processor) {
14935
15002
  return __awaiter(this, void 0, void 0, function* () {
14936
15003
  var _a;
14937
- const unlock = yield this.processorLock.lock();
15004
+ const unlock = yield this.trackChangeLock.lock();
14938
15005
  try {
14939
15006
  if (!isReactNative() && !this.audioContext) {
14940
15007
  throw Error("Audio context needs to be set on LocalAudioTrack in order to enable processors");
14941
15008
  }
14942
15009
  if (this.processor) {
14943
- yield this.stopProcessor();
15010
+ yield this.internalStopProcessor();
14944
15011
  }
14945
15012
  const processorOptions = {
14946
15013
  kind: this.kind,
@@ -15355,7 +15422,7 @@ var init_livekit_client_esm = __esm({
15355
15422
  return __awaiter(this, arguments, void 0, function(processor) {
15356
15423
  var _this = this;
15357
15424
  let showProcessedStreamLocally = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true;
15358
- return function* () {
15425
+ return (function* () {
15359
15426
  var _a, e_4, _b, _c;
15360
15427
  var _d, _e;
15361
15428
  yield _super.setProcessor.call(_this, processor, showProcessedStreamLocally);
@@ -15379,7 +15446,7 @@ var init_livekit_client_esm = __esm({
15379
15446
  }
15380
15447
  }
15381
15448
  }
15382
- }();
15449
+ })();
15383
15450
  });
15384
15451
  }
15385
15452
  setDegradationPreference(preference) {
@@ -15603,7 +15670,7 @@ var init_livekit_client_esm = __esm({
15603
15670
  let {
15604
15671
  channel
15605
15672
  } = _ref;
15606
- return function* () {
15673
+ return (function* () {
15607
15674
  if (!channel) {
15608
15675
  return;
15609
15676
  }
@@ -15616,7 +15683,7 @@ var init_livekit_client_esm = __esm({
15616
15683
  }
15617
15684
  _this.log.debug("on data channel ".concat(channel.id, ", ").concat(channel.label), _this.logContext);
15618
15685
  channel.onmessage = _this.handleDataMessage;
15619
- }();
15686
+ })();
15620
15687
  });
15621
15688
  this.handleDataMessage = (message) => __awaiter(this, void 0, void 0, function* () {
15622
15689
  var _a2, _b;
@@ -16499,7 +16566,7 @@ var init_livekit_client_esm = __esm({
16499
16566
  return __awaiter(this, arguments, void 0, function(kind) {
16500
16567
  var _this2 = this;
16501
16568
  let subscriber = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : this.subscriberPrimary;
16502
- return function* () {
16569
+ return (function* () {
16503
16570
  var _a;
16504
16571
  if (!_this2.pcManager) {
16505
16572
  throw new UnexpectedConnectionState("PC manager is closed");
@@ -16532,7 +16599,7 @@ var init_livekit_client_esm = __esm({
16532
16599
  yield sleep(50);
16533
16600
  }
16534
16601
  throw new ConnectionError("could not establish ".concat(transportName, " connection, state: ").concat(transport.getICEConnectionState()), ConnectionErrorReason.InternalError);
16535
- }();
16602
+ })();
16536
16603
  });
16537
16604
  }
16538
16605
  ensurePublisherConnected(kind) {
@@ -16775,30 +16842,72 @@ var init_livekit_client_esm = __esm({
16775
16842
  get info() {
16776
16843
  return this._info;
16777
16844
  }
16778
- constructor(info, stream, totalByteSize) {
16845
+ /** @internal */
16846
+ validateBytesReceived() {
16847
+ let doneReceiving = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : false;
16848
+ if (typeof this.totalByteSize !== "number" || this.totalByteSize === 0) {
16849
+ return;
16850
+ }
16851
+ if (doneReceiving && this.bytesReceived < this.totalByteSize) {
16852
+ throw new DataStreamError("Not enough chunk(s) received - expected ".concat(this.totalByteSize, " bytes of data total, only received ").concat(this.bytesReceived, " bytes"), DataStreamErrorReason.Incomplete);
16853
+ } else if (this.bytesReceived > this.totalByteSize) {
16854
+ throw new DataStreamError("Extra chunk(s) received - expected ".concat(this.totalByteSize, " bytes of data total, received ").concat(this.bytesReceived, " bytes"), DataStreamErrorReason.LengthExceeded);
16855
+ }
16856
+ }
16857
+ constructor(info, stream, totalByteSize, outOfBandFailureRejectingFuture) {
16779
16858
  this.reader = stream;
16780
16859
  this.totalByteSize = totalByteSize;
16781
16860
  this._info = info;
16782
16861
  this.bytesReceived = 0;
16862
+ this.outOfBandFailureRejectingFuture = outOfBandFailureRejectingFuture;
16783
16863
  }
16784
16864
  };
16785
16865
  ByteStreamReader = class extends BaseStreamReader {
16786
16866
  handleChunkReceived(chunk) {
16787
16867
  var _a;
16788
16868
  this.bytesReceived += chunk.content.byteLength;
16869
+ this.validateBytesReceived();
16789
16870
  const currentProgress = this.totalByteSize ? this.bytesReceived / this.totalByteSize : void 0;
16790
16871
  (_a = this.onProgress) === null || _a === void 0 ? void 0 : _a.call(this, currentProgress);
16791
16872
  }
16792
16873
  [Symbol.asyncIterator]() {
16793
16874
  const reader = this.reader.getReader();
16875
+ let rejectingSignalFuture = new Future();
16876
+ let activeSignal = null;
16877
+ let onAbort = null;
16878
+ if (this.signal) {
16879
+ const signal = this.signal;
16880
+ onAbort = () => {
16881
+ var _a;
16882
+ (_a = rejectingSignalFuture.reject) === null || _a === void 0 ? void 0 : _a.call(rejectingSignalFuture, signal.reason);
16883
+ };
16884
+ signal.addEventListener("abort", onAbort);
16885
+ activeSignal = signal;
16886
+ }
16887
+ const cleanup = () => {
16888
+ reader.releaseLock();
16889
+ if (activeSignal && onAbort) {
16890
+ activeSignal.removeEventListener("abort", onAbort);
16891
+ }
16892
+ this.signal = void 0;
16893
+ };
16794
16894
  return {
16795
16895
  next: () => __awaiter(this, void 0, void 0, function* () {
16896
+ var _a, _b;
16796
16897
  try {
16797
16898
  const {
16798
16899
  done,
16799
16900
  value
16800
- } = yield reader.read();
16901
+ } = yield Promise.race([
16902
+ reader.read(),
16903
+ // Rejects if this.signal is aborted
16904
+ rejectingSignalFuture.promise,
16905
+ // Rejects if something external says it should, like a participant disconnecting, etc
16906
+ (_b = (_a = this.outOfBandFailureRejectingFuture) === null || _a === void 0 ? void 0 : _a.promise) !== null && _b !== void 0 ? _b : new Promise(() => {
16907
+ })
16908
+ ]);
16801
16909
  if (done) {
16910
+ this.validateBytesReceived(true);
16802
16911
  return {
16803
16912
  done: true,
16804
16913
  value: void 0
@@ -16810,16 +16919,16 @@ var init_livekit_client_esm = __esm({
16810
16919
  value: value.content
16811
16920
  };
16812
16921
  }
16813
- } catch (error) {
16814
- return {
16815
- done: true,
16816
- value: void 0
16817
- };
16922
+ } catch (err) {
16923
+ cleanup();
16924
+ throw err;
16818
16925
  }
16819
16926
  }),
16927
+ // note: `return` runs only for premature exits, see:
16928
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#errors_during_iteration
16820
16929
  return() {
16821
16930
  return __awaiter(this, void 0, void 0, function* () {
16822
- reader.releaseLock();
16931
+ cleanup();
16823
16932
  return {
16824
16933
  done: true,
16825
16934
  value: void 0
@@ -16828,29 +16937,45 @@ var init_livekit_client_esm = __esm({
16828
16937
  }
16829
16938
  };
16830
16939
  }
16940
+ /**
16941
+ * Injects an AbortSignal, which if aborted, will terminate the currently active
16942
+ * stream iteration operation.
16943
+ *
16944
+ * Note that when using AbortSignal.timeout(...), the timeout applies across
16945
+ * the whole iteration operation, not just one individual chunk read.
16946
+ */
16947
+ withAbortSignal(signal) {
16948
+ this.signal = signal;
16949
+ return this;
16950
+ }
16831
16951
  readAll() {
16832
- return __awaiter(this, void 0, void 0, function* () {
16833
- var _a, e_1, _b, _c;
16834
- let chunks = /* @__PURE__ */ new Set();
16835
- try {
16836
- for (var _d = true, _e = __asyncValues(this), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
16837
- _c = _f.value;
16838
- _d = false;
16839
- const chunk = _c;
16840
- chunks.add(chunk);
16841
- }
16842
- } catch (e_1_1) {
16843
- e_1 = {
16844
- error: e_1_1
16845
- };
16846
- } finally {
16952
+ return __awaiter(this, arguments, void 0, function() {
16953
+ var _this = this;
16954
+ let opts = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
16955
+ return (function* () {
16956
+ var _a, e_1, _b, _c;
16957
+ let chunks = /* @__PURE__ */ new Set();
16958
+ const iterator = opts.signal ? _this.withAbortSignal(opts.signal) : _this;
16847
16959
  try {
16848
- if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
16960
+ 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) {
16961
+ _c = iterator_1_1.value;
16962
+ _d = false;
16963
+ const chunk = _c;
16964
+ chunks.add(chunk);
16965
+ }
16966
+ } catch (e_1_1) {
16967
+ e_1 = {
16968
+ error: e_1_1
16969
+ };
16849
16970
  } finally {
16850
- if (e_1) throw e_1.error;
16971
+ try {
16972
+ if (!_d && !_a && (_b = iterator_1.return)) yield _b.call(iterator_1);
16973
+ } finally {
16974
+ if (e_1) throw e_1.error;
16975
+ }
16851
16976
  }
16852
- }
16853
- return Array.from(chunks);
16977
+ return Array.from(chunks);
16978
+ })();
16854
16979
  });
16855
16980
  }
16856
16981
  };
@@ -16859,8 +16984,8 @@ var init_livekit_client_esm = __esm({
16859
16984
  * A TextStreamReader instance can be used as an AsyncIterator that returns the entire string
16860
16985
  * that has been received up to the current point in time.
16861
16986
  */
16862
- constructor(info, stream, totalChunkCount) {
16863
- super(info, stream, totalChunkCount);
16987
+ constructor(info, stream, totalChunkCount, outOfBandFailureRejectingFuture) {
16988
+ super(info, stream, totalChunkCount, outOfBandFailureRejectingFuture);
16864
16989
  this.receivedChunks = /* @__PURE__ */ new Map();
16865
16990
  }
16866
16991
  handleChunkReceived(chunk) {
@@ -16872,6 +16997,7 @@ var init_livekit_client_esm = __esm({
16872
16997
  }
16873
16998
  this.receivedChunks.set(index2, chunk);
16874
16999
  this.bytesReceived += chunk.content.byteLength;
17000
+ this.validateBytesReceived();
16875
17001
  const currentProgress = this.totalByteSize ? this.bytesReceived / this.totalByteSize : void 0;
16876
17002
  (_a = this.onProgress) === null || _a === void 0 ? void 0 : _a.call(this, currentProgress);
16877
17003
  }
@@ -16882,36 +17008,72 @@ var init_livekit_client_esm = __esm({
16882
17008
  */
16883
17009
  [Symbol.asyncIterator]() {
16884
17010
  const reader = this.reader.getReader();
16885
- const decoder = new TextDecoder();
17011
+ const decoder = new TextDecoder("utf-8", {
17012
+ fatal: true
17013
+ });
17014
+ let rejectingSignalFuture = new Future();
17015
+ let activeSignal = null;
17016
+ let onAbort = null;
17017
+ if (this.signal) {
17018
+ const signal = this.signal;
17019
+ onAbort = () => {
17020
+ var _a;
17021
+ (_a = rejectingSignalFuture.reject) === null || _a === void 0 ? void 0 : _a.call(rejectingSignalFuture, signal.reason);
17022
+ };
17023
+ signal.addEventListener("abort", onAbort);
17024
+ activeSignal = signal;
17025
+ }
17026
+ const cleanup = () => {
17027
+ reader.releaseLock();
17028
+ if (activeSignal && onAbort) {
17029
+ activeSignal.removeEventListener("abort", onAbort);
17030
+ }
17031
+ this.signal = void 0;
17032
+ };
16886
17033
  return {
16887
17034
  next: () => __awaiter(this, void 0, void 0, function* () {
17035
+ var _a, _b;
16888
17036
  try {
16889
17037
  const {
16890
17038
  done,
16891
17039
  value
16892
- } = yield reader.read();
17040
+ } = yield Promise.race([
17041
+ reader.read(),
17042
+ // Rejects if this.signal is aborted
17043
+ rejectingSignalFuture.promise,
17044
+ // Rejects if something external says it should, like a participant disconnecting, etc
17045
+ (_b = (_a = this.outOfBandFailureRejectingFuture) === null || _a === void 0 ? void 0 : _a.promise) !== null && _b !== void 0 ? _b : new Promise(() => {
17046
+ })
17047
+ ]);
16893
17048
  if (done) {
17049
+ this.validateBytesReceived(true);
16894
17050
  return {
16895
17051
  done: true,
16896
17052
  value: void 0
16897
17053
  };
16898
17054
  } else {
16899
17055
  this.handleChunkReceived(value);
17056
+ let decodedResult;
17057
+ try {
17058
+ decodedResult = decoder.decode(value.content);
17059
+ } catch (err) {
17060
+ throw new DataStreamError("Cannot decode datastream chunk ".concat(value.chunkIndex, " as text: ").concat(err), DataStreamErrorReason.DecodeFailed);
17061
+ }
16900
17062
  return {
16901
17063
  done: false,
16902
- value: decoder.decode(value.content)
17064
+ value: decodedResult
16903
17065
  };
16904
17066
  }
16905
- } catch (error) {
16906
- return {
16907
- done: true,
16908
- value: void 0
16909
- };
17067
+ } catch (err) {
17068
+ cleanup();
17069
+ throw err;
16910
17070
  }
16911
17071
  }),
17072
+ // note: `return` runs only for premature exits, see:
17073
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#errors_during_iteration
16912
17074
  return() {
16913
17075
  return __awaiter(this, void 0, void 0, function* () {
16914
- reader.releaseLock();
17076
+ cleanup();
16915
17077
  return {
16916
17078
  done: true,
16917
17079
  value: void 0
@@ -16920,31 +17082,215 @@ var init_livekit_client_esm = __esm({
16920
17082
  }
16921
17083
  };
16922
17084
  }
17085
+ /**
17086
+ * Injects an AbortSignal, which if aborted, will terminate the currently active
17087
+ * stream iteration operation.
17088
+ *
17089
+ * Note that when using AbortSignal.timeout(...), the timeout applies across
17090
+ * the whole iteration operation, not just one individual chunk read.
17091
+ */
17092
+ withAbortSignal(signal) {
17093
+ this.signal = signal;
17094
+ return this;
17095
+ }
16923
17096
  readAll() {
17097
+ return __awaiter(this, arguments, void 0, function() {
17098
+ var _this2 = this;
17099
+ let opts = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
17100
+ return (function* () {
17101
+ var _a, e_2, _b, _c;
17102
+ let finalString = "";
17103
+ const iterator = opts.signal ? _this2.withAbortSignal(opts.signal) : _this2;
17104
+ try {
17105
+ 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) {
17106
+ _c = iterator_2_1.value;
17107
+ _d = false;
17108
+ const chunk = _c;
17109
+ finalString += chunk;
17110
+ }
17111
+ } catch (e_2_1) {
17112
+ e_2 = {
17113
+ error: e_2_1
17114
+ };
17115
+ } finally {
17116
+ try {
17117
+ if (!_d && !_a && (_b = iterator_2.return)) yield _b.call(iterator_2);
17118
+ } finally {
17119
+ if (e_2) throw e_2.error;
17120
+ }
17121
+ }
17122
+ return finalString;
17123
+ })();
17124
+ });
17125
+ }
17126
+ };
17127
+ IncomingDataStreamManager = class {
17128
+ constructor() {
17129
+ this.log = livekitLogger;
17130
+ this.byteStreamControllers = /* @__PURE__ */ new Map();
17131
+ this.textStreamControllers = /* @__PURE__ */ new Map();
17132
+ this.byteStreamHandlers = /* @__PURE__ */ new Map();
17133
+ this.textStreamHandlers = /* @__PURE__ */ new Map();
17134
+ }
17135
+ registerTextStreamHandler(topic, callback) {
17136
+ if (this.textStreamHandlers.has(topic)) {
17137
+ throw new DataStreamError('A text stream handler for topic "'.concat(topic, '" has already been set.'), DataStreamErrorReason.HandlerAlreadyRegistered);
17138
+ }
17139
+ this.textStreamHandlers.set(topic, callback);
17140
+ }
17141
+ unregisterTextStreamHandler(topic) {
17142
+ this.textStreamHandlers.delete(topic);
17143
+ }
17144
+ registerByteStreamHandler(topic, callback) {
17145
+ if (this.byteStreamHandlers.has(topic)) {
17146
+ throw new DataStreamError('A byte stream handler for topic "'.concat(topic, '" has already been set.'), DataStreamErrorReason.HandlerAlreadyRegistered);
17147
+ }
17148
+ this.byteStreamHandlers.set(topic, callback);
17149
+ }
17150
+ unregisterByteStreamHandler(topic) {
17151
+ this.byteStreamHandlers.delete(topic);
17152
+ }
17153
+ clearHandlersAndControllers() {
17154
+ this.byteStreamControllers.clear();
17155
+ this.textStreamControllers.clear();
17156
+ this.byteStreamHandlers.clear();
17157
+ this.textStreamHandlers.clear();
17158
+ }
17159
+ validateParticipantHasNoActiveDataStreams(participantIdentity) {
17160
+ var _a, _b, _c, _d;
17161
+ const textStreamsBeingSentByDisconnectingParticipant = Array.from(this.textStreamControllers.entries()).filter((entry) => entry[1].sendingParticipantIdentity === participantIdentity);
17162
+ const byteStreamsBeingSentByDisconnectingParticipant = Array.from(this.byteStreamControllers.entries()).filter((entry) => entry[1].sendingParticipantIdentity === participantIdentity);
17163
+ if (textStreamsBeingSentByDisconnectingParticipant.length > 0 || byteStreamsBeingSentByDisconnectingParticipant.length > 0) {
17164
+ const abnormalEndError = new DataStreamError("Participant ".concat(participantIdentity, " unexpectedly disconnected in the middle of sending data"), DataStreamErrorReason.AbnormalEnd);
17165
+ for (const [id, controller] of byteStreamsBeingSentByDisconnectingParticipant) {
17166
+ (_b = (_a = controller.outOfBandFailureRejectingFuture).reject) === null || _b === void 0 ? void 0 : _b.call(_a, abnormalEndError);
17167
+ this.byteStreamControllers.delete(id);
17168
+ }
17169
+ for (const [id, controller] of textStreamsBeingSentByDisconnectingParticipant) {
17170
+ (_d = (_c = controller.outOfBandFailureRejectingFuture).reject) === null || _d === void 0 ? void 0 : _d.call(_c, abnormalEndError);
17171
+ this.textStreamControllers.delete(id);
17172
+ }
17173
+ }
17174
+ }
17175
+ handleDataStreamPacket(packet) {
16924
17176
  return __awaiter(this, void 0, void 0, function* () {
16925
- var _a, e_2, _b, _c;
16926
- let finalString = "";
16927
- try {
16928
- for (var _d = true, _e = __asyncValues(this), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
16929
- _c = _f.value;
16930
- _d = false;
16931
- const chunk = _c;
16932
- finalString += chunk;
17177
+ switch (packet.value.case) {
17178
+ case "streamHeader":
17179
+ return this.handleStreamHeader(packet.value.value, packet.participantIdentity);
17180
+ case "streamChunk":
17181
+ return this.handleStreamChunk(packet.value.value);
17182
+ case "streamTrailer":
17183
+ return this.handleStreamTrailer(packet.value.value);
17184
+ default:
17185
+ throw new Error('DataPacket of value "'.concat(packet.value.case, '" is not data stream related!'));
17186
+ }
17187
+ });
17188
+ }
17189
+ handleStreamHeader(streamHeader, participantIdentity) {
17190
+ return __awaiter(this, void 0, void 0, function* () {
17191
+ var _a;
17192
+ if (streamHeader.contentHeader.case === "byteHeader") {
17193
+ const streamHandlerCallback = this.byteStreamHandlers.get(streamHeader.topic);
17194
+ if (!streamHandlerCallback) {
17195
+ this.log.debug("ignoring incoming byte stream due to no handler for topic", streamHeader.topic);
17196
+ return;
16933
17197
  }
16934
- } catch (e_2_1) {
16935
- e_2 = {
16936
- error: e_2_1
17198
+ let streamController;
17199
+ const outOfBandFailureRejectingFuture = new Future();
17200
+ const info = {
17201
+ id: streamHeader.streamId,
17202
+ name: (_a = streamHeader.contentHeader.value.name) !== null && _a !== void 0 ? _a : "unknown",
17203
+ mimeType: streamHeader.mimeType,
17204
+ size: streamHeader.totalLength ? Number(streamHeader.totalLength) : void 0,
17205
+ topic: streamHeader.topic,
17206
+ timestamp: bigIntToNumber(streamHeader.timestamp),
17207
+ attributes: streamHeader.attributes
16937
17208
  };
16938
- } finally {
16939
- try {
16940
- if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
16941
- } finally {
16942
- if (e_2) throw e_2.error;
17209
+ const stream = new ReadableStream({
17210
+ start: (controller) => {
17211
+ streamController = controller;
17212
+ if (this.textStreamControllers.has(streamHeader.streamId)) {
17213
+ throw new DataStreamError("A data stream read is already in progress for a stream with id ".concat(streamHeader.streamId, "."), DataStreamErrorReason.AlreadyOpened);
17214
+ }
17215
+ this.byteStreamControllers.set(streamHeader.streamId, {
17216
+ info,
17217
+ controller: streamController,
17218
+ startTime: Date.now(),
17219
+ sendingParticipantIdentity: participantIdentity,
17220
+ outOfBandFailureRejectingFuture
17221
+ });
17222
+ }
17223
+ });
17224
+ streamHandlerCallback(new ByteStreamReader(info, stream, bigIntToNumber(streamHeader.totalLength), outOfBandFailureRejectingFuture), {
17225
+ identity: participantIdentity
17226
+ });
17227
+ } else if (streamHeader.contentHeader.case === "textHeader") {
17228
+ const streamHandlerCallback = this.textStreamHandlers.get(streamHeader.topic);
17229
+ if (!streamHandlerCallback) {
17230
+ this.log.debug("ignoring incoming text stream due to no handler for topic", streamHeader.topic);
17231
+ return;
16943
17232
  }
17233
+ let streamController;
17234
+ const outOfBandFailureRejectingFuture = new Future();
17235
+ const info = {
17236
+ id: streamHeader.streamId,
17237
+ mimeType: streamHeader.mimeType,
17238
+ size: streamHeader.totalLength ? Number(streamHeader.totalLength) : void 0,
17239
+ topic: streamHeader.topic,
17240
+ timestamp: Number(streamHeader.timestamp),
17241
+ attributes: streamHeader.attributes
17242
+ };
17243
+ const stream = new ReadableStream({
17244
+ start: (controller) => {
17245
+ streamController = controller;
17246
+ if (this.textStreamControllers.has(streamHeader.streamId)) {
17247
+ throw new DataStreamError("A data stream read is already in progress for a stream with id ".concat(streamHeader.streamId, "."), DataStreamErrorReason.AlreadyOpened);
17248
+ }
17249
+ this.textStreamControllers.set(streamHeader.streamId, {
17250
+ info,
17251
+ controller: streamController,
17252
+ startTime: Date.now(),
17253
+ sendingParticipantIdentity: participantIdentity,
17254
+ outOfBandFailureRejectingFuture
17255
+ });
17256
+ }
17257
+ });
17258
+ streamHandlerCallback(new TextStreamReader(info, stream, bigIntToNumber(streamHeader.totalLength), outOfBandFailureRejectingFuture), {
17259
+ identity: participantIdentity
17260
+ });
16944
17261
  }
16945
- return finalString;
16946
17262
  });
16947
17263
  }
17264
+ handleStreamChunk(chunk) {
17265
+ const fileBuffer = this.byteStreamControllers.get(chunk.streamId);
17266
+ if (fileBuffer) {
17267
+ if (chunk.content.length > 0) {
17268
+ fileBuffer.controller.enqueue(chunk);
17269
+ }
17270
+ }
17271
+ const textBuffer = this.textStreamControllers.get(chunk.streamId);
17272
+ if (textBuffer) {
17273
+ if (chunk.content.length > 0) {
17274
+ textBuffer.controller.enqueue(chunk);
17275
+ }
17276
+ }
17277
+ }
17278
+ handleStreamTrailer(trailer) {
17279
+ const textBuffer = this.textStreamControllers.get(trailer.streamId);
17280
+ if (textBuffer) {
17281
+ textBuffer.info.attributes = Object.assign(Object.assign({}, textBuffer.info.attributes), trailer.attributes);
17282
+ textBuffer.controller.close();
17283
+ this.textStreamControllers.delete(trailer.streamId);
17284
+ }
17285
+ const fileBuffer = this.byteStreamControllers.get(trailer.streamId);
17286
+ if (fileBuffer) {
17287
+ {
17288
+ fileBuffer.info.attributes = Object.assign(Object.assign({}, fileBuffer.info.attributes), trailer.attributes);
17289
+ fileBuffer.controller.close();
17290
+ this.byteStreamControllers.delete(trailer.streamId);
17291
+ }
17292
+ }
17293
+ }
16948
17294
  };
16949
17295
  BaseStreamWriter = class {
16950
17296
  constructor(writableStream, info, onClose) {
@@ -16969,6 +17315,277 @@ var init_livekit_client_esm = __esm({
16969
17315
  };
16970
17316
  ByteStreamWriter = class extends BaseStreamWriter {
16971
17317
  };
17318
+ STREAM_CHUNK_SIZE = 15e3;
17319
+ OutgoingDataStreamManager = class {
17320
+ constructor(engine, log2) {
17321
+ this.engine = engine;
17322
+ this.log = log2;
17323
+ }
17324
+ setupEngine(engine) {
17325
+ this.engine = engine;
17326
+ }
17327
+ /** {@inheritDoc LocalParticipant.sendText} */
17328
+ sendText(text7, options) {
17329
+ return __awaiter(this, void 0, void 0, function* () {
17330
+ var _a;
17331
+ const streamId = crypto.randomUUID();
17332
+ const textInBytes = new TextEncoder().encode(text7);
17333
+ const totalTextLength = textInBytes.byteLength;
17334
+ const fileIds = (_a = options === null || options === void 0 ? void 0 : options.attachments) === null || _a === void 0 ? void 0 : _a.map(() => crypto.randomUUID());
17335
+ const progresses = new Array(fileIds ? fileIds.length + 1 : 1).fill(0);
17336
+ const handleProgress = (progress, idx) => {
17337
+ var _a2;
17338
+ progresses[idx] = progress;
17339
+ const totalProgress = progresses.reduce((acc, val) => acc + val, 0);
17340
+ (_a2 = options === null || options === void 0 ? void 0 : options.onProgress) === null || _a2 === void 0 ? void 0 : _a2.call(options, totalProgress);
17341
+ };
17342
+ const writer2 = yield this.streamText({
17343
+ streamId,
17344
+ totalSize: totalTextLength,
17345
+ destinationIdentities: options === null || options === void 0 ? void 0 : options.destinationIdentities,
17346
+ topic: options === null || options === void 0 ? void 0 : options.topic,
17347
+ attachedStreamIds: fileIds,
17348
+ attributes: options === null || options === void 0 ? void 0 : options.attributes
17349
+ });
17350
+ yield writer2.write(text7);
17351
+ handleProgress(1, 0);
17352
+ yield writer2.close();
17353
+ if ((options === null || options === void 0 ? void 0 : options.attachments) && fileIds) {
17354
+ yield Promise.all(options.attachments.map((file, idx) => __awaiter(this, void 0, void 0, function* () {
17355
+ return this._sendFile(fileIds[idx], file, {
17356
+ topic: options.topic,
17357
+ mimeType: file.type,
17358
+ onProgress: (progress) => {
17359
+ handleProgress(progress, idx + 1);
17360
+ }
17361
+ });
17362
+ })));
17363
+ }
17364
+ return writer2.info;
17365
+ });
17366
+ }
17367
+ /**
17368
+ * @internal
17369
+ * @experimental CAUTION, might get removed in a minor release
17370
+ */
17371
+ streamText(options) {
17372
+ return __awaiter(this, void 0, void 0, function* () {
17373
+ var _a, _b;
17374
+ const streamId = (_a = options === null || options === void 0 ? void 0 : options.streamId) !== null && _a !== void 0 ? _a : crypto.randomUUID();
17375
+ const info = {
17376
+ id: streamId,
17377
+ mimeType: "text/plain",
17378
+ timestamp: Date.now(),
17379
+ topic: (_b = options === null || options === void 0 ? void 0 : options.topic) !== null && _b !== void 0 ? _b : "",
17380
+ size: options === null || options === void 0 ? void 0 : options.totalSize,
17381
+ attributes: options === null || options === void 0 ? void 0 : options.attributes
17382
+ };
17383
+ const header = new DataStream_Header({
17384
+ streamId,
17385
+ mimeType: info.mimeType,
17386
+ topic: info.topic,
17387
+ timestamp: numberToBigInt(info.timestamp),
17388
+ totalLength: numberToBigInt(options === null || options === void 0 ? void 0 : options.totalSize),
17389
+ attributes: info.attributes,
17390
+ contentHeader: {
17391
+ case: "textHeader",
17392
+ value: new DataStream_TextHeader({
17393
+ version: options === null || options === void 0 ? void 0 : options.version,
17394
+ attachedStreamIds: options === null || options === void 0 ? void 0 : options.attachedStreamIds,
17395
+ replyToStreamId: options === null || options === void 0 ? void 0 : options.replyToStreamId,
17396
+ operationType: (options === null || options === void 0 ? void 0 : options.type) === "update" ? DataStream_OperationType.UPDATE : DataStream_OperationType.CREATE
17397
+ })
17398
+ }
17399
+ });
17400
+ const destinationIdentities = options === null || options === void 0 ? void 0 : options.destinationIdentities;
17401
+ const packet = new DataPacket({
17402
+ destinationIdentities,
17403
+ value: {
17404
+ case: "streamHeader",
17405
+ value: header
17406
+ }
17407
+ });
17408
+ yield this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
17409
+ let chunkId = 0;
17410
+ const engine = this.engine;
17411
+ const writableStream = new WritableStream({
17412
+ // Implement the sink
17413
+ write(text7) {
17414
+ return __awaiter(this, void 0, void 0, function* () {
17415
+ for (const textByteChunk of splitUtf8(text7, STREAM_CHUNK_SIZE)) {
17416
+ yield engine.waitForBufferStatusLow(DataPacket_Kind.RELIABLE);
17417
+ const chunk = new DataStream_Chunk({
17418
+ content: textByteChunk,
17419
+ streamId,
17420
+ chunkIndex: numberToBigInt(chunkId)
17421
+ });
17422
+ const chunkPacket = new DataPacket({
17423
+ destinationIdentities,
17424
+ value: {
17425
+ case: "streamChunk",
17426
+ value: chunk
17427
+ }
17428
+ });
17429
+ yield engine.sendDataPacket(chunkPacket, DataPacket_Kind.RELIABLE);
17430
+ chunkId += 1;
17431
+ }
17432
+ });
17433
+ },
17434
+ close() {
17435
+ return __awaiter(this, void 0, void 0, function* () {
17436
+ const trailer = new DataStream_Trailer({
17437
+ streamId
17438
+ });
17439
+ const trailerPacket = new DataPacket({
17440
+ destinationIdentities,
17441
+ value: {
17442
+ case: "streamTrailer",
17443
+ value: trailer
17444
+ }
17445
+ });
17446
+ yield engine.sendDataPacket(trailerPacket, DataPacket_Kind.RELIABLE);
17447
+ });
17448
+ },
17449
+ abort(err) {
17450
+ console.log("Sink error:", err);
17451
+ }
17452
+ });
17453
+ let onEngineClose = () => __awaiter(this, void 0, void 0, function* () {
17454
+ yield writer2.close();
17455
+ });
17456
+ engine.once(EngineEvent.Closing, onEngineClose);
17457
+ const writer2 = new TextStreamWriter(writableStream, info, () => this.engine.off(EngineEvent.Closing, onEngineClose));
17458
+ return writer2;
17459
+ });
17460
+ }
17461
+ sendFile(file, options) {
17462
+ return __awaiter(this, void 0, void 0, function* () {
17463
+ const streamId = crypto.randomUUID();
17464
+ yield this._sendFile(streamId, file, options);
17465
+ return {
17466
+ id: streamId
17467
+ };
17468
+ });
17469
+ }
17470
+ _sendFile(streamId, file, options) {
17471
+ return __awaiter(this, void 0, void 0, function* () {
17472
+ var _a;
17473
+ const writer2 = yield this.streamBytes({
17474
+ streamId,
17475
+ totalSize: file.size,
17476
+ name: file.name,
17477
+ mimeType: (_a = options === null || options === void 0 ? void 0 : options.mimeType) !== null && _a !== void 0 ? _a : file.type,
17478
+ topic: options === null || options === void 0 ? void 0 : options.topic,
17479
+ destinationIdentities: options === null || options === void 0 ? void 0 : options.destinationIdentities
17480
+ });
17481
+ const reader = file.stream().getReader();
17482
+ while (true) {
17483
+ const {
17484
+ done,
17485
+ value
17486
+ } = yield reader.read();
17487
+ if (done) {
17488
+ break;
17489
+ }
17490
+ yield writer2.write(value);
17491
+ }
17492
+ yield writer2.close();
17493
+ return writer2.info;
17494
+ });
17495
+ }
17496
+ streamBytes(options) {
17497
+ return __awaiter(this, void 0, void 0, function* () {
17498
+ var _a, _b, _c, _d, _e;
17499
+ const streamId = (_a = options === null || options === void 0 ? void 0 : options.streamId) !== null && _a !== void 0 ? _a : crypto.randomUUID();
17500
+ const destinationIdentities = options === null || options === void 0 ? void 0 : options.destinationIdentities;
17501
+ const info = {
17502
+ id: streamId,
17503
+ mimeType: (_b = options === null || options === void 0 ? void 0 : options.mimeType) !== null && _b !== void 0 ? _b : "application/octet-stream",
17504
+ topic: (_c = options === null || options === void 0 ? void 0 : options.topic) !== null && _c !== void 0 ? _c : "",
17505
+ timestamp: Date.now(),
17506
+ attributes: options === null || options === void 0 ? void 0 : options.attributes,
17507
+ size: options === null || options === void 0 ? void 0 : options.totalSize,
17508
+ name: (_d = options === null || options === void 0 ? void 0 : options.name) !== null && _d !== void 0 ? _d : "unknown"
17509
+ };
17510
+ const header = new DataStream_Header({
17511
+ totalLength: numberToBigInt((_e = info.size) !== null && _e !== void 0 ? _e : 0),
17512
+ mimeType: info.mimeType,
17513
+ streamId,
17514
+ topic: info.topic,
17515
+ timestamp: numberToBigInt(Date.now()),
17516
+ attributes: info.attributes,
17517
+ contentHeader: {
17518
+ case: "byteHeader",
17519
+ value: new DataStream_ByteHeader({
17520
+ name: info.name
17521
+ })
17522
+ }
17523
+ });
17524
+ const packet = new DataPacket({
17525
+ destinationIdentities,
17526
+ value: {
17527
+ case: "streamHeader",
17528
+ value: header
17529
+ }
17530
+ });
17531
+ yield this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
17532
+ let chunkId = 0;
17533
+ const writeMutex = new _();
17534
+ const engine = this.engine;
17535
+ const logLocal = this.log;
17536
+ const writableStream = new WritableStream({
17537
+ write(chunk) {
17538
+ return __awaiter(this, void 0, void 0, function* () {
17539
+ const unlock = yield writeMutex.lock();
17540
+ let byteOffset = 0;
17541
+ try {
17542
+ while (byteOffset < chunk.byteLength) {
17543
+ const subChunk = chunk.slice(byteOffset, byteOffset + STREAM_CHUNK_SIZE);
17544
+ yield engine.waitForBufferStatusLow(DataPacket_Kind.RELIABLE);
17545
+ const chunkPacket = new DataPacket({
17546
+ destinationIdentities,
17547
+ value: {
17548
+ case: "streamChunk",
17549
+ value: new DataStream_Chunk({
17550
+ content: subChunk,
17551
+ streamId,
17552
+ chunkIndex: numberToBigInt(chunkId)
17553
+ })
17554
+ }
17555
+ });
17556
+ yield engine.sendDataPacket(chunkPacket, DataPacket_Kind.RELIABLE);
17557
+ chunkId += 1;
17558
+ byteOffset += subChunk.byteLength;
17559
+ }
17560
+ } finally {
17561
+ unlock();
17562
+ }
17563
+ });
17564
+ },
17565
+ close() {
17566
+ return __awaiter(this, void 0, void 0, function* () {
17567
+ const trailer = new DataStream_Trailer({
17568
+ streamId
17569
+ });
17570
+ const trailerPacket = new DataPacket({
17571
+ destinationIdentities,
17572
+ value: {
17573
+ case: "streamTrailer",
17574
+ value: trailer
17575
+ }
17576
+ });
17577
+ yield engine.sendDataPacket(trailerPacket, DataPacket_Kind.RELIABLE);
17578
+ });
17579
+ },
17580
+ abort(err) {
17581
+ logLocal.error("Sink error:", err);
17582
+ }
17583
+ });
17584
+ const byteWriter = new ByteStreamWriter(writableStream, info);
17585
+ return byteWriter;
17586
+ });
17587
+ }
17588
+ };
16972
17589
  RemoteTrack = class extends Track {
16973
17590
  constructor(mediaTrack, sid, kind, receiver, loggerOptions) {
16974
17591
  super(mediaTrack, kind, loggerOptions);
@@ -17304,6 +17921,13 @@ var init_livekit_client_esm = __esm({
17304
17921
  get isAdaptiveStream() {
17305
17922
  return this.adaptiveStreamSettings !== void 0;
17306
17923
  }
17924
+ setStreamState(value) {
17925
+ super.setStreamState(value);
17926
+ console.log("setStreamState", value);
17927
+ if (value === Track.StreamState.Active) {
17928
+ this.updateVisibility();
17929
+ }
17930
+ }
17307
17931
  /**
17308
17932
  * Note: When using adaptiveStream, you need to use remoteVideoTrack.attach() to add the track to a HTMLVideoElement, otherwise your video tracks might never start
17309
17933
  */
@@ -17447,13 +18071,13 @@ var init_livekit_client_esm = __esm({
17447
18071
  this.updateVisibility();
17448
18072
  });
17449
18073
  }
17450
- updateVisibility() {
18074
+ updateVisibility(forceEmit) {
17451
18075
  var _a, _b;
17452
18076
  const lastVisibilityChange = this.elementInfos.reduce((prev, info) => Math.max(prev, info.visibilityChangedAt || 0), 0);
17453
18077
  const backgroundPause = ((_b = (_a = this.adaptiveStreamSettings) === null || _a === void 0 ? void 0 : _a.pauseVideoInBackground) !== null && _b !== void 0 ? _b : true) ? this.isInBackground : false;
17454
18078
  const isPiPMode = this.elementInfos.some((info) => info.pictureInPicture);
17455
18079
  const isVisible = this.elementInfos.some((info) => info.visible) && !backgroundPause || isPiPMode;
17456
- if (this.lastVisible === isVisible) {
18080
+ if (this.lastVisible === isVisible && !forceEmit) {
17457
18081
  return;
17458
18082
  }
17459
18083
  if (!isVisible && Date.now() - lastVisibilityChange < REACTION_DELAY) {
@@ -18021,10 +18645,9 @@ var init_livekit_client_esm = __esm({
18021
18645
  }
18022
18646
  }
18023
18647
  };
18024
- STREAM_CHUNK_SIZE = 15e3;
18025
18648
  LocalParticipant = class extends Participant {
18026
18649
  /** @internal */
18027
- constructor(sid, identity, engine, options, roomRpcHandlers) {
18650
+ constructor(sid, identity, engine, options, roomRpcHandlers, roomOutgoingDataStreamManager) {
18028
18651
  super(sid, identity, void 0, void 0, void 0, {
18029
18652
  loggerName: options.loggerName,
18030
18653
  loggerContextCb: () => this.engine.logContext
@@ -18250,6 +18873,7 @@ var init_livekit_client_esm = __esm({
18250
18873
  this.activeDeviceMap = /* @__PURE__ */ new Map([["audioinput", "default"], ["videoinput", "default"], ["audiooutput", "default"]]);
18251
18874
  this.pendingSignalRequests = /* @__PURE__ */ new Map();
18252
18875
  this.rpcHandlers = roomRpcHandlers;
18876
+ this.roomOutgoingDataStreamManager = roomOutgoingDataStreamManager;
18253
18877
  }
18254
18878
  get lastCameraError() {
18255
18879
  return this.cameraError;
@@ -18341,7 +18965,7 @@ var init_livekit_client_esm = __esm({
18341
18965
  name: name2,
18342
18966
  attributes
18343
18967
  } = _ref;
18344
- return function* () {
18968
+ return (function* () {
18345
18969
  return new Promise((resolve, reject) => __awaiter(_this, void 0, void 0, function* () {
18346
18970
  var _a2, _b;
18347
18971
  try {
@@ -18376,7 +19000,7 @@ var init_livekit_client_esm = __esm({
18376
19000
  if (e3 instanceof Error) reject(e3);
18377
19001
  }
18378
19002
  }));
18379
- }();
19003
+ })();
18380
19004
  });
18381
19005
  }
18382
19006
  /**
@@ -18645,7 +19269,7 @@ var init_livekit_client_esm = __esm({
18645
19269
  return __awaiter(this, arguments, void 0, function(track, options) {
18646
19270
  var _this2 = this;
18647
19271
  let isRepublish = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : false;
18648
- return function* () {
19272
+ return (function* () {
18649
19273
  var _a, _b, _c, _d;
18650
19274
  if (isLocalAudioTrack(track)) {
18651
19275
  track.setAudioContext(_this2.audioContext);
@@ -18770,7 +19394,7 @@ var init_livekit_client_esm = __esm({
18770
19394
  } finally {
18771
19395
  _this2.pendingPublishPromises.delete(track);
18772
19396
  }
18773
- }();
19397
+ })();
18774
19398
  });
18775
19399
  }
18776
19400
  waitUntilEngineConnected() {
@@ -19252,7 +19876,7 @@ var init_livekit_client_esm = __esm({
19252
19876
  return __awaiter(this, arguments, void 0, function(options) {
19253
19877
  var _this3 = this;
19254
19878
  let restartTracks = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true;
19255
- return function* () {
19879
+ return (function* () {
19256
19880
  if (_this3.republishPromise) {
19257
19881
  yield _this3.republishPromise;
19258
19882
  }
@@ -19286,7 +19910,7 @@ var init_livekit_client_esm = __esm({
19286
19910
  }
19287
19911
  }));
19288
19912
  yield _this3.republishPromise;
19289
- }();
19913
+ })();
19290
19914
  });
19291
19915
  }
19292
19916
  /**
@@ -19300,7 +19924,7 @@ var init_livekit_client_esm = __esm({
19300
19924
  return __awaiter(this, arguments, void 0, function(data) {
19301
19925
  var _this4 = this;
19302
19926
  let options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
19303
- return function* () {
19927
+ return (function* () {
19304
19928
  const kind = options.reliable ? DataPacket_Kind.RELIABLE : DataPacket_Kind.LOSSY;
19305
19929
  const destinationIdentities = options.destinationIdentities;
19306
19930
  const topic = options.topic;
@@ -19317,7 +19941,7 @@ var init_livekit_client_esm = __esm({
19317
19941
  }
19318
19942
  });
19319
19943
  yield _this4.engine.sendDataPacket(packet, kind);
19320
- }();
19944
+ })();
19321
19945
  });
19322
19946
  }
19323
19947
  /**
@@ -19341,6 +19965,7 @@ var init_livekit_client_esm = __esm({
19341
19965
  yield this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
19342
19966
  });
19343
19967
  }
19968
+ /** @deprecated Consider migrating to {@link sendText} */
19344
19969
  sendChatMessage(text7, options) {
19345
19970
  return __awaiter(this, void 0, void 0, function* () {
19346
19971
  const msg = {
@@ -19362,6 +19987,7 @@ var init_livekit_client_esm = __esm({
19362
19987
  return msg;
19363
19988
  });
19364
19989
  }
19990
+ /** @deprecated Consider migrating to {@link sendText} */
19365
19991
  editChatMessage(editText, originalMessage) {
19366
19992
  return __awaiter(this, void 0, void 0, function* () {
19367
19993
  const msg = Object.assign(Object.assign({}, originalMessage), {
@@ -19382,264 +20008,51 @@ var init_livekit_client_esm = __esm({
19382
20008
  return msg;
19383
20009
  });
19384
20010
  }
20011
+ /**
20012
+ * Sends the given string to participants in the room via the data channel.
20013
+ * For longer messages, consider using {@link streamText} instead.
20014
+ *
20015
+ * @param text The text payload
20016
+ * @param options.topic Topic identifier used to route the stream to appropriate handlers.
20017
+ */
19385
20018
  sendText(text7, options) {
19386
20019
  return __awaiter(this, void 0, void 0, function* () {
19387
- var _a;
19388
- const streamId = crypto.randomUUID();
19389
- const textInBytes = new TextEncoder().encode(text7);
19390
- const totalTextLength = textInBytes.byteLength;
19391
- const fileIds = (_a = options === null || options === void 0 ? void 0 : options.attachments) === null || _a === void 0 ? void 0 : _a.map(() => crypto.randomUUID());
19392
- const progresses = new Array(fileIds ? fileIds.length + 1 : 1).fill(0);
19393
- const handleProgress = (progress, idx) => {
19394
- var _a2;
19395
- progresses[idx] = progress;
19396
- const totalProgress = progresses.reduce((acc, val) => acc + val, 0);
19397
- (_a2 = options === null || options === void 0 ? void 0 : options.onProgress) === null || _a2 === void 0 ? void 0 : _a2.call(options, totalProgress);
19398
- };
19399
- const writer2 = yield this.streamText({
19400
- streamId,
19401
- totalSize: totalTextLength,
19402
- destinationIdentities: options === null || options === void 0 ? void 0 : options.destinationIdentities,
19403
- topic: options === null || options === void 0 ? void 0 : options.topic,
19404
- attachedStreamIds: fileIds,
19405
- attributes: options === null || options === void 0 ? void 0 : options.attributes
19406
- });
19407
- yield writer2.write(text7);
19408
- handleProgress(1, 0);
19409
- yield writer2.close();
19410
- if ((options === null || options === void 0 ? void 0 : options.attachments) && fileIds) {
19411
- yield Promise.all(options.attachments.map((file, idx) => __awaiter(this, void 0, void 0, function* () {
19412
- return this._sendFile(fileIds[idx], file, {
19413
- topic: options.topic,
19414
- mimeType: file.type,
19415
- onProgress: (progress) => {
19416
- handleProgress(progress, idx + 1);
19417
- }
19418
- });
19419
- })));
19420
- }
19421
- return writer2.info;
20020
+ return this.roomOutgoingDataStreamManager.sendText(text7, options);
19422
20021
  });
19423
20022
  }
19424
20023
  /**
20024
+ * Creates a new TextStreamWriter which can be used to stream text incrementally
20025
+ * to participants in the room via the data channel.
20026
+ *
20027
+ * @param options.topic Topic identifier used to route the stream to appropriate handlers.
20028
+ *
19425
20029
  * @internal
19426
20030
  * @experimental CAUTION, might get removed in a minor release
19427
20031
  */
19428
20032
  streamText(options) {
19429
20033
  return __awaiter(this, void 0, void 0, function* () {
19430
- var _a, _b;
19431
- const streamId = (_a = options === null || options === void 0 ? void 0 : options.streamId) !== null && _a !== void 0 ? _a : crypto.randomUUID();
19432
- const info = {
19433
- id: streamId,
19434
- mimeType: "text/plain",
19435
- timestamp: Date.now(),
19436
- topic: (_b = options === null || options === void 0 ? void 0 : options.topic) !== null && _b !== void 0 ? _b : "",
19437
- size: options === null || options === void 0 ? void 0 : options.totalSize,
19438
- attributes: options === null || options === void 0 ? void 0 : options.attributes
19439
- };
19440
- const header = new DataStream_Header({
19441
- streamId,
19442
- mimeType: info.mimeType,
19443
- topic: info.topic,
19444
- timestamp: numberToBigInt(info.timestamp),
19445
- totalLength: numberToBigInt(options === null || options === void 0 ? void 0 : options.totalSize),
19446
- attributes: info.attributes,
19447
- contentHeader: {
19448
- case: "textHeader",
19449
- value: new DataStream_TextHeader({
19450
- version: options === null || options === void 0 ? void 0 : options.version,
19451
- attachedStreamIds: options === null || options === void 0 ? void 0 : options.attachedStreamIds,
19452
- replyToStreamId: options === null || options === void 0 ? void 0 : options.replyToStreamId,
19453
- operationType: (options === null || options === void 0 ? void 0 : options.type) === "update" ? DataStream_OperationType.UPDATE : DataStream_OperationType.CREATE
19454
- })
19455
- }
19456
- });
19457
- const destinationIdentities = options === null || options === void 0 ? void 0 : options.destinationIdentities;
19458
- const packet = new DataPacket({
19459
- destinationIdentities,
19460
- value: {
19461
- case: "streamHeader",
19462
- value: header
19463
- }
19464
- });
19465
- yield this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
19466
- let chunkId = 0;
19467
- const localP = this;
19468
- const writableStream = new WritableStream({
19469
- // Implement the sink
19470
- write(text7) {
19471
- return __awaiter(this, void 0, void 0, function* () {
19472
- for (const textByteChunk of splitUtf8(text7, STREAM_CHUNK_SIZE)) {
19473
- yield localP.engine.waitForBufferStatusLow(DataPacket_Kind.RELIABLE);
19474
- const chunk = new DataStream_Chunk({
19475
- content: textByteChunk,
19476
- streamId,
19477
- chunkIndex: numberToBigInt(chunkId)
19478
- });
19479
- const chunkPacket = new DataPacket({
19480
- destinationIdentities,
19481
- value: {
19482
- case: "streamChunk",
19483
- value: chunk
19484
- }
19485
- });
19486
- yield localP.engine.sendDataPacket(chunkPacket, DataPacket_Kind.RELIABLE);
19487
- chunkId += 1;
19488
- }
19489
- });
19490
- },
19491
- close() {
19492
- return __awaiter(this, void 0, void 0, function* () {
19493
- const trailer = new DataStream_Trailer({
19494
- streamId
19495
- });
19496
- const trailerPacket = new DataPacket({
19497
- destinationIdentities,
19498
- value: {
19499
- case: "streamTrailer",
19500
- value: trailer
19501
- }
19502
- });
19503
- yield localP.engine.sendDataPacket(trailerPacket, DataPacket_Kind.RELIABLE);
19504
- });
19505
- },
19506
- abort(err) {
19507
- console.log("Sink error:", err);
19508
- }
19509
- });
19510
- let onEngineClose = () => __awaiter(this, void 0, void 0, function* () {
19511
- yield writer2.close();
19512
- });
19513
- localP.engine.once(EngineEvent.Closing, onEngineClose);
19514
- const writer2 = new TextStreamWriter(writableStream, info, () => this.engine.off(EngineEvent.Closing, onEngineClose));
19515
- return writer2;
20034
+ return this.roomOutgoingDataStreamManager.streamText(options);
19516
20035
  });
19517
20036
  }
20037
+ /** Send a File to all participants in the room via the data channel.
20038
+ * @param file The File object payload
20039
+ * @param options.topic Topic identifier used to route the stream to appropriate handlers.
20040
+ * @param options.onProgress A callback function used to monitor the upload progress percentage.
20041
+ */
19518
20042
  sendFile(file, options) {
19519
20043
  return __awaiter(this, void 0, void 0, function* () {
19520
- const streamId = crypto.randomUUID();
19521
- yield this._sendFile(streamId, file, options);
19522
- return {
19523
- id: streamId
19524
- };
19525
- });
19526
- }
19527
- _sendFile(streamId, file, options) {
19528
- return __awaiter(this, void 0, void 0, function* () {
19529
- var _a;
19530
- const writer2 = yield this.streamBytes({
19531
- streamId,
19532
- totalSize: file.size,
19533
- name: file.name,
19534
- mimeType: (_a = options === null || options === void 0 ? void 0 : options.mimeType) !== null && _a !== void 0 ? _a : file.type,
19535
- topic: options === null || options === void 0 ? void 0 : options.topic,
19536
- destinationIdentities: options === null || options === void 0 ? void 0 : options.destinationIdentities
19537
- });
19538
- const reader = file.stream().getReader();
19539
- while (true) {
19540
- const {
19541
- done,
19542
- value
19543
- } = yield reader.read();
19544
- if (done) {
19545
- break;
19546
- }
19547
- yield writer2.write(value);
19548
- }
19549
- yield writer2.close();
19550
- return writer2.info;
20044
+ return this.roomOutgoingDataStreamManager.sendFile(file, options);
19551
20045
  });
19552
20046
  }
20047
+ /**
20048
+ * Stream bytes incrementally to participants in the room via the data channel.
20049
+ * For sending files, consider using {@link sendFile} instead.
20050
+ *
20051
+ * @param options.topic Topic identifier used to route the stream to appropriate handlers.
20052
+ */
19553
20053
  streamBytes(options) {
19554
20054
  return __awaiter(this, void 0, void 0, function* () {
19555
- var _a, _b, _c, _d, _e;
19556
- const streamId = (_a = options === null || options === void 0 ? void 0 : options.streamId) !== null && _a !== void 0 ? _a : crypto.randomUUID();
19557
- const destinationIdentities = options === null || options === void 0 ? void 0 : options.destinationIdentities;
19558
- const info = {
19559
- id: streamId,
19560
- mimeType: (_b = options === null || options === void 0 ? void 0 : options.mimeType) !== null && _b !== void 0 ? _b : "application/octet-stream",
19561
- topic: (_c = options === null || options === void 0 ? void 0 : options.topic) !== null && _c !== void 0 ? _c : "",
19562
- timestamp: Date.now(),
19563
- attributes: options === null || options === void 0 ? void 0 : options.attributes,
19564
- size: options === null || options === void 0 ? void 0 : options.totalSize,
19565
- name: (_d = options === null || options === void 0 ? void 0 : options.name) !== null && _d !== void 0 ? _d : "unknown"
19566
- };
19567
- const header = new DataStream_Header({
19568
- totalLength: numberToBigInt((_e = info.size) !== null && _e !== void 0 ? _e : 0),
19569
- mimeType: info.mimeType,
19570
- streamId,
19571
- topic: info.topic,
19572
- timestamp: numberToBigInt(Date.now()),
19573
- attributes: info.attributes,
19574
- contentHeader: {
19575
- case: "byteHeader",
19576
- value: new DataStream_ByteHeader({
19577
- name: info.name
19578
- })
19579
- }
19580
- });
19581
- const packet = new DataPacket({
19582
- destinationIdentities,
19583
- value: {
19584
- case: "streamHeader",
19585
- value: header
19586
- }
19587
- });
19588
- yield this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
19589
- let chunkId = 0;
19590
- const writeMutex = new _();
19591
- const engine = this.engine;
19592
- const log2 = this.log;
19593
- const writableStream = new WritableStream({
19594
- write(chunk) {
19595
- return __awaiter(this, void 0, void 0, function* () {
19596
- const unlock = yield writeMutex.lock();
19597
- let byteOffset = 0;
19598
- try {
19599
- while (byteOffset < chunk.byteLength) {
19600
- const subChunk = chunk.slice(byteOffset, byteOffset + STREAM_CHUNK_SIZE);
19601
- yield engine.waitForBufferStatusLow(DataPacket_Kind.RELIABLE);
19602
- const chunkPacket = new DataPacket({
19603
- destinationIdentities,
19604
- value: {
19605
- case: "streamChunk",
19606
- value: new DataStream_Chunk({
19607
- content: subChunk,
19608
- streamId,
19609
- chunkIndex: numberToBigInt(chunkId)
19610
- })
19611
- }
19612
- });
19613
- yield engine.sendDataPacket(chunkPacket, DataPacket_Kind.RELIABLE);
19614
- chunkId += 1;
19615
- byteOffset += subChunk.byteLength;
19616
- }
19617
- } finally {
19618
- unlock();
19619
- }
19620
- });
19621
- },
19622
- close() {
19623
- return __awaiter(this, void 0, void 0, function* () {
19624
- const trailer = new DataStream_Trailer({
19625
- streamId
19626
- });
19627
- const trailerPacket = new DataPacket({
19628
- destinationIdentities,
19629
- value: {
19630
- case: "streamTrailer",
19631
- value: trailer
19632
- }
19633
- });
19634
- yield engine.sendDataPacket(trailerPacket, DataPacket_Kind.RELIABLE);
19635
- });
19636
- },
19637
- abort(err) {
19638
- log2.error("Sink error:", err);
19639
- }
19640
- });
19641
- const byteWriter = new ByteStreamWriter(writableStream, info);
19642
- return byteWriter;
20055
+ return this.roomOutgoingDataStreamManager.streamBytes(options);
19643
20056
  });
19644
20057
  }
19645
20058
  /**
@@ -19657,7 +20070,7 @@ var init_livekit_client_esm = __esm({
19657
20070
  payload,
19658
20071
  responseTimeout = 1e4
19659
20072
  } = _ref3;
19660
- return function* () {
20073
+ return (function* () {
19661
20074
  const maxRoundTripLatency = 2e3;
19662
20075
  return new Promise((resolve, reject) => __awaiter(_this5, void 0, void 0, function* () {
19663
20076
  var _a2, _b, _c, _d;
@@ -19704,7 +20117,7 @@ var init_livekit_client_esm = __esm({
19704
20117
  participantIdentity: destinationIdentity
19705
20118
  });
19706
20119
  }));
19707
- }();
20120
+ })();
19708
20121
  });
19709
20122
  }
19710
20123
  /**
@@ -20396,12 +20809,12 @@ var init_livekit_client_esm = __esm({
20396
20809
  return super.emit(event, ...args);
20397
20810
  }
20398
20811
  };
20399
- (function(ConnectionState2) {
20400
- ConnectionState2["Disconnected"] = "disconnected";
20401
- ConnectionState2["Connecting"] = "connecting";
20402
- ConnectionState2["Connected"] = "connected";
20403
- ConnectionState2["Reconnecting"] = "reconnecting";
20404
- ConnectionState2["SignalReconnecting"] = "signalReconnecting";
20812
+ (function(ConnectionState3) {
20813
+ ConnectionState3["Disconnected"] = "disconnected";
20814
+ ConnectionState3["Connecting"] = "connecting";
20815
+ ConnectionState3["Connected"] = "connected";
20816
+ ConnectionState3["Reconnecting"] = "reconnecting";
20817
+ ConnectionState3["SignalReconnecting"] = "signalReconnecting";
20405
20818
  })(ConnectionState || (ConnectionState = {}));
20406
20819
  connectionReconcileFrequency = 4 * 1e3;
20407
20820
  Room = class _Room extends eventsExports.EventEmitter {
@@ -20422,10 +20835,6 @@ var init_livekit_client_esm = __esm({
20422
20835
  this.log = livekitLogger;
20423
20836
  this.bufferedEvents = [];
20424
20837
  this.isResuming = false;
20425
- this.byteStreamControllers = /* @__PURE__ */ new Map();
20426
- this.textStreamControllers = /* @__PURE__ */ new Map();
20427
- this.byteStreamHandlers = /* @__PURE__ */ new Map();
20428
- this.textStreamHandlers = /* @__PURE__ */ new Map();
20429
20838
  this.rpcHandlers = /* @__PURE__ */ new Map();
20430
20839
  this.connect = (url, token2, opts) => __awaiter(this, void 0, void 0, function* () {
20431
20840
  var _a2;
@@ -20640,7 +21049,7 @@ var init_livekit_client_esm = __esm({
20640
21049
  return __awaiter(_this, [...args_1], void 0, function() {
20641
21050
  var _this2 = this;
20642
21051
  let stopTracks = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : true;
20643
- return function* () {
21052
+ return (function* () {
20644
21053
  var _a2, _b2, _c2, _d;
20645
21054
  const unlock = yield _this2.disconnectLock.lock();
20646
21055
  try {
@@ -20666,7 +21075,7 @@ var init_livekit_client_esm = __esm({
20666
21075
  } finally {
20667
21076
  unlock();
20668
21077
  }
20669
- }();
21078
+ })();
20670
21079
  });
20671
21080
  };
20672
21081
  this.onPageLeave = () => __awaiter(this, void 0, void 0, function* () {
@@ -20874,8 +21283,8 @@ var init_livekit_client_esm = __esm({
20874
21283
  return;
20875
21284
  }
20876
21285
  const newStreamState = Track.streamStateFromProto(streamState.state);
21286
+ pub.track.setStreamState(newStreamState);
20877
21287
  if (newStreamState !== pub.track.streamState) {
20878
- pub.track.streamState = newStreamState;
20879
21288
  participant.emit(ParticipantEvent.TrackStreamStateChanged, pub, pub.track.streamState);
20880
21289
  this.emitWhenConnected(RoomEvent.TrackStreamStateChanged, pub, pub.track.streamState, participant);
20881
21290
  }
@@ -20915,12 +21324,8 @@ var init_livekit_client_esm = __esm({
20915
21324
  this.handleChatMessage(participant, packet.value.value);
20916
21325
  } else if (packet.value.case === "metrics") {
20917
21326
  this.handleMetrics(packet.value.value, participant);
20918
- } else if (packet.value.case === "streamHeader") {
20919
- this.handleStreamHeader(packet.value.value, packet.participantIdentity);
20920
- } else if (packet.value.case === "streamChunk") {
20921
- this.handleStreamChunk(packet.value.value);
20922
- } else if (packet.value.case === "streamTrailer") {
20923
- this.handleStreamTrailer(packet.value.value);
21327
+ } else if (packet.value.case === "streamHeader" || packet.value.case === "streamChunk" || packet.value.case === "streamTrailer") {
21328
+ this.handleDataStream(packet);
20924
21329
  } else if (packet.value.case === "rpcRequest") {
20925
21330
  const rpc = packet.value.value;
20926
21331
  this.handleIncomingRpcRequest(packet.participantIdentity, rpc.id, rpc.method, rpc.payload, rpc.responseTimeoutMs, rpc.version);
@@ -20934,7 +21339,6 @@ var init_livekit_client_esm = __esm({
20934
21339
  this.emit(RoomEvent.SipDTMFReceived, dtmf, participant);
20935
21340
  participant === null || participant === void 0 ? void 0 : participant.emit(ParticipantEvent.SipDTMFReceived, dtmf);
20936
21341
  };
20937
- this.bufferedSegments = /* @__PURE__ */ new Map();
20938
21342
  this.handleTranscription = (_remoteParticipant, transcription) => {
20939
21343
  const participant = transcription.transcribedParticipantIdentity === this.localParticipant.identity ? this.localParticipant : this.getParticipantByIdentity(transcription.transcribedParticipantIdentity);
20940
21344
  const publication = participant === null || participant === void 0 ? void 0 : participant.trackPublications.get(transcription.trackId);
@@ -20950,6 +21354,10 @@ var init_livekit_client_esm = __esm({
20950
21354
  this.handleMetrics = (metrics, participant) => {
20951
21355
  this.emit(RoomEvent.MetricsReceived, metrics, participant);
20952
21356
  };
21357
+ this.handleDataStream = (packet) => {
21358
+ this.incomingDataStreamManager.handleDataStreamPacket(packet);
21359
+ };
21360
+ this.bufferedSegments = /* @__PURE__ */ new Map();
20953
21361
  this.handleAudioPlaybackStarted = () => {
20954
21362
  if (this.canPlaybackAudio) {
20955
21363
  return;
@@ -21083,8 +21491,10 @@ var init_livekit_client_esm = __esm({
21083
21491
  this.options.videoCaptureDefaults = Object.assign(Object.assign({}, videoDefaults), options === null || options === void 0 ? void 0 : options.videoCaptureDefaults);
21084
21492
  this.options.publishDefaults = Object.assign(Object.assign({}, publishDefaults), options === null || options === void 0 ? void 0 : options.publishDefaults);
21085
21493
  this.maybeCreateEngine();
21494
+ this.incomingDataStreamManager = new IncomingDataStreamManager();
21495
+ this.outgoingDataStreamManager = new OutgoingDataStreamManager(this.engine, this.log);
21086
21496
  this.disconnectLock = new _();
21087
- this.localParticipant = new LocalParticipant("", "", this.engine, this.options, this.rpcHandlers);
21497
+ this.localParticipant = new LocalParticipant("", "", this.engine, this.options, this.rpcHandlers, this.outgoingDataStreamManager);
21088
21498
  if (this.options.videoCaptureDefaults.deviceId) {
21089
21499
  this.localParticipant.activeDeviceMap.set("videoinput", unwrapConstraint(this.options.videoCaptureDefaults.deviceId));
21090
21500
  }
@@ -21110,22 +21520,16 @@ var init_livekit_client_esm = __esm({
21110
21520
  }
21111
21521
  }
21112
21522
  registerTextStreamHandler(topic, callback) {
21113
- if (this.textStreamHandlers.has(topic)) {
21114
- throw new TypeError('A text stream handler for topic "'.concat(topic, '" has already been set.'));
21115
- }
21116
- this.textStreamHandlers.set(topic, callback);
21523
+ return this.incomingDataStreamManager.registerTextStreamHandler(topic, callback);
21117
21524
  }
21118
21525
  unregisterTextStreamHandler(topic) {
21119
- this.textStreamHandlers.delete(topic);
21526
+ return this.incomingDataStreamManager.unregisterTextStreamHandler(topic);
21120
21527
  }
21121
21528
  registerByteStreamHandler(topic, callback) {
21122
- if (this.byteStreamHandlers.has(topic)) {
21123
- throw new TypeError('A byte stream handler for topic "'.concat(topic, '" has already been set.'));
21124
- }
21125
- this.byteStreamHandlers.set(topic, callback);
21529
+ return this.incomingDataStreamManager.registerByteStreamHandler(topic, callback);
21126
21530
  }
21127
21531
  unregisterByteStreamHandler(topic) {
21128
- this.byteStreamHandlers.delete(topic);
21532
+ return this.incomingDataStreamManager.unregisterByteStreamHandler(topic);
21129
21533
  }
21130
21534
  /**
21131
21535
  * Establishes the participant as a receiver for calls of the specified RPC method.
@@ -21167,44 +21571,6 @@ var init_livekit_client_esm = __esm({
21167
21571
  unregisterRpcMethod(method) {
21168
21572
  this.rpcHandlers.delete(method);
21169
21573
  }
21170
- handleIncomingRpcRequest(callerIdentity, requestId, method, payload, responseTimeout, version2) {
21171
- return __awaiter(this, void 0, void 0, function* () {
21172
- yield this.engine.publishRpcAck(callerIdentity, requestId);
21173
- if (version2 !== 1) {
21174
- yield this.engine.publishRpcResponse(callerIdentity, requestId, null, RpcError.builtIn("UNSUPPORTED_VERSION"));
21175
- return;
21176
- }
21177
- const handler = this.rpcHandlers.get(method);
21178
- if (!handler) {
21179
- yield this.engine.publishRpcResponse(callerIdentity, requestId, null, RpcError.builtIn("UNSUPPORTED_METHOD"));
21180
- return;
21181
- }
21182
- let responseError = null;
21183
- let responsePayload = null;
21184
- try {
21185
- const response = yield handler({
21186
- requestId,
21187
- callerIdentity,
21188
- payload,
21189
- responseTimeout
21190
- });
21191
- if (byteLength(response) > MAX_PAYLOAD_BYTES) {
21192
- responseError = RpcError.builtIn("RESPONSE_PAYLOAD_TOO_LARGE");
21193
- console.warn("RPC Response payload too large for ".concat(method));
21194
- } else {
21195
- responsePayload = response;
21196
- }
21197
- } catch (error) {
21198
- if (error instanceof RpcError) {
21199
- responseError = error;
21200
- } else {
21201
- console.warn("Uncaught error returned by RPC handler for ".concat(method, ". Returning APPLICATION_ERROR instead."), error);
21202
- responseError = RpcError.builtIn("APPLICATION_ERROR");
21203
- }
21204
- }
21205
- yield this.engine.publishRpcResponse(callerIdentity, requestId, responsePayload, responseError);
21206
- });
21207
- }
21208
21574
  /**
21209
21575
  * @experimental
21210
21576
  */
@@ -21369,6 +21735,9 @@ var init_livekit_client_esm = __esm({
21369
21735
  if (this.e2eeManager) {
21370
21736
  this.e2eeManager.setupEngine(this.engine);
21371
21737
  }
21738
+ if (this.outgoingDataStreamManager) {
21739
+ this.outgoingDataStreamManager.setupEngine(this.engine);
21740
+ }
21372
21741
  }
21373
21742
  /**
21374
21743
  * getLocalDevices abstracts navigator.mediaDevices.enumerateDevices.
@@ -21579,7 +21948,7 @@ var init_livekit_client_esm = __esm({
21579
21948
  return __awaiter(this, arguments, void 0, function(kind, deviceId) {
21580
21949
  var _this3 = this;
21581
21950
  let exact = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : true;
21582
- return function* () {
21951
+ return (function* () {
21583
21952
  var _a, _b, _c, _d, _e, _f;
21584
21953
  var _g;
21585
21954
  let success = true;
@@ -21653,7 +22022,7 @@ var init_livekit_client_esm = __esm({
21653
22022
  _this3.emit(RoomEvent.ActiveDeviceChanged, kind, deviceId);
21654
22023
  }
21655
22024
  return success;
21656
- }();
22025
+ })();
21657
22026
  });
21658
22027
  }
21659
22028
  setupLocalParticipantEvents() {
@@ -21715,7 +22084,10 @@ var init_livekit_client_esm = __esm({
21715
22084
  adaptiveStreamSettings = {};
21716
22085
  }
21717
22086
  }
21718
- participant.addSubscribedMediaTrack(mediaTrack, trackId, stream, receiver, adaptiveStreamSettings);
22087
+ const publication = participant.addSubscribedMediaTrack(mediaTrack, trackId, stream, receiver, adaptiveStreamSettings);
22088
+ if ((publication === null || publication === void 0 ? void 0 : publication.isEncrypted) && !this.e2eeManager) {
22089
+ this.emit(RoomEvent.EncryptionError, new Error("Encrypted ".concat(publication.source, " track received from participant ").concat(participant.sid, ", but room does not have encryption enabled!")));
22090
+ }
21719
22091
  }
21720
22092
  handleDisconnect() {
21721
22093
  let shouldStopTracks = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : true;
@@ -21725,6 +22097,7 @@ var init_livekit_client_esm = __esm({
21725
22097
  this.isResuming = false;
21726
22098
  this.bufferedEvents = [];
21727
22099
  this.transcriptionReceivedTimes.clear();
22100
+ this.incomingDataStreamManager.clearHandlersAndControllers();
21728
22101
  if (this.state === ConnectionState.Disconnected) {
21729
22102
  return;
21730
22103
  }
@@ -21775,6 +22148,7 @@ var init_livekit_client_esm = __esm({
21775
22148
  if (!participant) {
21776
22149
  return;
21777
22150
  }
22151
+ this.incomingDataStreamManager.validateParticipantHasNoActiveDataStreams(identity);
21778
22152
  participant.trackPublications.forEach((publication) => {
21779
22153
  participant.unpublishTrack(publication.trackSid, true);
21780
22154
  });
@@ -21782,99 +22156,44 @@ var init_livekit_client_esm = __esm({
21782
22156
  participant.setDisconnected();
21783
22157
  (_a = this.localParticipant) === null || _a === void 0 ? void 0 : _a.handleParticipantDisconnected(participant.identity);
21784
22158
  }
21785
- handleStreamHeader(streamHeader, participantIdentity) {
22159
+ handleIncomingRpcRequest(callerIdentity, requestId, method, payload, responseTimeout, version2) {
21786
22160
  return __awaiter(this, void 0, void 0, function* () {
21787
- var _a;
21788
- if (streamHeader.contentHeader.case === "byteHeader") {
21789
- const streamHandlerCallback = this.byteStreamHandlers.get(streamHeader.topic);
21790
- if (!streamHandlerCallback) {
21791
- this.log.debug("ignoring incoming byte stream due to no handler for topic", streamHeader.topic);
21792
- return;
21793
- }
21794
- let streamController;
21795
- const info = {
21796
- id: streamHeader.streamId,
21797
- name: (_a = streamHeader.contentHeader.value.name) !== null && _a !== void 0 ? _a : "unknown",
21798
- mimeType: streamHeader.mimeType,
21799
- size: streamHeader.totalLength ? Number(streamHeader.totalLength) : void 0,
21800
- topic: streamHeader.topic,
21801
- timestamp: bigIntToNumber(streamHeader.timestamp),
21802
- attributes: streamHeader.attributes
21803
- };
21804
- const stream = new ReadableStream({
21805
- start: (controller) => {
21806
- streamController = controller;
21807
- this.byteStreamControllers.set(streamHeader.streamId, {
21808
- info,
21809
- controller: streamController,
21810
- startTime: Date.now()
21811
- });
21812
- }
21813
- });
21814
- streamHandlerCallback(new ByteStreamReader(info, stream, bigIntToNumber(streamHeader.totalLength)), {
21815
- identity: participantIdentity
22161
+ yield this.engine.publishRpcAck(callerIdentity, requestId);
22162
+ if (version2 !== 1) {
22163
+ yield this.engine.publishRpcResponse(callerIdentity, requestId, null, RpcError.builtIn("UNSUPPORTED_VERSION"));
22164
+ return;
22165
+ }
22166
+ const handler = this.rpcHandlers.get(method);
22167
+ if (!handler) {
22168
+ yield this.engine.publishRpcResponse(callerIdentity, requestId, null, RpcError.builtIn("UNSUPPORTED_METHOD"));
22169
+ return;
22170
+ }
22171
+ let responseError = null;
22172
+ let responsePayload = null;
22173
+ try {
22174
+ const response = yield handler({
22175
+ requestId,
22176
+ callerIdentity,
22177
+ payload,
22178
+ responseTimeout
21816
22179
  });
21817
- } else if (streamHeader.contentHeader.case === "textHeader") {
21818
- const streamHandlerCallback = this.textStreamHandlers.get(streamHeader.topic);
21819
- if (!streamHandlerCallback) {
21820
- this.log.debug("ignoring incoming text stream due to no handler for topic", streamHeader.topic);
21821
- return;
22180
+ if (byteLength(response) > MAX_PAYLOAD_BYTES) {
22181
+ responseError = RpcError.builtIn("RESPONSE_PAYLOAD_TOO_LARGE");
22182
+ console.warn("RPC Response payload too large for ".concat(method));
22183
+ } else {
22184
+ responsePayload = response;
22185
+ }
22186
+ } catch (error) {
22187
+ if (error instanceof RpcError) {
22188
+ responseError = error;
22189
+ } else {
22190
+ console.warn("Uncaught error returned by RPC handler for ".concat(method, ". Returning APPLICATION_ERROR instead."), error);
22191
+ responseError = RpcError.builtIn("APPLICATION_ERROR");
21822
22192
  }
21823
- let streamController;
21824
- const info = {
21825
- id: streamHeader.streamId,
21826
- mimeType: streamHeader.mimeType,
21827
- size: streamHeader.totalLength ? Number(streamHeader.totalLength) : void 0,
21828
- topic: streamHeader.topic,
21829
- timestamp: Number(streamHeader.timestamp),
21830
- attributes: streamHeader.attributes
21831
- };
21832
- const stream = new ReadableStream({
21833
- start: (controller) => {
21834
- streamController = controller;
21835
- this.textStreamControllers.set(streamHeader.streamId, {
21836
- info,
21837
- controller: streamController,
21838
- startTime: Date.now()
21839
- });
21840
- }
21841
- });
21842
- streamHandlerCallback(new TextStreamReader(info, stream, bigIntToNumber(streamHeader.totalLength)), {
21843
- identity: participantIdentity
21844
- });
21845
22193
  }
22194
+ yield this.engine.publishRpcResponse(callerIdentity, requestId, responsePayload, responseError);
21846
22195
  });
21847
22196
  }
21848
- handleStreamChunk(chunk) {
21849
- const fileBuffer = this.byteStreamControllers.get(chunk.streamId);
21850
- if (fileBuffer) {
21851
- if (chunk.content.length > 0) {
21852
- fileBuffer.controller.enqueue(chunk);
21853
- }
21854
- }
21855
- const textBuffer = this.textStreamControllers.get(chunk.streamId);
21856
- if (textBuffer) {
21857
- if (chunk.content.length > 0) {
21858
- textBuffer.controller.enqueue(chunk);
21859
- }
21860
- }
21861
- }
21862
- handleStreamTrailer(trailer) {
21863
- const textBuffer = this.textStreamControllers.get(trailer.streamId);
21864
- if (textBuffer) {
21865
- textBuffer.info.attributes = Object.assign(Object.assign({}, textBuffer.info.attributes), trailer.attributes);
21866
- textBuffer.controller.close();
21867
- this.textStreamControllers.delete(trailer.streamId);
21868
- }
21869
- const fileBuffer = this.byteStreamControllers.get(trailer.streamId);
21870
- if (fileBuffer) {
21871
- {
21872
- fileBuffer.info.attributes = Object.assign(Object.assign({}, fileBuffer.info.attributes), trailer.attributes);
21873
- fileBuffer.controller.close();
21874
- this.byteStreamControllers.delete(trailer.streamId);
21875
- }
21876
- }
21877
- }
21878
22197
  /**
21879
22198
  * attempt to select the default devices if the previously selected devices are no longer available after a device change event
21880
22199
  */
@@ -23311,11 +23630,12 @@ function setWebRTCCallbacks(newCallbacks) {
23311
23630
  function getCurrentCallbacks() {
23312
23631
  return callbacks;
23313
23632
  }
23314
- async function authenticate(userIdentity, apiKey, appId) {
23633
+ async function authenticate(userIdentity, apiKey, appId, language) {
23315
23634
  try {
23316
23635
  const authPayload = {
23317
23636
  user_identity: userIdentity,
23318
- app_id: appId || _appId
23637
+ app_id: appId || _appId,
23638
+ ...language && { language: language.code }
23319
23639
  };
23320
23640
  const response = await fetch(`${serverUrl}/auth/login`, {
23321
23641
  method: "POST",
@@ -23601,17 +23921,17 @@ var require_inline_style_parser = __commonJS({
23601
23921
  function position3() {
23602
23922
  var start2 = { line: lineno, column };
23603
23923
  return function(node2) {
23604
- node2.position = new Position(start2);
23924
+ node2.position = new Position2(start2);
23605
23925
  whitespace2();
23606
23926
  return node2;
23607
23927
  };
23608
23928
  }
23609
- function Position(start2) {
23929
+ function Position2(start2) {
23610
23930
  this.start = start2;
23611
23931
  this.end = { line: lineno, column };
23612
23932
  this.source = options.source;
23613
23933
  }
23614
- Position.prototype.content = style;
23934
+ Position2.prototype.content = style;
23615
23935
  var errorsList = [];
23616
23936
  function error(msg) {
23617
23937
  var err = new Error(
@@ -23916,7 +24236,7 @@ var require_core = __commonJS({
23916
24236
  root4.CryptoJS = factory();
23917
24237
  }
23918
24238
  })(exports, function() {
23919
- var CryptoJS = CryptoJS || function(Math2, undefined2) {
24239
+ var CryptoJS = CryptoJS || (function(Math2, undefined2) {
23920
24240
  var crypto2;
23921
24241
  if (typeof window !== "undefined" && window.crypto) {
23922
24242
  crypto2 = window.crypto;
@@ -23956,7 +24276,7 @@ var require_core = __commonJS({
23956
24276
  }
23957
24277
  throw new Error("Native crypto module could not be used to get secure random number.");
23958
24278
  };
23959
- var create2 = Object.create || /* @__PURE__ */ function() {
24279
+ var create2 = Object.create || /* @__PURE__ */ (function() {
23960
24280
  function F2() {
23961
24281
  }
23962
24282
  return function(obj) {
@@ -23966,10 +24286,10 @@ var require_core = __commonJS({
23966
24286
  F2.prototype = null;
23967
24287
  return subtype;
23968
24288
  };
23969
- }();
24289
+ })();
23970
24290
  var C = {};
23971
24291
  var C_lib = C.lib = {};
23972
- var Base = C_lib.Base = /* @__PURE__ */ function() {
24292
+ var Base = C_lib.Base = /* @__PURE__ */ (function() {
23973
24293
  return {
23974
24294
  /**
23975
24295
  * Creates a new object that inherits from this object.
@@ -24068,7 +24388,7 @@ var require_core = __commonJS({
24068
24388
  return this.init.prototype.extend(this);
24069
24389
  }
24070
24390
  };
24071
- }();
24391
+ })();
24072
24392
  var WordArray = C_lib.WordArray = Base.extend({
24073
24393
  /**
24074
24394
  * Initializes a newly created word array.
@@ -24506,7 +24826,7 @@ var require_core = __commonJS({
24506
24826
  });
24507
24827
  var C_algo = C.algo = {};
24508
24828
  return C;
24509
- }(Math);
24829
+ })(Math);
24510
24830
  return CryptoJS;
24511
24831
  });
24512
24832
  }
@@ -24695,11 +25015,15 @@ var require_md5 = __commonJS({
24695
25015
  // src/index.ts
24696
25016
  var index_exports = {};
24697
25017
  __export(index_exports, {
25018
+ AnsyrProvider: () => AnsyrProvider,
24698
25019
  BorderGlow: () => border_glow_default,
24699
25020
  ChatPopup: () => ChatPopup,
24700
- CuekitProvider: () => CuekitProvider,
25021
+ DraggableResizableContainer: () => DraggableResizableContainer,
24701
25022
  InitCuekit: () => InitCuekit,
25023
+ LanguageSelector: () => LanguageSelector,
24702
25024
  MicButton: () => MicButton,
25025
+ ResizeHandle: () => ResizeHandle,
25026
+ ResizeHandles: () => ResizeHandles,
24703
25027
  VoiceIntensityVisualizer: () => VoiceIntensityVisualizer,
24704
25028
  captureAllInteractiveElements: () => captureAllInteractiveElements,
24705
25029
  clearElementCache: () => clearElementCache,
@@ -24711,14 +25035,15 @@ __export(index_exports, {
24711
25035
  initWebRTC: () => initWebRTC,
24712
25036
  initWebRTCWithDeployedBackend: () => initWebRTCWithDeployedBackend,
24713
25037
  resolveRoutePath: () => resolveRoutePath,
25038
+ useAnsyrContext: () => useAnsyrContext,
24714
25039
  useCuekit: () => useCuekit,
24715
- useQubeContext: () => useQubeContext,
25040
+ useDraggableResizableContainer: () => useDraggableResizableContainer,
24716
25041
  useWebRTC: () => useWebRTC,
24717
25042
  validateDynamicElements: () => validateDynamicElements
24718
25043
  });
24719
25044
  module.exports = __toCommonJS(index_exports);
24720
25045
 
24721
- // src/providers/cuekit-provider.tsx
25046
+ // src/providers/ansyr-provider.tsx
24722
25047
  var import_react = __toESM(require("react"));
24723
25048
 
24724
25049
  // src/core/init.ts
@@ -24737,7 +25062,7 @@ function InitCuekit(config) {
24737
25062
  setWebRTCConfig(webRTCConfig);
24738
25063
  }
24739
25064
 
24740
- // src/providers/cuekit-provider.tsx
25065
+ // src/providers/ansyr-provider.tsx
24741
25066
  init_navigation();
24742
25067
  init_intent_store();
24743
25068
 
@@ -24782,9 +25107,9 @@ var initWebRTC = (apiKey) => {
24782
25107
  return initWebRTCWithDeployedBackend(apiKey);
24783
25108
  };
24784
25109
 
24785
- // src/providers/cuekit-provider.tsx
24786
- if (typeof window !== "undefined" && !globalThis.CuekitStore) {
24787
- globalThis.CuekitStore = {
25110
+ // src/providers/ansyr-provider.tsx
25111
+ if (typeof window !== "undefined" && !globalThis.AnsyrStore) {
25112
+ globalThis.AnsyrStore = {
24788
25113
  intent: null,
24789
25114
  lastText: "",
24790
25115
  lastClickedLabel: "",
@@ -24792,38 +25117,46 @@ if (typeof window !== "undefined" && !globalThis.CuekitStore) {
24792
25117
  appId: void 0,
24793
25118
  deviceId: void 0,
24794
25119
  update(data) {
24795
- Object.assign(globalThis.CuekitStore, data);
25120
+ Object.assign(globalThis.AnsyrStore, data);
24796
25121
  }
24797
25122
  };
24798
25123
  }
24799
- var QubeContext = (0, import_react.createContext)({
25124
+ var AnsyrContext = (0, import_react.createContext)({
24800
25125
  apiKey: "",
24801
- appId: ""
25126
+ appId: "",
25127
+ title: "ansyr.ai",
25128
+ showLogo: true,
25129
+ showAIIcon: true,
25130
+ showUserIcon: true
24802
25131
  });
24803
- var useQubeContext = () => (0, import_react.useContext)(QubeContext);
25132
+ var useAnsyrContext = () => (0, import_react.useContext)(AnsyrContext);
24804
25133
  var getUniqueId = () => {
24805
25134
  if (typeof window === "undefined") {
24806
25135
  return "server-" + Date.now().toString(36);
24807
25136
  }
24808
25137
  try {
24809
- let id = localStorage.getItem("cuekit_device_id");
25138
+ let id = localStorage.getItem("ansyr_device_id");
24810
25139
  if (!id) {
24811
25140
  id = Date.now().toString(36) + Math.random().toString(36).substring(2);
24812
- localStorage.setItem("cuekit_device_id", id);
25141
+ localStorage.setItem("ansyr_device_id", id);
24813
25142
  }
24814
25143
  return id;
24815
25144
  } catch {
24816
25145
  return "anon-" + Date.now().toString(36);
24817
25146
  }
24818
25147
  };
24819
- var CuekitProvider = ({
25148
+ var AnsyrProvider = ({
24820
25149
  apiKey,
24821
25150
  deviceId = "",
24822
25151
  appId,
24823
25152
  children,
24824
25153
  navigationHandler: navigationHandler2,
24825
25154
  onConnectionStateChange,
24826
- onParticipantUpdate
25155
+ onParticipantUpdate,
25156
+ title = "ansyr.ai",
25157
+ showLogo = true,
25158
+ showAIIcon = true,
25159
+ showUserIcon = true
24827
25160
  }) => {
24828
25161
  const [internalDeviceId, setInternalDeviceId] = (0, import_react.useState)(deviceId);
24829
25162
  (0, import_react.useEffect)(() => {
@@ -24871,8 +25204,8 @@ var CuekitProvider = ({
24871
25204
  }, [onConnectionStateChange, onParticipantUpdate, navigationHandler2]);
24872
25205
  (0, import_react.useEffect)(() => {
24873
25206
  const updateGlobalStore = (id) => {
24874
- if (typeof window !== "undefined" && globalThis.CuekitStore) {
24875
- globalThis.CuekitStore.update({
25207
+ if (typeof window !== "undefined" && globalThis.AnsyrStore) {
25208
+ globalThis.AnsyrStore.update({
24876
25209
  apiKey,
24877
25210
  appId,
24878
25211
  deviceId: id
@@ -24922,11 +25255,15 @@ var CuekitProvider = ({
24922
25255
  };
24923
25256
  }, [apiKey, appId, internalDeviceId]);
24924
25257
  return /* @__PURE__ */ import_react.default.createElement(
24925
- QubeContext.Provider,
25258
+ AnsyrContext.Provider,
24926
25259
  {
24927
25260
  value: {
24928
25261
  apiKey,
24929
- appId
25262
+ appId,
25263
+ title,
25264
+ showLogo,
25265
+ showAIIcon,
25266
+ showUserIcon
24930
25267
  }
24931
25268
  },
24932
25269
  children
@@ -24934,10 +25271,11 @@ var CuekitProvider = ({
24934
25271
  };
24935
25272
 
24936
25273
  // src/components/mic-button.tsx
24937
- var import_react15 = __toESM(require("react"));
25274
+ var import_react20 = __toESM(require("react"));
24938
25275
 
24939
25276
  // src/hooks/use-cuekit.ts
24940
25277
  var import_react3 = require("react");
25278
+ init_livekit_client_esm();
24941
25279
 
24942
25280
  // src/hooks/use-webrtc.ts
24943
25281
  var import_react2 = require("react");
@@ -24983,22 +25321,25 @@ var useWebRTC = (options) => {
24983
25321
  options?.onAISpeechStart,
24984
25322
  options?.onAISpeechEnd
24985
25323
  ]);
24986
- const connect = (0, import_react2.useCallback)(async (identity, apiKey, appId) => {
24987
- try {
24988
- setError(null);
24989
- setIsConnecting(true);
24990
- const authData = await authenticate(identity, apiKey || _apiKey, appId || _appId);
24991
- await connectToRoom(authData.livekit_url, authData.livekit_token);
24992
- setRoom(getRoom());
24993
- setIsConnected(true);
24994
- return authData;
24995
- } catch (err) {
24996
- setError(err.message || "Failed to connect");
24997
- setIsConnected(false);
24998
- } finally {
24999
- setIsConnecting(false);
25000
- }
25001
- }, []);
25324
+ const connect = (0, import_react2.useCallback)(
25325
+ async (identity, apiKey, appId, language) => {
25326
+ try {
25327
+ setError(null);
25328
+ setIsConnecting(true);
25329
+ const authData = await authenticate(identity, apiKey || _apiKey, appId || _appId, language);
25330
+ await connectToRoom(authData.livekit_url, authData.livekit_token);
25331
+ setRoom(getRoom());
25332
+ setIsConnected(true);
25333
+ return authData;
25334
+ } catch (err) {
25335
+ setError(err.message || "Failed to connect");
25336
+ setIsConnected(false);
25337
+ } finally {
25338
+ setIsConnecting(false);
25339
+ }
25340
+ },
25341
+ []
25342
+ );
25002
25343
  const disconnect = (0, import_react2.useCallback)(async () => {
25003
25344
  await disconnectFromRoom();
25004
25345
  setIsConnected(false);
@@ -25078,6 +25419,7 @@ var useCuekit = (options) => {
25078
25419
  }, []);
25079
25420
  const [micState, setMicState] = (0, import_react3.useState)("idle");
25080
25421
  const [status, setStatus] = (0, import_react3.useState)("");
25422
+ const [muteState, setMuteState] = (0, import_react3.useState)({ isMuted: false, canMute: false });
25081
25423
  const handleNavigationCommand = (event) => {
25082
25424
  console.log(`\u2B07\uFE0F Received event from backend: ${event.type}`, event);
25083
25425
  switch (event.type) {
@@ -25142,6 +25484,22 @@ var useCuekit = (options) => {
25142
25484
  }
25143
25485
  break;
25144
25486
  }
25487
+ case "chat": {
25488
+ const chatData = event.data;
25489
+ console.log("\u{1F4AC} Chat message received:", chatData);
25490
+ if (chatData.message && chatData.sender === "ai") {
25491
+ const newMessage = {
25492
+ id: `ai-${Date.now()}`,
25493
+ role: "ai",
25494
+ text: chatData.message,
25495
+ isFinal: true,
25496
+ timestamp: new Date(chatData.timestamp || Date.now()).toISOString()
25497
+ };
25498
+ setMessages((prev) => [...prev, newMessage]);
25499
+ setMicState("listening");
25500
+ }
25501
+ break;
25502
+ }
25145
25503
  case "request_runtime_data": {
25146
25504
  console.log("\u{1F9E0} Requesting runtime data");
25147
25505
  sendRuntimeData();
@@ -25174,17 +25532,21 @@ var useCuekit = (options) => {
25174
25532
  switch (state) {
25175
25533
  case "connecting":
25176
25534
  setStatus("Connecting...");
25535
+ setMuteState((prev) => ({ ...prev, canMute: false }));
25177
25536
  break;
25178
25537
  case "connected":
25179
25538
  setStatus("");
25180
25539
  setMicState("listening");
25540
+ setMuteState((prev) => ({ ...prev, canMute: true }));
25181
25541
  break;
25182
25542
  case "disconnected":
25183
25543
  setStatus("Disconnected");
25184
25544
  setMicState("idle");
25545
+ setMuteState({ isMuted: false, canMute: false });
25185
25546
  break;
25186
25547
  case "reconnecting":
25187
25548
  setStatus("Reconnecting...");
25549
+ setMuteState((prev) => ({ ...prev, canMute: false }));
25188
25550
  break;
25189
25551
  default:
25190
25552
  break;
@@ -25197,8 +25559,8 @@ var useCuekit = (options) => {
25197
25559
  onNavigationCommand: handleNavigationCommand
25198
25560
  });
25199
25561
  const connect = (0, import_react3.useCallback)(
25200
- async (identity, apiKey, appId) => {
25201
- await webrtc.connect(identity, apiKey, appId);
25562
+ async (identity, apiKey, appId, language) => {
25563
+ await webrtc.connect(identity, apiKey, appId, language);
25202
25564
  },
25203
25565
  [webrtc]
25204
25566
  );
@@ -25206,7 +25568,88 @@ var useCuekit = (options) => {
25206
25568
  await webrtc.disconnect();
25207
25569
  clearMessages();
25208
25570
  setMicState("idle");
25571
+ setMuteState({ isMuted: false, canMute: false });
25209
25572
  }, [webrtc, clearMessages]);
25573
+ const toggleMute = (0, import_react3.useCallback)(async () => {
25574
+ if (!webrtc.isConnected) return;
25575
+ try {
25576
+ const room2 = webrtc.room;
25577
+ if (!room2) return;
25578
+ const localParticipant = room2.localParticipant;
25579
+ const audioTrack = localParticipant.getTrackPublication(Track.Source.Microphone)?.track;
25580
+ if (audioTrack) {
25581
+ if (muteState.isMuted) {
25582
+ await audioTrack.unmute();
25583
+ setMuteState((prev) => ({ ...prev, isMuted: false }));
25584
+ } else {
25585
+ await audioTrack.mute();
25586
+ setMuteState((prev) => ({ ...prev, isMuted: true }));
25587
+ }
25588
+ }
25589
+ } catch (error) {
25590
+ console.error("Failed to toggle mute:", error);
25591
+ }
25592
+ }, [webrtc, muteState.isMuted]);
25593
+ const setMute = (0, import_react3.useCallback)(
25594
+ async (muted) => {
25595
+ if (!webrtc.isConnected) return;
25596
+ try {
25597
+ const room2 = webrtc.room;
25598
+ if (!room2) return;
25599
+ const localParticipant = room2.localParticipant;
25600
+ const audioTrack = localParticipant.getTrackPublication(Track.Source.Microphone)?.track;
25601
+ if (audioTrack) {
25602
+ if (muted && !muteState.isMuted) {
25603
+ await audioTrack.mute();
25604
+ setMuteState((prev) => ({ ...prev, isMuted: true }));
25605
+ } else if (!muted && muteState.isMuted) {
25606
+ await audioTrack.unmute();
25607
+ setMuteState((prev) => ({ ...prev, isMuted: false }));
25608
+ }
25609
+ }
25610
+ } catch (error) {
25611
+ console.error("Failed to set mute:", error);
25612
+ }
25613
+ },
25614
+ [webrtc, muteState.isMuted]
25615
+ );
25616
+ const sendChatMessage = (0, import_react3.useCallback)(
25617
+ async (message) => {
25618
+ if (!webrtc.isConnected) {
25619
+ console.warn("Cannot send chat message: not connected to LiveKit");
25620
+ return;
25621
+ }
25622
+ try {
25623
+ const room2 = webrtc.room;
25624
+ if (!room2) return;
25625
+ const payload = {
25626
+ type: "chat",
25627
+ message,
25628
+ timestamp: Date.now(),
25629
+ sender: "user"
25630
+ };
25631
+ console.log("\u{1F4E4} Sending chat message via LiveKit:", payload);
25632
+ const encoder = new TextEncoder();
25633
+ const encodedData = encoder.encode(JSON.stringify(payload));
25634
+ await room2.localParticipant.publishData(encodedData, {
25635
+ reliable: true
25636
+ });
25637
+ const newMessage = {
25638
+ id: `user-${Date.now()}`,
25639
+ role: "user",
25640
+ text: message,
25641
+ isFinal: true,
25642
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
25643
+ };
25644
+ setMessages((prev) => [...prev, newMessage]);
25645
+ setMicState("thinking");
25646
+ } catch (error) {
25647
+ console.error("Failed to send chat message:", error);
25648
+ throw error;
25649
+ }
25650
+ },
25651
+ [webrtc]
25652
+ );
25210
25653
  return {
25211
25654
  ...webrtc,
25212
25655
  messages,
@@ -25215,12 +25658,16 @@ var useCuekit = (options) => {
25215
25658
  status,
25216
25659
  setStatus,
25217
25660
  connect,
25218
- disconnect
25661
+ disconnect,
25662
+ muteState,
25663
+ toggleMute,
25664
+ setMute,
25665
+ sendChatMessage
25219
25666
  };
25220
25667
  };
25221
25668
 
25222
25669
  // src/components/chat-popup.tsx
25223
- var import_react9 = __toESM(require("react"));
25670
+ var import_react14 = __toESM(require("react"));
25224
25671
 
25225
25672
  // node_modules/devlop/lib/default.js
25226
25673
  function ok() {
@@ -32817,7 +33264,7 @@ var convert = (
32817
33264
  * @param {Test} [test]
32818
33265
  * @returns {Check}
32819
33266
  */
32820
- function(test) {
33267
+ (function(test) {
32821
33268
  if (test === null || test === void 0) {
32822
33269
  return ok2;
32823
33270
  }
@@ -32831,7 +33278,7 @@ var convert = (
32831
33278
  return typeFactory(test);
32832
33279
  }
32833
33280
  throw new Error("Expected function, string, or object as test");
32834
- }
33281
+ })
32835
33282
  );
32836
33283
  function anyFactory(tests) {
32837
33284
  const checks2 = [];
@@ -34011,7 +34458,7 @@ var CallableInstance = (
34011
34458
  * @param {string | symbol} property
34012
34459
  * @returns {(...parameters: Array<unknown>) => unknown}
34013
34460
  */
34014
- function(property) {
34461
+ (function(property) {
34015
34462
  const self2 = this;
34016
34463
  const constr = self2.constructor;
34017
34464
  const proto = (
@@ -34026,7 +34473,7 @@ var CallableInstance = (
34026
34473
  };
34027
34474
  Object.setPrototypeOf(apply, proto);
34028
34475
  return apply;
34029
- }
34476
+ })
34030
34477
  );
34031
34478
 
34032
34479
  // node_modules/unified/lib/index.js
@@ -37964,6 +38411,659 @@ var PhoneOffIcon = ({ width = 24, height = 24, className, ...props }) => {
37964
38411
  };
37965
38412
  var phone_off_default = PhoneOffIcon;
37966
38413
 
38414
+ // src/components/svgs/mic-off.tsx
38415
+ var import_react9 = __toESM(require("react"));
38416
+ var MicOffIcon = ({ style, className }) => {
38417
+ return /* @__PURE__ */ import_react9.default.createElement(
38418
+ "svg",
38419
+ {
38420
+ xmlns: "http://www.w3.org/2000/svg",
38421
+ width: "24",
38422
+ height: "24",
38423
+ viewBox: "0 0 24 24",
38424
+ fill: "none",
38425
+ stroke: "currentColor",
38426
+ strokeWidth: "2",
38427
+ strokeLinecap: "round",
38428
+ strokeLinejoin: "round",
38429
+ className: `lucide lucide-mic-off-icon lucide-mic-off ${className || ""}`,
38430
+ style
38431
+ },
38432
+ /* @__PURE__ */ import_react9.default.createElement("path", { d: "M12 19v3" }),
38433
+ /* @__PURE__ */ import_react9.default.createElement("path", { d: "M15 9.34V5a3 3 0 0 0-5.68-1.33" }),
38434
+ /* @__PURE__ */ import_react9.default.createElement("path", { d: "M16.95 16.95A7 7 0 0 1 5 12v-2" }),
38435
+ /* @__PURE__ */ import_react9.default.createElement("path", { d: "M18.89 13.23A7 7 0 0 0 19 12v-2" }),
38436
+ /* @__PURE__ */ import_react9.default.createElement("path", { d: "m2 2 20 20" }),
38437
+ /* @__PURE__ */ import_react9.default.createElement("path", { d: "M9 9v3a3 3 0 0 0 5.12 2.12" })
38438
+ );
38439
+ };
38440
+ var mic_off_default = MicOffIcon;
38441
+
38442
+ // src/components/svgs/mic.tsx
38443
+ var import_react10 = __toESM(require("react"));
38444
+ var MicIcon = ({ width = 24, height = 24, className, ...props }) => {
38445
+ return /* @__PURE__ */ import_react10.default.createElement(
38446
+ "svg",
38447
+ {
38448
+ xmlns: "http://www.w3.org/2000/svg",
38449
+ width,
38450
+ height,
38451
+ viewBox: "0 0 24 24",
38452
+ fill: "none",
38453
+ stroke: "currentColor",
38454
+ strokeWidth: "2",
38455
+ strokeLinecap: "round",
38456
+ strokeLinejoin: "round",
38457
+ className,
38458
+ ...props
38459
+ },
38460
+ /* @__PURE__ */ import_react10.default.createElement("path", { d: "M12 19v3" }),
38461
+ /* @__PURE__ */ import_react10.default.createElement("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
38462
+ /* @__PURE__ */ import_react10.default.createElement("rect", { x: "9", y: "2", width: "6", height: "13", rx: "3" })
38463
+ );
38464
+ };
38465
+ var mic_default = MicIcon;
38466
+
38467
+ // src/components/draggable-resizable-container.tsx
38468
+ var import_react13 = __toESM(require("react"));
38469
+
38470
+ // src/utils/draggable-resizable.ts
38471
+ var import_react11 = require("react");
38472
+ var absoluteToRelative = (position3, size, viewportWidth, viewportHeight) => {
38473
+ return {
38474
+ position: {
38475
+ xPercent: position3.x / viewportWidth * 100,
38476
+ yPercent: position3.y / viewportHeight * 100
38477
+ },
38478
+ size: {
38479
+ widthPercent: size.width / viewportWidth * 100,
38480
+ heightPercent: size.height / viewportHeight * 100
38481
+ }
38482
+ };
38483
+ };
38484
+ var relativeToAbsolute = (relativePosition, relativeSize, viewportWidth, viewportHeight) => {
38485
+ return {
38486
+ position: {
38487
+ x: relativePosition.xPercent / 100 * viewportWidth,
38488
+ y: relativePosition.yPercent / 100 * viewportHeight
38489
+ },
38490
+ size: {
38491
+ width: relativeSize.widthPercent / 100 * viewportWidth,
38492
+ height: relativeSize.heightPercent / 100 * viewportHeight
38493
+ }
38494
+ };
38495
+ };
38496
+ var DEFAULT_BOUNDS = {
38497
+ minWidth: 300,
38498
+ minHeight: 200,
38499
+ maxWidth: typeof window !== "undefined" ? Math.min(window.innerWidth * 0.92, 800) : 800,
38500
+ maxHeight: typeof window !== "undefined" ? Math.min(window.innerHeight * 0.9, 600) : 600
38501
+ };
38502
+ var DEFAULT_POSITION = { x: 0, y: 0 };
38503
+ var DEFAULT_SIZE = {
38504
+ width: 420,
38505
+ height: typeof window !== "undefined" ? Math.min(window.innerHeight * 0.55, 500) : 400
38506
+ };
38507
+ function useDraggableResizable(options = {}) {
38508
+ const {
38509
+ bounds = DEFAULT_BOUNDS,
38510
+ initialPosition = DEFAULT_POSITION,
38511
+ initialSize = DEFAULT_SIZE,
38512
+ onPositionChange,
38513
+ onSizeChange,
38514
+ disabled = false,
38515
+ dragHandle
38516
+ } = options;
38517
+ const [position3, setPositionState] = (0, import_react11.useState)(initialPosition);
38518
+ const [size, setSizeState] = (0, import_react11.useState)(initialSize);
38519
+ const [dragState, setDragState] = (0, import_react11.useState)({
38520
+ isDragging: false,
38521
+ startPosition: { x: 0, y: 0 },
38522
+ startMousePosition: { x: 0, y: 0 }
38523
+ });
38524
+ const [resizeState, setResizeState] = (0, import_react11.useState)({
38525
+ isResizing: false,
38526
+ direction: "se",
38527
+ startSize: { width: 0, height: 0 },
38528
+ startPosition: { x: 0, y: 0 },
38529
+ startMousePosition: { x: 0, y: 0 }
38530
+ });
38531
+ const containerRef = (0, import_react11.useRef)(null);
38532
+ const constrainPosition = (0, import_react11.useCallback)((pos, size2) => {
38533
+ const maxX = window.innerWidth - size2.width;
38534
+ const maxY = window.innerHeight - size2.height;
38535
+ return {
38536
+ x: Math.max(0, Math.min(pos.x, maxX)),
38537
+ y: Math.max(0, Math.min(pos.y, maxY))
38538
+ };
38539
+ }, []);
38540
+ const constrainSize = (0, import_react11.useCallback)(
38541
+ (newSize) => {
38542
+ return {
38543
+ width: Math.max(bounds.minWidth, Math.min(newSize.width, bounds.maxWidth || Infinity)),
38544
+ height: Math.max(bounds.minHeight, Math.min(newSize.height, bounds.maxHeight || Infinity))
38545
+ };
38546
+ },
38547
+ [bounds]
38548
+ );
38549
+ const setPosition = (0, import_react11.useCallback)(
38550
+ (newPosition) => {
38551
+ const constrainedPosition = constrainPosition(newPosition, size);
38552
+ setPositionState(constrainedPosition);
38553
+ onPositionChange?.(constrainedPosition);
38554
+ },
38555
+ [size, constrainPosition, onPositionChange]
38556
+ );
38557
+ const setSize = (0, import_react11.useCallback)(
38558
+ (newSize) => {
38559
+ const constrainedSize = constrainSize(newSize);
38560
+ setSizeState(constrainedSize);
38561
+ onSizeChange?.(constrainedSize);
38562
+ const constrainedPosition = constrainPosition(position3, constrainedSize);
38563
+ if (constrainedPosition.x !== position3.x || constrainedPosition.y !== position3.y) {
38564
+ setPositionState(constrainedPosition);
38565
+ onPositionChange?.(constrainedPosition);
38566
+ }
38567
+ },
38568
+ [position3, constrainSize, constrainPosition, onSizeChange, onPositionChange]
38569
+ );
38570
+ const resetToInitial = (0, import_react11.useCallback)(() => {
38571
+ setPositionState(initialPosition);
38572
+ setSizeState(initialSize);
38573
+ onPositionChange?.(initialPosition);
38574
+ onSizeChange?.(initialSize);
38575
+ }, [initialPosition, initialSize, onPositionChange, onSizeChange]);
38576
+ const handleDragStart = (0, import_react11.useCallback)(
38577
+ (e3) => {
38578
+ if (disabled) return;
38579
+ if (dragHandle) {
38580
+ const target = e3.target;
38581
+ if (!target.closest(dragHandle)) return;
38582
+ }
38583
+ e3.preventDefault();
38584
+ e3.stopPropagation();
38585
+ setDragState({
38586
+ isDragging: true,
38587
+ startPosition: { ...position3 },
38588
+ startMousePosition: { x: e3.clientX, y: e3.clientY }
38589
+ });
38590
+ },
38591
+ [disabled, dragHandle, position3]
38592
+ );
38593
+ const handleResizeStart = (0, import_react11.useCallback)(
38594
+ (direction) => (e3) => {
38595
+ if (disabled) return;
38596
+ e3.preventDefault();
38597
+ e3.stopPropagation();
38598
+ setResizeState({
38599
+ isResizing: true,
38600
+ direction,
38601
+ startSize: { ...size },
38602
+ startPosition: { ...position3 },
38603
+ startMousePosition: { x: e3.clientX, y: e3.clientY }
38604
+ });
38605
+ },
38606
+ [disabled, size, position3]
38607
+ );
38608
+ (0, import_react11.useEffect)(() => {
38609
+ const handleMouseMove = (e3) => {
38610
+ if (dragState.isDragging) {
38611
+ const deltaX = e3.clientX - dragState.startMousePosition.x;
38612
+ const deltaY = e3.clientY - dragState.startMousePosition.y;
38613
+ const newPosition = {
38614
+ x: dragState.startPosition.x + deltaX,
38615
+ y: dragState.startPosition.y + deltaY
38616
+ };
38617
+ setPosition(newPosition);
38618
+ } else if (resizeState.isResizing) {
38619
+ const deltaX = e3.clientX - resizeState.startMousePosition.x;
38620
+ const deltaY = e3.clientY - resizeState.startMousePosition.y;
38621
+ let newSize = { ...resizeState.startSize };
38622
+ let newPosition = { ...resizeState.startPosition };
38623
+ const { direction } = resizeState;
38624
+ if (direction.includes("e")) {
38625
+ newSize.width = resizeState.startSize.width + deltaX;
38626
+ }
38627
+ if (direction.includes("w")) {
38628
+ newSize.width = resizeState.startSize.width - deltaX;
38629
+ newPosition.x = resizeState.startPosition.x + deltaX;
38630
+ }
38631
+ if (direction.includes("s")) {
38632
+ newSize.height = resizeState.startSize.height + deltaY;
38633
+ }
38634
+ if (direction.includes("n")) {
38635
+ newSize.height = resizeState.startSize.height - deltaY;
38636
+ newPosition.y = resizeState.startPosition.y + deltaY;
38637
+ }
38638
+ setSize(newSize);
38639
+ if (newPosition.x !== resizeState.startPosition.x || newPosition.y !== resizeState.startPosition.y) {
38640
+ setPosition(newPosition);
38641
+ }
38642
+ }
38643
+ };
38644
+ const handleMouseUp = () => {
38645
+ setDragState((prev) => ({ ...prev, isDragging: false }));
38646
+ setResizeState((prev) => ({ ...prev, isResizing: false }));
38647
+ };
38648
+ if (dragState.isDragging || resizeState.isResizing) {
38649
+ document.addEventListener("mousemove", handleMouseMove);
38650
+ document.addEventListener("mouseup", handleMouseUp);
38651
+ }
38652
+ return () => {
38653
+ document.removeEventListener("mousemove", handleMouseMove);
38654
+ document.removeEventListener("mouseup", handleMouseUp);
38655
+ };
38656
+ }, [dragState, resizeState, setPosition, setSize]);
38657
+ const resizeHandlers = {
38658
+ n: { onMouseDown: handleResizeStart("n") },
38659
+ s: { onMouseDown: handleResizeStart("s") },
38660
+ e: { onMouseDown: handleResizeStart("e") },
38661
+ w: { onMouseDown: handleResizeStart("w") },
38662
+ ne: { onMouseDown: handleResizeStart("ne") },
38663
+ nw: { onMouseDown: handleResizeStart("nw") },
38664
+ se: { onMouseDown: handleResizeStart("se") },
38665
+ sw: { onMouseDown: handleResizeStart("sw") }
38666
+ };
38667
+ return {
38668
+ position: position3,
38669
+ size,
38670
+ isDragging: dragState.isDragging,
38671
+ isResizing: resizeState.isResizing,
38672
+ dragHandlers: {
38673
+ onMouseDown: handleDragStart
38674
+ },
38675
+ resizeHandlers,
38676
+ setPosition,
38677
+ setSize,
38678
+ resetToInitial
38679
+ };
38680
+ }
38681
+ function getResizeCursor(direction) {
38682
+ const cursorMap = {
38683
+ n: "n-resize",
38684
+ s: "s-resize",
38685
+ e: "e-resize",
38686
+ w: "w-resize",
38687
+ ne: "ne-resize",
38688
+ nw: "nw-resize",
38689
+ se: "se-resize",
38690
+ sw: "sw-resize"
38691
+ };
38692
+ return cursorMap[direction];
38693
+ }
38694
+
38695
+ // src/components/resize-handle.tsx
38696
+ var import_react12 = __toESM(require("react"));
38697
+ var ResizeHandle = ({
38698
+ direction,
38699
+ onMouseDown,
38700
+ disabled = false,
38701
+ className = "",
38702
+ style = {},
38703
+ size = 8
38704
+ }) => {
38705
+ const getHandleStyle = () => {
38706
+ const baseStyle = {
38707
+ position: "absolute",
38708
+ backgroundColor: "transparent",
38709
+ cursor: disabled ? "default" : getResizeCursor(direction),
38710
+ zIndex: 1e3,
38711
+ userSelect: "none",
38712
+ ...style
38713
+ };
38714
+ switch (direction) {
38715
+ case "n":
38716
+ return {
38717
+ ...baseStyle,
38718
+ top: -size / 2,
38719
+ left: 0,
38720
+ right: 0,
38721
+ height: size
38722
+ };
38723
+ case "s":
38724
+ return {
38725
+ ...baseStyle,
38726
+ bottom: -size / 2,
38727
+ left: 0,
38728
+ right: 0,
38729
+ height: size
38730
+ };
38731
+ case "e":
38732
+ return {
38733
+ ...baseStyle,
38734
+ top: 0,
38735
+ bottom: 0,
38736
+ right: -size / 2,
38737
+ width: size
38738
+ };
38739
+ case "w":
38740
+ return {
38741
+ ...baseStyle,
38742
+ top: 0,
38743
+ bottom: 0,
38744
+ left: -size / 2,
38745
+ width: size
38746
+ };
38747
+ case "ne":
38748
+ return {
38749
+ ...baseStyle,
38750
+ top: -size / 2,
38751
+ right: -size / 2,
38752
+ width: size,
38753
+ height: size
38754
+ };
38755
+ case "nw":
38756
+ return {
38757
+ ...baseStyle,
38758
+ top: -size / 2,
38759
+ left: -size / 2,
38760
+ width: size,
38761
+ height: size
38762
+ };
38763
+ case "se":
38764
+ return {
38765
+ ...baseStyle,
38766
+ bottom: -size / 2,
38767
+ right: -size / 2,
38768
+ width: size,
38769
+ height: size
38770
+ };
38771
+ case "sw":
38772
+ return {
38773
+ ...baseStyle,
38774
+ bottom: -size / 2,
38775
+ left: -size / 2,
38776
+ width: size,
38777
+ height: size
38778
+ };
38779
+ default:
38780
+ return baseStyle;
38781
+ }
38782
+ };
38783
+ const handleMouseDown = (e3) => {
38784
+ if (!disabled) {
38785
+ onMouseDown(e3);
38786
+ }
38787
+ };
38788
+ return /* @__PURE__ */ import_react12.default.createElement(
38789
+ "div",
38790
+ {
38791
+ className: `resize-handle resize-handle-${direction} ${className}`,
38792
+ style: getHandleStyle(),
38793
+ onMouseDown: handleMouseDown,
38794
+ "data-direction": direction,
38795
+ "aria-label": `Resize ${direction}`
38796
+ }
38797
+ );
38798
+ };
38799
+ var ResizeHandles = ({
38800
+ onResizeStart,
38801
+ disabled = false,
38802
+ className = "",
38803
+ style = {},
38804
+ size = 8,
38805
+ showHandles = ["n", "s", "e", "w", "ne", "nw", "se", "sw"]
38806
+ }) => {
38807
+ return /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, null, showHandles.map((direction) => /* @__PURE__ */ import_react12.default.createElement(
38808
+ ResizeHandle,
38809
+ {
38810
+ key: direction,
38811
+ direction,
38812
+ onMouseDown: onResizeStart(direction),
38813
+ disabled,
38814
+ className,
38815
+ style,
38816
+ size
38817
+ }
38818
+ )));
38819
+ };
38820
+
38821
+ // src/components/draggable-resizable-container.tsx
38822
+ var DraggableResizableContainer = ({
38823
+ children,
38824
+ className = "",
38825
+ style = {},
38826
+ dragHandle,
38827
+ showResizeHandles = true,
38828
+ resizeHandleSize = 8,
38829
+ onPositionChange,
38830
+ onSizeChange,
38831
+ onDragStart,
38832
+ onDragEnd,
38833
+ onResizeStart,
38834
+ onResizeEnd,
38835
+ storageKey,
38836
+ persistPosition = false,
38837
+ persistSize = false,
38838
+ ...options
38839
+ }) => {
38840
+ const containerRef = (0, import_react13.useRef)(null);
38841
+ const loadPersistedData = () => {
38842
+ if (!storageKey || typeof window === "undefined") return {};
38843
+ try {
38844
+ const data = localStorage.getItem(`cuekit-${storageKey}`);
38845
+ if (data) {
38846
+ const parsed = JSON.parse(data);
38847
+ if (parsed.relativePosition && parsed.relativeSize) {
38848
+ const viewportWidth = window.innerWidth;
38849
+ const viewportHeight = window.innerHeight;
38850
+ const { position: position4, size: size2 } = relativeToAbsolute(
38851
+ parsed.relativePosition,
38852
+ parsed.relativeSize,
38853
+ viewportWidth,
38854
+ viewportHeight
38855
+ );
38856
+ return { position: position4, size: size2 };
38857
+ }
38858
+ return {
38859
+ position: parsed.position,
38860
+ size: parsed.size
38861
+ };
38862
+ }
38863
+ } catch (error) {
38864
+ console.warn("Failed to load persisted position/size:", error);
38865
+ }
38866
+ return {};
38867
+ };
38868
+ const savePersistedData = (position4, size2) => {
38869
+ if (!storageKey || typeof window === "undefined") return;
38870
+ try {
38871
+ const viewportWidth = window.innerWidth;
38872
+ const viewportHeight = window.innerHeight;
38873
+ const { position: relativePosition, size: relativeSize } = absoluteToRelative(
38874
+ position4,
38875
+ size2,
38876
+ viewportWidth,
38877
+ viewportHeight
38878
+ );
38879
+ const data = {};
38880
+ if (persistPosition) {
38881
+ data.position = position4;
38882
+ data.relativePosition = relativePosition;
38883
+ }
38884
+ if (persistSize) {
38885
+ data.size = size2;
38886
+ data.relativeSize = relativeSize;
38887
+ }
38888
+ localStorage.setItem(`cuekit-${storageKey}`, JSON.stringify(data));
38889
+ } catch (error) {
38890
+ console.warn("Failed to save persisted position/size:", error);
38891
+ }
38892
+ };
38893
+ const persistedData = loadPersistedData();
38894
+ const initialPosition = persistedData.position || options.initialPosition;
38895
+ const initialSize = persistedData.size || options.initialSize;
38896
+ (0, import_react13.useEffect)(() => {
38897
+ const handleResize = () => {
38898
+ if (!storageKey || typeof window === "undefined") return;
38899
+ try {
38900
+ const data = localStorage.getItem(`cuekit-${storageKey}`);
38901
+ if (data) {
38902
+ const parsed = JSON.parse(data);
38903
+ if (parsed.relativePosition && parsed.relativeSize) {
38904
+ const viewportWidth = window.innerWidth;
38905
+ const viewportHeight = window.innerHeight;
38906
+ const { position: position4, size: size2 } = relativeToAbsolute(
38907
+ parsed.relativePosition,
38908
+ parsed.relativeSize,
38909
+ viewportWidth,
38910
+ viewportHeight
38911
+ );
38912
+ if (containerRef.current) {
38913
+ containerRef.current.style.left = `${position4.x}px`;
38914
+ containerRef.current.style.top = `${position4.y}px`;
38915
+ containerRef.current.style.width = `${size2.width}px`;
38916
+ containerRef.current.style.height = `${size2.height}px`;
38917
+ }
38918
+ }
38919
+ }
38920
+ } catch (error) {
38921
+ console.warn("Failed to update position on resize:", error);
38922
+ }
38923
+ };
38924
+ window.addEventListener("resize", handleResize);
38925
+ return () => window.removeEventListener("resize", handleResize);
38926
+ }, [storageKey]);
38927
+ const {
38928
+ position: position3,
38929
+ size,
38930
+ isDragging,
38931
+ isResizing,
38932
+ dragHandlers,
38933
+ resizeHandlers,
38934
+ setPosition,
38935
+ setSize
38936
+ } = useDraggableResizable({
38937
+ ...options,
38938
+ initialPosition,
38939
+ initialSize,
38940
+ onPositionChange: (pos) => {
38941
+ onPositionChange?.(pos);
38942
+ if (persistPosition || persistSize) {
38943
+ savePersistedData(pos, size);
38944
+ }
38945
+ },
38946
+ onSizeChange: (newSize) => {
38947
+ onSizeChange?.(newSize);
38948
+ if (persistPosition || persistSize) {
38949
+ savePersistedData(position3, newSize);
38950
+ }
38951
+ }
38952
+ });
38953
+ const handleDragStart = (e3) => {
38954
+ dragHandlers.onMouseDown(e3);
38955
+ onDragStart?.();
38956
+ };
38957
+ const handleResizeStart = (direction) => (e3) => {
38958
+ resizeHandlers[direction].onMouseDown(e3);
38959
+ onResizeStart?.();
38960
+ };
38961
+ (0, import_react13.useEffect)(() => {
38962
+ if (!isDragging) {
38963
+ onDragEnd?.();
38964
+ }
38965
+ }, [isDragging, onDragEnd]);
38966
+ (0, import_react13.useEffect)(() => {
38967
+ if (!isResizing) {
38968
+ onResizeEnd?.();
38969
+ }
38970
+ }, [isResizing, onResizeEnd]);
38971
+ const containerStyle = {
38972
+ position: "fixed",
38973
+ left: position3.x,
38974
+ top: position3.y,
38975
+ width: size.width,
38976
+ height: size.height,
38977
+ transform: "none",
38978
+ // We use left/top instead of transform for better performance
38979
+ zIndex: 1e3,
38980
+ ...style
38981
+ };
38982
+ const containerClassName = [
38983
+ "draggable-resizable-container",
38984
+ isDragging ? "is-dragging" : "",
38985
+ isResizing ? "is-resizing" : "",
38986
+ className
38987
+ ].filter(Boolean).join(" ");
38988
+ return /* @__PURE__ */ import_react13.default.createElement(
38989
+ "div",
38990
+ {
38991
+ ref: containerRef,
38992
+ className: containerClassName,
38993
+ style: containerStyle,
38994
+ "data-cuekit-ignore": true
38995
+ },
38996
+ /* @__PURE__ */ import_react13.default.createElement(
38997
+ "div",
38998
+ {
38999
+ className: "drag-handle",
39000
+ style: {
39001
+ position: "absolute",
39002
+ top: 0,
39003
+ left: 0,
39004
+ right: 0,
39005
+ height: "20px",
39006
+ // Height of the header area
39007
+ cursor: "move",
39008
+ zIndex: 10
39009
+ },
39010
+ onMouseDown: handleDragStart,
39011
+ "data-drag-handle": "true"
39012
+ }
39013
+ ),
39014
+ /* @__PURE__ */ import_react13.default.createElement(
39015
+ "div",
39016
+ {
39017
+ className: "draggable-content",
39018
+ style: {
39019
+ width: "100%",
39020
+ height: "100%",
39021
+ overflow: "hidden",
39022
+ display: "flex",
39023
+ flexDirection: "column"
39024
+ }
39025
+ },
39026
+ children
39027
+ ),
39028
+ showResizeHandles && /* @__PURE__ */ import_react13.default.createElement(
39029
+ ResizeHandles,
39030
+ {
39031
+ onResizeStart: handleResizeStart,
39032
+ disabled: options.disabled,
39033
+ size: resizeHandleSize
39034
+ }
39035
+ )
39036
+ );
39037
+ };
39038
+ var useDraggableResizableContainer = (storageKey) => {
39039
+ const loadData = () => {
39040
+ if (!storageKey || typeof window === "undefined") return null;
39041
+ try {
39042
+ const data = localStorage.getItem(`cuekit-${storageKey}`);
39043
+ return data ? JSON.parse(data) : null;
39044
+ } catch {
39045
+ return null;
39046
+ }
39047
+ };
39048
+ const saveData = (data) => {
39049
+ if (!storageKey || typeof window === "undefined") return;
39050
+ try {
39051
+ localStorage.setItem(`cuekit-${storageKey}`, JSON.stringify(data));
39052
+ } catch (error) {
39053
+ console.warn("Failed to save data:", error);
39054
+ }
39055
+ };
39056
+ const clearData = () => {
39057
+ if (!storageKey || typeof window === "undefined") return;
39058
+ try {
39059
+ localStorage.removeItem(`cuekit-${storageKey}`);
39060
+ } catch (error) {
39061
+ console.warn("Failed to clear data:", error);
39062
+ }
39063
+ };
39064
+ return { loadData, saveData, clearData };
39065
+ };
39066
+
37967
39067
  // src/components/chat-popup.tsx
37968
39068
  var ChatPopup = ({
37969
39069
  isOpen,
@@ -37980,15 +39080,28 @@ var ChatPopup = ({
37980
39080
  currentTheme = "dark",
37981
39081
  onThemeToggle,
37982
39082
  status,
37983
- anchor
39083
+ anchor,
39084
+ muteState,
39085
+ onToggleMute,
39086
+ // Draggable/Resizable props
39087
+ draggable = true,
39088
+ resizable = true,
39089
+ initialPosition,
39090
+ initialSize,
39091
+ onPositionChange,
39092
+ onSizeChange,
39093
+ persistPosition = true,
39094
+ persistSize = true,
39095
+ storageKey = "chat-popup"
37984
39096
  }) => {
37985
- const [inputText, setInputText] = (0, import_react9.useState)("");
37986
- const [isSending, setIsSending] = (0, import_react9.useState)(false);
37987
- const messagesEndRef = (0, import_react9.useRef)(null);
39097
+ const { title, showLogo, showAIIcon, showUserIcon } = useAnsyrContext();
39098
+ const [inputText, setInputText] = (0, import_react14.useState)("");
39099
+ const [isSending, setIsSending] = (0, import_react14.useState)(false);
39100
+ const messagesEndRef = (0, import_react14.useRef)(null);
37988
39101
  const scrollToBottom = () => {
37989
39102
  messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
37990
39103
  };
37991
- (0, import_react9.useEffect)(() => {
39104
+ (0, import_react14.useEffect)(() => {
37992
39105
  console.log("\u{1F4EC} ChatPopup received messages:", JSON.stringify(messages, null, 2));
37993
39106
  scrollToBottom();
37994
39107
  }, [messages]);
@@ -38010,7 +39123,6 @@ var ChatPopup = ({
38010
39123
  handleSend();
38011
39124
  }
38012
39125
  };
38013
- if (!isOpen || isMinimized) return null;
38014
39126
  const getStatusText = () => {
38015
39127
  if (status) return status;
38016
39128
  if (micState === "listening") return "Listening...";
@@ -38018,48 +39130,57 @@ var ChatPopup = ({
38018
39130
  if (micState === "replying") return "Responding...";
38019
39131
  return "Listening...";
38020
39132
  };
38021
- const getPositionStyle = () => {
39133
+ const getInitialPosition = () => {
39134
+ if (initialPosition) return initialPosition;
38022
39135
  if (!anchor) {
38023
39136
  return {
38024
- bottom: "100px",
38025
- right: "20px"
39137
+ x: window.innerWidth - 420 - 20,
39138
+ y: window.innerHeight - window.innerHeight * 0.55 - 20
38026
39139
  };
38027
39140
  }
38028
39141
  const bottomOffset = anchor.bottom + anchor.size + 16;
38029
- const baseStyle = {
38030
- bottom: `${bottomOffset}px`
38031
- };
39142
+ const popupHeight = window.innerHeight * 0.55;
39143
+ const y = window.innerHeight - bottomOffset - popupHeight;
38032
39144
  switch (anchor.position) {
38033
39145
  case "bottom-center":
38034
- return {
38035
- ...baseStyle,
38036
- left: "50%",
38037
- transform: "translateX(-50%)"
38038
- };
39146
+ return { x: (window.innerWidth - 420) / 2, y };
38039
39147
  case "bottom-left":
38040
- return {
38041
- ...baseStyle,
38042
- left: "20px"
38043
- };
39148
+ return { x: 20, y };
38044
39149
  case "bottom-right":
38045
39150
  default:
38046
- return {
38047
- ...baseStyle,
38048
- right: "20px"
38049
- };
39151
+ return { x: window.innerWidth - 420 - 20, y };
38050
39152
  }
38051
39153
  };
38052
- const positionStyle = getPositionStyle();
38053
- return /* @__PURE__ */ import_react9.default.createElement(
38054
- "div",
39154
+ const getInitialSize = () => {
39155
+ if (initialSize) return initialSize;
39156
+ return {
39157
+ width: 420,
39158
+ height: window.innerHeight * 0.55
39159
+ };
39160
+ };
39161
+ if (!isOpen || isMinimized) return null;
39162
+ return /* @__PURE__ */ import_react14.default.createElement(
39163
+ DraggableResizableContainer,
38055
39164
  {
38056
- "data-cuekit-ignore": true,
39165
+ initialPosition: getInitialPosition(),
39166
+ initialSize: getInitialSize(),
39167
+ onPositionChange,
39168
+ onSizeChange,
39169
+ persistPosition,
39170
+ persistSize,
39171
+ storageKey,
39172
+ disabled: !draggable && !resizable,
39173
+ showResizeHandles: resizable,
39174
+ bounds: {
39175
+ minWidth: 300,
39176
+ minHeight: 200,
39177
+ maxWidth: Math.min(window.innerWidth * 0.92, 800),
39178
+ // Cap at 800px max width
39179
+ maxHeight: Math.min(window.innerHeight * 0.9, 600)
39180
+ // Cap at 600px max height
39181
+ },
38057
39182
  className: `cuekit-voice-popup ${currentTheme === "dark" ? "cuekit-dark" : ""}`,
38058
39183
  style: {
38059
- position: "fixed",
38060
- width: "420px",
38061
- maxWidth: "92vw",
38062
- height: "55vh",
38063
39184
  borderRadius: "10px",
38064
39185
  background: "hsl(var(--voice-bg))",
38065
39186
  boxShadow: "var(--shadow-card)",
@@ -38067,13 +39188,11 @@ var ChatPopup = ({
38067
39188
  display: "flex",
38068
39189
  animation: "scaleIn 0.3s ease-out",
38069
39190
  flexDirection: "column",
38070
- zIndex: 1e3,
38071
39191
  fontFamily: "Inter, system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif",
38072
- overflow: "hidden",
38073
- ...positionStyle
39192
+ overflow: "hidden"
38074
39193
  }
38075
39194
  },
38076
- /* @__PURE__ */ import_react9.default.createElement(
39195
+ /* @__PURE__ */ import_react14.default.createElement(
38077
39196
  "div",
38078
39197
  {
38079
39198
  style: {
@@ -38084,14 +39203,14 @@ var ChatPopup = ({
38084
39203
  justifyContent: "space-between"
38085
39204
  }
38086
39205
  },
38087
- /* @__PURE__ */ import_react9.default.createElement("div", { style: { display: "flex", alignItems: "center", gap: 0 } }, /* @__PURE__ */ import_react9.default.createElement(
39206
+ /* @__PURE__ */ import_react14.default.createElement("div", { style: { display: "flex", alignItems: "center", gap: 0 } }, showLogo && /* @__PURE__ */ import_react14.default.createElement(
38088
39207
  "img",
38089
39208
  {
38090
39209
  src: "https://dashboard.cuekit.ai/_next/image?url=%2Fimages%2Fcuekit-logo-2.png&w=256&q=100",
38091
39210
  alt: "Cuekit AI",
38092
39211
  style: { width: 58, objectFit: "cover" }
38093
39212
  }
38094
- ), /* @__PURE__ */ import_react9.default.createElement(
39213
+ ), /* @__PURE__ */ import_react14.default.createElement(
38095
39214
  "div",
38096
39215
  {
38097
39216
  style: {
@@ -38102,10 +39221,11 @@ var ChatPopup = ({
38102
39221
  justifyContent: "center"
38103
39222
  }
38104
39223
  },
38105
- /* @__PURE__ */ import_react9.default.createElement(
39224
+ /* @__PURE__ */ import_react14.default.createElement(
38106
39225
  "span",
38107
39226
  {
38108
39227
  style: {
39228
+ paddingLeft: showLogo ? 0 : 12,
38109
39229
  fontSize: 18,
38110
39230
  fontWeight: 700,
38111
39231
  lineHeight: "1.2",
@@ -38117,9 +39237,9 @@ var ChatPopup = ({
38117
39237
  WebkitTextFillColor: "transparent"
38118
39238
  }
38119
39239
  },
38120
- "Cuekit.ai"
39240
+ title
38121
39241
  ),
38122
- /* @__PURE__ */ import_react9.default.createElement("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 4 } }, /* @__PURE__ */ import_react9.default.createElement(
39242
+ /* @__PURE__ */ import_react14.default.createElement("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 4 } }, /* @__PURE__ */ import_react14.default.createElement(
38123
39243
  "div",
38124
39244
  {
38125
39245
  style: {
@@ -38135,7 +39255,7 @@ var ChatPopup = ({
38135
39255
  fontWeight: "500"
38136
39256
  }
38137
39257
  },
38138
- /* @__PURE__ */ import_react9.default.createElement(
39258
+ /* @__PURE__ */ import_react14.default.createElement(
38139
39259
  "span",
38140
39260
  {
38141
39261
  style: {
@@ -38146,8 +39266,8 @@ var ChatPopup = ({
38146
39266
  )
38147
39267
  ))
38148
39268
  )),
38149
- /* @__PURE__ */ import_react9.default.createElement("div", { style: { minWidth: 100, textAlign: "center" } }),
38150
- /* @__PURE__ */ import_react9.default.createElement(
39269
+ /* @__PURE__ */ import_react14.default.createElement("div", { style: { minWidth: 100, textAlign: "center" } }),
39270
+ /* @__PURE__ */ import_react14.default.createElement(
38151
39271
  "div",
38152
39272
  {
38153
39273
  style: {
@@ -38159,7 +39279,7 @@ var ChatPopup = ({
38159
39279
  top: 16
38160
39280
  }
38161
39281
  },
38162
- onThemeToggle && /* @__PURE__ */ import_react9.default.createElement(
39282
+ onThemeToggle && /* @__PURE__ */ import_react14.default.createElement(
38163
39283
  "button",
38164
39284
  {
38165
39285
  onClick: () => {
@@ -38189,7 +39309,7 @@ var ChatPopup = ({
38189
39309
  "aria-label": "Toggle theme",
38190
39310
  title: `Switch to ${currentTheme === "dark" ? "light" : "dark"} mode`
38191
39311
  },
38192
- currentTheme === "dark" ? /* @__PURE__ */ import_react9.default.createElement(
39312
+ currentTheme === "dark" ? /* @__PURE__ */ import_react14.default.createElement(
38193
39313
  sun_default,
38194
39314
  {
38195
39315
  style: {
@@ -38199,7 +39319,7 @@ var ChatPopup = ({
38199
39319
  animation: "themeToggleEnter 0.3s ease-in-out"
38200
39320
  }
38201
39321
  }
38202
- ) : /* @__PURE__ */ import_react9.default.createElement(
39322
+ ) : /* @__PURE__ */ import_react14.default.createElement(
38203
39323
  moon_default,
38204
39324
  {
38205
39325
  style: {
@@ -38211,7 +39331,7 @@ var ChatPopup = ({
38211
39331
  }
38212
39332
  )
38213
39333
  ),
38214
- /* @__PURE__ */ import_react9.default.createElement(
39334
+ /* @__PURE__ */ import_react14.default.createElement(
38215
39335
  "button",
38216
39336
  {
38217
39337
  onClick: onMinimize,
@@ -38238,11 +39358,11 @@ var ChatPopup = ({
38238
39358
  "aria-label": "Minimize",
38239
39359
  title: "Minimize chat"
38240
39360
  },
38241
- /* @__PURE__ */ import_react9.default.createElement(close_default, { style: { width: 16, height: 16, color: "hsl(var(--voice-text-muted))" } })
39361
+ /* @__PURE__ */ import_react14.default.createElement(close_default, { style: { width: 16, height: 16, color: "hsl(var(--voice-text-muted))" } })
38242
39362
  )
38243
39363
  )
38244
39364
  ),
38245
- /* @__PURE__ */ import_react9.default.createElement(
39365
+ /* @__PURE__ */ import_react14.default.createElement(
38246
39366
  "div",
38247
39367
  {
38248
39368
  style: {
@@ -38255,7 +39375,7 @@ var ChatPopup = ({
38255
39375
  color: "hsl(var(--voice-text))"
38256
39376
  }
38257
39377
  },
38258
- messages.length === 0 ? /* @__PURE__ */ import_react9.default.createElement(
39378
+ messages.length === 0 ? /* @__PURE__ */ import_react14.default.createElement(
38259
39379
  "div",
38260
39380
  {
38261
39381
  style: {
@@ -38265,7 +39385,7 @@ var ChatPopup = ({
38265
39385
  }
38266
39386
  },
38267
39387
  "Start a conversation with CueKit AI"
38268
- ) : messages.map((message, index2) => /* @__PURE__ */ import_react9.default.createElement(
39388
+ ) : messages.map((message, index2) => /* @__PURE__ */ import_react14.default.createElement(
38269
39389
  "div",
38270
39390
  {
38271
39391
  key: index2,
@@ -38279,7 +39399,7 @@ var ChatPopup = ({
38279
39399
  justifyContent: message.sender === "user" ? "flex-end" : "flex-start"
38280
39400
  }
38281
39401
  },
38282
- message.sender === "assistant" && /* @__PURE__ */ import_react9.default.createElement(
39402
+ message.sender === "assistant" && showAIIcon && /* @__PURE__ */ import_react14.default.createElement(
38283
39403
  "div",
38284
39404
  {
38285
39405
  style: {
@@ -38294,7 +39414,7 @@ var ChatPopup = ({
38294
39414
  overflow: "hidden"
38295
39415
  }
38296
39416
  },
38297
- /* @__PURE__ */ import_react9.default.createElement(
39417
+ /* @__PURE__ */ import_react14.default.createElement(
38298
39418
  "img",
38299
39419
  {
38300
39420
  src: "https://dashboard.cuekit.ai/_next/image?url=%2Fimages%2Fcuekit-logo-2.png&w=256&q=100",
@@ -38308,7 +39428,7 @@ var ChatPopup = ({
38308
39428
  }
38309
39429
  )
38310
39430
  ),
38311
- /* @__PURE__ */ import_react9.default.createElement(
39431
+ /* @__PURE__ */ import_react14.default.createElement(
38312
39432
  "div",
38313
39433
  {
38314
39434
  style: {
@@ -38319,7 +39439,7 @@ var ChatPopup = ({
38319
39439
  flex: 1
38320
39440
  }
38321
39441
  },
38322
- /* @__PURE__ */ import_react9.default.createElement(
39442
+ /* @__PURE__ */ import_react14.default.createElement(
38323
39443
  "div",
38324
39444
  {
38325
39445
  style: {
@@ -38337,12 +39457,12 @@ var ChatPopup = ({
38337
39457
  marginLeft: message.sender === "user" ? "auto" : 0
38338
39458
  }
38339
39459
  },
38340
- /* @__PURE__ */ import_react9.default.createElement("div", null, /* @__PURE__ */ import_react9.default.createElement(
39460
+ /* @__PURE__ */ import_react14.default.createElement("div", null, /* @__PURE__ */ import_react14.default.createElement(
38341
39461
  Markdown,
38342
39462
  {
38343
39463
  remarkPlugins: [remarkGfm],
38344
39464
  components: {
38345
- p: ({ children }) => /* @__PURE__ */ import_react9.default.createElement(
39465
+ p: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38346
39466
  "p",
38347
39467
  {
38348
39468
  style: {
@@ -38353,7 +39473,7 @@ var ChatPopup = ({
38353
39473
  },
38354
39474
  children
38355
39475
  ),
38356
- h1: ({ children }) => /* @__PURE__ */ import_react9.default.createElement(
39476
+ h1: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38357
39477
  "h1",
38358
39478
  {
38359
39479
  style: {
@@ -38365,7 +39485,7 @@ var ChatPopup = ({
38365
39485
  },
38366
39486
  children
38367
39487
  ),
38368
- h2: ({ children }) => /* @__PURE__ */ import_react9.default.createElement(
39488
+ h2: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38369
39489
  "h2",
38370
39490
  {
38371
39491
  style: {
@@ -38377,7 +39497,7 @@ var ChatPopup = ({
38377
39497
  },
38378
39498
  children
38379
39499
  ),
38380
- h3: ({ children }) => /* @__PURE__ */ import_react9.default.createElement(
39500
+ h3: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38381
39501
  "h3",
38382
39502
  {
38383
39503
  style: {
@@ -38389,7 +39509,7 @@ var ChatPopup = ({
38389
39509
  },
38390
39510
  children
38391
39511
  ),
38392
- ul: ({ children }) => /* @__PURE__ */ import_react9.default.createElement(
39512
+ ul: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38393
39513
  "ul",
38394
39514
  {
38395
39515
  style: {
@@ -38401,7 +39521,7 @@ var ChatPopup = ({
38401
39521
  },
38402
39522
  children
38403
39523
  ),
38404
- ol: ({ children }) => /* @__PURE__ */ import_react9.default.createElement(
39524
+ ol: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38405
39525
  "ol",
38406
39526
  {
38407
39527
  style: {
@@ -38413,7 +39533,7 @@ var ChatPopup = ({
38413
39533
  },
38414
39534
  children
38415
39535
  ),
38416
- li: ({ children }) => /* @__PURE__ */ import_react9.default.createElement(
39536
+ li: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38417
39537
  "li",
38418
39538
  {
38419
39539
  style: {
@@ -38424,7 +39544,7 @@ var ChatPopup = ({
38424
39544
  },
38425
39545
  children
38426
39546
  ),
38427
- strong: ({ children }) => /* @__PURE__ */ import_react9.default.createElement(
39547
+ strong: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38428
39548
  "strong",
38429
39549
  {
38430
39550
  style: {
@@ -38435,7 +39555,7 @@ var ChatPopup = ({
38435
39555
  },
38436
39556
  children
38437
39557
  ),
38438
- em: ({ children }) => /* @__PURE__ */ import_react9.default.createElement(
39558
+ em: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38439
39559
  "em",
38440
39560
  {
38441
39561
  style: {
@@ -38446,7 +39566,7 @@ var ChatPopup = ({
38446
39566
  },
38447
39567
  children
38448
39568
  ),
38449
- code: ({ children }) => /* @__PURE__ */ import_react9.default.createElement(
39569
+ code: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38450
39570
  "code",
38451
39571
  {
38452
39572
  style: {
@@ -38459,7 +39579,7 @@ var ChatPopup = ({
38459
39579
  },
38460
39580
  children
38461
39581
  ),
38462
- pre: ({ children }) => /* @__PURE__ */ import_react9.default.createElement(
39582
+ pre: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38463
39583
  "pre",
38464
39584
  {
38465
39585
  style: {
@@ -38474,7 +39594,7 @@ var ChatPopup = ({
38474
39594
  },
38475
39595
  children
38476
39596
  ),
38477
- blockquote: ({ children }) => /* @__PURE__ */ import_react9.default.createElement(
39597
+ blockquote: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38478
39598
  "blockquote",
38479
39599
  {
38480
39600
  style: {
@@ -38493,7 +39613,7 @@ var ChatPopup = ({
38493
39613
  message.text
38494
39614
  ))
38495
39615
  ),
38496
- message.sender === "user" && /* @__PURE__ */ import_react9.default.createElement(
39616
+ message.sender === "user" && showUserIcon && /* @__PURE__ */ import_react14.default.createElement(
38497
39617
  "div",
38498
39618
  {
38499
39619
  style: {
@@ -38514,9 +39634,9 @@ var ChatPopup = ({
38514
39634
  )
38515
39635
  )
38516
39636
  )),
38517
- /* @__PURE__ */ import_react9.default.createElement("div", { ref: messagesEndRef })
39637
+ /* @__PURE__ */ import_react14.default.createElement("div", { ref: messagesEndRef })
38518
39638
  ),
38519
- /* @__PURE__ */ import_react9.default.createElement(
39639
+ /* @__PURE__ */ import_react14.default.createElement(
38520
39640
  "div",
38521
39641
  {
38522
39642
  style: {
@@ -38525,7 +39645,7 @@ var ChatPopup = ({
38525
39645
  background: "hsl(var(--voice-bg))"
38526
39646
  }
38527
39647
  },
38528
- /* @__PURE__ */ import_react9.default.createElement(
39648
+ /* @__PURE__ */ import_react14.default.createElement(
38529
39649
  "form",
38530
39650
  {
38531
39651
  onSubmit: (e3) => {
@@ -38534,7 +39654,7 @@ var ChatPopup = ({
38534
39654
  },
38535
39655
  style: { display: "flex", alignItems: "center", gap: 8, margin: 0 }
38536
39656
  },
38537
- /* @__PURE__ */ import_react9.default.createElement(
39657
+ /* @__PURE__ */ import_react14.default.createElement(
38538
39658
  "input",
38539
39659
  {
38540
39660
  type: "text",
@@ -38561,7 +39681,47 @@ var ChatPopup = ({
38561
39681
  }
38562
39682
  }
38563
39683
  ),
38564
- isConnected2 && onEndCall && /* @__PURE__ */ import_react9.default.createElement(
39684
+ muteState?.canMute && onToggleMute && /* @__PURE__ */ import_react14.default.createElement(
39685
+ "button",
39686
+ {
39687
+ onClick: onToggleMute,
39688
+ style: {
39689
+ padding: "10px 12px",
39690
+ borderRadius: 8,
39691
+ border: "1px solid hsl(var(--voice-accent))",
39692
+ background: "hsl(var(--voice-accent))",
39693
+ fontSize: 12,
39694
+ fontWeight: 700,
39695
+ display: "flex",
39696
+ alignItems: "center",
39697
+ justifyContent: "center",
39698
+ cursor: "pointer",
39699
+ transition: "all 0.3s ease"
39700
+ },
39701
+ "aria-label": muteState.isMuted ? "Unmute microphone" : "Mute microphone",
39702
+ title: muteState.isMuted ? "Unmute microphone" : "Mute microphone"
39703
+ },
39704
+ muteState.isMuted ? /* @__PURE__ */ import_react14.default.createElement(
39705
+ mic_off_default,
39706
+ {
39707
+ style: {
39708
+ width: 16,
39709
+ height: 16,
39710
+ color: "hsl(var(--voice-user-text))"
39711
+ }
39712
+ }
39713
+ ) : /* @__PURE__ */ import_react14.default.createElement(
39714
+ mic_default,
39715
+ {
39716
+ style: {
39717
+ width: 16,
39718
+ height: 16,
39719
+ color: "hsl(var(--voice-user-text))"
39720
+ }
39721
+ }
39722
+ )
39723
+ ),
39724
+ isConnected2 && onEndCall && /* @__PURE__ */ import_react14.default.createElement(
38565
39725
  "button",
38566
39726
  {
38567
39727
  type: "submit",
@@ -38580,7 +39740,7 @@ var ChatPopup = ({
38580
39740
  cursor: "pointer"
38581
39741
  }
38582
39742
  },
38583
- /* @__PURE__ */ import_react9.default.createElement(phone_off_default, { style: { width: 16, height: 16 } })
39743
+ /* @__PURE__ */ import_react14.default.createElement(phone_off_default, { style: { width: 16, height: 16 } })
38584
39744
  )
38585
39745
  )
38586
39746
  )
@@ -38588,7 +39748,7 @@ var ChatPopup = ({
38588
39748
  };
38589
39749
 
38590
39750
  // src/components/border-glow.tsx
38591
- var import_react10 = __toESM(require("react"));
39751
+ var import_react15 = __toESM(require("react"));
38592
39752
  var BorderGlow = ({ isActive }) => {
38593
39753
  if (!isActive) return null;
38594
39754
  const styles = {
@@ -38715,7 +39875,7 @@ var BorderGlow = ({ isActive }) => {
38715
39875
  opacity: 0.6
38716
39876
  }
38717
39877
  };
38718
- return /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, /* @__PURE__ */ import_react10.default.createElement("style", null, `
39878
+ return /* @__PURE__ */ import_react15.default.createElement(import_react15.default.Fragment, null, /* @__PURE__ */ import_react15.default.createElement("style", null, `
38719
39879
  @keyframes borderPulse {
38720
39880
  0%, 100% {
38721
39881
  opacity: 1;
@@ -38724,12 +39884,12 @@ var BorderGlow = ({ isActive }) => {
38724
39884
  opacity: 0.5;
38725
39885
  }
38726
39886
  }
38727
- `), /* @__PURE__ */ import_react10.default.createElement("div", { style: styles.container }, /* @__PURE__ */ import_react10.default.createElement("div", { style: styles.rightBorder1 }), /* @__PURE__ */ import_react10.default.createElement("div", { style: styles.rightBorder2 }), /* @__PURE__ */ import_react10.default.createElement("div", { style: styles.rightBorder3 }), /* @__PURE__ */ import_react10.default.createElement("div", { style: styles.leftBorder1 }), /* @__PURE__ */ import_react10.default.createElement("div", { style: styles.leftBorder2 }), /* @__PURE__ */ import_react10.default.createElement("div", { style: styles.leftBorder3 }), /* @__PURE__ */ import_react10.default.createElement("div", { style: styles.cornerTopLeft }), /* @__PURE__ */ import_react10.default.createElement("div", { style: styles.cornerTopRight }), /* @__PURE__ */ import_react10.default.createElement("div", { style: styles.cornerBottomRight }), /* @__PURE__ */ import_react10.default.createElement("div", { style: styles.cornerBottomLeft })));
39887
+ `), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.container }, /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.rightBorder1 }), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.rightBorder2 }), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.rightBorder3 }), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.leftBorder1 }), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.leftBorder2 }), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.leftBorder3 }), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.cornerTopLeft }), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.cornerTopRight }), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.cornerBottomRight }), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.cornerBottomLeft })));
38728
39888
  };
38729
39889
  var border_glow_default = BorderGlow;
38730
39890
 
38731
39891
  // src/components/voice-intensity-visualizer.tsx
38732
- var import_react12 = __toESM(require("react"));
39892
+ var import_react17 = __toESM(require("react"));
38733
39893
 
38734
39894
  // node_modules/@livekit/components-react/dist/hooks-C2Bp5v2q.mjs
38735
39895
  var r2 = __toESM(require("react"), 1);
@@ -38745,7 +39905,7 @@ var Me = { exports: {} };
38745
39905
  var Or = Me.exports;
38746
39906
  var kt;
38747
39907
  function kr() {
38748
- return kt || (kt = 1, function(e3) {
39908
+ return kt || (kt = 1, (function(e3) {
38749
39909
  (function(t, n) {
38750
39910
  e3.exports ? e3.exports = n() : t.log = n();
38751
39911
  })(Or, function() {
@@ -38889,7 +40049,7 @@ function kr() {
38889
40049
  return o2;
38890
40050
  }, s.default = s, s;
38891
40051
  });
38892
- }(Me)), Me.exports;
40052
+ })(Me)), Me.exports;
38893
40053
  }
38894
40054
  var _r = kr();
38895
40055
  var Lr = /* @__PURE__ */ Ar(_r);
@@ -39112,7 +40272,7 @@ function Ue(e3, t) {
39112
40272
  0 <= n && e3.splice(n, 1);
39113
40273
  }
39114
40274
  }
39115
- var Oe = function() {
40275
+ var Oe = (function() {
39116
40276
  function e3(t) {
39117
40277
  this.initialTeardown = t, this.closed = false, this._parentage = null, this._finalizers = null;
39118
40278
  }
@@ -39196,11 +40356,11 @@ var Oe = function() {
39196
40356
  }, e3.prototype.remove = function(t) {
39197
40357
  var n = this._finalizers;
39198
40358
  n && Ue(n, t), t instanceof e3 && t._removeParent(this);
39199
- }, e3.EMPTY = function() {
40359
+ }, e3.EMPTY = (function() {
39200
40360
  var t = new e3();
39201
40361
  return t.closed = true, t;
39202
- }(), e3;
39203
- }();
40362
+ })(), e3;
40363
+ })();
39204
40364
  var an = Oe.EMPTY;
39205
40365
  function cn(e3) {
39206
40366
  return e3 instanceof Oe || e3 && "closed" in e3 && P(e3.remove) && P(e3.add) && P(e3.unsubscribe);
@@ -39232,7 +40392,7 @@ function je() {
39232
40392
  function Re(e3) {
39233
40393
  e3();
39234
40394
  }
39235
- var gt = function(e3) {
40395
+ var gt = (function(e3) {
39236
40396
  te(t, e3);
39237
40397
  function t(n) {
39238
40398
  var r3 = e3.call(this) || this;
@@ -39263,8 +40423,8 @@ var gt = function(e3) {
39263
40423
  this.unsubscribe();
39264
40424
  }
39265
40425
  }, t;
39266
- }(Oe);
39267
- var Nr = function() {
40426
+ })(Oe);
40427
+ var Nr = (function() {
39268
40428
  function e3(t) {
39269
40429
  this.partialObserver = t;
39270
40430
  }
@@ -39295,8 +40455,8 @@ var Nr = function() {
39295
40455
  Le(n);
39296
40456
  }
39297
40457
  }, e3;
39298
- }();
39299
- var Ce = function(e3) {
40458
+ })();
40459
+ var Ce = (function(e3) {
39300
40460
  te(t, e3);
39301
40461
  function t(n, r3, i2) {
39302
40462
  var o2 = e3.call(this) || this, s;
@@ -39307,7 +40467,7 @@ var Ce = function(e3) {
39307
40467
  } : s = n, o2.destination = new Nr(s), o2;
39308
40468
  }
39309
40469
  return t;
39310
- }(gt);
40470
+ })(gt);
39311
40471
  function Le(e3) {
39312
40472
  un(e3);
39313
40473
  }
@@ -39320,9 +40480,9 @@ var Ur = {
39320
40480
  error: Fr,
39321
40481
  complete: je
39322
40482
  };
39323
- var bt = function() {
40483
+ var bt = (function() {
39324
40484
  return typeof Symbol == "function" && Symbol.observable || "@@observable";
39325
- }();
40485
+ })();
39326
40486
  function Ge(e3) {
39327
40487
  return e3;
39328
40488
  }
@@ -39333,7 +40493,7 @@ function jr(e3) {
39333
40493
  }, n);
39334
40494
  };
39335
40495
  }
39336
- var k = function() {
40496
+ var k = (function() {
39337
40497
  function e3(t) {
39338
40498
  t && (this._subscribe = t);
39339
40499
  }
@@ -39392,7 +40552,7 @@ var k = function() {
39392
40552
  }, e3.create = function(t) {
39393
40553
  return new e3(t);
39394
40554
  }, e3;
39395
- }();
40555
+ })();
39396
40556
  function Lt(e3) {
39397
40557
  var t;
39398
40558
  return (t = e3 ?? Dr.Promise) !== null && t !== void 0 ? t : Promise;
@@ -39422,7 +40582,7 @@ function j(e3) {
39422
40582
  function F(e3, t, n, r3, i2) {
39423
40583
  return new Hr(e3, t, n, r3, i2);
39424
40584
  }
39425
- var Hr = function(e3) {
40585
+ var Hr = (function(e3) {
39426
40586
  te(t, e3);
39427
40587
  function t(n, r3, i2, o2, s, a) {
39428
40588
  var c = e3.call(this, n) || this;
@@ -39457,13 +40617,13 @@ var Hr = function(e3) {
39457
40617
  e3.prototype.unsubscribe.call(this), !r3 && ((n = this.onFinalize) === null || n === void 0 || n.call(this));
39458
40618
  }
39459
40619
  }, t;
39460
- }(gt);
40620
+ })(gt);
39461
40621
  var zr = mt(function(e3) {
39462
40622
  return function() {
39463
40623
  e3(this), this.name = "ObjectUnsubscribedError", this.message = "object unsubscribed";
39464
40624
  };
39465
40625
  });
39466
- var ee = function(e3) {
40626
+ var ee = (function(e3) {
39467
40627
  te(t, e3);
39468
40628
  function t() {
39469
40629
  var n = e3.call(this) || this;
@@ -39542,8 +40702,8 @@ var ee = function(e3) {
39542
40702
  }, t.create = function(n, r3) {
39543
40703
  return new It(n, r3);
39544
40704
  }, t;
39545
- }(k);
39546
- var It = function(e3) {
40705
+ })(k);
40706
+ var It = (function(e3) {
39547
40707
  te(t, e3);
39548
40708
  function t(n, r3) {
39549
40709
  var i2 = e3.call(this) || this;
@@ -39562,8 +40722,8 @@ var It = function(e3) {
39562
40722
  var r3, i2;
39563
40723
  return (i2 = (r3 = this.source) === null || r3 === void 0 ? void 0 : r3.subscribe(n)) !== null && i2 !== void 0 ? i2 : an;
39564
40724
  }, t;
39565
- }(ee);
39566
- var ln = function(e3) {
40725
+ })(ee);
40726
+ var ln = (function(e3) {
39567
40727
  te(t, e3);
39568
40728
  function t(n) {
39569
40729
  var r3 = e3.call(this) || this;
@@ -39586,13 +40746,13 @@ var ln = function(e3) {
39586
40746
  }, t.prototype.next = function(n) {
39587
40747
  e3.prototype.next.call(this, this._value = n);
39588
40748
  }, t;
39589
- }(ee);
40749
+ })(ee);
39590
40750
  var Yr = {
39591
40751
  now: function() {
39592
40752
  return Date.now();
39593
40753
  }
39594
40754
  };
39595
- var qr = function(e3) {
40755
+ var qr = (function(e3) {
39596
40756
  te(t, e3);
39597
40757
  function t(n, r3) {
39598
40758
  return e3.call(this) || this;
@@ -39600,7 +40760,7 @@ var qr = function(e3) {
39600
40760
  return t.prototype.schedule = function(n, r3) {
39601
40761
  return this;
39602
40762
  }, t;
39603
- }(Oe);
40763
+ })(Oe);
39604
40764
  var Mt = {
39605
40765
  setInterval: function(e3, t) {
39606
40766
  for (var n = [], r3 = 2; r3 < arguments.length; r3++)
@@ -39612,7 +40772,7 @@ var Mt = {
39612
40772
  },
39613
40773
  delegate: void 0
39614
40774
  };
39615
- var Kr = function(e3) {
40775
+ var Kr = (function(e3) {
39616
40776
  te(t, e3);
39617
40777
  function t(n, r3) {
39618
40778
  var i2 = e3.call(this, n, r3) || this;
@@ -39654,16 +40814,16 @@ var Kr = function(e3) {
39654
40814
  this.work = this.state = this.scheduler = null, this.pending = false, Ue(o2, this), r3 != null && (this.id = this.recycleAsyncId(i2, r3, null)), this.delay = null, e3.prototype.unsubscribe.call(this);
39655
40815
  }
39656
40816
  }, t;
39657
- }(qr);
39658
- var Rt = function() {
40817
+ })(qr);
40818
+ var Rt = (function() {
39659
40819
  function e3(t, n) {
39660
40820
  n === void 0 && (n = e3.now), this.schedulerActionCtor = t, this.now = n;
39661
40821
  }
39662
40822
  return e3.prototype.schedule = function(t, n, r3) {
39663
40823
  return n === void 0 && (n = 0), new this.schedulerActionCtor(this, t).schedule(r3, n);
39664
40824
  }, e3.now = Yr.now, e3;
39665
- }();
39666
- var Gr = function(e3) {
40825
+ })();
40826
+ var Gr = (function(e3) {
39667
40827
  te(t, e3);
39668
40828
  function t(n, r3) {
39669
40829
  r3 === void 0 && (r3 = Rt.now);
@@ -39688,7 +40848,7 @@ var Gr = function(e3) {
39688
40848
  throw i2;
39689
40849
  }
39690
40850
  }, t;
39691
- }(Rt);
40851
+ })(Rt);
39692
40852
  var Qr = new Gr(Kr);
39693
40853
  function Jr(e3) {
39694
40854
  return e3 && P(e3.schedule);
@@ -40375,7 +41535,7 @@ function Yt(e3, t = {}) {
40375
41535
 
40376
41536
  // node_modules/@livekit/components-react/dist/components-Bz2b1Fa9.mjs
40377
41537
  var e2 = __toESM(require("react"), 1);
40378
- var import_react11 = require("react");
41538
+ var import_react16 = require("react");
40379
41539
  init_livekit_client_esm();
40380
41540
  var Y;
40381
41541
  var ue;
@@ -40470,8 +41630,8 @@ var Dt = (t) => {
40470
41630
  };
40471
41631
  var fe2 = (t) => [[Math.floor(t / 2)], [-1]];
40472
41632
  var Ut2 = (t, n, a) => {
40473
- const [r3, c] = (0, import_react11.useState)(0), [s, o2] = (0, import_react11.useState)([[]]);
40474
- (0, import_react11.useEffect)(() => {
41633
+ const [r3, c] = (0, import_react16.useState)(0), [s, o2] = (0, import_react16.useState)([[]]);
41634
+ (0, import_react16.useEffect)(() => {
40475
41635
  if (t === "thinking")
40476
41636
  o2(fe2(n));
40477
41637
  else if (t === "connecting" || t === "initializing") {
@@ -40480,8 +41640,8 @@ var Ut2 = (t, n, a) => {
40480
41640
  } else o2(t === "listening" ? fe2(n) : t === void 0 || t === "speaking" ? [new Array(n).fill(0).map((i2, u) => u)] : [[]]);
40481
41641
  c(0);
40482
41642
  }, [t, n]);
40483
- const l = (0, import_react11.useRef)(null);
40484
- return (0, import_react11.useEffect)(() => {
41643
+ const l = (0, import_react16.useRef)(null);
41644
+ return (0, import_react16.useEffect)(() => {
40485
41645
  let i2 = performance.now();
40486
41646
  const u = (d) => {
40487
41647
  d - i2 >= a && (c((f) => f + 1), i2 = d), l.current = requestAnimationFrame(u);
@@ -40551,8 +41711,8 @@ var Xt = /* @__PURE__ */ e2.forwardRef(
40551
41711
  init_livekit_client_esm();
40552
41712
  init_webrtc_service();
40553
41713
  var VoiceIntensityWithRoom = (props) => {
40554
- const [room2, setRoom] = (0, import_react12.useState)(null);
40555
- (0, import_react12.useEffect)(() => {
41714
+ const [room2, setRoom] = (0, import_react17.useState)(null);
41715
+ (0, import_react17.useEffect)(() => {
40556
41716
  if (props.isActive) {
40557
41717
  const currentRoom = getRoom();
40558
41718
  if (currentRoom) {
@@ -40565,7 +41725,7 @@ var VoiceIntensityWithRoom = (props) => {
40565
41725
  if (!room2) {
40566
41726
  return null;
40567
41727
  }
40568
- return /* @__PURE__ */ import_react12.default.createElement(Wn.Provider, { value: room2 }, /* @__PURE__ */ import_react12.default.createElement(VoiceIntensityBars, { ...props }));
41728
+ return /* @__PURE__ */ import_react17.default.createElement(Wn.Provider, { value: room2 }, /* @__PURE__ */ import_react17.default.createElement(VoiceIntensityBars, { ...props }));
40569
41729
  };
40570
41730
  var VoiceIntensityBars = ({
40571
41731
  isActive,
@@ -40608,7 +41768,7 @@ var VoiceIntensityBars = ({
40608
41768
  if (!trackRef) {
40609
41769
  return null;
40610
41770
  }
40611
- return /* @__PURE__ */ import_react12.default.createElement(
41771
+ return /* @__PURE__ */ import_react17.default.createElement(
40612
41772
  "div",
40613
41773
  {
40614
41774
  className: `voice-intensity-visualizer ${className}`,
@@ -40625,7 +41785,7 @@ var VoiceIntensityBars = ({
40625
41785
  pointerEvents: "none"
40626
41786
  }
40627
41787
  },
40628
- /* @__PURE__ */ import_react12.default.createElement(
41788
+ /* @__PURE__ */ import_react17.default.createElement(
40629
41789
  Xt,
40630
41790
  {
40631
41791
  barCount,
@@ -40639,7 +41799,7 @@ var VoiceIntensityBars = ({
40639
41799
  gap: "0.25rem"
40640
41800
  }
40641
41801
  },
40642
- /* @__PURE__ */ import_react12.default.createElement("span", { className: "cuekit-voice-intensity-bar" })
41802
+ /* @__PURE__ */ import_react17.default.createElement("span", { className: "cuekit-voice-intensity-bar" })
40643
41803
  )
40644
41804
  );
40645
41805
  };
@@ -40648,10 +41808,18 @@ var VoiceIntensityVisualizer = VoiceIntensityWithRoom;
40648
41808
  // src/components/mic-button.tsx
40649
41809
  init_webrtc_service();
40650
41810
 
40651
- // src/components/svgs/mic.tsx
40652
- var import_react13 = __toESM(require("react"));
40653
- var MicIcon = ({ width = 24, height = 24, className, ...props }) => {
40654
- return /* @__PURE__ */ import_react13.default.createElement(
41811
+ // src/components/language-selector.tsx
41812
+ var import_react19 = __toESM(require("react"));
41813
+
41814
+ // src/components/svgs/chevron-down.tsx
41815
+ var import_react18 = __toESM(require("react"));
41816
+ function ChevronDownIcon({
41817
+ width = 24,
41818
+ height = 24,
41819
+ className,
41820
+ ...props
41821
+ }) {
41822
+ return /* @__PURE__ */ import_react18.default.createElement(
40655
41823
  "svg",
40656
41824
  {
40657
41825
  xmlns: "http://www.w3.org/2000/svg",
@@ -40660,41 +41828,117 @@ var MicIcon = ({ width = 24, height = 24, className, ...props }) => {
40660
41828
  viewBox: "0 0 24 24",
40661
41829
  fill: "none",
40662
41830
  stroke: "currentColor",
40663
- strokeWidth: "2",
40664
- strokeLinecap: "round",
40665
- strokeLinejoin: "round",
41831
+ "stroke-width": "2",
41832
+ "stroke-linecap": "round",
41833
+ "stroke-linejoin": "round",
40666
41834
  className,
40667
41835
  ...props
40668
41836
  },
40669
- /* @__PURE__ */ import_react13.default.createElement("path", { d: "M12 19v3" }),
40670
- /* @__PURE__ */ import_react13.default.createElement("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
40671
- /* @__PURE__ */ import_react13.default.createElement("rect", { x: "9", y: "2", width: "6", height: "13", rx: "3" })
41837
+ /* @__PURE__ */ import_react18.default.createElement("path", { d: "m6 9 6 6 6-6" })
40672
41838
  );
40673
- };
40674
- var mic_default = MicIcon;
41839
+ }
40675
41840
 
40676
- // src/components/svgs/loader.tsx
40677
- var import_react14 = __toESM(require("react"));
40678
- var LoaderIcon = ({ width = 24, height = 24, className, ...props }) => {
40679
- return /* @__PURE__ */ import_react14.default.createElement(
40680
- "svg",
41841
+ // src/components/language-selector.tsx
41842
+ var FLAG_EMOJIS = {
41843
+ "en-US": "\u{1F1FA}\u{1F1F8}",
41844
+ "ar-SA": "\u{1F1F8}\u{1F1E6}",
41845
+ "es-ES": "\u{1F1EA}\u{1F1F8}",
41846
+ "fr-FR": "\u{1F1EB}\u{1F1F7}",
41847
+ "de-DE": "\u{1F1E9}\u{1F1EA}",
41848
+ "it-IT": "\u{1F1EE}\u{1F1F9}",
41849
+ "pt-BR": "\u{1F1E7}\u{1F1F7}",
41850
+ "ja-JP": "\u{1F1EF}\u{1F1F5}",
41851
+ "ko-KR": "\u{1F1F0}\u{1F1F7}",
41852
+ "zh-CN": "\u{1F1E8}\u{1F1F3}",
41853
+ "hi-IN": "\u{1F1EE}\u{1F1F3}"
41854
+ };
41855
+ var LanguageSelector = ({
41856
+ selectedLanguage,
41857
+ onLanguageChange,
41858
+ availableLanguages,
41859
+ disabled = false,
41860
+ className = "",
41861
+ tooltip,
41862
+ screenPosition = "bottom-center"
41863
+ }) => {
41864
+ const [isOpen, setIsOpen] = (0, import_react19.useState)(false);
41865
+ const [showTooltip, setShowTooltip] = (0, import_react19.useState)(false);
41866
+ const [dropdownUp, setDropdownUp] = (0, import_react19.useState)(false);
41867
+ const dropdownRef = (0, import_react19.useRef)(null);
41868
+ (0, import_react19.useEffect)(() => {
41869
+ const handleClickOutside = (event) => {
41870
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
41871
+ setIsOpen(false);
41872
+ }
41873
+ };
41874
+ document.addEventListener("mousedown", handleClickOutside);
41875
+ return () => {
41876
+ document.removeEventListener("mousedown", handleClickOutside);
41877
+ };
41878
+ }, []);
41879
+ const handleLanguageSelect = (language) => {
41880
+ if (disabled) return;
41881
+ onLanguageChange(language);
41882
+ setIsOpen(false);
41883
+ };
41884
+ const handleButtonClick = () => {
41885
+ if (disabled) return;
41886
+ const isBottomPosition = screenPosition.startsWith("bottom");
41887
+ setDropdownUp(isBottomPosition);
41888
+ setIsOpen(!isOpen);
41889
+ };
41890
+ const getFlagEmoji = (code4) => {
41891
+ return FLAG_EMOJIS[code4] || "\u{1F310}";
41892
+ };
41893
+ return /* @__PURE__ */ import_react19.default.createElement(
41894
+ "div",
40681
41895
  {
40682
- xmlns: "http://www.w3.org/2000/svg",
40683
- width: "24",
40684
- height: "24",
40685
- viewBox: "0 0 24 24",
40686
- fill: "none",
40687
- stroke: "currentColor",
40688
- strokeWidth: "2",
40689
- strokeLinecap: "round",
40690
- strokeLinejoin: "round",
40691
- className,
40692
- ...props
41896
+ className: `language-selector-container ${className}`,
41897
+ ref: dropdownRef,
41898
+ onMouseEnter: () => {
41899
+ if (disabled) {
41900
+ setShowTooltip(true);
41901
+ }
41902
+ },
41903
+ onMouseLeave: () => {
41904
+ setShowTooltip(false);
41905
+ }
40693
41906
  },
40694
- /* @__PURE__ */ import_react14.default.createElement("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
41907
+ /* @__PURE__ */ import_react19.default.createElement(
41908
+ "button",
41909
+ {
41910
+ className: `language-selector-button ${isOpen ? "open" : ""} ${disabled ? "disabled" : ""}`,
41911
+ onClick: handleButtonClick,
41912
+ disabled,
41913
+ "aria-label": disabled ? tooltip || "Language cannot be changed during conversation" : "Select language",
41914
+ "aria-expanded": isOpen,
41915
+ "aria-haspopup": "listbox"
41916
+ },
41917
+ /* @__PURE__ */ import_react19.default.createElement("div", { className: "language-selector-content" }, /* @__PURE__ */ import_react19.default.createElement("span", { className: "language-flag" }, getFlagEmoji(selectedLanguage.code)), /* @__PURE__ */ import_react19.default.createElement("span", { className: "language-code" }, selectedLanguage.code), /* @__PURE__ */ import_react19.default.createElement(
41918
+ ChevronDownIcon,
41919
+ {
41920
+ className: `language-chevron ${isOpen ? dropdownUp ? "rotated-up" : "rotated" : ""}`,
41921
+ width: 14,
41922
+ height: 14
41923
+ }
41924
+ ))
41925
+ ),
41926
+ disabled && /* @__PURE__ */ import_react19.default.createElement("div", { className: `language-tooltip ${showTooltip ? "show" : ""}` }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "language-tooltip-content" }, tooltip || "Close the conversation to change the language"), /* @__PURE__ */ import_react19.default.createElement("div", { className: "language-tooltip-arrow" })),
41927
+ isOpen && /* @__PURE__ */ import_react19.default.createElement("div", { className: `language-dropdown ${dropdownUp ? "dropdown-up" : ""}` }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "language-dropdown-content" }, availableLanguages.map((language) => /* @__PURE__ */ import_react19.default.createElement(
41928
+ "button",
41929
+ {
41930
+ key: language.code,
41931
+ className: `language-option ${selectedLanguage.code === language.code ? "selected" : ""}`,
41932
+ onClick: () => handleLanguageSelect(language),
41933
+ role: "option",
41934
+ "aria-selected": selectedLanguage.code === language.code
41935
+ },
41936
+ /* @__PURE__ */ import_react19.default.createElement("span", { className: "language-flag" }, getFlagEmoji(language.code)),
41937
+ /* @__PURE__ */ import_react19.default.createElement("div", { className: "language-info" }, /* @__PURE__ */ import_react19.default.createElement("span", { className: "language-name" }, language.name)),
41938
+ selectedLanguage.code === language.code && /* @__PURE__ */ import_react19.default.createElement("div", { className: "language-check" }, "\u2713")
41939
+ ))))
40695
41940
  );
40696
41941
  };
40697
- var loader_default = LoaderIcon;
40698
41942
 
40699
41943
  // src/components/mic-button.tsx
40700
41944
  var chatState = {
@@ -40702,7 +41946,7 @@ var chatState = {
40702
41946
  isMinimized: false
40703
41947
  };
40704
41948
  var VoiceIntensityWrapper = ({ active, buttonSize }) => {
40705
- return /* @__PURE__ */ import_react15.default.createElement(
41949
+ return /* @__PURE__ */ import_react20.default.createElement(
40706
41950
  VoiceIntensityVisualizer,
40707
41951
  {
40708
41952
  isActive: active,
@@ -40712,6 +41956,10 @@ var VoiceIntensityWrapper = ({ active, buttonSize }) => {
40712
41956
  }
40713
41957
  );
40714
41958
  };
41959
+ var DEFAULT_LANGUAGES = [
41960
+ { code: "en-US", name: "English (US)", flag: "\u{1F1FA}\u{1F1F8}" },
41961
+ { code: "ar-SA", name: "\u0627\u0644\u0639\u0631\u0628\u064A\u0629", flag: "\u{1F1F8}\u{1F1E6}" }
41962
+ ];
40715
41963
  var MicButton = ({
40716
41964
  buttonSize = 52,
40717
41965
  screenPosition = "bottom-center",
@@ -40723,22 +41971,29 @@ var MicButton = ({
40723
41971
  buttonStyle,
40724
41972
  bottomSpace = 20,
40725
41973
  defaultTheme = "system",
40726
- showBorderGlow = false
41974
+ showBorderGlow = false,
41975
+ language,
41976
+ defaultLanguage,
41977
+ onLanguageChange
40727
41978
  }) => {
40728
- const { apiKey, appId } = useQubeContext();
40729
- const [showBodyGlow, setShowBodyGlow] = (0, import_react15.useState)(false);
40730
- const [currentTheme, setCurrentTheme] = (0, import_react15.useState)("dark");
40731
- const [isChatOpen, setIsChatOpen] = (0, import_react15.useState)(chatState.isOpen);
40732
- const [isChatMinimized, setIsChatMinimized] = (0, import_react15.useState)(chatState.isMinimized);
40733
- (0, import_react15.useEffect)(() => {
41979
+ const { apiKey, appId } = useAnsyrContext();
41980
+ const [showBodyGlow, setShowBodyGlow] = (0, import_react20.useState)(false);
41981
+ const [currentTheme, setCurrentTheme] = (0, import_react20.useState)("dark");
41982
+ const [showLanguageSelector, setShowLanguageSelector] = (0, import_react20.useState)(false);
41983
+ const [selectedLanguage, setSelectedLanguage] = (0, import_react20.useState)(
41984
+ language || defaultLanguage || DEFAULT_LANGUAGES[0]
41985
+ );
41986
+ const [isChatOpen, setIsChatOpen] = (0, import_react20.useState)(chatState.isOpen);
41987
+ const [isChatMinimized, setIsChatMinimized] = (0, import_react20.useState)(chatState.isMinimized);
41988
+ (0, import_react20.useEffect)(() => {
40734
41989
  chatState.isOpen = isChatOpen;
40735
41990
  chatState.isMinimized = isChatMinimized;
40736
41991
  }, [isChatOpen, isChatMinimized]);
40737
- const audioContainerRef2 = (0, import_react15.useRef)(null);
40738
- const silenceTimerRef = (0, import_react15.useRef)(null);
40739
- const aiSpeakingRef = (0, import_react15.useRef)(false);
40740
- const aiSpeechTimeoutRef = (0, import_react15.useRef)(null);
40741
- const activeAITracksRef = (0, import_react15.useRef)(/* @__PURE__ */ new Set());
41992
+ const audioContainerRef2 = (0, import_react20.useRef)(null);
41993
+ const silenceTimerRef = (0, import_react20.useRef)(null);
41994
+ const aiSpeakingRef = (0, import_react20.useRef)(false);
41995
+ const aiSpeechTimeoutRef = (0, import_react20.useRef)(null);
41996
+ const activeAITracksRef = (0, import_react20.useRef)(/* @__PURE__ */ new Set());
40742
41997
  const {
40743
41998
  isConnected: isConnected2,
40744
41999
  isConnecting,
@@ -40746,12 +42001,16 @@ var MicButton = ({
40746
42001
  connect: voiceConnect,
40747
42002
  disconnect: voiceDisconnect,
40748
42003
  sendUserCommand: sendUserCommand2,
42004
+ sendChatMessage,
40749
42005
  messages: messageManagerMessages,
40750
42006
  micState,
40751
42007
  setMicState,
40752
42008
  status,
40753
42009
  setStatus,
40754
- participants
42010
+ participants,
42011
+ muteState,
42012
+ toggleMute,
42013
+ setMute
40755
42014
  } = useCuekit({
40756
42015
  // Don't override navigation command - let the provider handle it
40757
42016
  onConnectionStateChange: (state) => {
@@ -40764,7 +42023,7 @@ var MicButton = ({
40764
42023
  onAISpeechEnd: (trackId) => handleAISpeech(false, trackId),
40765
42024
  appId
40766
42025
  });
40767
- (0, import_react15.useEffect)(() => {
42026
+ (0, import_react20.useEffect)(() => {
40768
42027
  const checkTheme = () => {
40769
42028
  if (typeof document !== "undefined") {
40770
42029
  let newTheme;
@@ -40787,31 +42046,31 @@ var MicButton = ({
40787
42046
  return () => observer.disconnect();
40788
42047
  }
40789
42048
  }, [defaultTheme]);
40790
- const openChat = (0, import_react15.useCallback)(() => {
42049
+ const openChat = (0, import_react20.useCallback)(() => {
40791
42050
  setIsChatOpen(true);
40792
42051
  setIsChatMinimized(false);
40793
42052
  }, []);
40794
- const minimizeChat = (0, import_react15.useCallback)(() => {
42053
+ const minimizeChat = (0, import_react20.useCallback)(() => {
40795
42054
  setIsChatMinimized(true);
40796
42055
  if (showBorderGlow) {
40797
42056
  setShowBodyGlow(false);
40798
42057
  }
40799
42058
  }, [showBorderGlow]);
40800
- const restoreChat = (0, import_react15.useCallback)(() => {
42059
+ const restoreChat = (0, import_react20.useCallback)(() => {
40801
42060
  setIsChatMinimized(false);
40802
42061
  setIsChatOpen(true);
40803
42062
  if (showBorderGlow && (micState === "listening" || micState === "thinking" || micState === "replying")) {
40804
42063
  setShowBodyGlow(true);
40805
42064
  }
40806
42065
  }, [showBorderGlow, micState]);
40807
- const closeChat = (0, import_react15.useCallback)(() => {
42066
+ const closeChat = (0, import_react20.useCallback)(() => {
40808
42067
  setIsChatOpen(false);
40809
42068
  setIsChatMinimized(false);
40810
42069
  if (showBorderGlow) {
40811
42070
  setShowBodyGlow(false);
40812
42071
  }
40813
42072
  }, [showBorderGlow]);
40814
- const handleAISpeech = (0, import_react15.useCallback)(
42073
+ const handleAISpeech = (0, import_react20.useCallback)(
40815
42074
  (isSpeaking, trackId) => {
40816
42075
  if (isSpeaking && trackId) {
40817
42076
  activeAITracksRef.current.add(trackId);
@@ -40832,7 +42091,7 @@ var MicButton = ({
40832
42091
  },
40833
42092
  [status, micState, isConnected2]
40834
42093
  );
40835
- (0, import_react15.useEffect)(() => {
42094
+ (0, import_react20.useEffect)(() => {
40836
42095
  if (audioContainerRef2.current) {
40837
42096
  setAudioContainer(audioContainerRef2);
40838
42097
  }
@@ -40859,29 +42118,51 @@ var MicButton = ({
40859
42118
  }
40860
42119
  return isConnected3 ? "Ready" : "Connecting...";
40861
42120
  };
40862
- (0, import_react15.useEffect)(() => {
42121
+ (0, import_react20.useEffect)(() => {
40863
42122
  if (isConnected2) {
40864
42123
  } else {
40865
42124
  }
40866
42125
  }, [isConnected2]);
40867
- (0, import_react15.useEffect)(() => {
42126
+ (0, import_react20.useEffect)(() => {
40868
42127
  if (isConnected2 && !isChatOpen) {
40869
42128
  openChat();
40870
42129
  }
40871
42130
  }, [isConnected2, isChatOpen, openChat]);
40872
- (0, import_react15.useEffect)(() => {
42131
+ (0, import_react20.useEffect)(() => {
40873
42132
  if (messageManagerMessages.length > 0 && !isChatOpen) {
40874
42133
  openChat();
40875
42134
  }
40876
42135
  }, [messageManagerMessages.length, isChatOpen, openChat]);
40877
- const handleMicClick = (0, import_react15.useCallback)(() => {
42136
+ const handleLanguageChange = (0, import_react20.useCallback)(
42137
+ (newLanguage) => {
42138
+ setSelectedLanguage(newLanguage);
42139
+ onLanguageChange?.(newLanguage);
42140
+ },
42141
+ [onLanguageChange]
42142
+ );
42143
+ const handleLanguageConfirm = (0, import_react20.useCallback)(() => {
42144
+ setShowLanguageSelector(false);
42145
+ voiceConnect(`user_${Date.now()}`, apiKey, appId, selectedLanguage).then(() => {
42146
+ if (showBorderGlow) setShowBodyGlow(true);
42147
+ openChat();
42148
+ setTimeout(() => {
42149
+ openChat();
42150
+ }, 500);
42151
+ }).catch((error) => {
42152
+ });
42153
+ }, [voiceConnect, apiKey, appId, selectedLanguage, showBorderGlow, openChat]);
42154
+ const handleMicClick = (0, import_react20.useCallback)(() => {
40878
42155
  const shouldStop = micState === "listening" && isConnected2;
40879
42156
  if (shouldStop) {
40880
42157
  voiceDisconnect().then(() => {
40881
42158
  }).catch((error) => {
40882
42159
  });
40883
42160
  } else {
40884
- voiceConnect(`user_${Date.now()}`, apiKey, appId).then(() => {
42161
+ if (!language && !defaultLanguage && !selectedLanguage) {
42162
+ setShowLanguageSelector(true);
42163
+ return;
42164
+ }
42165
+ voiceConnect(`user_${Date.now()}`, apiKey, appId, selectedLanguage).then(() => {
40885
42166
  if (showBorderGlow) setShowBodyGlow(true);
40886
42167
  openChat();
40887
42168
  setTimeout(() => {
@@ -40897,8 +42178,12 @@ var MicButton = ({
40897
42178
  voiceConnect,
40898
42179
  apiKey,
40899
42180
  appId,
42181
+ language,
42182
+ selectedLanguage,
40900
42183
  openChat,
40901
- showBorderGlow
42184
+ showBorderGlow,
42185
+ sendChatMessage,
42186
+ isChatOpen
40902
42187
  ]);
40903
42188
  const handleSendText = async (textToSend) => {
40904
42189
  setMicState("thinking");
@@ -40908,13 +42193,14 @@ var MicButton = ({
40908
42193
  }
40909
42194
  if (isConnected2) {
40910
42195
  try {
40911
- await sendUserCommand2(textToSend);
42196
+ await sendChatMessage(textToSend);
40912
42197
  setMicState("replying");
40913
42198
  setTimeout(() => {
40914
42199
  setMicState("listening");
40915
42200
  if (showBorderGlow) setShowBodyGlow(true);
40916
42201
  }, 1e3);
40917
42202
  } catch (error) {
42203
+ console.error("Failed to send chat message:", error);
40918
42204
  } finally {
40919
42205
  setMicState("listening");
40920
42206
  if (showBorderGlow) setShowBodyGlow(true);
@@ -40941,8 +42227,11 @@ var MicButton = ({
40941
42227
  filter: "drop-shadow(0 10px 8px rgba(0, 0, 0, 0.04)) drop-shadow(0 4px 3px rgba(0, 0, 0, 0.1))",
40942
42228
  ...imageStyle
40943
42229
  };
40944
- const animatedImageStyle = micState === "thinking" ? { ...baseImageStyle, animation: "spin 1s linear infinite" } : micState === "replying" ? { ...baseImageStyle, animation: "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite" } : baseImageStyle;
40945
- return /* @__PURE__ */ import_react15.default.createElement("img", { src: imageSource, alt: "Voice Assistant", style: animatedImageStyle });
42230
+ if (micState === "idle") {
42231
+ return /* @__PURE__ */ import_react20.default.createElement("img", { src: imageSource, alt: "Voice Assistant", style: baseImageStyle });
42232
+ } else {
42233
+ return /* @__PURE__ */ import_react20.default.createElement(VoiceIntensityWrapper, { active: true, buttonSize });
42234
+ }
40946
42235
  }
40947
42236
  const iconStyle = {
40948
42237
  width: `100%`,
@@ -40950,15 +42239,10 @@ var MicButton = ({
40950
42239
  color: "white",
40951
42240
  filter: "drop-shadow(0 10px 8px rgba(0, 0, 0, 0.04)) drop-shadow(0 4px 3px rgba(0, 0, 0, 0.1))"
40952
42241
  };
40953
- switch (micState) {
40954
- case "thinking":
40955
- return /* @__PURE__ */ import_react15.default.createElement(loader_default, { style: { ...iconStyle, animation: "spin 1s linear infinite" } });
40956
- case "replying":
40957
- return /* @__PURE__ */ import_react15.default.createElement(VoiceIntensityWrapper, { active: true, buttonSize });
40958
- case "listening":
40959
- return /* @__PURE__ */ import_react15.default.createElement(VoiceIntensityWrapper, { active: true, buttonSize });
40960
- default:
40961
- return /* @__PURE__ */ import_react15.default.createElement(mic_default, { style: iconStyle });
42242
+ if (micState === "idle") {
42243
+ return /* @__PURE__ */ import_react20.default.createElement(mic_default, { style: iconStyle });
42244
+ } else {
42245
+ return /* @__PURE__ */ import_react20.default.createElement(VoiceIntensityWrapper, { active: true, buttonSize });
40962
42246
  }
40963
42247
  };
40964
42248
  const getPositionStyle = () => {
@@ -41020,16 +42304,15 @@ var MicButton = ({
41020
42304
  const baseStyle = { ...buttonStyles.button };
41021
42305
  switch (micState) {
41022
42306
  case "listening":
41023
- baseStyle.transform = "scale(1.1)";
42307
+ baseStyle.transform = "scale(1.05)";
41024
42308
  baseStyle.boxShadow = "0 25px 50px -12px rgba(59, 130, 246, 0.6)";
41025
42309
  break;
41026
42310
  case "thinking":
41027
- baseStyle.transform = "scale(1.05)";
42311
+ baseStyle.transform = "scale(1.02)";
41028
42312
  baseStyle.boxShadow = "0 20px 25px -5px rgba(196, 132, 252, 0.4)";
41029
- baseStyle.animation = "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite";
41030
42313
  break;
41031
42314
  case "replying":
41032
- baseStyle.transform = "scale(1.05)";
42315
+ baseStyle.transform = "scale(1.02)";
41033
42316
  baseStyle.boxShadow = "0 20px 25px -5px rgba(34, 211, 238, 0.4)";
41034
42317
  break;
41035
42318
  default:
@@ -41038,7 +42321,34 @@ var MicButton = ({
41038
42321
  }
41039
42322
  return baseStyle;
41040
42323
  };
41041
- return /* @__PURE__ */ import_react15.default.createElement(import_react15.default.Fragment, null, /* @__PURE__ */ import_react15.default.createElement("div", { "data-cuekit-ignore": true, style: { ...buttonStyles.container, ...getPositionStyle() } }, /* @__PURE__ */ import_react15.default.createElement("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: "8px" } }, /* @__PURE__ */ import_react15.default.createElement(
42324
+ return /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement("div", { "data-cuekit-ignore": true, style: { ...buttonStyles.container, ...getPositionStyle() } }, showLanguageSelector ? /* @__PURE__ */ import_react20.default.createElement("div", { className: "voice-chat-language-selection" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "voice-chat-language-header" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "voice-chat-language-icon" }, /* @__PURE__ */ import_react20.default.createElement(mic_default, { width: 20, height: 20 })), /* @__PURE__ */ import_react20.default.createElement("span", { className: "voice-chat-language-title" }, "Select Language")), /* @__PURE__ */ import_react20.default.createElement(
42325
+ LanguageSelector,
42326
+ {
42327
+ selectedLanguage,
42328
+ onLanguageChange: handleLanguageChange,
42329
+ availableLanguages: DEFAULT_LANGUAGES,
42330
+ className: "voice-chat-language-selector",
42331
+ screenPosition
42332
+ }
42333
+ ), /* @__PURE__ */ import_react20.default.createElement("div", { className: "voice-chat-language-actions" }, /* @__PURE__ */ import_react20.default.createElement(
42334
+ "button",
42335
+ {
42336
+ className: "voice-chat-cancel-button",
42337
+ onClick: () => setShowLanguageSelector(false)
42338
+ },
42339
+ "Cancel"
42340
+ ), /* @__PURE__ */ import_react20.default.createElement("button", { className: "voice-chat-confirm-button", onClick: handleLanguageConfirm }, "Start Voice Chat"))) : /* @__PURE__ */ import_react20.default.createElement("div", { className: "voice-chat-main-button" }, /* @__PURE__ */ import_react20.default.createElement(
42341
+ LanguageSelector,
42342
+ {
42343
+ selectedLanguage,
42344
+ onLanguageChange: handleLanguageChange,
42345
+ availableLanguages: DEFAULT_LANGUAGES,
42346
+ className: "voice-chat-language-preview",
42347
+ disabled: isConnected2 || micState !== "idle",
42348
+ tooltip: "Close the conversation to change the language",
42349
+ screenPosition
42350
+ }
42351
+ ), /* @__PURE__ */ import_react20.default.createElement(
41042
42352
  "button",
41043
42353
  {
41044
42354
  "data-testid": "ignore",
@@ -41059,8 +42369,8 @@ var MicButton = ({
41059
42369
  },
41060
42370
  "aria-label": micState === "thinking" ? "Processing..." : micState === "replying" ? "AI is responding..." : isListening ? "Stop listening" : "Start listening"
41061
42371
  },
41062
- /* @__PURE__ */ import_react15.default.createElement("div", { style: buttonStyles.iconContainer }, getIcon())
41063
- ), hasText && text7 && /* @__PURE__ */ import_react15.default.createElement(
42372
+ /* @__PURE__ */ import_react20.default.createElement("div", { style: buttonStyles.iconContainer }, getIcon())
42373
+ )), !showLanguageSelector && hasText && text7 && /* @__PURE__ */ import_react20.default.createElement(
41064
42374
  "div",
41065
42375
  {
41066
42376
  style: {
@@ -41078,11 +42388,12 @@ var MicButton = ({
41078
42388
  alignItems: "center",
41079
42389
  justifyContent: "center",
41080
42390
  gap: "4px",
42391
+ marginTop: "8px",
41081
42392
  ...textStyle
41082
42393
  }
41083
42394
  },
41084
- /* @__PURE__ */ import_react15.default.createElement("span", null, text7)
41085
- ))), /* @__PURE__ */ import_react15.default.createElement(
42395
+ /* @__PURE__ */ import_react20.default.createElement("span", null, text7)
42396
+ )), /* @__PURE__ */ import_react20.default.createElement(
41086
42397
  ChatPopup,
41087
42398
  {
41088
42399
  isOpen: isChatOpen,
@@ -41103,9 +42414,16 @@ var MicButton = ({
41103
42414
  currentTheme,
41104
42415
  onThemeToggle: setCurrentTheme,
41105
42416
  status: getUserFriendlyStatus(micState, isConnected2 ?? false),
41106
- anchor: { position: screenPosition, bottom: bottomSpace, size: buttonSize }
41107
- }
41108
- ), isChatOpen && isChatMinimized && /* @__PURE__ */ import_react15.default.createElement(
42417
+ anchor: { position: screenPosition, bottom: bottomSpace, size: buttonSize },
42418
+ muteState,
42419
+ onToggleMute: toggleMute,
42420
+ draggable: true,
42421
+ resizable: true,
42422
+ persistPosition: true,
42423
+ persistSize: true,
42424
+ storageKey: "cuekit-chat-popup"
42425
+ }
42426
+ ), isChatOpen && isChatMinimized && /* @__PURE__ */ import_react20.default.createElement(
41109
42427
  "button",
41110
42428
  {
41111
42429
  onClick: restoreChat,
@@ -41126,8 +42444,8 @@ var MicButton = ({
41126
42444
  className: `cuekit-voice-popup ${currentTheme === "dark" ? "cuekit-dark" : ""}`,
41127
42445
  "aria-label": "Open chat"
41128
42446
  },
41129
- /* @__PURE__ */ import_react15.default.createElement("span", { style: { fontSize: 12, fontWeight: 600, color: "hsl(var(--voice-text))" } }, "Open chat")
41130
- ), /* @__PURE__ */ import_react15.default.createElement("div", { ref: audioContainerRef2, style: { display: "none" } }), showBorderGlow && showBodyGlow && /* @__PURE__ */ import_react15.default.createElement(border_glow_default, { isActive: true }));
42447
+ /* @__PURE__ */ import_react20.default.createElement("span", { style: { fontSize: 12, fontWeight: 600, color: "hsl(var(--voice-text))" } }, "Open chat")
42448
+ ), /* @__PURE__ */ import_react20.default.createElement("div", { ref: audioContainerRef2, style: { display: "none" } }), showBorderGlow && showBodyGlow && /* @__PURE__ */ import_react20.default.createElement(border_glow_default, { isActive: true }));
41131
42449
  };
41132
42450
 
41133
42451
  // src/index.ts