@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
- console.log("[TapToTalk] toggleVoice called. isActive:", isActive);
893
- const now = Date.now();
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
- if (isActive) {
912
- if (isTranscribing && !isListening) {
913
- console.log("[TapToTalk] Ignoring click during transcription");
914
- return;
915
- }
916
- console.log("[TapToTalk] Stopping voice...");
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
- customRecorder.stop();
921
+ tapCountRef.current.count = 1;
921
922
  }
922
- setVoiceTrigger(null);
923
- } else {
924
- console.log("[TapToTalk] Starting voice...");
925
- setErrorMsg(null);
926
- onFocusTarget == null ? void 0 : onFocusTarget();
927
- setVoiceTrigger("click");
928
- if ((voiceConfig == null ? void 0 : voiceConfig.mode) === "custom") {
929
- try {
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
- } else {
936
- if (!nativeSpeech.isSupported) {
937
- setErrorMsg("Speech not supported");
938
- setVoiceTrigger(null);
933
+ return;
934
+ }
935
+ if (isActive) {
936
+ if (isTranscribing && !isListening) {
937
+ console.log("[TapToTalk] Ignoring click during transcription");
939
938
  return;
940
939
  }
941
- nativeSpeech.start();
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;