@memori.ai/memori-react 7.19.2 → 7.21.1
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.
- package/CHANGELOG.md +52 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.d.ts +3 -2
- package/dist/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.js +13 -6
- package/dist/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.d.ts +14 -18
- package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +19 -77
- package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.d.ts +17 -2
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +95 -70
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.d.ts +65 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js +747 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js.map +1 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.d.ts +9 -2
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js +60 -2
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.d.ts +3 -4
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js +5 -11
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/constants.d.ts +13 -52
- package/dist/components/Avatar/AvatarView/AvatarComponent/constants.js +68 -70
- package/dist/components/Avatar/AvatarView/AvatarComponent/constants.js.map +1 -1
- package/dist/components/Avatar/AvatarView/index.d.ts +1 -1
- package/dist/components/Avatar/AvatarView/index.js +2 -2
- package/dist/components/Avatar/AvatarView/index.js.map +1 -1
- package/dist/components/ChatBubble/ChatBubble.css +9 -0
- package/dist/components/ChatBubble/ChatBubble.js +7 -1
- package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
- package/dist/components/MemoriWidget/MemoriWidget.js +130 -62
- package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/dist/components/UploadButton/UploadButton.js +2 -2
- package/dist/components/UploadButton/UploadButton.js.map +1 -1
- package/dist/components/WhyThisAnswer/WhyThisAnswer.css +43 -0
- package/dist/components/WhyThisAnswer/WhyThisAnswer.js +2 -1
- package/dist/components/WhyThisAnswer/WhyThisAnswer.js.map +1 -1
- package/dist/context/visemeContext.js +0 -39
- package/dist/context/visemeContext.js.map +1 -1
- package/dist/locales/de.json +1 -0
- package/dist/locales/en.json +1 -0
- package/dist/locales/es.json +1 -0
- package/dist/locales/fr.json +1 -0
- package/dist/locales/it.json +1 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.d.ts +3 -2
- package/esm/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.js +13 -6
- package/esm/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.d.ts +14 -18
- package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +20 -78
- package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.d.ts +17 -2
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +99 -74
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.d.ts +65 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js +743 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js.map +1 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.d.ts +9 -2
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js +61 -3
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.d.ts +3 -4
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js +5 -11
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/constants.d.ts +13 -52
- package/esm/components/Avatar/AvatarView/AvatarComponent/constants.js +67 -69
- package/esm/components/Avatar/AvatarView/AvatarComponent/constants.js.map +1 -1
- package/esm/components/Avatar/AvatarView/index.d.ts +1 -1
- package/esm/components/Avatar/AvatarView/index.js +2 -2
- package/esm/components/Avatar/AvatarView/index.js.map +1 -1
- package/esm/components/ChatBubble/ChatBubble.css +9 -0
- package/esm/components/ChatBubble/ChatBubble.js +7 -1
- package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
- package/esm/components/MemoriWidget/MemoriWidget.js +130 -62
- package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/esm/components/UploadButton/UploadButton.js +2 -2
- package/esm/components/UploadButton/UploadButton.js.map +1 -1
- package/esm/components/WhyThisAnswer/WhyThisAnswer.css +43 -0
- package/esm/components/WhyThisAnswer/WhyThisAnswer.js +2 -1
- package/esm/components/WhyThisAnswer/WhyThisAnswer.js.map +1 -1
- package/esm/context/visemeContext.js +0 -39
- package/esm/context/visemeContext.js.map +1 -1
- package/esm/locales/de.json +1 -0
- package/esm/locales/en.json +1 -0
- package/esm/locales/es.json +1 -0
- package/esm/locales/fr.json +1 -0
- package/esm/locales/it.json +1 -0
- package/package.json +2 -2
- package/src/components/Avatar/AvatarView/AvatarComponent/Shadow/DynamicShadow.tsx +15 -8
- package/src/components/Avatar/AvatarView/AvatarComponent/avatarComponent.tsx +64 -219
- package/src/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.tsx +221 -124
- package/src/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.ts +1250 -0
- package/src/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.ts +164 -8
- package/src/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.tsx +19 -17
- package/src/components/Avatar/AvatarView/AvatarComponent/constants.ts +80 -79
- package/src/components/Avatar/AvatarView/index.tsx +1 -7
- package/src/components/ChatBubble/ChatBubble.css +9 -0
- package/src/components/ChatBubble/ChatBubble.tsx +14 -2
- package/src/components/MemoriWidget/MemoriWidget.tsx +168 -76
- package/src/components/UploadButton/UploadButton.tsx +4 -4
- package/src/components/UploadButton/__snapshots__/UploadButton.test.tsx.snap +1 -1
- package/src/components/WhyThisAnswer/WhyThisAnswer.css +43 -0
- package/src/components/WhyThisAnswer/WhyThisAnswer.stories.tsx +44 -3
- package/src/components/WhyThisAnswer/WhyThisAnswer.test.tsx +128 -8
- package/src/components/WhyThisAnswer/WhyThisAnswer.tsx +28 -3
- package/src/components/WhyThisAnswer/__snapshots__/WhyThisAnswer.test.tsx.snap +15 -1
- package/src/components/layouts/layouts.stories.tsx +0 -8
- package/src/context/visemeContext.tsx +40 -41
- package/src/index.stories.tsx +63 -65
- package/src/locales/de.json +1 -0
- package/src/locales/en.json +1 -0
- package/src/locales/es.json +1 -0
- package/src/locales/fr.json +1 -0
- package/src/locales/it.json +1 -0
- package/src/components/Avatar/AvatarView/AvatarComponent/components/controllers/AnimationController.ts +0 -308
|
@@ -2202,26 +2202,20 @@ const MemoriWidget = ({
|
|
|
2202
2202
|
cleanup();
|
|
2203
2203
|
};
|
|
2204
2204
|
|
|
2205
|
-
const cleanup = ()
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2205
|
+
const cleanup = () => {
|
|
2206
|
+
if (recognizer) {
|
|
2207
|
+
recognizer.stopContinuousRecognitionAsync();
|
|
2208
|
+
recognizer.close();
|
|
2209
|
+
recognizer = null;
|
|
2210
|
+
}
|
|
2210
2211
|
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
const currentSynthesizer = speechSynthesizer;
|
|
2214
|
-
speechSynthesizer = null; // Clear reference first
|
|
2215
|
-
console.debug('Closing speech synthesizer');
|
|
2216
|
-
currentSynthesizer.close();
|
|
2217
|
-
}
|
|
2218
|
-
} catch (error) {
|
|
2219
|
-
console.debug('Error during synthesizer cleanup:', error);
|
|
2220
|
-
// Even if close fails, ensure synthesizer is nullified
|
|
2212
|
+
if (speechSynthesizer) {
|
|
2213
|
+
speechSynthesizer.close();
|
|
2221
2214
|
speechSynthesizer = null;
|
|
2222
2215
|
}
|
|
2223
2216
|
|
|
2224
|
-
|
|
2217
|
+
setListening(false);
|
|
2218
|
+
clearListeningTimeout();
|
|
2225
2219
|
};
|
|
2226
2220
|
|
|
2227
2221
|
// Modify stopAudio to include speech state reset
|
|
@@ -2282,34 +2276,41 @@ const MemoriWidget = ({
|
|
|
2282
2276
|
|
|
2283
2277
|
const resetTranscript = () => {
|
|
2284
2278
|
setTranscript('');
|
|
2285
|
-
// setIsProcessingSTT(false);
|
|
2286
2279
|
};
|
|
2287
|
-
|
|
2280
|
+
// Modify setListeningTimeout to be more robust
|
|
2288
2281
|
const setListeningTimeout = () => {
|
|
2289
|
-
clearListeningTimeout();
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2282
|
+
clearListeningTimeout(); // Clear any existing timeout
|
|
2283
|
+
|
|
2284
|
+
console.debug('Setting speech processing timeout');
|
|
2285
|
+
const timeout = setTimeout(() => {
|
|
2286
|
+
console.debug('Speech timeout triggered, processing transcript');
|
|
2287
|
+
handleTranscriptProcessing();
|
|
2288
|
+
}, continuousSpeechTimeout * 1000 + 300);
|
|
2289
|
+
|
|
2294
2290
|
setTranscriptTimeout(timeout as unknown as NodeJS.Timeout);
|
|
2295
2291
|
};
|
|
2296
2292
|
|
|
2297
2293
|
const clearListeningTimeout = () => {
|
|
2298
2294
|
if (transcriptTimeout) {
|
|
2295
|
+
console.debug('Clearing transcript timeout');
|
|
2299
2296
|
clearTimeout(transcriptTimeout);
|
|
2300
2297
|
setTranscriptTimeout(null);
|
|
2301
2298
|
}
|
|
2302
2299
|
};
|
|
2303
2300
|
|
|
2301
|
+
// Add safety check in resetListeningTimeout
|
|
2304
2302
|
const resetListeningTimeout = () => {
|
|
2305
2303
|
clearListeningTimeout();
|
|
2306
|
-
if (continuousSpeech) {
|
|
2304
|
+
if (continuousSpeech && !isProcessingSTT) {
|
|
2305
|
+
console.debug('Setting new listening timeout');
|
|
2307
2306
|
setListeningTimeout();
|
|
2308
2307
|
}
|
|
2309
2308
|
};
|
|
2310
|
-
|
|
2309
|
+
|
|
2310
|
+
// Make sure only one path can trigger message sending
|
|
2311
2311
|
useEffect(() => {
|
|
2312
|
-
if (!isSpeaking) {
|
|
2312
|
+
if (!isSpeaking && transcript && transcript.length > 0) {
|
|
2313
|
+
console.debug('Transcript updated while not speaking, resetting timeout');
|
|
2313
2314
|
resetListeningTimeout();
|
|
2314
2315
|
resetInteractionTimeout();
|
|
2315
2316
|
}
|
|
@@ -2325,87 +2326,126 @@ const MemoriWidget = ({
|
|
|
2325
2326
|
/**
|
|
2326
2327
|
* Listening methods
|
|
2327
2328
|
*/
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
* Sets up recognizer and begins continuous recognition
|
|
2331
|
-
*/
|
|
2329
|
+
let microphoneStream: MediaStream | null = null;
|
|
2330
|
+
// Modify startListening to ensure full cleanup before starting
|
|
2332
2331
|
const startListening = async (): Promise<void> => {
|
|
2332
|
+
console.debug('Starting speech recognition...');
|
|
2333
|
+
|
|
2333
2334
|
if (!AZURE_COGNITIVE_SERVICES_TTS_KEY) {
|
|
2335
|
+
console.error('No TTS key available');
|
|
2334
2336
|
throw new Error('No TTS key available');
|
|
2335
2337
|
}
|
|
2336
2338
|
|
|
2337
2339
|
if (!sessionId) {
|
|
2340
|
+
console.error('No session ID available');
|
|
2338
2341
|
throw new Error('No session ID available');
|
|
2339
2342
|
}
|
|
2340
2343
|
|
|
2341
|
-
//
|
|
2342
|
-
|
|
2344
|
+
// First, ensure any existing recognizer is fully closed
|
|
2345
|
+
if (recognizer) {
|
|
2346
|
+
console.debug('Cleaning up existing recognizer...');
|
|
2347
|
+
try {
|
|
2348
|
+
// Stop the recognizer properly
|
|
2349
|
+
await new Promise<void>((resolve, _) => {
|
|
2350
|
+
recognizer?.stopContinuousRecognitionAsync(resolve, error => {
|
|
2351
|
+
console.error('Error stopping recognition:', error);
|
|
2352
|
+
resolve(); // Resolve anyway to continue cleanup
|
|
2353
|
+
});
|
|
2354
|
+
});
|
|
2355
|
+
|
|
2356
|
+
console.debug('Closing existing recognizer...');
|
|
2357
|
+
recognizer.close();
|
|
2358
|
+
recognizer = null;
|
|
2359
|
+
} catch (error) {
|
|
2360
|
+
console.error('Error during recognizer cleanup:', error);
|
|
2361
|
+
// Continue with initialization anyway
|
|
2362
|
+
}
|
|
2363
|
+
}
|
|
2364
|
+
|
|
2365
|
+
// Clear any existing state
|
|
2366
|
+
console.debug('Resetting transcript and STT state...');
|
|
2343
2367
|
resetTranscript();
|
|
2368
|
+
setIsProcessingSTT(false);
|
|
2369
|
+
|
|
2370
|
+
// Add a small delay to ensure Azure services have time to release resources
|
|
2371
|
+
console.debug('Adding delay for Azure services cleanup...');
|
|
2372
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
2344
2373
|
|
|
2345
2374
|
try {
|
|
2346
|
-
|
|
2347
|
-
//
|
|
2375
|
+
console.debug('Requesting microphone access...');
|
|
2376
|
+
// Release previous microphone stream if it exists
|
|
2377
|
+
if (microphoneStream) {
|
|
2378
|
+
microphoneStream.getTracks().forEach(track => track.stop());
|
|
2379
|
+
microphoneStream = null;
|
|
2380
|
+
}
|
|
2348
2381
|
|
|
2349
|
-
const stream = await navigator.mediaDevices.getUserMedia({
|
|
2382
|
+
const stream = await navigator.mediaDevices.getUserMedia({
|
|
2383
|
+
audio: true,
|
|
2384
|
+
});
|
|
2350
2385
|
setHasUserActivatedListening(true);
|
|
2351
2386
|
|
|
2352
2387
|
// Recreate speech config each time
|
|
2388
|
+
console.debug('Setting up speech config...');
|
|
2353
2389
|
speechConfig = setupSpeechConfig(AZURE_COGNITIVE_SERVICES_TTS_KEY);
|
|
2354
2390
|
|
|
2391
|
+
console.debug('Creating audio config and recognizer...');
|
|
2355
2392
|
const audioConfig = speechSdk.AudioConfig.fromDefaultMicrophoneInput();
|
|
2356
2393
|
recognizer = new speechSdk.SpeechRecognizer(speechConfig, audioConfig);
|
|
2357
2394
|
|
|
2358
2395
|
// Set up recognizer event handlers
|
|
2396
|
+
console.debug('Setting up recognizer handlers...');
|
|
2359
2397
|
setupRecognizerHandlers(recognizer);
|
|
2360
2398
|
|
|
2361
|
-
// Start recognition
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
console.debug(
|
|
2370
|
-
'CANCELED: Did you set the speech resource key and region values?'
|
|
2371
|
-
);
|
|
2372
|
-
stopListening();
|
|
2373
|
-
cleanup();
|
|
2374
|
-
}
|
|
2375
|
-
|
|
2376
|
-
stopListening();
|
|
2377
|
-
};
|
|
2399
|
+
// Start recognition - use promises for better error handling
|
|
2400
|
+
console.debug('Starting continuous recognition...');
|
|
2401
|
+
await new Promise<void>((resolve, reject) => {
|
|
2402
|
+
recognizer?.startContinuousRecognitionAsync(resolve, error => {
|
|
2403
|
+
console.error('Failed to start recognition:', error);
|
|
2404
|
+
reject(error);
|
|
2405
|
+
});
|
|
2406
|
+
});
|
|
2378
2407
|
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
resetTranscript();
|
|
2382
|
-
};
|
|
2408
|
+
console.debug('Speech recognition started successfully');
|
|
2409
|
+
setListening(true);
|
|
2383
2410
|
} catch (error) {
|
|
2384
2411
|
console.error('Error in startListening:', error);
|
|
2385
|
-
|
|
2412
|
+
// Ensure cleanup happens even on error
|
|
2413
|
+
if (recognizer) {
|
|
2414
|
+
console.debug('Cleaning up recognizer after error...');
|
|
2415
|
+
recognizer.close();
|
|
2416
|
+
recognizer = null;
|
|
2417
|
+
}
|
|
2418
|
+
setListening(false);
|
|
2386
2419
|
throw error;
|
|
2387
2420
|
}
|
|
2388
2421
|
};
|
|
2389
2422
|
|
|
2390
2423
|
const setupSpeechConfig = (AZURE_COGNITIVE_SERVICES_TTS_KEY: string) => {
|
|
2424
|
+
console.debug('Creating speech config...');
|
|
2391
2425
|
speechConfig = speechSdk.SpeechConfig.fromSubscription(
|
|
2392
2426
|
AZURE_COGNITIVE_SERVICES_TTS_KEY,
|
|
2393
2427
|
'westeurope'
|
|
2394
2428
|
);
|
|
2429
|
+
console.debug('Setting speech recognition language:', userLang);
|
|
2395
2430
|
speechConfig.speechRecognitionLanguage = getCultureCodeByLanguage(userLang);
|
|
2396
2431
|
speechConfig.speechSynthesisLanguage = getCultureCodeByLanguage(userLang);
|
|
2397
2432
|
speechConfig.speechSynthesisVoiceName = getTTSVoice(userLang); // https://docs.microsoft.com/it-it/azure/cognitive-services/speech-service/language-support#text-to-speech
|
|
2398
2433
|
return speechConfig;
|
|
2399
2434
|
};
|
|
2400
2435
|
|
|
2436
|
+
const [isProcessingSTT, setIsProcessingSTT] = useState(false);
|
|
2437
|
+
|
|
2401
2438
|
const setupRecognizerHandlers = (recognizer: speechSdk.SpeechRecognizer) => {
|
|
2402
2439
|
if (recognizer) {
|
|
2440
|
+
console.debug('Setting up recognizer event handlers...');
|
|
2403
2441
|
recognizer.recognized = (_, event) => {
|
|
2404
2442
|
// Process the recognized speech result
|
|
2443
|
+
console.debug('Recognition event received');
|
|
2405
2444
|
handleRecognizedSpeech(event.result.text);
|
|
2406
2445
|
};
|
|
2407
2446
|
|
|
2408
2447
|
// Configure speech recognition properties directly on the recognizer
|
|
2448
|
+
console.debug('Configuring recognizer properties...');
|
|
2409
2449
|
recognizer.properties.setProperty(
|
|
2410
2450
|
'SpeechServiceResponse_JsonResult',
|
|
2411
2451
|
'true'
|
|
@@ -2423,32 +2463,66 @@ const MemoriWidget = ({
|
|
|
2423
2463
|
}
|
|
2424
2464
|
};
|
|
2425
2465
|
|
|
2426
|
-
|
|
2427
|
-
|
|
2466
|
+
// Add a mutex-like flag to prevent duplicate processing
|
|
2467
|
+
let isProcessingSpeech = false;
|
|
2428
2468
|
|
|
2429
|
-
|
|
2430
|
-
|
|
2469
|
+
// Create a single, centralized function to process and send messages
|
|
2470
|
+
const processSpeechAndSendMessage = (text: string) => {
|
|
2471
|
+
// Skip if already processing or no text
|
|
2472
|
+
if (isProcessingSpeech || !text || text.trim().length === 0) {
|
|
2473
|
+
console.debug(
|
|
2474
|
+
'Skipping speech processing: already processing or empty text'
|
|
2475
|
+
);
|
|
2431
2476
|
return;
|
|
2432
2477
|
}
|
|
2433
2478
|
|
|
2479
|
+
try {
|
|
2480
|
+
// Set processing flag immediately
|
|
2481
|
+
isProcessingSpeech = true;
|
|
2482
|
+
|
|
2483
|
+
// Process the text
|
|
2484
|
+
const message = stripDuplicates(text);
|
|
2485
|
+
console.debug('Processing speech message:', message);
|
|
2486
|
+
|
|
2487
|
+
if (message.length > 0) {
|
|
2488
|
+
// Update UI states
|
|
2489
|
+
setIsProcessingSTT(true);
|
|
2490
|
+
setUserMessage('');
|
|
2491
|
+
|
|
2492
|
+
// Send the message
|
|
2493
|
+
console.debug('Sending message:', message);
|
|
2494
|
+
sendMessage(message);
|
|
2495
|
+
|
|
2496
|
+
// Reset states
|
|
2497
|
+
resetTranscript();
|
|
2498
|
+
clearListening();
|
|
2499
|
+
}
|
|
2500
|
+
} finally {
|
|
2501
|
+
// Reset processing flag after a short delay to prevent race conditions
|
|
2502
|
+
setTimeout(() => {
|
|
2503
|
+
isProcessingSpeech = false;
|
|
2504
|
+
}, 1000);
|
|
2505
|
+
}
|
|
2506
|
+
};
|
|
2507
|
+
|
|
2508
|
+
// Update handleRecognizedSpeech to use the centralized function
|
|
2509
|
+
const handleRecognizedSpeech = (text: string) => {
|
|
2510
|
+
console.debug('Speech recognized:', text);
|
|
2434
2511
|
setTranscript(text);
|
|
2435
2512
|
setIsSpeaking(false);
|
|
2436
2513
|
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2514
|
+
// Don't process here - wait for timeout or explicit processing
|
|
2515
|
+
if (!continuousSpeech) {
|
|
2516
|
+
// For manual mode, process immediately
|
|
2517
|
+
processSpeechAndSendMessage(text);
|
|
2441
2518
|
}
|
|
2519
|
+
// For continuous mode, rely on the timeout
|
|
2442
2520
|
};
|
|
2443
2521
|
|
|
2444
|
-
//
|
|
2522
|
+
// Update handleTranscriptProcessing to use the centralized function
|
|
2445
2523
|
const handleTranscriptProcessing = () => {
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
sendMessage(message);
|
|
2449
|
-
resetTranscript();
|
|
2450
|
-
setUserMessage('');
|
|
2451
|
-
clearListening();
|
|
2524
|
+
if (transcript && transcript.length > 0 && listening) {
|
|
2525
|
+
processSpeechAndSendMessage(transcript);
|
|
2452
2526
|
} else if (listening) {
|
|
2453
2527
|
resetInteractionTimeout();
|
|
2454
2528
|
}
|
|
@@ -2458,14 +2532,32 @@ const MemoriWidget = ({
|
|
|
2458
2532
|
* Stops the speech recognition process
|
|
2459
2533
|
* Closes recognizer and cleans up resources
|
|
2460
2534
|
*/
|
|
2461
|
-
|
|
2535
|
+
// Similarly, modify stopListening to use promises
|
|
2536
|
+
// Enhance stopListening to fully release resources
|
|
2537
|
+
const stopListening = async () => {
|
|
2462
2538
|
console.debug('Stopping speech recognition');
|
|
2539
|
+
|
|
2540
|
+
// Stop the recognizer
|
|
2463
2541
|
if (recognizer) {
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2542
|
+
try {
|
|
2543
|
+
recognizer.stopContinuousRecognitionAsync();
|
|
2544
|
+
recognizer.close();
|
|
2545
|
+
} catch (error) {
|
|
2546
|
+
console.error('Error stopping recognizer:', error);
|
|
2547
|
+
}
|
|
2467
2548
|
recognizer = null;
|
|
2468
2549
|
}
|
|
2550
|
+
|
|
2551
|
+
// Release the microphone stream
|
|
2552
|
+
if (microphoneStream) {
|
|
2553
|
+
try {
|
|
2554
|
+
microphoneStream.getTracks().forEach(track => track.stop());
|
|
2555
|
+
} catch (error) {
|
|
2556
|
+
console.error('Error stopping microphone stream:', error);
|
|
2557
|
+
}
|
|
2558
|
+
microphoneStream = null;
|
|
2559
|
+
}
|
|
2560
|
+
|
|
2469
2561
|
setListening(false);
|
|
2470
2562
|
};
|
|
2471
2563
|
|
|
@@ -39,7 +39,7 @@ const FileUploadButton = ({
|
|
|
39
39
|
}) => {
|
|
40
40
|
// State for loading indicator
|
|
41
41
|
const [isLoading, setIsLoading] = useState(false);
|
|
42
|
-
// State for tracking upload errors
|
|
42
|
+
// State for tracking upload errors
|
|
43
43
|
const [errors, setErrors] = useState<UploadError[]>([]);
|
|
44
44
|
// Reference to hidden file input
|
|
45
45
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
@@ -122,7 +122,7 @@ const FileUploadButton = ({
|
|
|
122
122
|
const validateFile = (file: File): boolean => {
|
|
123
123
|
const fileExt = `.${file.name.split('.').pop()?.toLowerCase()}`;
|
|
124
124
|
const ALLOWED_FILE_TYPES = ['.pdf', '.txt'];
|
|
125
|
-
|
|
125
|
+
|
|
126
126
|
if (!ALLOWED_FILE_TYPES.includes(fileExt)) {
|
|
127
127
|
addError({
|
|
128
128
|
message: `File type "${fileExt}" is not supported. Please use: ${ALLOWED_FILE_TYPES.join(
|
|
@@ -161,7 +161,7 @@ const FileUploadButton = ({
|
|
|
161
161
|
|
|
162
162
|
if (fileExt === 'pdf') {
|
|
163
163
|
text = await extractTextFromPDF(file);
|
|
164
|
-
} else if (fileExt === 'txt') {
|
|
164
|
+
} else if (fileExt === 'txt' || fileExt === 'json') {
|
|
165
165
|
text = await file.text();
|
|
166
166
|
}
|
|
167
167
|
|
|
@@ -241,7 +241,7 @@ const FileUploadButton = ({
|
|
|
241
241
|
<input
|
|
242
242
|
ref={fileInputRef}
|
|
243
243
|
type="file"
|
|
244
|
-
accept=".pdf,.txt"
|
|
244
|
+
accept=".pdf,.txt,.json"
|
|
245
245
|
className="memori--upload-file-input"
|
|
246
246
|
onChange={handleFileSelect}
|
|
247
247
|
multiple
|
|
@@ -126,3 +126,46 @@ div.memori--whythisanswer-skeleton-text {
|
|
|
126
126
|
margin-bottom: 0.5rem;
|
|
127
127
|
background: #ccc;
|
|
128
128
|
}
|
|
129
|
+
|
|
130
|
+
.memori--whythisanswer-title-text {
|
|
131
|
+
width: 100%;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.memori--whythisanswer-title-text-top {
|
|
135
|
+
display: flex;
|
|
136
|
+
align-items: space-between;
|
|
137
|
+
gap: 0.5rem;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.memori--whythisanswer-title-text-top p {
|
|
141
|
+
margin: 0;
|
|
142
|
+
font-size: 0.75rem;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.memori--whythisanswer-contextvars {
|
|
146
|
+
display: flex;
|
|
147
|
+
flex-wrap: wrap;
|
|
148
|
+
margin-top: 0.5rem;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.memori--whythisanswer-contextvars-card {
|
|
152
|
+
max-width: max-content;
|
|
153
|
+
padding: 0.5rem;
|
|
154
|
+
box-shadow: 0 0 0.25rem var(--memori-primary);
|
|
155
|
+
font-size: 0.75rem;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.memori--whythisanswer-contextvars-card + .memori--whythisanswer-contextvars-card {
|
|
159
|
+
margin-left: 0.5rem;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.memori--whythisanswer-contextvars-card > div > div {
|
|
163
|
+
padding: 0 !important;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.memori--whythisanswer-title-text-top-container {
|
|
167
|
+
display: flex;
|
|
168
|
+
justify-content: space-between;
|
|
169
|
+
margin-bottom: 8px;
|
|
170
|
+
gap: 0.5rem;
|
|
171
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Meta, Story } from '@storybook/react';
|
|
3
|
-
import { sessionID
|
|
3
|
+
import { sessionID } from '../../mocks/data';
|
|
4
4
|
import I18nWrapper from '../../I18nWrapper';
|
|
5
5
|
import WhyThisAnswer, { Props } from './WhyThisAnswer';
|
|
6
|
+
import { SearchMatches } from '@memori.ai/memori-api-client/dist/types';
|
|
6
7
|
|
|
7
8
|
import './WhyThisAnswer.css';
|
|
8
|
-
import { SearchMatches } from '@memori.ai/memori-api-client/dist/types';
|
|
9
9
|
|
|
10
10
|
const meta: Meta = {
|
|
11
11
|
title: 'Why This Answer',
|
|
@@ -69,6 +69,7 @@ WithData.args = {
|
|
|
69
69
|
confidenceLevel: 'HIGH',
|
|
70
70
|
memory: {
|
|
71
71
|
memoryID: '1',
|
|
72
|
+
memoryType: 'Question',
|
|
72
73
|
title: 'This is the title of the content',
|
|
73
74
|
titleVariants: [
|
|
74
75
|
"This is a variant of the content's title",
|
|
@@ -89,6 +90,7 @@ WithData.args = {
|
|
|
89
90
|
confidenceLevel: 'LOW',
|
|
90
91
|
memory: {
|
|
91
92
|
memoryID: '2',
|
|
93
|
+
memoryType: 'Question',
|
|
92
94
|
title: 'Content with a long answer',
|
|
93
95
|
titleVariants: undefined,
|
|
94
96
|
answers: [
|
|
@@ -105,6 +107,7 @@ WithData.args = {
|
|
|
105
107
|
memoryID: '3',
|
|
106
108
|
title: 'Content with sources',
|
|
107
109
|
titleVariants: undefined,
|
|
110
|
+
memoryType: 'Question',
|
|
108
111
|
answers: [
|
|
109
112
|
{
|
|
110
113
|
text: 'This is a test answer',
|
|
@@ -130,9 +133,9 @@ WithData.args = {
|
|
|
130
133
|
confidence: 0.7,
|
|
131
134
|
confidenceLevel: 'MEDIUM',
|
|
132
135
|
memory: {
|
|
133
|
-
...memoryQuestion,
|
|
134
136
|
memoryID: '4',
|
|
135
137
|
title: 'Content with links',
|
|
138
|
+
memoryType: 'Question',
|
|
136
139
|
titleVariants: undefined,
|
|
137
140
|
answers: [
|
|
138
141
|
{
|
|
@@ -155,5 +158,43 @@ WithData.args = {
|
|
|
155
158
|
],
|
|
156
159
|
},
|
|
157
160
|
} as SearchMatches,
|
|
161
|
+
{
|
|
162
|
+
confidence: 0.7,
|
|
163
|
+
confidenceLevel: 'MEDIUM',
|
|
164
|
+
memory: {
|
|
165
|
+
memoryID: '5',
|
|
166
|
+
memoryType: 'Question',
|
|
167
|
+
title: 'Content with receiver',
|
|
168
|
+
titleVariants: undefined,
|
|
169
|
+
receiverName: 'receiver',
|
|
170
|
+
receiverTag: '🧑💻',
|
|
171
|
+
answers: [
|
|
172
|
+
{
|
|
173
|
+
text: 'This is a an answer',
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
media: [],
|
|
177
|
+
},
|
|
178
|
+
} as SearchMatches,
|
|
179
|
+
{
|
|
180
|
+
confidence: 0.5,
|
|
181
|
+
confidenceLevel: 'MEDIUM',
|
|
182
|
+
memory: {
|
|
183
|
+
memoryID: '5',
|
|
184
|
+
memoryType: 'Question',
|
|
185
|
+
title: 'Content with context',
|
|
186
|
+
titleVariants: undefined,
|
|
187
|
+
contextVars: {
|
|
188
|
+
KEY1: 'VALUE1',
|
|
189
|
+
KEY2: 'VALUE2',
|
|
190
|
+
},
|
|
191
|
+
answers: [
|
|
192
|
+
{
|
|
193
|
+
text: 'This is a an answer',
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
media: [],
|
|
197
|
+
},
|
|
198
|
+
} as SearchMatches,
|
|
158
199
|
],
|
|
159
200
|
};
|