@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
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
 
2
2
 
3
+ ## [8.41.1](https://github.com/memori-ai/memori-react/compare/v8.41.0...v8.41.1) (2026-06-25)
4
+
5
+
6
+ ### Features
7
+
8
+ * implement session expiration handling in MemoriWidget and add related tests ([65e96fa](https://github.com/memori-ai/memori-react/commit/65e96fa561462fc60abbcd71ef461cacd7b2b263))
9
+
10
+ ## [8.41.0](https://github.com/memori-ai/memori-react/compare/v8.40.4...v8.41.0) (2026-06-22)
11
+
12
+
13
+ ### Features
14
+
15
+ * integrate JetStream support in NATS configuration and session handling ([d133c95](https://github.com/memori-ai/memori-react/commit/d133c95fc9385a7e06875dadcc6ea9be444f3868))
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * update NATS subject default value to include session ID format ([dc0e7ea](https://github.com/memori-ai/memori-react/commit/dc0e7ea0a1c0eba5fb8f834df3ef55d598e05166))
21
+
3
22
  ## [8.40.4](https://github.com/memori-ai/memori-react/compare/v8.40.3...v8.40.4) (2026-06-19)
4
23
 
5
24
 
@@ -42,6 +42,7 @@ const useTTS_1 = require("../../helpers/tts/useTTS");
42
42
  const ChatHistory_1 = tslib_1.__importDefault(require("../ChatHistoryDrawer/ChatHistory"));
43
43
  const useSTT_1 = require("../../helpers/stt/useSTT");
44
44
  const useNats_1 = require("../../helpers/nats/useNats");
45
+ const isSessionExpiredError_1 = require("../../helpers/nats/isSessionExpiredError");
45
46
  const getMemoriState = (integrationId) => {
46
47
  var _a, _b, _c, _d, _f;
47
48
  let widget = integrationId
@@ -395,8 +396,8 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, ownerUserName, tenan
395
396
  });
396
397
  };
397
398
  const [chatLogID, setChatLogID] = (0, react_1.useState)(undefined);
398
- const sendMessage = async (text, media, newSessionId, translate = true, translatedText, hidden = false, typingText, useLoaderTextAsMsg = false, hasBatchQueued = false) => {
399
- var _a, _b, _c, _d;
399
+ const sendMessage = async (text, media, newSessionId, translate = true, translatedText, hidden = false, typingText, useLoaderTextAsMsg = false, hasBatchQueued = false, skipHistoryPush = false) => {
400
+ var _a, _b;
400
401
  const sessionID = newSessionId ||
401
402
  sessionId ||
402
403
  ((_a = window.getMemoriState()) === null || _a === void 0 ? void 0 : _a.sessionID);
@@ -440,7 +441,7 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, ownerUserName, tenan
440
441
  return;
441
442
  }
442
443
  }
443
- if (!hidden)
444
+ if (!hidden && !skipHistoryPush)
444
445
  pushMessage({
445
446
  text: text,
446
447
  translatedText,
@@ -465,6 +466,11 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, ownerUserName, tenan
465
466
  if (response.resultCode === 0 && correlationID) {
466
467
  registerPendingEnterText(correlationID, {
467
468
  msg,
469
+ text,
470
+ media,
471
+ translate,
472
+ translatedText,
473
+ hidden,
468
474
  typingText,
469
475
  useLoaderTextAsMsg,
470
476
  hasBatchQueued,
@@ -476,18 +482,17 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, ownerUserName, tenan
476
482
  logWidgetError('enter-text missing correlationID', response);
477
483
  }
478
484
  else if (response.resultCode === 404) {
479
- setHistory(h => [...h.slice(0, h.length - 1)]);
480
- reopenSession(true, memoriPwd || memori.secretToken, memoriTokens, undefined, undefined, {
481
- LANG: userLang,
482
- PATHNAME: window.location.pathname,
483
- ROUTE: ((_d = (_c = window.location.pathname) === null || _c === void 0 ? void 0 : _c.split('/')) === null || _d === void 0 ? void 0 : _d.pop()) || '',
484
- ...(initialContextVars || {}),
485
- }, initialQuestion, undefined, undefined, undefined, undefined, true).then(state => {
486
- if (state === null || state === void 0 ? void 0 : state.sessionID) {
487
- setTimeout(() => {
488
- sendMessage(text, media, state === null || state === void 0 ? void 0 : state.sessionID);
489
- }, 500);
490
- }
485
+ retryAfterExpiredSessionRef.current({
486
+ text,
487
+ media,
488
+ translate,
489
+ translatedText,
490
+ hidden,
491
+ typingText,
492
+ useLoaderTextAsMsg,
493
+ hasBatchQueued,
494
+ expiredSessionID: sessionID,
495
+ continueFromChatLogID: chatLogID,
491
496
  });
492
497
  }
493
498
  else if (response.resultCode === 500 && response.resultMessage) {
@@ -792,7 +797,7 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, ownerUserName, tenan
792
797
  logWidgetError('fetchSession failed', err);
793
798
  }
794
799
  };
795
- const reopenSession = async (updateDialogState = false, password, recoveryTokens, tag, pin, initialContextVars, initialQuestion, birthDate, additionalInfoProp, continueFromChatLogID, continueFromSessionID, isSessionExpired) => {
800
+ const reopenSession = async (updateDialogState = false, password, recoveryTokens, tag, pin, initialContextVars, initialQuestion, birthDate, additionalInfoProp, continueFromChatLogID, continueFromSessionID, isSessionExpired, suppressHistoryUpdate) => {
796
801
  var _a, _b, _c, _d, _f, _g, _h, _j, _k, _l, _m;
797
802
  setLoading(true);
798
803
  let storageBirthDate = (0, configuration_1.getLocalConfig)('birthDate', undefined);
@@ -851,9 +856,22 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, ownerUserName, tenan
851
856
  setSessionId(sessionID);
852
857
  if (updateDialogState) {
853
858
  setCurrentDialogState(currentState);
854
- if (currentState.emission) {
855
- const initialStatus = isSessionExpired && history.length > 1
856
- ? 'Session Expired, reopening session'
859
+ const sessionExpiredStatus = isSessionExpired && history.length > 1
860
+ ? t('sessionExpiredReopening')
861
+ : null;
862
+ if (sessionExpiredStatus && suppressHistoryUpdate) {
863
+ pushMessage({
864
+ text: '',
865
+ emitter: 'system',
866
+ fromUser: false,
867
+ initial: sessionExpiredStatus,
868
+ contextVars: {},
869
+ date: new Date().toISOString(),
870
+ });
871
+ }
872
+ if (currentState.emission && !suppressHistoryUpdate) {
873
+ const initialStatus = sessionExpiredStatus
874
+ ? sessionExpiredStatus
857
875
  : history.length <= 1
858
876
  ? true
859
877
  : undefined;
@@ -920,6 +938,50 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, ownerUserName, tenan
920
938
  setLoading(false);
921
939
  return null;
922
940
  };
941
+ const retryAfterExpiredSessionRef = (0, react_1.useRef)(() => Promise.resolve(null));
942
+ retryAfterExpiredSessionRef.current = (params) => {
943
+ const { text, media, translate = true, translatedText, hidden = false, typingText, useLoaderTextAsMsg = false, hasBatchQueued = false, expiredSessionID, continueFromChatLogID: continueFromChatLogIDParam, } = params;
944
+ const continueFromSessionID = expiredSessionID !== null && expiredSessionID !== void 0 ? expiredSessionID : sessionId;
945
+ const continueFromChatLogID = continueFromChatLogIDParam !== null && continueFromChatLogIDParam !== void 0 ? continueFromChatLogIDParam : chatLogID;
946
+ const reopenAfterExpiry = () => {
947
+ var _a, _b;
948
+ return reopenSession(true, memoriPwd || memori.secretToken, memoriTokens, undefined, undefined, {
949
+ LANG: userLang,
950
+ PATHNAME: window.location.pathname,
951
+ ROUTE: ((_b = (_a = window.location.pathname) === null || _a === void 0 ? void 0 : _a.split('/')) === null || _b === void 0 ? void 0 : _b.pop()) || '',
952
+ ...(initialContextVars || {}),
953
+ }, initialQuestion, undefined, undefined, continueFromChatLogID, continueFromSessionID, true, true);
954
+ };
955
+ const scheduleRetry = (newSessionID) => {
956
+ setTimeout(() => {
957
+ sendMessage(text, media, newSessionID, translate, translatedText, hidden, typingText, useLoaderTextAsMsg, hasBatchQueued, true);
958
+ }, 500);
959
+ };
960
+ const handleReopenFailure = (state) => {
961
+ setMemoriTyping(false);
962
+ setTypingText(undefined);
963
+ if (state === null && text && !hidden) {
964
+ react_hot_toast_1.default.error(t('errors.SESSION_EXPIRED'));
965
+ }
966
+ };
967
+ if (!text) {
968
+ return reopenAfterExpiry().then(state => {
969
+ if (!(state === null || state === void 0 ? void 0 : state.sessionID)) {
970
+ handleReopenFailure(state);
971
+ }
972
+ return state;
973
+ });
974
+ }
975
+ return reopenAfterExpiry().then(state => {
976
+ if (state === null || state === void 0 ? void 0 : state.sessionID) {
977
+ scheduleRetry(state.sessionID);
978
+ }
979
+ else {
980
+ handleReopenFailure(state);
981
+ }
982
+ return state;
983
+ });
984
+ };
923
985
  const changeTag = async (memoriId, sessionId, tag, pin) => {
924
986
  var _a, _b, _c, _d, _f, _g, _h, _j, _k;
925
987
  if (!memoriId || !sessionId) {
@@ -1115,6 +1177,23 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, ownerUserName, tenan
1115
1177
  const { msg, typingText: pendingTypingText, useLoaderTextAsMsg, } = pending;
1116
1178
  const currentState = event.currentState;
1117
1179
  if (event.resultCode !== 0 || !currentState) {
1180
+ if ((0, isSessionExpiredError_1.isSessionExpiredNatsResponse)(event) && pending.text) {
1181
+ setMemoriTyping(false);
1182
+ setTypingText(undefined);
1183
+ retryAfterExpiredSessionRef.current({
1184
+ text: pending.text,
1185
+ media: pending.media,
1186
+ translate: pending.translate,
1187
+ translatedText: pending.translatedText,
1188
+ hidden: pending.hidden,
1189
+ typingText: pending.typingText,
1190
+ useLoaderTextAsMsg: pending.useLoaderTextAsMsg,
1191
+ hasBatchQueued: pending.hasBatchQueued,
1192
+ expiredSessionID: sessionId,
1193
+ continueFromChatLogID: chatLogID,
1194
+ });
1195
+ return;
1196
+ }
1118
1197
  if (event.resultCode === 500 && event.resultMessage) {
1119
1198
  setHistory(h => [
1120
1199
  ...h,
@@ -1195,6 +1274,31 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, ownerUserName, tenan
1195
1274
  const deliverEnterTextNatsError = (0, react_1.useCallback)((event) => {
1196
1275
  var _a, _b, _c;
1197
1276
  const correlationID = event.correlationID;
1277
+ let pending;
1278
+ if (correlationID) {
1279
+ pending = pendingEnterTextRef.current.get(correlationID);
1280
+ if (pending) {
1281
+ clearEnterTextPending(correlationID, pending);
1282
+ (_a = pending.waitForResponse) === null || _a === void 0 ? void 0 : _a.reject(new Error((_b = event.errorMessage) !== null && _b !== void 0 ? _b : String((_c = event.errorCode) !== null && _c !== void 0 ? _c : 'NATS error')));
1283
+ }
1284
+ }
1285
+ if ((0, isSessionExpiredError_1.isSessionExpiredNatsError)(event) && (pending === null || pending === void 0 ? void 0 : pending.text)) {
1286
+ setMemoriTyping(false);
1287
+ setTypingText(undefined);
1288
+ retryAfterExpiredSessionRef.current({
1289
+ text: pending.text,
1290
+ media: pending.media,
1291
+ translate: pending.translate,
1292
+ translatedText: pending.translatedText,
1293
+ hidden: pending.hidden,
1294
+ typingText: pending.typingText,
1295
+ useLoaderTextAsMsg: pending.useLoaderTextAsMsg,
1296
+ hasBatchQueued: pending.hasBatchQueued,
1297
+ expiredSessionID: sessionId,
1298
+ continueFromChatLogID: chatLogID,
1299
+ });
1300
+ return;
1301
+ }
1198
1302
  const errorText = event.errorMessage
1199
1303
  ? `Error: ${event.errorMessage}`
1200
1304
  : event.errorCode
@@ -1208,13 +1312,6 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, ownerUserName, tenan
1208
1312
  contextVars: {},
1209
1313
  date: new Date().toISOString(),
1210
1314
  });
1211
- if (correlationID) {
1212
- const pending = pendingEnterTextRef.current.get(correlationID);
1213
- if (pending) {
1214
- clearEnterTextPending(correlationID, pending);
1215
- (_a = pending.waitForResponse) === null || _a === void 0 ? void 0 : _a.reject(new Error((_b = event.errorMessage) !== null && _b !== void 0 ? _b : String((_c = event.errorCode) !== null && _c !== void 0 ? _c : 'NATS error')));
1216
- }
1217
- }
1218
1315
  setMemoriTyping(false);
1219
1316
  setTypingText(undefined);
1220
1317
  }, [clearEnterTextPending]);