@memori.ai/memori-react 8.39.0 → 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 +13 -0
- package/dist/components/MemoriWidget/MemoriWidget.d.ts +2 -1
- package/dist/components/MemoriWidget/MemoriWidget.js +357 -73
- package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/dist/helpers/credits.d.ts +3 -2
- package/dist/helpers/credits.js +4 -3
- 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/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/esm/components/MemoriWidget/MemoriWidget.d.ts +2 -1
- package/esm/components/MemoriWidget/MemoriWidget.js +357 -73
- package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/esm/helpers/credits.d.ts +3 -2
- package/esm/helpers/credits.js +4 -3
- 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/index.js +1 -1
- package/esm/index.js.map +1 -1
- package/esm/version.d.ts +1 -1
- package/esm/version.js +1 -1
- package/package.json +3 -2
- package/src/components/MemoriWidget/MemoriWidget.tsx +475 -108
- package/src/components/layouts/layouts.stories.tsx +28 -34
- package/src/helpers/credits.ts +6 -3
- 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/index.tsx +1 -0
- package/src/version.ts +1 -1
|
@@ -38,6 +38,7 @@ import { sanitizeText } from '../../helpers/sanitizer';
|
|
|
38
38
|
import { useTTS } from '../../helpers/tts/useTTS';
|
|
39
39
|
import ChatHistoryDrawer from '../ChatHistoryDrawer/ChatHistory';
|
|
40
40
|
import { useSTT } from '../../helpers/stt/useSTT';
|
|
41
|
+
import { useNats } from '../../helpers/nats/useNats';
|
|
41
42
|
const getMemoriState = (integrationId) => {
|
|
42
43
|
var _a, _b, _c, _d, _f;
|
|
43
44
|
let widget = integrationId
|
|
@@ -65,6 +66,11 @@ const NULL_PLACE_SPEC = {
|
|
|
65
66
|
longitude: null,
|
|
66
67
|
uncertaintyKm: null,
|
|
67
68
|
};
|
|
69
|
+
const ENTER_TEXT_NATS_TIMEOUT_MS = 120000;
|
|
70
|
+
function readCorrelationID(response) {
|
|
71
|
+
const value = response.correlationID;
|
|
72
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
73
|
+
}
|
|
68
74
|
const typeMessage = (message, waitForPrevious = true, hidden = false, typingText, useLoaderTextAsMsg = false, hasBatchQueued = false) => {
|
|
69
75
|
const e = new CustomEvent('MemoriTextEntered', {
|
|
70
76
|
detail: {
|
|
@@ -161,7 +167,7 @@ window.typeBatchMessages = typeBatchMessages;
|
|
|
161
167
|
let audioContext;
|
|
162
168
|
let memoriPassword;
|
|
163
169
|
let userToken;
|
|
164
|
-
const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, tenantID, memoriLang, uiLang, spokenLang, multilingual, integration, layout, customLayout, showShare, preview = false, embed = false, showCopyButton = true, showTranslationOriginal = false, showInputs = true, showDates = false, showContextPerLine = false, showMessageConsumption = false, showSettings, showTypingText = false, showClear = false, showLogin = false, showUpload, showOnlyLastMessages, showChatHistory, showReasoning, avatar3dHidden, height = '100vh', secret, baseUrl = 'https://aisuru-staging.aclambda.online', apiURL = 'https://backend-staging.memori.ai', engineURL = 'https://engine-staging.memori.ai', initialContextVars, initialQuestion, ttsProvider, ogImage, sessionID: initialSessionID, tenant, personification, authToken, enableAudio, defaultSpeakerActive = true, disableTextEnteredEvents = false, onStateChange, additionalInfo, additionalSettings, customMediaRenderer, userAvatar, __WEBCOMPONENT__ = false, useMathFormatting = false, autoStart = false, applyVarsToRoot = false, showFunctionCache = false, maxTotalMessagePayload, maxTextareaCharacters, }) => {
|
|
170
|
+
const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, ownerUserName, tenantID, memoriLang, uiLang, spokenLang, multilingual, integration, layout, customLayout, showShare, preview = false, embed = false, showCopyButton = true, showTranslationOriginal = false, showInputs = true, showDates = false, showContextPerLine = false, showMessageConsumption = false, showSettings, showTypingText = false, showClear = false, showLogin = false, showUpload, showOnlyLastMessages, showChatHistory, showReasoning, avatar3dHidden, height = '100vh', secret, baseUrl = 'https://aisuru-staging.aclambda.online', apiURL = 'https://backend-staging.memori.ai', engineURL = 'https://engine-staging.memori.ai', initialContextVars, initialQuestion, ttsProvider, ogImage, sessionID: initialSessionID, tenant, personification, authToken, enableAudio, defaultSpeakerActive = true, disableTextEnteredEvents = false, onStateChange, additionalInfo, additionalSettings, customMediaRenderer, userAvatar, __WEBCOMPONENT__ = false, useMathFormatting = false, autoStart = false, applyVarsToRoot = false, showFunctionCache = false, maxTotalMessagePayload, maxTextareaCharacters, }) => {
|
|
165
171
|
var _a, _b, _c, _d, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18;
|
|
166
172
|
const { t, i18n } = useTranslation();
|
|
167
173
|
const [isClient, setIsClient] = useState(false);
|
|
@@ -169,7 +175,7 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, tenantID, memoriLang
|
|
|
169
175
|
setIsClient(true);
|
|
170
176
|
}, []);
|
|
171
177
|
const client = memoriApiClient(apiURL, engineURL);
|
|
172
|
-
const { initSession, deleteSession, postTextEnteredEvent, postPlaceChangedEvent, postDateChangedEvent, postTagChangedEvent, getSession, getExpertReferences, getSessionChatLogs, } = client;
|
|
178
|
+
const { initSession, deleteSession, postEnterTextAsync, postTextEnteredEvent, postPlaceChangedEvent, postDateChangedEvent, postTagChangedEvent, getSession, getExpertReferences, getSessionChatLogs, } = client;
|
|
173
179
|
const [instruct, setInstruct] = useState(false);
|
|
174
180
|
const [enableFocusChatInput, setEnableFocusChatInput] = useState(true);
|
|
175
181
|
const [loginToken, setLoginToken] = useState((_a = additionalInfo === null || additionalInfo === void 0 ? void 0 : additionalInfo.loginToken) !== null && _a !== void 0 ? _a : authToken);
|
|
@@ -234,6 +240,8 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, tenantID, memoriLang
|
|
|
234
240
|
const [loading, setLoading] = useState(false);
|
|
235
241
|
const [memoriTyping, setMemoriTyping] = useState(false);
|
|
236
242
|
const [typingText, setTypingText] = useState();
|
|
243
|
+
const pendingEnterTextRef = useRef(new Map());
|
|
244
|
+
const bufferedNatsResponsesRef = useRef(new Map());
|
|
237
245
|
const layoutName = typeof layout === 'string'
|
|
238
246
|
? layout
|
|
239
247
|
: typeof (integrationConfig === null || integrationConfig === void 0 ? void 0 : integrationConfig.layout) === 'string'
|
|
@@ -382,7 +390,7 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, tenantID, memoriLang
|
|
|
382
390
|
};
|
|
383
391
|
const [chatLogID, setChatLogID] = useState(undefined);
|
|
384
392
|
const sendMessage = async (text, media, newSessionId, translate = true, translatedText, hidden = false, typingText, useLoaderTextAsMsg = false, hasBatchQueued = false) => {
|
|
385
|
-
var _a, _b, _c, _d
|
|
393
|
+
var _a, _b, _c, _d;
|
|
386
394
|
const sessionID = newSessionId ||
|
|
387
395
|
sessionId ||
|
|
388
396
|
((_a = window.getMemoriState()) === null || _a === void 0 ? void 0 : _a.sessionID);
|
|
@@ -436,12 +444,16 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, tenantID, memoriLang
|
|
|
436
444
|
? !!newSessionId && newSessionId !== sessionId
|
|
437
445
|
: !!newSessionId,
|
|
438
446
|
});
|
|
439
|
-
setMemoriTyping(true);
|
|
440
|
-
setTypingText(typingText);
|
|
441
447
|
let gotError = false;
|
|
442
448
|
try {
|
|
443
449
|
const placeSpec = getPlaceSpecForEnterText(position);
|
|
444
|
-
|
|
450
|
+
console.debug('[EnterText] sendMessage: posting', {
|
|
451
|
+
sessionId: sessionID,
|
|
452
|
+
textLength: msg.length,
|
|
453
|
+
hasBatchQueued,
|
|
454
|
+
typingText,
|
|
455
|
+
});
|
|
456
|
+
const response = await postEnterTextAsync({
|
|
445
457
|
sessionId: sessionID,
|
|
446
458
|
text: msg,
|
|
447
459
|
...(memori.needsDateTime && {
|
|
@@ -449,57 +461,35 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, tenantID, memoriLang
|
|
|
449
461
|
}),
|
|
450
462
|
...(placeSpec !== undefined && { place: placeSpec }),
|
|
451
463
|
});
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
pushMessage({
|
|
475
|
-
text: emission,
|
|
476
|
-
emitter: currentState.emitter,
|
|
477
|
-
media: (_d = currentState.emittedMedia) !== null && _d !== void 0 ? _d : currentState.media,
|
|
478
|
-
llmUsage: currentState.llmUsage,
|
|
479
|
-
fromUser: false,
|
|
480
|
-
questionAnswered: msg,
|
|
481
|
-
generatedByAI: !!currentState.completion,
|
|
482
|
-
contextVars: currentState.contextVars,
|
|
483
|
-
date: currentState.currentDate,
|
|
484
|
-
placeName: currentState.currentPlaceName,
|
|
485
|
-
placeLatitude: currentState.currentLatitude,
|
|
486
|
-
placeLongitude: currentState.currentLongitude,
|
|
487
|
-
placeUncertaintyKm: currentState.currentUncertaintyKm,
|
|
488
|
-
tag: currentState.currentTag,
|
|
489
|
-
memoryTags: currentState.memoryTags,
|
|
490
|
-
});
|
|
491
|
-
if (emission && shouldPlayAudio(emission)) {
|
|
492
|
-
handleSpeak(emission);
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
}
|
|
464
|
+
console.debug('[EnterText] sendMessage: HTTP response', {
|
|
465
|
+
resultCode: response.resultCode,
|
|
466
|
+
correlationID: readCorrelationID(response),
|
|
467
|
+
resultMessage: response.resultMessage,
|
|
468
|
+
});
|
|
469
|
+
const correlationID = readCorrelationID(response);
|
|
470
|
+
if (response.resultCode === 0 && correlationID) {
|
|
471
|
+
registerPendingEnterText(correlationID, {
|
|
472
|
+
msg,
|
|
473
|
+
typingText,
|
|
474
|
+
useLoaderTextAsMsg,
|
|
475
|
+
hasBatchQueued,
|
|
476
|
+
});
|
|
477
|
+
console.info('[EnterText] sendMessage: accepted, showing typing indicator', {
|
|
478
|
+
correlationID: correlationID,
|
|
479
|
+
typingText,
|
|
480
|
+
});
|
|
481
|
+
setMemoriTyping(true);
|
|
482
|
+
setTypingText(typingText);
|
|
483
|
+
}
|
|
484
|
+
else if (response.resultCode === 0) {
|
|
485
|
+
console.error('[EnterText] sendMessage: HTTP 200 but missing correlationID — cannot match NATS response', response);
|
|
496
486
|
}
|
|
497
487
|
else if (response.resultCode === 404) {
|
|
498
488
|
setHistory(h => [...h.slice(0, h.length - 1)]);
|
|
499
489
|
reopenSession(true, memoriPwd || memori.secretToken, memoriTokens, undefined, undefined, {
|
|
500
490
|
LANG: userLang,
|
|
501
491
|
PATHNAME: window.location.pathname,
|
|
502
|
-
ROUTE: ((
|
|
492
|
+
ROUTE: ((_d = (_c = window.location.pathname) === null || _c === void 0 ? void 0 : _c.split('/')) === null || _d === void 0 ? void 0 : _d.pop()) || '',
|
|
503
493
|
...(initialContextVars || {}),
|
|
504
494
|
}, initialQuestion, undefined, undefined, undefined, undefined, true).then(state => {
|
|
505
495
|
console.info('session timeout');
|
|
@@ -529,16 +519,11 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, tenantID, memoriLang
|
|
|
529
519
|
}
|
|
530
520
|
}
|
|
531
521
|
catch (error) {
|
|
532
|
-
console.
|
|
533
|
-
console.error(error);
|
|
522
|
+
console.error('[EnterText] sendMessage: request failed', error);
|
|
534
523
|
gotError = true;
|
|
535
524
|
setTypingText(undefined);
|
|
536
525
|
setMemoriTyping(false);
|
|
537
526
|
}
|
|
538
|
-
if (!hasBatchQueued) {
|
|
539
|
-
setTypingText(undefined);
|
|
540
|
-
setMemoriTyping(false);
|
|
541
|
-
}
|
|
542
527
|
};
|
|
543
528
|
const translateDialogState = async (state, userLang, msg, avoidPushingMessage = false) => {
|
|
544
529
|
var _a, _b, _c, _d, _f, _g;
|
|
@@ -760,7 +745,7 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, tenantID, memoriLang
|
|
|
760
745
|
setAuthModalState('password');
|
|
761
746
|
return;
|
|
762
747
|
}
|
|
763
|
-
if (!(await checkCredits({ notify: true
|
|
748
|
+
if (!(await checkCredits({ notify: true }))) {
|
|
764
749
|
return;
|
|
765
750
|
}
|
|
766
751
|
setLoading(true);
|
|
@@ -843,7 +828,7 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, tenantID, memoriLang
|
|
|
843
828
|
setAuthModalState('password');
|
|
844
829
|
return;
|
|
845
830
|
}
|
|
846
|
-
if (!(await checkCredits({ notify: true
|
|
831
|
+
if (!(await checkCredits({ notify: true }))) {
|
|
847
832
|
setLoading(false);
|
|
848
833
|
return null;
|
|
849
834
|
}
|
|
@@ -1156,6 +1141,277 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, tenantID, memoriLang
|
|
|
1156
1141
|
setHasUserActivatedSpeak,
|
|
1157
1142
|
speakerMuted,
|
|
1158
1143
|
]);
|
|
1144
|
+
const processEnterTextDialogResponse = useCallback((event, pending) => {
|
|
1145
|
+
var _a, _b;
|
|
1146
|
+
console.debug('[EnterText] processDialogResponse', {
|
|
1147
|
+
correlationID: event.correlationID,
|
|
1148
|
+
resultCode: event.resultCode,
|
|
1149
|
+
hasCurrentState: !!event.currentState,
|
|
1150
|
+
hasBatchQueued: pending.hasBatchQueued,
|
|
1151
|
+
});
|
|
1152
|
+
const { msg, typingText: pendingTypingText, useLoaderTextAsMsg, } = pending;
|
|
1153
|
+
const currentState = event.currentState;
|
|
1154
|
+
if (event.resultCode !== 0 || !currentState) {
|
|
1155
|
+
if (event.resultCode === 500 && event.resultMessage) {
|
|
1156
|
+
console.warn('[EnterText] processDialogResponse: server error', {
|
|
1157
|
+
correlationID: event.correlationID,
|
|
1158
|
+
resultMessage: event.resultMessage,
|
|
1159
|
+
});
|
|
1160
|
+
setHistory(h => [
|
|
1161
|
+
...h,
|
|
1162
|
+
{
|
|
1163
|
+
text: 'Error: ' + event.resultMessage,
|
|
1164
|
+
emitter: 'system',
|
|
1165
|
+
fromUser: false,
|
|
1166
|
+
initial: false,
|
|
1167
|
+
contextVars: {},
|
|
1168
|
+
date: new Date().toISOString(),
|
|
1169
|
+
},
|
|
1170
|
+
]);
|
|
1171
|
+
}
|
|
1172
|
+
else if (event.resultCode !== 0) {
|
|
1173
|
+
console.warn('[SEND_MESSAGE/NATS]', event);
|
|
1174
|
+
}
|
|
1175
|
+
return;
|
|
1176
|
+
}
|
|
1177
|
+
if (!msg) {
|
|
1178
|
+
console.debug('[EnterText] processDialogResponse: no msg in pending, skipping');
|
|
1179
|
+
return;
|
|
1180
|
+
}
|
|
1181
|
+
setChatLogID(undefined);
|
|
1182
|
+
const emission = useLoaderTextAsMsg && pendingTypingText
|
|
1183
|
+
? pendingTypingText
|
|
1184
|
+
: (_a = currentState.emission) !== null && _a !== void 0 ? _a : currentDialogState === null || currentDialogState === void 0 ? void 0 : currentDialogState.emission;
|
|
1185
|
+
console.debug('[EnterText] processDialogResponse: rendering emission', {
|
|
1186
|
+
correlationID: event.correlationID,
|
|
1187
|
+
emissionPreview: emission === null || emission === void 0 ? void 0 : emission.slice(0, 80),
|
|
1188
|
+
state: currentState.state,
|
|
1189
|
+
});
|
|
1190
|
+
if (userLang.toLowerCase() !== language.toLowerCase() &&
|
|
1191
|
+
emission &&
|
|
1192
|
+
isMultilanguageEnabled) {
|
|
1193
|
+
currentState.emission = emission;
|
|
1194
|
+
translateDialogState(currentState, userLang, msg).then(ts => {
|
|
1195
|
+
const text = ts.translatedEmission || ts.emission;
|
|
1196
|
+
if (text && shouldPlayAudio(text)) {
|
|
1197
|
+
handleSpeak(text);
|
|
1198
|
+
}
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
1201
|
+
else {
|
|
1202
|
+
setCurrentDialogState({
|
|
1203
|
+
...currentState,
|
|
1204
|
+
emission,
|
|
1205
|
+
});
|
|
1206
|
+
if (emission) {
|
|
1207
|
+
pushMessage({
|
|
1208
|
+
text: emission,
|
|
1209
|
+
emitter: currentState.emitter,
|
|
1210
|
+
media: (_b = currentState.emittedMedia) !== null && _b !== void 0 ? _b : currentState.media,
|
|
1211
|
+
llmUsage: currentState.llmUsage,
|
|
1212
|
+
fromUser: false,
|
|
1213
|
+
questionAnswered: msg,
|
|
1214
|
+
generatedByAI: !!currentState.completion,
|
|
1215
|
+
contextVars: currentState.contextVars,
|
|
1216
|
+
date: currentState.currentDate,
|
|
1217
|
+
placeName: currentState.currentPlaceName,
|
|
1218
|
+
placeLatitude: currentState.currentLatitude,
|
|
1219
|
+
placeLongitude: currentState.currentLongitude,
|
|
1220
|
+
placeUncertaintyKm: currentState.currentUncertaintyKm,
|
|
1221
|
+
tag: currentState.currentTag,
|
|
1222
|
+
memoryTags: currentState.memoryTags,
|
|
1223
|
+
});
|
|
1224
|
+
if (emission && shouldPlayAudio(emission)) {
|
|
1225
|
+
handleSpeak(emission);
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
}, [
|
|
1230
|
+
userLang,
|
|
1231
|
+
language,
|
|
1232
|
+
isMultilanguageEnabled,
|
|
1233
|
+
currentDialogState === null || currentDialogState === void 0 ? void 0 : currentDialogState.emission,
|
|
1234
|
+
translateDialogState,
|
|
1235
|
+
handleSpeak,
|
|
1236
|
+
shouldPlayAudio,
|
|
1237
|
+
]);
|
|
1238
|
+
const clearEnterTextPending = useCallback((correlationID, pending) => {
|
|
1239
|
+
var _a;
|
|
1240
|
+
if (pending.natsTimeoutId) {
|
|
1241
|
+
clearTimeout(pending.natsTimeoutId);
|
|
1242
|
+
}
|
|
1243
|
+
if ((_a = pending.waitForResponse) === null || _a === void 0 ? void 0 : _a.timeoutId) {
|
|
1244
|
+
clearTimeout(pending.waitForResponse.timeoutId);
|
|
1245
|
+
}
|
|
1246
|
+
pendingEnterTextRef.current.delete(correlationID);
|
|
1247
|
+
}, []);
|
|
1248
|
+
const deliverEnterTextNatsError = useCallback((event) => {
|
|
1249
|
+
var _a, _b, _c;
|
|
1250
|
+
const correlationID = event.correlationID;
|
|
1251
|
+
const errorText = event.errorMessage
|
|
1252
|
+
? `Error: ${event.errorMessage}`
|
|
1253
|
+
: event.errorCode
|
|
1254
|
+
? `Error: ${event.errorCode}`
|
|
1255
|
+
: 'Error: An unexpected error occurred';
|
|
1256
|
+
console.error('[EnterText] NATS error event', {
|
|
1257
|
+
correlationID,
|
|
1258
|
+
errorCode: event.errorCode,
|
|
1259
|
+
errorMessage: event.errorMessage,
|
|
1260
|
+
});
|
|
1261
|
+
pushMessage({
|
|
1262
|
+
text: errorText,
|
|
1263
|
+
emitter: 'system',
|
|
1264
|
+
fromUser: false,
|
|
1265
|
+
initial: false,
|
|
1266
|
+
contextVars: {},
|
|
1267
|
+
date: new Date().toISOString(),
|
|
1268
|
+
});
|
|
1269
|
+
if (correlationID) {
|
|
1270
|
+
const pending = pendingEnterTextRef.current.get(correlationID);
|
|
1271
|
+
if (pending) {
|
|
1272
|
+
clearEnterTextPending(correlationID, pending);
|
|
1273
|
+
(_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')));
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
setMemoriTyping(false);
|
|
1277
|
+
setTypingText(undefined);
|
|
1278
|
+
}, [clearEnterTextPending]);
|
|
1279
|
+
const deliverEnterTextNatsResponse = useCallback((correlationID, event) => {
|
|
1280
|
+
const pending = pendingEnterTextRef.current.get(correlationID);
|
|
1281
|
+
if (!pending) {
|
|
1282
|
+
const pendingCorrelationIDs = [...pendingEnterTextRef.current.keys()];
|
|
1283
|
+
console.warn('[EnterText] NATS response buffered (no matching pending)', {
|
|
1284
|
+
receivedCorrelationID: correlationID,
|
|
1285
|
+
resultCode: event.resultCode,
|
|
1286
|
+
pendingCorrelationIDs,
|
|
1287
|
+
hint: pendingCorrelationIDs.length > 0
|
|
1288
|
+
? 'Use one of pendingCorrelationIDs in your nats pub correlation_id'
|
|
1289
|
+
: 'Send a message in the widget first, then copy correlationID from HTTP response logs',
|
|
1290
|
+
});
|
|
1291
|
+
bufferedNatsResponsesRef.current.set(correlationID, event);
|
|
1292
|
+
return;
|
|
1293
|
+
}
|
|
1294
|
+
clearEnterTextPending(correlationID, pending);
|
|
1295
|
+
if (pending.waitForResponse) {
|
|
1296
|
+
console.info('[EnterText] NATS response delivered to waiter', {
|
|
1297
|
+
correlationID,
|
|
1298
|
+
resultCode: event.resultCode,
|
|
1299
|
+
});
|
|
1300
|
+
pending.waitForResponse.resolve(event);
|
|
1301
|
+
setMemoriTyping(false);
|
|
1302
|
+
setTypingText(undefined);
|
|
1303
|
+
return;
|
|
1304
|
+
}
|
|
1305
|
+
processEnterTextDialogResponse(event, pending);
|
|
1306
|
+
if (!pending.hasBatchQueued) {
|
|
1307
|
+
console.info('[EnterText] typing indicator cleared', { correlationID });
|
|
1308
|
+
setMemoriTyping(false);
|
|
1309
|
+
setTypingText(undefined);
|
|
1310
|
+
}
|
|
1311
|
+
else {
|
|
1312
|
+
console.debug('[EnterText] typing kept (batch queued)', {
|
|
1313
|
+
correlationID,
|
|
1314
|
+
});
|
|
1315
|
+
}
|
|
1316
|
+
}, [processEnterTextDialogResponse, clearEnterTextPending]);
|
|
1317
|
+
const registerPendingEnterText = useCallback((correlationID, pending) => {
|
|
1318
|
+
const buffered = bufferedNatsResponsesRef.current.get(correlationID);
|
|
1319
|
+
if (buffered) {
|
|
1320
|
+
console.info('[EnterText] replaying buffered NATS response', {
|
|
1321
|
+
correlationID,
|
|
1322
|
+
waitForResponse: !!pending.waitForResponse,
|
|
1323
|
+
});
|
|
1324
|
+
bufferedNatsResponsesRef.current.delete(correlationID);
|
|
1325
|
+
pendingEnterTextRef.current.set(correlationID, pending);
|
|
1326
|
+
deliverEnterTextNatsResponse(correlationID, buffered);
|
|
1327
|
+
return;
|
|
1328
|
+
}
|
|
1329
|
+
if (!pending.waitForResponse && !pending.natsTimeoutId) {
|
|
1330
|
+
pending.natsTimeoutId = setTimeout(() => {
|
|
1331
|
+
var _a;
|
|
1332
|
+
const current = pendingEnterTextRef.current.get(correlationID);
|
|
1333
|
+
if (!current)
|
|
1334
|
+
return;
|
|
1335
|
+
clearEnterTextPending(correlationID, current);
|
|
1336
|
+
console.error('[EnterText] NATS response timeout', {
|
|
1337
|
+
correlationID,
|
|
1338
|
+
timeoutMs: ENTER_TEXT_NATS_TIMEOUT_MS,
|
|
1339
|
+
});
|
|
1340
|
+
if (!current.hasBatchQueued) {
|
|
1341
|
+
setMemoriTyping(false);
|
|
1342
|
+
setTypingText(undefined);
|
|
1343
|
+
}
|
|
1344
|
+
(_a = current.waitForResponse) === null || _a === void 0 ? void 0 : _a.reject(new Error('NATS enter-text response timeout'));
|
|
1345
|
+
}, ENTER_TEXT_NATS_TIMEOUT_MS);
|
|
1346
|
+
}
|
|
1347
|
+
console.debug('[EnterText] pending registered', {
|
|
1348
|
+
correlationID,
|
|
1349
|
+
waitForResponse: !!pending.waitForResponse,
|
|
1350
|
+
hasBatchQueued: pending.hasBatchQueued,
|
|
1351
|
+
});
|
|
1352
|
+
pendingEnterTextRef.current.set(correlationID, pending);
|
|
1353
|
+
}, [deliverEnterTextNatsResponse, clearEnterTextPending]);
|
|
1354
|
+
const waitForEnterTextNatsResponse = useCallback((correlationID, timeoutMs = 120000) => new Promise((resolve, reject) => {
|
|
1355
|
+
console.debug('[EnterText] waiting for NATS response', {
|
|
1356
|
+
correlationID,
|
|
1357
|
+
timeoutMs,
|
|
1358
|
+
});
|
|
1359
|
+
const timeoutId = setTimeout(() => {
|
|
1360
|
+
const current = pendingEnterTextRef.current.get(correlationID);
|
|
1361
|
+
if (current) {
|
|
1362
|
+
clearEnterTextPending(correlationID, current);
|
|
1363
|
+
}
|
|
1364
|
+
console.error('[EnterText] NATS response timeout', {
|
|
1365
|
+
correlationID,
|
|
1366
|
+
timeoutMs,
|
|
1367
|
+
});
|
|
1368
|
+
reject(new Error('NATS enter-text response timeout'));
|
|
1369
|
+
}, timeoutMs);
|
|
1370
|
+
registerPendingEnterText(correlationID, {
|
|
1371
|
+
waitForResponse: {
|
|
1372
|
+
resolve: event => {
|
|
1373
|
+
clearTimeout(timeoutId);
|
|
1374
|
+
resolve(event);
|
|
1375
|
+
},
|
|
1376
|
+
reject: error => {
|
|
1377
|
+
clearTimeout(timeoutId);
|
|
1378
|
+
reject(error);
|
|
1379
|
+
},
|
|
1380
|
+
timeoutId,
|
|
1381
|
+
},
|
|
1382
|
+
});
|
|
1383
|
+
}), [registerPendingEnterText, clearEnterTextPending]);
|
|
1384
|
+
useNats({
|
|
1385
|
+
baseUrl,
|
|
1386
|
+
sessionId,
|
|
1387
|
+
onProgress: useCallback((event) => {
|
|
1388
|
+
console.debug('[EnterText] NATS progress', {
|
|
1389
|
+
correlationID: event.correlationID,
|
|
1390
|
+
step: event.currentStep,
|
|
1391
|
+
finalStep: event.finalStep,
|
|
1392
|
+
message: event.message,
|
|
1393
|
+
});
|
|
1394
|
+
if (event.message) {
|
|
1395
|
+
setTypingText(event.message);
|
|
1396
|
+
}
|
|
1397
|
+
}, []),
|
|
1398
|
+
onDialogResponse: useCallback((event) => {
|
|
1399
|
+
const correlationID = event.correlationID;
|
|
1400
|
+
console.debug('[EnterText] NATS dialog.text_entered_response received', {
|
|
1401
|
+
correlationID,
|
|
1402
|
+
resultCode: event.resultCode,
|
|
1403
|
+
requestID: event.requestID,
|
|
1404
|
+
});
|
|
1405
|
+
if (!correlationID) {
|
|
1406
|
+
console.warn('[EnterText] dialog_text_entered_response without correlationID', event);
|
|
1407
|
+
setMemoriTyping(false);
|
|
1408
|
+
setTypingText(undefined);
|
|
1409
|
+
return;
|
|
1410
|
+
}
|
|
1411
|
+
deliverEnterTextNatsResponse(correlationID, event);
|
|
1412
|
+
}, [deliverEnterTextNatsResponse]),
|
|
1413
|
+
onError: deliverEnterTextNatsError,
|
|
1414
|
+
});
|
|
1159
1415
|
const focusChatInput = () => {
|
|
1160
1416
|
let textarea = document.querySelector('#chat-fieldset textarea');
|
|
1161
1417
|
if (textarea && enableFocusChatInput) {
|
|
@@ -1350,7 +1606,7 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, tenantID, memoriLang
|
|
|
1350
1606
|
};
|
|
1351
1607
|
}, [sessionId, userLang, disableTextEnteredEvents]);
|
|
1352
1608
|
const onClickStart = useCallback(async (session, initialSessionExpired = false, chatLog, targetSessionID) => {
|
|
1353
|
-
var _a, _b, _c, _d, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v
|
|
1609
|
+
var _a, _b, _c, _d, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
|
|
1354
1610
|
const sessionID = chatLog ? undefined : (session === null || session === void 0 ? void 0 : session.sessionID) || sessionId;
|
|
1355
1611
|
const dialogState = chatLog
|
|
1356
1612
|
? undefined
|
|
@@ -1367,7 +1623,7 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, tenantID, memoriLang
|
|
|
1367
1623
|
setShowPositionDrawer(true);
|
|
1368
1624
|
return;
|
|
1369
1625
|
}
|
|
1370
|
-
if (!(await checkCredits({ notify: true
|
|
1626
|
+
if (!(await checkCredits({ notify: true }))) {
|
|
1371
1627
|
setClickedStart(false);
|
|
1372
1628
|
setLoading(false);
|
|
1373
1629
|
return;
|
|
@@ -1573,9 +1829,11 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, tenantID, memoriLang
|
|
|
1573
1829
|
console.log('[onClickStart] Starting with initial question');
|
|
1574
1830
|
translatedMessages = [];
|
|
1575
1831
|
setHistory([]);
|
|
1576
|
-
setMemoriTyping(true);
|
|
1577
1832
|
const placeSpec = getPlaceSpecForEnterText(position);
|
|
1578
|
-
|
|
1833
|
+
console.debug('[EnterText] onClickStart: posting initial question', {
|
|
1834
|
+
sessionId: sessionID,
|
|
1835
|
+
});
|
|
1836
|
+
const response = await postEnterTextAsync({
|
|
1579
1837
|
sessionId: sessionID,
|
|
1580
1838
|
text: initialQuestion,
|
|
1581
1839
|
...(memori.needsDateTime && {
|
|
@@ -1583,6 +1841,10 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, tenantID, memoriLang
|
|
|
1583
1841
|
}),
|
|
1584
1842
|
...(placeSpec !== undefined && { place: placeSpec }),
|
|
1585
1843
|
});
|
|
1844
|
+
console.debug('[EnterText] onClickStart: HTTP response', {
|
|
1845
|
+
resultCode: response.resultCode,
|
|
1846
|
+
correlationID: readCorrelationID(response),
|
|
1847
|
+
});
|
|
1586
1848
|
if (response.resultCode === 500 && response.resultMessage) {
|
|
1587
1849
|
setHistory(h => [
|
|
1588
1850
|
...h,
|
|
@@ -1595,10 +1857,33 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, tenantID, memoriLang
|
|
|
1595
1857
|
date: new Date().toISOString(),
|
|
1596
1858
|
},
|
|
1597
1859
|
]);
|
|
1598
|
-
setMemoriTyping(false);
|
|
1599
1860
|
return;
|
|
1600
1861
|
}
|
|
1601
|
-
|
|
1862
|
+
const onClickStartCorrelationID = readCorrelationID(response);
|
|
1863
|
+
if (response.resultCode === 0 && onClickStartCorrelationID) {
|
|
1864
|
+
console.info('[EnterText] onClickStart: accepted, showing typing indicator', {
|
|
1865
|
+
correlationID: onClickStartCorrelationID,
|
|
1866
|
+
});
|
|
1867
|
+
setMemoriTyping(true);
|
|
1868
|
+
try {
|
|
1869
|
+
const natsEvent = await waitForEnterTextNatsResponse(onClickStartCorrelationID);
|
|
1870
|
+
console.info('[EnterText] onClickStart: NATS response received', {
|
|
1871
|
+
correlationID: onClickStartCorrelationID,
|
|
1872
|
+
resultCode: natsEvent.resultCode,
|
|
1873
|
+
});
|
|
1874
|
+
if (natsEvent.resultCode === 0 && natsEvent.currentState) {
|
|
1875
|
+
await translateAndSpeak(natsEvent.currentState, userLang, undefined, false);
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
catch (e) {
|
|
1879
|
+
console.error('[EnterText] onClickStart: NATS wait failed', e);
|
|
1880
|
+
setMemoriTyping(false);
|
|
1881
|
+
setTypingText(undefined);
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
else if (response.resultCode === 0) {
|
|
1885
|
+
console.error('[EnterText] onClickStart: HTTP 200 but missing correlationID', response);
|
|
1886
|
+
}
|
|
1602
1887
|
}
|
|
1603
1888
|
}
|
|
1604
1889
|
}
|
|
@@ -1669,21 +1954,18 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, tenantID, memoriLang
|
|
|
1669
1954
|
(user === null || user === void 0 ? void 0 : user.pAndCUAccepted);
|
|
1670
1955
|
const needsCredits = tenant === null || tenant === void 0 ? void 0 : tenant.billingDelegation;
|
|
1671
1956
|
const [hasEnoughCredits, setHasEnoughCredits] = useState(true);
|
|
1672
|
-
const handleNotEnoughCredits = useCallback((
|
|
1957
|
+
const handleNotEnoughCredits = useCallback(() => {
|
|
1673
1958
|
setHasEnoughCredits(false);
|
|
1674
1959
|
setAuthModalState(null);
|
|
1675
1960
|
toast.error(t('notEnoughCredits'));
|
|
1676
|
-
if (goBack && window.history.length > 1) {
|
|
1677
|
-
window.history.back();
|
|
1678
|
-
}
|
|
1679
1961
|
}, [t]);
|
|
1680
1962
|
const checkCredits = useCallback(async (options) => {
|
|
1681
1963
|
if (!(tenant === null || tenant === void 0 ? void 0 : tenant.billingDelegation))
|
|
1682
1964
|
return true;
|
|
1683
|
-
if (!ownerUserID) {
|
|
1684
|
-
console.warn('Cannot verify credits: missing
|
|
1965
|
+
if (!ownerUserID && !ownerUserName) {
|
|
1966
|
+
console.warn('Cannot verify credits: missing owner identifier');
|
|
1685
1967
|
if (options === null || options === void 0 ? void 0 : options.notify) {
|
|
1686
|
-
handleNotEnoughCredits(
|
|
1968
|
+
handleNotEnoughCredits();
|
|
1687
1969
|
}
|
|
1688
1970
|
else {
|
|
1689
1971
|
setHasEnoughCredits(false);
|
|
@@ -1697,6 +1979,7 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, tenantID, memoriLang
|
|
|
1697
1979
|
: 'session_creation',
|
|
1698
1980
|
baseUrl: baseUrl,
|
|
1699
1981
|
userID: ownerUserID,
|
|
1982
|
+
userName: ownerUserName,
|
|
1700
1983
|
tenant: tenantID,
|
|
1701
1984
|
});
|
|
1702
1985
|
if (resp.enough) {
|
|
@@ -1706,7 +1989,7 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, tenantID, memoriLang
|
|
|
1706
1989
|
else {
|
|
1707
1990
|
console.warn('Not enough credits. Required:', resp.required);
|
|
1708
1991
|
if (options === null || options === void 0 ? void 0 : options.notify) {
|
|
1709
|
-
handleNotEnoughCredits(
|
|
1992
|
+
handleNotEnoughCredits();
|
|
1710
1993
|
}
|
|
1711
1994
|
else {
|
|
1712
1995
|
setHasEnoughCredits(false);
|
|
@@ -1724,6 +2007,7 @@ const MemoriWidget = ({ memori, memoriConfigs, ownerUserID, tenantID, memoriLang
|
|
|
1724
2007
|
deepThoughtEnabled,
|
|
1725
2008
|
handleNotEnoughCredits,
|
|
1726
2009
|
ownerUserID,
|
|
2010
|
+
ownerUserName,
|
|
1727
2011
|
tenant === null || tenant === void 0 ? void 0 : tenant.billingDelegation,
|
|
1728
2012
|
tenantID,
|
|
1729
2013
|
]);
|