@superinterface/react 5.3.0-beta.4 → 5.3.0-beta.6

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.cjs CHANGED
@@ -47436,39 +47436,74 @@ function _toPrimitive47(t, r) {
47436
47436
  }
47437
47437
  return ("string" === r ? String : Number)(t);
47438
47438
  }
47439
- var splitSentencesFast = function(text) {
47440
- var t = text.replace(/\s+/g, " ").trim();
47441
- if (!t) return [];
47442
- var parts = t.split(RegExp("(?<=[.!?])\\s+(?=[^\\s])", "g"));
47443
- return parts;
47439
+ var THROTTLE_MS = 80;
47440
+ var MAX_SEG_CACHE = 256;
47441
+ var KEEP_FINISHED_MESSAGES = 12;
47442
+ var hasLetters = function(s) {
47443
+ for(var i = 0; i < s.length; i++){
47444
+ var ch = s.charAt(i);
47445
+ if (ch.toLowerCase() !== ch.toUpperCase()) return true;
47446
+ }
47447
+ return false;
47444
47448
  };
47445
- var getIncrementalSentences = function(prev, nextInput) {
47446
- if (!prev) {
47447
- return {
47448
- input: nextInput,
47449
- sentences: splitSentencesFast(nextInput)
47450
- };
47449
+ var isSentencePunct = function(ch) {
47450
+ return ch === "." || ch === "!" || ch === "?" || ch === "\u3002" || ch === "\uFF01" || ch === "\uFF1F";
47451
+ };
47452
+ var normalizeBoundaries = function(text) {
47453
+ var out = "";
47454
+ for(var i = 0; i < text.length; i++){
47455
+ var ch = text.charAt(i);
47456
+ out += ch;
47457
+ if (isSentencePunct(ch)) {
47458
+ var next = text.charAt(i + 1);
47459
+ if (next && next !== " " && hasLetters(next)) {
47460
+ out += " ";
47461
+ }
47462
+ }
47451
47463
  }
47452
- if (nextInput === prev.input) {
47453
- return prev;
47464
+ return out;
47465
+ };
47466
+ var splitSentencesFast = function(raw) {
47467
+ var t = normalizeBoundaries(raw.replace(/\s+/g, " ").trim());
47468
+ if (!t) return [];
47469
+ var parts = t.split(RegExp("(?<=[.!?])\\s+(?=[^\\s])", "g"));
47470
+ var filtered = [];
47471
+ for(var i = 0; i < parts.length; i++){
47472
+ var p = parts[i].trim();
47473
+ if (p && hasLetters(p)) filtered.push(p);
47454
47474
  }
47475
+ return filtered;
47476
+ };
47477
+ var getIncrementalSentences = function(prev, nextInput, now) {
47478
+ if (!prev) return {
47479
+ input: nextInput,
47480
+ sentences: splitSentencesFast(nextInput),
47481
+ touched: now
47482
+ };
47483
+ if (nextInput === prev.input) return {
47484
+ input: prev.input,
47485
+ sentences: prev.sentences,
47486
+ touched: now
47487
+ };
47455
47488
  if (nextInput.startsWith(prev.input)) {
47456
- var _prev$sentences;
47457
- var prevLast = (_prev$sentences = prev.sentences[prev.sentences.length - 1]) !== null && _prev$sentences !== void 0 ? _prev$sentences : "";
47489
+ var prevSentences = prev.sentences;
47490
+ var prevLast = prevSentences[prevSentences.length - 1] || "";
47458
47491
  var baseLen = prev.input.length - prevLast.length;
47459
47492
  if (baseLen >= 0 && prev.input.slice(baseLen) === prevLast) {
47460
47493
  var tail = nextInput.slice(baseLen);
47461
47494
  var tailSegments = splitSentencesFast(tail);
47462
- var merged = prev.sentences.length > 0 ? _to_consumable_array(prev.sentences.slice(0, -1)).concat(_to_consumable_array(tailSegments)) : tailSegments;
47495
+ var merged = prevSentences.length > 0 ? prevSentences.slice(0, -1).concat(tailSegments) : tailSegments;
47463
47496
  return {
47464
47497
  input: nextInput,
47465
- sentences: merged
47498
+ sentences: merged,
47499
+ touched: now
47466
47500
  };
47467
47501
  }
47468
47502
  }
47469
47503
  return {
47470
47504
  input: nextInput,
47471
- sentences: splitSentencesFast(nextInput)
47505
+ sentences: splitSentencesFast(nextInput),
47506
+ touched: now
47472
47507
  };
47473
47508
  };
47474
47509
  var useMessageAudio = function(_ref) {
@@ -47489,41 +47524,65 @@ var useMessageAudio = function(_ref) {
47489
47524
  var currentSentenceRef = (0, import_react67.useRef)(null);
47490
47525
  var messagesProps = useMessages();
47491
47526
  var segCacheRef = (0, import_react67.useRef)(/* @__PURE__ */ new Map());
47527
+ var mirrorTimerRef = (0, import_react67.useRef)(null);
47528
+ var pendingMirrorRef = (0, import_react67.useRef)(false);
47492
47529
  (0, import_react67.useEffect)(function() {
47493
- var assistantsDesc = messagesProps.messages.filter(function(m) {
47494
- return m.role === "assistant";
47495
- });
47496
- var assistantsAsc = _to_consumable_array(assistantsDesc).reverse();
47497
- setAudioQueue(function(prev) {
47498
- var prevById = new Map(prev.map(function(p) {
47499
- return [
47500
- p.id,
47501
- p
47502
- ];
47503
- }));
47504
- var changed = false;
47505
- var next = [];
47506
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
47507
- try {
47508
- for(var _iterator = assistantsAsc[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
47509
- var m_0 = _step.value;
47530
+ if (mirrorTimerRef.current != null) {
47531
+ pendingMirrorRef.current = true;
47532
+ return;
47533
+ }
47534
+ var run = function() {
47535
+ var assistantsDesc = messagesProps.messages.filter(function(m) {
47536
+ return m.role === "assistant";
47537
+ });
47538
+ var assistantsAsc = assistantsDesc.slice().reverse();
47539
+ var nowTs = typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
47540
+ var segCache = segCacheRef.current;
47541
+ var touch = function(id, entry) {
47542
+ segCache.set(id, {
47543
+ input: entry.input,
47544
+ sentences: entry.sentences,
47545
+ touched: nowTs
47546
+ });
47547
+ };
47548
+ var evictLRU = function() {
47549
+ if (segCache.size <= MAX_SEG_CACHE) return;
47550
+ var entries = Array.from(segCache.entries());
47551
+ entries.sort(function(a, b) {
47552
+ return a[1].touched - b[1].touched;
47553
+ });
47554
+ var toRemove = segCache.size - MAX_SEG_CACHE;
47555
+ for(var i = 0; i < toRemove; i++)segCache.delete(entries[i][0]);
47556
+ };
47557
+ setAudioQueue(function(prev) {
47558
+ var prevById = new Map(prev.map(function(p) {
47559
+ return [
47560
+ p.id,
47561
+ p
47562
+ ];
47563
+ }));
47564
+ var next = [];
47565
+ var changed = false;
47566
+ for(var i_0 = 0; i_0 < assistantsAsc.length; i_0++){
47510
47567
  var _existing$nextIndex, _existing$stopped;
47568
+ var m_0 = assistantsAsc[i_0];
47511
47569
  var inp = input({
47512
47570
  message: m_0
47513
47571
  });
47514
47572
  if (inp == null) continue;
47515
- var prevSeg = segCacheRef.current.get(m_0.id);
47516
- var nextSeg = getIncrementalSentences(prevSeg, inp);
47517
- if (!prevSeg || nextSeg.input !== prevSeg.input) {
47518
- segCacheRef.current.set(m_0.id, nextSeg);
47573
+ var prevSeg = segCache.get(m_0.id);
47574
+ var nextSeg = getIncrementalSentences(prevSeg, inp, nowTs);
47575
+ if (!prevSeg || nextSeg.input !== prevSeg.input || nextSeg.sentences !== prevSeg.sentences) {
47576
+ touch(m_0.id, nextSeg);
47577
+ } else {
47578
+ touch(m_0.id, prevSeg);
47519
47579
  }
47520
47580
  var existing = prevById.get(m_0.id);
47521
47581
  var sentences = nextSeg.sentences;
47522
47582
  var nextIndex = Math.min((_existing$nextIndex = existing === null || existing === void 0 ? void 0 : existing.nextIndex) !== null && _existing$nextIndex !== void 0 ? _existing$nextIndex : 0, sentences.length);
47523
47583
  var stopped = (_existing$stopped = existing === null || existing === void 0 ? void 0 : existing.stopped) !== null && _existing$stopped !== void 0 ? _existing$stopped : false;
47524
- var reuseExisting = !!existing && existing.status === m_0.status && existing.sentences === sentences && // same array ref -> no change
47525
- existing.nextIndex === nextIndex && existing.stopped === stopped;
47526
- if (reuseExisting) {
47584
+ var reuse = !!existing && existing.status === m_0.status && existing.sentences === sentences && existing.nextIndex === nextIndex && existing.stopped === stopped;
47585
+ if (reuse) {
47527
47586
  next.push(existing);
47528
47587
  } else {
47529
47588
  next.push({
@@ -47536,32 +47595,69 @@ var useMessageAudio = function(_ref) {
47536
47595
  changed = true;
47537
47596
  }
47538
47597
  }
47539
- } catch (err) {
47540
- _didIteratorError = true;
47541
- _iteratorError = err;
47542
- } finally{
47598
+ var unfinished = [];
47599
+ var finished = [];
47600
+ for(var i_1 = 0; i_1 < next.length; i_1++){
47601
+ var m_1 = next[i_1];
47602
+ if (!m_1.stopped && (m_1.status === "in_progress" || m_1.nextIndex < m_1.sentences.length)) {
47603
+ unfinished.push(m_1);
47604
+ } else {
47605
+ finished.push(m_1);
47606
+ }
47607
+ }
47608
+ var prunedFinished = finished.length > KEEP_FINISHED_MESSAGES ? finished.slice(finished.length - KEEP_FINISHED_MESSAGES) : finished;
47609
+ var combined = unfinished.concat(prunedFinished);
47610
+ if (!changed) {
47611
+ if (combined.length !== prev.length) changed = true;
47612
+ else {
47613
+ for(var i_2 = 0; i_2 < combined.length; i_2++){
47614
+ if (combined[i_2] !== prev[i_2]) {
47615
+ changed = true;
47616
+ break;
47617
+ }
47618
+ }
47619
+ }
47620
+ }
47621
+ var idsInQueue = new Set(combined.map(function(m_2) {
47622
+ return m_2.id;
47623
+ }));
47624
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
47543
47625
  try {
47544
- if (!_iteratorNormalCompletion && _iterator.return != null) {
47545
- _iterator.return();
47626
+ for(var _iterator = Array.from(segCache.keys())[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
47627
+ var id_0 = _step.value;
47628
+ if (!idsInQueue.has(id_0)) segCache.delete(id_0);
47546
47629
  }
47630
+ } catch (err) {
47631
+ _didIteratorError = true;
47632
+ _iteratorError = err;
47547
47633
  } finally{
47548
- if (_didIteratorError) {
47549
- throw _iteratorError;
47634
+ try {
47635
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
47636
+ _iterator.return();
47637
+ }
47638
+ } finally{
47639
+ if (_didIteratorError) {
47640
+ throw _iteratorError;
47641
+ }
47550
47642
  }
47551
47643
  }
47644
+ evictLRU();
47645
+ return changed ? combined : prev;
47646
+ });
47647
+ mirrorTimerRef.current = null;
47648
+ if (pendingMirrorRef.current) {
47649
+ pendingMirrorRef.current = false;
47650
+ mirrorTimerRef.current = window.setTimeout(run, THROTTLE_MS);
47552
47651
  }
47553
- if (next.length !== prev.length) {
47554
- changed = true;
47555
- } else {
47556
- for(var i = 0; i < next.length; i++){
47557
- if (next[i] !== prev[i]) {
47558
- changed = true;
47559
- break;
47560
- }
47561
- }
47652
+ };
47653
+ mirrorTimerRef.current = window.setTimeout(run, THROTTLE_MS);
47654
+ return function() {
47655
+ if (mirrorTimerRef.current != null) {
47656
+ clearTimeout(mirrorTimerRef.current);
47657
+ mirrorTimerRef.current = null;
47562
47658
  }
47563
- return changed ? next : prev;
47564
- });
47659
+ pendingMirrorRef.current = false;
47660
+ };
47565
47661
  }, [
47566
47662
  messagesProps.messages
47567
47663
  ]);
@@ -47573,15 +47669,14 @@ var useMessageAudio = function(_ref) {
47573
47669
  audioPlayer.load("".concat(superinterfaceContext.baseUrl, "/audio-runtimes/tts?").concat(searchParams), {
47574
47670
  format: "mp3",
47575
47671
  autoplay: isAudioPlayed,
47576
- // first call false; then true for snappier chaining
47577
47672
  html5: isHtmlAudioSupported,
47578
47673
  onplay: onPlay,
47579
47674
  onstop: onStop,
47580
47675
  onload: function() {
47581
47676
  var current = currentSentenceRef.current;
47582
47677
  if (!current) return;
47583
- var msg = audioQueueRef.current.find(function(m_1) {
47584
- return m_1.id === current.messageId;
47678
+ var msg = audioQueueRef.current.find(function(m_3) {
47679
+ return m_3.id === current.messageId;
47585
47680
  });
47586
47681
  if (!msg) return;
47587
47682
  var nextSentence = msg.sentences[msg.nextIndex];
@@ -47616,42 +47711,23 @@ var useMessageAudio = function(_ref) {
47616
47711
  if (audioPlayer.playing) return;
47617
47712
  if (pickLockRef.current) return;
47618
47713
  var candidate = null;
47619
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
47620
- try {
47621
- for(var _iterator = audioQueue[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
47622
- var msg_0 = _step.value;
47623
- if (msg_0.stopped) continue;
47624
- var sentence = msg_0.sentences[msg_0.nextIndex];
47625
- while(sentence && !/\S/.test(sentence)){
47626
- msg_0.nextIndex++;
47627
- sentence = msg_0.sentences[msg_0.nextIndex];
47628
- }
47629
- if (!sentence) continue;
47630
- var isFull = isOptimistic({
47631
- id: msg_0.id
47632
- }) || msg_0.status !== "in_progress" || fullSentenceRegex.test(sentence);
47633
- if (isFull) {
47634
- candidate = {
47635
- messageId: msg_0.id,
47636
- sentence: sentence,
47637
- index: msg_0.nextIndex,
47638
- ownerStatus: msg_0.status
47639
- };
47640
- break;
47641
- }
47642
- }
47643
- } catch (err) {
47644
- _didIteratorError = true;
47645
- _iteratorError = err;
47646
- } finally{
47647
- try {
47648
- if (!_iteratorNormalCompletion && _iterator.return != null) {
47649
- _iterator.return();
47650
- }
47651
- } finally{
47652
- if (_didIteratorError) {
47653
- throw _iteratorError;
47654
- }
47714
+ for(var mIdx = 0; mIdx < audioQueue.length; mIdx++){
47715
+ var msg_0 = audioQueue[mIdx];
47716
+ if (msg_0.stopped) continue;
47717
+ var idx = msg_0.nextIndex;
47718
+ var sentence = msg_0.sentences[idx];
47719
+ if (!sentence) continue;
47720
+ var isFull = isOptimistic({
47721
+ id: msg_0.id
47722
+ }) || msg_0.status !== "in_progress" || fullSentenceRegex.test(sentence);
47723
+ if (isFull) {
47724
+ candidate = {
47725
+ messageId: msg_0.id,
47726
+ sentence: sentence,
47727
+ index: idx,
47728
+ ownerStatus: msg_0.status
47729
+ };
47730
+ break;
47655
47731
  }
47656
47732
  }
47657
47733
  if (!candidate) return;
@@ -47662,10 +47738,10 @@ var useMessageAudio = function(_ref) {
47662
47738
  index: candidate.index
47663
47739
  };
47664
47740
  setAudioQueue(function(prev_0) {
47665
- return prev_0.map(function(m_2) {
47666
- return m_2.id === candidate.messageId ? _objectSpread47(_objectSpread47({}, m_2), {}, {
47667
- nextIndex: m_2.nextIndex + 1
47668
- }) : m_2;
47741
+ return prev_0.map(function(m_4) {
47742
+ return m_4.id === candidate.messageId ? _objectSpread47(_objectSpread47({}, m_4), {}, {
47743
+ nextIndex: candidate.index + 1
47744
+ }) : m_4;
47669
47745
  });
47670
47746
  });
47671
47747
  play({
@@ -47675,10 +47751,10 @@ var useMessageAudio = function(_ref) {
47675
47751
  },
47676
47752
  onStop: function() {
47677
47753
  setAudioQueue(function(prev_1) {
47678
- return prev_1.map(function(m_3) {
47679
- return m_3.id === candidate.messageId ? _objectSpread47(_objectSpread47({}, m_3), {}, {
47754
+ return prev_1.map(function(m_5) {
47755
+ return m_5.id === candidate.messageId ? _objectSpread47(_objectSpread47({}, m_5), {}, {
47680
47756
  stopped: true
47681
- }) : m_3;
47757
+ }) : m_5;
47682
47758
  });
47683
47759
  });
47684
47760
  setIsPlaying(false);
@@ -47689,10 +47765,10 @@ var useMessageAudio = function(_ref) {
47689
47765
  setIsPlaying(false);
47690
47766
  currentSentenceRef.current = null;
47691
47767
  pickLockRef.current = false;
47692
- var hasPending = audioQueueRef.current.some(function(m_4) {
47693
- if (m_4.stopped) return false;
47694
- var hasMore = m_4.nextIndex < m_4.sentences.length;
47695
- var streaming = m_4.status === "in_progress";
47768
+ var hasPending = audioQueueRef.current.some(function(m_6) {
47769
+ if (m_6.stopped) return false;
47770
+ var hasMore = m_6.nextIndex < m_6.sentences.length;
47771
+ var streaming = m_6.status === "in_progress";
47696
47772
  return hasMore || streaming;
47697
47773
  });
47698
47774
  if (!hasPending) _onEnd();
@@ -47708,9 +47784,9 @@ var useMessageAudio = function(_ref) {
47708
47784
  ]);
47709
47785
  (0, import_react67.useEffect)(function() {
47710
47786
  if (isHtmlAudioSupported) {
47711
- var _Howler$_howls$;
47712
- if (!(import_howler.Howler !== null && import_howler.Howler !== void 0 && (_Howler$_howls$ = import_howler.Howler._howls[0]) !== null && _Howler$_howls$ !== void 0 && (_Howler$_howls$ = _Howler$_howls$._sounds[0]) !== null && _Howler$_howls$ !== void 0 && _Howler$_howls$._node)) return;
47713
- import_howler.Howler._howls[0]._sounds[0]._node.crossOrigin = "anonymous";
47787
+ var _Howler$_howls;
47788
+ var node = import_howler.Howler === null || import_howler.Howler === void 0 || (_Howler$_howls = import_howler.Howler._howls) === null || _Howler$_howls === void 0 || (_Howler$_howls = _Howler$_howls[0]) === null || _Howler$_howls === void 0 || (_Howler$_howls = _Howler$_howls._sounds) === null || _Howler$_howls === void 0 || (_Howler$_howls = _Howler$_howls[0]) === null || _Howler$_howls === void 0 ? void 0 : _Howler$_howls._node;
47789
+ if (node) node.crossOrigin = "anonymous";
47714
47790
  }
47715
47791
  }, [
47716
47792
  audioPlayer
@@ -47722,14 +47798,17 @@ var useMessageAudio = function(_ref) {
47722
47798
  if (isAudioEngineInited.current) return;
47723
47799
  isAudioEngineInited.current = true;
47724
47800
  if (isHtmlAudioSupported) {
47725
- var _Howler$_howls$2;
47726
- var audioContext = new AudioContext();
47727
- setAudioEngine({
47728
- // @ts-ignore-next-line
47729
- source: audioContext.createMediaElementSource(// @ts-ignore-next-line
47730
- (_Howler$_howls$2 = import_howler.Howler._howls[0]) === null || _Howler$_howls$2 === void 0 || (_Howler$_howls$2 = _Howler$_howls$2._sounds[0]) === null || _Howler$_howls$2 === void 0 ? void 0 : _Howler$_howls$2._node),
47731
- audioContext: audioContext
47732
- });
47801
+ var _Howler$_howls2;
47802
+ var AudioCtx = window.AudioContext || window.webkitAudioContext;
47803
+ var audioContext = new AudioCtx();
47804
+ var node_0 = import_howler.Howler === null || import_howler.Howler === void 0 || (_Howler$_howls2 = import_howler.Howler._howls) === null || _Howler$_howls2 === void 0 || (_Howler$_howls2 = _Howler$_howls2[0]) === null || _Howler$_howls2 === void 0 || (_Howler$_howls2 = _Howler$_howls2._sounds) === null || _Howler$_howls2 === void 0 || (_Howler$_howls2 = _Howler$_howls2[0]) === null || _Howler$_howls2 === void 0 ? void 0 : _Howler$_howls2._node;
47805
+ if (node_0) {
47806
+ setAudioEngine({
47807
+ // @ts-ignore-next-line
47808
+ source: audioContext.createMediaElementSource(node_0),
47809
+ audioContext: audioContext
47810
+ });
47811
+ }
47733
47812
  } else {
47734
47813
  setAudioEngine({
47735
47814
  source: import_howler.Howler.masterGain,
@@ -47749,8 +47828,8 @@ var useMessageAudio = function(_ref) {
47749
47828
  audioEngine
47750
47829
  ]);
47751
47830
  var isPending = (0, import_react67.useMemo)(function() {
47752
- return isPlaying || audioQueue.some(function(m_5) {
47753
- return !m_5.stopped && (m_5.nextIndex < m_5.sentences.length || m_5.status === "in_progress");
47831
+ return isPlaying || audioQueue.some(function(m_7) {
47832
+ return !m_7.stopped && (m_7.nextIndex < m_7.sentences.length || m_7.status === "in_progress");
47754
47833
  });
47755
47834
  }, [
47756
47835
  isPlaying,