n8n-nodes-tembory 1.3.5 → 1.3.7

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.
package/README.md CHANGED
@@ -2,7 +2,15 @@
2
2
 
3
3
  Node de memoria operacional da Tembory para agentes de IA no n8n.
4
4
 
5
- Versao atual: `1.3.5`.
5
+ Versao atual: `1.3.6`.
6
+
7
+ ## 1.3.6
8
+
9
+ - Fortalece o default recomendado para agentes mini/SLM em workflows reais.
10
+ - `Memoria Inteligente (Recomendado)` agora usa `productionBalanced` com contexto de 20000 caracteres, entrada do SLM em 12000 caracteres, resumo SLM em 3000 caracteres e active summary em 3500 caracteres.
11
+ - Mantem 30 tools recentes no contexto operacional e TTL de tool history em 86400 segundos.
12
+ - Alinha os defaults visiveis em `Ajustes Tecnicos` para nao mostrar configuracao mais fraca quando o usuario abre os grupos.
13
+ - Esclarece que o cache tecnico SLM usa segundos; 300 segundos equivalem a 5 minutos.
6
14
 
7
15
  ## 1.3.5
8
16
 
@@ -220,13 +228,18 @@ No modo simples, o node aplica automaticamente:
220
228
 
221
229
  - `Modo de Recuperacao`: operacional estruturado.
222
230
  - `Formato do Contexto`: producao estruturado.
223
- - `Preset Operacional`: producao rapida.
224
- - `Fonte do Resumo do SLM`: contexto ativo.
231
+ - `Preset Operacional`: producao balanceada.
232
+ - `Fonte do Resumo do SLM`: automatica.
233
+ - `Maximo de Caracteres do Contexto`: 20000.
234
+ - `Maximo de Caracteres de Entrada do SLM`: 12000.
235
+ - `Maximo de Caracteres do Resumo do SLM`: 3000.
236
+ - `Maximo de Caracteres do Active Summary`: 3500.
225
237
  - Tool history, resultados de tools, action ledger, working memory, decision state, operational state e memory compression ligados.
226
238
  - Persistencia no backend e active summary ligados.
227
239
  - Diagnostico pesado, scores, semantic fallback e tool facts desligados.
228
- - TTL de tool history em 36000 segundos.
229
- - Ultimas tools mantidas no contexto compacto: 50.
240
+ - Cache tecnico do SLM em 300 segundos.
241
+ - TTL de tool history em 86400 segundos.
242
+ - Ultimas tools mantidas no contexto compacto: 30.
230
243
 
231
244
  ## Uso com `$fromAI()`
232
245
 
@@ -234,6 +247,27 @@ Em tools conectadas ao AI Agent, o n8n permite que o modelo preencha parametros
234
247
 
235
248
  Referencia oficial do n8n: https://docs.n8n.io/advanced-ai/examples/using-the-fromai-function/
236
249
 
250
+ ## Prompt recomendado para AI Agent
251
+
252
+ O Tembory entrega memoria operacional, mas o Agent ainda precisa de politica clara para decidir quando usar memoria e quando chamar tool. Em workflows com muitas tools, adicione um bloco como este no `System Message` do AI Agent:
253
+
254
+ ```text
255
+ Antes de chamar uma ferramenta, consulte a memoria Tembory: tool_state, tool_history, action_ledger, decision_state, operational_state, active_summary e conversation_frame.
256
+ Use a memoria para evitar repeticao, mas nao substitua verificacao operacional nova por inferencia.
257
+ Se o usuario pedir para verificar, validar, consultar, checar, confirmar status, criar, atualizar, registrar ou acionar algo que ainda nao esteja confirmado por uma tool recente no tool_history, chame a tool correta.
258
+ Nao repita uma tool se a memoria ja trouxer evidencia suficiente para a pergunta atual.
259
+ Nunca declare uma acao como confirmada, criada, atualizada, enviada ou reservada sem uma tool de side effect bem-sucedida no turno atual.
260
+ Se uma tool retornar dado incoerente com a pergunta, aponte a inconsistencia em vez de inventar.
261
+ Quando responder sobre historico operacional, use os outputs e timestamps das tools salvas pela memoria.
262
+ ```
263
+
264
+ Regras praticas:
265
+
266
+ - Perguntas de recall/status podem usar memoria sem chamar tools.
267
+ - Pedidos novos de verificacao, consulta, atualizacao ou registro devem chamar a tool correta quando ainda nao houver evidencia recente.
268
+ - Acoes laterais como confirmar, reservar, enviar, criar ou atualizar so podem ser declaradas como concluidas depois de uma tool de side effect bem-sucedida.
269
+ - Outputs incoerentes de tools devem ser tratados como inconsistencia, nao como fato confirmado.
270
+
237
271
  ## Payload visual do n8n
