n8n-nodes-tembory 1.0.45 → 1.0.47

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'))
@@ -1185,6 +1185,51 @@ const userKeyFrom = (threadId, adv, project = '') => {
1185
1185
  const namespace = namespacePart(project || (adv === null || adv === void 0 ? void 0 : adv.project) || (adv === null || adv === void 0 ? void 0 : adv.projectId));
1186
1186
  return namespace ? `${namespace}::${base}` : base;
1187
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
+ };
1188
1233
  const applyOperationalPreset = (advanced = {}) => {
1189
1234
  const preset = String(advanced.operationPreset || 'productionFast');
1190
1235
  const presets = {
@@ -1237,7 +1282,7 @@ const applyOperationalPreset = (advanced = {}) => {
1237
1282
  includeSummary: true,
1238
1283
  includeScores: true,
1239
1284
  includeDiagnostics: true,
1240
- includeRelations: true,
1285
+ includeRelations: false,
1241
1286
  includeToolHistory: true,
1242
1287
  includeToolResults: true,
1243
1288
  persistToolFactsToMem0: true,
@@ -1270,7 +1315,7 @@ const applyOperationalPreset = (advanced = {}) => {
1270
1315
  includeSummary: true,
1271
1316
  includeScores: false,
1272
1317
  includeDiagnostics: false,
1273
- includeRelations: true,
1318
+ includeRelations: false,
1274
1319
  includeToolHistory: true,
1275
1320
  includeToolResults: true,
1276
1321
  persistToolFactsToMem0: false,
@@ -1375,7 +1420,7 @@ const applyOperationalPreset = (advanced = {}) => {
1375
1420
  includeSummary: true,
1376
1421
  includeScores: true,
1377
1422
  includeDiagnostics: true,
1378
- includeRelations: true,
1423
+ includeRelations: false,
1379
1424
  includeToolHistory: true,
1380
1425
  includeToolResults: true,
1381
1426
  persistToolFactsToMem0: true,
@@ -1396,7 +1441,12 @@ const applyOperationalPreset = (advanced = {}) => {
1396
1441
  payloadFormat: 'auditJson',
1397
1442
  },
1398
1443
  };
1399
- return { ...(presets[preset === 'lab' ? 'diagnostic' : preset] || {}), ...advanced };
1444
+ const resolved = { ...(presets[preset === 'lab' ? 'diagnostic' : preset] || {}), ...advanced };
1445
+ if (resolved.useVectorMemory === false) {
1446
+ resolved.includeRelations = false;
1447
+ resolved.includeEntityTimeline = false;
1448
+ }
1449
+ return resolved;
1400
1450
  };
1401
1451
  const flattenAdvancedGroups = (groups = {}) => {
1402
1452
  const flattened = {};
@@ -2810,7 +2860,7 @@ class Mem0Memory {
2810
2860
  { displayName: 'Máximo de Fatos no Resumo', name: 'summaryMaxFacts', type: 'number', default: 4 },
2811
2861
  { displayName: 'Incluir Scores', name: 'includeScores', type: 'boolean', default: true },
2812
2862
  { displayName: 'Incluir Diagnóstico', name: 'includeDiagnostics', type: 'boolean', default: false },
2813
- { displayName: 'Incluir Grafo', name: 'includeRelations', type: 'boolean', default: true },
2863
+ { displayName: 'Incluir Grafo', name: 'includeRelations', type: 'boolean', default: false },
2814
2864
  { displayName: 'Máximo de Relações', name: 'maxRelations', type: 'number', default: 10 },
2815
2865
  { displayName: 'Incluir Tool History', name: 'includeToolHistory', type: 'boolean', default: true },
2816
2866
  { displayName: 'Incluir Resultado Das Tools', name: 'includeToolResults', type: 'boolean', default: true },
@@ -3077,8 +3127,24 @@ class Mem0Memory {
3077
3127
  body.app_id = String(adv.appId);
3078
3128
  if (adv.runId)
3079
3129
  body.run_id = String(adv.runId);
3130
+ await saveThreadState(this, key, threadId, project, {
3131
+ kind: 'tembory.thread_state.v1',
3132
+ threadId,
3133
+ project: project || undefined,
3134
+ updatedAt: nowIso(),
3135
+ recentMessages: recentForTurn,
3136
+ toolHistory: toolHistoryForTurn,
3137
+ profileFacts: store.profileFacts[key] || {},
3138
+ workingMemory: workingMemoryForTurn,
3139
+ decisionState: decisionStateForTurn,
3140
+ memoryCompression: compressionForTurn,
3141
+ operationalState: operationalStateForTurn,
3142
+ activeSummary: store.activeSummary[key] || '',
3143
+ });
3080
3144
  if (adv.persistBackendMemories === false)
3081
3145
  return;
3146
+ if (adv.useVectorMemory === false)
3147
+ return;
3082
3148
  const connectedEmbedding = await getConnectedEmbedding(this, itemIndex);
3083
3149
  if (connectedEmbedding) {
3084
3150
  const ids = { user_id: body.user_id, agent_id: body.agent_id, run_id: body.run_id };
@@ -3311,6 +3377,8 @@ class Mem0Memory {
3311
3377
  const key = userKeyFrom(threadId, adv, project);
3312
3378
  const queryParam = this.getNodeParameter('query', itemIndex, '');
3313
3379
  const query = stripThreadTestPrefix(asSearchQuery(queryParam) || asSearchQuery(inputValues.query) || asSearchQuery(inputValues.input) || asSearchQuery(inputValues.chatInput));
3380
+ const remoteThreadState = await loadThreadState(this, key, threadId, project);
3381
+ mergeRemoteThreadState(store, key, remoteThreadState);
3314
3382
  let connectedLanguageModel;
3315
3383
  let connectedEmbedding;
3316
3384
  const connectedAi = {
@@ -3327,7 +3395,7 @@ class Mem0Memory {
3327
3395
  catch (error) {
3328
3396
  connectedAi.errors.push(`languageModel: ${error.message || String(error)}`);
3329
3397
  }
3330
- if (vectorMemoryEnabled || backendPersistenceEnabled) {
3398
+ if (vectorMemoryEnabled) {
3331
3399
  try {
3332
3400
  connectedEmbedding = await this.getInputConnectionData(n8n_workflow_1.NodeConnectionTypes.AiEmbedding, itemIndex);
3333
3401
  connectedAi.embedding = true;
@@ -3349,28 +3417,6 @@ class Mem0Memory {
3349
3417
  catch { }
3350
3418
  let payload;
3351
3419
  let vectorMemories = [];
3352
- if (!vectorMemoryEnabled && backendPersistenceEnabled && connectedEmbedding && String(query || '').trim()) {
3353
- try {
3354
- const archiveBody = {
3355
- user_id: key,
3356
- agent_id: adv.agentId ? String(adv.agentId) : undefined,
3357
- run_id: adv.runId ? String(adv.runId) : undefined,
3358
- top_k: Math.max(Number(adv.lastN || 0), Number(adv.maxReturn || 12), 12),
3359
- filters: { kind: 'turn_archive' },
3360
- };
3361
- const archiveRes = await searchClientVectorMemories(this, connectedEmbedding, `latest turn archive for thread ${threadId}\n${query}`, archiveBody);
3362
- vectorMemories = normalizeResults(archiveRes).map((memory) => withTemboryScore(memory, {
3363
- semanticScore: scoreOf(memory),
3364
- source: 'turn_archive_lookup',
3365
- }));
3366
- connectedAi.embedding = true;
3367
- connectedAi.embeddingQuery = true;
3368
- connectedAi.turnArchiveLookup = true;
3369
- }
3370
- catch (error) {
3371
- connectedAi.errors.push(`turnArchiveLookup: ${error.message || String(error)}`);
3372
- }
3373
- }
3374
3420
  if (vectorMemoryEnabled && (retrievalMode === 'semantic' || retrievalMode === 'semanticV2' || retrievalMode === 'hybrid')) {
3375
3421
  const body = { query: String(query || '') };
3376
3422
  // IDs
@@ -3508,7 +3554,7 @@ class Mem0Memory {
3508
3554
  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) }); });
3509
3555
  }
3510
3556
  }
3511
- else if (backendPersistenceEnabled) {
3557
+ else if (backendPersistenceEnabled && vectorMemoryEnabled) {
3512
3558
  const qs = {};
3513
3559
  qs.user_id = key;
3514
3560
  if (adv.agentId)
@@ -3617,7 +3663,7 @@ class Mem0Memory {
3617
3663
  let persistedRecentMessages = [];
3618
3664
  let persistedToolHistory = [];
3619
3665
  let persistedMemoryItems = [];
3620
- if (backendPersistenceEnabled && (adv.includeRecentMessages !== false || adv.includeToolHistory !== false)) {
3666
+ if (backendPersistenceEnabled && vectorMemoryEnabled && (adv.includeRecentMessages !== false || adv.includeToolHistory !== false)) {
3621
3667
  try {
3622
3668
  const qs = { user_id: key, limit: Math.max(Number(adv.recentMessagesLastN || 50) * 8, Number(adv.toolHistoryLastN || 10) * 12, 200) };
3623
3669
  if (adv.agentId)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-tembory",
3
- "version": "1.0.45",
3
+ "version": "1.0.47",
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",