n8n-nodes-tembory 1.0.28 → 1.0.30
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/README.md +13 -1
- package/dist/nodes/Mem0/Mem0Memory.node.js +69 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
Node de memoria operacional da Tembory para agentes de IA no n8n.
|
|
4
4
|
|
|
5
|
-
Versao atual: `1.0.
|
|
5
|
+
Versao atual: `1.0.30`.
|
|
6
|
+
|
|
7
|
+
## 1.0.30
|
|
8
|
+
|
|
9
|
+
- Adiciona `Action directive` quando a memoria conclui que uma tool deve ser chamada no turno atual.
|
|
10
|
+
- Torna `next_expected_action` mais coercitivo para agenda: usa `MUST call ...` e proibe respostas como "se quiser/posso" no lugar da tool obrigatoria.
|
|
11
|
+
- Reduz o peso instrucional de `first_user_message`; o foco passa a ser mensagem atual, mensagem anterior e transcript cronologico recente.
|
|
12
|
+
|
|
13
|
+
## 1.0.29
|
|
14
|
+
|
|
15
|
+
- Considera disponibilidade recente no transcript como contexto operacional valido quando `tool_history` ainda nao foi recuperado no turno.
|
|
16
|
+
- Evita repetir `agenda_consultar_disponibilidade` apos o agente ja ter respondido vagas no historico recente.
|
|
17
|
+
- Direciona selecao de horario como "quero dia 13" para `agenda_pre_reservar_horario` quando ha vagas recentes, mesmo sem marker estruturado no contexto atual.
|
|
6
18
|
|
|
7
19
|
## 1.0.28
|
|
8
20
|
|
|
@@ -408,11 +408,32 @@ const safeParseToolPayload = (value) => {
|
|
|
408
408
|
const compactToolPayload = (value) => truncate(typeof value === 'string' ? value : safeStringify(value), 900);
|
|
409
409
|
const maybeToolResult = (tool, includeResults = true) => includeResults === false ? undefined : compactToolPayload(safeParseToolPayload(tool === null || tool === void 0 ? void 0 : tool.result));
|
|
410
410
|
const containsSelectedSlot = (text = '') => /\b(?:às|as|das|para)?\s*\d{1,2}(?::\d{2}|h\d{0,2})?\b/i.test(String(text || '')) || /\b\d{1,2}\/\d{1,2}(?:\/\d{2,4})?\b/.test(String(text || ''));
|
|
411
|
+
const availabilityFromRecentMessages = (recentMessages = []) => {
|
|
412
|
+
const messages = Array.isArray(recentMessages) ? recentMessages : [];
|
|
413
|
+
const candidates = [...messages].reverse().filter((message) => {
|
|
414
|
+
const role = String(message.role || '').toLowerCase();
|
|
415
|
+
const text = String(message.content || message.text || message.memory || '');
|
|
416
|
+
if (role && role !== 'assistant' && role !== 'ai' && role !== 'system')
|
|
417
|
+
return false;
|
|
418
|
+
return /\b(?:tem|tenho|há|ha)\s+vagas?\b|\bop[cç][oõ]es?\s+dispon[ií]veis\b|\bavailable_slots\b/i.test(text)
|
|
419
|
+
&& (/\b\d{1,2}\/\d{1,2}(?:\/\d{2,4})?\b/.test(text) || /\b\d{1,2}:\d{2}\b/.test(text));
|
|
420
|
+
});
|
|
421
|
+
const latest = candidates[0];
|
|
422
|
+
if (!latest)
|
|
423
|
+
return null;
|
|
424
|
+
return {
|
|
425
|
+
text: truncate(String(latest.content || latest.text || latest.memory || ''), 900),
|
|
426
|
+
at: latest.at || latest.created_at || latest.createdAt || nowIso(),
|
|
427
|
+
source: latest.source || 'recent_message',
|
|
428
|
+
};
|
|
429
|
+
};
|
|
411
430
|
const deriveOperationalState = (toolHistory = [], profileFacts = {}, recentMessages = [], includeResults = true) => {
|
|
412
431
|
const tools = Array.isArray(toolHistory) ? toolHistory : [];
|
|
413
432
|
const successfulTools = tools.filter((tool) => tool.ok !== false);
|
|
414
433
|
const byName = (name) => successfulTools.filter((tool) => tool.name === name);
|
|
415
434
|
const availability = byName('agenda_consultar_disponibilidade');
|
|
435
|
+
const recentAvailability = availability.length ? null : availabilityFromRecentMessages(recentMessages);
|
|
436
|
+
const hasAvailability = availability.length > 0 || Boolean(recentAvailability);
|
|
416
437
|
const reservations = byName('agenda_pre_reservar_horario');
|
|
417
438
|
const confirmations = byName('agenda_confirmar_agendamento');
|
|
418
439
|
const lastTool = tools[tools.length - 1] || null;
|
|
@@ -420,18 +441,18 @@ const deriveOperationalState = (toolHistory = [], profileFacts = {}, recentMessa
|
|
|
420
441
|
const lastConfirmation = confirmations[confirmations.length - 1] || null;
|
|
421
442
|
const hasPendingReservation = Boolean(lastReservation && (!lastConfirmation || String(lastReservation.at || '') > String(lastConfirmation.at || '')));
|
|
422
443
|
const blockedWithoutContext = [];
|
|
423
|
-
if (!
|
|
444
|
+
if (!hasAvailability)
|
|
424
445
|
blockedWithoutContext.push('agenda_pre_reservar_horario');
|
|
425
446
|
if (!reservations.length)
|
|
426
447
|
blockedWithoutContext.push('agenda_confirmar_agendamento');
|
|
427
448
|
const guidance = [];
|
|
428
|
-
if (!
|
|
449
|
+
if (!hasAvailability)
|
|
429
450
|
guidance.push('No availability result is known for this session; consult availability before reserving or confirming.');
|
|
430
451
|
else if (hasPendingReservation)
|
|
431
452
|
guidance.push('A pre-reservation exists after the latest confirmation; confirmation can use the latest pre-reservation context.');
|
|
432
453
|
else if (lastConfirmation)
|
|
433
454
|
guidance.push('The latest reservation appears confirmed; do not confirm again unless the user explicitly asks to repeat or change it.');
|
|
434
|
-
else if (
|
|
455
|
+
else if (hasAvailability)
|
|
435
456
|
guidance.push('Availability is known; if the user chooses one listed slot, reserve without repeating availability.');
|
|
436
457
|
return {
|
|
437
458
|
profile_complete: Boolean(profileFacts && profileFacts.name && profileFacts.company && profileFacts.email && profileFacts.phone),
|
|
@@ -445,11 +466,12 @@ const deriveOperationalState = (toolHistory = [], profileFacts = {}, recentMessa
|
|
|
445
466
|
agenda_confirmar_agendamento: confirmations.length,
|
|
446
467
|
},
|
|
447
468
|
agenda_state: {
|
|
448
|
-
has_availability:
|
|
469
|
+
has_availability: hasAvailability,
|
|
449
470
|
has_pre_reservation: reservations.length > 0,
|
|
450
471
|
has_confirmation: confirmations.length > 0,
|
|
451
472
|
has_pending_pre_reservation: hasPendingReservation,
|
|
452
|
-
latest_availability_result: availability.length ? maybeToolResult(availability[availability.length - 1], includeResults) : null,
|
|
473
|
+
latest_availability_result: availability.length ? maybeToolResult(availability[availability.length - 1], includeResults) : (recentAvailability && includeResults !== false ? recentAvailability.text : null),
|
|
474
|
+
latest_availability_source: availability.length ? 'tool_history' : (recentAvailability ? recentAvailability.source : null),
|
|
453
475
|
latest_pre_reservation_result: lastReservation ? maybeToolResult(lastReservation, includeResults) : null,
|
|
454
476
|
latest_confirmation_result: lastConfirmation ? maybeToolResult(lastConfirmation, includeResults) : null,
|
|
455
477
|
},
|
|
@@ -1284,7 +1306,7 @@ const buildConversationFrame = ({ query = '', recentMessages = [], workingMemory
|
|
|
1284
1306
|
.filter((msg) => normalizeIntentText(msg.content).trim() !== normalizedQuery)
|
|
1285
1307
|
.slice(0, 5)
|
|
1286
1308
|
.map((msg) => ({ role: msg.role, content: truncate(msg.content, 500), at: msg.at })),
|
|
1287
|
-
instruction: 'This is the authoritative short-term conversation frame. If the user asks about
|
|
1309
|
+
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 current_user_message/previous_user_message/conversation_history_chronological/all_user_messages_chronological before using vector memories, summaries, operational state, or tool history.',
|
|
1288
1310
|
});
|
|
1289
1311
|
if (!previousUserMessage)
|
|
1290
1312
|
frame.previous_user_message = null;
|
|
@@ -1324,13 +1346,33 @@ const buildCurrentTurnFocus = ({ query = '', recentMessages = [], operationalSta
|
|
|
1324
1346
|
has_availability: Boolean(agenda.has_availability),
|
|
1325
1347
|
} : undefined,
|
|
1326
1348
|
instruction: recall
|
|
1327
|
-
? 'Answer the user meta-question from
|
|
1349
|
+
? 'Answer the user meta-question from previous_user_message/recent_user_messages and the chronological transcript. Do not answer with agenda availability unless the user asks for availability.'
|
|
1328
1350
|
: 'Answer whether the appointment/reservation is already scheduled using agenda_status. Do not offer availability as the main answer unless there is no schedule/reservation state.',
|
|
1329
1351
|
});
|
|
1330
1352
|
if (!previousUserMessage)
|
|
1331
1353
|
focus.previous_user_message = null;
|
|
1332
1354
|
return focus;
|
|
1333
1355
|
};
|
|
1356
|
+
const buildActionDirective = ({ workingMemory = {}, operationalState = {} }) => {
|
|
1357
|
+
const next = String((workingMemory || {}).next_expected_action || '');
|
|
1358
|
+
const match = /\bagenda_(consultar_disponibilidade|pre_reservar_horario|confirmar_agendamento)\b/.exec(next);
|
|
1359
|
+
if (!match || !/\bcall\b|\bMUST\b/i.test(next))
|
|
1360
|
+
return null;
|
|
1361
|
+
const tool = match[0];
|
|
1362
|
+
const agenda = (operationalState || {}).agenda_state || {};
|
|
1363
|
+
return cleanContextValue({
|
|
1364
|
+
required_tool: tool,
|
|
1365
|
+
next_expected_action: next,
|
|
1366
|
+
agenda_state: {
|
|
1367
|
+
has_availability: Boolean(agenda.has_availability),
|
|
1368
|
+
latest_availability_source: agenda.latest_availability_source,
|
|
1369
|
+
has_pre_reservation: Boolean(agenda.has_pre_reservation),
|
|
1370
|
+
has_pending_pre_reservation: Boolean(agenda.has_pending_pre_reservation),
|
|
1371
|
+
has_confirmation: Boolean(agenda.has_confirmation),
|
|
1372
|
+
},
|
|
1373
|
+
instruction: `You MUST call ${tool} now. Do not answer with "posso", "se quiser", "já posso" or ask for the same confirmation instead of calling the required tool. Only skip this tool if it is explicitly blocked in Tool guard.`,
|
|
1374
|
+
});
|
|
1375
|
+
};
|
|
1334
1376
|
const inferToolGuard = ({ query, recentMessages, toolHistory, vectorMemories }) => {
|
|
1335
1377
|
const text = normalizeIntentText(query);
|
|
1336
1378
|
const names = new Set((toolHistory || []).map((tool) => String(tool.name || '')));
|
|
@@ -1386,24 +1428,26 @@ const deriveNextExpectedAction = (intent, operationalState = {}) => {
|
|
|
1386
1428
|
const agenda = operationalState.agenda_state || {};
|
|
1387
1429
|
if (intent === 'affirm') {
|
|
1388
1430
|
if (agenda.has_pending_pre_reservation)
|
|
1389
|
-
return 'call agenda_confirmar_agendamento now; do not ask the same confirmation question again';
|
|
1431
|
+
return 'MUST call agenda_confirmar_agendamento now; do not ask the same confirmation question again';
|
|
1390
1432
|
if (agenda.has_availability)
|
|
1391
|
-
return 'call agenda_pre_reservar_horario now using the selected or latest discussed slot; do not ask again';
|
|
1433
|
+
return 'MUST call agenda_pre_reservar_horario now using the selected or latest discussed slot; do not ask again';
|
|
1392
1434
|
return 'call agenda_consultar_disponibilidade before reserving';
|
|
1393
1435
|
}
|
|
1394
1436
|
if (intent === 'confirm') {
|
|
1395
1437
|
if (agenda.has_pending_pre_reservation)
|
|
1396
|
-
return 'call agenda_confirmar_agendamento now using the latest pre-reservation context; do not ask again';
|
|
1397
|
-
|
|
1438
|
+
return 'MUST call agenda_confirmar_agendamento now using the latest pre-reservation context; do not ask again';
|
|
1439
|
+
if (agenda.has_availability)
|
|
1440
|
+
return 'MUST call agenda_pre_reservar_horario first using the selected or latest discussed slot; do not ask for permission again';
|
|
1441
|
+
return 'do not call agenda_confirmar_agendamento; call agenda_consultar_disponibilidade first because no availability is known';
|
|
1398
1442
|
}
|
|
1399
1443
|
if (intent === 'select_slot') {
|
|
1400
1444
|
if (agenda.has_availability)
|
|
1401
|
-
return 'call agenda_pre_reservar_horario now using the selected slot; do not ask for confirmation before pre-reserving';
|
|
1445
|
+
return 'MUST call agenda_pre_reservar_horario now using the selected slot; do not ask for confirmation before pre-reserving';
|
|
1402
1446
|
return 'call agenda_consultar_disponibilidade before pre-reserving';
|
|
1403
1447
|
}
|
|
1404
1448
|
if (intent === 'pre_reserve') {
|
|
1405
1449
|
if (agenda.has_availability)
|
|
1406
|
-
return 'call agenda_pre_reservar_horario now using one of the known available slots';
|
|
1450
|
+
return 'MUST call agenda_pre_reservar_horario now using one of the known available slots';
|
|
1407
1451
|
return 'call agenda_consultar_disponibilidade before pre-reserving';
|
|
1408
1452
|
}
|
|
1409
1453
|
if (intent === 'check_availability')
|
|
@@ -1988,8 +2032,8 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
1988
2032
|
sections.push({
|
|
1989
2033
|
section: 'conversation_frame',
|
|
1990
2034
|
title: 'Conversation frame',
|
|
1991
|
-
|
|
1992
|
-
|
|
2035
|
+
value: buildConversationFrame({ query, recentMessages, workingMemory }),
|
|
2036
|
+
});
|
|
1993
2037
|
const currentTurnFocus = buildCurrentTurnFocus({ query, recentMessages, operationalState, workingMemory });
|
|
1994
2038
|
if (currentTurnFocus) {
|
|
1995
2039
|
sections.push({
|
|
@@ -1998,6 +2042,14 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
1998
2042
|
value: currentTurnFocus,
|
|
1999
2043
|
});
|
|
2000
2044
|
}
|
|
2045
|
+
const actionDirective = buildActionDirective({ workingMemory, operationalState });
|
|
2046
|
+
if (actionDirective) {
|
|
2047
|
+
sections.push({
|
|
2048
|
+
section: 'action_directive',
|
|
2049
|
+
title: 'Action directive',
|
|
2050
|
+
value: actionDirective,
|
|
2051
|
+
});
|
|
2052
|
+
}
|
|
2001
2053
|
if (compactForAgent) {
|
|
2002
2054
|
if (includeSummary) {
|
|
2003
2055
|
const summary = compactVectorMemoriesForAgent(vectorMemories, toolHistory, Number(adv.summaryMaxFacts || 3));
|
|
@@ -3638,6 +3690,8 @@ exports.__private = {
|
|
|
3638
3690
|
explicitToolHistoryItemsFromMemory,
|
|
3639
3691
|
toolHistoryFromMemory,
|
|
3640
3692
|
cleanAssistantTranscriptText,
|
|
3693
|
+
availabilityFromRecentMessages,
|
|
3694
|
+
buildActionDirective,
|
|
3641
3695
|
recentMessageFromMemory,
|
|
3642
3696
|
previousUserFallbackFromWorkingMemory,
|
|
3643
3697
|
firstUserMessageFromConversation,
|
package/package.json
CHANGED