n8n-nodes-tembory 1.3.0 → 1.3.2

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,19 @@
2
2
 
3
3
  Node de memoria operacional da Tembory para agentes de IA no n8n.
4
4
 
5
- Versao atual: `1.3.0`.
5
+ Versao atual: `1.3.2`.
6
+
7
+ ## 1.3.2
8
+
9
+ - Remodela o output visual para debug simples no n8n com `sentToAgent`, `slm`, `memory`, `conversation`, `tools`, `io` e `save`.
10
+ - Remove duplicacoes visuais de `saveContext`: `savedMessages`, `conversationTimeline`, `toolNames` e `toolEvents` deixam de aparecer como blocos paralelos no topo.
11
+ - Expõe o status real da SLM no visual: fonte, geração no load atual, cache técnico, active summary carregado/atualizado, chars e preview.
12
+ - Mantem o contexto enviado ao Agent como `tembory.agent_context.v2`; a mudança é no side channel visual e na instrução da SLM para resumir objetivo, próxima ação e evidências operacionais.
13
+
14
+ ## 1.3.1
15
+
16
+ - Republica o pacote como `latest` sem a marcacao deprecated aplicada por engano na `1.3.0`.
17
+ - Mantem o mesmo contrato da `1.3.0`: node legado `Tembory` e node opt in `Tembory Agent Memory`.
6
18
 
7
19
  ## 1.3.0
8
20
 
