@memori.ai/memori-react 8.38.8 → 8.40.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 +20 -0
- package/dist/components/MemoriWidget/MemoriWidget.js +401 -87
- package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/dist/helpers/credits.d.ts +5 -2
- package/dist/helpers/credits.js +5 -1
- package/dist/helpers/credits.js.map +1 -1
- package/dist/helpers/nats/getNatsConfig.d.ts +5 -0
- package/dist/helpers/nats/getNatsConfig.js +29 -0
- package/dist/helpers/nats/getNatsConfig.js.map +1 -0
- package/dist/helpers/nats/useNats.d.ts +12 -0
- package/dist/helpers/nats/useNats.js +72 -0
- package/dist/helpers/nats/useNats.js.map +1 -0
- package/dist/helpers/nats/useNatsSession.d.ts +27 -0
- package/dist/helpers/nats/useNatsSession.js +108 -0
- package/dist/helpers/nats/useNatsSession.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/esm/components/MemoriWidget/MemoriWidget.js +401 -87
- package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/esm/helpers/credits.d.ts +5 -2
- package/esm/helpers/credits.js +5 -1
- package/esm/helpers/credits.js.map +1 -1
- package/esm/helpers/nats/getNatsConfig.d.ts +5 -0
- package/esm/helpers/nats/getNatsConfig.js +25 -0
- package/esm/helpers/nats/getNatsConfig.js.map +1 -0
- package/esm/helpers/nats/useNats.d.ts +12 -0
- package/esm/helpers/nats/useNats.js +68 -0
- package/esm/helpers/nats/useNats.js.map +1 -0
- package/esm/helpers/nats/useNatsSession.d.ts +27 -0
- package/esm/helpers/nats/useNatsSession.js +103 -0
- package/esm/helpers/nats/useNatsSession.js.map +1 -0
- package/esm/version.d.ts +1 -1
- package/esm/version.js +1 -1
- package/package.json +3 -2
- package/src/components/MemoriWidget/MemoriWidget.tsx +546 -140
- package/src/components/StartPanel/StartPanel.stories.tsx +21 -0
- package/src/components/StartPanel/StartPanel.test.tsx +66 -1
- package/src/components/StartPanel/__snapshots__/StartPanel.test.tsx.snap +156 -0
- package/src/components/layouts/layouts.stories.tsx +28 -34
- package/src/helpers/credits.ts +16 -1
- package/src/helpers/nats/getNatsConfig.ts +69 -0
- package/src/helpers/nats/useNats.ts +122 -0
- package/src/helpers/nats/useNatsSession.ts +210 -0
- package/src/index.stories.tsx +19 -3
- package/src/version.ts +1 -1
|
@@ -85,6 +85,12 @@ import { sanitizeText } from '../../helpers/sanitizer';
|
|
|
85
85
|
import { TTSConfig, useTTS } from '../../helpers/tts/useTTS';
|
|
86
86
|
import ChatHistoryDrawer from '../ChatHistoryDrawer/ChatHistory';
|
|
87
87
|
import { STTConfig, useSTT } from '../../helpers/stt/useSTT';
|
|
88
|
+
import { useNats } from '../../helpers/nats/useNats';
|
|
89
|
+
import {
|
|
90
|
+
NatsProgressEvent,
|
|
91
|
+
NatsDialogResponseEvent,
|
|
92
|
+
NatsErrorEvent,
|
|
93
|
+
} from '../../helpers/nats/useNatsSession';
|
|
88
94
|
|
|
89
95
|
// Widget utilities and helpers
|
|
90
96
|
const getMemoriState = (integrationId?: string): object | null => {
|
|
@@ -115,7 +121,7 @@ const getMemoriState = (integrationId?: string): object | null => {
|
|
|
115
121
|
};
|
|
116
122
|
};
|
|
117
123
|
|
|
118
|
-
/** Place spec with all nulls for
|
|
124
|
+
/** Place spec with all nulls for postEnterTextAsync when position is not set or user chose "I don't want to provide my position". */
|
|
119
125
|
const NULL_PLACE_SPEC = {
|
|
120
126
|
placeName: null,
|
|
121
127
|
latitude: null,
|
|
@@ -123,6 +129,16 @@ const NULL_PLACE_SPEC = {
|
|
|
123
129
|
uncertaintyKm: null,
|
|
124
130
|
} as const;
|
|
125
131
|
|
|
132
|
+
const ENTER_TEXT_NATS_TIMEOUT_MS = 120_000;
|
|
133
|
+
|
|
134
|
+
/** Reads correlation id from HTTP async response (supports camelCase / snake_case). */
|
|
135
|
+
function readCorrelationID(response: {
|
|
136
|
+
correlationID?: string;
|
|
137
|
+
}): string | undefined {
|
|
138
|
+
const value = response.correlationID;
|
|
139
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
140
|
+
}
|
|
141
|
+
|
|
126
142
|
type MemoriTextEnteredEvent = CustomEvent<{
|
|
127
143
|
text: string;
|
|
128
144
|
waitForPrevious?: boolean;
|
|
@@ -521,6 +537,7 @@ const MemoriWidget = ({
|
|
|
521
537
|
const {
|
|
522
538
|
initSession,
|
|
523
539
|
deleteSession,
|
|
540
|
+
postEnterTextAsync,
|
|
524
541
|
postTextEnteredEvent,
|
|
525
542
|
postPlaceChangedEvent,
|
|
526
543
|
postDateChangedEvent,
|
|
@@ -565,7 +582,6 @@ const MemoriWidget = ({
|
|
|
565
582
|
const [showLoginDrawer, setShowLoginDrawer] = useState(false);
|
|
566
583
|
|
|
567
584
|
const [clickedStart, setClickedStart] = useState(false);
|
|
568
|
-
const [gotErrorInOpening, setGotErrorInOpening] = useState(false);
|
|
569
585
|
|
|
570
586
|
const language =
|
|
571
587
|
memori.culture?.split('-')?.[0]?.toUpperCase()! ||
|
|
@@ -627,6 +643,23 @@ const MemoriWidget = ({
|
|
|
627
643
|
const [memoriTyping, setMemoriTyping] = useState<boolean>(false);
|
|
628
644
|
const [typingText, setTypingText] = useState<string>();
|
|
629
645
|
|
|
646
|
+
type PendingEnterText = {
|
|
647
|
+
msg?: string;
|
|
648
|
+
typingText?: string;
|
|
649
|
+
useLoaderTextAsMsg?: boolean;
|
|
650
|
+
hasBatchQueued?: boolean;
|
|
651
|
+
natsTimeoutId?: ReturnType<typeof setTimeout>;
|
|
652
|
+
waitForResponse?: {
|
|
653
|
+
resolve: (event: NatsDialogResponseEvent) => void;
|
|
654
|
+
reject: (error: Error) => void;
|
|
655
|
+
timeoutId: ReturnType<typeof setTimeout>;
|
|
656
|
+
};
|
|
657
|
+
};
|
|
658
|
+
const pendingEnterTextRef = useRef<Map<string, PendingEnterText>>(new Map());
|
|
659
|
+
const bufferedNatsResponsesRef = useRef<Map<string, NatsDialogResponseEvent>>(
|
|
660
|
+
new Map()
|
|
661
|
+
);
|
|
662
|
+
|
|
630
663
|
// Layout: from prop (string only) or integrationConfig. PII detection is only from integrationConfig (customData.layout as object with piiDetection).
|
|
631
664
|
const layoutName =
|
|
632
665
|
typeof layout === 'string'
|
|
@@ -707,7 +740,9 @@ const MemoriWidget = ({
|
|
|
707
740
|
setRuntimeShowMessageConsumption(
|
|
708
741
|
getLocalConfig(
|
|
709
742
|
'showMessageConsumption',
|
|
710
|
-
showMessageConsumption ??
|
|
743
|
+
showMessageConsumption ??
|
|
744
|
+
integrationConfig?.showMessageConsumption ??
|
|
745
|
+
false
|
|
711
746
|
)
|
|
712
747
|
);
|
|
713
748
|
|
|
@@ -770,17 +805,11 @@ const MemoriWidget = ({
|
|
|
770
805
|
longitude?: number;
|
|
771
806
|
uncertaintyKm?: number;
|
|
772
807
|
} = {};
|
|
773
|
-
if (
|
|
774
|
-
venue.latitude != null &&
|
|
775
|
-
venue.longitude != null
|
|
776
|
-
) {
|
|
808
|
+
if (venue.latitude != null && venue.longitude != null) {
|
|
777
809
|
place.latitude = venue.latitude;
|
|
778
810
|
place.longitude = venue.longitude;
|
|
779
811
|
if (venue.placeName) place.placeName = venue.placeName;
|
|
780
|
-
if (
|
|
781
|
-
venue.uncertainty != null &&
|
|
782
|
-
venue.uncertainty > 0
|
|
783
|
-
)
|
|
812
|
+
if (venue.uncertainty != null && venue.uncertainty > 0)
|
|
784
813
|
place.uncertaintyKm = venue.uncertainty;
|
|
785
814
|
} else if (venue.placeName) {
|
|
786
815
|
place.placeName = venue.placeName;
|
|
@@ -788,7 +817,7 @@ const MemoriWidget = ({
|
|
|
788
817
|
return Object.keys(place).length > 0 ? place : undefined;
|
|
789
818
|
}, []);
|
|
790
819
|
|
|
791
|
-
/** Place to send with
|
|
820
|
+
/** Place to send with postEnterTextAsync: real place, nulls when no/declined position, or undefined when position not needed. */
|
|
792
821
|
const getPlaceSpecForEnterText = useCallback(
|
|
793
822
|
(venue: Venue | undefined) => {
|
|
794
823
|
if (!memori.needsPosition) return undefined;
|
|
@@ -950,27 +979,18 @@ const MemoriWidget = ({
|
|
|
950
979
|
: !!newSessionId,
|
|
951
980
|
});
|
|
952
981
|
|
|
953
|
-
// Show typing indicator
|
|
954
|
-
setMemoriTyping(true);
|
|
955
|
-
setTypingText(typingText);
|
|
956
|
-
|
|
982
|
+
// Show typing indicator after the async enter-text request is accepted (HTTP 200).
|
|
957
983
|
let gotError = false;
|
|
958
984
|
|
|
959
985
|
try {
|
|
960
|
-
// Add chat reference link to the message if it exists
|
|
961
|
-
// if (chatLogID) {
|
|
962
|
-
// msg =
|
|
963
|
-
// msg +
|
|
964
|
-
// ' \n\n' +
|
|
965
|
-
// '<chat-reference session-id="' +
|
|
966
|
-
// sessionID +
|
|
967
|
-
// '" event-log-id="' +
|
|
968
|
-
// chatLogID +
|
|
969
|
-
// '"></chat-reference>';
|
|
970
|
-
// }
|
|
971
|
-
|
|
972
986
|
const placeSpec = getPlaceSpecForEnterText(position);
|
|
973
|
-
|
|
987
|
+
console.debug('[EnterText] sendMessage: posting', {
|
|
988
|
+
sessionId: sessionID,
|
|
989
|
+
textLength: msg.length,
|
|
990
|
+
hasBatchQueued,
|
|
991
|
+
typingText,
|
|
992
|
+
});
|
|
993
|
+
const response = await postEnterTextAsync({
|
|
974
994
|
sessionId: sessionID,
|
|
975
995
|
text: msg,
|
|
976
996
|
...(memori.needsDateTime && {
|
|
@@ -978,55 +998,33 @@ const MemoriWidget = ({
|
|
|
978
998
|
}),
|
|
979
999
|
...(placeSpec !== undefined && { place: placeSpec }),
|
|
980
1000
|
});
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
}
|
|
1000
|
-
});
|
|
1001
|
-
} else {
|
|
1002
|
-
setCurrentDialogState({
|
|
1003
|
-
...currentState,
|
|
1004
|
-
emission,
|
|
1005
|
-
});
|
|
1006
|
-
|
|
1007
|
-
if (emission) {
|
|
1008
|
-
pushMessage({
|
|
1009
|
-
text: emission,
|
|
1010
|
-
emitter: currentState.emitter,
|
|
1011
|
-
media: currentState.emittedMedia ?? currentState.media,
|
|
1012
|
-
llmUsage: (currentState as any).llmUsage,
|
|
1013
|
-
fromUser: false,
|
|
1014
|
-
questionAnswered: msg,
|
|
1015
|
-
generatedByAI: !!currentState.completion,
|
|
1016
|
-
contextVars: currentState.contextVars,
|
|
1017
|
-
date: currentState.currentDate,
|
|
1018
|
-
placeName: currentState.currentPlaceName,
|
|
1019
|
-
placeLatitude: currentState.currentLatitude,
|
|
1020
|
-
placeLongitude: currentState.currentLongitude,
|
|
1021
|
-
placeUncertaintyKm: currentState.currentUncertaintyKm,
|
|
1022
|
-
tag: currentState.currentTag,
|
|
1023
|
-
memoryTags: currentState.memoryTags,
|
|
1024
|
-
} as any);
|
|
1025
|
-
if (emission && shouldPlayAudio(emission)) {
|
|
1026
|
-
handleSpeak(emission);
|
|
1027
|
-
}
|
|
1001
|
+
console.debug('[EnterText] sendMessage: HTTP response', {
|
|
1002
|
+
resultCode: response.resultCode,
|
|
1003
|
+
correlationID: readCorrelationID(response),
|
|
1004
|
+
resultMessage: response.resultMessage,
|
|
1005
|
+
});
|
|
1006
|
+
const correlationID = readCorrelationID(response);
|
|
1007
|
+
if (response.resultCode === 0 && correlationID) {
|
|
1008
|
+
registerPendingEnterText(correlationID, {
|
|
1009
|
+
msg,
|
|
1010
|
+
typingText,
|
|
1011
|
+
useLoaderTextAsMsg,
|
|
1012
|
+
hasBatchQueued,
|
|
1013
|
+
});
|
|
1014
|
+
console.info(
|
|
1015
|
+
'[EnterText] sendMessage: accepted, showing typing indicator',
|
|
1016
|
+
{
|
|
1017
|
+
correlationID: correlationID,
|
|
1018
|
+
typingText,
|
|
1028
1019
|
}
|
|
1029
|
-
|
|
1020
|
+
);
|
|
1021
|
+
setMemoriTyping(true);
|
|
1022
|
+
setTypingText(typingText);
|
|
1023
|
+
} else if (response.resultCode === 0) {
|
|
1024
|
+
console.error(
|
|
1025
|
+
'[EnterText] sendMessage: HTTP 200 but missing correlationID — cannot match NATS response',
|
|
1026
|
+
response
|
|
1027
|
+
);
|
|
1030
1028
|
} else if (response.resultCode === 404) {
|
|
1031
1029
|
// Handle expired session
|
|
1032
1030
|
// remove last sent message, will set it as initial
|
|
@@ -1075,18 +1073,12 @@ const MemoriWidget = ({
|
|
|
1075
1073
|
return Promise.reject(response);
|
|
1076
1074
|
}
|
|
1077
1075
|
} catch (error) {
|
|
1078
|
-
console.
|
|
1079
|
-
console.error(error);
|
|
1076
|
+
console.error('[EnterText] sendMessage: request failed', error);
|
|
1080
1077
|
gotError = true;
|
|
1081
1078
|
|
|
1082
1079
|
setTypingText(undefined);
|
|
1083
1080
|
setMemoriTyping(false);
|
|
1084
1081
|
}
|
|
1085
|
-
|
|
1086
|
-
if (!hasBatchQueued) {
|
|
1087
|
-
setTypingText(undefined);
|
|
1088
|
-
setMemoriTyping(false);
|
|
1089
|
-
}
|
|
1090
1082
|
};
|
|
1091
1083
|
|
|
1092
1084
|
/**
|
|
@@ -1393,6 +1385,10 @@ const MemoriWidget = ({
|
|
|
1393
1385
|
return;
|
|
1394
1386
|
}
|
|
1395
1387
|
|
|
1388
|
+
if (!(await checkCredits({ notify: true }))) {
|
|
1389
|
+
return;
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1396
1392
|
setLoading(true);
|
|
1397
1393
|
|
|
1398
1394
|
try {
|
|
@@ -1469,10 +1465,9 @@ const MemoriWidget = ({
|
|
|
1469
1465
|
) {
|
|
1470
1466
|
console.warn(session);
|
|
1471
1467
|
toast.error(t('underageTwinSession', { age: minAge }));
|
|
1472
|
-
setGotErrorInOpening(true);
|
|
1473
1468
|
}
|
|
1474
1469
|
// Handle authentication error
|
|
1475
|
-
else if (session?.resultCode === 403) {
|
|
1470
|
+
else if (session?.resultCode === 403 && memori.privacyType !== 'PUBLIC') {
|
|
1476
1471
|
setMemoriPwd(undefined);
|
|
1477
1472
|
setAuthModalState('password');
|
|
1478
1473
|
return session;
|
|
@@ -1498,7 +1493,6 @@ const MemoriWidget = ({
|
|
|
1498
1493
|
duration: Infinity,
|
|
1499
1494
|
}
|
|
1500
1495
|
);
|
|
1501
|
-
setGotErrorInOpening(true);
|
|
1502
1496
|
return session;
|
|
1503
1497
|
}
|
|
1504
1498
|
} catch (err) {
|
|
@@ -1565,6 +1559,11 @@ const MemoriWidget = ({
|
|
|
1565
1559
|
return;
|
|
1566
1560
|
}
|
|
1567
1561
|
|
|
1562
|
+
if (!(await checkCredits({ notify: true }))) {
|
|
1563
|
+
setLoading(false);
|
|
1564
|
+
return null;
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1568
1567
|
// Get current URL as referral
|
|
1569
1568
|
let referral;
|
|
1570
1569
|
try {
|
|
@@ -1692,10 +1691,12 @@ const MemoriWidget = ({
|
|
|
1692
1691
|
) {
|
|
1693
1692
|
console.error('[REOPEN_SESSION] Age restriction error:', response);
|
|
1694
1693
|
toast.error(t('underageTwinSession', { age: minAge }));
|
|
1695
|
-
setGotErrorInOpening(true);
|
|
1696
1694
|
}
|
|
1697
1695
|
// Handle authentication error
|
|
1698
|
-
else if (
|
|
1696
|
+
else if (
|
|
1697
|
+
response?.resultCode === 403 &&
|
|
1698
|
+
memori.privacyType !== 'PUBLIC'
|
|
1699
|
+
) {
|
|
1699
1700
|
console.error('[REOPEN_SESSION] Authentication error');
|
|
1700
1701
|
setMemoriPwd(undefined);
|
|
1701
1702
|
setAuthModalState('password');
|
|
@@ -1704,7 +1705,6 @@ const MemoriWidget = ({
|
|
|
1704
1705
|
else {
|
|
1705
1706
|
console.error('[REOPEN_SESSION] Other error:', response);
|
|
1706
1707
|
toast.error(t(getErrori18nKey(response.resultCode)));
|
|
1707
|
-
setGotErrorInOpening(true);
|
|
1708
1708
|
}
|
|
1709
1709
|
} catch (err) {
|
|
1710
1710
|
console.error('[REOPEN_SESSION] Caught error:', err);
|
|
@@ -2043,6 +2043,341 @@ const MemoriWidget = ({
|
|
|
2043
2043
|
]
|
|
2044
2044
|
);
|
|
2045
2045
|
|
|
2046
|
+
const processEnterTextDialogResponse = useCallback(
|
|
2047
|
+
(event: NatsDialogResponseEvent, pending: PendingEnterText) => {
|
|
2048
|
+
console.debug('[EnterText] processDialogResponse', {
|
|
2049
|
+
correlationID: event.correlationID,
|
|
2050
|
+
resultCode: event.resultCode,
|
|
2051
|
+
hasCurrentState: !!event.currentState,
|
|
2052
|
+
hasBatchQueued: pending.hasBatchQueued,
|
|
2053
|
+
});
|
|
2054
|
+
const {
|
|
2055
|
+
msg,
|
|
2056
|
+
typingText: pendingTypingText,
|
|
2057
|
+
useLoaderTextAsMsg,
|
|
2058
|
+
} = pending;
|
|
2059
|
+
const currentState = event.currentState;
|
|
2060
|
+
|
|
2061
|
+
if (event.resultCode !== 0 || !currentState) {
|
|
2062
|
+
if (event.resultCode === 500 && event.resultMessage) {
|
|
2063
|
+
console.warn('[EnterText] processDialogResponse: server error', {
|
|
2064
|
+
correlationID: event.correlationID,
|
|
2065
|
+
resultMessage: event.resultMessage,
|
|
2066
|
+
});
|
|
2067
|
+
setHistory(h => [
|
|
2068
|
+
...h,
|
|
2069
|
+
{
|
|
2070
|
+
text: 'Error: ' + event.resultMessage,
|
|
2071
|
+
emitter: 'system',
|
|
2072
|
+
fromUser: false,
|
|
2073
|
+
initial: false,
|
|
2074
|
+
contextVars: {},
|
|
2075
|
+
date: new Date().toISOString(),
|
|
2076
|
+
},
|
|
2077
|
+
]);
|
|
2078
|
+
} else if (event.resultCode !== 0) {
|
|
2079
|
+
console.warn('[SEND_MESSAGE/NATS]', event);
|
|
2080
|
+
}
|
|
2081
|
+
return;
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2084
|
+
if (!msg) {
|
|
2085
|
+
console.debug(
|
|
2086
|
+
'[EnterText] processDialogResponse: no msg in pending, skipping'
|
|
2087
|
+
);
|
|
2088
|
+
return;
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
setChatLogID(undefined);
|
|
2092
|
+
const emission =
|
|
2093
|
+
useLoaderTextAsMsg && pendingTypingText
|
|
2094
|
+
? pendingTypingText
|
|
2095
|
+
: currentState.emission ?? currentDialogState?.emission;
|
|
2096
|
+
|
|
2097
|
+
console.debug('[EnterText] processDialogResponse: rendering emission', {
|
|
2098
|
+
correlationID: event.correlationID,
|
|
2099
|
+
emissionPreview: emission?.slice(0, 80),
|
|
2100
|
+
state: currentState.state,
|
|
2101
|
+
});
|
|
2102
|
+
|
|
2103
|
+
if (
|
|
2104
|
+
userLang.toLowerCase() !== language.toLowerCase() &&
|
|
2105
|
+
emission &&
|
|
2106
|
+
isMultilanguageEnabled
|
|
2107
|
+
) {
|
|
2108
|
+
currentState.emission = emission;
|
|
2109
|
+
|
|
2110
|
+
translateDialogState(currentState, userLang, msg).then(ts => {
|
|
2111
|
+
const text = ts.translatedEmission || ts.emission;
|
|
2112
|
+
if (text && shouldPlayAudio(text)) {
|
|
2113
|
+
handleSpeak(text);
|
|
2114
|
+
}
|
|
2115
|
+
});
|
|
2116
|
+
} else {
|
|
2117
|
+
setCurrentDialogState({
|
|
2118
|
+
...currentState,
|
|
2119
|
+
emission,
|
|
2120
|
+
});
|
|
2121
|
+
|
|
2122
|
+
if (emission) {
|
|
2123
|
+
pushMessage({
|
|
2124
|
+
text: emission,
|
|
2125
|
+
emitter: currentState.emitter,
|
|
2126
|
+
media: currentState.emittedMedia ?? currentState.media,
|
|
2127
|
+
llmUsage: (currentState as any).llmUsage,
|
|
2128
|
+
fromUser: false,
|
|
2129
|
+
questionAnswered: msg,
|
|
2130
|
+
generatedByAI: !!currentState.completion,
|
|
2131
|
+
contextVars: currentState.contextVars,
|
|
2132
|
+
date: currentState.currentDate,
|
|
2133
|
+
placeName: currentState.currentPlaceName,
|
|
2134
|
+
placeLatitude: currentState.currentLatitude,
|
|
2135
|
+
placeLongitude: currentState.currentLongitude,
|
|
2136
|
+
placeUncertaintyKm: currentState.currentUncertaintyKm,
|
|
2137
|
+
tag: currentState.currentTag,
|
|
2138
|
+
memoryTags: currentState.memoryTags,
|
|
2139
|
+
} as any);
|
|
2140
|
+
if (emission && shouldPlayAudio(emission)) {
|
|
2141
|
+
handleSpeak(emission);
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
},
|
|
2146
|
+
[
|
|
2147
|
+
userLang,
|
|
2148
|
+
language,
|
|
2149
|
+
isMultilanguageEnabled,
|
|
2150
|
+
currentDialogState?.emission,
|
|
2151
|
+
translateDialogState,
|
|
2152
|
+
handleSpeak,
|
|
2153
|
+
shouldPlayAudio,
|
|
2154
|
+
]
|
|
2155
|
+
);
|
|
2156
|
+
|
|
2157
|
+
const clearEnterTextPending = useCallback(
|
|
2158
|
+
(correlationID: string, pending: PendingEnterText) => {
|
|
2159
|
+
if (pending.natsTimeoutId) {
|
|
2160
|
+
clearTimeout(pending.natsTimeoutId);
|
|
2161
|
+
}
|
|
2162
|
+
if (pending.waitForResponse?.timeoutId) {
|
|
2163
|
+
clearTimeout(pending.waitForResponse.timeoutId);
|
|
2164
|
+
}
|
|
2165
|
+
pendingEnterTextRef.current.delete(correlationID);
|
|
2166
|
+
},
|
|
2167
|
+
[]
|
|
2168
|
+
);
|
|
2169
|
+
|
|
2170
|
+
const deliverEnterTextNatsError = useCallback(
|
|
2171
|
+
(event: NatsErrorEvent) => {
|
|
2172
|
+
const correlationID = event.correlationID;
|
|
2173
|
+
const errorText = event.errorMessage
|
|
2174
|
+
? `Error: ${event.errorMessage}`
|
|
2175
|
+
: event.errorCode
|
|
2176
|
+
? `Error: ${event.errorCode}`
|
|
2177
|
+
: 'Error: An unexpected error occurred';
|
|
2178
|
+
|
|
2179
|
+
console.error('[EnterText] NATS error event', {
|
|
2180
|
+
correlationID,
|
|
2181
|
+
errorCode: event.errorCode,
|
|
2182
|
+
errorMessage: event.errorMessage,
|
|
2183
|
+
});
|
|
2184
|
+
|
|
2185
|
+
pushMessage({
|
|
2186
|
+
text: errorText,
|
|
2187
|
+
emitter: 'system',
|
|
2188
|
+
fromUser: false,
|
|
2189
|
+
initial: false,
|
|
2190
|
+
contextVars: {},
|
|
2191
|
+
date: new Date().toISOString(),
|
|
2192
|
+
});
|
|
2193
|
+
|
|
2194
|
+
if (correlationID) {
|
|
2195
|
+
const pending = pendingEnterTextRef.current.get(correlationID);
|
|
2196
|
+
if (pending) {
|
|
2197
|
+
clearEnterTextPending(correlationID, pending);
|
|
2198
|
+
pending.waitForResponse?.reject(
|
|
2199
|
+
new Error(event.errorMessage ?? String(event.errorCode ?? 'NATS error'))
|
|
2200
|
+
);
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
|
|
2204
|
+
setMemoriTyping(false);
|
|
2205
|
+
setTypingText(undefined);
|
|
2206
|
+
},
|
|
2207
|
+
[clearEnterTextPending]
|
|
2208
|
+
);
|
|
2209
|
+
|
|
2210
|
+
const deliverEnterTextNatsResponse = useCallback(
|
|
2211
|
+
(correlationID: string, event: NatsDialogResponseEvent) => {
|
|
2212
|
+
const pending = pendingEnterTextRef.current.get(correlationID);
|
|
2213
|
+
if (!pending) {
|
|
2214
|
+
const pendingCorrelationIDs = [...pendingEnterTextRef.current.keys()];
|
|
2215
|
+
console.warn(
|
|
2216
|
+
'[EnterText] NATS response buffered (no matching pending)',
|
|
2217
|
+
{
|
|
2218
|
+
receivedCorrelationID: correlationID,
|
|
2219
|
+
resultCode: event.resultCode,
|
|
2220
|
+
pendingCorrelationIDs,
|
|
2221
|
+
hint:
|
|
2222
|
+
pendingCorrelationIDs.length > 0
|
|
2223
|
+
? 'Use one of pendingCorrelationIDs in your nats pub correlation_id'
|
|
2224
|
+
: 'Send a message in the widget first, then copy correlationID from HTTP response logs',
|
|
2225
|
+
}
|
|
2226
|
+
);
|
|
2227
|
+
bufferedNatsResponsesRef.current.set(correlationID, event);
|
|
2228
|
+
return;
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2231
|
+
clearEnterTextPending(correlationID, pending);
|
|
2232
|
+
|
|
2233
|
+
if (pending.waitForResponse) {
|
|
2234
|
+
console.info('[EnterText] NATS response delivered to waiter', {
|
|
2235
|
+
correlationID,
|
|
2236
|
+
resultCode: event.resultCode,
|
|
2237
|
+
});
|
|
2238
|
+
pending.waitForResponse.resolve(event);
|
|
2239
|
+
setMemoriTyping(false);
|
|
2240
|
+
setTypingText(undefined);
|
|
2241
|
+
return;
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
processEnterTextDialogResponse(event, pending);
|
|
2245
|
+
|
|
2246
|
+
if (!pending.hasBatchQueued) {
|
|
2247
|
+
console.info('[EnterText] typing indicator cleared', { correlationID });
|
|
2248
|
+
setMemoriTyping(false);
|
|
2249
|
+
setTypingText(undefined);
|
|
2250
|
+
} else {
|
|
2251
|
+
console.debug('[EnterText] typing kept (batch queued)', {
|
|
2252
|
+
correlationID,
|
|
2253
|
+
});
|
|
2254
|
+
}
|
|
2255
|
+
},
|
|
2256
|
+
[processEnterTextDialogResponse, clearEnterTextPending]
|
|
2257
|
+
);
|
|
2258
|
+
|
|
2259
|
+
const registerPendingEnterText = useCallback(
|
|
2260
|
+
(correlationID: string, pending: PendingEnterText) => {
|
|
2261
|
+
const buffered = bufferedNatsResponsesRef.current.get(correlationID);
|
|
2262
|
+
if (buffered) {
|
|
2263
|
+
console.info('[EnterText] replaying buffered NATS response', {
|
|
2264
|
+
correlationID,
|
|
2265
|
+
waitForResponse: !!pending.waitForResponse,
|
|
2266
|
+
});
|
|
2267
|
+
bufferedNatsResponsesRef.current.delete(correlationID);
|
|
2268
|
+
pendingEnterTextRef.current.set(correlationID, pending);
|
|
2269
|
+
deliverEnterTextNatsResponse(correlationID, buffered);
|
|
2270
|
+
return;
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
if (!pending.waitForResponse && !pending.natsTimeoutId) {
|
|
2274
|
+
pending.natsTimeoutId = setTimeout(() => {
|
|
2275
|
+
const current = pendingEnterTextRef.current.get(correlationID);
|
|
2276
|
+
if (!current) return;
|
|
2277
|
+
clearEnterTextPending(correlationID, current);
|
|
2278
|
+
console.error('[EnterText] NATS response timeout', {
|
|
2279
|
+
correlationID,
|
|
2280
|
+
timeoutMs: ENTER_TEXT_NATS_TIMEOUT_MS,
|
|
2281
|
+
});
|
|
2282
|
+
if (!current.hasBatchQueued) {
|
|
2283
|
+
setMemoriTyping(false);
|
|
2284
|
+
setTypingText(undefined);
|
|
2285
|
+
}
|
|
2286
|
+
current.waitForResponse?.reject(
|
|
2287
|
+
new Error('NATS enter-text response timeout')
|
|
2288
|
+
);
|
|
2289
|
+
}, ENTER_TEXT_NATS_TIMEOUT_MS);
|
|
2290
|
+
}
|
|
2291
|
+
|
|
2292
|
+
console.debug('[EnterText] pending registered', {
|
|
2293
|
+
correlationID,
|
|
2294
|
+
waitForResponse: !!pending.waitForResponse,
|
|
2295
|
+
hasBatchQueued: pending.hasBatchQueued,
|
|
2296
|
+
});
|
|
2297
|
+
pendingEnterTextRef.current.set(correlationID, pending);
|
|
2298
|
+
},
|
|
2299
|
+
[deliverEnterTextNatsResponse, clearEnterTextPending]
|
|
2300
|
+
);
|
|
2301
|
+
|
|
2302
|
+
const waitForEnterTextNatsResponse = useCallback(
|
|
2303
|
+
(correlationID: string, timeoutMs = 120000) =>
|
|
2304
|
+
new Promise<NatsDialogResponseEvent>((resolve, reject) => {
|
|
2305
|
+
console.debug('[EnterText] waiting for NATS response', {
|
|
2306
|
+
correlationID,
|
|
2307
|
+
timeoutMs,
|
|
2308
|
+
});
|
|
2309
|
+
const timeoutId = setTimeout(() => {
|
|
2310
|
+
const current = pendingEnterTextRef.current.get(correlationID);
|
|
2311
|
+
if (current) {
|
|
2312
|
+
clearEnterTextPending(correlationID, current);
|
|
2313
|
+
}
|
|
2314
|
+
console.error('[EnterText] NATS response timeout', {
|
|
2315
|
+
correlationID,
|
|
2316
|
+
timeoutMs,
|
|
2317
|
+
});
|
|
2318
|
+
reject(new Error('NATS enter-text response timeout'));
|
|
2319
|
+
}, timeoutMs);
|
|
2320
|
+
|
|
2321
|
+
registerPendingEnterText(correlationID, {
|
|
2322
|
+
waitForResponse: {
|
|
2323
|
+
resolve: event => {
|
|
2324
|
+
clearTimeout(timeoutId);
|
|
2325
|
+
resolve(event);
|
|
2326
|
+
},
|
|
2327
|
+
reject: error => {
|
|
2328
|
+
clearTimeout(timeoutId);
|
|
2329
|
+
reject(error);
|
|
2330
|
+
},
|
|
2331
|
+
timeoutId,
|
|
2332
|
+
},
|
|
2333
|
+
});
|
|
2334
|
+
}),
|
|
2335
|
+
[registerPendingEnterText, clearEnterTextPending]
|
|
2336
|
+
);
|
|
2337
|
+
|
|
2338
|
+
// NATS subscription: receives progress updates and the async enter-text response.
|
|
2339
|
+
useNats({
|
|
2340
|
+
baseUrl,
|
|
2341
|
+
sessionId,
|
|
2342
|
+
onProgress: useCallback((event: NatsProgressEvent) => {
|
|
2343
|
+
console.debug('[EnterText] NATS progress', {
|
|
2344
|
+
correlationID: event.correlationID,
|
|
2345
|
+
step: event.currentStep,
|
|
2346
|
+
finalStep: event.finalStep,
|
|
2347
|
+
message: event.message,
|
|
2348
|
+
});
|
|
2349
|
+
if (event.message) {
|
|
2350
|
+
setTypingText(event.message);
|
|
2351
|
+
}
|
|
2352
|
+
}, []),
|
|
2353
|
+
onDialogResponse: useCallback(
|
|
2354
|
+
(event: NatsDialogResponseEvent) => {
|
|
2355
|
+
const correlationID = event.correlationID;
|
|
2356
|
+
console.debug(
|
|
2357
|
+
'[EnterText] NATS dialog.text_entered_response received',
|
|
2358
|
+
{
|
|
2359
|
+
correlationID,
|
|
2360
|
+
resultCode: event.resultCode,
|
|
2361
|
+
requestID: event.requestID,
|
|
2362
|
+
}
|
|
2363
|
+
);
|
|
2364
|
+
if (!correlationID) {
|
|
2365
|
+
console.warn(
|
|
2366
|
+
'[EnterText] dialog_text_entered_response without correlationID',
|
|
2367
|
+
event
|
|
2368
|
+
);
|
|
2369
|
+
setMemoriTyping(false);
|
|
2370
|
+
setTypingText(undefined);
|
|
2371
|
+
return;
|
|
2372
|
+
}
|
|
2373
|
+
|
|
2374
|
+
deliverEnterTextNatsResponse(correlationID, event);
|
|
2375
|
+
},
|
|
2376
|
+
[deliverEnterTextNatsResponse]
|
|
2377
|
+
),
|
|
2378
|
+
onError: deliverEnterTextNatsError,
|
|
2379
|
+
});
|
|
2380
|
+
|
|
2046
2381
|
const focusChatInput = () => {
|
|
2047
2382
|
let textarea = document.querySelector(
|
|
2048
2383
|
'#chat-fieldset textarea'
|
|
@@ -2370,6 +2705,12 @@ const MemoriWidget = ({
|
|
|
2370
2705
|
return;
|
|
2371
2706
|
}
|
|
2372
2707
|
|
|
2708
|
+
if (!(await checkCredits({ notify: true }))) {
|
|
2709
|
+
setClickedStart(false);
|
|
2710
|
+
setLoading(false);
|
|
2711
|
+
return;
|
|
2712
|
+
}
|
|
2713
|
+
|
|
2373
2714
|
// Handle age verification
|
|
2374
2715
|
if (!sessionID && !!minAge && !birth) {
|
|
2375
2716
|
setShowAgeVerification(true);
|
|
@@ -2377,12 +2718,11 @@ const MemoriWidget = ({
|
|
|
2377
2718
|
}
|
|
2378
2719
|
// Handle authentication
|
|
2379
2720
|
else if (
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
(!sessionID && gotErrorInOpening)
|
|
2721
|
+
!sessionID &&
|
|
2722
|
+
memori.privacyType !== 'PUBLIC' &&
|
|
2723
|
+
!memori.secretToken &&
|
|
2724
|
+
!memoriPwd &&
|
|
2725
|
+
!memoriTokens
|
|
2386
2726
|
) {
|
|
2387
2727
|
setAuthModalState('password');
|
|
2388
2728
|
setClickedStart(false);
|
|
@@ -2391,7 +2731,6 @@ const MemoriWidget = ({
|
|
|
2391
2731
|
// Create new session if needed
|
|
2392
2732
|
else if (!sessionID || initialSessionExpired) {
|
|
2393
2733
|
setClickedStart(false);
|
|
2394
|
-
setGotErrorInOpening(false);
|
|
2395
2734
|
const session = await fetchSession({
|
|
2396
2735
|
memoriID: memori.engineMemoriID!,
|
|
2397
2736
|
password: secret || memoriPwd || memori.secretToken,
|
|
@@ -2513,7 +2852,6 @@ const MemoriWidget = ({
|
|
|
2513
2852
|
|
|
2514
2853
|
if (response.resultCode !== 0 || !currentState) {
|
|
2515
2854
|
const { chatLogs } = await getSessionChatLogs(sessionID!, sessionID!);
|
|
2516
|
-
setGotErrorInOpening(true);
|
|
2517
2855
|
setSessionId(undefined);
|
|
2518
2856
|
setClickedStart(false);
|
|
2519
2857
|
await onClickStart(undefined, true, chatLogs?.[0]);
|
|
@@ -2684,11 +3022,15 @@ const MemoriWidget = ({
|
|
|
2684
3022
|
translatedMessages = [];
|
|
2685
3023
|
setHistory([]);
|
|
2686
3024
|
|
|
2687
|
-
setMemoriTyping(true);
|
|
2688
|
-
|
|
2689
3025
|
// we have no chat history, we start by initial question
|
|
2690
3026
|
const placeSpec = getPlaceSpecForEnterText(position);
|
|
2691
|
-
|
|
3027
|
+
console.debug(
|
|
3028
|
+
'[EnterText] onClickStart: posting initial question',
|
|
3029
|
+
{
|
|
3030
|
+
sessionId: sessionID,
|
|
3031
|
+
}
|
|
3032
|
+
);
|
|
3033
|
+
const response = await postEnterTextAsync({
|
|
2692
3034
|
sessionId: sessionID!,
|
|
2693
3035
|
text: initialQuestion,
|
|
2694
3036
|
...(memori.needsDateTime && {
|
|
@@ -2696,8 +3038,12 @@ const MemoriWidget = ({
|
|
|
2696
3038
|
}),
|
|
2697
3039
|
...(placeSpec !== undefined && { place: placeSpec }),
|
|
2698
3040
|
});
|
|
3041
|
+
console.debug('[EnterText] onClickStart: HTTP response', {
|
|
3042
|
+
resultCode: response.resultCode,
|
|
3043
|
+
correlationID: readCorrelationID(response),
|
|
3044
|
+
});
|
|
2699
3045
|
|
|
2700
|
-
// Handle 500 error from
|
|
3046
|
+
// Handle 500 error from EnterTextAsync
|
|
2701
3047
|
if (response.resultCode === 500 && response.resultMessage) {
|
|
2702
3048
|
setHistory(h => [
|
|
2703
3049
|
...h,
|
|
@@ -2710,19 +3056,50 @@ const MemoriWidget = ({
|
|
|
2710
3056
|
date: new Date().toISOString(),
|
|
2711
3057
|
},
|
|
2712
3058
|
]);
|
|
2713
|
-
setMemoriTyping(false);
|
|
2714
3059
|
return;
|
|
2715
3060
|
}
|
|
2716
3061
|
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
3062
|
+
const onClickStartCorrelationID = readCorrelationID(response);
|
|
3063
|
+
if (response.resultCode === 0 && onClickStartCorrelationID) {
|
|
3064
|
+
console.info(
|
|
3065
|
+
'[EnterText] onClickStart: accepted, showing typing indicator',
|
|
3066
|
+
{
|
|
3067
|
+
correlationID: onClickStartCorrelationID,
|
|
3068
|
+
}
|
|
3069
|
+
);
|
|
3070
|
+
setMemoriTyping(true);
|
|
3071
|
+
try {
|
|
3072
|
+
const natsEvent = await waitForEnterTextNatsResponse(
|
|
3073
|
+
onClickStartCorrelationID
|
|
3074
|
+
);
|
|
3075
|
+
console.info(
|
|
3076
|
+
'[EnterText] onClickStart: NATS response received',
|
|
3077
|
+
{
|
|
3078
|
+
correlationID: onClickStartCorrelationID,
|
|
3079
|
+
resultCode: natsEvent.resultCode,
|
|
3080
|
+
}
|
|
3081
|
+
);
|
|
3082
|
+
if (natsEvent.resultCode === 0 && natsEvent.currentState) {
|
|
3083
|
+
await translateAndSpeak(
|
|
3084
|
+
natsEvent.currentState,
|
|
3085
|
+
userLang,
|
|
3086
|
+
undefined,
|
|
3087
|
+
false
|
|
3088
|
+
);
|
|
3089
|
+
}
|
|
3090
|
+
} catch (e) {
|
|
3091
|
+
console.error('[EnterText] onClickStart: NATS wait failed', e);
|
|
3092
|
+
setMemoriTyping(false);
|
|
3093
|
+
setTypingText(undefined);
|
|
3094
|
+
}
|
|
3095
|
+
} else if (response.resultCode === 0) {
|
|
3096
|
+
console.error(
|
|
3097
|
+
'[EnterText] onClickStart: HTTP 200 but missing correlationID',
|
|
3098
|
+
response
|
|
3099
|
+
);
|
|
3100
|
+
}
|
|
2723
3101
|
}
|
|
2724
3102
|
}
|
|
2725
|
-
|
|
2726
3103
|
}
|
|
2727
3104
|
// Default case - just translate and activate
|
|
2728
3105
|
else {
|
|
@@ -2817,36 +3194,72 @@ const MemoriWidget = ({
|
|
|
2817
3194
|
// check if owner has enough credits
|
|
2818
3195
|
const needsCredits = tenant?.billingDelegation;
|
|
2819
3196
|
const [hasEnoughCredits, setHasEnoughCredits] = useState<boolean>(true);
|
|
2820
|
-
const
|
|
2821
|
-
|
|
3197
|
+
const handleNotEnoughCredits = useCallback(() => {
|
|
3198
|
+
setHasEnoughCredits(false);
|
|
3199
|
+
setAuthModalState(null);
|
|
3200
|
+
toast.error(t('notEnoughCredits'));
|
|
3201
|
+
}, [t]);
|
|
3202
|
+
const checkCredits = useCallback(
|
|
3203
|
+
async (options?: { notify?: boolean }) => {
|
|
3204
|
+
if (!tenant?.billingDelegation) return true;
|
|
3205
|
+
|
|
3206
|
+
// Billing delegation is active: credits MUST be verified.
|
|
3207
|
+
// Without either owner identifier we cannot call the API, so we fail closed
|
|
3208
|
+
// instead of silently letting the session start unverified.
|
|
3209
|
+
if (!ownerUserID && !ownerUserName) {
|
|
3210
|
+
console.warn('Cannot verify credits: missing owner identifier');
|
|
3211
|
+
if (options?.notify) {
|
|
3212
|
+
handleNotEnoughCredits();
|
|
3213
|
+
} else {
|
|
3214
|
+
setHasEnoughCredits(false);
|
|
3215
|
+
}
|
|
3216
|
+
return false;
|
|
3217
|
+
}
|
|
2822
3218
|
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
3219
|
+
try {
|
|
3220
|
+
const resp = await getCredits({
|
|
3221
|
+
operation: deepThoughtEnabled
|
|
3222
|
+
? 'dt_session_creation'
|
|
3223
|
+
: 'session_creation',
|
|
3224
|
+
baseUrl: baseUrl,
|
|
3225
|
+
userID: ownerUserID,
|
|
3226
|
+
userName: ownerUserName,
|
|
3227
|
+
tenant: tenantID,
|
|
3228
|
+
});
|
|
2833
3229
|
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
3230
|
+
if (resp.enough) {
|
|
3231
|
+
setHasEnoughCredits(true);
|
|
3232
|
+
return true;
|
|
3233
|
+
} else {
|
|
3234
|
+
console.warn('Not enough credits. Required:', resp.required);
|
|
3235
|
+
if (options?.notify) {
|
|
3236
|
+
handleNotEnoughCredits();
|
|
3237
|
+
} else {
|
|
3238
|
+
setHasEnoughCredits(false);
|
|
3239
|
+
}
|
|
3240
|
+
return false;
|
|
3241
|
+
}
|
|
3242
|
+
} catch (e) {
|
|
3243
|
+
let err = e as Error;
|
|
3244
|
+
console.debug(err);
|
|
3245
|
+
return true;
|
|
2839
3246
|
}
|
|
2840
|
-
}
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
3247
|
+
},
|
|
3248
|
+
[
|
|
3249
|
+
baseUrl,
|
|
3250
|
+
deepThoughtEnabled,
|
|
3251
|
+
handleNotEnoughCredits,
|
|
3252
|
+
ownerUserID,
|
|
3253
|
+
ownerUserName,
|
|
3254
|
+
tenant?.billingDelegation,
|
|
3255
|
+
tenantID,
|
|
3256
|
+
]
|
|
3257
|
+
);
|
|
2845
3258
|
useEffect(() => {
|
|
2846
3259
|
if (tenant?.billingDelegation) {
|
|
2847
3260
|
checkCredits();
|
|
2848
3261
|
}
|
|
2849
|
-
}, [tenant?.billingDelegation, deepThoughtEnabled]);
|
|
3262
|
+
}, [tenant?.billingDelegation, deepThoughtEnabled, checkCredits]);
|
|
2850
3263
|
|
|
2851
3264
|
useEffect(() => {
|
|
2852
3265
|
if (__WEBCOMPONENT__) return;
|
|
@@ -3203,12 +3616,6 @@ const MemoriWidget = ({
|
|
|
3203
3616
|
}
|
|
3204
3617
|
})
|
|
3205
3618
|
.catch(error => {
|
|
3206
|
-
if (
|
|
3207
|
-
!(error instanceof Error) ||
|
|
3208
|
-
error.message !== 'AUTH_FAILED'
|
|
3209
|
-
) {
|
|
3210
|
-
setGotErrorInOpening(true);
|
|
3211
|
-
}
|
|
3212
3619
|
throw error;
|
|
3213
3620
|
});
|
|
3214
3621
|
}}
|
|
@@ -3254,7 +3661,6 @@ const MemoriWidget = ({
|
|
|
3254
3661
|
})
|
|
3255
3662
|
.catch(() => {
|
|
3256
3663
|
setShowAgeVerification(false);
|
|
3257
|
-
setGotErrorInOpening(true);
|
|
3258
3664
|
});
|
|
3259
3665
|
} else {
|
|
3260
3666
|
setShowAgeVerification(false);
|