n8n-nodes-tembory 1.0.2 → 1.0.3

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.
@@ -346,6 +346,7 @@ const safeParseToolPayload = (value) => {
346
346
  };
347
347
  const compactToolPayload = (value) => truncate(typeof value === 'string' ? value : safeStringify(value), 900);
348
348
  const maybeToolResult = (tool, includeResults = true) => includeResults === false ? undefined : compactToolPayload(safeParseToolPayload(tool === null || tool === void 0 ? void 0 : tool.result));
349
+ 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 || ''));
349
350
  const deriveOperationalState = (toolHistory = [], profileFacts = {}, recentMessages = [], includeResults = true) => {
350
351
  const tools = Array.isArray(toolHistory) ? toolHistory : [];
351
352
  const successfulTools = tools.filter((tool) => tool.ok !== false);
@@ -1029,8 +1030,12 @@ const inferToolGuard = ({ query, recentMessages, toolHistory, vectorMemories })
1029
1030
  const inferUserIntent = (query = '', recentMessages = []) => {
1030
1031
  const latestUser = [...(recentMessages || [])].reverse().find((msg) => /^(user|human)$/i.test(String(msg.role || '')));
1031
1032
  const text = `${query || ''}\n${latestUser?.content || ''}`.toLowerCase();
1033
+ if (/^(ok|sim|pode|pode sim|isso|isso mesmo|confirmo|confirmar)$/i.test(String(query || '').trim()))
1034
+ return 'affirm';
1032
1035
  if (/\b(confirm|confirma|confirmar|fechar|pode confirmar)\b/.test(text))
1033
1036
  return 'confirm';
1037
+ if (containsSelectedSlot(text))
1038
+ return 'select_slot';
1034
1039
  if (/\b(pre.?reserv|pré.?reserv|reservar|segurar|marcar)\b/.test(text))
1035
1040
  return 'pre_reserve';
1036
1041
  if (/\b(disponibilidade|hor[aá]rios?|agenda|quando pode|tem vaga)\b/.test(text))
@@ -1045,14 +1050,26 @@ const inferUserIntent = (query = '', recentMessages = []) => {
1045
1050
  };
1046
1051
  const deriveNextExpectedAction = (intent, operationalState = {}) => {
1047
1052
  const agenda = operationalState.agenda_state || {};
1053
+ if (intent === 'affirm') {
1054
+ if (agenda.has_pending_pre_reservation)
1055
+ return 'call agenda_confirmar_agendamento now; do not ask the same confirmation question again';
1056
+ if (agenda.has_availability)
1057
+ return 'call agenda_pre_reservar_horario now using the selected or latest discussed slot; do not ask again';
1058
+ return 'call agenda_consultar_disponibilidade before reserving';
1059
+ }
1048
1060
  if (intent === 'confirm') {
1049
1061
  if (agenda.has_pending_pre_reservation)
1050
- return 'call agenda_confirmar_agendamento using the latest pre-reservation context';
1062
+ return 'call agenda_confirmar_agendamento now using the latest pre-reservation context; do not ask again';
1051
1063
  return 'ask for or create a pre-reservation before confirming';
1052
1064
  }
1065
+ if (intent === 'select_slot') {
1066
+ if (agenda.has_availability)
1067
+ return 'call agenda_pre_reservar_horario now using the selected slot; do not ask for confirmation before pre-reserving';
1068
+ return 'call agenda_consultar_disponibilidade before pre-reserving';
1069
+ }
1053
1070
  if (intent === 'pre_reserve') {
1054
1071
  if (agenda.has_availability)
1055
- return 'call agenda_pre_reservar_horario using one of the known available slots';
1072
+ return 'call agenda_pre_reservar_horario now using one of the known available slots';
1056
1073
  return 'call agenda_consultar_disponibilidade before pre-reserving';
1057
1074
  }
1058
1075
  if (intent === 'check_availability')
@@ -1331,7 +1348,7 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
1331
1348
  sections.push({
1332
1349
  section: 'context_header',
1333
1350
  title: 'Tembory context',
1334
- value: 'Use this context as read-only memory. Prefer it over guessing. Do not mention internal section names to the user. If the user asks to continue, choose, reserve, confirm, update, cancel, or perform any downstream action that depends on a prior tool result, first verify the required prior result in tool_history, recent_messages, or vector memories. If the required prior result is absent, do not call the downstream tool; ask for the missing context or call the appropriate prerequisite tool.',
1351
+ value: 'Use this context as read-only memory. Prefer it over guessing. Do not mention internal section names to the user. Treat next_expected_action as an instruction, not as a suggestion. If it says to call a tool now, call that tool instead of asking the user the same question again. If the user asks to continue, chooses a slot, says ok/sim, reserve, confirm, update, cancel, or performs any downstream action that depends on a prior tool result, first verify the required prior result in tool_history, recent_messages, or vector memories. If the required prior result is absent, do not call the downstream tool; ask for the missing context or call the appropriate prerequisite tool.',
1335
1352
  });
1336
1353
  }
1337
1354
  if (includeSummary) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-tembory",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Tembory node for n8n AI Agents with profile, tools, timeline, graph and semantic memory",
5
5
  "license": "MIT",
6
6
  "homepage": "https://tembory.com",