@contentgrowth/llm-service 0.9.8 → 0.9.9
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.
|
@@ -167,6 +167,7 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
167
167
|
onResultRef.current = onResult;
|
|
168
168
|
onEndRef.current = onEnd;
|
|
169
169
|
}, [onResult, onEnd]);
|
|
170
|
+
const isStartingRef = useRef(false);
|
|
170
171
|
useEffect(() => {
|
|
171
172
|
if (typeof window !== "undefined") {
|
|
172
173
|
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
|
@@ -177,11 +178,13 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
177
178
|
recognition.interimResults = true;
|
|
178
179
|
recognition.onstart = () => {
|
|
179
180
|
console.log("[useSpeechRecognition] Native onstart event fired");
|
|
181
|
+
isStartingRef.current = false;
|
|
180
182
|
setIsListening(true);
|
|
181
183
|
setError(null);
|
|
182
184
|
};
|
|
183
185
|
recognition.onend = () => {
|
|
184
186
|
console.log("[useSpeechRecognition] Native onend event fired");
|
|
187
|
+
isStartingRef.current = false;
|
|
185
188
|
if (isSimulatingRef.current) {
|
|
186
189
|
return;
|
|
187
190
|
}
|
|
@@ -205,6 +208,7 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
205
208
|
};
|
|
206
209
|
recognition.onerror = (event) => {
|
|
207
210
|
console.error("[useSpeechRecognition] Native onerror event:", event.error);
|
|
211
|
+
isStartingRef.current = false;
|
|
208
212
|
if (event.error === "not-allowed" && process.env.NODE_ENV === "development") {
|
|
209
213
|
console.warn("Speech recognition blocked. Simulating input for development...");
|
|
210
214
|
isSimulatingRef.current = true;
|
|
@@ -252,14 +256,27 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
252
256
|
console.error("[useSpeechRecognition] Recognition instance missing");
|
|
253
257
|
return;
|
|
254
258
|
}
|
|
259
|
+
if (isStartingRef.current) {
|
|
260
|
+
console.warn("[useSpeechRecognition] Already starting - ignoring duplicate call");
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
if (recognitionRef.current.isListening) {
|
|
264
|
+
console.warn("[useSpeechRecognition] Already listening - ignoring");
|
|
265
|
+
}
|
|
266
|
+
if (isListening) {
|
|
267
|
+
console.warn("[useSpeechRecognition] App state says already listening - ignoring");
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
255
270
|
try {
|
|
256
271
|
setTranscript("");
|
|
272
|
+
isStartingRef.current = true;
|
|
257
273
|
recognitionRef.current.start();
|
|
258
274
|
console.log("[useSpeechRecognition] recognition.start() executed");
|
|
259
275
|
} catch (error2) {
|
|
276
|
+
isStartingRef.current = false;
|
|
260
277
|
console.error("[useSpeechRecognition] Failed to start recognition:", error2);
|
|
261
278
|
}
|
|
262
|
-
}, []);
|
|
279
|
+
}, [isListening]);
|
|
263
280
|
const stop = useCallback(() => {
|
|
264
281
|
console.log("[useSpeechRecognition] stop() called");
|
|
265
282
|
if (isSimulatingRef.current) {
|
|
@@ -888,58 +905,70 @@ var TapToTalk = ({
|
|
|
888
905
|
});
|
|
889
906
|
const isListening = !!voiceTrigger || nativeSpeech.isListening || customRecorder.isRecording;
|
|
890
907
|
const isActive = isListening || isTranscribing;
|
|
908
|
+
const processingRef = useRef4(false);
|
|
891
909
|
const toggleVoice = async () => {
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
if (now - tapCountRef.current.lastTap < 500) {
|
|
895
|
-
tapCountRef.current.count++;
|
|
896
|
-
} else {
|
|
897
|
-
tapCountRef.current.count = 1;
|
|
898
|
-
}
|
|
899
|
-
tapCountRef.current.lastTap = now;
|
|
900
|
-
if (tapCountRef.current.count >= 5) {
|
|
901
|
-
setShowDebug((prev) => !prev);
|
|
902
|
-
tapCountRef.current.count = 0;
|
|
903
|
-
if (isActive) {
|
|
904
|
-
console.log("[TapToTalk] Debug trigger force-stop");
|
|
905
|
-
if ((voiceConfig == null ? void 0 : voiceConfig.mode) === "native") nativeSpeech.stop();
|
|
906
|
-
else customRecorder.stop();
|
|
907
|
-
setVoiceTrigger(null);
|
|
908
|
-
}
|
|
910
|
+
if (processingRef.current) {
|
|
911
|
+
console.log("[TapToTalk] toggleVoice ignored - processing");
|
|
909
912
|
return;
|
|
910
913
|
}
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
if ((voiceConfig == null ? void 0 : voiceConfig.mode) === "native") {
|
|
918
|
-
nativeSpeech.stop();
|
|
914
|
+
processingRef.current = true;
|
|
915
|
+
console.log("[TapToTalk] toggleVoice called. isActive:", isActive);
|
|
916
|
+
try {
|
|
917
|
+
const now = Date.now();
|
|
918
|
+
if (now - tapCountRef.current.lastTap < 500) {
|
|
919
|
+
tapCountRef.current.count++;
|
|
919
920
|
} else {
|
|
920
|
-
|
|
921
|
+
tapCountRef.current.count = 1;
|
|
921
922
|
}
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
await customRecorder.start();
|
|
931
|
-
} catch (e) {
|
|
932
|
-
setErrorMsg("Mic access denied");
|
|
923
|
+
tapCountRef.current.lastTap = now;
|
|
924
|
+
if (tapCountRef.current.count >= 5) {
|
|
925
|
+
setShowDebug((prev) => !prev);
|
|
926
|
+
tapCountRef.current.count = 0;
|
|
927
|
+
if (isActive) {
|
|
928
|
+
console.log("[TapToTalk] Debug trigger force-stop");
|
|
929
|
+
if ((voiceConfig == null ? void 0 : voiceConfig.mode) === "native") nativeSpeech.stop();
|
|
930
|
+
else customRecorder.stop();
|
|
933
931
|
setVoiceTrigger(null);
|
|
934
932
|
}
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
933
|
+
return;
|
|
934
|
+
}
|
|
935
|
+
if (isActive) {
|
|
936
|
+
if (isTranscribing && !isListening) {
|
|
937
|
+
console.log("[TapToTalk] Ignoring click during transcription");
|
|
939
938
|
return;
|
|
940
939
|
}
|
|
941
|
-
|
|
940
|
+
console.log("[TapToTalk] Stopping voice...");
|
|
941
|
+
if ((voiceConfig == null ? void 0 : voiceConfig.mode) === "native") {
|
|
942
|
+
nativeSpeech.stop();
|
|
943
|
+
} else {
|
|
944
|
+
customRecorder.stop();
|
|
945
|
+
}
|
|
946
|
+
setVoiceTrigger(null);
|
|
947
|
+
} else {
|
|
948
|
+
console.log("[TapToTalk] Starting voice...");
|
|
949
|
+
setErrorMsg(null);
|
|
950
|
+
onFocusTarget == null ? void 0 : onFocusTarget();
|
|
951
|
+
setVoiceTrigger("click");
|
|
952
|
+
if ((voiceConfig == null ? void 0 : voiceConfig.mode) === "custom") {
|
|
953
|
+
try {
|
|
954
|
+
await customRecorder.start();
|
|
955
|
+
} catch (e) {
|
|
956
|
+
setErrorMsg("Mic access denied");
|
|
957
|
+
setVoiceTrigger(null);
|
|
958
|
+
}
|
|
959
|
+
} else {
|
|
960
|
+
if (!nativeSpeech.isSupported) {
|
|
961
|
+
setErrorMsg("Speech not supported");
|
|
962
|
+
setVoiceTrigger(null);
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
nativeSpeech.start();
|
|
966
|
+
}
|
|
942
967
|
}
|
|
968
|
+
} finally {
|
|
969
|
+
setTimeout(() => {
|
|
970
|
+
processingRef.current = false;
|
|
971
|
+
}, 300);
|
|
943
972
|
}
|
|
944
973
|
};
|
|
945
974
|
let bgColor = accentColor;
|