@contentgrowth/llm-service 0.9.3 → 0.9.5
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.
|
@@ -203,6 +203,12 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
203
203
|
const recognitionRef = (0, import_react2.useRef)(null);
|
|
204
204
|
const isSimulatingRef = (0, import_react2.useRef)(false);
|
|
205
205
|
const simulationTimeoutRef = (0, import_react2.useRef)(null);
|
|
206
|
+
const onResultRef = (0, import_react2.useRef)(onResult);
|
|
207
|
+
const onEndRef = (0, import_react2.useRef)(onEnd);
|
|
208
|
+
(0, import_react2.useEffect)(() => {
|
|
209
|
+
onResultRef.current = onResult;
|
|
210
|
+
onEndRef.current = onEnd;
|
|
211
|
+
}, [onResult, onEnd]);
|
|
206
212
|
(0, import_react2.useEffect)(() => {
|
|
207
213
|
if (typeof window !== "undefined") {
|
|
208
214
|
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
|
@@ -221,7 +227,7 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
221
227
|
return;
|
|
222
228
|
}
|
|
223
229
|
setIsListening(false);
|
|
224
|
-
if (
|
|
230
|
+
if (onEndRef.current) onEndRef.current();
|
|
225
231
|
};
|
|
226
232
|
recognition.onresult = (event) => {
|
|
227
233
|
let interimTranscript = "";
|
|
@@ -230,10 +236,10 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
230
236
|
const result = event.results[i];
|
|
231
237
|
if (result.isFinal) {
|
|
232
238
|
finalTranscript += result[0].transcript;
|
|
233
|
-
if (
|
|
239
|
+
if (onResultRef.current) onResultRef.current(finalTranscript, true);
|
|
234
240
|
} else {
|
|
235
241
|
interimTranscript += result[0].transcript;
|
|
236
|
-
if (
|
|
242
|
+
if (onResultRef.current) onResultRef.current(interimTranscript, false);
|
|
237
243
|
}
|
|
238
244
|
}
|
|
239
245
|
setTranscript((prev) => prev + finalTranscript);
|
|
@@ -248,10 +254,10 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
248
254
|
simulationTimeoutRef.current = setTimeout(() => {
|
|
249
255
|
const mockText = "This is a simulated voice input for testing.";
|
|
250
256
|
setTranscript((prev) => prev + (prev ? " " : "") + mockText);
|
|
251
|
-
if (
|
|
257
|
+
if (onResultRef.current) onResultRef.current(mockText, true);
|
|
252
258
|
isSimulatingRef.current = false;
|
|
253
259
|
setIsListening(false);
|
|
254
|
-
if (
|
|
260
|
+
if (onEndRef.current) onEndRef.current();
|
|
255
261
|
simulationTimeoutRef.current = null;
|
|
256
262
|
}, 3e3);
|
|
257
263
|
return;
|
|
@@ -268,9 +274,11 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
268
274
|
clearTimeout(simulationTimeoutRef.current);
|
|
269
275
|
simulationTimeoutRef.current = null;
|
|
270
276
|
}
|
|
271
|
-
recognitionRef.current
|
|
277
|
+
if (recognitionRef.current) {
|
|
278
|
+
recognitionRef.current.stop();
|
|
279
|
+
}
|
|
272
280
|
};
|
|
273
|
-
}, [
|
|
281
|
+
}, [language]);
|
|
274
282
|
const start = (0, import_react2.useCallback)(() => {
|
|
275
283
|
if (recognitionRef.current && !isListening) {
|
|
276
284
|
try {
|
|
@@ -290,10 +298,10 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
290
298
|
}
|
|
291
299
|
const mockText = "This is a simulated voice input for testing.";
|
|
292
300
|
setTranscript((prev) => prev + (prev ? " " : "") + mockText);
|
|
293
|
-
if (
|
|
301
|
+
if (onResultRef.current) onResultRef.current(mockText, true);
|
|
294
302
|
isSimulatingRef.current = false;
|
|
295
303
|
setIsListening(false);
|
|
296
|
-
if (
|
|
304
|
+
if (onEndRef.current) onEndRef.current();
|
|
297
305
|
return;
|
|
298
306
|
}
|
|
299
307
|
if (recognitionRef.current && isListening) {
|
|
@@ -429,6 +437,42 @@ var ChatInputArea = (0, import_react5.forwardRef)(({
|
|
|
429
437
|
const [isTranscribing, setIsTranscribing] = (0, import_react5.useState)(false);
|
|
430
438
|
const [voiceError, setVoiceError] = (0, import_react5.useState)(null);
|
|
431
439
|
const [isFocused, setIsFocused] = (0, import_react5.useState)(false);
|
|
440
|
+
const [showDebug, setShowDebug] = (0, import_react5.useState)(false);
|
|
441
|
+
const [logs, setLogs] = (0, import_react5.useState)([]);
|
|
442
|
+
const tapCountRef = (0, import_react5.useRef)({ count: 0, lastTap: 0 });
|
|
443
|
+
(0, import_react5.useEffect)(() => {
|
|
444
|
+
const originalLog = console.log;
|
|
445
|
+
const originalWarn = console.warn;
|
|
446
|
+
const originalError = console.error;
|
|
447
|
+
const addLog = (type, args) => {
|
|
448
|
+
try {
|
|
449
|
+
const msg = args.map((arg) => {
|
|
450
|
+
if (arg instanceof Error) return `${arg.name}: ${arg.message}`;
|
|
451
|
+
if (typeof arg === "object") return JSON.stringify(arg);
|
|
452
|
+
return String(arg);
|
|
453
|
+
}).join(" ");
|
|
454
|
+
setLogs((prev) => [`[${type}] ${msg}`, ...prev].slice(0, 50));
|
|
455
|
+
} catch (e) {
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
console.log = (...args) => {
|
|
459
|
+
originalLog(...args);
|
|
460
|
+
addLog("LOG", args);
|
|
461
|
+
};
|
|
462
|
+
console.warn = (...args) => {
|
|
463
|
+
originalWarn(...args);
|
|
464
|
+
addLog("WRN", args);
|
|
465
|
+
};
|
|
466
|
+
console.error = (...args) => {
|
|
467
|
+
originalError(...args);
|
|
468
|
+
addLog("ERR", args);
|
|
469
|
+
};
|
|
470
|
+
return () => {
|
|
471
|
+
console.log = originalLog;
|
|
472
|
+
console.warn = originalWarn;
|
|
473
|
+
console.error = originalError;
|
|
474
|
+
};
|
|
475
|
+
}, []);
|
|
432
476
|
const textareaRef = (0, import_react5.useRef)(null);
|
|
433
477
|
const measurementRef = (0, import_react5.useRef)(null);
|
|
434
478
|
const pendingSelectionRef = (0, import_react5.useRef)(null);
|
|
@@ -498,6 +542,12 @@ var ChatInputArea = (0, import_react5.forwardRef)(({
|
|
|
498
542
|
(_b2 = (_a2 = voiceConfigRef.current) == null ? void 0 : _a2.onVoiceEnd) == null ? void 0 : _b2.call(_a2);
|
|
499
543
|
}, []);
|
|
500
544
|
const nativeSpeech = useSpeechRecognition(handleVoiceResult, handleVoiceEnd, voiceConfig == null ? void 0 : voiceConfig.language);
|
|
545
|
+
(0, import_react5.useEffect)(() => {
|
|
546
|
+
if (nativeSpeech.error) {
|
|
547
|
+
setVoiceError(nativeSpeech.error);
|
|
548
|
+
console.error("[ChatInputArea] Native Speech Error:", nativeSpeech.error);
|
|
549
|
+
}
|
|
550
|
+
}, [nativeSpeech.error]);
|
|
501
551
|
const customRecorder = useAudioRecorder(async (blob) => {
|
|
502
552
|
var _a2, _b2, _c2;
|
|
503
553
|
setVoiceTrigger(null);
|
|
@@ -611,20 +661,40 @@ var ChatInputArea = (0, import_react5.forwardRef)(({
|
|
|
611
661
|
if (!showInputForm) {
|
|
612
662
|
return null;
|
|
613
663
|
}
|
|
614
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col w-full", children: [
|
|
664
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col w-full relative", children: [
|
|
665
|
+
showDebug && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "absolute bottom-full left-0 right-0 mb-2 p-2 bg-black/80 text-green-400 text-xs font-mono h-48 overflow-y-auto rounded z-50 pointer-events-auto", children: [
|
|
666
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex justify-between items-center bg-gray-800 p-1 mb-1", children: [
|
|
667
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Debug Logs" }),
|
|
668
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { onClick: () => setShowDebug(false), className: "text-white hover:text-red-400", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_outline.XMarkIcon, { className: "w-4 h-4" }) })
|
|
669
|
+
] }),
|
|
670
|
+
logs.map((log, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mb-0.5 border-b border-gray-700/50 pb-0.5 break-all", children: log }, i)),
|
|
671
|
+
logs.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { children: "No logs yet..." })
|
|
672
|
+
] }),
|
|
615
673
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
616
674
|
voiceConfig && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
617
675
|
"button",
|
|
618
676
|
{
|
|
619
677
|
type: "button",
|
|
620
678
|
onClick: () => {
|
|
679
|
+
const now = Date.now();
|
|
680
|
+
if (now - tapCountRef.current.lastTap < 500) {
|
|
681
|
+
tapCountRef.current.count++;
|
|
682
|
+
} else {
|
|
683
|
+
tapCountRef.current.count = 1;
|
|
684
|
+
}
|
|
685
|
+
tapCountRef.current.lastTap = now;
|
|
686
|
+
if (tapCountRef.current.count >= 5) {
|
|
687
|
+
setShowDebug((prev) => !prev);
|
|
688
|
+
tapCountRef.current.count = 0;
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
621
691
|
if (voiceTrigger) {
|
|
622
692
|
stopRecording();
|
|
623
693
|
} else if (!isTranscribing) {
|
|
624
694
|
startRecording("click");
|
|
625
695
|
}
|
|
626
696
|
},
|
|
627
|
-
className: `mb-1 p-2 rounded-full transition-all duration-300 flex-shrink-0 border ${
|
|
697
|
+
className: `mb-1 p-2 rounded-full transition-all duration-300 flex-shrink-0 border ${isTranscribing ? "text-white border-indigo-500 bg-indigo-600 scale-110 shadow-lg" : voiceTrigger ? "text-white border-orange-400 bg-orange-500 scale-110 shadow-lg" : "text-gray-500 border-gray-300 bg-white hover:text-gray-700 hover:bg-gray-100"} ${voiceTrigger ? "animate-pulse" : ""} ${isTranscribing ? "cursor-wait" : ""}`,
|
|
628
698
|
disabled: isTranscribing,
|
|
629
699
|
title: isTranscribing ? "Transcribing..." : voiceTrigger ? "Stop Recording" : "Start Voice Input",
|
|
630
700
|
children: isTranscribing ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "animate-spin w-5 h-5 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { className: "w-5 h-5 text-white", viewBox: "0 0 24 24", children: [
|
|
@@ -727,16 +797,16 @@ var ChatInputArea = (0, import_react5.forwardRef)(({
|
|
|
727
797
|
)
|
|
728
798
|
] }),
|
|
729
799
|
inputHint && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "text-sm text-red-500 bg-red-50 py-1 px-4 rounded-lg mt-1", children: inputHint }),
|
|
730
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "ml-[46px] mb-2 mt-0.5 min-h-[0.75rem]", style: { marginLeft: "48px" }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: `text-[10px] leading-tight transition-all duration-200 ${voiceError ? "text-red-500" :
|
|
800
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "ml-[46px] mb-2 mt-0.5 min-h-[0.75rem]", style: { marginLeft: "48px" }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: `text-[10px] leading-tight transition-all duration-200 ${voiceError ? "text-red-500" : isTranscribing ? "text-indigo-600 font-bold" : voiceTrigger ? "text-orange-600 font-medium" : "text-gray-400"}`, children: voiceError ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "flex items-center gap-1 font-semibold italic", children: [
|
|
731
801
|
"Error: ",
|
|
732
802
|
voiceError
|
|
733
|
-
] }) : isTranscribing ? "Transcribing, please wait..." : voiceTrigger ? "Listening... tap mic icon again to stop" : hintText || (voiceConfig ? "Type in text or tap mic icon to talk" : "Type your message...") }) })
|
|
803
|
+
] }) : isTranscribing ? "Transcribing... please wait" : voiceTrigger ? "Transcribing, please wait..." : voiceTrigger ? "Listening... tap mic icon again to stop" : hintText || (voiceConfig ? "Type in text or tap mic icon to talk" : "Type your message...") }) })
|
|
734
804
|
] });
|
|
735
805
|
});
|
|
736
806
|
ChatInputArea.displayName = "ChatInputArea";
|
|
737
807
|
|
|
738
808
|
// src/ui/react/components/TapToTalk.tsx
|
|
739
|
-
var import_react6 = require("react");
|
|
809
|
+
var import_react6 = __toESM(require("react"), 1);
|
|
740
810
|
var import_outline2 = require("@heroicons/react/24/outline");
|
|
741
811
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
742
812
|
var TapToTalk = ({
|
|
@@ -754,6 +824,42 @@ var TapToTalk = ({
|
|
|
754
824
|
const [isTranscribing, setIsTranscribing] = (0, import_react6.useState)(false);
|
|
755
825
|
const [voiceTrigger, setVoiceTrigger] = (0, import_react6.useState)(null);
|
|
756
826
|
const [errorMsg, setErrorMsg] = (0, import_react6.useState)(null);
|
|
827
|
+
const [showDebug, setShowDebug] = (0, import_react6.useState)(false);
|
|
828
|
+
const [logs, setLogs] = (0, import_react6.useState)([]);
|
|
829
|
+
const tapCountRef = (0, import_react6.useRef)({ count: 0, lastTap: 0 });
|
|
830
|
+
import_react6.default.useEffect(() => {
|
|
831
|
+
const originalLog = console.log;
|
|
832
|
+
const originalWarn = console.warn;
|
|
833
|
+
const originalError = console.error;
|
|
834
|
+
const addLog = (type, args) => {
|
|
835
|
+
try {
|
|
836
|
+
const msg = args.map((arg) => {
|
|
837
|
+
if (arg instanceof Error) return `${arg.name}: ${arg.message}`;
|
|
838
|
+
if (typeof arg === "object") return JSON.stringify(arg);
|
|
839
|
+
return String(arg);
|
|
840
|
+
}).join(" ");
|
|
841
|
+
setLogs((prev) => [`[${type}] ${msg}`, ...prev].slice(0, 50));
|
|
842
|
+
} catch (e) {
|
|
843
|
+
}
|
|
844
|
+
};
|
|
845
|
+
console.log = (...args) => {
|
|
846
|
+
originalLog(...args);
|
|
847
|
+
addLog("LOG", args);
|
|
848
|
+
};
|
|
849
|
+
console.warn = (...args) => {
|
|
850
|
+
originalWarn(...args);
|
|
851
|
+
addLog("WRN", args);
|
|
852
|
+
};
|
|
853
|
+
console.error = (...args) => {
|
|
854
|
+
originalError(...args);
|
|
855
|
+
addLog("ERR", args);
|
|
856
|
+
};
|
|
857
|
+
return () => {
|
|
858
|
+
console.log = originalLog;
|
|
859
|
+
console.warn = originalWarn;
|
|
860
|
+
console.error = originalError;
|
|
861
|
+
};
|
|
862
|
+
}, []);
|
|
757
863
|
const handleVoiceResult = (0, import_react6.useCallback)((text, isFinal) => {
|
|
758
864
|
if (isFinal) {
|
|
759
865
|
onResult(text);
|
|
@@ -765,6 +871,12 @@ var TapToTalk = ({
|
|
|
765
871
|
setVoiceTrigger(null);
|
|
766
872
|
}, []);
|
|
767
873
|
const nativeSpeech = useSpeechRecognition(handleVoiceResult, handleVoiceEnd, voiceConfig == null ? void 0 : voiceConfig.language);
|
|
874
|
+
import_react6.default.useEffect(() => {
|
|
875
|
+
if (nativeSpeech.error) {
|
|
876
|
+
setErrorMsg(nativeSpeech.error);
|
|
877
|
+
console.error("[TapToTalk] Native Speech Error:", nativeSpeech.error);
|
|
878
|
+
}
|
|
879
|
+
}, [nativeSpeech.error]);
|
|
768
880
|
const customRecorder = useAudioRecorder(async (blob) => {
|
|
769
881
|
setVoiceTrigger(null);
|
|
770
882
|
setIsTranscribing(true);
|
|
@@ -793,6 +905,18 @@ var TapToTalk = ({
|
|
|
793
905
|
const isListening = !!voiceTrigger || nativeSpeech.isListening || customRecorder.isRecording;
|
|
794
906
|
const isActive = isListening || isTranscribing;
|
|
795
907
|
const toggleVoice = async () => {
|
|
908
|
+
const now = Date.now();
|
|
909
|
+
if (now - tapCountRef.current.lastTap < 500) {
|
|
910
|
+
tapCountRef.current.count++;
|
|
911
|
+
} else {
|
|
912
|
+
tapCountRef.current.count = 1;
|
|
913
|
+
}
|
|
914
|
+
tapCountRef.current.lastTap = now;
|
|
915
|
+
if (tapCountRef.current.count >= 5) {
|
|
916
|
+
setShowDebug((prev) => !prev);
|
|
917
|
+
tapCountRef.current.count = 0;
|
|
918
|
+
return;
|
|
919
|
+
}
|
|
796
920
|
if (isActive) {
|
|
797
921
|
if (isTranscribing && !isListening) return;
|
|
798
922
|
if ((voiceConfig == null ? void 0 : voiceConfig.mode) === "native") {
|
|
@@ -830,30 +954,43 @@ var TapToTalk = ({
|
|
|
830
954
|
label = "Listening ... Tap to stop";
|
|
831
955
|
Icon = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_outline2.MicrophoneIcon, { className: "h-5 w-5 animate-pulse" });
|
|
832
956
|
} else if (isTranscribing) {
|
|
833
|
-
bgColor = "bg-
|
|
957
|
+
bgColor = "bg-indigo-600";
|
|
834
958
|
label = "Transcribing ...";
|
|
835
959
|
Icon = /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { className: "animate-spin h-5 w-5 text-white", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
|
|
836
960
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
|
|
837
961
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
|
|
838
962
|
] });
|
|
839
963
|
}
|
|
840
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
841
|
-
"
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
964
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-col w-full relative", children: [
|
|
965
|
+
showDebug && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "absolute bottom-full left-0 right-0 mb-2 p-2 bg-black/80 text-green-400 text-xs font-mono h-48 overflow-y-auto rounded z-50 pointer-events-auto", children: [
|
|
966
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex justify-between items-center bg-gray-800 p-1 mb-1", children: [
|
|
967
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Debug Logs" }),
|
|
968
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { onClick: (e) => {
|
|
969
|
+
e.stopPropagation();
|
|
970
|
+
setShowDebug(false);
|
|
971
|
+
}, className: "text-white hover:text-red-400", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_outline2.XMarkIcon, { className: "w-4 h-4" }) })
|
|
972
|
+
] }),
|
|
973
|
+
logs.map((log, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mb-0.5 border-b border-gray-700/50 pb-0.5 break-all", children: log }, i)),
|
|
974
|
+
logs.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { children: "No logs yet..." })
|
|
975
|
+
] }),
|
|
976
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
977
|
+
"button",
|
|
978
|
+
{
|
|
979
|
+
onClick: toggleVoice,
|
|
980
|
+
disabled: disabled || isTranscribing && !isListening,
|
|
981
|
+
className: `flex items-center justify-center gap-3 px-6 py-3 rounded-xl transition-all duration-300 w-full font-medium shadow-md active:scale-[0.98]
|
|
846
982
|
${bgColor} text-white
|
|
847
983
|
${disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}
|
|
848
984
|
${className}`,
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
985
|
+
title: label,
|
|
986
|
+
children: [
|
|
987
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex items-center justify-center shrink-0", children: Icon }),
|
|
988
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate", children: label }),
|
|
989
|
+
errorMsg && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[10px] bg-white/20 px-1.5 py-0.5 rounded text-red-100 animate-in fade-in slide-in-from-right-1", children: errorMsg })
|
|
990
|
+
]
|
|
991
|
+
}
|
|
992
|
+
)
|
|
993
|
+
] });
|
|
857
994
|
};
|
|
858
995
|
|
|
859
996
|
// src/ui/react/components/ChatMessageList.tsx
|