@memori.ai/memori-react 8.40.4 → 8.41.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/components/MemoriWidget/MemoriWidget.js +123 -26
  3. package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
  4. package/dist/helpers/nats/getNatsConfig.d.ts +4 -0
  5. package/dist/helpers/nats/getNatsConfig.js +42 -5
  6. package/dist/helpers/nats/getNatsConfig.js.map +1 -1
  7. package/dist/helpers/nats/isSessionExpiredError.d.ts +3 -0
  8. package/dist/helpers/nats/isSessionExpiredError.js +37 -0
  9. package/dist/helpers/nats/isSessionExpiredError.js.map +1 -0
  10. package/dist/helpers/nats/useNats.js +6 -2
  11. package/dist/helpers/nats/useNats.js.map +1 -1
  12. package/dist/helpers/nats/useNatsSession.d.ts +2 -1
  13. package/dist/helpers/nats/useNatsSession.js +122 -25
  14. package/dist/helpers/nats/useNatsSession.js.map +1 -1
  15. package/dist/locales/de.json +1 -0
  16. package/dist/locales/en.json +1 -0
  17. package/dist/locales/es.json +1 -0
  18. package/dist/locales/fr.json +1 -0
  19. package/dist/locales/it.json +1 -0
  20. package/dist/version.d.ts +1 -1
  21. package/dist/version.js +1 -1
  22. package/esm/components/MemoriWidget/MemoriWidget.js +123 -26
  23. package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
  24. package/esm/helpers/nats/getNatsConfig.d.ts +4 -0
  25. package/esm/helpers/nats/getNatsConfig.js +40 -4
  26. package/esm/helpers/nats/getNatsConfig.js.map +1 -1
  27. package/esm/helpers/nats/isSessionExpiredError.d.ts +3 -0
  28. package/esm/helpers/nats/isSessionExpiredError.js +32 -0
  29. package/esm/helpers/nats/isSessionExpiredError.js.map +1 -0
  30. package/esm/helpers/nats/useNats.js +6 -2
  31. package/esm/helpers/nats/useNats.js.map +1 -1
  32. package/esm/helpers/nats/useNatsSession.d.ts +2 -1
  33. package/esm/helpers/nats/useNatsSession.js +123 -26
  34. package/esm/helpers/nats/useNatsSession.js.map +1 -1
  35. package/esm/locales/de.json +1 -0
  36. package/esm/locales/en.json +1 -0
  37. package/esm/locales/es.json +1 -0
  38. package/esm/locales/fr.json +1 -0
  39. package/esm/locales/it.json +1 -0
  40. package/esm/version.d.ts +1 -1
  41. package/esm/version.js +1 -1
  42. package/package.json +2 -1
  43. package/src/components/MemoriWidget/MemoriWidget.tsx +195 -46
  44. package/src/helpers/nats/getNatsConfig.ts +83 -7
  45. package/src/helpers/nats/isSessionExpiredError.test.ts +38 -0
  46. package/src/helpers/nats/isSessionExpiredError.ts +51 -0
  47. package/src/helpers/nats/useNats.ts +8 -6
  48. package/src/helpers/nats/useNatsSession.ts +203 -39
  49. package/src/index.stories.tsx +16 -0
  50. package/src/locales/de.json +1 -0
  51. package/src/locales/en.json +1 -0
  52. package/src/locales/es.json +1 -0
  53. package/src/locales/fr.json +1 -0
  54. package/src/locales/it.json +1 -0
  55. package/src/version.ts +1 -1
@@ -1,5 +1,6 @@
1
- import { useEffect, useRef } from 'react';
1
+ import { useEffect, useRef, useState } from 'react';
2
2
  import { wsconnect } from '@nats-io/nats-core';
3
+ import { jetstream, DeliverPolicy, } from '@nats-io/jetstream';
3
4
  function readString(raw, camelKey, snakeKey) {
4
5
  var _a;
5
6
  const value = (_a = raw[camelKey]) !== null && _a !== void 0 ? _a : raw[snakeKey];
@@ -57,24 +58,123 @@ export function normalizeNatsEvent(raw) {
57
58
  correlationID,
58
59
  };
59
60
  }