238
272
 
239
273
  No output do node durante uma execucao, o Tembory mostra um resumo compacto para humano:
@@ -252,8 +286,8 @@ Exemplo de budget:
252
286
  {
253
287
  "agentContextBudget": {
254
288
  "messages": 1,
255
- "chars": 4200,
256
- "approxTokens": 1050,
289
+ "chars": 12000,
290
+ "approxTokens": 3000,
257
291
  "largestSections": [
258
292
  { "section": "tools", "chars": 1600, "approxTokens": 400 }
259
293
  ]
@@ -1250,32 +1250,18 @@ const extractToolCalls = (outputValues = {}) => {
1250
1250
  return Array.from(byKey.values());
1251
1251
  };
1252
1252
  const getMemoryStore = (ctx) => {
1253
- try {
1254
- const data = ctx.getWorkflowStaticData('global');
1255
- data.tembory = data.tembory || {};
1256
- data.tembory.toolHistory = data.tembory.toolHistory || {};
1257
- data.tembory.recentMessages = data.tembory.recentMessages || {};
1258
- data.tembory.profileFacts = data.tembory.profileFacts || {};
1259
- data.tembory.workingMemory = data.tembory.workingMemory || {};
1260
- data.tembory.decisionState = data.tembory.decisionState || {};
1261
- data.tembory.memoryCompression = data.tembory.memoryCompression || {};
1262
- data.tembory.activeSummary = data.tembory.activeSummary || {};
1263
- data.tembory.connectedModelSummaryCache = data.tembory.connectedModelSummaryCache || {};
1264
- data.tembory.captureState = data.tembory.captureState || {};
1265
- data.tembory.memoryDedupe = data.tembory.memoryDedupe || {};
1266
- return data.tembory;
1267
- }
1268
- catch {
1269
- global.__temboryMemory = global.__temboryMemory || { toolHistory: {}, recentMessages: {}, profileFacts: {}, workingMemory: {}, decisionState: {}, memoryCompression: {}, activeSummary: {}, connectedModelSummaryCache: {}, captureState: {}, memoryDedupe: {} };
1270
- global.__temboryMemory.workingMemory = global.__temboryMemory.workingMemory || {};
1271
- global.__temboryMemory.decisionState = global.__temboryMemory.decisionState || {};
1272
- global.__temboryMemory.memoryCompression = global.__temboryMemory.memoryCompression || {};
1273
- global.__temboryMemory.activeSummary = global.__temboryMemory.activeSummary || {};
1274
- global.__temboryMemory.connectedModelSummaryCache = global.__temboryMemory.connectedModelSummaryCache || {};
1275
- global.__temboryMemory.captureState = global.__temboryMemory.captureState || {};
1276
- global.__temboryMemory.memoryDedupe = global.__temboryMemory.memoryDedupe || {};
1277
- return global.__temboryMemory;
1278
- }
1253
+ global.__temboryMemory = global.__temboryMemory || { toolHistory: {}, recentMessages: {}, profileFacts: {}, workingMemory: {}, decisionState: {}, memoryCompression: {}, activeSummary: {}, connectedModelSummaryCache: {}, captureState: {}, memoryDedupe: {} };
1254
+ global.__temboryMemory.toolHistory = global.__temboryMemory.toolHistory || {};
1255
+ global.__temboryMemory.recentMessages = global.__temboryMemory.recentMessages || {};
1256
+ global.__temboryMemory.profileFacts = global.__temboryMemory.profileFacts || {};
1257
+ global.__temboryMemory.workingMemory = global.__temboryMemory.workingMemory || {};
1258
+ global.__temboryMemory.decisionState = global.__temboryMemory.decisionState || {};
1259
+ global.__temboryMemory.memoryCompression = global.__temboryMemory.memoryCompression || {};
1260
+ global.__temboryMemory.activeSummary = global.__temboryMemory.activeSummary || {};
1261
+ global.__temboryMemory.connectedModelSummaryCache = global.__temboryMemory.connectedModelSummaryCache || {};
1262
+ global.__temboryMemory.captureState = global.__temboryMemory.captureState || {};
1263
+ global.__temboryMemory.memoryDedupe = global.__temboryMemory.memoryDedupe || {};
1264
+ return global.__temboryMemory;
1279
1265
  };
1280
1266
  const namespacePart = (value) => String(value || '').trim().replace(/\s+/g, '_').replace(/[:|]+/g, '-');
1281
1267
  const userKeyFrom = (threadId, adv, project = '') => {
@@ -1333,8 +1319,8 @@ const mergeRemoteThreadState = (store, key, state) => {
1333
1319
  store.activeSummary[key] = state.activeSummary;
1334
1320
  };
1335
1321
  const SIMPLE_MODE_OVERRIDES = {
1336
- operationPreset: 'productionFast',
1337
- summarySource: 'activeContext',
1322
+ operationPreset: 'productionBalanced',
1323
+ summarySource: 'auto',
1338
1324
  includeContextHeader: true,
1339
1325
  compactStateSections: true,
1340
1326
  includeSummary: true,
@@ -1357,13 +1343,13 @@ const SIMPLE_MODE_OVERRIDES = {
1357
1343
  includeDiagnostics: false,
1358
1344
  persistToolFactsToTembory: false,
1359
1345
  includeToolHistorySemanticFallback: false,
1360
- contextMaxChars: 10000,
1361
- toolHistoryLastN: 50,
1362
- toolHistoryTTLSeconds: 36000,
1346
+ contextMaxChars: 20000,
1347
+ toolHistoryLastN: 30,
1348
+ toolHistoryTTLSeconds: 86400,
1363
1349
  recentMessagesLastN: 50,
1364
- connectedModelSummaryInputMaxChars: 4200,
1365
- connectedModelSummaryMaxChars: 1200,
1366
- activeSummaryMaxChars: 1800,
1350
+ connectedModelSummaryInputMaxChars: 12000,
1351
+ connectedModelSummaryMaxChars: 3000,
1352
+ activeSummaryMaxChars: 3500,
1367
1353
  activeSummaryRetentionDays: 30,
1368
1354
  };
1369
1355
  const applyOperationalPreset = (advanced = {}) => {
@@ -1445,7 +1431,7 @@ const applyOperationalPreset = (advanced = {}) => {
1445
1431
  includeConnectedModelSummary: true,
1446
1432
  includeActiveSummary: true,
1447
1433
  persistActiveSummary: true,
1448
- activeSummaryMaxChars: 1800,
1434
+ activeSummaryMaxChars: 3500,
1449
1435
  activeSummaryRetentionDays: 30,
1450
1436
  enableTransientSummaryCache: true,
1451
1437
  transientSummaryCacheTTLSeconds: 300,
@@ -1471,12 +1457,14 @@ const applyOperationalPreset = (advanced = {}) => {
1471
1457
  includeRecentHighlights: true,
1472
1458
  topK: 6,
1473
1459
  lastN: 8,
1474
- toolHistoryLastN: 10,
1460
+ toolHistoryLastN: 30,
1461
+ toolHistoryTTLSeconds: 86400,
1475
1462
  recentMessagesLastN: 50,
1476
1463
  vectorMemoryMaxChars: 360,
1477
- contextMaxChars: 10000,
1478
- connectedModelSummaryMaxChars: 1200,
1479
- connectedModelSummaryInputMaxChars: 4200,
1464
+ contextMaxChars: 20000,
1465
+ connectedModelSummaryMaxChars: 3000,
1466
+ connectedModelSummaryInputMaxChars: 12000,
1467
+ summaryMaxFacts: 8,
1480
1468
  },
1481
1469
  productionCheap: {
1482
1470
  summarySource: 'activeContext',
@@ -4513,18 +4501,18 @@ class TemboryMemory {
4513
4501
  options: [
4514
4502
  { name: 'Custom', value: 'custom' },
4515
4503
  { name: 'Diagnóstico Completo', value: 'diagnostic' },
4516
- { name: 'Produção Rápida (Thread + SLM)', value: 'productionFast' },
4517
- { name: 'Produção Balanceada', value: 'productionBalanced' },
4504
+ { name: 'Produção Balanceada (Recomendado)', value: 'productionBalanced' },
4505
+ { name: 'Produção Rápida (Thread + SLM)', value: 'productionFast' },
4518
4506
  { name: 'Produção Econômica', value: 'productionCheap' },
4519
4507
  { name: 'Produção Nano/SLM', value: 'productionNano' },
4520
4508
  { name: 'Auditoria', value: 'audit' },
4521
4509
  ],
4522
- default: 'productionFast',
4523
- description: 'Preenche defaults seguros para contexto, historico de tools e memoria ativa.',
4524
- },
4510
+ default: 'productionBalanced',
4511
+ description: 'Preenche defaults seguros para contexto, historico de tools e memoria ativa.',
4512
+ },
4525
4513
  { displayName: 'Incluir Cabeçalho de Contexto', name: 'includeContextHeader', type: 'boolean', default: true },
4526
4514
  { displayName: 'Organizar Seções de Produção', name: 'compactStateSections', type: 'boolean', default: true },
4527
- { displayName: 'Máximo de Caracteres do Contexto', name: 'contextMaxChars', type: 'number', default: 10000 },
4515
+ { displayName: 'Máximo de Caracteres do Contexto', name: 'contextMaxChars', type: 'number', default: 20000 },
4528
4516
  { displayName: 'Incluir Tool History', name: 'includeToolHistory', type: 'boolean', default: true },
4529
4517
  { displayName: 'Incluir Resultado Das Tools', name: 'includeToolResults', type: 'boolean', default: true },
4530
4518
  { displayName: 'Incluir Working Memory', name: 'includeWorkingMemory', type: 'boolean', default: true },
@@ -4562,16 +4550,16 @@ class TemboryMemory {
4562
4550
  ],
4563
4551
  default: 'auto',
4564
4552
  },
4565
- { displayName: 'Máximo de Caracteres de Entrada do SLM', name: 'connectedModelSummaryInputMaxChars', type: 'number', default: 4200 },
4566
- { displayName: 'Máximo de Caracteres do Resumo do SLM', name: 'connectedModelSummaryMaxChars', type: 'number', default: 1200 },
4553
+ { displayName: 'Máximo de Caracteres de Entrada do SLM', name: 'connectedModelSummaryInputMaxChars', type: 'number', default: 12000 },
4554
+ { displayName: 'Máximo de Caracteres do Resumo do SLM', name: 'connectedModelSummaryMaxChars', type: 'number', default: 3000 },
4567
4555
  { displayName: 'Incluir Active Summary', name: 'includeActiveSummary', type: 'boolean', default: true },
4568
4556
  { displayName: 'Persistir Active Summary', name: 'persistActiveSummary', type: 'boolean', default: true },
4569
- { displayName: 'Máximo de Caracteres do Active Summary', name: 'activeSummaryMaxChars', type: 'number', default: 1800 },
4557
+ { displayName: 'Máximo de Caracteres do Active Summary', name: 'activeSummaryMaxChars', type: 'number', default: 3500 },
4570
4558
  { displayName: 'Retenção do Active Summary (Dias)', name: 'activeSummaryRetentionDays', type: 'number', default: 30 },
4571
4559
  { displayName: 'Ativar Cache Técnico do Resumo SLM', name: 'enableTransientSummaryCache', type: 'boolean', default: true },
4572
4560
  { displayName: 'TTL do Cache Técnico SLM (Segundos)', name: 'transientSummaryCacheTTLSeconds', type: 'number', default: 300 },
4573
4561
  { displayName: 'Máximo de Itens no Cache Técnico SLM', name: 'transientSummaryCacheMaxItems', type: 'number', default: 50 },
4574
- { displayName: 'Máximo de Fatos no Resumo', name: 'summaryMaxFacts', type: 'number', default: 4 },
4562
+ { displayName: 'Máximo de Fatos no Resumo', name: 'summaryMaxFacts', type: 'number', default: 8 },
4575
4563
  ],
4576
4564
  },
4577
4565
  {
@@ -4580,8 +4568,8 @@ class TemboryMemory {
4580
4568
  values: [
4581
4569
  { displayName: 'Incluir Scores', name: 'includeScores', type: 'boolean', default: false },
4582
4570
  { displayName: 'Incluir Diagnóstico', name: 'includeDiagnostics', type: 'boolean', default: false },
4583
- { displayName: 'Últimas N Tools', name: 'toolHistoryLastN', type: 'number', default: 10 },
4584
- { displayName: 'TTL Das Tools (Segundos)', name: 'toolHistoryTTLSeconds', type: 'number', default: 3600 },
4571
+ { displayName: 'Últimas N Tools Mantidas no Contexto', name: 'toolHistoryLastN', type: 'number', default: 30 },
4572
+ { displayName: 'TTL Das Tools (Segundos)', name: 'toolHistoryTTLSeconds', type: 'number', default: 86400 },
4585
4573
  { displayName: 'Persistir Tool Facts no Backend', name: 'persistToolFactsToTembory', type: 'boolean', default: false },
4586
4574
  { displayName: 'Fallback Semântico Para Tools', name: 'includeToolHistorySemanticFallback', type: 'boolean', default: false },
4587
4575
  ],
@@ -4821,20 +4809,10 @@ class TemboryMemory {
4821
4809
  const profileFromTurn = extractProfileFactsFromText(input, 'user_message', nowIso());
4822
4810
  if (Object.keys(profileFromTurn).length) {
4823
4811
  store.profileFacts[key] = mergeProfileFacts(store.profileFacts[key], profileFromTurn);
4824
- try {
4825
- const globalData = this.getWorkflowStaticData('global');
4826
- globalData.__dataChanged = true;
4827
- }
4828
- catch { }
4829
4812
  }
4830
4813
  if (toolCalls.length) {
4831
4814
  const existing = store.toolHistory[key] || [];
4832
4815
  store.toolHistory[key] = applyToolHistoryWindow(existing.concat(toolCalls), adv.toolHistoryTTLSeconds, adv.toolHistoryLastN || 15);
4833
- try {
4834
- const globalData = this.getWorkflowStaticData('global');
4835
- globalData.__dataChanged = true;
4836
- }
4837
- catch { }
4838
4816
  }
4839
4817
  if (adv.includeRecentMessages !== false) {
4840
4818
  const recent = store.recentMessages[key] || [];
@@ -4849,11 +4827,6 @@ class TemboryMemory {
4849
4827
  recentForTembory.push(item);
4850
4828
  }
4851
4829
  store.recentMessages[key] = pruneByLimit(recent, adv.recentMessagesLastN || 8);
4852
- try {
4853
- const globalData = this.getWorkflowStaticData('global');
4854
- globalData.__dataChanged = true;
4855
- }
4856
- catch { }
4857
4830
  }
4858
4831
  const renderedProfileForTurn = renderProfileFacts(store.profileFacts[key] || {});
4859
4832
  const recentForTurn = store.recentMessages[key] || [];
@@ -4884,11 +4857,6 @@ class TemboryMemory {
4884
4857
  store.workingMemory[key] = workingMemoryForTurn;
4885
4858
  store.decisionState[key] = decisionStateForTurn;
4886
4859
  store.memoryCompression[key] = compressionForTurn;
4887
- try {
4888
- const globalData = this.getWorkflowStaticData('global');
4889
- globalData.__dataChanged = true;
4890
- }
4891
- catch { }
4892
4860
  const messages = [];
4893
4861
  if (input)
4894
4862
  messages.push({ role: 'user', content: input });
@@ -4938,11 +4906,6 @@ class TemboryMemory {
4938
4906
  ...nextCaptureState,
4939
4907
  last_save_thread_state_saved: threadStateSaved,
4940
4908
  });
4941
- try {
4942
- const globalData = this.getWorkflowStaticData('global');
4943
- globalData.__dataChanged = true;
4944
- }
4945
- catch { }
4946
4909
  if (adv.persistBackendMemories === false) {
4947
4910
  await finalizeDedupeSummary();
4948
4911
  return;
@@ -5597,11 +5560,6 @@ class TemboryMemory {
5597
5560
  const profileFacts = adv.includeProfileFacts === false ? {} : mergeProfileFacts(store.profileFacts[key], profileFactsFromMessages(allRecentMessages), profileFactsFromMemories(vectorMemories));
5598
5561
  if (adv.includeProfileFacts !== false && Object.keys(profileFacts).length) {
5599
5562
  store.profileFacts[key] = mergeProfileFacts(store.profileFacts[key], profileFacts);
5600
- try {
5601
- const globalData = this.getWorkflowStaticData('global');
5602
- globalData.__dataChanged = true;
5603
- }
5604
- catch { }
5605
5563
  }
5606
5564
  const includeToolResults = adv.includeToolResults !== false;
5607
5565
  const operationalState = deriveOperationalState(toolHistory, renderProfileFacts(profileFacts), recentMessages, includeToolResults);
@@ -5741,11 +5699,6 @@ class TemboryMemory {
5741
5699
  store.workingMemory[key] = workingMemory;
5742
5700
  store.decisionState[key] = decisionState;
5743
5701
  store.memoryCompression[key] = memoryCompression;
5744
- try {
5745
- const globalData = this.getWorkflowStaticData('global');
5746
- globalData.__dataChanged = true;
5747
- }
5748
- catch { }
5749
5702
  payload = buildContextMessages({
5750
5703
  payloadFormat,
5751
5704
  query,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-tembory",
3
- "version": "1.3.5",
3
+ "version": "1.3.7",
4
4
  "description": "Tembory node for n8n AI Agents with operational memory, tool history and decision state",
5
5
  "license": "MIT",
6
6
  "homepage": "https://tembory.com",