n8n-nodes-tembory 1.0.33 → 1.0.35

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.
@@ -577,6 +577,7 @@ const deriveEntityTimeline = (profileFacts = {}, graph = [], recentMessages = []
577
577
  return pruneByLimit(deduped.sort((a, b) => String(a.at || '').localeCompare(String(b.at || ''))), maxItems || 24);
578
578
  };
579
579
  const RECENT_MESSAGE_MARKER = '__tembory_recent_message_v1__';
580
+ const CONVERSATION_LEDGER_MARKER = '__tembory_conversation_ledger_v1__';
580
581
  const TOOL_HISTORY_MARKER = '__tembory_tool_history_v1__';
581
582
  const TOOL_LEDGER_MARKER = '__tembory_tool_ledger_v1__';
582
583
  const encodeRecentMessage = (recent, threadId) => `${RECENT_MESSAGE_MARKER}${safeStringify({
@@ -585,6 +586,22 @@ const encodeRecentMessage = (recent, threadId) => `${RECENT_MESSAGE_MARKER}${saf
585
586
  at: recent.at || nowIso(),
586
587
  thread_id: threadId,
587
588
  })}`;
589
+ const encodeConversationLedger = (messages = [], threadId) => {
590
+ const chronological = sortConversationChronological(messages || []);
591
+ const userMessages = chronological.filter((msg) => /^(user|human)$/i.test(String(msg.role || '')));
592
+ const firstUser = userMessages[0];
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 || ''}. `;
595
+ return `${readable}${CONVERSATION_LEDGER_MARKER}${safeStringify({
596
+ thread_id: threadId,
597
+ generated_at: nowIso(),
598
+ messages: chronological.map((msg) => ({
599
+ role: msg.role || 'user',
600
+ content: msg.content || '',
601
+ at: msg.at || nowIso(),
602
+ })),
603
+ })}`;
604
+ };
588
605
  const encodeToolCall = (tool, threadId) => `${TOOL_HISTORY_MARKER}${safeStringify({
589
606
  id: tool.id || tool.callId || '',
590
607
  turn_id: tool.turnId || '',
@@ -597,10 +614,14 @@ const encodeToolCall = (tool, threadId) => `${TOOL_HISTORY_MARKER}${safeStringif
597
614
  source: tool.source || 'n8n',
598
615
  thread_id: threadId,
599
616
  })}`;
600
- const encodeToolLedger = (tools = [], threadId) => `${TOOL_LEDGER_MARKER}${safeStringify({
601
- thread_id: threadId,
602
- generated_at: nowIso(),
603
- tools: sortToolHistory(tools || []).map((tool, index) => ({
617
+ const encodeToolLedger = (tools = [], threadId) => {
618
+ const orderedTools = sortToolHistory(tools || []);
619
+ const names = orderedTools.map((tool) => tool.name || tool.tool || tool.toolName || 'tool').filter(Boolean);
620
+ const readable = `Tool history ledger. Tools called in this thread: ${names.join(', ')}. Use this ledger to answer questions about called tools, tool inputs, tool outputs, tool status and tool order. `;
621
+ return `${readable}${TOOL_LEDGER_MARKER}${safeStringify({
622
+ thread_id: threadId,
623
+ generated_at: nowIso(),
624
+ tools: orderedTools.map((tool, index) => ({
604
625
  id: tool.id || tool.callId || tool.call_id || '',
605
626
  turn_id: tool.turnId || tool.turn_id || '',
606
627
  sequence: tool.sequence || index + 1,
@@ -611,7 +632,8 @@ const encodeToolLedger = (tools = [], threadId) => `${TOOL_LEDGER_MARKER}${safeS
611
632
  at: tool.at || nowIso(),
612
633
  source: tool.source || 'n8n',
613
634
  })),
614
- })}`;
635
+ })}`;
636
+ };
615
637
  const parseRecentMessageMarker = (text) => {
616
638
  if (!text || typeof text !== 'string' || !text.startsWith(RECENT_MESSAGE_MARKER))
617
639
  return null;
@@ -653,10 +675,13 @@ const parseToolHistoryMarker = (text) => {
653
675
  }
654
676
  };
655
677
  const parseToolLedgerMarker = (text) => {
656
- if (!text || typeof text !== 'string' || !text.startsWith(TOOL_LEDGER_MARKER))
678
+ if (!text || typeof text !== 'string')
679
+ return [];
680
+ const markerIndex = text.indexOf(TOOL_LEDGER_MARKER);
681
+ if (markerIndex < 0)
657
682
  return [];
658
683
  try {
659
- const parsed = JSON.parse(text.slice(TOOL_LEDGER_MARKER.length));
684
+ const parsed = JSON.parse(text.slice(markerIndex + TOOL_LEDGER_MARKER.length));
660
685
  const tools = Array.isArray(parsed?.tools) ? parsed.tools : [];
661
686
  return tools
662
687
  .filter((tool) => tool && tool.name)
@@ -676,6 +701,27 @@ const parseToolLedgerMarker = (text) => {
676
701
  return [];
677
702
  }
678
703
  };
704
+ const parseConversationLedgerMarker = (text) => {
705
+ if (!text || typeof text !== 'string')
706
+ return [];
707
+ const markerIndex = text.indexOf(CONVERSATION_LEDGER_MARKER);
708
+ if (markerIndex < 0)
709
+ return [];
710
+ try {
711
+ const parsed = JSON.parse(text.slice(markerIndex + CONVERSATION_LEDGER_MARKER.length));
712
+ const messages = Array.isArray(parsed?.messages) ? parsed.messages : [];
713
+ return messages
714
+ .filter((msg) => msg && msg.content)
715
+ .map((msg) => ({
716
+ role: msg.role || 'user',
717
+ content: truncate(msg.content, 2000),
718
+ at: msg.at || parsed.generated_at || nowIso(),
719
+ }));
720
+ }
721
+ catch {
722
+ return [];
723
+ }
724
+ };
679
725
  const recentMessageFromMemory = (item) => {
680
726
  const meta = metadataOf(item);
681
727
  const content = meta.content || item.memory || item.text || item.value || item.content || item.data;
@@ -692,6 +738,15 @@ const recentMessageFromMemory = (item) => {
692
738
  at: meta.at || item.created_at || item.createdAt || nowIso(),
693
739
  };
694
740
  };
741
+ const recentMessagesFromMemory = (item) => {
742
+ const meta = metadataOf(item);
743
+ const content = meta.content || item.memory || item.text || item.value || item.content || item.data;
744
+ const ledger = parseConversationLedgerMarker(content);
745
+ if (ledger.length)
746
+ return ledger;
747
+ const single = recentMessageFromMemory(item);
748
+ return single ? [single] : [];
749
+ };
695
750
  const toolHistoryFromMemory = (item) => {
696
751
  const meta = metadataOf(item);
697
752
  const content = meta.content || item.memory || item.text || item.value || item.content || item.data;
@@ -2831,6 +2886,13 @@ class Mem0Memory {
2831
2886
  source: 'n8n_connected_embedding',
2832
2887
  }, ids));
2833
2888
  }