@@ -3231,6 +3231,14 @@ const buildAgentContextV2 = ({ query = '', userId = '', payloadFormat = 'structu
3231
3231
  memory: cleanContextValue({
3232
3232
  slmSummary: connectedModelSummary ? truncate(connectedModelSummary, Number(adv.connectedModelSummaryMaxChars || 900)) : undefined,
3233
3233
  activeSummary: !connectedModelSummary && activeSummary ? truncate(activeSummary, Number(adv.activeSummaryMaxChars || 900)) : undefined,
3234
+ summaryStatus: diagnostics?.activeSummary ? cleanContextValue({
3235
+ source: diagnostics.activeSummary.source,
3236
+ generated: Boolean(connectedModelSummary),
3237
+ activeSummaryLoaded: Boolean(diagnostics.activeSummary.activeSummaryLoaded),
3238
+ activeSummaryUpdated: Boolean(diagnostics.activeSummary.activeSummaryUpdated),
3239
+ transientCacheHit: Boolean(diagnostics.activeSummary.transientCacheHit),
3240
+ chars: diagnostics.activeSummary.summaryChars,
3241
+ }) : undefined,
3234
3242
  referenceFacts,
3235
3243
  compression: adv.includeMemoryCompression === false ? undefined : compactMemoryCompressionForAgent(memoryCompression || {}),
3236
3244
  }),
@@ -3352,13 +3360,13 @@ const invokeConnectedModelSummary = async (connectedLanguageModel, summaryInput,
3352
3360
  const response = await connectedLanguageModel.invoke([
3353
3361
  toBaseMessage({
3354
3362
  role: 'user',
3355
- content: `Update the Tembory active summary for the next agent turn. Return only concise Portuguese bullets, no JSON and no markdown table. Preserve IDs, dates, tool names, confirmed decisions, explicit pending actions, constraints, contradictions, and do-not-repeat instructions. Prefer durable useful context over raw logs. Do not invent facts. Treat inferred gaps or missing details as read-only observations, not action requirements, unless they are explicitly present in tool_state, action_ledger, working_memory.next_expected_action, or the current user message. Do not convert observations, guesses, or helpful suggestions into blocking pending actions. Do-not-repeat means avoiding duplicate prerequisite lookup calls; it never means a current side-effect action is completed without a successful tool call in the current turn.\n\nContext:\n${summaryInput}`,
3363
+ content: `Update the Tembory active summary for the next agent turn. Return only concise Portuguese bullets, no JSON and no markdown table. Include what the agent is doing now, the current objective, the next expected action, useful tool evidence, pending confirmations, durable user facts, constraints, contradictions, and do-not-repeat guidance when present. Preserve IDs, dates, tool names, confirmed decisions, explicit pending actions, constraints, contradictions, and do-not-repeat instructions. Prefer durable useful context over raw logs. Do not invent facts. Treat inferred gaps or missing details as read-only observations, not action requirements, unless they are explicitly present in tool_state, action_ledger, working_memory.next_expected_action, or the current user message. Do not convert observations, guesses, or helpful suggestions into blocking pending actions. Do-not-repeat means avoiding duplicate prerequisite lookup calls; it never means a current side-effect action is completed without a successful tool call in the current turn.\n\nContext:\n${summaryInput}`,
3356
3364
  }),
3357
3365
  ]);
3358
3366
  return cleanModelSummaryText(response, Number(adv.connectedModelSummaryMaxChars || 1200));
3359
3367
  };
3360
- const VISUAL_SCHEMA_VERSION = 'tembory.visual.v1';
3361
- const TOOL_LOG_VISUAL_SCHEMA_VERSION = 'tembory.visual.v1.toolLog';
3368
+ const VISUAL_SCHEMA_VERSION = 'tembory.visual.v2';
3369
+ const TOOL_LOG_VISUAL_SCHEMA_VERSION = 'tembory.visual.v2.toolLog';
3362
3370
  const SIDE_CHANNEL_TOOL_EVENT_MAX = 12;
3363
3371
  const SIDE_CHANNEL_SAVE_TOOL_EVENT_MAX = 20;
3364
3372
  const compactParsedToolInputForSideChannel = (input) => {
@@ -3538,22 +3546,35 @@ const summarizeSaveContextForSideChannel = (input = {}, output = {}, chatHistory
3538
3546
  const outputMessage = output?.output || output?.response || output?.text || output?.message || output?.answer || '';
3539
3547
  const toolCalls = extractToolCalls(output || {});
3540
3548
  const toolEvents = compactToolEventsForSideChannel(toolCalls, SIDE_CHANNEL_SAVE_TOOL_EVENT_MAX);
3541
- return keepVisibleToolLogArrays(cleanContextValue({
3549
+ const conversation = conversationDigestFromMessagesForSideChannel(chatHistory);
3550
+ const timeline = conversationTimelineFromMessagesForSideChannel(chatHistory, 16);
3551
+ return cleanContextValue({
3542
3552
  visualSchema: VISUAL_SCHEMA_VERSION,
3543
- messagesAfterSave: Array.isArray(chatHistory) ? chatHistory.length : 0,
3544
- conversation: conversationDigestFromMessagesForSideChannel(chatHistory),
3545
- conversationTimeline: conversationTimelineFromMessagesForSideChannel(chatHistory, 16),
3546
- savedMessages: Array.isArray(chatHistory)
3547
- ? chatHistory.slice(-6).map((message) => compactMessageForSideChannel(message))
3548
- : undefined,
3549
- userInput: inputMessage ? truncate(String(inputMessage), 500) : undefined,
3550
- assistantOutput: outputMessage ? truncate(String(outputMessage), 700) : undefined,
3551
- toolCallsCaptured: toolCalls.length,
3552
- toolNames: toolEvents.map((tool) => tool.name).filter(Boolean),
3553
- toolCapture: summarizeToolCaptureForSideChannel(output, toolCalls),
3554
- toolLog: buildToolLogForSideChannel(toolEvents, toolCalls.length, SIDE_CHANNEL_SAVE_TOOL_EVENT_MAX),
3555
- toolEvents,
3556
- }));
3553
+ summary: cleanContextValue({
3554
+ action: 'saveContext',
3555
+ messagesAfterSave: Array.isArray(chatHistory) ? chatHistory.length : 0,
3556
+ userInputPreview: inputMessage ? truncate(String(inputMessage), 220) : undefined,
3557
+ assistantOutputPreview: outputMessage ? truncate(String(outputMessage), 260) : undefined,
3558
+ toolCallsCaptured: toolCalls.length,
3559
+ }),
3560
+ conversation: cleanContextValue({
3561
+ ...conversation,
3562
+ timeline,
3563
+ }),
3564
+ io: cleanContextValue({
3565
+ userInput: inputMessage ? truncate(String(inputMessage), 500) : undefined,
3566
+ assistantOutput: outputMessage ? truncate(String(outputMessage), 700) : undefined,
3567
+ }),
3568
+ tools: cleanContextValue({
3569
+ captured: toolCalls.length,
3570
+ capture: summarizeToolCaptureForSideChannel(output, toolCalls),
3571
+ log: buildToolLogForSideChannel(toolEvents, toolCalls.length, SIDE_CHANNEL_SAVE_TOOL_EVENT_MAX),
3572
+ }),
3573
+ save: cleanContextValue({
3574
+ messagesAfterSave: Array.isArray(chatHistory) ? chatHistory.length : 0,
3575
+ status: 'saved_to_memory_contract',
3576
+ }),
3577
+ });
3557
3578
  };
3558
3579
  const compactMemoryEventPayload = (payload = {}) => {
3559
3580
  const compact = { ...(payload || {}) };
@@ -3771,10 +3792,20 @@ const summarizeMemoryMessagesForSideChannel = (messages = []) => {
3771
3792
  toolCallsCaptured: parsed.captureHealth?.toolCallsCapturedLastSave,
3772
3793
  captureSources: parsed.captureHealth?.captureSources,
3773
3794
  } : {}));
3795
+ const summaryStatus = parsed.memory?.summaryStatus || parsed.diagnostics?.activeSummary || {};
3796
+ const slmPreview = parsed.memory?.slmSummary || parsed.memory?.activeSummary || summaryText || '';
3774
3797
  const fullDedupeSummary = parsed.dedupeSummary || parsed.diagnostics?.dedupeSummary || undefined;
3775
3798
  const loadedSections = loadedSectionsForSideChannel(parsed, memoryAudit);
3776
3799
  const agentContextBudget = agentContextBudgetForSideChannel(list, parsed);
3777
3800
  summary.visualSchema = VISUAL_SCHEMA_VERSION;
3801
+ summary.sentToAgent = cleanContextValue({
3802
+ messages: list.length,
3803
+ contextKind: parsed.kind,
3804
+ schemaVersion: parsed.schemaVersion,
3805
+ chars: agentContextBudget.chars,
3806
+ approxTokens: agentContextBudget.approxTokens,
3807
+ largestSections: agentContextBudget.largestSections,
3808
+ });
3778
3809
  summary.userId = parsed.userId;
3779
3810
  summary.project = parsed.project || undefined;
3780
3811
  summary.retrievalMode = parsed.retrievalMode;
@@ -3796,6 +3827,7 @@ const summarizeMemoryMessagesForSideChannel = (messages = []) => {
3796
3827
  at: lastAgent.at || lastAgent.timestamp || lastAgent.created_at || lastAgent.createdAt,
3797
3828
  preview: truncate(String(lastAgent.content || lastAgent.text || lastAgent.message || ''), 240),
3798
3829
  } : undefined,
3830
+ timeline: compactConversationTimelineForSideChannel(conversation, 16),
3799
3831
  });
