n8n-nodes-tembory 1.0.20 → 1.0.22

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 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.20`.
5
+ Versao atual: `1.0.22`.
6
+
7
+ ## 1.0.22
8
+
9
+ - Corrige persistencia do transcript quando ha embedding conectado: mensagens recentes tambem sao gravadas como markers estruturados em `/v1/memories/`.
10
+ - Persiste tool history estruturado por padrao quando `includeToolHistory` esta ativo, mesmo sem `persistToolFactsToMem0`.
11
+ - Resolve falha real em n8n onde cada execucao carregava apenas a mensagem atual no `Conversation frame`.
12
+
13
+ ## 1.0.21
14
+
15
+ - O contexto principal passa a anexar o input atual do agente ao transcript antes de renderizar memoria.
16
+ - `Conversation frame` agora inclui `recent_messages_chronological`, com janela curta usuario/assistente em ordem.
17
+ - Mesmo antes do `saveContext`, o agente recebe a mensagem atual e a mensagem anterior do cliente no contexto estrutural.
6
18
 
7
19
  ## 1.0.20
8
20
 
@@ -1090,6 +1090,16 @@ const dedupeRecentMessages = (items) => {
1090
1090
  }
1091
1091
  return out;
1092
1092
  };
1093
+ const appendCurrentUserMessage = (items = [], query = '') => {
1094
+ const content = String(query || '').trim();
1095
+ if (!content)
1096
+ return items || [];
1097
+ const normalized = normalizeIntentText(content).trim();
1098
+ const lastUser = [...(items || [])].reverse().find((msg) => /^(user|human)$/i.test(String(msg.role || '')));
1099
+ if (lastUser && normalizeIntentText(lastUser.content).trim() === normalized)
1100
+ return items || [];
1101
+ return (items || []).concat([{ role: 'user', content: truncate(content, 2000), at: nowIso(), source: 'current_input' }]);
1102
+ };
1093
1103
  const dedupeToolHistory = (items) => {
1094
1104
  const seen = new Set();
1095
1105
  const out = [];
@@ -1172,9 +1182,15 @@ const buildConversationFrame = ({ query = '', recentMessages = [], workingMemory
1172
1182
  const users = recentUserMessages(recentMessages);
1173
1183
  const currentUser = users.find((msg) => normalizeIntentText(msg.content).trim() === normalizedQuery) || (query ? { role: 'user', content: query, at: nowIso() } : null);
1174
1184
  const previousUser = previousUserMessageForQuery(query, recentMessages);
1185
+ const chronological = pruneByLimit(recentMessages || [], 10).map((msg) => ({
1186
+ role: msg.role,
1187
+ content: truncate(msg.content, 500),
1188
+ at: msg.at,
1189
+ }));
1175
1190
  return cleanContextValue({
1176
1191
  current_user_message: currentUser ? truncate(currentUser.content, 500) : truncate(query, 500),
1177
1192
  previous_user_message: previousUser ? truncate(previousUser.content, 500) : (workingMemory === null || workingMemory === void 0 ? void 0 : workingMemory.last_user_message) || null,
1193
+ recent_messages_chronological: chronological,
1178
1194
  recent_user_messages: users
1179
1195
  .filter((msg) => normalizeIntentText(msg.content).trim() !== normalizedQuery)
1180
1196
  .slice(0, 5)
@@ -2722,6 +2738,51 @@ class Mem0Memory {
2722
2738
  }
2723
2739
  }
2724
2740
  await saveClientVectorMemories(this, clientMemories, ids);
2741
+ if (adv.includeRecentMessages !== false && recentForMem0.length) {
2742
+ for (const recent of recentForMem0) {
2743
+ await GenericFunctions_1.mem0ApiRequest.call(this, 'POST', '/v1/memories/', {
2744
+ messages: [{ role: 'system', content: encodeRecentMessage(recent, threadId) }],
2745
+ infer: false,
2746
+ user_id: body.user_id,
2747
+ agent_id: body.agent_id,
2748
+ run_id: body.run_id,
2749
+ metadata: {
2750
+ kind: 'recent_message',
2751
+ role: recent.role,
2752
+ content: recent.content,
2753
+ at: recent.at,
2754
+ thread_id: threadId,
2755
+ project: project || undefined,
2756
+ source: 'tembory_transcript',
2757
+ },
2758
+ });
2759
+ }
2760
+ }
2761
+ if (adv.includeToolHistory !== false && toolCalls.length) {
2762
+ for (const tool of toolCalls) {
2763
+ await GenericFunctions_1.mem0ApiRequest.call(this, 'POST', '/v1/memories/', {
2764
+ messages: [{ role: 'system', content: encodeToolCall(tool, threadId) }],
2765
+ infer: false,
2766
+ user_id: body.user_id,
2767
+ agent_id: body.agent_id,
2768
+ run_id: body.run_id,
2769
+ metadata: {
2770
+ kind: 'tool_history',
2771
+ id: tool.id,
2772
+ sequence: tool.sequence,
2773
+ turn_id: tool.turnId,
2774
+ name: tool.name,
2775
+ input: tool.input,
2776
+ ok: tool.ok,
2777
+ result: tool.result,
2778
+ at: tool.at,
2779
+ source: tool.source || 'tembory_transcript',
2780
+ thread_id: threadId,
2781
+ project: project || undefined,
2782
+ },
2783
+ });
2784
+ }
2785
+ }
2725
2786
  return;
2726
2787
  }
2727
2788
  await GenericFunctions_1.mem0ApiRequest.call(this, 'POST', '/v1/memories/', body);
@@ -2744,6 +2805,31 @@ class Mem0Memory {
2744
2805
  });
2745
2806
  }
2746
2807
  }
2808
+ if (adv.includeToolHistory !== false && !adv.persistToolFactsToMem0 && toolCalls.length) {
2809
+ for (const tool of toolCalls) {
2810
+ await GenericFunctions_1.mem0ApiRequest.call(this, 'POST', '/v1/memories/', {
2811
+ messages: [{ role: 'system', content: encodeToolCall(tool, threadId) }],
2812
+ infer: false,
2813
+ user_id: body.user_id,
2814
+ agent_id: body.agent_id,
2815
+ run_id: body.run_id,
2816
+ metadata: {
2817
+ kind: 'tool_history',
2818
+ id: tool.id,
2819
+ sequence: tool.sequence,
2820
+ turn_id: tool.turnId,
2821
+ name: tool.name,
2822
+ input: tool.input,
2823
+ ok: tool.ok,
2824
+ result: tool.result,
2825
+ at: tool.at,
2826
+ source: tool.source || 'tembory_transcript',
2827
+ thread_id: threadId,
2828
+ project: project || undefined,
2829
+ },
2830
+ });
2831
+ }
2832
+ }
2747
2833
  if (adv.persistToolFactsToMem0 && toolCalls.length) {
2748
2834
  const facts = toolCalls.map((tool) => `Tool ${tool.name} input=${tool.input}${tool.result ? ` result=${tool.result}` : ''}`).join('\n');
2749
2835
  await GenericFunctions_1.mem0ApiRequest.call(this, 'POST', '/v1/memories/', {
@@ -3033,8 +3119,9 @@ class Mem0Memory {
3033
3119
  .flatMap(toolHistoryItemsFromMemory)
3034
3120
  .sort((a, b) => new Date(a.at || 0).getTime() - new Date(b.at || 0).getTime());
3035
3121
  }
3036
- const allRecentMessages = dedupeRecentMessages((store.recentMessages[key] || []).concat(persistedRecentMessages));
3037
- const recentMessages = adv.includeRecentMessages === false ? [] : pruneByLimit(allRecentMessages, adv.recentMessagesLastN || 8);
3122
+ const storedRecentMessages = adv.includeRecentMessages === false ? [] : (store.recentMessages[key] || []).concat(persistedRecentMessages);
3123
+ const allRecentMessages = dedupeRecentMessages(appendCurrentUserMessage(storedRecentMessages, query));
3124
+ const recentMessages = pruneByLimit(allRecentMessages, Math.max(Number(adv.recentMessagesLastN || 8), 8));
3038
3125
  const toolHistoryFromRecentMessages = [];
3039
3126
  if (adv.includeToolHistory !== false) {
3040
3127
  for (const msg of recentMessages)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-tembory",
3
- "version": "1.0.20",
3
+ "version": "1.0.22",
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",