@contentgrowth/llm-service 0.8.5 → 0.8.7
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.
|
@@ -212,11 +212,16 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
212
212
|
recognition.interimResults = true;
|
|
213
213
|
recognition.lang = language;
|
|
214
214
|
recognition.onstart = () => {
|
|
215
|
+
console.log("[useSpeechRecognition] Native onstart event fired");
|
|
215
216
|
setIsListening(true);
|
|
216
217
|
setError(null);
|
|
217
218
|
};
|
|
218
219
|
recognition.onend = () => {
|
|
219
|
-
|
|
220
|
+
console.log("[useSpeechRecognition] Native onend event fired");
|
|
221
|
+
if (isSimulatingRef.current) {
|
|
222
|
+
console.log("[useSpeechRecognition] Ignoring onend due to simulation");
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
220
225
|
setIsListening(false);
|
|
221
226
|
if (onEnd) onEnd();
|
|
222
227
|
};
|
|
@@ -236,6 +241,7 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
236
241
|
setTranscript((prev) => prev + finalTranscript);
|
|
237
242
|
};
|
|
238
243
|
recognition.onerror = (event) => {
|
|
244
|
+
console.error("[useSpeechRecognition] Native onerror event:", event.error);
|
|
239
245
|
if (event.error === "not-allowed" && process.env.NODE_ENV === "development") {
|
|
240
246
|
console.warn("Speech recognition blocked. Simulating input for development...");
|
|
241
247
|
isSimulatingRef.current = true;
|
|
@@ -268,17 +274,23 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
268
274
|
};
|
|
269
275
|
}, [onResult, onEnd, language]);
|
|
270
276
|
const start = (0, import_react2.useCallback)(() => {
|
|
277
|
+
console.log("[useSpeechRecognition] start() called");
|
|
271
278
|
if (recognitionRef.current && !isListening) {
|
|
272
279
|
try {
|
|
273
280
|
setTranscript("");
|
|
274
281
|
recognitionRef.current.start();
|
|
282
|
+
console.log("[useSpeechRecognition] recognitionRef.current.start() executed");
|
|
275
283
|
} catch (e) {
|
|
276
|
-
console.error("Failed to start speech recognition:", e);
|
|
284
|
+
console.error("[useSpeechRecognition] Failed to start speech recognition:", e);
|
|
277
285
|
}
|
|
286
|
+
} else {
|
|
287
|
+
console.log("[useSpeechRecognition] start() ignored: already listening or no recognition instance", { hasInstance: !!recognitionRef.current, isListening });
|
|
278
288
|
}
|
|
279
289
|
}, [isListening]);
|
|
280
290
|
const stop = (0, import_react2.useCallback)(() => {
|
|
291
|
+
console.log("[useSpeechRecognition] stop() called");
|
|
281
292
|
if (isSimulatingRef.current) {
|
|
293
|
+
console.log("[useSpeechRecognition] Stopping simulation");
|
|
282
294
|
if (simulationTimeoutRef.current) {
|
|
283
295
|
clearTimeout(simulationTimeoutRef.current);
|
|
284
296
|
simulationTimeoutRef.current = null;
|
|
@@ -292,7 +304,10 @@ var useSpeechRecognition = (onResult, onEnd, language = "en-US") => {
|
|
|
292
304
|
return;
|
|
293
305
|
}
|
|
294
306
|
if (recognitionRef.current && isListening) {
|
|
307
|
+
console.log("[useSpeechRecognition] recognitionRef.current.stop() executed");
|
|
295
308
|
recognitionRef.current.stop();
|
|
309
|
+
} else {
|
|
310
|
+
console.log("[useSpeechRecognition] stop() ignored: not listening", { isListening });
|
|
296
311
|
}
|
|
297
312
|
}, [isListening, onResult, onEnd]);
|
|
298
313
|
const resetTranscript = (0, import_react2.useCallback)(() => {
|
|
@@ -318,23 +333,32 @@ var useAudioRecorder = (onStop) => {
|
|
|
318
333
|
const mediaRecorderRef = (0, import_react3.useRef)(null);
|
|
319
334
|
const chunksRef = (0, import_react3.useRef)([]);
|
|
320
335
|
const start = (0, import_react3.useCallback)(async () => {
|
|
336
|
+
console.log("[useAudioRecorder] start() called");
|
|
321
337
|
try {
|
|
322
338
|
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
339
|
+
console.log("[useAudioRecorder] Stream acquired", stream.id);
|
|
323
340
|
const mediaRecorder = new MediaRecorder(stream);
|
|
324
341
|
mediaRecorderRef.current = mediaRecorder;
|
|
325
342
|
chunksRef.current = [];
|
|
326
343
|
mediaRecorder.ondataavailable = (e) => {
|
|
344
|
+
console.log(`[useAudioRecorder] Data available, size: ${e.data.size}`);
|
|
327
345
|
if (e.data.size > 0) {
|
|
328
346
|
chunksRef.current.push(e.data);
|
|
329
347
|
}
|
|
330
348
|
};
|
|
331
349
|
mediaRecorder.onstop = () => {
|
|
350
|
+
console.log(`[useAudioRecorder] Recorder stopped. Chunks: ${chunksRef.current.length}`);
|
|
332
351
|
const audioBlob = new Blob(chunksRef.current, { type: "audio/webm" });
|
|
352
|
+
console.log(`[useAudioRecorder] Blob created. Size: ${audioBlob.size}, Type: ${audioBlob.type}`);
|
|
333
353
|
setBlob(audioBlob);
|
|
334
354
|
setIsRecording(false);
|
|
335
355
|
if (onStop) onStop(audioBlob);
|
|
336
|
-
stream.getTracks().forEach((track) =>
|
|
356
|
+
stream.getTracks().forEach((track) => {
|
|
357
|
+
console.log(`[useAudioRecorder] Stopping track: ${track.label} (${track.kind})`);
|
|
358
|
+
track.stop();
|
|
359
|
+
});
|
|
337
360
|
};
|
|
361
|
+
console.log("[useAudioRecorder] Starting MediaRecorder...");
|
|
338
362
|
mediaRecorder.start();
|
|
339
363
|
setIsRecording(true);
|
|
340
364
|
setError(null);
|
|
@@ -344,8 +368,12 @@ var useAudioRecorder = (onStop) => {
|
|
|
344
368
|
}
|
|
345
369
|
}, [onStop]);
|
|
346
370
|
const stop = (0, import_react3.useCallback)(() => {
|
|
371
|
+
console.log("[useAudioRecorder] stop() called");
|
|
347
372
|
if (mediaRecorderRef.current && mediaRecorderRef.current.state !== "inactive") {
|
|
373
|
+
console.log(`[useAudioRecorder] Stopping MediaRecorder. State was: ${mediaRecorderRef.current.state}`);
|
|
348
374
|
mediaRecorderRef.current.stop();
|
|
375
|
+
} else {
|
|
376
|
+
console.log("[useAudioRecorder] stop() ignored. Recorder is inactive or missing.");
|
|
349
377
|
}
|
|
350
378
|
}, []);
|
|
351
379
|
return {
|
|
@@ -411,20 +439,30 @@ var ChatInputArea = (0, import_react5.forwardRef)(({
|
|
|
411
439
|
}, [inputMode]);
|
|
412
440
|
const isControlled = value !== void 0;
|
|
413
441
|
const message = isControlled ? value : internalMessage;
|
|
442
|
+
const messageRef = (0, import_react5.useRef)(message);
|
|
443
|
+
messageRef.current = message;
|
|
444
|
+
const onChangeRef = (0, import_react5.useRef)(onChange);
|
|
445
|
+
(0, import_react5.useEffect)(() => {
|
|
446
|
+
onChangeRef.current = onChange;
|
|
447
|
+
}, [onChange]);
|
|
414
448
|
const { voice: globalVoice } = useChatConfig();
|
|
415
449
|
const isVoiceEnabled = (_a = globalVoice == null ? void 0 : globalVoice.enabled) != null ? _a : !!propVoiceConfig;
|
|
416
450
|
const voiceConfig = isVoiceEnabled ? propVoiceConfig || (globalVoice == null ? void 0 : globalVoice.config) : void 0;
|
|
417
|
-
const
|
|
418
|
-
|
|
451
|
+
const voiceConfigRef = (0, import_react5.useRef)(voiceConfig);
|
|
452
|
+
(0, import_react5.useEffect)(() => {
|
|
453
|
+
voiceConfigRef.current = voiceConfig;
|
|
454
|
+
}, [voiceConfig]);
|
|
455
|
+
const triggerChange = (0, import_react5.useCallback)((newValue) => {
|
|
456
|
+
if (isControlled && onChangeRef.current && textareaRef.current) {
|
|
419
457
|
const syntheticEvent = {
|
|
420
458
|
target: { value: newValue },
|
|
421
459
|
currentTarget: { value: newValue }
|
|
422
460
|
};
|
|
423
|
-
|
|
461
|
+
onChangeRef.current(syntheticEvent);
|
|
424
462
|
} else {
|
|
425
463
|
setInternalMessage(newValue);
|
|
426
464
|
}
|
|
427
|
-
};
|
|
465
|
+
}, [isControlled]);
|
|
428
466
|
const isInputDisabled = (currentTask == null ? void 0 : currentTask.complete) || (lastInteractiveMessage == null ? void 0 : lastInteractiveMessage.interactive) && (((_b = lastInteractiveMessage == null ? void 0 : lastInteractiveMessage.interactiveData) == null ? void 0 : _b.function) === "form" && !(lastInteractiveMessage == null ? void 0 : lastInteractiveMessage.isResponseSubmitted) || ((_c = lastInteractiveMessage == null ? void 0 : lastInteractiveMessage.interactiveData) == null ? void 0 : _c.function) === "confirm" && !(lastInteractiveMessage == null ? void 0 : lastInteractiveMessage.isResponseSubmitted));
|
|
429
467
|
useProactiveResize(textareaRef, measurementRef, message, isInputDisabled || !!voiceTrigger || inputMode === "voice");
|
|
430
468
|
const handleVoiceKeyDown = (e) => {
|
|
@@ -449,23 +487,28 @@ var ChatInputArea = (0, import_react5.forwardRef)(({
|
|
|
449
487
|
}
|
|
450
488
|
}
|
|
451
489
|
};
|
|
452
|
-
const
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
490
|
+
const handleVoiceResult = (0, import_react5.useCallback)((text) => {
|
|
491
|
+
console.log("[ChatInputArea] nativeSpeech result:", text);
|
|
492
|
+
triggerChange(messageRef.current + (messageRef.current ? " " : "") + text);
|
|
493
|
+
}, []);
|
|
494
|
+
const handleVoiceEnd = (0, import_react5.useCallback)(() => {
|
|
495
|
+
var _a2, _b2;
|
|
496
|
+
console.log("[ChatInputArea] nativeSpeech onEnd triggered");
|
|
456
497
|
setVoiceTrigger(null);
|
|
457
|
-
(_a2 =
|
|
458
|
-
},
|
|
498
|
+
(_b2 = (_a2 = voiceConfigRef.current) == null ? void 0 : _a2.onVoiceEnd) == null ? void 0 : _b2.call(_a2);
|
|
499
|
+
}, []);
|
|
500
|
+
const nativeSpeech = useSpeechRecognition(handleVoiceResult, handleVoiceEnd, voiceConfig == null ? void 0 : voiceConfig.language);
|
|
459
501
|
const customRecorder = useAudioRecorder(async (blob) => {
|
|
460
|
-
var _a2;
|
|
502
|
+
var _a2, _b2, _c2;
|
|
503
|
+
console.log("[ChatInputArea] customRecorder onStop triggered");
|
|
461
504
|
setVoiceTrigger(null);
|
|
462
|
-
(_a2 =
|
|
463
|
-
if (
|
|
505
|
+
(_b2 = (_a2 = voiceConfigRef.current) == null ? void 0 : _a2.onVoiceEnd) == null ? void 0 : _b2.call(_a2);
|
|
506
|
+
if ((_c2 = voiceConfigRef.current) == null ? void 0 : _c2.onAudioCapture) {
|
|
464
507
|
try {
|
|
465
|
-
const text = await
|
|
466
|
-
if (text) triggerChange(
|
|
508
|
+
const text = await voiceConfigRef.current.onAudioCapture(blob);
|
|
509
|
+
if (text) triggerChange(messageRef.current + (messageRef.current ? " " : "") + text);
|
|
467
510
|
} catch (e) {
|
|
468
|
-
console.error("Audio capture failed", e);
|
|
511
|
+
console.error("[ChatInputArea] Audio capture failed", e);
|
|
469
512
|
}
|
|
470
513
|
}
|
|
471
514
|
});
|
|
@@ -507,6 +550,8 @@ var ChatInputArea = (0, import_react5.forwardRef)(({
|
|
|
507
550
|
};
|
|
508
551
|
const startRecording = async (trigger) => {
|
|
509
552
|
var _a2;
|
|
553
|
+
console.log(`[ChatInputArea] startRecording triggered by: ${trigger}, current voiceTrigger: ${voiceTrigger}`);
|
|
554
|
+
console.log("[ChatInputArea] voiceConfig:", voiceConfig);
|
|
510
555
|
if (voiceTrigger) return;
|
|
511
556
|
setVoiceTrigger(trigger);
|
|
512
557
|
(_a2 = voiceConfig == null ? void 0 : voiceConfig.onVoiceStart) == null ? void 0 : _a2.call(voiceConfig);
|
|
@@ -516,12 +561,15 @@ var ChatInputArea = (0, import_react5.forwardRef)(({
|
|
|
516
561
|
setVoiceTrigger(null);
|
|
517
562
|
return;
|
|
518
563
|
}
|
|
564
|
+
console.log("[ChatInputArea] Starting nativeSpeech");
|
|
519
565
|
nativeSpeech.start();
|
|
520
566
|
} else {
|
|
567
|
+
console.log("[ChatInputArea] Starting customRecorder");
|
|
521
568
|
await customRecorder.start();
|
|
522
569
|
}
|
|
523
570
|
};
|
|
524
571
|
const stopRecording = () => {
|
|
572
|
+
console.log(`[ChatInputArea] stopRecording called. Current voiceTrigger: ${voiceTrigger}`);
|
|
525
573
|
if (!voiceTrigger) return;
|
|
526
574
|
if ((voiceConfig == null ? void 0 : voiceConfig.mode) === "native") {
|
|
527
575
|
nativeSpeech.stop();
|