@contentgrowth/llm-service 0.9.4 → 0.9.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.
|
@@ -149,7 +149,7 @@ function ChatHeader({
|
|
|
149
149
|
|
|
150
150
|
// src/ui/react/components/ChatInputArea.tsx
|
|
151
151
|
import { useState as useState3, useRef as useRef3, useImperativeHandle, forwardRef, useEffect as useEffect3, useCallback as useCallback3, useLayoutEffect } from "react";
|
|
152
|
-
import { MicrophoneIcon, StopIcon, PaperAirplaneIcon, XMarkIcon } from "@heroicons/react/24/outline";
|
|
152
|
+
import { MicrophoneIcon, StopIcon, PaperAirplaneIcon, XMarkIcon, Square2StackIcon } from "@heroicons/react/24/outline";
|
|
153
153
|
|
|
154
154
|
// src/ui/react/hooks/useSpeechRecognition.ts
|
|
155
155
|
import { useState, useEffect, useCallback, useRef } from "react";
|
|
@@ -161,6 +161,12 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
161
161
|
const recognitionRef = useRef(null);
|
|
162
162
|
const isSimulatingRef = useRef(false);
|
|
163
163
|
const simulationTimeoutRef = useRef(null);
|
|
164
|
+
const onResultRef = useRef(onResult);
|
|
165
|
+
const onEndRef = useRef(onEnd);
|
|
166
|
+
useEffect(() => {
|
|
167
|
+
onResultRef.current = onResult;
|
|
168
|
+
onEndRef.current = onEnd;
|
|
169
|
+
}, [onResult, onEnd]);
|
|
164
170
|
useEffect(() => {
|
|
165
171
|
if (typeof window !== "undefined") {
|
|
166
172
|
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
|
@@ -179,7 +185,7 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
179
185
|
return;
|
|
180
186
|
}
|
|
181
187
|
setIsListening(false);
|
|
182
|
-
if (
|
|
188
|
+
if (onEndRef.current) onEndRef.current();
|
|
183
189
|
};
|
|
184
190
|
recognition.onresult = (event) => {
|
|
185
191
|
let interimTranscript = "";
|
|
@@ -188,10 +194,10 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
188
194
|
const result = event.results[i];
|
|
189
195
|
if (result.isFinal) {
|
|
190
196
|
finalTranscript += result[0].transcript;
|
|
191
|
-
if (
|
|
197
|
+
if (onResultRef.current) onResultRef.current(finalTranscript, true);
|
|
192
198
|
} else {
|
|
193
199
|
interimTranscript += result[0].transcript;
|
|
194
|
-
if (
|
|
200
|
+
if (onResultRef.current) onResultRef.current(interimTranscript, false);
|
|
195
201
|
}
|
|
196
202
|
}
|
|
197
203
|
setTranscript((prev) => prev + finalTranscript);
|
|
@@ -206,10 +212,10 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
206
212
|
simulationTimeoutRef.current = setTimeout(() => {
|
|
207
213
|
const mockText = "This is a simulated voice input for testing.";
|
|
208
214
|
setTranscript((prev) => prev + (prev ? " " : "") + mockText);
|
|
209
|
-
if (
|
|
215
|
+
if (onResultRef.current) onResultRef.current(mockText, true);
|
|
210
216
|
isSimulatingRef.current = false;
|
|
211
217
|
setIsListening(false);
|
|
212
|
-
if (
|
|
218
|
+
if (onEndRef.current) onEndRef.current();
|
|
213
219
|
simulationTimeoutRef.current = null;
|
|
214
220
|
}, 3e3);
|
|
215
221
|
return;
|
|
@@ -226,9 +232,11 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
226
232
|
clearTimeout(simulationTimeoutRef.current);
|
|
227
233
|
simulationTimeoutRef.current = null;
|
|
228
234
|
}
|
|
229
|
-
recognitionRef.current
|
|
235
|
+
if (recognitionRef.current) {
|
|
236
|
+
recognitionRef.current.stop();
|
|
237
|
+
}
|
|
230
238
|
};
|
|
231
|
-
}, [
|
|
239
|
+
}, [language]);
|
|
232
240
|
const start = useCallback(() => {
|
|
233
241
|
if (recognitionRef.current && !isListening) {
|
|
234
242
|
try {
|
|
@@ -248,10 +256,10 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
248
256
|
}
|
|
249
257
|
const mockText = "This is a simulated voice input for testing.";
|
|
250
258
|
setTranscript((prev) => prev + (prev ? " " : "") + mockText);
|
|
251
|
-
if (
|
|
259
|
+
if (onResultRef.current) onResultRef.current(mockText, true);
|
|
252
260
|
isSimulatingRef.current = false;
|
|
253
261
|
setIsListening(false);
|
|
254
|
-
if (
|
|
262
|
+
if (onEndRef.current) onEndRef.current();
|
|
255
263
|
return;
|
|
256
264
|
}
|
|
257
265
|
if (recognitionRef.current && isListening) {
|
|
@@ -423,6 +431,9 @@ var ChatInputArea = forwardRef(({
|
|
|
423
431
|
console.error = originalError;
|
|
424
432
|
};
|
|
425
433
|
}, []);
|
|
434
|
+
const copyLogs = useCallback3(() => {
|
|
435
|
+
navigator.clipboard.writeText(logs.join("\n")).then(() => alert("Logs copied to clipboard")).catch((err) => console.error("Failed to copy logs", err));
|
|
436
|
+
}, [logs]);
|
|
426
437
|
const textareaRef = useRef3(null);
|
|
427
438
|
const measurementRef = useRef3(null);
|
|
428
439
|
const pendingSelectionRef = useRef3(null);
|
|
@@ -615,7 +626,13 @@ var ChatInputArea = forwardRef(({
|
|
|
615
626
|
showDebug && /* @__PURE__ */ jsxs3("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: [
|
|
616
627
|
/* @__PURE__ */ jsxs3("div", { className: "flex justify-between items-center bg-gray-800 p-1 mb-1", children: [
|
|
617
628
|
/* @__PURE__ */ jsx5("span", { children: "Debug Logs" }),
|
|
618
|
-
/* @__PURE__ */
|
|
629
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex gap-2", children: [
|
|
630
|
+
/* @__PURE__ */ jsx5("button", { onClick: copyLogs, className: "text-white hover:text-blue-400", title: "Copy Logs", children: /* @__PURE__ */ jsx5(Square2StackIcon, { className: "w-4 h-4" }) }),
|
|
631
|
+
/* @__PURE__ */ jsx5("button", { onClick: () => {
|
|
632
|
+
copyLogs();
|
|
633
|
+
setShowDebug(false);
|
|
634
|
+
}, className: "text-white hover:text-red-400", title: "Copy & Close", children: /* @__PURE__ */ jsx5(XMarkIcon, { className: "w-4 h-4" }) })
|
|
635
|
+
] })
|
|
619
636
|
] }),
|
|
620
637
|
logs.map((log, i) => /* @__PURE__ */ jsx5("div", { className: "mb-0.5 border-b border-gray-700/50 pb-0.5 break-all", children: log }, i)),
|
|
621
638
|
logs.length === 0 && /* @__PURE__ */ jsx5("div", { children: "No logs yet..." })
|
|
@@ -636,6 +653,7 @@ var ChatInputArea = forwardRef(({
|
|
|
636
653
|
if (tapCountRef.current.count >= 5) {
|
|
637
654
|
setShowDebug((prev) => !prev);
|
|
638
655
|
tapCountRef.current.count = 0;
|
|
656
|
+
stopRecording();
|
|
639
657
|
return;
|
|
640
658
|
}
|
|
641
659
|
if (voiceTrigger) {
|
|
@@ -757,7 +775,7 @@ ChatInputArea.displayName = "ChatInputArea";
|
|
|
757
775
|
|
|
758
776
|
// src/ui/react/components/TapToTalk.tsx
|
|
759
777
|
import React3, { useState as useState4, useCallback as useCallback4, useRef as useRef4 } from "react";
|
|
760
|
-
import { MicrophoneIcon as MicrophoneIcon2, XMarkIcon as XMarkIcon2 } from "@heroicons/react/24/outline";
|
|
778
|
+
import { MicrophoneIcon as MicrophoneIcon2, XMarkIcon as XMarkIcon2, Square2StackIcon as Square2StackIcon2 } from "@heroicons/react/24/outline";
|
|
761
779
|
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
762
780
|
var TapToTalk = ({
|
|
763
781
|
onResult,
|
|
@@ -810,6 +828,9 @@ var TapToTalk = ({
|
|
|
810
828
|
console.error = originalError;
|
|
811
829
|
};
|
|
812
830
|
}, []);
|
|
831
|
+
const copyLogs = useCallback4(() => {
|
|
832
|
+
navigator.clipboard.writeText(logs.join("\n")).then(() => alert("Logs copied to clipboard")).catch((err) => console.error("Failed to copy logs", err));
|
|
833
|
+
}, [logs]);
|
|
813
834
|
const handleVoiceResult = useCallback4((text, isFinal) => {
|
|
814
835
|
if (isFinal) {
|
|
815
836
|
onResult(text);
|
|
@@ -865,6 +886,11 @@ var TapToTalk = ({
|
|
|
865
886
|
if (tapCountRef.current.count >= 5) {
|
|
866
887
|
setShowDebug((prev) => !prev);
|
|
867
888
|
tapCountRef.current.count = 0;
|
|
889
|
+
if (isActive) {
|
|
890
|
+
if ((voiceConfig == null ? void 0 : voiceConfig.mode) === "native") nativeSpeech.stop();
|
|
891
|
+
else customRecorder.stop();
|
|
892
|
+
setVoiceTrigger(null);
|
|
893
|
+
}
|
|
868
894
|
return;
|
|
869
895
|
}
|
|
870
896
|
if (isActive) {
|
|
@@ -915,10 +941,17 @@ var TapToTalk = ({
|
|
|
915
941
|
showDebug && /* @__PURE__ */ jsxs4("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: [
|
|
916
942
|
/* @__PURE__ */ jsxs4("div", { className: "flex justify-between items-center bg-gray-800 p-1 mb-1", children: [
|
|
917
943
|
/* @__PURE__ */ jsx6("span", { children: "Debug Logs" }),
|
|
918
|
-
/* @__PURE__ */
|
|
919
|
-
e
|
|
920
|
-
|
|
921
|
-
|
|
944
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex gap-2", children: [
|
|
945
|
+
/* @__PURE__ */ jsx6("button", { onClick: (e) => {
|
|
946
|
+
e.stopPropagation();
|
|
947
|
+
copyLogs();
|
|
948
|
+
}, className: "text-white hover:text-blue-400", title: "Copy Logs", children: /* @__PURE__ */ jsx6(Square2StackIcon2, { className: "w-4 h-4" }) }),
|
|
949
|
+
/* @__PURE__ */ jsx6("button", { onClick: (e) => {
|
|
950
|
+
e.stopPropagation();
|
|
951
|
+
copyLogs();
|
|
952
|
+
setShowDebug(false);
|
|
953
|
+
}, className: "text-white hover:text-red-400", title: "Copy & Close", children: /* @__PURE__ */ jsx6(XMarkIcon2, { className: "w-4 h-4" }) })
|
|
954
|
+
] })
|
|
922
955
|
] }),
|
|
923
956
|
logs.map((log, i) => /* @__PURE__ */ jsx6("div", { className: "mb-0.5 border-b border-gray-700/50 pb-0.5 break-all", children: log }, i)),
|
|
924
957
|
logs.length === 0 && /* @__PURE__ */ jsx6("div", { children: "No logs yet..." })
|