@contentgrowth/llm-service 0.9.8 → 0.9.91
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;
|
|
@@ -288,20 +292,36 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
288
292
|
}
|
|
289
293
|
}, [language]);
|
|
290
294
|
const start = (0, import_react2.useCallback)(() => {
|
|
291
|
-
console.log("[useSpeechRecognition] start() called");
|
|
292
|
-
if (isSimulatingRef.current)
|
|
295
|
+
console.log("[useSpeechRecognition] start() called. isListening:", isListening, "isStarting:", isStartingRef.current, "hasInstance:", !!recognitionRef.current);
|
|
296
|
+
if (isSimulatingRef.current) {
|
|
297
|
+
console.log("[useSpeechRecognition] isSimulating, ignoring start");
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
293
300
|
if (!recognitionRef.current) {
|
|
294
301
|
console.error("[useSpeechRecognition] Recognition instance missing");
|
|
295
302
|
return;
|
|
296
303
|
}
|
|
304
|
+
if (isStartingRef.current) {
|
|
305
|
+
console.warn("[useSpeechRecognition] Already starting - ignoring duplicate call");
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
if (recognitionRef.current.isListening) {
|
|
309
|
+
console.warn("[useSpeechRecognition] Already listening (native prop) - ignoring");
|
|
310
|
+
}
|
|
311
|
+
if (isListening) {
|
|
312
|
+
console.warn("[useSpeechRecognition] App state says already listening - ignoring");
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
297
315
|
try {
|
|
298
316
|
setTranscript("");
|
|
317
|
+
isStartingRef.current = true;
|
|
299
318
|
recognitionRef.current.start();
|
|
300
|
-
console.log("[useSpeechRecognition] recognition.start() executed");
|
|
319
|
+
console.log("[useSpeechRecognition] recognition.start() executed successfully");
|
|
301
320
|
} catch (error2) {
|
|
321
|
+
isStartingRef.current = false;
|
|
302
322
|
console.error("[useSpeechRecognition] Failed to start recognition:", error2);
|
|
303
323
|
}
|
|
304
|
-
}, []);
|
|
324
|
+
}, [isListening]);
|
|
305
325
|
const stop = (0, import_react2.useCallback)(() => {
|
|
306
326
|
console.log("[useSpeechRecognition] stop() called");
|
|
307
327
|
if (isSimulatingRef.current) {
|
|
@@ -930,58 +950,80 @@ var TapToTalk = ({
|
|
|
930
950
|
});
|
|
931
951
|
const isListening = !!voiceTrigger || nativeSpeech.isListening || customRecorder.isRecording;
|
|
932
952
|
const isActive = isListening || isTranscribing;
|
|
933
|
-
const
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
} else {
|
|
939
|
-
tapCountRef.current.count = 1;
|
|
953
|
+
const processingRef = (0, import_react6.useRef)(false);
|
|
954
|
+
const toggleVoice = async (e) => {
|
|
955
|
+
if (e) {
|
|
956
|
+
e.preventDefault();
|
|
957
|
+
e.stopPropagation();
|
|
940
958
|
}
|
|
941
|
-
|
|
942
|
-
if (
|
|
943
|
-
|
|
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
|
-
}
|
|
959
|
+
console.trace("[TapToTalk] toggleVoice called trace");
|
|
960
|
+
if (processingRef.current) {
|
|
961
|
+
console.log("[TapToTalk] toggleVoice ignored - processing");
|
|
951
962
|
return;
|
|
952
963
|
}
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
if ((voiceConfig == null ? void 0 : voiceConfig.mode) === "native") {
|
|
960
|
-
nativeSpeech.stop();
|
|
964
|
+
processingRef.current = true;
|
|
965
|
+
console.log("[TapToTalk] toggleVoice called. isActive:", isActive);
|
|
966
|
+
try {
|
|
967
|
+
const now = Date.now();
|
|
968
|
+
if (now - tapCountRef.current.lastTap < 500) {
|
|
969
|
+
tapCountRef.current.count++;
|
|
961
970
|
} else {
|
|
962
|
-
|
|
971
|
+
tapCountRef.current.count = 1;
|
|
963
972
|
}
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
await customRecorder.start();
|
|
973
|
-
} catch (e) {
|
|
974
|
-
setErrorMsg("Mic access denied");
|
|
973
|
+
tapCountRef.current.lastTap = now;
|
|
974
|
+
if (tapCountRef.current.count >= 5) {
|
|
975
|
+
setShowDebug((prev) => !prev);
|
|
976
|
+
tapCountRef.current.count = 0;
|
|
977
|
+
if (isActive) {
|
|
978
|
+
console.log("[TapToTalk] Debug trigger force-stop");
|
|
979
|
+
if ((voiceConfig == null ? void 0 : voiceConfig.mode) === "native") nativeSpeech.stop();
|
|
980
|
+
else customRecorder.stop();
|
|
975
981
|
setVoiceTrigger(null);
|
|
976
982
|
}
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
985
|
+
if (isActive) {
|
|
986
|
+
if (isTranscribing && !isListening) {
|
|
987
|
+
console.log("[TapToTalk] Ignoring click during transcription");
|
|
981
988
|
return;
|
|
982
989
|
}
|
|
983
|
-
|
|
990
|
+
console.log("[TapToTalk] Stopping voice...");
|
|
991
|
+
if ((voiceConfig == null ? void 0 : voiceConfig.mode) === "native") {
|
|
992
|
+
nativeSpeech.stop();
|
|
993
|
+
} else {
|
|
994
|
+
customRecorder.stop();
|
|
995
|
+
}
|
|
996
|
+
setVoiceTrigger(null);
|
|
997
|
+
} else {
|
|
998
|
+
console.log("[TapToTalk] Starting voice...");
|
|
999
|
+
setErrorMsg(null);
|
|
1000
|
+
if (onFocusTarget) {
|
|
1001
|
+
console.log("[TapToTalk] calling onFocusTarget() - this might trigger keyboard");
|
|
1002
|
+
onFocusTarget();
|
|
1003
|
+
} else {
|
|
1004
|
+
console.log("[TapToTalk] onFocusTarget is undefined");
|
|
1005
|
+
}
|
|
1006
|
+
setVoiceTrigger("click");
|
|
1007
|
+
if ((voiceConfig == null ? void 0 : voiceConfig.mode) === "custom") {
|
|
1008
|
+
try {
|
|
1009
|
+
await customRecorder.start();
|
|
1010
|
+
} catch (e2) {
|
|
1011
|
+
setErrorMsg("Mic access denied");
|
|
1012
|
+
setVoiceTrigger(null);
|
|
1013
|
+
}
|
|
1014
|
+
} else {
|
|
1015
|
+
if (!nativeSpeech.isSupported) {
|
|
1016
|
+
setErrorMsg("Speech not supported");
|
|
1017
|
+
setVoiceTrigger(null);
|
|
1018
|
+
return;
|
|
1019
|
+
}
|
|
1020
|
+
nativeSpeech.start();
|
|
1021
|
+
}
|
|
984
1022
|
}
|
|
1023
|
+
} finally {
|
|
1024
|
+
setTimeout(() => {
|
|
1025
|
+
processingRef.current = false;
|
|
1026
|
+
}, 300);
|
|
985
1027
|
}
|
|
986
1028
|
};
|
|
987
1029
|
let bgColor = accentColor;
|