n8n-nodes-tembory 1.0.4 → 1.0.6
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.
|
@@ -630,17 +630,21 @@ const toolHistoryFromMemory = (item) => {
|
|
|
630
630
|
source: meta.source || 'metadata',
|
|
631
631
|
};
|
|
632
632
|
};
|
|
633
|
-
const
|
|
633
|
+
const explicitToolHistoryItemsFromMemory = (item) => {
|
|
634
634
|
const meta = metadataOf(item);
|
|
635
635
|
const content = meta.content || item.memory || item.text || item.value || item.content || item.data;
|
|
636
636
|
const marked = parseToolHistoryMarker(content);
|
|
637
637
|
if (marked)
|
|
638
638
|
return [marked];
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
639
|
+
const textCalls = extractToolCallsFromText(content, meta.at || item.created_at || item.createdAt || nowIso());
|
|
640
|
+
return textCalls.length ? textCalls : [];
|
|
641
|
+
};
|
|
642
|
+
const toolHistoryItemsFromMemory = (item) => {
|
|
643
|
+
const meta = metadataOf(item);
|
|
644
|
+
const content = meta.content || item.memory || item.text || item.value || item.content || item.data;
|
|
645
|
+
const explicit = explicitToolHistoryItemsFromMemory(item);
|
|
646
|
+
if (explicit.length)
|
|
647
|
+
return explicit;
|
|
644
648
|
const single = toolHistoryFromMemory(item);
|
|
645
649
|
return single ? [single] : [];
|
|
646
650
|
};
|
|
@@ -1005,11 +1009,18 @@ const getRecentHighlights = (recentMessages, tools, maxItems = 6) => {
|
|
|
1005
1009
|
}
|
|
1006
1010
|
return pruneByLimit(Array.from(new Set(lines)), maxItems);
|
|
1007
1011
|
};
|
|
1012
|
+
const normalizeIntentText = (value = '') => String(value || '')
|
|
1013
|
+
.toLowerCase()
|
|
1014
|
+
.normalize('NFD')
|
|
1015
|
+
.replace(/[\u0300-\u036f]/g, '');
|
|
1016
|
+
const hasConfirmIntent = (value = '') => /\b(confirm\w*|confim\w*|cnfirm\w*|cofnirm\w*|ocnfi\w*|ocnfia\w*|fechar)\b/.test(normalizeIntentText(value));
|
|
1008
1017
|
const inferToolGuard = ({ query, recentMessages, toolHistory, vectorMemories }) => {
|
|
1009
|
-
const text =
|
|
1018
|
+
const text = normalizeIntentText(query);
|
|
1010
1019
|
const names = new Set((toolHistory || []).map((tool) => String(tool.name || '')));
|
|
1011
1020
|
const hasRecentContext = (recentMessages || []).some((msg) => /reserva|pré-reserva|pre-reserva|agend|confirm|hor[aá]rio|dispon/i.test(String(msg.content || '')));
|
|
1012
1021
|
const hasVectorContext = (vectorMemories || []).some((memory) => /reserva|pré-reserva|pre-reserva|agend|confirm|hor[aá]rio|dispon/i.test(memoryText(memory)));
|
|
1022
|
+
const hasAvailabilityTool = names.has('agenda_consultar_disponibilidade');
|
|
1023
|
+
const hasPreReservationTool = names.has('agenda_pre_reservar_horario');
|
|
1013
1024
|
const hasAnyContext = names.size > 0 || hasRecentContext || hasVectorContext;
|
|
1014
1025
|
const blocked = [];
|
|
1015
1026
|
const reasons = [];
|
|
@@ -1017,32 +1028,34 @@ const inferToolGuard = ({ query, recentMessages, toolHistory, vectorMemories })
|
|
|
1017
1028
|
blocked.push('agenda_pre_reservar_horario', 'agenda_confirmar_agendamento');
|
|
1018
1029
|
reasons.push('no prior availability or pre-reservation context was found for this session');
|
|
1019
1030
|
}
|
|
1020
|
-
if ((
|
|
1031
|
+
if (hasConfirmIntent(text) && !hasPreReservationTool) {
|
|
1021
1032
|
blocked.push('agenda_confirmar_agendamento');
|
|
1022
|
-
reasons.push('confirmation requested but no
|
|
1033
|
+
reasons.push('confirmation requested but no structured agenda_pre_reservar_horario tool result was found; assistant text or vector memories are not enough to confirm');
|
|
1023
1034
|
}
|
|
1024
|
-
if ((/pre.?reserv|
|
|
1035
|
+
if ((/pre.?reserv|pre.?reserv|reservar/.test(text)) && !hasAvailabilityTool) {
|
|
1025
1036
|
blocked.push('agenda_pre_reservar_horario');
|
|
1026
|
-
reasons.push('reservation requested but no
|
|
1037
|
+
reasons.push('reservation requested but no structured agenda_consultar_disponibilidade tool result was found');
|
|
1027
1038
|
}
|
|
1028
1039
|
return { blockedTools: Array.from(new Set(blocked)), reasons };
|
|
1029
1040
|
};
|
|
1030
1041
|
const inferUserIntent = (query = '', recentMessages = []) => {
|
|
1031
1042
|
const latestUser = [...(recentMessages || [])].reverse().find((msg) => /^(user|human)$/i.test(String(msg.role || '')));
|
|
1032
|
-
const
|
|
1033
|
-
|
|
1043
|
+
const rawText = `${query || ''}\n${latestUser?.content || ''}`;
|
|
1044
|
+
const text = normalizeIntentText(rawText);
|
|
1045
|
+
const normalizedQuery = normalizeIntentText(query).trim();
|
|
1046
|
+
if (/^(ok|sim|pode|pode sim|isso|isso mesmo|confirmo|confirmar)$/.test(normalizedQuery))
|
|
1034
1047
|
return 'affirm';
|
|
1035
|
-
if (
|
|
1048
|
+
if (hasConfirmIntent(text))
|
|
1036
1049
|
return 'confirm';
|
|
1037
1050
|
if (containsSelectedSlot(text))
|
|
1038
1051
|
return 'select_slot';
|
|
1039
|
-
if (/\b(pre.?reserv|
|
|
1052
|
+
if (/\b(pre.?reserv|pre.?reserv|reservar|segurar|marcar)\b/.test(text))
|
|
1040
1053
|
return 'pre_reserve';
|
|
1041
|
-
if (/\b(disponibilidade|
|
|
1054
|
+
if (/\b(disponibilidade|horarios?|agenda(?:r|mento)?|quando pode|tem vaga|quero agendar|gostaria de agendar|preciso agendar)\b/.test(text))
|
|
1042
1055
|
return 'check_availability';
|
|
1043
1056
|
if (/\b(cancel|desmarcar|remarcar|alterar|mudar)\b/.test(text))
|
|
1044
1057
|
return 'change_or_cancel';
|
|
1045
|
-
if (/\b(meu nome|email|telefone|empresa|prefiro|
|
|
1058
|
+
if (/\b(meu nome|email|telefone|empresa|prefiro|preferencia)\b/.test(text))
|
|
1046
1059
|
return 'profile_update';
|
|
1047
1060
|
if (text.trim())
|
|
1048
1061
|
return 'general_message';
|
|
@@ -1060,7 +1073,7 @@ const deriveNextExpectedAction = (intent, operationalState = {}) => {
|
|
|
1060
1073
|
if (intent === 'confirm') {
|
|
1061
1074
|
if (agenda.has_pending_pre_reservation)
|
|
1062
1075
|
return 'call agenda_confirmar_agendamento now using the latest pre-reservation context; do not ask again';
|
|
1063
|
-
return '
|
|
1076
|
+
return 'do not call agenda_confirmar_agendamento; call agenda_pre_reservar_horario first if a selected slot and availability are known, otherwise call agenda_consultar_disponibilidade';
|
|
1064
1077
|
}
|
|
1065
1078
|
if (intent === 'select_slot') {
|
|
1066
1079
|
if (agenda.has_availability)
|
|
@@ -1274,6 +1287,17 @@ const deriveContextHealth = ({ userId = '', project = '', vectorMemories = [], r
|
|
|
1274
1287
|
generated_at: nowIso(),
|
|
1275
1288
|
};
|
|
1276
1289
|
};
|
|
1290
|
+
const contextMemoryText = (memory, max = 700) => {
|
|
1291
|
+
const text = memoryText(memory);
|
|
1292
|
+
const tools = explicitToolHistoryItemsFromMemory(memory);
|
|
1293
|
+
if (tools.length) {
|
|
1294
|
+
const names = tools.map((tool) => `${tool.name || 'tool'}:${tool.ok === false ? 'failed' : 'ok'}`).join(', ');
|
|
1295
|
+
const ids = tools.map((tool) => tool.result || tool.input || '').join(' ');
|
|
1296
|
+
const idMatch = /(reservation_id|confirmation_id|id)["':\s]+([A-Za-z0-9_.:-]+)/i.exec(ids);
|
|
1297
|
+
return truncate(`[tool_events_extracted] ${names}${idMatch ? ` ${idMatch[1]}=${idMatch[2]}` : ''}. See Tool history for structured details.`, max);
|
|
1298
|
+
}
|
|
1299
|
+
return truncate(text, max);
|
|
1300
|
+
};
|
|
1277
1301
|
const wrapElefaiMemory = (memory, ctx, memoryKey) => new Proxy(memory, {
|
|
1278
1302
|
get(target, prop) {
|
|
1279
1303
|
if (prop === 'loadMemoryVariables') {
|
|
@@ -1352,7 +1376,7 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
1352
1376
|
});
|
|
1353
1377
|
}
|
|
1354
1378
|
if (includeSummary) {
|
|
1355
|
-
const summary = vectorMemories.slice(0, Number(adv.summaryMaxFacts || 4)).map(
|
|
1379
|
+
const summary = vectorMemories.slice(0, Number(adv.summaryMaxFacts || 4)).map((memory) => contextMemoryText(memory, 360)).filter(Boolean);
|
|
1356
1380
|
sections.push({ section: 'summary', title: 'Summary', value: summary.length ? summary : null, why_null: summary.length ? undefined : 'no vector memories to summarize' });
|
|
1357
1381
|
}
|
|
1358
1382
|
sections.push({
|
|
@@ -1410,7 +1434,7 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
1410
1434
|
const scoreMeta = scoreMetaOf(m);
|
|
1411
1435
|
const rawScore = scoreOf(m);
|
|
1412
1436
|
return {
|
|
1413
|
-
memory:
|
|
1437
|
+
memory: contextMemoryText(m, Number(adv.vectorMemoryMaxChars || 700)),
|
|
1414
1438
|
score: includeScores ? (rawScore !== undefined ? rawScore : scoreMeta.hybridScore ?? scoreMeta.recencyScore ?? 'unavailable') : undefined,
|
|
1415
1439
|
semantic_score: includeScores ? scoreMeta.semanticScore : undefined,
|
|
1416
1440
|
recency_score: includeScores ? scoreMeta.recencyScore : undefined,
|
|
@@ -2222,8 +2246,9 @@ class Mem0Memory {
|
|
|
2222
2246
|
for (const msg of recentMessages)
|
|
2223
2247
|
toolHistoryFromRecentMessages.push(...extractToolCallsFromText(msg.content, msg.at));
|
|
2224
2248
|
}
|
|
2249
|
+
const toolHistoryFromVectorMarkers = adv.includeToolHistory === false ? [] : vectorMemories.flatMap(explicitToolHistoryItemsFromMemory);
|
|
2225
2250
|
const toolHistoryFromVectorMemories = adv.includeToolHistory === false || adv.includeToolHistorySemanticFallback !== true ? [] : vectorMemories.flatMap(toolHistoryItemsFromMemory);
|
|
2226
|
-
const toolHistory = adv.includeToolHistory === false ? [] : applyToolHistoryWindow((store.toolHistory[key] || []).concat(persistedToolHistory, toolHistoryFromRecentMessages, toolHistoryFromVectorMemories), adv.toolHistoryTTLSeconds, adv.toolHistoryLastN || 15);
|
|
2251
|
+
const toolHistory = adv.includeToolHistory === false ? [] : applyToolHistoryWindow((store.toolHistory[key] || []).concat(persistedToolHistory, toolHistoryFromRecentMessages, toolHistoryFromVectorMarkers, toolHistoryFromVectorMemories), adv.toolHistoryTTLSeconds, adv.toolHistoryLastN || 15);
|
|
2227
2252
|
const highlights = adv.includeRecentHighlights === false ? [] : getRecentHighlights(recentMessages, toolHistory, adv.recentHighlightsMaxItems || 6);
|
|
2228
2253
|
const profileFacts = adv.includeProfileFacts === false ? {} : mergeProfileFacts(store.profileFacts[key], profileFactsFromMessages(allRecentMessages), profileFactsFromMemories(vectorMemories));
|
|
2229
2254
|
if (adv.includeProfileFacts !== false && Object.keys(profileFacts).length) {
|
|
@@ -2237,7 +2262,7 @@ class Mem0Memory {
|
|
|
2237
2262
|
let connectedModelSummary = '';
|
|
2238
2263
|
if (connectedLanguageModel && typeof connectedLanguageModel.invoke === 'function' && (vectorMemories.length || String(query || '').trim()) && adv.includeSummary !== false) {
|
|
2239
2264
|
try {
|
|
2240
|
-
const facts = vectorMemories.slice(0, Number(adv.summaryMaxFacts || 4)).map(
|
|
2265
|
+
const facts = vectorMemories.slice(0, Number(adv.summaryMaxFacts || 4)).map((memory) => contextMemoryText(memory, 500)).filter(Boolean).join('\n') || '(no vector memories found)';
|
|
2241
2266
|
if (facts || String(query || '').trim()) {
|
|
2242
2267
|
const response = await connectedLanguageModel.invoke([
|
|
2243
2268
|
toBaseMessage({
|
|
@@ -2521,6 +2546,7 @@ exports.__private = {
|
|
|
2521
2546
|
extractToolCallsFromText,
|
|
2522
2547
|
extractToolCalls,
|
|
2523
2548
|
toolHistoryItemsFromMemory,
|
|
2549
|
+
explicitToolHistoryItemsFromMemory,
|
|
2524
2550
|
toolHistoryFromMemory,
|
|
2525
2551
|
recentMessageFromMemory,
|
|
2526
2552
|
dedupeToolHistory,
|
package/package.json
CHANGED