3800
3832
  summary.conversationTimeline = compactConversationTimelineForSideChannel(conversation, 16);
3801
3833
  const visibleToolEvents = compactToolEventsForSideChannel(toolItems, SIDE_CHANNEL_TOOL_EVENT_MAX);
@@ -3831,6 +3863,30 @@ const summarizeMemoryMessagesForSideChannel = (messages = []) => {
3831
3863
  });
3832
3864
  summary.loadedSections = loadedSections;
3833
3865
  summary.agentContextBudget = agentContextBudget;
3866
+ summary.slm = cleanContextValue({
3867
+ status: slmPreview ? 'available' : 'empty',
3868
+ source: summaryStatus.source || (parsed.memory?.slmSummary ? 'slm_summary' : parsed.memory?.activeSummary ? 'active_summary' : 'none'),
3869
+ generatedThisLoad: summaryStatus.source === 'fresh_slm',
3870
+ activeSummaryLoaded: summaryStatus.activeSummaryLoaded,
3871
+ activeSummaryUpdated: summaryStatus.activeSummaryUpdated,
3872
+ transientCacheHit: summaryStatus.transientCacheHit,
3873
+ chars: summaryStatus.chars || summaryStatus.summaryChars || (slmPreview ? String(slmPreview).length : 0),
3874
+ preview: slmPreview ? truncate(String(slmPreview), 500) : undefined,
3875
+ });
3876
+ summary.memory = cleanContextValue({
3877
+ conversation: summary.conversation,
3878
+ tools: {
3879
+ count: toolItems.length || summary.toolCount || 0,
3880
+ names: summary.toolNames,
3881
+ last: summary.lastTool,
3882
+ log: summary.toolLog,
3883
+ },
3884
+ compression: parsed.memory?.compression || parsed.memoryCompression,
3885
+ referenceFacts: parsed.memory?.referenceFacts,
3886
+ canonicalFacts: parsed.canonicalFacts,
3887
+ captureHealth: parsed.captureHealth,
3888
+ });
3889
+ summary.tools = summary.memory?.tools;
3834
3890
  summary.lastSave = Object.keys(lastSave).length ? lastSave : undefined;
3835
3891
  summary.dedupe = fullDedupeSummary ? compactDedupeForSideChannel(fullDedupeSummary) : undefined;
3836
3892
  summary.workingMemory = cleanContextValue({
@@ -3875,6 +3931,13 @@ const summarizeMemoryMessagesForSideChannel = (messages = []) => {
3875
3931
  dedupeSummary: fullDedupeSummary,
3876
3932
  conversationTimelineFull: compactConversationTimelineForSideChannel(conversation, 12, true),
3877
3933
  }) : undefined;
3934
+ delete summary.currentUserMessage;
3935
+ delete summary.toolNames;
3936
+ delete summary.toolEvents;
3937
+ delete summary.toolLog;
3938
+ delete summary.lastTool;
3939
+ delete summary.agentContextBudget;
3940
+ delete summary.conversationTimeline;
3878
3941
  return Object.fromEntries(Object.entries(summary).filter(([, value]) => value !== undefined));
3879
3942
  }
3880
3943
  catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-tembory",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
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",