@memori.ai/memori-react 8.7.0 → 8.7.2

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.
@@ -417,6 +417,7 @@ export interface Props {
417
417
  applyVarsToRoot?: boolean;
418
418
  showFunctionCache?: boolean;
419
419
  authToken?: string;
420
+ __WEBCOMPONENT__?: boolean;
420
421
  }
421
422
 
422
423
  const MemoriWidget = ({
@@ -467,6 +468,7 @@ const MemoriWidget = ({
467
468
  additionalSettings,
468
469
  customMediaRenderer,
469
470
  userAvatar,
471
+ __WEBCOMPONENT__ = false,
470
472
  useMathFormatting = false,
471
473
  autoStart = false,
472
474
  applyVarsToRoot = false,
@@ -1196,6 +1198,13 @@ const MemoriWidget = ({
1196
1198
  });
1197
1199
  };
1198
1200
 
1201
+ useEffect(() => {
1202
+ if (initialSessionID) {
1203
+ setSessionId(initialSessionID);
1204
+ onClickStart(undefined, false, undefined, initialSessionID);
1205
+ }
1206
+ }, [initialSessionID]);
1207
+
1199
1208
  /**
1200
1209
  * Opening Session
1201
1210
  */
@@ -2322,12 +2331,17 @@ const MemoriWidget = ({
2322
2331
  * Handles clicking the start button to begin or resume a session
2323
2332
  * @param session Optional existing session with dialog state and ID
2324
2333
  * @param initialSessionExpired Whether the initial session has expired
2325
- */
2334
+ /**
2335
+ * Handles clicking the start button to begin or resume a session
2336
+ * @param session Optional existing session with dialog state and ID
2337
+ * @param initialSessionExpired Whether the initial session has expired
2338
+ */
2326
2339
  const onClickStart = useCallback(
2327
2340
  async (
2328
2341
  session?: { dialogState: DialogState; sessionID: string },
2329
2342
  initialSessionExpired = false,
2330
- chatLog?: ChatLog
2343
+ chatLog?: ChatLog,
2344
+ targetSessionID?: string
2331
2345
  ) => {
2332
2346
  // console.log('[onClickStart] Starting with params:', {
2333
2347
  // session,
@@ -2350,7 +2364,7 @@ const MemoriWidget = ({
2350
2364
  undefined
2351
2365
  );
2352
2366
  let birth = birthDate || storageBirthDate || user?.birthDate;
2353
- if (!birth && autoStart && initialSessionID)
2367
+ if (!birth && autoStart && (initialSessionID || targetSessionID))
2354
2368
  birth = '1970-01-01T10:24:03.845Z';
2355
2369
 
2356
2370
  const localPosition = getLocalConfig<Venue | undefined>(
@@ -2416,7 +2430,6 @@ const MemoriWidget = ({
2416
2430
  if (session?.dialogState) {
2417
2431
  // reset history
2418
2432
  if (!chatLog) {
2419
- // console.log('[onClickStart] No chat log, resetting history');
2420
2433
  setHistory([]);
2421
2434
 
2422
2435
  // Use translateAndSpeak which already handles the speaking
@@ -2470,7 +2483,7 @@ const MemoriWidget = ({
2470
2483
  })
2471
2484
  );
2472
2485
  } catch (e) {
2473
- console.error('[CLICK_START] Error translating messages:', e);
2486
+ console.error('[onClickStart] Error translating messages:', e);
2474
2487
  }
2475
2488
  }
2476
2489
 
@@ -2488,16 +2501,16 @@ const MemoriWidget = ({
2488
2501
  } else if (session?.resultCode === 0) {
2489
2502
  await onClickStart((session as any) || undefined);
2490
2503
  } else {
2491
- // console.log('[onClickStart] Session creation failed');
2492
2504
  setLoading(false);
2493
2505
  }
2494
2506
 
2495
2507
  return;
2496
2508
  }
2497
2509
  // Handle initial session
2498
- else if (initialSessionID) {
2510
+ else if (initialSessionID || targetSessionID) {
2511
+ const sessionID = targetSessionID ?? initialSessionID;
2499
2512
  // check if session is valid and not expired
2500
- const { currentState, ...response } = await getSession(sessionID);
2513
+ const { currentState, ...response } = await getSession(sessionID!);
2501
2514
 
2502
2515
  if (response.resultCode !== 0 || !currentState) {
2503
2516
  setGotErrorInOpening(true);
@@ -2525,11 +2538,11 @@ const MemoriWidget = ({
2525
2538
  ) {
2526
2539
  try {
2527
2540
  // reset tag
2528
- await changeTag(memori.engineMemoriID!, sessionID, '-');
2541
+ await changeTag(memori.engineMemoriID!, sessionID!, '-');
2529
2542
  // change tag to receiver
2530
2543
  const session = await changeTag(
2531
2544
  memori.engineMemoriID!,
2532
- sessionID,
2545
+ sessionID!,
2533
2546
  personification.tag,
2534
2547
  personification.pin
2535
2548
  );
@@ -2570,11 +2583,11 @@ const MemoriWidget = ({
2570
2583
  ) {
2571
2584
  try {
2572
2585
  // reset tag
2573
- await changeTag(memori.engineMemoriID!, sessionID, '-');
2586
+ await changeTag(memori.engineMemoriID!, sessionID!, '-');
2574
2587
  // change tag to anonymous
2575
2588
  const session = await changeTag(
2576
2589
  memori.engineMemoriID!,
2577
- sessionID,
2590
+ sessionID!,
2578
2591
  anonTag
2579
2592
  );
2580
2593
 
@@ -2607,7 +2620,7 @@ const MemoriWidget = ({
2607
2620
  // No tag changes needed
2608
2621
  else {
2609
2622
  try {
2610
- const { chatLogs } = await getSessionChatLogs(sessionID, sessionID);
2623
+ const { chatLogs } = await getSessionChatLogs(sessionID!, sessionID!);
2611
2624
 
2612
2625
  const messages = chatLogs?.[0]?.lines.map(
2613
2626
  (l, i) =>
@@ -2643,13 +2656,13 @@ const MemoriWidget = ({
2643
2656
  }))
2644
2657
  );
2645
2658
  } catch (e) {
2646
- console.error('[CLICK_START] Error translating messages:', e);
2659
+ console.error('[onClickStart] Error translating messages:', e);
2647
2660
  }
2648
2661
  }
2649
2662
 
2650
2663
  setHistory(translatedMessages);
2651
2664
  } catch (e) {
2652
- console.error('[CLICK_START] Error retrieving chat logs:', e);
2665
+ console.error('[onClickStart] Error retrieving chat logs:', e);
2653
2666
  }
2654
2667
 
2655
2668
  if (
@@ -2657,6 +2670,7 @@ const MemoriWidget = ({
2657
2670
  !initialQuestion
2658
2671
  ) {
2659
2672
  // we have a history, don't push message
2673
+ setHasUserActivatedSpeak(true);
2660
2674
  await translateAndSpeak(
2661
2675
  currentState,
2662
2676
  userLang,
@@ -2666,6 +2680,7 @@ const MemoriWidget = ({
2666
2680
  !!translatedMessages?.length
2667
2681
  );
2668
2682
  } else {
2683
+ console.log('[onClickStart] Starting with initial question');
2669
2684
  // remove default initial message
2670
2685
  translatedMessages = [];
2671
2686
  setHistory([]);
@@ -2674,7 +2689,7 @@ const MemoriWidget = ({
2674
2689
 
2675
2690
  // we have no chat history, we start by initial question
2676
2691
  const response = await postTextEnteredEvent({
2677
- sessionId: sessionID,
2692
+ sessionId: sessionID!,
2678
2693
  text: initialQuestion,
2679
2694
  });
2680
2695
 
@@ -2708,10 +2723,6 @@ const MemoriWidget = ({
2708
2723
  );
2709
2724
 
2710
2725
  useEffect(() => {
2711
- // Don't auto-start for HIDDEN_CHAT layout - let the layout handle it
2712
- // console.log('clickedStart', clickedStart);
2713
- // console.log('autoStart', autoStart);
2714
- // console.log('selectedLayout', selectedLayout);
2715
2726
  if (!clickedStart && autoStart && selectedLayout !== 'HIDDEN_CHAT') {
2716
2727
  onClickStart();
2717
2728
  }
@@ -2824,6 +2835,8 @@ const MemoriWidget = ({
2824
2835
  }, [tenant?.billingDelegation, deepThoughtEnabled]);
2825
2836
 
2826
2837
  useEffect(() => {
2838
+ if (__WEBCOMPONENT__) return;
2839
+
2827
2840
  const closeSession = () => {
2828
2841
  if (sessionId) {
2829
2842
  deleteSession(sessionId);
package/src/index.tsx CHANGED
@@ -43,6 +43,7 @@ export interface Props {
43
43
  showDates?: boolean;
44
44
  showContextPerLine?: boolean;
45
45
  showSettings?: boolean;
46
+ __WEBCOMPONENT__?: boolean;
46
47
  showClear?: boolean;
47
48
  showOnlyLastMessages?: boolean;
48
49
  showTypingText?: boolean;
@@ -149,10 +150,13 @@ const Memori: React.FC<Props> = ({
149
150
  useMathFormatting = false,
150
151
  autoStart,
151
152
  applyVarsToRoot = false,
153
+ __WEBCOMPONENT__ = false,
152
154
  }) => {
153
155
  const [memori, setMemori] = useState<IMemori>();
154
156
  const [tenant, setTenant] = useState<Tenant>();
155
157
  const [provider, setProvider] = useState<string | undefined>();
158
+ const [sessionId, setSessionId] = useState<string | undefined>();
159
+
156
160
  const { t } = useTranslation();
157
161
 
158
162
  if (!((memoriID && ownerUserID) || (memoriName && ownerUserName))) {
@@ -241,6 +245,42 @@ const Memori: React.FC<Props> = ({
241
245
  fetchTenant();
242
246
  }, [fetchTenant]);
243
247
 
248
+ useEffect(() => {
249
+ const targetNode =
250
+ document.querySelector(`memori-client[memoriname="${memori?.name}"]`) ||
251
+ document.querySelector(`memori-client[memoriid="${memori?.memoriID}"]`) ||
252
+ document.querySelector('memori-client');
253
+ if (!targetNode) {
254
+ return;
255
+ }
256
+
257
+ const config = { attributes: true, childList: false, subtree: false };
258
+ const callback: MutationCallback = (mutationList, _observer) => {
259
+ for (const mutation of mutationList) {
260
+ if (
261
+ mutation.type === 'attributes' &&
262
+ mutation.attributeName?.toLowerCase() === 'authtoken'
263
+ ) {
264
+ const target =
265
+ mutation.target.nodeName === 'MEMORI-CLIENT'
266
+ ? mutation.target
267
+ : mutation.target.parentElement;
268
+ // @ts-ignore
269
+ const targetSessionId = target.getAttribute('sessionid') || undefined;
270
+ if (target && targetSessionId) {
271
+ setSessionId(targetSessionId);
272
+ }
273
+ }
274
+ }
275
+ };
276
+ const observer = new MutationObserver(callback);
277
+ observer.observe(targetNode, config);
278
+
279
+ return () => {
280
+ observer.disconnect();
281
+ };
282
+ }, []);
283
+
244
284
  /**
245
285
  * Sets the language in the i18n instance
246
286
  */
@@ -338,67 +378,71 @@ const Memori: React.FC<Props> = ({
338
378
  <I18nWrapper>
339
379
  <VisemeProvider>
340
380
  <ArtifactProvider>
341
- <Toaster position="top-center" reverseOrder={true} />
342
- {memori ? (
343
- <MemoriWidget
344
- // General props
345
- layout={layout}
346
- customLayout={customLayout}
347
- height={height}
348
- baseUrl={
349
- baseURL ||
350
- (tenantID.startsWith('https://') || tenantID.startsWith('http://')
351
- ? tenantID
352
- : `https://${tenantID}`)
353
- }
354
- apiURL={apiURL}
355
- engineURL={engineURL}
356
- memori={{
357
- ...memori,
358
- secretToken,
359
- }}
360
- ownerUserName={ownerUserName ?? memori.ownerUserName}
361
- ownerUserID={ownerUserID ?? memori.ownerUserID}
362
- tenant={tenant}
363
- tenantID={tenantID}
364
- sessionID={sessionID}
365
- secret={secretToken}
366
- ttsProvider={provider ? (provider as 'azure' | 'openai') : 'azure'}
367
- integration={layoutIntegration}
368
- authToken={authToken}
369
- onStateChange={onStateChange}
370
- additionalInfo={additionalInfo}
371
- customMediaRenderer={customMediaRenderer}
372
- additionalSettings={additionalSettings}
373
- userAvatar={userAvatar}
374
- applyVarsToRoot={applyVarsToRoot}
375
- disableTextEnteredEvents={disableTextEnteredEvents}
376
- // From layout, from client if allowed
377
- {...clientAttributes}
378
- // Client only
379
- showOnlyLastMessages={showOnlyLastMessages}
380
- showInputs={showInputs}
381
- showDates={showDates}
382
- />
383
- ) : (
384
- <div
385
- style={{
386
- display: 'flex',
387
- alignItems: 'center',
388
- justifyContent: 'center',
389
- }}
390
- >
391
- <p
381
+ <Toaster position="top-center" reverseOrder={true} />
382
+ {memori ? (
383
+ <MemoriWidget
384
+ // General props
385
+ layout={layout}
386
+ customLayout={customLayout}
387
+ height={height}
388
+ baseUrl={
389
+ baseURL ||
390
+ (tenantID.startsWith('https://') ||
391
+ tenantID.startsWith('http://')
392
+ ? tenantID
393
+ : `https://${tenantID}`)
394
+ }
395
+ apiURL={apiURL}
396
+ engineURL={engineURL}
397
+ memori={{
398
+ ...memori,
399
+ secretToken,
400
+ }}
401
+ __WEBCOMPONENT__={__WEBCOMPONENT__}
402
+ ownerUserName={ownerUserName ?? memori.ownerUserName}
403
+ ownerUserID={ownerUserID ?? memori.ownerUserID}
404
+ tenant={tenant}
405
+ tenantID={tenantID}
406
+ sessionID={sessionID ?? sessionId}
407
+ secret={secretToken}
408
+ ttsProvider={
409
+ provider ? (provider as 'azure' | 'openai') : 'azure'
410
+ }
411
+ integration={layoutIntegration}
412
+ authToken={authToken}
413
+ onStateChange={onStateChange}
414
+ additionalInfo={additionalInfo}
415
+ customMediaRenderer={customMediaRenderer}
416
+ additionalSettings={additionalSettings}
417
+ userAvatar={userAvatar}
418
+ applyVarsToRoot={applyVarsToRoot}
419
+ disableTextEnteredEvents={disableTextEnteredEvents}
420
+ // From layout, from client if allowed
421
+ {...clientAttributes}
422
+ // Client only
423
+ showOnlyLastMessages={showOnlyLastMessages}
424
+ showInputs={showInputs}
425
+ showDates={showDates}
426
+ />
427
+ ) : (
428
+ <div
392
429
  style={{
393
- textAlign: 'center',
394
- margin: '2rem auto',
395
- textTransform: 'capitalize',
430
+ display: 'flex',
431
+ alignItems: 'center',
432
+ justifyContent: 'center',
396
433
  }}
397
434
  >
398
- {t('loading') || 'Loading'}...
399
- </p>
400
- </div>
401
- )}
435
+ <p
436
+ style={{
437
+ textAlign: 'center',
438
+ margin: '2rem auto',
439
+ textTransform: 'capitalize',
440
+ }}
441
+ >
442
+ {t('loading') || 'Loading'}...
443
+ </p>
444
+ </div>
445
+ )}
402
446
  </ArtifactProvider>
403
447
  </VisemeProvider>
404
448
  </I18nWrapper>
package/src/styles.css CHANGED
@@ -12,6 +12,7 @@
12
12
  @import url('./components/ui/Expandable.css');
13
13
  @import url('./components/ui/Slider.css');
14
14
  @import url('./components/ui/Alert.css');
15
+ @import url('./components/ui/Dropdown.css');
15
16
 
16
17
  @import url('./components/CompletionProviderStatus/CompletionProviderStatus.css');
17
18
  @import url('./components/PoweredBy/PoweredBy.css');