n8n-nodes-tembory 1.0.44 → 1.0.46

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.
@@ -33,6 +33,10 @@ async function mem0ApiRequest(method, endpoint, body = {}, qs = {}) {
33
33
  function resolveGatewayOperation(method, endpoint) {
34
34
  const normalizedMethod = String(method || '').toUpperCase();
35
35
  const path = String(endpoint || '').toLowerCase();
36
+ if (path.includes('thread-state') && (normalizedMethod === 'GET' || path.includes('load')))
37
+ return 'thread-state.load';
38
+ if (path.includes('thread-state'))
39
+ return 'thread-state.save';
36
40
  if (path.includes('search') || normalizedMethod === 'GET')
37
41
  return 'memory.search';
38
42
  if (path.includes('delete'))
@@ -750,6 +750,23 @@ const parseConversationLedgerMarker = (text) => {
750
750
  return [];
751
751
  }
752
752
  };
753
+ const parseTurnArchive = (text) => {
754
+ if (!text || typeof text !== 'string')
755
+ return null;
756
+ const marker = '"marker":"tembory_turn_archive_v1"';
757
+ const markerIndex = text.indexOf(marker);
758
+ if (markerIndex < 0)
759
+ return null;
760
+ const jsonStart = text.lastIndexOf('{', markerIndex);
761
+ if (jsonStart < 0)
762
+ return null;
763
+ try {
764
+ return JSON.parse(text.slice(jsonStart));
765
+ }
766
+ catch {
767
+ return null;
768
+ }
769
+ };
753
770
  const recentMessageFromMemory = (item) => {
754
771
  const meta = metadataOf(item);
755
772
  const content = meta.content || item.memory || item.text || item.value || item.content || item.data;
@@ -769,6 +786,16 @@ const recentMessageFromMemory = (item) => {
769
786
  const recentMessagesFromMemory = (item) => {
770
787
  const meta = metadataOf(item);
771
788
  const content = meta.content || item.memory || item.text || item.value || item.content || item.data;
789
+ const archive = parseTurnArchive(content);
790
+ if (archive && Array.isArray(archive.conversation)) {
791
+ return archive.conversation
792
+ .filter((msg) => msg && msg.content)
793
+ .map((msg) => ({
794
+ role: msg.role || 'user',
795
+ content: truncate(msg.content, 2000),
796
+ at: msg.at || archive.generated_at || nowIso(),
797
+ }));
798
+ }
772
799
  const ledger = parseConversationLedgerMarker(content);
773
800
  if (ledger.length)
774
801
  return ledger;
@@ -833,6 +860,22 @@ const toolHistoryFromMemory = (item) => {
833
860
  const explicitToolHistoryItemsFromMemory = (item) => {
834
861
  const meta = metadataOf(item);
835
862
  const content = meta.content || item.memory || item.text || item.value || item.content || item.data;
863
+ const archive = parseTurnArchive(content);
864
+ if (archive && Array.isArray(archive.tools)) {
865
+ return archive.tools
866
+ .filter((tool) => tool && tool.name)
867
+ .map((tool, index) => ({
868
+ id: tool.id || tool.call_id || tool.callId || '',
869
+ turnId: tool.turn_id || tool.turnId || '',
870
+ sequence: tool.sequence || index + 1,
871
+ name: String(tool.name),
872
+ input: tool.input === undefined ? '' : String(tool.input),
873
+ ok: tool.ok !== false,
874
+ result: truncate(tool.output || tool.result || '', 1000),
875
+ at: tool.at || archive.generated_at || nowIso(),
876
+ source: tool.source || 'turn_archive',
877
+ }));
878
+ }
836
879
  const ledger = parseToolLedgerMarker(content);
837
880
  if (ledger.length)
838
881
  return ledger;
@@ -1142,6 +1185,51 @@ const userKeyFrom = (threadId, adv, project = '') => {
1142
1185
  const namespace = namespacePart(project || (adv === null || adv === void 0 ? void 0 : adv.project) || (adv === null || adv === void 0 ? void 0 : adv.projectId));
1143
1186
  return namespace ? `${namespace}::${base}` : base;
1144
1187
  };
1188
+ const loadThreadState = async (ctx, key, threadId, project) => {
1189
+ try {
1190
+ const res = await GenericFunctions_1.mem0ApiRequest.call(ctx, 'GET', '/v1/tembory/thread-state/load', {}, {
1191
+ user_id: key,
1192
+ thread_id: threadId,
1193
+ project: project || undefined,
1194
+ });
1195
+ return (res === null || res === void 0 ? void 0 : res.state) && typeof res.state === 'object' ? res.state : null;
1196
+ }
1197
+ catch {
1198
+ return null;
1199
+ }
1200
+ };
1201
+ const saveThreadState = async (ctx, key, threadId, project, state) => {
1202
+ try {
1203
+ await GenericFunctions_1.mem0ApiRequest.call(ctx, 'POST', '/v1/tembory/thread-state', {
1204
+ user_id: key,
1205
+ thread_id: threadId,
1206
+ project: project || undefined,
1207
+ state,
1208
+ });
1209
+ return true;
1210
+ }
1211
+ catch {
1212
+ return false;
1213
+ }
1214
+ };
1215
+ const mergeRemoteThreadState = (store, key, state) => {
1216
+ if (!state || typeof state !== 'object')
1217
+ return;
1218
+ if (Array.isArray(state.recentMessages))
1219
+ store.recentMessages[key] = dedupeRecentMessages((store.recentMessages[key] || []).concat(state.recentMessages));
1220
+ if (Array.isArray(state.toolHistory))
1221
+ store.toolHistory[key] = applyToolHistoryWindow((store.toolHistory[key] || []).concat(state.toolHistory), undefined, Math.max(state.toolHistory.length, 15));
1222
+ if (state.profileFacts && typeof state.profileFacts === 'object')
1223
+ store.profileFacts[key] = mergeProfileFacts(store.profileFacts[key], state.profileFacts);
1224
+ if (state.workingMemory && typeof state.workingMemory === 'object')
1225
+ store.workingMemory[key] = { ...(store.workingMemory[key] || {}), ...state.workingMemory };
1226
+ if (state.decisionState && typeof state.decisionState === 'object')
1227
+ store.decisionState[key] = { ...(store.decisionState[key] || {}), ...state.decisionState };
1228
+ if (state.memoryCompression && typeof state.memoryCompression === 'object')
1229
+ store.memoryCompression[key] = state.memoryCompression;
1230
+ if (typeof state.activeSummary === 'string' && state.activeSummary)
1231
+ store.activeSummary[key] = state.activeSummary;
1232
+ };
1145
1233
  const applyOperationalPreset = (advanced = {}) => {
1146
1234
  const preset = String(advanced.operationPreset || 'productionFast');
1147
1235
  const presets = {
@@ -1194,7 +1282,7 @@ const applyOperationalPreset = (advanced = {}) => {
1194
1282
  includeSummary: true,
1195
1283
  includeScores: true,
1196
1284
  includeDiagnostics: true,
1197
- includeRelations: true,
1285
+ includeRelations: false,
1198
1286
  includeToolHistory: true,
1199
1287
  includeToolResults: true,
1200
1288
  persistToolFactsToMem0: true,
@@ -1227,7 +1315,7 @@ const applyOperationalPreset = (advanced = {}) => {
1227
1315
  includeSummary: true,
1228
1316
  includeScores: false,
1229
1317
  includeDiagnostics: false,
1230
- includeRelations: true,
1318
+ includeRelations: false,
1231
1319
  includeToolHistory: true,
1232
1320
  includeToolResults: true,
1233
1321
  persistToolFactsToMem0: false,
@@ -1332,7 +1420,7 @@ const applyOperationalPreset = (advanced = {}) => {
1332
1420
  includeSummary: true,
1333
1421
  includeScores: true,
1334
1422
  includeDiagnostics: true,
1335
- includeRelations: true,
1423
+ includeRelations: false,
1336
1424
  includeToolHistory: true,
1337
1425
  includeToolResults: true,
1338
1426
  persistToolFactsToMem0: true,
@@ -2767,7 +2855,7 @@ class Mem0Memory {
2767
2855
  { displayName: 'Máximo de Fatos no Resumo', name: 'summaryMaxFacts', type: 'number', default: 4 },
2768
2856
  { displayName: 'Incluir Scores', name: 'includeScores', type: 'boolean', default: true },
2769
2857
  { displayName: 'Incluir Diagnóstico', name: 'includeDiagnostics', type: 'boolean', default: false },
2770
- { displayName: 'Incluir Grafo', name: 'includeRelations', type: 'boolean', default: true },
2858
+ { displayName: 'Incluir Grafo', name: 'includeRelations', type: 'boolean', default: false },
2771
2859
  { displayName: 'Máximo de Relações', name: 'maxRelations', type: 'number', default: 10 },
2772
2860
  { displayName: 'Incluir Tool History', name: 'includeToolHistory', type: 'boolean', default: true },
2773
2861
  { displayName: 'Incluir Resultado Das Tools', name: 'includeToolResults', type: 'boolean', default: true },
@@ -3036,6 +3124,22 @@ class Mem0Memory {
3036
3124
  body.run_id = String(adv.runId);
3037
3125
  if (adv.persistBackendMemories === false)
3038
3126
  return;
3127
+ await saveThreadState(this, key, threadId, project, {
3128
+ kind: 'tembory.thread_state.v1',
3129
+ threadId,
3130
+ project: project || undefined,
3131
+ updatedAt: nowIso(),
3132
+ recentMessages: recentForTurn,
3133
+ toolHistory: toolHistoryForTurn,
3134
+ profileFacts: store.profileFacts[key] || {},
3135
+ workingMemory: workingMemoryForTurn,
3136
+ decisionState: decisionStateForTurn,
3137
+ memoryCompression: compressionForTurn,
3138
+ operationalState: operationalStateForTurn,
3139
+ activeSummary: store.activeSummary[key] || '',
3140
+ });
3141
+ if (adv.useVectorMemory === false)
3142
+ return;
3039
3143
  const connectedEmbedding = await getConnectedEmbedding(this, itemIndex);
3040
3144
  if (connectedEmbedding) {
3041
3145
  const ids = { user_id: body.user_id, agent_id: body.agent_id, run_id: body.run_id };
@@ -3268,6 +3372,8 @@ class Mem0Memory {
3268
3372
  const key = userKeyFrom(threadId, adv, project);
3269
3373
  const queryParam = this.getNodeParameter('query', itemIndex, '');
3270
3374
  const query = stripThreadTestPrefix(asSearchQuery(queryParam) || asSearchQuery(inputValues.query) || asSearchQuery(inputValues.input) || asSearchQuery(inputValues.chatInput));
3375
+ const remoteThreadState = backendPersistenceEnabled ? await loadThreadState(this, key, threadId, project) : null;
3376
+ mergeRemoteThreadState(store, key, remoteThreadState);
3271
3377
  let connectedLanguageModel;
3272
3378
  let connectedEmbedding;
3273
3379
  const connectedAi = {
@@ -3443,7 +3549,7 @@ class Mem0Memory {
3443
3549
  payload = semMemories.map((m) => { var _a, _b; return ({ role: 'system', content: (_b = (_a = m.memory) !== null && _a !== void 0 ? _a : m.text) !== null && _b !== void 0 ? _b : JSON.stringify(m) }); });
3444
3550
  }
3445
3551
  }
3446
- else if (backendPersistenceEnabled) {
3552
+ else if (backendPersistenceEnabled && vectorMemoryEnabled) {
3447
3553
  const qs = {};
3448
3554
  qs.user_id = key;
3449
3555
  if (adv.agentId)
@@ -3552,7 +3658,7 @@ class Mem0Memory {
3552
3658
  let persistedRecentMessages = [];
3553
3659
  let persistedToolHistory = [];
3554
3660
  let persistedMemoryItems = [];
3555
- if (backendPersistenceEnabled && (adv.includeRecentMessages !== false || adv.includeToolHistory !== false)) {
3661
+ if (backendPersistenceEnabled && vectorMemoryEnabled && (adv.includeRecentMessages !== false || adv.includeToolHistory !== false)) {
3556
3662
  try {
3557
3663
  const qs = { user_id: key, limit: Math.max(Number(adv.recentMessagesLastN || 50) * 8, Number(adv.toolHistoryLastN || 10) * 12, 200) };
3558
3664
  if (adv.agentId)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-tembory",
3
- "version": "1.0.44",
3
+ "version": "1.0.46",
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",