@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.
@@ -203,6 +203,12 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
203
203
  const recognitionRef = (0, import_react2.useRef)(null);
204
204
  const isSimulatingRef = (0, import_react2.useRef)(false);
205
205
  const simulationTimeoutRef = (0, import_react2.useRef)(null);
206
+ const onResultRef = (0, import_react2.useRef)(onResult);
207
+ const onEndRef = (0, import_react2.useRef)(onEnd);
208
+ (0, import_react2.useEffect)(() => {
209
+ onResultRef.current = onResult;
210
+ onEndRef.current = onEnd;
211
+ }, [onResult, onEnd]);
206
212
  (0, import_react2.useEffect)(() => {
207
213
  if (typeof window !== "undefined") {
208
214
  const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
@@ -221,7 +227,7 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
221
227
  return;
222
228
  }
223
229
  setIsListening(false);
224
- if (onEnd) onEnd();
230
+ if (onEndRef.current) onEndRef.current();
225
231
  };
226
232
  recognition.onresult = (event) => {
227
233
  let interimTranscript = "";
@@ -230,10 +236,10 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
230
236
  const result = event.results[i];
231
237
  if (result.isFinal) {
232
238
  finalTranscript += result[0].transcript;
233
- if (onResult) onResult(finalTranscript, true);
239
+ if (onResultRef.current) onResultRef.current(finalTranscript, true);
234
240
  } else {
235
241
  interimTranscript += result[0].transcript;
236
- if (onResult) onResult(interimTranscript, false);
242
+ if (onResultRef.current) onResultRef.current(interimTranscript, false);
237
243
  }
238
244
  }
239
245
  setTranscript((prev) => prev + finalTranscript);
@@ -248,10 +254,10 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
248
254
  simulationTimeoutRef.current = setTimeout(() => {
249
255
  const mockText = "This is a simulated voice input for testing.";
250
256
  setTranscript((prev) => prev + (prev ? " " : "") + mockText);
251
- if (onResult) onResult(mockText, true);
257
+ if (onResultRef.current) onResultRef.current(mockText, true);
252
258
  isSimulatingRef.current = false;
253
259
  setIsListening(false);
254
- if (onEnd) onEnd();
260
+ if (onEndRef.current) onEndRef.current();
255
261
  simulationTimeoutRef.current = null;
256
262
  }, 3e3);
257
263
  return;
@@ -268,9 +274,11 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
268
274
  clearTimeout(simulationTimeoutRef.current);
269
275
  simulationTimeoutRef.current = null;
270
276
  }
271
- recognitionRef.current.stop();
277
+ if (recognitionRef.current) {
278
+ recognitionRef.current.stop();
279
+ }
272
280
  };
273
- }, [onResult, onEnd, language]);
281
+ }, [language]);
274
282
  const start = (0, import_react2.useCallback)(() => {
275
283
  if (recognitionRef.current && !isListening) {
276
284
  try {
@@ -290,10 +298,10 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
290
298
  }
291
299
  const mockText = "This is a simulated voice input for testing.";
292
300
  setTranscript((prev) => prev + (prev ? " " : "") + mockText);
293
- if (onResult) onResult(mockText, true);
301
+ if (onResultRef.current) onResultRef.current(mockText, true);
294
302
  isSimulatingRef.current = false;
295
303
  setIsListening(false);
296
- if (onEnd) onEnd();
304
+ if (onEndRef.current) onEndRef.current();
297
305
  return;
298
306
  }
299
307
  if (recognitionRef.current && isListening) {
@@ -465,6 +473,9 @@ var ChatInputArea = (0, import_react5.forwardRef)(({
465
473
  console.error = originalError;
466
474
  };
467
475
  }, []);
476
+ const copyLogs = (0, import_react5.useCallback)(() => {
477
+ navigator.clipboard.writeText(logs.join("\n")).then(() => alert("Logs copied to clipboard")).catch((err) => console.error("Failed to copy logs", err));
478
+ }, [logs]);
468
479
  const textareaRef = (0, import_react5.useRef)(null);
469
480
  const measurementRef = (0, import_react5.useRef)(null);
470
481
  const pendingSelectionRef = (0, import_react5.useRef)(null);
@@ -657,7 +668,13 @@ var ChatInputArea = (0, import_react5.forwardRef)(({
657
668
  showDebug && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("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: [
658
669
  /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex justify-between items-center bg-gray-800 p-1 mb-1", children: [
659
670
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Debug Logs" }),
660
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { onClick: () => setShowDebug(false), className: "text-white hover:text-red-400", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_outline.XMarkIcon, { className: "w-4 h-4" }) })
671
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex gap-2", children: [
672
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { onClick: copyLogs, className: "text-white hover:text-blue-400", title: "Copy Logs", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_outline.Square2StackIcon, { className: "w-4 h-4" }) }),
673
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { onClick: () => {
674
+ copyLogs();
675
+ setShowDebug(false);
676
+ }, className: "text-white hover:text-red-400", title: "Copy & Close", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_outline.XMarkIcon, { className: "w-4 h-4" }) })
677
+ ] })
661
678
  ] }),
