@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.
|
@@ -209,6 +209,7 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
209
209
|
onResultRef.current = onResult;
|
|
210
210
|
onEndRef.current = onEnd;
|
|
211
211
|
}, [onResult, onEnd]);
|
|
212
|
+
const isStartingRef = (0, import_react2.useRef)(false);
|
|
212
213
|
(0, import_react2.useEffect)(() => {
|
|
213
214
|
if (typeof window !== "undefined") {
|
|
214
215
|
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
|
@@ -219,11 +220,13 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
219
220
|
recognition.interimResults = true;
|
|
220
221
|
recognition.onstart = () => {
|
|
221
222
|
console.log("[useSpeechRecognition] Native onstart event fired");
|
|
223
|
+
isStartingRef.current = false;
|
|
222
224
|
setIsListening(true);
|
|
223
225
|
setError(null);
|
|
224
226
|
};
|
|
225
227
|
recognition.onend = () => {
|
|
226
228
|
console.log("[useSpeechRecognition] Native onend event fired");
|
|
229
|
+
isStartingRef.current = false;
|
|
227
230
|
if (isSimulatingRef.current) {
|
|
228
231
|
return;
|
|
229
232
|
}
|
|
@@ -247,6 +250,7 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
247
250
|
};
|
|
248
251
|
recognition.onerror = (event) => {
|
|
249
252
|
console.error("[useSpeechRecognition] Native onerror event:", event.error);
|
|
253
|
+
isStartingRef.current = false;
|
|
250
254
|
if (event.error === "not-allowed" && process.env.NODE_ENV === "development") {
|
|
251
255
|
console.warn("Speech recognition blocked. Simulating input for development...");
|
|
252
256
|
isSimulatingRef.current = true;
|
|
@@ -294,14 +298,27 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
294
298
|
console.error("[useSpeechRecognition] Recognition instance missing");
|
|
295
299
|
return;
|
|
296
300
|
}
|
|
301
|
+
if (isStartingRef.current) {
|
|
302
|
+
console.warn("[useSpeechRecognition] Already starting - ignoring duplicate call");
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
if (recognitionRef.current.isListening) {
|
|
306
|
+
console.warn("[useSpeechRecognition] Already listening - ignoring");
|
|
307
|
+
}
|
|
308
|
+
if (isListening) {
|
|
309
|
+
console.warn("[useSpeechRecognition] App state says already listening - ignoring");
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
297
312
|
try {
|
|
298
313
|
setTranscript("");
|
|
314
|
+
isStartingRef.current = true;
|
|
299
315
|
recognitionRef.current.start();
|
|
300
316
|
console.log("[useSpeechRecognition] recognition.start() executed");
|
|
301
317
|
} catch (error2) {
|
|
318
|
+
isStartingRef.current = false;
|
|
302
319
|
console.error("[useSpeechRecognition] Failed to start recognition:", error2);
|
|
303
320
|
}
|
|
304
|
-
}, []);
|
|
321
|
+
}, [isListening]);
|
|
305
322
|
const stop = (0, import_react2.useCallback)(() => {
|
|
306
323
|
console.log("[useSpeechRecognition] stop() called");
|
|
307
324
|
if (isSimulatingRef.current) {
|
|
@@ -930,58 +947,70 @@ var TapToTalk = ({
|
|
|
930
947
|
});
|
|
931
948
|
const isListening = !!voiceTrigger || nativeSpeech.isListening || customRecorder.isRecording;
|
|
932
949
|
const isActive = isListening || isTranscribing;
|
|
950
|
+
const processingRef = (0, import_react6.useRef)(false);
|
|
933
951
|
const toggleVoice = async () => {
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
if (now - tapCountRef.current.lastTap < 500) {
|
|
937
|
-
tapCountRef.current.count++;
|
|
938
|
-
} else {
|
|
939
|
-
tapCountRef.current.count = 1;
|
|
940
|
-
}
|
|
941
|
-
tapCountRef.current.lastTap = now;
|
|
942
|
-
if (tapCountRef.current.count >= 5) {
|
|
943
|
-
setShowDebug((prev) => !prev);
|
|
944
|
-
tapCountRef.current.count = 0;
|
|
945
|
-
if (isActive) {
|
|
946
|
-
console.log("[TapToTalk] Debug trigger force-stop");
|
|
947
|
-
if ((voiceConfig == null ? void 0 : voiceConfig.mode) === "native") nativeSpeech.stop();
|
|
948
|
-
else customRecorder.stop();
|
|
949
|
-
setVoiceTrigger(null);
|
|
950
|
-
}
|
|
952
|
+
if (processingRef.current) {
|
|
953
|
+
console.log("[TapToTalk] toggleVoice ignored - processing");
|
|
951
954
|
return;
|
|
952
955
|
}
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
if ((voiceConfig == null ? void 0 : voiceConfig.mode) === "native") {
|
|
960
|
-
nativeSpeech.stop();
|
|
956
|
+
processingRef.current = true;
|
|
957
|
+
console.log("[TapToTalk] toggleVoice called. isActive:", isActive);
|
|
958
|
+
try {
|
|
959
|
+
const now = Date.now();
|
|
960
|
+
if (now - tapCountRef.current.lastTap < 500) {
|
|
961
|
+
tapCountRef.current.count++;
|
|
961
962
|
} else {
|
|
962
|
-
|
|
963
|
+
tapCountRef.current.count = 1;
|
|
963
964
|
}
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
await customRecorder.start();
|
|
973
|
-
} catch (e) {
|
|
974
|
-
setErrorMsg("Mic access denied");
|
|
965
|
+
tapCountRef.current.lastTap = now;
|
|
966
|
+
if (tapCountRef.current.count >= 5) {
|
|
967
|
+
setShowDebug((prev) => !prev);
|
|
968
|
+
tapCountRef.current.count = 0;
|
|
969
|
+
if (isActive) {
|
|
970
|
+
console.log("[TapToTalk] Debug trigger force-stop");
|
|
971
|
+
if ((voiceConfig == null ? void 0 : voiceConfig.mode) === "native") nativeSpeech.stop();
|
|
972
|
+
else customRecorder.stop();
|
|
975
973
|
setVoiceTrigger(null);
|
|
976
974
|
}
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
if (isActive) {
|
|
978
|
+
if (isTranscribing && !isListening) {
|
|
979
|
+
console.log("[TapToTalk] Ignoring click during transcription");
|
|
981
980
|
return;
|
|
982
981
|
}
|
|
983
|
-
|
|
982
|
+
console.log("[TapToTalk] Stopping voice...");
|
|
983
|
+
if ((voiceConfig == null ? void 0 : voiceConfig.mode) === "native") {
|
|
984
|
+
nativeSpeech.stop();
|
|
985
|
+
} else {
|
|
986
|
+
customRecorder.stop();
|
|
987
|
+
}
|
|
988
|
+
setVoiceTrigger(null);
|
|
989
|
+
} else {
|
|
990
|
+
console.log("[TapToTalk] Starting voice...");
|
|
991
|
+
setErrorMsg(null);
|
|
992
|
+
onFocusTarget == null ? void 0 : onFocusTarget();
|
|
993
|
+
setVoiceTrigger("click");
|
|
994
|
+
if ((voiceConfig == null ? void 0 : voiceConfig.mode) === "custom") {
|
|
995
|
+
try {
|
|
996
|
+
await customRecorder.start();
|
|
997
|
+
} catch (e) {
|
|
998
|
+
setErrorMsg("Mic access denied");
|
|
999
|
+
setVoiceTrigger(null);
|
|
1000
|
+
}
|
|
1001
|
+
} else {
|
|
1002
|
+
if (!nativeSpeech.isSupported) {
|
|
1003
|
+
setErrorMsg("Speech not supported");
|
|
1004
|
+
setVoiceTrigger(null);
|
|
1005
|
+
return;
|
|
1006
|
+
}
|
|
1007
|
+
nativeSpeech.start();
|
|
1008
|
+
}
|
|
984
1009
|
}
|
|
1010
|
+
} finally {
|
|
1011
|
+
setTimeout(() => {
|
|
1012
|
+
processingRef.current = false;
|
|
1013
|
+
}, 300);
|
|
985
1014
|
}
|
|
986
1015
|
};
|
|
987
1016
|
let bgColor = accentColor;
|