@memori.ai/memori-react 7.19.1 → 7.21.0
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 +57 -0
- package/dist/components/Avatar/Avatar.js +3 -3
- package/dist/components/Avatar/Avatar.js.map +1 -1
- 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/Chat/Chat.js +2 -2
- package/dist/components/Chat/Chat.js.map +1 -1
- package/dist/components/ChatBubble/ChatBubble.js +12 -9
- package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
- package/dist/components/ExpertsDrawer/ExpertsDrawer.js +1 -1
- package/dist/components/ExpertsDrawer/ExpertsDrawer.js.map +1 -1
- package/dist/components/LoginDrawer/LoginDrawer.js +6 -6
- package/dist/components/LoginDrawer/LoginDrawer.js.map +1 -1
- package/dist/components/MemoriWidget/MemoriWidget.js +143 -64
- package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/dist/components/SignupForm/SignupForm.js +4 -4
- package/dist/components/SignupForm/SignupForm.js.map +1 -1
- package/dist/components/StartPanel/StartPanel.js +5 -5
- package/dist/components/StartPanel/StartPanel.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/index.js +4 -3
- package/dist/index.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/Avatar.js +3 -3
- package/esm/components/Avatar/Avatar.js.map +1 -1
- 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/Chat/Chat.js +2 -2
- package/esm/components/Chat/Chat.js.map +1 -1
- package/esm/components/ChatBubble/ChatBubble.js +12 -9
- package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
- package/esm/components/ExpertsDrawer/ExpertsDrawer.js +1 -1
- package/esm/components/ExpertsDrawer/ExpertsDrawer.js.map +1 -1
- package/esm/components/LoginDrawer/LoginDrawer.js +6 -6
- package/esm/components/LoginDrawer/LoginDrawer.js.map +1 -1
- package/esm/components/MemoriWidget/MemoriWidget.js +143 -64
- package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/esm/components/SignupForm/SignupForm.js +4 -4
- package/esm/components/SignupForm/SignupForm.js.map +1 -1
- package/esm/components/StartPanel/StartPanel.js +5 -5
- package/esm/components/StartPanel/StartPanel.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/index.js +4 -3
- package/esm/index.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/Avatar.tsx +3 -3
- 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/Chat/Chat.tsx +2 -2
- package/src/components/ChatBubble/ChatBubble.tsx +37 -26
- package/src/components/ExpertsDrawer/ExpertsDrawer.tsx +1 -1
- package/src/components/LoginDrawer/LoginDrawer.tsx +6 -6
- package/src/components/MemoriWidget/MemoriWidget.tsx +184 -78
- package/src/components/SignupForm/SignupForm.tsx +5 -5
- package/src/components/StartPanel/StartPanel.tsx +5 -5
- 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/index.tsx +5 -3
- 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/mocks/data.ts +3 -9
- package/src/components/Avatar/AvatarView/AvatarComponent/components/controllers/AnimationController.ts +0 -308
- package/src/helpers/tenant.ts +0 -47
|
@@ -55,7 +55,7 @@ const LoginDrawer = ({
|
|
|
55
55
|
__TEST__changePwd
|
|
56
56
|
? {
|
|
57
57
|
flowID: 'flowID',
|
|
58
|
-
tenant: tenant.
|
|
58
|
+
tenant: tenant.name,
|
|
59
59
|
eMail: 'email',
|
|
60
60
|
userName: 'username',
|
|
61
61
|
password: 'password',
|
|
@@ -85,12 +85,12 @@ const LoginDrawer = ({
|
|
|
85
85
|
const isEmail = mailRegEx.test(userNameOrEmail);
|
|
86
86
|
const user: User = isEmail
|
|
87
87
|
? {
|
|
88
|
-
tenant: tenant?.
|
|
88
|
+
tenant: tenant?.name,
|
|
89
89
|
eMail: userNameOrEmail,
|
|
90
90
|
password: password,
|
|
91
91
|
}
|
|
92
92
|
: {
|
|
93
|
-
tenant: tenant?.
|
|
93
|
+
tenant: tenant?.name,
|
|
94
94
|
userName: userNameOrEmail,
|
|
95
95
|
password: password,
|
|
96
96
|
};
|
|
@@ -100,7 +100,7 @@ const LoginDrawer = ({
|
|
|
100
100
|
.then(data => {
|
|
101
101
|
if (data.resultCode === -14) {
|
|
102
102
|
setUserMustChangePwd({
|
|
103
|
-
tenant: tenant.
|
|
103
|
+
tenant: tenant.name,
|
|
104
104
|
eMail: isEmail ? userNameOrEmail : undefined,
|
|
105
105
|
userName: isEmail ? undefined : userNameOrEmail,
|
|
106
106
|
password: password,
|
|
@@ -200,7 +200,7 @@ const LoginDrawer = ({
|
|
|
200
200
|
|
|
201
201
|
const form = e.currentTarget as HTMLFormElement;
|
|
202
202
|
|
|
203
|
-
const tenantID = form.tenant.value ?? tenant.
|
|
203
|
+
const tenantID = form.tenant.value ?? tenant.name;
|
|
204
204
|
const flowID = form.flowID.value ?? userMustChangePwd?.flowID;
|
|
205
205
|
const eMail = form.eMail.value ?? userMustChangePwd?.eMail;
|
|
206
206
|
const userName = form.userName.value ?? userMustChangePwd?.userName;
|
|
@@ -389,7 +389,7 @@ const LoginDrawer = ({
|
|
|
389
389
|
<input
|
|
390
390
|
type="hidden"
|
|
391
391
|
name="tenant"
|
|
392
|
-
value={userMustChangePwd.tenant ?? tenant?.
|
|
392
|
+
value={userMustChangePwd.tenant ?? tenant?.name}
|
|
393
393
|
/>
|
|
394
394
|
<input
|
|
395
395
|
type="hidden"
|
|
@@ -1959,7 +1959,9 @@ const MemoriWidget = ({
|
|
|
1959
1959
|
|
|
1960
1960
|
const phonemes = {
|
|
1961
1961
|
...(phonemesMap.common ?? {}),
|
|
1962
|
-
...(tenant?.
|
|
1962
|
+
...(tenant?.name && phonemesMap[tenant.name]
|
|
1963
|
+
? phonemesMap[tenant.name]
|
|
1964
|
+
: {}),
|
|
1963
1965
|
};
|
|
1964
1966
|
const phonemesPairs = Object.keys(phonemes).map(word => {
|
|
1965
1967
|
const phoneme =
|
|
@@ -2200,26 +2202,20 @@ const MemoriWidget = ({
|
|
|
2200
2202
|
cleanup();
|
|
2201
2203
|
};
|
|
2202
2204
|
|
|
2203
|
-
const cleanup = ()
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2205
|
+
const cleanup = () => {
|
|
2206
|
+
if (recognizer) {
|
|
2207
|
+
recognizer.stopContinuousRecognitionAsync();
|
|
2208
|
+
recognizer.close();
|
|
2209
|
+
recognizer = null;
|
|
2210
|
+
}
|
|
2208
2211
|
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
const currentSynthesizer = speechSynthesizer;
|
|
2212
|
-
speechSynthesizer = null; // Clear reference first
|
|
2213
|
-
console.debug('Closing speech synthesizer');
|
|
2214
|
-
currentSynthesizer.close();
|
|
2215
|
-
}
|
|
2216
|
-
} catch (error) {
|
|
2217
|
-
console.debug('Error during synthesizer cleanup:', error);
|
|
2218
|
-
// Even if close fails, ensure synthesizer is nullified
|
|
2212
|
+
if (speechSynthesizer) {
|
|
2213
|
+
speechSynthesizer.close();
|
|
2219
2214
|
speechSynthesizer = null;
|
|
2220
2215
|
}
|
|
2221
2216
|
|
|
2222
|
-
|
|
2217
|
+
setListening(false);
|
|
2218
|
+
clearListeningTimeout();
|
|
2223
2219
|
};
|
|
2224
2220
|
|
|
2225
2221
|
// Modify stopAudio to include speech state reset
|
|
@@ -2280,34 +2276,41 @@ const MemoriWidget = ({
|
|
|
2280
2276
|
|
|
2281
2277
|
const resetTranscript = () => {
|
|
2282
2278
|
setTranscript('');
|
|
2283
|
-
// setIsProcessingSTT(false);
|
|
2284
2279
|
};
|
|
2285
|
-
|
|
2280
|
+
// Modify setListeningTimeout to be more robust
|
|
2286
2281
|
const setListeningTimeout = () => {
|
|
2287
|
-
clearListeningTimeout();
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
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
|
+
|
|
2292
2290
|
setTranscriptTimeout(timeout as unknown as NodeJS.Timeout);
|
|
2293
2291
|
};
|
|
2294
2292
|
|
|
2295
2293
|
const clearListeningTimeout = () => {
|
|
2296
2294
|
if (transcriptTimeout) {
|
|
2295
|
+
console.debug('Clearing transcript timeout');
|
|
2297
2296
|
clearTimeout(transcriptTimeout);
|
|
2298
2297
|
setTranscriptTimeout(null);
|
|
2299
2298
|
}
|
|
2300
2299
|
};
|
|
2301
2300
|
|
|
2301
|
+
// Add safety check in resetListeningTimeout
|
|
2302
2302
|
const resetListeningTimeout = () => {
|
|
2303
2303
|
clearListeningTimeout();
|
|
2304
|
-
if (continuousSpeech) {
|
|
2304
|
+
if (continuousSpeech && !isProcessingSTT) {
|
|
2305
|
+
console.debug('Setting new listening timeout');
|
|
2305
2306
|
setListeningTimeout();
|
|
2306
2307
|
}
|
|
2307
2308
|
};
|
|
2308
|
-
|
|
2309
|
+
|
|
2310
|
+
// Make sure only one path can trigger message sending
|
|
2309
2311
|
useEffect(() => {
|
|
2310
|
-
if (!isSpeaking) {
|
|
2312
|
+
if (!isSpeaking && transcript && transcript.length > 0) {
|
|
2313
|
+
console.debug('Transcript updated while not speaking, resetting timeout');
|
|
2311
2314
|
resetListeningTimeout();
|
|
2312
2315
|
resetInteractionTimeout();
|
|
2313
2316
|
}
|
|
@@ -2323,87 +2326,126 @@ const MemoriWidget = ({
|
|
|
2323
2326
|
/**
|
|
2324
2327
|
* Listening methods
|
|
2325
2328
|
*/
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
* Sets up recognizer and begins continuous recognition
|
|
2329
|
-
*/
|
|
2329
|
+
let microphoneStream: MediaStream | null = null;
|
|
2330
|
+
// Modify startListening to ensure full cleanup before starting
|
|
2330
2331
|
const startListening = async (): Promise<void> => {
|
|
2332
|
+
console.debug('Starting speech recognition...');
|
|
2333
|
+
|
|
2331
2334
|
if (!AZURE_COGNITIVE_SERVICES_TTS_KEY) {
|
|
2335
|
+
console.error('No TTS key available');
|
|
2332
2336
|
throw new Error('No TTS key available');
|
|
2333
2337
|
}
|
|
2334
2338
|
|
|
2335
2339
|
if (!sessionId) {
|
|
2340
|
+
console.error('No session ID available');
|
|
2336
2341
|
throw new Error('No session ID available');
|
|
2337
2342
|
}
|
|
2338
2343
|
|
|
2339
|
-
//
|
|
2340
|
-
|
|
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...');
|
|
2341
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));
|
|
2342
2373
|
|
|
2343
2374
|
try {
|
|
2344
|
-
|
|
2345
|
-
//
|
|
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
|
+
}
|
|
2346
2381
|
|
|
2347
|
-
const stream = await navigator.mediaDevices.getUserMedia({
|
|
2382
|
+
const stream = await navigator.mediaDevices.getUserMedia({
|
|
2383
|
+
audio: true,
|
|
2384
|
+
});
|
|
2348
2385
|
setHasUserActivatedListening(true);
|
|
2349
2386
|
|
|
2350
2387
|
// Recreate speech config each time
|
|
2388
|
+
console.debug('Setting up speech config...');
|
|
2351
2389
|
speechConfig = setupSpeechConfig(AZURE_COGNITIVE_SERVICES_TTS_KEY);
|
|
2352
2390
|
|
|
2391
|
+
console.debug('Creating audio config and recognizer...');
|
|
2353
2392
|
const audioConfig = speechSdk.AudioConfig.fromDefaultMicrophoneInput();
|
|
2354
2393
|
recognizer = new speechSdk.SpeechRecognizer(speechConfig, audioConfig);
|
|
2355
2394
|
|
|
2356
2395
|
// Set up recognizer event handlers
|
|
2396
|
+
console.debug('Setting up recognizer handlers...');
|
|
2357
2397
|
setupRecognizerHandlers(recognizer);
|
|
2358
2398
|
|
|
2359
|
-
// Start recognition
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
console.debug(
|
|
2368
|
-
'CANCELED: Did you set the speech resource key and region values?'
|
|
2369
|
-
);
|
|
2370
|
-
stopListening();
|
|
2371
|
-
cleanup();
|
|
2372
|
-
}
|
|
2373
|
-
|
|
2374
|
-
stopListening();
|
|
2375
|
-
};
|
|
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
|
+
});
|
|
2376
2407
|
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
resetTranscript();
|
|
2380
|
-
};
|
|
2408
|
+
console.debug('Speech recognition started successfully');
|
|
2409
|
+
setListening(true);
|
|
2381
2410
|
} catch (error) {
|
|
2382
2411
|
console.error('Error in startListening:', error);
|
|
2383
|
-
|
|
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);
|
|
2384
2419
|
throw error;
|
|
2385
2420
|
}
|
|
2386
2421
|
};
|
|
2387
2422
|
|
|
2388
2423
|
const setupSpeechConfig = (AZURE_COGNITIVE_SERVICES_TTS_KEY: string) => {
|
|
2424
|
+
console.debug('Creating speech config...');
|
|
2389
2425
|
speechConfig = speechSdk.SpeechConfig.fromSubscription(
|
|
2390
2426
|
AZURE_COGNITIVE_SERVICES_TTS_KEY,
|
|
2391
2427
|
'westeurope'
|
|
2392
2428
|
);
|
|
2429
|
+
console.debug('Setting speech recognition language:', userLang);
|
|
2393
2430
|
speechConfig.speechRecognitionLanguage = getCultureCodeByLanguage(userLang);
|
|
2394
2431
|
speechConfig.speechSynthesisLanguage = getCultureCodeByLanguage(userLang);
|
|
2395
2432
|
speechConfig.speechSynthesisVoiceName = getTTSVoice(userLang); // https://docs.microsoft.com/it-it/azure/cognitive-services/speech-service/language-support#text-to-speech
|
|
2396
2433
|
return speechConfig;
|
|
2397
2434
|
};
|
|
2398
2435
|
|
|
2436
|
+
const [isProcessingSTT, setIsProcessingSTT] = useState(false);
|
|
2437
|
+
|
|
2399
2438
|
const setupRecognizerHandlers = (recognizer: speechSdk.SpeechRecognizer) => {
|
|
2400
2439
|
if (recognizer) {
|
|
2440
|
+
console.debug('Setting up recognizer event handlers...');
|
|
2401
2441
|
recognizer.recognized = (_, event) => {
|
|
2402
2442
|
// Process the recognized speech result
|
|
2443
|
+
console.debug('Recognition event received');
|
|
2403
2444
|
handleRecognizedSpeech(event.result.text);
|
|
2404
2445
|
};
|
|
2405
2446
|
|
|
2406
2447
|
// Configure speech recognition properties directly on the recognizer
|
|
2448
|
+
console.debug('Configuring recognizer properties...');
|
|
2407
2449
|
recognizer.properties.setProperty(
|
|
2408
2450
|
'SpeechServiceResponse_JsonResult',
|
|
2409
2451
|
'true'
|
|
@@ -2421,32 +2463,66 @@ const MemoriWidget = ({
|
|
|
2421
2463
|
}
|
|
2422
2464
|
};
|
|
2423
2465
|
|
|
2424
|
-
|
|
2425
|
-
|
|
2466
|
+
// Add a mutex-like flag to prevent duplicate processing
|
|
2467
|
+
let isProcessingSpeech = false;
|
|
2426
2468
|
|
|
2427
|
-
|
|
2428
|
-
|
|
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
|
+
);
|
|
2429
2476
|
return;
|
|
2430
2477
|
}
|
|
2431
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);
|
|
2432
2511
|
setTranscript(text);
|
|
2433
2512
|
setIsSpeaking(false);
|
|
2434
2513
|
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2514
|
+
// Don't process here - wait for timeout or explicit processing
|
|
2515
|
+
if (!continuousSpeech) {
|
|
2516
|
+
// For manual mode, process immediately
|
|
2517
|
+
processSpeechAndSendMessage(text);
|
|
2439
2518
|
}
|
|
2519
|
+
// For continuous mode, rely on the timeout
|
|
2440
2520
|
};
|
|
2441
2521
|
|
|
2442
|
-
//
|
|
2522
|
+
// Update handleTranscriptProcessing to use the centralized function
|
|
2443
2523
|
const handleTranscriptProcessing = () => {
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
sendMessage(message);
|
|
2447
|
-
resetTranscript();
|
|
2448
|
-
setUserMessage('');
|
|
2449
|
-
clearListening();
|
|
2524
|
+
if (transcript && transcript.length > 0 && listening) {
|
|
2525
|
+
processSpeechAndSendMessage(transcript);
|
|
2450
2526
|
} else if (listening) {
|
|
2451
2527
|
resetInteractionTimeout();
|
|
2452
2528
|
}
|
|
@@ -2456,14 +2532,32 @@ const MemoriWidget = ({
|
|
|
2456
2532
|
* Stops the speech recognition process
|
|
2457
2533
|
* Closes recognizer and cleans up resources
|
|
2458
2534
|
*/
|
|
2459
|
-
|
|
2535
|
+
// Similarly, modify stopListening to use promises
|
|
2536
|
+
// Enhance stopListening to fully release resources
|
|
2537
|
+
const stopListening = async () => {
|
|
2460
2538
|
console.debug('Stopping speech recognition');
|
|
2539
|
+
|
|
2540
|
+
// Stop the recognizer
|
|
2461
2541
|
if (recognizer) {
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2542
|
+
try {
|
|
2543
|
+
recognizer.stopContinuousRecognitionAsync();
|
|
2544
|
+
recognizer.close();
|
|
2545
|
+
} catch (error) {
|
|
2546
|
+
console.error('Error stopping recognizer:', error);
|
|
2547
|
+
}
|
|
2465
2548
|
recognizer = null;
|
|
2466
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
|
+
|
|
2467
2561
|
setListening(false);
|
|
2468
2562
|
};
|
|
2469
2563
|
|
|
@@ -2804,6 +2898,15 @@ const MemoriWidget = ({
|
|
|
2804
2898
|
birth = '1970-01-01T10:24:03.845Z';
|
|
2805
2899
|
|
|
2806
2900
|
// console.log('[CLICK_START] Using birth date:', birth);
|
|
2901
|
+
const localPosition = getLocalConfig<Venue | undefined>(
|
|
2902
|
+
'position',
|
|
2903
|
+
undefined
|
|
2904
|
+
);
|
|
2905
|
+
if (autoStart && !localPosition && memori.needsPosition) {
|
|
2906
|
+
console.log('position required', localPosition);
|
|
2907
|
+
setShowPositionDrawer(true);
|
|
2908
|
+
return;
|
|
2909
|
+
}
|
|
2807
2910
|
|
|
2808
2911
|
// Handle age verification
|
|
2809
2912
|
if (!sessionID && !!minAge && !birth) {
|
|
@@ -3681,6 +3784,9 @@ const MemoriWidget = ({
|
|
|
3681
3784
|
onClose={position => {
|
|
3682
3785
|
if (position) applyPosition(position);
|
|
3683
3786
|
setShowPositionDrawer(false);
|
|
3787
|
+
if (autoStart) {
|
|
3788
|
+
onClickStart();
|
|
3789
|
+
}
|
|
3684
3790
|
}}
|
|
3685
3791
|
/>
|
|
3686
3792
|
)}
|
|
@@ -3706,7 +3812,7 @@ const MemoriWidget = ({
|
|
|
3706
3812
|
/>
|
|
3707
3813
|
)}
|
|
3708
3814
|
|
|
3709
|
-
{showLoginDrawer && tenant?.
|
|
3815
|
+
{showLoginDrawer && tenant?.name && (
|
|
3710
3816
|
<LoginDrawer
|
|
3711
3817
|
tenant={tenant}
|
|
3712
3818
|
apiClient={client}
|
|
@@ -80,7 +80,7 @@ const SignupForm = ({
|
|
|
80
80
|
e.preventDefault();
|
|
81
81
|
const form = e.currentTarget as HTMLFormElement;
|
|
82
82
|
|
|
83
|
-
const tenantID = form.tenant.value ?? tenant.
|
|
83
|
+
const tenantID = form.tenant.value ?? tenant.name;
|
|
84
84
|
|
|
85
85
|
const eMail = (form.eMail.value ?? email).toLowerCase();
|
|
86
86
|
const userName = form.userName.value ?? username;
|
|
@@ -151,7 +151,7 @@ const SignupForm = ({
|
|
|
151
151
|
|
|
152
152
|
try {
|
|
153
153
|
const resp = await resendVerificationCode({
|
|
154
|
-
tenant: tenant?.
|
|
154
|
+
tenant: tenant?.name,
|
|
155
155
|
userName: username,
|
|
156
156
|
});
|
|
157
157
|
|
|
@@ -174,7 +174,7 @@ const SignupForm = ({
|
|
|
174
174
|
e.preventDefault();
|
|
175
175
|
const form = e.currentTarget as HTMLFormElement;
|
|
176
176
|
|
|
177
|
-
const tenantID = form.tenant.value ?? tenant.
|
|
177
|
+
const tenantID = form.tenant.value ?? tenant.name;
|
|
178
178
|
const userName = form.userName.value ?? username;
|
|
179
179
|
const pwd = form.password.value ?? password;
|
|
180
180
|
|
|
@@ -212,7 +212,7 @@ const SignupForm = ({
|
|
|
212
212
|
<form className="memori--login-drawer--form" onSubmit={validateOtp}>
|
|
213
213
|
<input type="hidden" name="userName" value={username} />
|
|
214
214
|
<input type="hidden" name="password" value={password} />
|
|
215
|
-
<input type="hidden" name="tenant" value={tenant.
|
|
215
|
+
<input type="hidden" name="tenant" value={tenant.name} />
|
|
216
216
|
|
|
217
217
|
<label htmlFor="#verificationCode">
|
|
218
218
|
{t('login.otpCode')}
|
|
@@ -244,7 +244,7 @@ const SignupForm = ({
|
|
|
244
244
|
) : (
|
|
245
245
|
<>
|
|
246
246
|
<form className="memori--login-drawer--form" onSubmit={signup}>
|
|
247
|
-
<input type="hidden" name="tenant" value={tenant.
|
|
247
|
+
<input type="hidden" name="tenant" value={tenant.name} />
|
|
248
248
|
<input type="hidden" name="referral" value={referral} />
|
|
249
249
|
|
|
250
250
|
<label htmlFor="#eMail">
|
|
@@ -106,13 +106,13 @@ const StartPanel: React.FC<Props> = ({
|
|
|
106
106
|
style={{
|
|
107
107
|
backgroundImage: `url("${getResourceUrl({
|
|
108
108
|
type: 'cover',
|
|
109
|
-
tenantID: tenant?.
|
|
109
|
+
tenantID: tenant?.name,
|
|
110
110
|
resourceURI: memori.coverURL,
|
|
111
111
|
baseURL: baseUrl,
|
|
112
112
|
apiURL: apiUrl,
|
|
113
113
|
})}"), url("${getResourceUrl({
|
|
114
114
|
type: 'cover',
|
|
115
|
-
tenantID: tenant?.
|
|
115
|
+
tenantID: tenant?.name,
|
|
116
116
|
baseURL: baseUrl,
|
|
117
117
|
apiURL: apiUrl,
|
|
118
118
|
})}")`,
|
|
@@ -150,7 +150,7 @@ const StartPanel: React.FC<Props> = ({
|
|
|
150
150
|
memori.avatarURL ??
|
|
151
151
|
getResourceUrl({
|
|
152
152
|
type: 'avatar',
|
|
153
|
-
tenantID: tenant?.
|
|
153
|
+
tenantID: tenant?.name,
|
|
154
154
|
resourceURI: memori.avatarURL,
|
|
155
155
|
baseURL: baseUrl,
|
|
156
156
|
apiURL: apiUrl,
|
|
@@ -163,14 +163,14 @@ const StartPanel: React.FC<Props> = ({
|
|
|
163
163
|
memori.avatarURL && memori.avatarURL.length > 0
|
|
164
164
|
? getResourceUrl({
|
|
165
165
|
type: 'avatar',
|
|
166
|
-
tenantID: tenant?.
|
|
166
|
+
tenantID: tenant?.name,
|
|
167
167
|
resourceURI: memori.avatarURL,
|
|
168
168
|
baseURL: baseUrl,
|
|
169
169
|
apiURL: apiUrl,
|
|
170
170
|
})
|
|
171
171
|
: getResourceUrl({
|
|
172
172
|
type: 'avatar',
|
|
173
|
-
tenantID: tenant?.
|
|
173
|
+
tenantID: tenant?.name,
|
|
174
174
|
baseURL: baseUrl,
|
|
175
175
|
apiURL: apiUrl,
|
|
176
176
|
})
|
|
@@ -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
|
+
}
|