n8n-nodes-tembory 1.0.45 → 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'))
@@ -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,
@@ -2810,7 +2855,7 @@ class Mem0Memory {
2810
2855
  { displayName: 'Máximo de Fatos no Resumo', name: 'summaryMaxFacts', type: 'number', default: 4 },
2811
2856
  { displayName: 'Incluir Scores', name: 'includeScores', type: 'boolean', default: true },
2812
2857
  { displayName: 'Incluir Diagnóstico', name: 'includeDiagnostics', type: 'boolean', default: false },
2813
- { displayName: 'Incluir Grafo', name: 'includeRelations', type: 'boolean', default: true },
2858
+ { displayName: 'Incluir Grafo', name: 'includeRelations', type: 'boolean', default: false },
2814
2859
  { displayName: 'Máximo de Relações', name: 'maxRelations', type: 'number', default: 10 },
2815
2860
  { displayName: 'Incluir Tool History', name: 'includeToolHistory', type: 'boolean', default: true },
2816
2861
  { displayName: 'Incluir Resultado Das Tools', name: 'includeToolResults', type: 'boolean', default: true },
@@ -3079,6 +3124,22 @@ class Mem0Memory {
3079
3124
  body.run_id = String(adv.runId);
3080
3125
  if (adv.persistBackendMemories === false)
3081
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;
3082
3143
  const connectedEmbedding = await getConnectedEmbedding(this, itemIndex);
3083
3144
  if (connectedEmbedding) {
3084
3145
  const ids = { user_id: body.user_id, agent_id: body.agent_id, run_id: body.run_id };
@@ -3311,6 +3372,8 @@ class Mem0Memory {
3311
3372
  const key = userKeyFrom(threadId, adv, project);
3312
3373
  const queryParam = this.getNodeParameter('query', itemIndex, '');
3313
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);
3314
3377
  let connectedLanguageModel;
3315
3378
  let connectedEmbedding;
3316
3379
  const connectedAi = {
@@ -3327,7 +3390,7 @@ class Mem0Memory {
3327
3390
  catch (error) {
3328
3391
  connectedAi.errors.push(`languageModel: ${error.message || String(error)}`);
3329
3392
  }
3330
- if (vectorMemoryEnabled || backendPersistenceEnabled) {
3393
+ if (vectorMemoryEnabled) {
3331
3394
  try {
3332
3395
  connectedEmbedding = await this.getInputConnectionData(n8n_workflow_1.NodeConnectionTypes.AiEmbedding, itemIndex);
3333
3396
  connectedAi.embedding = true;
@@ -3349,28 +3412,6 @@ class Mem0Memory {
3349
3412
  catch { }
3350
3413
  let payload;
3351
3414
  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
3415
  if (vectorMemoryEnabled && (retrievalMode === 'semantic' || retrievalMode === 'semanticV2' || retrievalMode === 'hybrid')) {
3375
3416
  const body = { query: String(query || '') };
3376
3417
  // IDs
@@ -3508,7 +3549,7 @@ class Mem0Memory {
3508
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) }); });
3509
3550
  }
3510
3551
  }
3511
- else if (backendPersistenceEnabled) {
3552
+ else if (backendPersistenceEnabled && vectorMemoryEnabled) {
3512
3553
  const qs = {};
3513
3554
  qs.user_id = key;
3514
3555
  if (adv.agentId)
@@ -3617,7 +3658,7 @@ class Mem0Memory {
3617
3658
  let persistedRecentMessages = [];
3618
3659
  let persistedToolHistory = [];
3619
3660
  let persistedMemoryItems = [];
3620
- if (backendPersistenceEnabled && (adv.includeRecentMessages !== false || adv.includeToolHistory !== false)) {
3661
+ if (backendPersistenceEnabled && vectorMemoryEnabled && (adv.includeRecentMessages !== false || adv.includeToolHistory !== false)) {
3621
3662
  try {
3622
3663
  const qs = { user_id: key, limit: Math.max(Number(adv.recentMessagesLastN || 50) * 8, Number(adv.toolHistoryLastN || 10) * 12, 200) };
3623
3664
  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.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",