60
- export function useNatsSession(sessionId, natsWsUrl, natsToken, onMessage) {
61
+ function decodeMessage(subject, received, raw, onMessage) {
62
+ const payload = normalizeNatsEvent(raw);
63
+ console.debug(`[NATS] message #${received} on ${subject} (eventType=${payload.eventType})`, payload);
64
+ onMessage(payload);
65
+ }
66
+ async function consumeCoreSubscription(nc, subject, onMessage) {
67
+ const sub = nc.subscribe(subject);
68
+ console.info('[NATS] subscribed to subject', subject);
69
+ let received = 0;
70
+ for await (const msg of sub) {
71
+ received += 1;
72
+ try {
73
+ decodeMessage(subject, received, msg.json(), onMessage);
74
+ }
75
+ catch (err) {
76
+ console.error('[NATS] message decode error', err);
77
+ }
78
+ }
79
+ console.info(`[NATS] subscription on ${subject} closed (received ${received} messages)`);
80
+ }
81
+ async function consumeJetStream(nc, config, subject, mode, onMessage, setConsumerMessages) {
82
+ const js = jetstream(nc);
83
+ const consumer = config.consumer
84
+ ? await js.consumers.get(config.stream, config.consumer)
85
+ : await js.consumers.get(config.stream, {
86
+ filter_subjects: [subject],
87
+ deliver_policy: mode === 'catch-up'
88
+ ? DeliverPolicy.LastPerSubject
89
+ : DeliverPolicy.New,
90
+ });
91
+ console.info('[NATS] JetStream consumer ready', config.consumer
92
+ ? { stream: config.stream, consumer: config.consumer, subject, mode }
93
+ : { stream: config.stream, subject, mode });
94
+ const messages = await consumer.consume();
95
+ setConsumerMessages(messages);
96
+ let received = 0;
97
+ for await (const msg of messages) {
98
+ received += 1;
99
+ try {
100
+ decodeMessage(subject, received, msg.json(), onMessage);
101
+ }
102
+ catch (err) {
103
+ console.error('[NATS] message decode error', err);
104
+ }
105
+ }
106
+ console.info(`[NATS] JetStream consumer on ${subject} closed (received ${received} messages)`);
107
+ }
108
+ function closeNatsSession(consumerMessagesRef, connRef) {
109
+ var _a, _b;
110
+ (_a = consumerMessagesRef.current) === null || _a === void 0 ? void 0 : _a.stop();
111
+ consumerMessagesRef.current = null;
112
+ (_b = connRef.current) === null || _b === void 0 ? void 0 : _b.close();
113
+ connRef.current = null;
114
+ }
115
+ export function useNatsSession(sessionId, config, onMessage) {
61
116
  const connRef = useRef(null);
117
+ const consumerMessagesRef = useRef(null);
62
118
  const onMessageRef = useRef(onMessage);
119
+ const wasHiddenRef = useRef(false);
120
+ const [resumeGeneration, setResumeGeneration] = useState(0);
63
121
  useEffect(() => {
64
122
  onMessageRef.current = onMessage;
65
123
  }, [onMessage]);
66
124
  useEffect(() => {
67
- if (!sessionId || !natsWsUrl || !natsToken) {
68
- console.debug('[NATS] subscription skipped (missing sessionId/url/token)', { sessionId, hasUrl: !!natsWsUrl, hasToken: !!natsToken });
125
+ if (!sessionId || !(config === null || config === void 0 ? void 0 : config.stream)) {
126
+ return;
127
+ }
128
+ const requestResume = () => {
129
+ if (document.visibilityState !== 'visible') {
130
+ return;
131
+ }
132
+ console.info('[NATS] resuming JetStream after visibility/network change');
133
+ setResumeGeneration(generation => generation + 1);
134
+ };
135
+ const onVisibilityChange = () => {
136
+ if (document.visibilityState === 'hidden') {
137
+ wasHiddenRef.current = true;
138
+ return;
139
+ }
140
+ if (wasHiddenRef.current) {
141
+ wasHiddenRef.current = false;
142
+ requestResume();
143
+ }
144
+ };
145
+ const onPageShow = (event) => {
146
+ if (event.persisted) {
147
+ requestResume();
148
+ }
149
+ };
150
+ document.addEventListener('visibilitychange', onVisibilityChange);
151
+ window.addEventListener('online', requestResume);
152
+ window.addEventListener('pageshow', onPageShow);
153
+ return () => {
154
+ document.removeEventListener('visibilitychange', onVisibilityChange);
155
+ window.removeEventListener('online', requestResume);
156
+ window.removeEventListener('pageshow', onPageShow);
157
+ };
158
+ }, [sessionId, config === null || config === void 0 ? void 0 : config.stream]);
159
+ useEffect(() => {
160
+ var _a;
161
+ if (!sessionId || !(config === null || config === void 0 ? void 0 : config.url) || !config.token) {
162
+ console.debug('[NATS] subscription skipped (missing sessionId/url/token)', {
163
+ sessionId,
164
+ hasUrl: !!(config === null || config === void 0 ? void 0 : config.url),
165
+ hasToken: !!(config === null || config === void 0 ? void 0 : config.token),
166
+ });
69
167
  return;
70
168
  }
71
169
  let closed = false;
72
- const subject = sessionId;
170
+ const subject = (_a = config.subject) !== null && _a !== void 0 ? _a : `sessions.${sessionId}`;
171
+ const useJetStream = !!config.stream;
172
+ const jetStreamMode = useJetStream && resumeGeneration > 0 ? 'catch-up' : 'live';
73
173
  (async () => {
74
- console.info('[NATS] connecting to', natsWsUrl, 'for session', sessionId);
174
+ console.info('[NATS] connecting to', config.url, 'for session', sessionId, useJetStream ? `(JetStream/${jetStreamMode})` : '(core)');
75
175
  const nc = await wsconnect({
76
- servers: [natsWsUrl],
77
- token: natsToken,
176
+ servers: [config.url],
177
+ token: config.token,
78
178
  });
79
179
  if (closed) {
80
180
  console.debug('[NATS] connection established after cleanup, closing immediately');
@@ -83,29 +183,26 @@ export function useNatsSession(sessionId, natsWsUrl, natsToken, onMessage) {
83
183
  }
84
184
  connRef.current = nc;
85
185
  console.info('[NATS] connected to', nc.getServer());
86
- const sub = nc.subscribe(subject);
87
- console.info('[NATS] subscribed to subject', subject);
88
- let received = 0;
89
- for await (const msg of sub) {
90
- received += 1;
91
- try {
92
- const payload = normalizeNatsEvent(msg.json());
93
- console.debug(`[NATS] message #${received} on ${subject} (eventType=${payload.eventType})`, payload);
94
- onMessageRef.current(payload);
95
- }
96
- catch (err) {
97
- console.error('[NATS] message decode error', err);
98
- }
186
+ const dispatch = (event) => {
187
+ onMessageRef.current(event);
188
+ };
189
+ if (useJetStream) {
190
+ await consumeJetStream(nc, config, subject, jetStreamMode, dispatch, messages => {
191
+ consumerMessagesRef.current = messages;
192
+ });
193
+ }
194
+ else {
195
+ await consumeCoreSubscription(nc, subject, dispatch);
99
196
  }
100
- console.info(`[NATS] subscription on ${subject} closed (received ${received} messages)`);
101
197
  })().catch(err => console.error('[NATS] connection error', err));
102
198
  return () => {
103
- var _a;
104
199
  console.info('[NATS] cleanup: closing connection for subject', subject);
105
200
  closed = true;
106
- (_a = connRef.current) === null || _a === void 0 ? void 0 : _a.close();
107
- connRef.current = null;
201
+ closeNatsSession(consumerMessagesRef, connRef);
108
202
  };
109
- }, [sessionId, natsWsUrl, natsToken]);
203
+ }, [sessionId, config, resumeGeneration]);
204
+ useEffect(() => {
205
+ setResumeGeneration(0);
206
+ }, [sessionId]);
110
207
  }
111
208
  //# sourceMappingURL=useNatsSession.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useNatsSession.js","sourceRoot":"","sources":["../../../src/helpers/nats/useNatsSession.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useNatsSession.js","sourceRoot":"","sources":["../../../src/helpers/nats/useNatsSession.ts"],"names":[],"mappings":"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"}
@@ -75,6 +75,7 @@
75
75
  "errorFetchingSession": "Fehler beim Laden der Sitzung",
76
76
  "errorGettingReferralURL": "Fehler beim Laden des Referrals",
77
77
  "errorReopeningSession": "Fehler beim erneuten Öffnen der Sitzung",
78
+ "sessionExpiredReopening": "Sitzung abgelaufen, Sitzung wird neu geöffnet",
78
79
  "ageVerification": "Altersüberprüfung",
79
80
  "ageVerificationText": "Um mit diesem Zwilling interagieren zu können, müssen Sie mindestens sein {{minAge}} Jahre alt.",
80
81
  "nsfw": "NSFW: Dieser Agent enthält Inhalte für Erwachsene",
@@ -77,6 +77,7 @@
77
77
  "errorFetchingSession": "Error during session loading",
78
78
  "errorGettingReferralURL": "Error during referral loading",
79
79
  "errorReopeningSession": "Error during session reopening",
80
+ "sessionExpiredReopening": "Session expired, reopening session",
80
81
  "ageVerification": "Age verification",
81
82
  "ageVerificationText": "To interact with this agent, you must be at least {{minAge}} years old.",
82
83
  "nsfw": "NSFW: This agent contains adult contents",
@@ -75,6 +75,7 @@
75
75
  "errorFetchingSession": "Error durante el cargamento de la sesión",
76
76
  "errorGettingReferralURL": "Error durante el cargamento del référent",
77
77
  "errorReopeningSession": "Error durante el re-abrir la sesión",
78
+ "sessionExpiredReopening": "Sesión expirada, reabriendo sesión",
78
79
  "ageVerification": "Verificación de edad",
79
80
  "ageVerificationText": "Para interactuar con este Gemelo, debes tener al menos {{minAge}} años.",
80
81
  "nsfw": "NSFW: Este gemelo contiene contenido para adultos",
@@ -74,6 +74,7 @@
74
74
  "errorFetchingSession": "Erreur lors du chargement de la session",
75
75
  "errorGettingReferralURL": "Erreur lors du chargement du référent",
76
76
  "errorReopeningSession": "Erreur lors de la re-ouverture de la session",
77
+ "sessionExpiredReopening": "Session expirée, réouverture en cours",
77
78
  "ageVerification": "Vérification de l'âge",
78
79
  "ageVerificationText": "Pour interagir avec ce Agent, vous devez être au minimum {{minAge}} ans.",
79
80
  "nsfw": "NSFW : Ce jumeau contient du contenu pour adultes",
@@ -78,6 +78,7 @@
78
78
  "errorFetchingSession": "Errore durante il caricamento della sessione",
79
79
  "errorGettingReferralURL": "Errore durante il caricamento del riferimento",
80
80
  "errorReopeningSession": "Errore durante il riapertura della sessione",
81
+ "sessionExpiredReopening": "Sessione scaduta, riapertura in corso",
81
82
  "ageVerification": "Verifica dell'età",
82
83
  "ageVerificationText": "Per interagire con questo agente, devi aver almeno {{minAge}} anni.",
83
84
  "nsfw": "NSFW: Questo agente contiene contenuti per adulti",
package/esm/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "8.40.4";
1
+ export declare const version = "8.41.1";
package/esm/version.js CHANGED
@@ -1,2 +1,2 @@
1
- export const version = '8.40.4';
1
+ export const version = '8.41.1';
2
2
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "8.40.4",
2
+ "version": "8.41.1",
3
3
  "name": "@memori.ai/memori-react",
4
4
  "author": "Memori Srl",
5
5
  "main": "dist/index.js",
@@ -294,6 +294,7 @@
294
294
  "dependencies": {
295
295
  "@headlessui/react": "1.7.4",
296
296
  "@memori.ai/memori-api-client": "6.24.1",
297
+ "@nats-io/jetstream": "^3.4.0",
297
298
  "@nats-io/nats-core": "^3.4.0",
298
299
  "@react-three/drei": "8.20.2",
299
300
  "@react-three/fiber": "7.0.25",
@@ -91,6 +91,10 @@ import {
91
91
  NatsDialogResponseEvent,
92
92
  NatsErrorEvent,
93
93
  } from '../../helpers/nats/useNatsSession';
94
+ import {
95
+ isSessionExpiredNatsError,
96
+ isSessionExpiredNatsResponse,
97
+ } from '../../helpers/nats/isSessionExpiredError';
94
98
 
95
99
  // Widget utilities and helpers
96
100
  const getMemoriState = (integrationId?: string): object | null => {
@@ -646,11 +650,21 @@ const MemoriWidget = ({
646
650
  const [memoriTyping, setMemoriTyping] = useState<boolean>(false);
647
651
  const [typingText, setTypingText] = useState<string>();
648
652
 
649
- type PendingEnterText = {
650
- msg?: string;
653
+ type EnterTextRetryParams = {
654
+ text?: string;
655
+ media?: Medium[];
656
+ translate?: boolean;
657
+ translatedText?: string;
658
+ hidden?: boolean;
651
659
  typingText?: string;
652
660
  useLoaderTextAsMsg?: boolean;
653
661
  hasBatchQueued?: boolean;
662
+ expiredSessionID?: string;
663
+ continueFromChatLogID?: string;
664
+ };
665
+
666
+ type PendingEnterText = EnterTextRetryParams & {
667
+ msg?: string;
654
668
  waitForResponse?: {
655
669
  resolve: (event: NatsDialogResponseEvent) => void;
656
670
  reject: (error: Error) => void;
@@ -893,6 +907,7 @@ const MemoriWidget = ({
893
907
  * @param typingText Optional custom typing indicator text
894
908
  * @param useLoaderTextAsMsg Whether to use the loader text as the message (default false)
895
909
  * @param hasBatchQueued Whether there are more messages queued to be sent (default false)
910
+ * @param skipHistoryPush Skip adding the user message to history (e.g. session-expired retry)
896
911
  */
897
912
  const sendMessage = async (
898
913
  text: string,
@@ -903,7 +918,8 @@ const MemoriWidget = ({
903
918
  hidden: boolean = false,
904
919
  typingText?: string,
905
920
  useLoaderTextAsMsg = false,
906
- hasBatchQueued = false
921
+ hasBatchQueued = false,
922
+ skipHistoryPush = false
907
923
  ) => {
908
924
  // Get the session ID from params or global state
909
925
  const sessionID =
@@ -970,7 +986,7 @@ const MemoriWidget = ({
970
986
  }
971
987
 
972
988
  // Add user message to chat history if not hidden
973
- if (!hidden)
989
+ if (!hidden && !skipHistoryPush)
974
990
  pushMessage({
975
991
  text: text,
976
992
  translatedText,
@@ -998,6 +1014,11 @@ const MemoriWidget = ({
998
1014
  if (response.resultCode === 0 && correlationID) {
999
1015
  registerPendingEnterText(correlationID, {
1000
1016
  msg,
1017
+ text,
1018
+ media,
1019
+ translate,
1020
+ translatedText,
1021
+ hidden,
1001
1022
  typingText,
1002
1023
  useLoaderTextAsMsg,
1003
1024
  hasBatchQueued,
@@ -1007,34 +1028,17 @@ const MemoriWidget = ({
1007
1028
  } else if (response.resultCode === 0) {
1008
1029
  logWidgetError('enter-text missing correlationID', response);
1009
1030
  } else if (response.resultCode === 404) {
1010
- // Handle expired session
1011
- // remove last sent message, will set it as initial
1012
- setHistory(h => [...h.slice(0, h.length - 1)]);
1013
-
1014
- reopenSession(
1015
- true,
1016
- memoriPwd || memori.secretToken,
1017
- memoriTokens,
1018
- undefined,
1019
- undefined,
1020
- {
1021
- LANG: userLang,
1022
- PATHNAME: window.location.pathname,
1023
- ROUTE: window.location.pathname?.split('/')?.pop() || '',
1024
- ...(initialContextVars || {}),
1025
- },
1026
- initialQuestion,
1027
- undefined,
1028
- undefined,
1029
- undefined,
1030
- undefined,
1031
- true // isSessionExpired
1032
- ).then(state => {
1033
- if (state?.sessionID) {
1034
- setTimeout(() => {
1035
- sendMessage(text, media, state?.sessionID);
1036
- }, 500);
1037
- }
1031
+ retryAfterExpiredSessionRef.current({
1032
+ text,
1033
+ media,
1034
+ translate,
1035
+ translatedText,
1036
+ hidden,
1037
+ typingText,
1038
+ useLoaderTextAsMsg,
1039
+ hasBatchQueued,
1040
+ expiredSessionID: sessionID,
1041
+ continueFromChatLogID: chatLogID,
1038
1042
  });
1039
1043
  } else if (response.resultCode === 500 && response.resultMessage) {
1040
1044
  setHistory(h => [
@@ -1487,7 +1491,8 @@ const MemoriWidget = ({
1487
1491
  additionalInfoProp?: { [key: string]: string | undefined },
1488
1492
  continueFromChatLogID?: string,
1489
1493
  continueFromSessionID?: string,
1490
- isSessionExpired?: boolean
1494
+ isSessionExpired?: boolean,
1495
+ suppressHistoryUpdate?: boolean
1491
1496
  ) => {
1492
1497
  // Set loading state while reopening session
1493
1498
  setLoading(true);
@@ -1577,12 +1582,28 @@ const MemoriWidget = ({
1577
1582
  if (updateDialogState) {
1578
1583
  setCurrentDialogState(currentState);
1579
1584
 
1580
- if (currentState.emission) {
1585
+ const sessionExpiredStatus =
1586
+ isSessionExpired && history.length > 1
1587
+ ? t('sessionExpiredReopening')
1588
+ : null;
1589
+
1590
+ if (sessionExpiredStatus && suppressHistoryUpdate) {
1591
+ pushMessage({
1592
+ text: '',
1593
+ emitter: 'system',
1594
+ fromUser: false,
1595
+ initial: sessionExpiredStatus as any,
1596
+ contextVars: {},
1597
+ date: new Date().toISOString(),
1598
+ });
1599
+ }
1600
+
1601
+ if (currentState.emission && !suppressHistoryUpdate) {
1581
1602
  // Determine initial status message based on context
1582
1603
  // Show status message only if session expired and there's existing history
1583
1604
  const initialStatus =
1584
- isSessionExpired && history.length > 1
1585
- ? 'Session Expired, reopening session'
1605
+ sessionExpiredStatus
1606
+ ? sessionExpiredStatus
1586
1607
  : history.length <= 1
1587
1608
  ? true
1588
1609
  : undefined;
@@ -1661,6 +1682,94 @@ const MemoriWidget = ({
1661
1682
  return null;
1662
1683
  };
1663
1684
 
1685
+ const retryAfterExpiredSessionRef = useRef<
1686
+ (params: EnterTextRetryParams) => ReturnType<typeof reopenSession>
1687
+ >(() => Promise.resolve(null));
1688
+
1689
+ retryAfterExpiredSessionRef.current = (params: EnterTextRetryParams) => {
1690
+ const {
1691
+ text,
1692
+ media,
1693
+ translate = true,
1694
+ translatedText,
1695
+ hidden = false,
1696
+ typingText,
1697
+ useLoaderTextAsMsg = false,
1698
+ hasBatchQueued = false,
1699
+ expiredSessionID,
1700
+ continueFromChatLogID: continueFromChatLogIDParam,
1701
+ } = params;
1702
+
1703
+ const continueFromSessionID = expiredSessionID ?? sessionId;
1704
+ const continueFromChatLogID = continueFromChatLogIDParam ?? chatLogID;
1705
+
1706
+ const reopenAfterExpiry = () =>
1707
+ reopenSession(
1708
+ true,
1709
+ memoriPwd || memori.secretToken,
1710
+ memoriTokens,
1711
+ undefined,
1712
+ undefined,
1713
+ {
1714
+ LANG: userLang,
1715
+ PATHNAME: window.location.pathname,
1716
+ ROUTE: window.location.pathname?.split('/')?.pop() || '',
1717
+ ...(initialContextVars || {}),
1718
+ },
1719
+ initialQuestion,
1720
+ undefined,
1721
+ undefined,
1722
+ continueFromChatLogID,
1723
+ continueFromSessionID,
1724
+ true,
1725
+ true
1726
+ );
1727
+
1728
+ const scheduleRetry = (newSessionID: string) => {
1729
+ setTimeout(() => {
1730
+ sendMessage(
1731
+ text!,
1732
+ media,
1733
+ newSessionID,
1734
+ translate,
1735
+ translatedText,
1736
+ hidden,
1737
+ typingText,
1738
+ useLoaderTextAsMsg,
1739
+ hasBatchQueued,
1740
+ true
1741
+ );
1742
+ }, 500);
1743
+ };
1744
+
1745
+ const handleReopenFailure = (state: Awaited<ReturnType<typeof reopenSession>>) => {
1746
+ setMemoriTyping(false);
1747
+ setTypingText(undefined);
1748
+ // `null` = explicit failure; `undefined` = auth/age modal opened (message kept in history)
1749
+ if (state === null && text && !hidden) {
1750
+ toast.error(t('errors.SESSION_EXPIRED'));
1751
+ }
1752
+ };
1753
+
1754
+ if (!text) {
1755
+ return reopenAfterExpiry().then(state => {
1756
+ if (!state?.sessionID) {
1757
+ handleReopenFailure(state);
1758
+ }
1759
+ return state;
1760
+ });
1761
+ }
1762
+
1763
+ return reopenAfterExpiry().then(state => {
1764
+ if (state?.sessionID) {
1765
+ scheduleRetry(state.sessionID);
1766
+ } else {
1767
+ handleReopenFailure(state);
1768
+ }
1769
+ return state;
1770
+ });
1771
+ };
1772
+
1664
1773
  const changeTag = async (
1665
1774
  memoriId: string,
1666
1775
  sessionId: string,
@@ -1990,6 +2099,24 @@ const MemoriWidget = ({
1990
2099
  const currentState = event.currentState;
1991
2100
 
1992
2101
  if (event.resultCode !== 0 || !currentState) {
2102
+ if (isSessionExpiredNatsResponse(event) && pending.text) {
2103
+ setMemoriTyping(false);
2104
+ setTypingText(undefined);
2105
+ retryAfterExpiredSessionRef.current({
2106
+ text: pending.text,
2107
+ media: pending.media,
2108
+ translate: pending.translate,
2109
+ translatedText: pending.translatedText,
2110
+ hidden: pending.hidden,
2111
+ typingText: pending.typingText,
2112
+ useLoaderTextAsMsg: pending.useLoaderTextAsMsg,
2113
+ hasBatchQueued: pending.hasBatchQueued,
2114
+ expiredSessionID: sessionId,
2115
+ continueFromChatLogID: chatLogID,
2116
+ });
2117
+ return;
2118
+ }
2119
+
1993
2120
  if (event.resultCode === 500 && event.resultMessage) {
1994
2121
  setHistory(h => [
1995
2122
  ...h,
@@ -2083,6 +2210,38 @@ const MemoriWidget = ({
2083
2210
  const deliverEnterTextNatsError = useCallback(
2084
2211
  (event: NatsErrorEvent) => {
2085
2212
  const correlationID = event.correlationID;
2213
+ let pending: PendingEnterText | undefined;
2214
+
2215
+ if (correlationID) {
2216
+ pending = pendingEnterTextRef.current.get(correlationID);
2217
+ if (pending) {
2218
+ clearEnterTextPending(correlationID, pending);
2219
+ pending.waitForResponse?.reject(
2220
+ new Error(
2221
+ event.errorMessage ?? String(event.errorCode ?? 'NATS error')
2222
+ )
2223
+ );
2224
+ }
2225
+ }
2226
+
2227
+ if (isSessionExpiredNatsError(event) && pending?.text) {
2228
+ setMemoriTyping(false);
2229
+ setTypingText(undefined);
2230
+ retryAfterExpiredSessionRef.current({
2231
+ text: pending.text,
2232
+ media: pending.media,
2233
+ translate: pending.translate,
2234
+ translatedText: pending.translatedText,
2235
+ hidden: pending.hidden,
2236
+ typingText: pending.typingText,
2237
+ useLoaderTextAsMsg: pending.useLoaderTextAsMsg,
2238
+ hasBatchQueued: pending.hasBatchQueued,
2239
+ expiredSessionID: sessionId,
2240
+ continueFromChatLogID: chatLogID,
2241
+ });
2242
+ return;
2243
+ }
2244
+
2086
2245
  const errorText = event.errorMessage
2087
2246
  ? `Error: ${event.errorMessage}`
2088
2247
  : event.errorCode
@@ -2098,16 +2257,6 @@ const MemoriWidget = ({
2098
2257
  date: new Date().toISOString(),
2099
2258
  });
2100
2259
 
2101
- if (correlationID) {
2102
- const pending = pendingEnterTextRef.current.get(correlationID);
2103
- if (pending) {
2104
- clearEnterTextPending(correlationID, pending);
2105
- pending.waitForResponse?.reject(
2106
- new Error(event.errorMessage ?? String(event.errorCode ?? 'NATS error'))
2107
- );
2108
- }
2109
- }
2110
-
2111
2260
  setMemoriTyping(false);
2112
2261
  setTypingText(undefined);
2113
2262
  },