n8n-nodes-tembory 1.1.21 → 1.1.22

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.
@@ -1396,7 +1396,7 @@ const applyOperationalPreset = (advanced = {}) => {
1396
1396
  includeToolHistorySemanticFallback: false,
1397
1397
  includeProfileFacts: true,
1398
1398
  includeOperationalState: true,
1399
- includeActionLedger: false,
1399
+ includeActionLedger: true,
1400
1400
  includeEntityTimeline: false,
1401
1401
  includeWorkingMemory: true,
1402
1402
  includeDecisionState: true,
@@ -2114,9 +2114,29 @@ const compactActionLedgerForAgent = (ledger = [], maxItems = 6, includeResults =
2114
2114
  status: item.status,
2115
2115
  at: item.at,
2116
2116
  reason: item.reason,
2117
- input: item.input,
2118
- result: includeResults ? compactToolResult(item.result, 180) : undefined,
2117
+ input: truncate(String(item.input || ''), 500) || undefined,
2118
+ result: includeResults ? compactToolResult(item.result, 700) : undefined,
2119
2119
  }));
2120
+ const compactSaveAuditForAgent = (capture = {}) => cleanContextValue({
2121
+ last_save: {
2122
+ saved: capture.last_save_status === 'saved' || capture.last_save_saved === true,
2123
+ status: capture.last_save_status,
2124
+ at: capture.last_save_at,
2125
+ had_input: capture.last_save_had_input,
2126
+ had_output: capture.last_save_had_output,
2127
+ input_chars: capture.last_save_input_chars,
2128
+ output_chars: capture.last_save_output_chars,
2129
+ input_preview: capture.last_save_input_preview,
2130
+ output_preview: capture.last_save_output_preview,
2131
+ tool_calls_captured: capture.last_save_tool_calls_captured,
2132
+ tool_names: capture.last_save_tool_names,
2133
+ capture_sources: capture.last_save_capture_sources,
2134
+ conversation_messages_after_save: capture.last_save_conversation_messages_after_save,
2135
+ tool_history_after_save: capture.last_save_tool_history_after_save,
2136
+ thread_state_saved: capture.last_save_thread_state_saved,
2137
+ backend_memory_persistence: capture.last_save_backend_memory_persistence,
2138
+ },
2139
+ });
2120
2140
  const compactEntityTimelineForAgent = (timeline = [], maxItems = 8) => pruneByLimit(timeline || [], maxItems).map((item) => cleanContextValue({
2121
2141
  entity: item.entity || item.source || item.name,
2122
2142
  event: truncate(item.event || item.fact || item.relation || item.kind || item.value, 220),
@@ -2326,6 +2346,7 @@ const summarizeMemoryMessagesForSideChannel = (messages = []) => {
2326
2346
  const conversation = parsed.conversation || {};
2327
2347
  const tools = parsed.tools || {};
2328
2348
  const toolItems = Array.isArray(tools.items) ? tools.items : [];
2349
+ const memoryAudit = parsed.memoryAudit || parsed.memory_audit || {};
2329
2350
  const summaryText = parsed.summary?.slm || parsed.summary || parsed.connectedModelSummary || parsed.activeSummary || '';
2330
2351
  summary.userId = parsed.userId;
2331
2352
  summary.project = parsed.project || undefined;
@@ -2357,6 +2378,7 @@ const summarizeMemoryMessagesForSideChannel = (messages = []) => {
2357
2378
  graph: Array.isArray(parsed.graph) ? parsed.graph.length : undefined,
2358
2379
  recentHighlights: Array.isArray(parsed.recentHighlights) ? parsed.recentHighlights.length : undefined,
2359
2380
  });
2381
+ summary.lastSave = memoryAudit.last_save || parsed.state?.last_save || undefined;
2360
2382
  summary.loadedSections = cleanContextValue({
2361
2383
  conversation: Boolean(parsed.conversation),
2362
2384
  summary: Boolean(parsed.summary),
@@ -2367,6 +2389,7 @@ const summarizeMemoryMessagesForSideChannel = (messages = []) => {
2367
2389
  memoryCompression: Boolean(parsed.memoryCompression),
2368
2390
  operationalState: Boolean(parsed.operationalState),
2369
2391
  actionLedger: Array.isArray(parsed.actionLedger),
2392
+ memoryAudit: Boolean(memoryAudit && Object.keys(memoryAudit).length),
2370
2393
  entityTimeline: Array.isArray(parsed.entityTimeline),
2371
2394
  vectorMemories: Array.isArray(parsed.vectorMemories),
2372
2395
  graph: Array.isArray(parsed.graph),
@@ -2510,6 +2533,18 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
2510
2533
  value: adv.includeWorkingMemory === false ? null : compactWorkingMemoryForAgent(workingMemory || {}),
2511
2534
  why_null: adv.includeWorkingMemory === false ? 'working memory disabled' : undefined,
2512
2535
  });
2536
+ sections.push({
2537
+ section: 'decision_state',
2538
+ title: 'Decision state',
2539
+ value: adv.includeDecisionState === false ? null : compactDecisionStateForAgent(decisionState || {}),
2540
+ why_null: adv.includeDecisionState === false ? 'decision state disabled' : undefined,
2541
+ });
2542
+ sections.push({
2543
+ section: 'operational_state',
2544
+ title: 'Operational state',
2545
+ value: adv.includeOperationalState === false ? null : compactOperationalStateForAgent(operationalState || {}),
2546
+ why_null: adv.includeOperationalState === false ? 'operational state disabled' : undefined,
2547
+ });
2513
2548
  sections.push({
2514
2549
  section: 'tool_ledger',
2515
2550
  title: 'Tool ledger',
@@ -2518,12 +2553,29 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
2518
2553
  items: adv.includeToolHistory === false ? [] : compactToolHistoryForAgent(toolHistory, adv.toolHistoryLastN || 6, adv.includeToolResults !== false),
2519
2554
  },
2520
2555
  });
2556
+ sections.push({
2557
+ section: 'action_ledger',
2558
+ title: 'Action ledger',
2559
+ value: adv.includeActionLedger === false ? null : compactActionLedgerForAgent(actionLedger || [], adv.actionLedgerMaxItems || adv.toolHistoryLastN || 8, adv.includeToolResults !== false),
2560
+ why_null: adv.includeActionLedger === false ? 'action ledger disabled' : undefined,
2561
+ });
2562
+ sections.push({
2563
+ section: 'memory_compression',
2564
+ title: 'Memory compression',
2565
+ value: adv.includeMemoryCompression === false ? null : compactMemoryCompressionForAgent(memoryCompression || {}),
2566
+ why_null: adv.includeMemoryCompression === false ? 'memory compression disabled' : undefined,
2567
+ });
2521
2568
  sections.push({
2522
2569
  section: 'profile_facts',
2523
2570
  title: 'Profile facts',
2524
2571
  value: adv.includeProfileFacts === false ? null : renderProfileFacts(profileFacts),
2525
2572
  why_null: adv.includeProfileFacts === false ? 'profile facts disabled' : undefined,
2526
2573
  });
2574
+ sections.push({
2575
+ section: 'memory_audit',
2576
+ title: 'Memory audit',
2577
+ value: compactSaveAuditForAgent((diagnostics || {}).captureState || {}),
2578
+ });
2527
2579
  sections.push({
2528
2580
  section: 'next_action',
2529
2581
  title: 'Next action',
@@ -2552,8 +2604,11 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
2552
2604
  const slmSummary = sectionValue('connected_model_summary') || sectionValue('active_summary');
2553
2605
  const directive = sectionValue('action_directive');
2554
2606
  const inferredIntent = deriveUserIntentObservation({ query, workingMemory, decisionState, recentMessages });
2607
+ const memoryAudit = sectionValue('memory_audit');
2555
2608
  const minimalState = cleanContextValue({
2556
2609
  next_expected_action: directive ? undefined : workingMemory.next_expected_action,
2610
+ context_quality_score: diagnostics?.contextHealth?.quality_score || diagnostics?.quality_score,
2611
+ last_save: memoryAudit?.last_save,
2557
2612
  });
2558
2613
  const compactJson = cleanContextValue({
2559
2614
  kind: 'tembory.agent_context.v1',
@@ -2576,8 +2631,14 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
2576
2631
  slm: hasToolLedger ? undefined : slmSummary,
2577
2632
  },
2578
2633
  state: minimalState,
2634
+ workingMemory: sectionValue('working_memory'),
2635
+ decisionState: sectionValue('decision_state'),
2636
+ operationalState: sectionValue('operational_state'),
2637
+ actionLedger: sectionValue('action_ledger'),
2638
+ memoryCompression: sectionValue('memory_compression'),
2579
2639
  profile: sectionValue('profile_facts'),
2580
2640
  tools: compactToolLedger,
2641
+ memoryAudit,
2581
2642
  });
2582
2643
  const renderCompactSection = (section) => {
2583
2644
  if (section.value === null || section.value === undefined)
@@ -2678,6 +2739,11 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
2678
2739
  value: adv.includeMemoryCompression === false ? null : (compactStateSections ? compactMemoryCompressionForAgent(memoryCompression || {}) : (memoryCompression || {})),
2679
2740
  why_null: adv.includeMemoryCompression === false ? 'memory compression disabled' : undefined,
2680
2741
  });
2742
+ sections.push({
2743
+ section: 'memory_audit',
2744
+ title: 'Memory audit',
2745
+ value: compactSaveAuditForAgent((diagnostics || {}).captureState || {}),
2746
+ });
2681
2747
  sections.push({
2682
2748
  section: 'graph',
2683
2749
  title: 'Graph',
@@ -3096,10 +3162,17 @@ class TemboryMemory {
3096
3162
  const rawOutput = pickText(outputValues, ['output', 'response', 'text', 'answer']);
3097
3163
  const output = cleanAssistantTranscriptText(rawOutput);
3098
3164
  const toolCalls = extractToolCalls(outputValues);
3165
+ const saveAt = nowIso();
3099
3166
  store.captureState[key] = {
3100
- last_save_at: nowIso(),
3167
+ last_save_status: 'started',
3168
+ last_save_saved: false,
3169
+ last_save_at: saveAt,
3101
3170
  last_save_had_input: Boolean(input),
3102
3171
  last_save_had_output: Boolean(output),
3172
+ last_save_input_chars: input.length,
3173
+ last_save_output_chars: output.length,
3174
+ last_save_input_preview: input ? truncate(input, 500) : undefined,
3175
+ last_save_output_preview: output ? truncate(output, 700) : undefined,
3103
3176
  last_save_tool_calls_captured: toolCalls.length,
3104
3177
  last_save_tool_names: toolCalls.map((tool) => tool.name).filter(Boolean).slice(0, 20),
3105
3178
  last_save_capture_sources: Array.from(new Set(toolCalls.map((tool) => tool.source).filter(Boolean))),
@@ -3191,7 +3264,7 @@ class TemboryMemory {
3191
3264
  body.app_id = String(adv.appId);
3192
3265
  if (adv.runId)
3193
3266
  body.run_id = String(adv.runId);
3194
- await saveThreadState(this, key, threadId, project, {
3267
+ const threadStateSaved = await saveThreadState(this, key, threadId, project, {
3195
3268
  kind: 'tembory.thread_state.v1',
3196
3269
  threadId,
3197
3270
  project: project || undefined,
@@ -3205,6 +3278,24 @@ class TemboryMemory {
3205
3278
  operationalState: operationalStateForTurn,
3206
3279
  activeSummary: store.activeSummary[key] || '',
3207
3280
  });
3281
+ store.captureState[key] = cleanContextValue({
3282
+ ...(store.captureState[key] || {}),
3283
+ last_save_status: 'saved',
3284
+ last_save_saved: true,
3285
+ last_save_conversation_messages_after_save: recentForTurn.length,
3286
+ last_save_tool_history_after_save: toolHistoryForTurn.length,
3287
+ last_save_thread_state_saved: threadStateSaved,
3288
+ last_save_backend_memory_persistence: adv.persistBackendMemories === false
3289
+ ? 'disabled'
3290
+ : adv.useVectorMemory === false
3291
+ ? 'thread_state_only'
3292
+ : 'enabled',
3293
+ });
3294
+ try {
3295
+ const globalData = this.getWorkflowStaticData('global');
3296
+ globalData.__dataChanged = true;
3297
+ }
3298
+ catch { }
3208
3299
  if (adv.persistBackendMemories === false)
3209
3300
  return;
3210
3301
  if (adv.useVectorMemory === false)
@@ -3896,12 +3987,20 @@ class TemboryMemory {
3896
3987
  vectorMemoryEnabled,
3897
3988
  backendPersistenceEnabled,
3898
3989
  captureState: store.captureState[key] || {
3990
+ last_save_status: null,
3991
+ last_save_saved: false,
3899
3992
  last_save_at: null,
3900
3993
  last_save_had_input: false,
3901
3994
  last_save_had_output: false,
3995
+ last_save_input_chars: 0,
3996
+ last_save_output_chars: 0,
3902
3997
  last_save_tool_calls_captured: 0,
3903
3998
  last_save_tool_names: [],
3904
3999
  last_save_capture_sources: [],
4000
+ last_save_conversation_messages_after_save: 0,
4001
+ last_save_tool_history_after_save: 0,
4002
+ last_save_thread_state_saved: false,
4003
+ last_save_backend_memory_persistence: backendPersistenceEnabled ? 'enabled' : 'disabled',
3905
4004
  },
3906
4005
  connectedAi,
3907
4006
  activeSummary: summaryDiagnostics,
@@ -3918,6 +4017,7 @@ class TemboryMemory {
3918
4017
  operationalState,
3919
4018
  diagnostics,
3920
4019
  });
4020
+ diagnostics.contextHealth = contextHealth;
3921
4021
  store.workingMemory[key] = workingMemory;
3922
4022
  store.decisionState[key] = decisionState;
3923
4023
  store.memoryCompression[key] = memoryCompression;
@@ -4187,6 +4287,7 @@ exports.__private = {
4187
4287
  compactVectorMemoriesForAgent,
4188
4288
  isConversationEchoMemory,
4189
4289
  compactOperationalStateForAgent,
4290
+ compactSaveAuditForAgent,
4190
4291
  activeSummaryIsFresh,
4191
4292
  readActiveSummary,
4192
4293
  writeActiveSummary,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-tembory",
3
- "version": "1.1.21",
3
+ "version": "1.1.22",
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",