n8n-nodes-tembory 1.0.34 → 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 || '',
@@ -684,6 +701,27 @@ const parseToolLedgerMarker = (text) => {
684
701
  return [];
685
702
  }
686
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
+ };
687
725
  const recentMessageFromMemory = (item) => {
688
726
  const meta = metadataOf(item);
689
727
  const content = meta.content || item.memory || item.text || item.value || item.content || item.data;
@@ -700,6 +738,15 @@ const recentMessageFromMemory = (item) => {
700
738
  at: meta.at || item.created_at || item.createdAt || nowIso(),
701
739
  };
702
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
+ };
703
750
  const toolHistoryFromMemory = (item) => {
704
751
  const meta = metadataOf(item);
705
752
  const content = meta.content || item.memory || item.text || item.value || item.content || item.data;
@@ -2839,6 +2886,13 @@ class Mem0Memory {
2839
2886
  source: 'n8n_connected_embedding',
2840
2887
  }, ids));
2841
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));
2842
2896
  }
2843
2897
  if (adv.persistToolFactsToMem0 && toolCalls.length) {
2844
2898
  const facts = toolCalls.map((tool) => `Tool ${tool.name} input=${tool.input}${tool.result ? ` result=${tool.result}` : ''}`).join('\n');
@@ -2894,6 +2948,23 @@ class Mem0Memory {
2894
2948
  user_id: body.user_id,
2895
2949
  });
2896
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
+ });
2897
2968
  }
2898
2969
  if (adv.includeToolHistory !== false && toolCalls.length) {
2899
2970
  for (const tool of toolCalls) {
@@ -2962,6 +3033,20 @@ class Mem0Memory {
2962
3033
  },
2963
3034
  });
2964
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
+ });
2965
3050
  }
2966
3051
  if (adv.includeToolHistory !== false && !adv.persistToolFactsToMem0 && toolCalls.length) {
2967
3052
  for (const tool of toolCalls) {
@@ -3317,13 +3402,11 @@ class Mem0Memory {
3317
3402
  }
3318
3403
  if (adv.includeRecentMessages !== false) {
3319
3404
  persistedRecentMessages = persistedMemoryItems
3320
- .map(recentMessageFromMemory)
3321
- .filter(Boolean)
3405
+ .flatMap(recentMessagesFromMemory)
3322
3406
  .sort((a, b) => new Date(a.at || 0).getTime() - new Date(b.at || 0).getTime());
3323
3407
  }
3324
3408
  const vectorRecentMessages = adv.includeRecentMessages === false ? [] : vectorMemories
3325
- .map(recentMessageFromMemory)
3326
- .filter(Boolean)
3409
+ .flatMap(recentMessagesFromMemory)
3327
3410
  .sort((a, b) => new Date(a.at || 0).getTime() - new Date(b.at || 0).getTime());
3328
3411
  if (adv.includeToolHistory !== false) {
3329
3412
  persistedToolHistory = persistedMemoryItems
@@ -3699,7 +3782,9 @@ exports.__private = {
3699
3782
  toolHistoryFromMemory,
3700
3783
  cleanAssistantTranscriptText,
3701
3784
  buildActionDirective,
3785
+ buildConversationFrame,
3702
3786
  recentMessageFromMemory,
3787
+ recentMessagesFromMemory,
3703
3788
  previousUserFallbackFromWorkingMemory,
3704
3789
  firstUserMessageFromConversation,
3705
3790
  sortConversationChronological,
@@ -3710,9 +3795,11 @@ exports.__private = {
3710
3795
  parseToolHistoryMarker,
3711
3796
  parseToolLedgerMarker,
3712
3797
  parseRecentMessageMarker,
3798
+ parseConversationLedgerMarker,
3713
3799
  encodeToolCall,
3714
3800
  encodeToolLedger,
3715
3801
  encodeRecentMessage,
3802
+ encodeConversationLedger,
3716
3803
  userKeyFrom,
3717
3804
  applyOperationalPreset,
3718
3805
  flattenAdvancedGroups,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-tembory",
3
- "version": "1.0.34",
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",