n8n-nodes-tembory 1.0.1 → 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.
@@ -112,8 +112,12 @@ const memoryText = (memory) => {
112
112
  if (!memory)
113
113
  return '';
114
114
  if (typeof memory === 'string')
115
- return memory;
116
- return memory.memory || memory.text || memory.value || memory.content || memory.data || safeStringify(memory);
115
+ return parseRecentMessageMarker(memory)?.content || memory;
116
+ const meta = metadataOf(memory);
117
+ if (meta.kind === 'recent_message' && meta.content)
118
+ return String(meta.content);
119
+ const text = memory.memory || memory.text || memory.value || memory.content || memory.data || safeStringify(memory);
120
+ return parseRecentMessageMarker(text)?.content || text;
117
121
  };
118
122
  const normalizeResults = (value) => {
119
123
  if (!value)
@@ -342,6 +346,7 @@ const safeParseToolPayload = (value) => {
342
346
  };
343
347
  const compactToolPayload = (value) => truncate(typeof value === 'string' ? value : safeStringify(value), 900);
344
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 || ''));
345
350
  const deriveOperationalState = (toolHistory = [], profileFacts = {}, recentMessages = [], includeResults = true) => {
346
351
  const tools = Array.isArray(toolHistory) ? toolHistory : [];
347
352
  const successfulTools = tools.filter((tool) => tool.ok !== false);
@@ -1025,8 +1030,12 @@ const inferToolGuard = ({ query, recentMessages, toolHistory, vectorMemories })
1025
1030
  const inferUserIntent = (query = '', recentMessages = []) => {
1026
1031
  const latestUser = [...(recentMessages || [])].reverse().find((msg) => /^(user|human)$/i.test(String(msg.role || '')));
1027
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';
1028
1035
  if (/\b(confirm|confirma|confirmar|fechar|pode confirmar)\b/.test(text))
1029
1036
  return 'confirm';
1037
+ if (containsSelectedSlot(text))
1038
+ return 'select_slot';
1030
1039
  if (/\b(pre.?reserv|pré.?reserv|reservar|segurar|marcar)\b/.test(text))
1031
1040
  return 'pre_reserve';
1032
1041
  if (/\b(disponibilidade|hor[aá]rios?|agenda|quando pode|tem vaga)\b/.test(text))
@@ -1041,14 +1050,26 @@ const inferUserIntent = (query = '', recentMessages = []) => {
1041
1050
  };
1042
1051
  const deriveNextExpectedAction = (intent, operationalState = {}) => {
1043
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
+ }
1044
1060
  if (intent === 'confirm') {
1045
1061
  if (agenda.has_pending_pre_reservation)
1046
- 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';
1047
1063
  return 'ask for or create a pre-reservation before confirming';
1048
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
+ }
1049
1070
  if (intent === 'pre_reserve') {
1050
1071
  if (agenda.has_availability)
1051
- 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';
1052
1073
  return 'call agenda_consultar_disponibilidade before pre-reserving';
1053
1074
  }
1054
1075
  if (intent === 'check_availability')
@@ -1327,7 +1348,7 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
1327
1348
  sections.push({
1328
1349
  section: 'context_header',
1329
1350
  title: 'Tembory context',
1330
- 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.',
1331
1352
  });
1332
1353
  }
1333
1354
  if (includeSummary) {
@@ -2168,38 +2189,31 @@ class Mem0Memory {
2168
2189
  }
2169
2190
  let persistedRecentMessages = [];
2170
2191
  let persistedToolHistory = [];
2171
- if (adv.includeRecentMessages !== false) {
2192
+ let persistedMemoryItems = [];
2193
+ if (adv.includeRecentMessages !== false || adv.includeToolHistory !== false) {
2172
2194
  try {
2173
2195
  const qs = { user_id: key };
2174
2196
  if (adv.agentId)
2175
2197
  qs.agent_id = String(adv.agentId);
2176
2198
  if (adv.runId)
2177
2199
  qs.run_id = String(adv.runId);
2178
- const recentRes = await GenericFunctions_1.mem0ApiRequest.call(this, 'GET', '/v1/memories/', {}, qs);
2179
- persistedRecentMessages = normalizeResults(recentRes)
2180
- .map(recentMessageFromMemory)
2181
- .filter(Boolean)
2182
- .sort((a, b) => new Date(a.at || 0).getTime() - new Date(b.at || 0).getTime());
2200
+ const persistedRes = await GenericFunctions_1.mem0ApiRequest.call(this, 'GET', '/v1/memories/', {}, qs);
2201
+ persistedMemoryItems = normalizeResults(persistedRes);
2183
2202
  }
2184
2203
  catch (error) {
2185
- connectedAi.errors.push(`recentMessages.load: ${error.message || String(error)}`);
2204
+ connectedAi.errors.push(`persistedContext.load: ${error.message || String(error)}`);
2186
2205
  }
2187
2206
  }
2207
+ if (adv.includeRecentMessages !== false) {
2208
+ persistedRecentMessages = persistedMemoryItems
2209
+ .map(recentMessageFromMemory)
2210
+ .filter(Boolean)
2211
+ .sort((a, b) => new Date(a.at || 0).getTime() - new Date(b.at || 0).getTime());
2212
+ }
2188
2213
  if (adv.includeToolHistory !== false) {
2189
- try {
2190
- const qs = { user_id: key };
2191
- if (adv.agentId)
2192
- qs.agent_id = String(adv.agentId);
2193
- if (adv.runId)
2194
- qs.run_id = String(adv.runId);
2195
- const toolRes = await GenericFunctions_1.mem0ApiRequest.call(this, 'GET', '/v1/memories/', {}, qs);
2196
- persistedToolHistory = normalizeResults(toolRes)
2197
- .flatMap(toolHistoryItemsFromMemory)
2198
- .sort((a, b) => new Date(a.at || 0).getTime() - new Date(b.at || 0).getTime());
2199
- }
2200
- catch (error) {
2201
- connectedAi.errors.push(`toolHistory.load: ${error.message || String(error)}`);
2202
- }
2214
+ persistedToolHistory = persistedMemoryItems
2215
+ .flatMap(toolHistoryItemsFromMemory)
2216
+ .sort((a, b) => new Date(a.at || 0).getTime() - new Date(b.at || 0).getTime());
2203
2217
  }
2204
2218
  const allRecentMessages = dedupeRecentMessages((store.recentMessages[key] || []).concat(persistedRecentMessages));
2205
2219
  const recentMessages = adv.includeRecentMessages === false ? [] : pruneByLimit(allRecentMessages, adv.recentMessagesLastN || 8);
@@ -2330,7 +2344,7 @@ class Mem0Memory {
2330
2344
  superseded_by: enriched.superseded_by,
2331
2345
  id: m.id || m.uuid || m.memory_id,
2332
2346
  created_at: m.created_at || m.createdAt,
2333
- raw: m,
2347
+ raw: adv.includeDiagnostics ? m : undefined,
2334
2348
  };
2335
2349
  });
2336
2350
  const summary = vectorMemories.slice(0, Number(adv.summaryMaxFacts || 4)).map(memoryText).filter(Boolean);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-tembory",
3
- "version": "1.0.1",
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",