662
679
  logs.map((log, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mb-0.5 border-b border-gray-700/50 pb-0.5 break-all", children: log }, i)),
663
680
  logs.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { children: "No logs yet..." })
@@ -678,6 +695,7 @@ var ChatInputArea = (0, import_react5.forwardRef)(({
678
695
  if (tapCountRef.current.count >= 5) {
679
696
  setShowDebug((prev) => !prev);
680
697
  tapCountRef.current.count = 0;
698
+ stopRecording();
681
699
  return;
682
700
  }
683
701
  if (voiceTrigger) {
@@ -852,6 +870,9 @@ var TapToTalk = ({
852
870
  console.error = originalError;
853
871
  };
854
872
  }, []);
873
+ const copyLogs = (0, import_react6.useCallback)(() => {
874
+ navigator.clipboard.writeText(logs.join("\n")).then(() => alert("Logs copied to clipboard")).catch((err) => console.error("Failed to copy logs", err));
875
+ }, [logs]);
855
876
  const handleVoiceResult = (0, import_react6.useCallback)((text, isFinal) => {
856
877
  if (isFinal) {
857
878
  onResult(text);
@@ -907,6 +928,11 @@ var TapToTalk = ({
907
928
  if (tapCountRef.current.count >= 5) {
908
929
  setShowDebug((prev) => !prev);
909
930
  tapCountRef.current.count = 0;
931
+ if (isActive) {
932
+ if ((voiceConfig == null ? void 0 : voiceConfig.mode) === "native") nativeSpeech.stop();
933
+ else customRecorder.stop();
934
+ setVoiceTrigger(null);
935
+ }
910
936
  return;
911
937
  }
912
938
  if (isActive) {
@@ -957,10 +983,17 @@ var TapToTalk = ({
957
983
  showDebug && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("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: [
958
984
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex justify-between items-center bg-gray-800 p-1 mb-1", children: [
959
985
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Debug Logs" }),
960
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { onClick: (e) => {
961
- e.stopPropagation();
962
- setShowDebug(false);
963
- }, className: "text-white hover:text-red-400", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_outline2.XMarkIcon, { className: "w-4 h-4" }) })
986
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex gap-2", children: [
987
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { onClick: (e) => {
988
+ e.stopPropagation();
989
+ copyLogs();
990
+ }, className: "text-white hover:text-blue-400", title: "Copy Logs", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_outline2.Square2StackIcon, { className: "w-4 h-4" }) }),
991
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { onClick: (e) => {
992
+ e.stopPropagation();
993
+ copyLogs();
994
+ setShowDebug(false);
995
+ }, className: "text-white hover:text-red-400", title: "Copy & Close", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_outline2.XMarkIcon, { className: "w-4 h-4" }) })
996
+ ] })
964
997
  ] }),
965
998
  logs.map((log, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mb-0.5 border-b border-gray-700/50 pb-0.5 break-all", children: log }, i)),
966
999
  logs.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { children: "No logs yet..." })