n8n-nodes-tembory 1.0.35 → 1.0.36
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.
|
@@ -589,9 +589,7 @@ const encodeRecentMessage = (recent, threadId) => `${RECENT_MESSAGE_MARKER}${saf
|
|
|
589
589
|
const encodeConversationLedger = (messages = [], threadId) => {
|
|
590
590
|
const chronological = sortConversationChronological(messages || []);
|
|
591
591
|
const userMessages = chronological.filter((msg) => /^(user|human)$/i.test(String(msg.role || '')));
|
|
592
|
-
const
|
|
593
|
-
const lastUser = userMessages[userMessages.length - 1];
|
|
594
|
-
const readable = `Conversation transcript ledger. Use this ledger to answer first message, previous message, last message, conversation history and what the user already said. First user message: ${firstUser?.content || ''}. Last user message: ${lastUser?.content || ''}. `;
|
|
592
|
+
const readable = `Conversation transcript ledger. Use the chronological messages array to answer conversation recall, including what the user said, message order, and the user message immediately before the current request. Total messages: ${chronological.length}. User messages: ${userMessages.length}. `;
|
|
595
593
|
return `${readable}${CONVERSATION_LEDGER_MARKER}${safeStringify({
|
|
596
594
|
thread_id: threadId,
|
|
597
595
|
generated_at: nowIso(),
|
|
@@ -1069,7 +1067,7 @@ const applyOperationalPreset = (advanced = {}) => {
|
|
|
1069
1067
|
topK: 8,
|
|
1070
1068
|
lastN: 12,
|
|
1071
1069
|
toolHistoryLastN: 15,
|
|
1072
|
-
recentMessagesLastN:
|
|
1070
|
+
recentMessagesLastN: 50,
|
|
1073
1071
|
},
|
|
1074
1072
|
productionBalanced: {
|
|
1075
1073
|
summarySource: 'auto',
|
|
@@ -1102,7 +1100,7 @@ const applyOperationalPreset = (advanced = {}) => {
|
|
|
1102
1100
|
topK: 6,
|
|
1103
1101
|
lastN: 8,
|
|
1104
1102
|
toolHistoryLastN: 10,
|
|
1105
|
-
recentMessagesLastN:
|
|
1103
|
+
recentMessagesLastN: 50,
|
|
1106
1104
|
vectorMemoryMaxChars: 360,
|
|
1107
1105
|
contextMaxChars: 10000,
|
|
1108
1106
|
connectedModelSummaryMaxChars: 1200,
|
|
@@ -1139,7 +1137,7 @@ const applyOperationalPreset = (advanced = {}) => {
|
|
|
1139
1137
|
topK: 4,
|
|
1140
1138
|
lastN: 4,
|
|
1141
1139
|
toolHistoryLastN: 5,
|
|
1142
|
-
recentMessagesLastN:
|
|
1140
|
+
recentMessagesLastN: 50,
|
|
1143
1141
|
vectorMemoryMaxChars: 260,
|
|
1144
1142
|
contextMaxChars: 7000,
|
|
1145
1143
|
connectedModelSummaryMaxChars: 1000,
|
|
@@ -1177,7 +1175,7 @@ const applyOperationalPreset = (advanced = {}) => {
|
|
|
1177
1175
|
lastN: 4,
|
|
1178
1176
|
maxReturn: 6,
|
|
1179
1177
|
toolHistoryLastN: 6,
|
|
1180
|
-
recentMessagesLastN:
|
|
1178
|
+
recentMessagesLastN: 50,
|
|
1181
1179
|
vectorMemoryMaxChars: 220,
|
|
1182
1180
|
contextMaxChars: 7000,
|
|
1183
1181
|
connectedModelSummaryMaxChars: 1200,
|
|
@@ -1207,7 +1205,7 @@ const applyOperationalPreset = (advanced = {}) => {
|
|
|
1207
1205
|
topK: 10,
|
|
1208
1206
|
lastN: 20,
|
|
1209
1207
|
toolHistoryLastN: 20,
|
|
1210
|
-
recentMessagesLastN:
|
|
1208
|
+
recentMessagesLastN: 50,
|
|
1211
1209
|
payloadFormat: 'auditJson',
|
|
1212
1210
|
},
|
|
1213
1211
|
};
|
|
@@ -1375,13 +1373,10 @@ const previousUserFallbackFromWorkingMemory = (query = '', workingMemory = {}) =
|
|
|
1375
1373
|
const firstUserMessageFromConversation = (recentMessages = []) => [...(recentMessages || [])]
|
|
1376
1374
|
.filter((msg) => /^(user|human)$/i.test(String(msg.role || '')))
|
|
1377
1375
|
.sort((a, b) => new Date(a.at || 0).getTime() - new Date(b.at || 0).getTime())[0] || null;
|
|
1378
|
-
const buildConversationFrame = ({ query = '', recentMessages = []
|
|
1376
|
+
const buildConversationFrame = ({ query = '', recentMessages = [] }) => {
|
|
1379
1377
|
const normalizedQuery = normalizeIntentText(query).trim();
|
|
1380
1378
|
const users = recentUserMessages(recentMessages);
|
|
1381
1379
|
const currentUser = users.find((msg) => normalizeIntentText(msg.content).trim() === normalizedQuery) || (query ? { role: 'user', content: query, at: nowIso() } : null);
|
|
1382
|
-
const previousUser = previousUserMessageForQuery(query, recentMessages);
|
|
1383
|
-
const firstUser = firstUserMessageFromConversation(recentMessages);
|
|
1384
|
-
const previousUserMessage = previousUser ? truncate(previousUser.content, 500) : previousUserFallbackFromWorkingMemory(query, workingMemory);
|
|
1385
1380
|
const chronological = (recentMessages || []).map((msg) => ({
|
|
1386
1381
|
role: msg.role,
|
|
1387
1382
|
content: truncate(msg.content, 500),
|
|
@@ -1390,8 +1385,6 @@ const buildConversationFrame = ({ query = '', recentMessages = [], workingMemory
|
|
|
1390
1385
|
const userMessagesChronological = chronological.filter((msg) => /^(user|human)$/i.test(String(msg.role || '')));
|
|
1391
1386
|
const frame = cleanContextValue({
|
|
1392
1387
|
current_user_message: currentUser ? truncate(currentUser.content, 500) : truncate(query, 500),
|
|
1393
|
-
first_user_message: firstUser ? truncate(firstUser.content, 500) : null,
|
|
1394
|
-
previous_user_message: previousUserMessage,
|
|
1395
1388
|
conversation_history_chronological: chronological,
|
|
1396
1389
|
recent_messages_chronological: chronological,
|
|
1397
1390
|
all_user_messages_chronological: userMessagesChronological,
|
|
@@ -1399,10 +1392,8 @@ const buildConversationFrame = ({ query = '', recentMessages = [], workingMemory
|
|
|
1399
1392
|
.filter((msg) => normalizeIntentText(msg.content).trim() !== normalizedQuery)
|
|
1400
1393
|
.slice(0, 5)
|
|
1401
1394
|
.map((msg) => ({ role: msg.role, content: truncate(msg.content, 500), at: msg.at })),
|
|
1402
|
-
instruction: 'This is the authoritative short-term conversation frame. If the user asks about current/previous/last client messages or what they already said, answer from
|
|
1395
|
+
instruction: 'This is the authoritative short-term conversation frame. If the user asks about current/previous/last client messages or what they already said, answer from conversation_history_chronological/all_user_messages_chronological before using vector memories, summaries, operational state, or tool history. For the last message before the current one, use the user message immediately before current_user_message in all_user_messages_chronological.',
|
|
1403
1396
|
});
|
|
1404
|
-
if (!previousUserMessage)
|
|
1405
|
-
frame.previous_user_message = null;
|
|
1406
1397
|
return frame;
|
|
1407
1398
|
};
|
|
1408
1399
|
const buildCurrentTurnFocus = ({ query = '', recentMessages = [], operationalState = {}, workingMemory = {} }) => {
|
|
@@ -1410,31 +1401,31 @@ const buildCurrentTurnFocus = ({ query = '', recentMessages = [], operationalSta
|
|
|
1410
1401
|
const operationalStatus = isOperationalStatusQuery(query);
|
|
1411
1402
|
if (!recall && !operationalStatus)
|
|
1412
1403
|
return null;
|
|
1413
|
-
const previousUser = previousUserMessageForQuery(query, recentMessages);
|
|
1414
|
-
const firstUser = firstUserMessageFromConversation(recentMessages);
|
|
1415
1404
|
const users = recentUserMessages(recentMessages)
|
|
1416
1405
|
.filter((msg) => normalizeIntentText(msg.content).trim() !== normalizeIntentText(query).trim())
|
|
1417
|
-
.slice(0,
|
|
1406
|
+
.slice(0, 8)
|
|
1418
1407
|
.map((msg) => ({ role: msg.role, content: truncate(msg.content, 500), at: msg.at }));
|
|
1419
1408
|
const toolState = (operationalState || {}).tool_state || {};
|
|
1420
|
-
const
|
|
1409
|
+
const chronological = (recentMessages || []).map((msg) => ({
|
|
1410
|
+
role: msg.role,
|
|
1411
|
+
content: truncate(msg.content, 500),
|
|
1412
|
+
at: msg.at,
|
|
1413
|
+
}));
|
|
1414
|
+
const userMessagesChronological = chronological.filter((msg) => /^(user|human)$/i.test(String(msg.role || '')));
|
|
1421
1415
|
const focus = cleanContextValue({
|
|
1422
1416
|
current_user_request: truncate(query, 500),
|
|
1423
1417
|
intent: recall ? 'conversation_recall' : 'tool_or_status_question',
|
|
1424
|
-
first_user_message: firstUser ? truncate(firstUser.content, 500) : null,
|
|
1425
|
-
previous_user_message: previousUserMessage,
|
|
1426
1418
|
recent_user_messages: users,
|
|
1419
|
+
all_user_messages_chronological: recall ? userMessagesChronological : undefined,
|
|
1427
1420
|
tool_status: operationalStatus ? {
|
|
1428
1421
|
executed_tools: toolState.names || [],
|
|
1429
1422
|
last_successful_tool: toolState.last_successful_tool || null,
|
|
1430
1423
|
failed_by_name: toolState.failed_by_name || {},
|
|
1431
1424
|
} : undefined,
|
|
1432
1425
|
instruction: recall
|
|
1433
|
-
? 'Answer the user meta-question from
|
|
1426
|
+
? 'Answer the user meta-question from conversation_history_chronological/all_user_messages_chronological. Do not call tools for recall-only questions and do not infer missing turns from vector memories or summaries.'
|
|
1434
1427
|
: 'Answer status questions from tool_state, tool_history and action_ledger. Do not call tools unless the agent prompt requires it.',
|
|
1435
1428
|
});
|
|
1436
|
-
if (!previousUserMessage)
|
|
1437
|
-
focus.previous_user_message = null;
|
|
1438
1429
|
return focus;
|
|
1439
1430
|
};
|
|
1440
1431
|
const buildActionDirective = ({ workingMemory = {}, operationalState = {} }) => {
|
|
@@ -1490,7 +1481,7 @@ const deriveNextExpectedAction = (intent, operationalState = {}) => {
|
|
|
1490
1481
|
if (intent === 'profile_update')
|
|
1491
1482
|
return 'save stable profile facts and continue the conversation';
|
|
1492
1483
|
if (intent === 'conversation_recall')
|
|
1493
|
-
return 'answer directly using
|
|
1484
|
+
return 'answer directly using conversation_history_chronological/all_user_messages_chronological; do not call tools for recall-only questions';
|
|
1494
1485
|
if (intent === 'operational_status_question')
|
|
1495
1486
|
return 'answer status questions from tool_state, tool_history and action_ledger; do not call tools unless the agent prompt requires it';
|
|
1496
1487
|
return 'answer using retrieved context and avoid unnecessary tool calls';
|
|
@@ -2474,7 +2465,7 @@ class Mem0Memory {
|
|
|
2474
2465
|
values: [
|
|
2475
2466
|
{ displayName: 'Incluir Profile Facts', name: 'includeProfileFacts', type: 'boolean', default: true },
|
|
2476
2467
|
{ displayName: 'Incluir Mensagens Recentes', name: 'includeRecentMessages', type: 'boolean', default: true },
|
|
2477
|
-
{ displayName: 'Últimas N Mensagens', name: 'recentMessagesLastN', type: 'number', default:
|
|
2468
|
+
{ displayName: 'Últimas N Mensagens', name: 'recentMessagesLastN', type: 'number', default: 50 },
|
|
2478
2469
|
{ displayName: 'Incluir Highlights Recentes', name: 'includeRecentHighlights', type: 'boolean', default: true },
|
|
2479
2470
|
{ displayName: 'Máximo de Highlights', name: 'recentHighlightsMaxItems', type: 'number', default: 6 },
|
|
2480
2471
|
{ displayName: 'Incluir Grafo', name: 'includeRelations', type: 'boolean', default: true },
|
|
@@ -2629,7 +2620,7 @@ class Mem0Memory {
|
|
|
2629
2620
|
{ displayName: 'Incluir Entity Timeline', name: 'includeEntityTimeline', type: 'boolean', default: true, description: 'Injeta uma timeline compacta de entidades, fatos de perfil, relações do grafo e eventos importantes da sessão.' },
|
|
2630
2621
|
{ displayName: 'Incluir Compressão de Memória', name: 'includeMemoryCompression', type: 'boolean', default: true, description: 'Injeta resumos compactos de turno, sessão, entidades e workflow para reduzir ruído.' },
|
|
2631
2622
|
{ displayName: 'Incluir Mensagens Recentes', name: 'includeRecentMessages', type: 'boolean', default: true },
|
|
2632
|
-
{ displayName: 'Últimas N Mensagens', name: 'recentMessagesLastN', type: 'number', default:
|
|
2623
|
+
{ displayName: 'Últimas N Mensagens', name: 'recentMessagesLastN', type: 'number', default: 50 },
|
|
2633
2624
|
{ displayName: 'Incluir Highlights Recentes', name: 'includeRecentHighlights', type: 'boolean', default: true },
|
|
2634
2625
|
{ displayName: 'Máximo de Highlights', name: 'recentHighlightsMaxItems', type: 'number', default: 6 },
|
|
2635
2626
|
],
|
|
@@ -3352,7 +3343,7 @@ class Mem0Memory {
|
|
|
3352
3343
|
try {
|
|
3353
3344
|
const transcriptProbe = [
|
|
3354
3345
|
'recent conversation transcript',
|
|
3355
|
-
'
|
|
3346
|
+
'chronological user messages earliest message latest message message immediately before current request full conversation',
|
|
3356
3347
|
query,
|
|
3357
3348
|
].filter(Boolean).join('\n');
|
|
3358
3349
|
const transcriptBody = {
|
package/package.json
CHANGED
|
@@ -42,8 +42,40 @@ function requiredToolFromText(text) {
|
|
|
42
42
|
return /"required_tool":"([^"]+)"/.exec(text)?.[1] || null;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
function
|
|
46
|
-
|
|
45
|
+
function conversationFrameFromText(text) {
|
|
46
|
+
const match = /## Conversation frame\n([\s\S]*?)(?:\n\n## |\n## |$)/.exec(text);
|
|
47
|
+
if (!match) return null;
|
|
48
|
+
try {
|
|
49
|
+
return JSON.parse(match[1].trim());
|
|
50
|
+
} catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function previousUserMessageFromText(text, currentMessage) {
|
|
56
|
+
const frame = conversationFrameFromText(text);
|
|
57
|
+
const userMessages = Array.isArray(frame?.all_user_messages_chronological)
|
|
58
|
+
? frame.all_user_messages_chronological
|
|
59
|
+
: [];
|
|
60
|
+
const normalizedCurrent = normalizeText(currentMessage).trim();
|
|
61
|
+
for (let index = userMessages.length - 1; index >= 0; index -= 1) {
|
|
62
|
+
const message = userMessages[index];
|
|
63
|
+
if (normalizeText(message?.content).trim() === normalizedCurrent) {
|
|
64
|
+
return userMessages[index - 1]?.content || '';
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return userMessages.at(-2)?.content || '';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function previousUserMessageFromState(messages, currentMessage) {
|
|
71
|
+
const userMessages = (messages || []).filter((message) => /^(user|human)$/i.test(String(message.role || '')));
|
|
72
|
+
const normalizedCurrent = normalizeText(currentMessage).trim();
|
|
73
|
+
for (let index = userMessages.length - 1; index >= 0; index -= 1) {
|
|
74
|
+
if (normalizeText(userMessages[index]?.content).trim() === normalizedCurrent) {
|
|
75
|
+
return userMessages[index - 1]?.content || '';
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return userMessages.at(-2)?.content || '';
|
|
47
79
|
}
|
|
48
80
|
|
|
49
81
|
function normalizeText(value) {
|
|
@@ -105,7 +137,8 @@ function answerFor({ userMessage, toolCalls, state, contextText }) {
|
|
|
105
137
|
.join('\n');
|
|
106
138
|
}
|
|
107
139
|
if (/qual.*ultima mensagem antes/.test(normalized)) {
|
|
108
|
-
const previous = previousUserMessageFromText(contextText)
|
|
140
|
+
const previous = previousUserMessageFromText(contextText, userMessage)
|
|
141
|
+
|| previousUserMessageFromState(state.recentMessages, userMessage)
|
|
109
142
|
|| core.previousUserFallbackFromWorkingMemory(userMessage, state.workingMemory);
|
|
110
143
|
return previous ? `Sua última mensagem antes desta foi: "${previous}".` : 'Não encontrei mensagem anterior.';
|
|
111
144
|
}
|