2889
+ clientMemories.push(await createClientVectorMemory(connectedEmbedding, encodeConversationLedger(recentForTurn, threadId), {
2890
+ kind: 'conversation_ledger',
2891
+ thread_id: threadId,
2892
+ project: project || undefined,
2893
+ source: 'n8n_connected_embedding',
2894
+ generated_at: nowIso(),
2895
+ }, ids));
2834
2896
  }
2835
2897
  if (adv.persistToolFactsToMem0 && toolCalls.length) {
2836
2898
  const facts = toolCalls.map((tool) => `Tool ${tool.name} input=${tool.input}${tool.result ? ` result=${tool.result}` : ''}`).join('\n');
@@ -2886,6 +2948,23 @@ class Mem0Memory {
2886
2948
  user_id: body.user_id,
2887
2949
  });
2888
2950
  }
2951
+ await safePersistLegacyMemory(this, {
2952
+ messages: [{ role: 'system', content: encodeConversationLedger(recentForTurn, threadId) }],
2953
+ infer: false,
2954
+ user_id: body.user_id,
2955
+ agent_id: body.agent_id,
2956
+ run_id: body.run_id,
2957
+ metadata: {
2958
+ kind: 'conversation_ledger',
2959
+ thread_id: threadId,
2960
+ project: project || undefined,
2961
+ source: 'tembory_transcript',
2962
+ generated_at: nowIso(),
2963
+ },
2964
+ }, {
2965
+ kind: 'conversation_ledger',
2966
+ user_id: body.user_id,
2967
+ });
2889
2968
  }
