n8n-nodes-tembory 1.1.27 → 1.1.29

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.
@@ -153,38 +153,39 @@ const currentInputJsonFromContext = (ctx, itemIndex = 0) => {
153
153
  return {};
154
154
  }
155
155
  };
156
- const resolveCurrentTurnQuery = (ctx, itemIndex = 0, inputValues = {}, queryParam = '') => {
156
+ const resolveCurrentTurnQueryWithSource = (ctx, itemIndex = 0, inputValues = {}, queryParam = '') => {
157
157
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
158
158
  const inputJson = currentInputJsonFromContext(ctx, itemIndex);
159
159
  const candidates = [
160
- queryParam,
161
- inputValues.query,
162
- inputValues.input,
163
- inputValues.chatInput,
164
- inputValues.text,
165
- inputValues.question,
166
- inputValues.message,
167
- inputJson.query,
168
- inputJson.lastUserMessage,
169
- inputJson.chatInput,
170
- inputJson.input,
171
- inputJson.text,
172
- inputJson.message,
173
- (_a = inputJson.body) === null || _a === void 0 ? void 0 : _a.consolidated_text,
174
- (_b = inputJson.body) === null || _b === void 0 ? void 0 : _b.chatInput,
175
- (_c = inputJson.body) === null || _c === void 0 ? void 0 : _c.message,
176
- (_d = inputJson.body) === null || _d === void 0 ? void 0 : _d.text,
177
- (_e = inputJson.body) === null || _e === void 0 ? void 0 : _e.input,
178
- (_h = (_g = (_f = inputJson.body) === null || _f === void 0 ? void 0 : _f.messages) === null || _g === void 0 ? void 0 : _g[0]) === null || _h === void 0 ? void 0 : _h.text,
179
- (_k = (_j = inputJson.body) === null || _j === void 0 ? void 0 : _j.messages) === null || _k === void 0 ? void 0 : _k[0],
160
+ ['query_param', queryParam],
161
+ ['input_values.query', inputValues.query],
162
+ ['input_values.input', inputValues.input],
163
+ ['input_values.chatInput', inputValues.chatInput],
164
+ ['input_values.text', inputValues.text],
165
+ ['input_values.question', inputValues.question],
166
+ ['input_values.message', inputValues.message],
167
+ ['input_json.query', inputJson.query],
168
+ ['input_json.lastUserMessage', inputJson.lastUserMessage],
169
+ ['input_json.chatInput', inputJson.chatInput],
170
+ ['input_json.input', inputJson.input],
171
+ ['input_json.text', inputJson.text],
172
+ ['input_json.message', inputJson.message],
173
+ ['input_json.body.consolidated_text', (_a = inputJson.body) === null || _a === void 0 ? void 0 : _a.consolidated_text],
174
+ ['input_json.body.chatInput', (_b = inputJson.body) === null || _b === void 0 ? void 0 : _b.chatInput],
175
+ ['input_json.body.message', (_c = inputJson.body) === null || _c === void 0 ? void 0 : _c.message],
176
+ ['input_json.body.text', (_d = inputJson.body) === null || _d === void 0 ? void 0 : _d.text],
177
+ ['input_json.body.input', (_e = inputJson.body) === null || _e === void 0 ? void 0 : _e.input],
178
+ ['input_json.body.messages.0.text', (_h = (_g = (_f = inputJson.body) === null || _f === void 0 ? void 0 : _f.messages) === null || _g === void 0 ? void 0 : _g[0]) === null || _h === void 0 ? void 0 : _h.text],
179
+ ['input_json.body.messages.0', (_k = (_j = inputJson.body) === null || _j === void 0 ? void 0 : _j.messages) === null || _k === void 0 ? void 0 : _k[0]],
180
180
  ];
181
- for (const candidate of candidates) {
181
+ for (const [source, candidate] of candidates) {
182
182
  const query = asSearchQuery(candidate).trim();
183
183
  if (query)
184
- return stripThreadTestPrefix(query);
184
+ return { query: stripThreadTestPrefix(query), source };
185
185
  }
186
- return '';
186
+ return { query: '', source: 'missing' };
187
187
  };
188
+ const resolveCurrentTurnQuery = (ctx, itemIndex = 0, inputValues = {}, queryParam = '') => resolveCurrentTurnQueryWithSource(ctx, itemIndex, inputValues, queryParam).query;
188
189
  const memoryText = (memory) => {
189
190
  if (!memory)
190
191
  return '';
@@ -1838,6 +1839,12 @@ const isOperationalStatusQuery = (value = '') => {
1838
1839
  || /\b(tools?|ferramentas?|apis?|a[cç][oõ]es?|chamadas?|executadas?|usadas?)\b.{0,80}\b(quais?|qual|lista|mostra|resume|status|estado|historico|hist[oó]rico|outputs?|retornos?|resultado|resultados?)\b/.test(text)
1839
1840
  || /\b(ja|ainda|tinha|tenho|foi|esta|ta)\b.{0,60}\b(feito|feita|executad\w*|chamad\w*|concluid\w*|confirm\w*|criad\w*|atualizad\w*|agend\w*|agned\w*|ganed\w*|marc\w*|reserv\w*)\b/.test(text);
1840
1841
  };
1842
+ const hasNoToolRequested = (value = '') => {
1843
+ const text = normalizeIntentText(value);
1844
+ return /\b(nao|nunca|sem)\b.{0,30}\b(chame|chamar|use|usar|execute|executar|rode|rodar)\b.{0,30}\b(tools?|ferramentas?|apis?)\b/.test(text)
1845
+ || /\b(nao|nunca|sem)\b.{0,30}\b(tools?|ferramentas?|apis?)\b/.test(text)
1846
+ || /\b(responda|responder)\b.{0,40}\b(sem)\b.{0,20}\b(tools?|ferramentas?|apis?)\b/.test(text);
1847
+ };
1841
1848
  const recentUserMessages = (recentMessages = []) => [...(recentMessages || [])]
1842
1849
  .filter((msg) => /^(user|human)$/i.test(String(msg.role || '')))
1843
1850
  .reverse();
@@ -2078,6 +2085,8 @@ const deriveWorkingMemory = ({ query = '', profileFacts = {}, recentMessages = [
2078
2085
  const currentGoal = carryPreviousGoal ? previous.current_goal : nextExpectedAction;
2079
2086
  const toolNames = Array.from(new Set((toolHistory || []).map((tool) => tool.name || tool.tool_name || tool.tool).filter(Boolean)));
2080
2087
  const currentTurnMayNeedTool = ['affirm', 'commit_or_continue', 'tool_action_candidate', 'selection_or_slot'].includes(intent);
2088
+ const noToolRequested = hasNoToolRequested(query);
2089
+ const recallOnly = intent === 'conversation_recall' || (intent === 'operational_status_question' && noToolRequested);
2081
2090
  return {
2082
2091
  current_goal: currentGoal,
2083
2092
  current_goal_reason: carryPreviousGoal ? 'carried_from_previous_non_generic_goal' : 'derived_from_current_turn_intent',
@@ -2105,8 +2114,9 @@ const deriveWorkingMemory = ({ query = '', profileFacts = {}, recentMessages = [
2105
2114
  failed_by_name: toolState.failed_by_name,
2106
2115
  }),
2107
2116
  turn_flags: cleanContextValue({
2108
- recall_only: intent === 'conversation_recall',
2117
+ recall_only: recallOnly,
2109
2118
  status_question: intent === 'operational_status_question',
2119
+ no_tool_requested: noToolRequested,
2110
2120
  current_turn_may_need_tool: currentTurnMayNeedTool,
2111
2121
  has_prior_tools: Array.isArray(toolHistory) && toolHistory.length > 0,
2112
2122
  has_profile_facts: activeEntities.length > 0,
@@ -2364,6 +2374,67 @@ const compactToolResult = (result, max = 360) => {
2364
2374
  return truncate(safeStringify(picked), max);
2365
2375
  return truncate(text, max);
2366
2376
  };
2377
+ const tryParseJsonValue = (value) => {
2378
+ if (value === undefined || value === null || value === '')
2379
+ return undefined;
2380
+ if (typeof value === 'object')
2381
+ return value;
2382
+ if (typeof value !== 'string')
2383
+ return undefined;
2384
+ try {
2385
+ return JSON.parse(value);
2386
+ }
2387
+ catch {
2388
+ return undefined;
2389
+ }
2390
+ };
2391
+ const normalizeToolResultEnvelope = (value) => {
2392
+ const parsed = tryParseJsonValue(value);
2393
+ if (Array.isArray(parsed)) {
2394
+ const responses = parsed
2395
+ .map((item) => normalizeToolResultEnvelope(item))
2396
+ .filter((item) => item !== undefined && item !== null);
2397
+ if (responses.length === 1)
2398
+ return responses[0];
2399
+ return responses.length ? responses : parsed;
2400
+ }
2401
+ if (!parsed || typeof parsed !== 'object')
2402
+ return parsed;
2403
+ if (typeof parsed.response === 'string') {
2404
+ const nested = normalizeToolResultEnvelope(parsed.response);
2405
+ if (nested !== undefined)
2406
+ return nested;
2407
+ }
2408
+ if (parsed.response && typeof parsed.response === 'object')
2409
+ return normalizeToolResultEnvelope(parsed.response);
2410
+ return parsed;
2411
+ };
2412
+ const compactParsedToolOutputForSideChannel = (parsed) => {
2413
+ if (parsed === undefined || parsed === null)
2414
+ return undefined;
2415
+ if (Array.isArray(parsed))
2416
+ return cleanContextValue(parsed.map((item) => compactParsedToolOutputForSideChannel(item)));
2417
+ if (typeof parsed !== 'object')
2418
+ return parsed;
2419
+ if (parsed.output !== undefined)
2420
+ return cleanContextValue(stripNoisyToolFields(parsed.output));
2421
+ return cleanContextValue(stripNoisyToolFields(parsed));
2422
+ };
2423
+ const toolResultTimestampFromParsed = (parsed) => {
2424
+ if (!parsed)
2425
+ return undefined;
2426
+ if (Array.isArray(parsed)) {
2427
+ for (const item of parsed) {
2428
+ const found = toolResultTimestampFromParsed(item);
2429
+ if (found)
2430
+ return found;
2431
+ }
2432
+ return undefined;
2433
+ }
2434
+ if (typeof parsed !== 'object')
2435
+ return undefined;
2436
+ return parsed.timestamp || parsed.at || parsed.output?.timestamp;
2437
+ };
2367
2438
  const compactToolHistoryForAgent = (toolHistory = [], maxItems = 6, includeResults = true) => pruneByLimit(toolHistory || [], maxItems).map((tool) => ({
2368
2439
  name: tool.name,
2369
2440
  status: tool.ok === false ? 'failed' : 'ok',
@@ -2620,14 +2691,23 @@ const invokeConnectedModelSummary = async (connectedLanguageModel, summaryInput,
2620
2691
  ]);
2621
2692
  return cleanModelSummaryText(response, Number(adv.connectedModelSummaryMaxChars || 1200));
2622
2693
  };
2623
- const compactToolAuditForSideChannel = (tool = {}) => cleanContextValue({
2624
- name: tool.name || tool.tool_name || tool.tool,
2625
- status: tool.status || (tool.ok === false ? 'failed' : 'ok'),
2626
- at: tool.at || tool.timestamp,
2627
- timestamp: tool.timestamp || tool.at,
2628
- input: truncate(String(tool.input || tool.tool_args || tool.normalized_args || ''), 500) || undefined,
2629
- output: compactToolResult(tool.result !== undefined ? tool.result : tool.output !== undefined ? tool.output : tool.observation, 1200),
2630
- });
2694
+ const compactToolAuditForSideChannel = (tool = {}) => {
2695
+ const capturedAt = tool.at || tool.timestamp;
2696
+ const rawResult = tool.result !== undefined ? tool.result : tool.output !== undefined ? tool.output : tool.observation;
2697
+ const parsedResult = normalizeToolResultEnvelope(rawResult);
2698
+ return cleanContextValue({
2699
+ name: tool.name || tool.tool_name || tool.tool,
2700
+ status: tool.status || (tool.ok === false ? 'failed' : 'ok'),
2701
+ at: capturedAt,
2702
+ timestamp: capturedAt,
2703
+ capturedAt,
2704
+ toolTimestamp: toolResultTimestampFromParsed(parsedResult),
2705
+ toolStatus: parsedResult && typeof parsedResult === 'object' && !Array.isArray(parsedResult) ? parsedResult.status : undefined,
2706
+ input: truncate(String(tool.input || tool.tool_args || tool.normalized_args || ''), 300) || undefined,
2707
+ output: compactToolResult(rawResult, 800),
2708
+ outputParsed: compactParsedToolOutputForSideChannel(parsedResult),
2709
+ });
2710
+ };
2631
2711
  const compactMessageForSideChannel = (message = {}) => {
2632
2712
  const type = messageTypeOf(message) || String(message.role || 'message').toLowerCase();
2633
2713
  const role = type === 'human' ? 'user' : type === 'ai' ? 'assistant' : type || 'message';
@@ -2650,7 +2730,7 @@ const normalizeConversationRoleForSideChannel = (role = '') => {
2650
2730
  return 'tool';
2651
2731
  return normalized || 'message';
2652
2732
  };
2653
- const compactConversationTimelineForSideChannel = (conversation = {}, maxItems = 12) => {
2733
+ const compactConversationTimelineForSideChannel = (conversation = {}, maxItems = 4, includeFull = false) => {
2654
2734
  const chronological = Array.isArray(conversation.conversation_history_chronological)
2655
2735
  ? conversation.conversation_history_chronological
2656
2736
  : [];
@@ -2666,13 +2746,12 @@ const compactConversationTimelineForSideChannel = (conversation = {}, maxItems =
2666
2746
  at,
2667
2747
  chars: content.length,
2668
2748
  preview,
2669
- content: preview,
2670
- message: {
2749
+ message: includeFull ? {
2671
2750
  role,
2672
2751
  at,
2673
2752
  content: role === 'system' ? '[system context hidden]' : truncate(content, 2000),
2674
2753
  truncated: content.length > 2000,
2675
- },
2754
+ } : undefined,
2676
2755
  });
2677
2756
  });
2678
2757
  };
@@ -2702,11 +2781,11 @@ const compactMemoryEventPayload = (payload = {}) => {
2702
2781
  compact.toolNames = compact.toolCalls
2703
2782
  .map((tool) => (tool && (tool.name || tool.tool_name || tool.tool)) || '')
2704
2783
  .filter(Boolean)
2705
- .slice(0, 20);
2784
+ .slice(0, 12);
2706
2785
  compact.toolEvents = compact.toolCalls
2707
2786
  .map((tool) => compactToolAuditForSideChannel(tool || {}))
2708
2787
  .filter((tool) => tool && Object.keys(tool).length)
2709
- .slice(0, 20);
2788
+ .slice(0, 8);
2710
2789
  delete compact.toolCalls;
2711
2790
  }
2712
2791
  for (const key of ['input', 'output', 'values', 'chatHistory', 'context', 'contextText', 'diagnostics']) {
@@ -2716,6 +2795,49 @@ const compactMemoryEventPayload = (payload = {}) => {
2716
2795
  }
2717
2796
  return compact;
2718
2797
  };
2798
+ const compactLastSaveForSideChannel = (lastSave = {}) => cleanContextValue({
2799
+ saved: lastSave.saved,
2800
+ status: lastSave.status,
2801
+ at: lastSave.at,
2802
+ inputChars: lastSave.input_chars,
2803
+ outputChars: lastSave.output_chars,
2804
+ toolCallsCaptured: lastSave.tool_calls_captured,
2805
+ toolNames: lastSave.tool_names,
2806
+ conversationMessagesAfterSave: lastSave.conversation_messages_after_save,
2807
+ toolHistoryAfterSave: lastSave.tool_history_after_save,
2808
+ threadStateSaved: lastSave.thread_state_saved,
2809
+ backendPersistence: lastSave.backend_memory_persistence,
2810
+ });
2811
+ const compactDedupeForSideChannel = (dedupe = {}) => {
2812
+ const load = dedupe.load || {};
2813
+ const removedOnLoad = Object.values(load).reduce((sum, item) => sum + Number((item || {}).removed || 0), 0);
2814
+ const write = dedupe.lastSave?.write || dedupe.write || {};
2815
+ return cleanContextValue({
2816
+ enabled: dedupe.enabled,
2817
+ removedOnLoad,
2818
+ skippedWrites: Number(write.skipped || 0),
2819
+ persistedWrites: Number(write.persisted || 0),
2820
+ candidates: Number(write.candidates || 0),
2821
+ });
2822
+ };
2823
+ const loadedSectionsForSideChannel = (parsed = {}, memoryAudit = {}) => cleanContextValue({
2824
+ conversation: Boolean(parsed.conversation),
2825
+ summary: Boolean(parsed.summary),
2826
+ activeSummary: Boolean(parsed.activeSummary),
2827
+ connectedModelSummary: Boolean(parsed.connectedModelSummary),
2828
+ workingMemory: Boolean(parsed.workingMemory),
2829
+ decisionState: Boolean(parsed.decisionState),
2830
+ memoryCompression: Boolean(parsed.memoryCompression),
2831
+ operationalState: Boolean(parsed.operationalState),
2832
+ actionLedger: Array.isArray(parsed.actionLedger),
2833
+ turnBrief: Boolean(parsed.turnBrief || parsed.turn_brief),
2834
+ memoryAudit: Boolean(memoryAudit && Object.keys(memoryAudit).length),
2835
+ entityTimeline: Array.isArray(parsed.entityTimeline),
2836
+ vectorMemories: Array.isArray(parsed.vectorMemories),
2837
+ graph: Array.isArray(parsed.graph),
2838
+ recentHighlights: Array.isArray(parsed.recentHighlights),
2839
+ contextHealth: Boolean(parsed.contextHealth),
2840
+ });
2719
2841
  const summarizeMemoryMessagesForSideChannel = (messages = []) => {
2720
2842
  const list = Array.isArray(messages) ? messages : [];
2721
2843
  const summary = { messages: list.length };
@@ -2732,20 +2854,45 @@ const summarizeMemoryMessagesForSideChannel = (messages = []) => {
2732
2854
  const toolItems = Array.isArray(tools.items) ? tools.items : [];
2733
2855
  const memoryAudit = parsed.memoryAudit || parsed.memory_audit || {};
2734
2856
  const summaryText = parsed.summary?.slm || parsed.summary || parsed.connectedModelSummary || parsed.activeSummary || '';
2857
+ const chronological = Array.isArray(conversation.conversation_history_chronological)
2858
+ ? conversation.conversation_history_chronological
2859
+ : [];
2860
+ const allUserMessages = Array.isArray(conversation.all_user_messages_chronological)
2861
+ ? conversation.all_user_messages_chronological
2862
+ : chronological.filter((message) => normalizeConversationRoleForSideChannel(message.role || message.type) === 'user');
2863
+ const lastUser = [...chronological].reverse().find((message) => normalizeConversationRoleForSideChannel(message.role || message.type) === 'user');
2864
+ const lastAgent = [...chronological].reverse().find((message) => normalizeConversationRoleForSideChannel(message.role || message.type) === 'agent');
2865
+ const includeDebug = Boolean(parsed.options?.includeDiagnostics || parsed.diagnostics?.includeDiagnostics || parsed.diagnostics?.include_diagnostics);
2866
+ const lastSave = compactLastSaveForSideChannel(memoryAudit.last_save || parsed.state?.last_save || {});
2867
+ const fullDedupeSummary = parsed.dedupeSummary || parsed.diagnostics?.dedupeSummary || undefined;
2868
+ const loadedSections = loadedSectionsForSideChannel(parsed, memoryAudit);
2735
2869
  summary.userId = parsed.userId;
2736
2870
  summary.project = parsed.project || undefined;
2737
2871
  summary.retrievalMode = parsed.retrievalMode;
2738
2872
  summary.payloadFormat = parsed.payloadFormat;
2739
- summary.options = cleanContextValue(parsed.options || {});
2740
2873
  summary.intent = parsed.observations?.inferred_intent?.label || parsed.workingMemory?.last_user_intent || parsed.decisionState?.current_intent || undefined;
2741
2874
  const parsedTurnBrief = parsed.turnBrief || parsed.turn_brief || undefined;
2875
+ summary.currentTurn = parsed.currentTurn || parsed.current_turn || parsed.diagnostics?.currentTurn || undefined;
2742
2876
  summary.currentUserMessage = conversation.current_user_message ? truncate(conversation.current_user_message, 180) : undefined;
2743
- summary.recentMessages = Array.isArray(conversation.conversation_history_chronological) ? conversation.conversation_history_chronological.length : undefined;
2744
- summary.conversationTimeline = compactConversationTimelineForSideChannel(conversation, 12);
2877
+ summary.recentMessages = chronological.length || undefined;
2878
+ summary.conversation = cleanContextValue({
2879
+ messages: chronological.length,
2880
+ userMessages: allUserMessages.length,
2881
+ currentUserMessage: summary.currentUserMessage,
2882
+ lastUser: lastUser ? {
2883
+ at: lastUser.at || lastUser.timestamp || lastUser.created_at || lastUser.createdAt,
2884
+ preview: truncate(String(lastUser.content || lastUser.text || lastUser.message || ''), 240),
2885
+ } : undefined,
2886
+ lastAgent: lastAgent ? {
2887
+ at: lastAgent.at || lastAgent.timestamp || lastAgent.created_at || lastAgent.createdAt,
2888
+ preview: truncate(String(lastAgent.content || lastAgent.text || lastAgent.message || ''), 240),
2889
+ } : undefined,
2890
+ });
2891
+ summary.conversationTimeline = compactConversationTimelineForSideChannel(conversation, 4);
2745
2892
  summary.toolCount = toolItems.length || tools.count || parsed.operationalState?.tool_counts?.total || undefined;
2746
- summary.toolNames = toolItems.map((tool) => tool.name || tool.tool_name).filter(Boolean).slice(0, 20);
2893
+ summary.toolNames = toolItems.map((tool) => tool.name || tool.tool_name).filter(Boolean).slice(0, 12);
2747
2894
  summary.toolEvents = toolItems
2748
- .slice(-6)
2895
+ .slice(-3)
2749
2896
  .map((tool) => compactToolAuditForSideChannel(tool || {}))
2750
2897
  .filter((tool) => tool && Object.keys(tool).length);
2751
2898
  summary.lastTool = tools.last_successful_tool
@@ -2765,8 +2912,8 @@ const summarizeMemoryMessagesForSideChannel = (messages = []) => {
2765
2912
  })
2766
2913
  : parsedTurnBrief;
2767
2914
  summary.counts = cleanContextValue({
2768
- conversationMessages: Array.isArray(conversation.conversation_history_chronological) ? conversation.conversation_history_chronological.length : undefined,
2769
- userMessages: Array.isArray(conversation.all_user_messages_chronological) ? conversation.all_user_messages_chronological.length : undefined,
2915
+ conversationMessages: chronological.length || undefined,
2916
+ userMessages: allUserMessages.length || undefined,
2770
2917
  toolHistory: toolItems.length,
2771
2918
  actionLedger: Array.isArray(parsed.actionLedger) ? parsed.actionLedger.length : undefined,
2772
2919
  entityTimeline: Array.isArray(parsed.entityTimeline) ? parsed.entityTimeline.length : undefined,
@@ -2774,26 +2921,8 @@ const summarizeMemoryMessagesForSideChannel = (messages = []) => {
2774
2921
  graph: Array.isArray(parsed.graph) ? parsed.graph.length : undefined,
2775
2922
  recentHighlights: Array.isArray(parsed.recentHighlights) ? parsed.recentHighlights.length : undefined,
2776
2923
  });
2777
- summary.lastSave = memoryAudit.last_save || parsed.state?.last_save || undefined;
2778
- summary.dedupeSummary = parsed.dedupeSummary || parsed.diagnostics?.dedupeSummary || undefined;
2779
- summary.loadedSections = cleanContextValue({
2780
- conversation: Boolean(parsed.conversation),
2781
- summary: Boolean(parsed.summary),
2782
- activeSummary: Boolean(parsed.activeSummary),
2783
- connectedModelSummary: Boolean(parsed.connectedModelSummary),
2784
- workingMemory: Boolean(parsed.workingMemory),
2785
- decisionState: Boolean(parsed.decisionState),
2786
- memoryCompression: Boolean(parsed.memoryCompression),
2787
- operationalState: Boolean(parsed.operationalState),
2788
- actionLedger: Array.isArray(parsed.actionLedger),
2789
- turnBrief: Boolean(parsed.turnBrief || parsed.turn_brief),
2790
- memoryAudit: Boolean(memoryAudit && Object.keys(memoryAudit).length),
2791
- entityTimeline: Array.isArray(parsed.entityTimeline),
2792
- vectorMemories: Array.isArray(parsed.vectorMemories),
2793
- graph: Array.isArray(parsed.graph),
2794
- recentHighlights: Array.isArray(parsed.recentHighlights),
2795
- contextHealth: Boolean(parsed.contextHealth),
2796
- });
2924
+ summary.lastSave = Object.keys(lastSave).length ? lastSave : undefined;
2925
+ summary.dedupe = fullDedupeSummary ? compactDedupeForSideChannel(fullDedupeSummary) : undefined;
2797
2926
  summary.workingMemory = cleanContextValue({
2798
2927
  currentGoal: parsed.workingMemory?.current_goal,
2799
2928
  currentGoalReason: parsed.workingMemory?.current_goal_reason,
@@ -2814,8 +2943,14 @@ const summarizeMemoryMessagesForSideChannel = (messages = []) => {
2814
2943
  doNotRepeatTools: parsed.decisionState?.do_not_repeat_tools,
2815
2944
  });
2816
2945
  summary.quality = parsed.contextHealth?.quality_score || parsed.contextQualityScore || undefined;
2817
- summary.contextSize = parsed.diagnostics?.contextSize || undefined;
2818
- summary.summaryChars = typeof summaryText === 'string' ? summaryText.length : safeStringify(summaryText).length;
2946
+ summary.debug = includeDebug ? cleanContextValue({
2947
+ options: parsed.options,
2948
+ loadedSections,
2949
+ contextSize: parsed.diagnostics?.contextSize,
2950
+ summaryChars: typeof summaryText === 'string' ? summaryText.length : safeStringify(summaryText).length,
2951
+ dedupeSummary: fullDedupeSummary,
2952
+ conversationTimelineFull: compactConversationTimelineForSideChannel(conversation, 12, true),
2953
+ }) : undefined;
2819
2954
  return Object.fromEntries(Object.entries(summary).filter(([, value]) => value !== undefined));
2820
2955
  }
2821
2956
  catch {
@@ -3032,6 +3167,7 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
3032
3167
  current_user_request: focus.current_user_request,
3033
3168
  instruction: focus.instruction,
3034
3169
  }),
3170
+ currentTurn: diagnostics?.currentTurn,
3035
3171
  action_directive: directive ? cleanContextValue({
3036
3172
  required_tool: directive.required_tool,
3037
3173
  next_expected_action: directive.next_expected_action,
@@ -4070,7 +4206,8 @@ class TemboryMemory {
4070
4206
  const store = getMemoryStore(this);
4071
4207
  const key = userKeyFrom(threadId, adv, project);
4072
4208
  const queryParam = this.getNodeParameter('query', itemIndex, '');
4073
- const query = resolveCurrentTurnQuery(this, itemIndex, inputValues, queryParam);
4209
+ const currentTurn = resolveCurrentTurnQueryWithSource(this, itemIndex, inputValues, queryParam);
4210
+ const query = currentTurn.query;
4074
4211
  const remoteThreadState = await loadThreadState(this, key, threadId, project);
4075
4212
  mergeRemoteThreadState(store, key, remoteThreadState);
4076
4213
  let connectedLanguageModel;
@@ -4099,6 +4236,7 @@ class TemboryMemory {
4099
4236
  retrievalMode,
4100
4237
  requestedRetrievalMode,
4101
4238
  hasQuery: String(query || '').trim().length > 0,
4239
+ querySource: currentTurn.source,
4102
4240
  connectedAi,
4103
4241
  });
4104
4242
  }
@@ -4542,6 +4680,7 @@ class TemboryMemory {
4542
4680
  connectedAi,
4543
4681
  activeSummary: summaryDiagnostics,
4544
4682
  dedupeSummary: cleanContextValue(loadDedupeSummary),
4683
+ currentTurn,
4545
4684
  };
4546
4685
  const contextHealth = deriveContextHealth({
4547
4686
  userId: key,
@@ -4613,6 +4752,7 @@ class TemboryMemory {
4613
4752
  userId: key,
4614
4753
  project: project || undefined,
4615
4754
  query,
4755
+ currentTurn,
4616
4756
  retrievalMode,
4617
4757
  requestedRetrievalMode: requestedRetrievalMode === retrievalMode ? undefined : requestedRetrievalMode,
4618
4758
  payloadFormat,
@@ -4798,6 +4938,7 @@ exports.__private = {
4798
4938
  flattenAdvancedGroups,
4799
4939
  asSearchQuery,
4800
4940
  currentInputJsonFromContext,
4941
+ resolveCurrentTurnQueryWithSource,
4801
4942
  resolveCurrentTurnQuery,
4802
4943
  safePersistLegacyMemory,
4803
4944
  stripThreadTestPrefix,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-tembory",
3
- "version": "1.1.27",
3
+ "version": "1.1.29",
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",