2890
2969
  if (adv.includeToolHistory !== false && toolCalls.length) {
2891
2970
  for (const tool of toolCalls) {
@@ -2954,6 +3033,20 @@ class Mem0Memory {
2954
3033
  },
2955
3034
  });
2956
3035
  }
3036
+ await GenericFunctions_1.mem0ApiRequest.call(this, 'POST', '/v1/memories/', {
3037
+ messages: [{ role: 'system', content: encodeConversationLedger(recentForTurn, threadId) }],
3038
+ infer: false,
3039
+ user_id: body.user_id,
3040
+ agent_id: body.agent_id,
3041
+ run_id: body.run_id,
3042
+ metadata: {
3043
+ kind: 'conversation_ledger',
3044
+ thread_id: threadId,
3045
+ project: project || undefined,
3046
+ source: 'tembory_transcript',
3047
+ generated_at: nowIso(),
3048
+ },
3049
+ });
2957
3050
  }
2958
3051
  if (adv.includeToolHistory !== false && !adv.persistToolFactsToMem0 && toolCalls.length) {
2959
3052
  for (const tool of toolCalls) {
@@ -3309,13 +3402,11 @@ class Mem0Memory {
3309
3402
  }
3310
3403
  if (adv.includeRecentMessages !== false) {
3311
3404
  persistedRecentMessages = persistedMemoryItems
3312
- .map(recentMessageFromMemory)
3313
- .filter(Boolean)
3405
+ .flatMap(recentMessagesFromMemory)
3314
3406
  .sort((a, b) => new Date(a.at || 0).getTime() - new Date(b.at || 0).getTime());
3315
3407
  }
3316
3408
  const vectorRecentMessages = adv.includeRecentMessages === false ? [] : vectorMemories
3317
- .map(recentMessageFromMemory)
3318
- .filter(Boolean)
3409
+ .flatMap(recentMessagesFromMemory)
3319
3410
  .sort((a, b) => new Date(a.at || 0).getTime() - new Date(b.at || 0).getTime());
3320
3411
  if (adv.includeToolHistory !== false) {
3321
3412
  persistedToolHistory = persistedMemoryItems
@@ -3691,7 +3782,9 @@ exports.__private = {
3691
3782
  toolHistoryFromMemory,
3692
3783
  cleanAssistantTranscriptText,
3693
3784
  buildActionDirective,
3785
+ buildConversationFrame,
3694
3786
  recentMessageFromMemory,
3787
+ recentMessagesFromMemory,
3695
3788
  previousUserFallbackFromWorkingMemory,
3696
3789
  firstUserMessageFromConversation,
3697
3790
  sortConversationChronological,
@@ -3702,9 +3795,11 @@ exports.__private = {
3702
3795
  parseToolHistoryMarker,
3703
3796
  parseToolLedgerMarker,
3704
3797
  parseRecentMessageMarker,
3798
+ parseConversationLedgerMarker,
3705
3799
  encodeToolCall,
3706
3800
  encodeToolLedger,
3707
3801
  encodeRecentMessage,
3802
+ encodeConversationLedger,
3708
3803
  userKeyFrom,
3709
3804
  applyOperationalPreset,
3710
3805
  flattenAdvancedGroups,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-tembory",
3
- "version": "1.0.33",
3
+ "version": "1.0.35",
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",