n8n-nodes-tembory 1.1.24 → 1.1.26
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.
|
@@ -1723,6 +1723,56 @@ const buildCurrentTurnFocus = ({ query = '', recentMessages = [], operationalSta
|
|
|
1723
1723
|
});
|
|
1724
1724
|
return focus;
|
|
1725
1725
|
};
|
|
1726
|
+
const turnBriefGuidanceForIntent = (intent = '') => {
|
|
1727
|
+
if (intent === 'conversation_recall')
|
|
1728
|
+
return 'Answer from the chronological conversation frame. Do not call tools for recall-only requests.';
|
|
1729
|
+
if (intent === 'operational_status_question')
|
|
1730
|
+
return 'Answer from tool_state, tool_history and action_ledger. Do not call tools just to inspect prior calls.';
|
|
1731
|
+
if (['tool_action_candidate', 'selection_or_slot', 'affirm', 'commit_or_continue'].includes(intent))
|
|
1732
|
+
return 'May require a tool. Use prompt policy. Prior tools are evidence only; do not claim new side effects without a current required tool call.';
|
|
1733
|
+
if (intent === 'profile_update')
|
|
1734
|
+
return 'Likely stable profile data. Save useful facts and continue; call tools only when prompt requires.';
|
|
1735
|
+
return 'Continue according to the agent prompt using conversation, tool history and operational state as read-only context.';
|
|
1736
|
+
};
|
|
1737
|
+
const buildTurnBriefForAgent = ({ query = '', recentMessages = [], toolHistory = [], operationalState = {}, workingMemory = {}, decisionState = {}, diagnostics = {} }) => {
|
|
1738
|
+
const currentIntent = (decisionState || {}).current_intent || (workingMemory || {}).last_user_intent || inferUserIntent(query, recentMessages);
|
|
1739
|
+
const toolState = (operationalState || {}).tool_state || {};
|
|
1740
|
+
const lastTool = (toolState.last_successful_tool || (operationalState || {}).last_tool || (Array.isArray(toolHistory) && toolHistory.length ? toolHistory[toolHistory.length - 1] : null));
|
|
1741
|
+
const toolNames = Array.from(new Set([]
|
|
1742
|
+
.concat(toolState.names || [])
|
|
1743
|
+
.concat((Array.isArray(toolHistory) ? toolHistory : []).map((tool) => tool && (tool.name || tool.tool_name || tool.tool)).filter(Boolean))));
|
|
1744
|
+
const userMessages = (recentMessages || []).filter((msg) => /^(user|human)$/i.test(String(msg.role || '')));
|
|
1745
|
+
const lastSave = (diagnostics || {}).captureState || {};
|
|
1746
|
+
return cleanContextValue({
|
|
1747
|
+
current_intent: currentIntent,
|
|
1748
|
+
current_request: truncate(query || ((userMessages[userMessages.length - 1] || {}).content || ''), 300),
|
|
1749
|
+
memory_status: {
|
|
1750
|
+
messages: Array.isArray(recentMessages) ? recentMessages.length : 0,
|
|
1751
|
+
users: userMessages.length,
|
|
1752
|
+
tools: Array.isArray(toolHistory) ? toolHistory.length : 0,
|
|
1753
|
+
last_save_at: lastSave.last_save_at,
|
|
1754
|
+
last_save_tool_calls_captured: lastSave.last_save_tool_calls_captured,
|
|
1755
|
+
},
|
|
1756
|
+
tool_names: toolNames.slice(0, 8),
|
|
1757
|
+
last_tool: lastTool ? {
|
|
1758
|
+
name: lastTool.name || lastTool.tool_name || lastTool.tool,
|
|
1759
|
+
status: lastTool.status || (lastTool.ok === false ? 'failed' : 'ok'),
|
|
1760
|
+
at: lastTool.at || lastTool.timestamp,
|
|
1761
|
+
} : undefined,
|
|
1762
|
+
do_not_repeat_tools: ((decisionState || {}).do_not_repeat_tools || []).slice(0, 12),
|
|
1763
|
+
guidance: turnBriefGuidanceForIntent(currentIntent),
|
|
1764
|
+
});
|
|
1765
|
+
};
|
|
1766
|
+
const compactTurnBriefForAgent = (brief = {}) => {
|
|
1767
|
+
const status = brief.memory_status || {};
|
|
1768
|
+
const parts = [
|
|
1769
|
+
brief.current_intent ? `intent=${brief.current_intent}` : '',
|
|
1770
|
+
brief.current_request ? `request=${truncate(brief.current_request, 80)}` : '',
|
|
1771
|
+
status.tools !== undefined ? `tools=${status.tools}` : '',
|
|
1772
|
+
'prior tools are evidence; new side effects need current tool',
|
|
1773
|
+
].filter(Boolean);
|
|
1774
|
+
return parts.join('; ');
|
|
1775
|
+
};
|
|
1726
1776
|
const SIDE_EFFECT_SAFETY_INSTRUCTION = 'Previous tool calls are evidence only. Never tell the user that a new side-effect action is done, confirmed, booked, created, updated, cancelled, sent, charged, assigned, or executed from memory alone. If the current user turn asks to commit a side-effect and the agent prompt requires a tool, call the appropriate tool in the current turn before saying it is done. Use prior tool outputs only to avoid repeating prerequisite lookup tools and to fill inputs for the required tool call.';
|
|
1727
1777
|
const intentConfidence = (intent = '') => {
|
|
1728
1778
|
if (['conversation_recall', 'operational_status_question'].includes(intent))
|
|
@@ -1789,7 +1839,7 @@ const inferUserIntent = (query = '', recentMessages = []) => {
|
|
|
1789
1839
|
return 'selection_or_slot';
|
|
1790
1840
|
if (hasCommitIntent(text))
|
|
1791
1841
|
return 'commit_or_continue';
|
|
1792
|
-
if (/\b(buscar|busca|criar|cria|atualizar|atualiza|consultar|consulta|reservar|reserva|agendar|agenda|abrir|abre|cancelar|cancela|enviar|envia|gerar|gera|validar|valida|processar|processa|executar|executa)\b/.test(text))
|
|
1842
|
+
if (/\b(buscar|busca|criar|cria|atualizar|atualiza|consultar|consulta|reservar|reserva|agendar|agenda|abrir|abre|cancelar|cancela|enviar|envia|gerar|gera|validar|valida|processar|processa|executar|executa|registrar|registra|salvar|salva|gravar|grava|cadastrar|cadastra|inserir|insere)\b/.test(text))
|
|
1793
1843
|
return 'tool_action_candidate';
|
|
1794
1844
|
if (/\b(meu nome|email|telefone|empresa|prefiro|preferencia)\b/.test(text))
|
|
1795
1845
|
return 'profile_update';
|
|
@@ -1809,21 +1859,73 @@ const deriveNextExpectedAction = (intent, operationalState = {}) => {
|
|
|
1809
1859
|
return 'continue according to the agent prompt using retrieved context; call tools when the agent prompt or tool policy requires them';
|
|
1810
1860
|
};
|
|
1811
1861
|
const isGenericMemoryNextAction = (value = '') => /answer using retrieved context and avoid unnecessary tool calls|continue according to the agent prompt using retrieved context/i.test(String(value || ''));
|
|
1862
|
+
const shouldCarryPreviousGoal = (intent = '', previousGoal = '') => {
|
|
1863
|
+
if (!previousGoal || isGenericMemoryNextAction(previousGoal))
|
|
1864
|
+
return false;
|
|
1865
|
+
return ['general_message', 'profile_update', 'unknown'].includes(intent);
|
|
1866
|
+
};
|
|
1812
1867
|
const deriveWorkingMemory = ({ query = '', profileFacts = {}, recentMessages = [], toolHistory = [], operationalState = {}, previous = {} }) => {
|
|
1813
1868
|
const intent = inferUserIntent(query, recentMessages);
|
|
1814
|
-
const
|
|
1869
|
+
const chronological = sortConversationChronological(recentMessages || []);
|
|
1870
|
+
const userMessages = chronological.filter((msg) => /^(user|human)$/i.test(String(msg.role || '')));
|
|
1871
|
+
const assistantMessages = chronological.filter((msg) => /^(assistant|ai|agent)$/i.test(String(msg.role || '')));
|
|
1872
|
+
const normalizedQuery = normalizeIntentText(query).trim();
|
|
1873
|
+
const lastUser = [...userMessages].reverse().find((msg) => /^(user|human)$/i.test(String(msg.role || '')));
|
|
1874
|
+
const priorUser = [...userMessages].reverse().find((msg) => normalizeIntentText(msg.content).trim() !== normalizedQuery);
|
|
1875
|
+
const lastAssistant = assistantMessages[assistantMessages.length - 1] || null;
|
|
1815
1876
|
const activeEntities = [];
|
|
1816
1877
|
for (const key of ['name', 'company', 'email', 'phone']) {
|
|
1817
1878
|
if (profileFacts && profileFacts[key])
|
|
1818
1879
|
activeEntities.push({ type: key, value: profileFacts[key] });
|
|
1819
1880
|
}
|
|
1820
1881
|
const lastTool = toolHistory && toolHistory.length ? toolHistory[toolHistory.length - 1] : null;
|
|
1882
|
+
const toolState = (operationalState || {}).tool_state || {};
|
|
1821
1883
|
const nextExpectedAction = deriveNextExpectedAction(intent, operationalState);
|
|
1884
|
+
const carryPreviousGoal = shouldCarryPreviousGoal(intent, previous.current_goal);
|
|
1885
|
+
const currentGoal = carryPreviousGoal ? previous.current_goal : nextExpectedAction;
|
|
1886
|
+
const toolNames = Array.from(new Set((toolHistory || []).map((tool) => tool.name || tool.tool_name || tool.tool).filter(Boolean)));
|
|
1887
|
+
const currentTurnMayNeedTool = ['affirm', 'commit_or_continue', 'tool_action_candidate', 'selection_or_slot'].includes(intent);
|
|
1822
1888
|
return {
|
|
1823
|
-
current_goal:
|
|
1889
|
+
current_goal: currentGoal,
|
|
1890
|
+
current_goal_reason: carryPreviousGoal ? 'carried_from_previous_non_generic_goal' : 'derived_from_current_turn_intent',
|
|
1824
1891
|
current_task: nextExpectedAction,
|
|
1825
1892
|
last_user_intent: intent,
|
|
1826
1893
|
last_user_message: lastUser ? truncate(lastUser.content, 500) : truncate(query, 500),
|
|
1894
|
+
conversation_digest: cleanContextValue({
|
|
1895
|
+
messages: chronological.length,
|
|
1896
|
+
user_messages: userMessages.length,
|
|
1897
|
+
assistant_messages: assistantMessages.length,
|
|
1898
|
+
current_user: truncate(query, 220),
|
|
1899
|
+
prior_user: priorUser ? { content: truncate(priorUser.content, 180), at: priorUser.at } : undefined,
|
|
1900
|
+
last_assistant: lastAssistant ? { content: truncate(lastAssistant.content, 180), at: lastAssistant.at } : undefined,
|
|
1901
|
+
}),
|
|
1902
|
+
tool_digest: cleanContextValue({
|
|
1903
|
+
total: Array.isArray(toolHistory) ? toolHistory.length : 0,
|
|
1904
|
+
ok: (operationalState || {}).tool_counts?.ok,
|
|
1905
|
+
failed: (operationalState || {}).tool_counts?.failed,
|
|
1906
|
+
names: toolNames.slice(0, 12),
|
|
1907
|
+
last_successful: toolState.last_successful_tool ? {
|
|
1908
|
+
name: toolState.last_successful_tool.name,
|
|
1909
|
+
at: toolState.last_successful_tool.at,
|
|
1910
|
+
status: toolState.last_successful_tool.status || 'ok',
|
|
1911
|
+
} : undefined,
|
|
1912
|
+
failed_by_name: toolState.failed_by_name,
|
|
1913
|
+
}),
|
|
1914
|
+
turn_flags: cleanContextValue({
|
|
1915
|
+
recall_only: intent === 'conversation_recall',
|
|
1916
|
+
status_question: intent === 'operational_status_question',
|
|
1917
|
+
current_turn_may_need_tool: currentTurnMayNeedTool,
|
|
1918
|
+
has_prior_tools: Array.isArray(toolHistory) && toolHistory.length > 0,
|
|
1919
|
+
has_profile_facts: activeEntities.length > 0,
|
|
1920
|
+
carry_previous_goal: carryPreviousGoal,
|
|
1921
|
+
}),
|
|
1922
|
+
context_sources: cleanContextValue({
|
|
1923
|
+
conversation: chronological.length > 0,
|
|
1924
|
+
tool_history: Array.isArray(toolHistory) && toolHistory.length > 0,
|
|
1925
|
+
operational_state: Boolean((operationalState || {}).tool_state || (operationalState || {}).tool_counts),
|
|
1926
|
+
profile_facts: activeEntities.length > 0,
|
|
1927
|
+
}),
|
|
1928
|
+
agent_guidance: nextExpectedAction,
|
|
1827
1929
|
active_entities: activeEntities,
|
|
1828
1930
|
open_decisions: previous.open_decisions || [],
|
|
1829
1931
|
last_error: lastTool && lastTool.ok === false ? { tool: lastTool.name, at: lastTool.at, result: lastTool.result } : null,
|
|
@@ -2098,9 +2200,15 @@ const cleanContextValue = (value) => {
|
|
|
2098
2200
|
};
|
|
2099
2201
|
const compactWorkingMemoryForAgent = (memory = {}) => cleanContextValue({
|
|
2100
2202
|
current_goal: memory.current_goal,
|
|
2203
|
+
current_goal_reason: memory.current_goal_reason,
|
|
2101
2204
|
current_task: memory.current_task,
|
|
2102
2205
|
last_user_intent: memory.last_user_intent,
|
|
2103
2206
|
last_user_message: truncate(memory.last_user_message, 220),
|
|
2207
|
+
conversation_digest: memory.conversation_digest,
|
|
2208
|
+
tool_digest: memory.tool_digest,
|
|
2209
|
+
turn_flags: memory.turn_flags,
|
|
2210
|
+
context_sources: memory.context_sources,
|
|
2211
|
+
agent_guidance: memory.agent_guidance,
|
|
2104
2212
|
active_entities: memory.active_entities,
|
|
2105
2213
|
open_decisions: memory.open_decisions,
|
|
2106
2214
|
last_error: memory.last_error,
|
|
@@ -2355,13 +2463,22 @@ const compactConversationTimelineForSideChannel = (conversation = {}, maxItems =
|
|
|
2355
2463
|
return pruneByLimit(chronological, maxItems).map((message, index) => {
|
|
2356
2464
|
const role = normalizeConversationRoleForSideChannel(message.role || message.type);
|
|
2357
2465
|
const content = String(message.content || message.text || message.message || '');
|
|
2466
|
+
const at = message.at || message.timestamp || message.created_at || message.createdAt;
|
|
2467
|
+
const preview = role === 'system' ? '[system context hidden]' : truncate(content, 180);
|
|
2358
2468
|
return cleanContextValue({
|
|
2359
2469
|
index,
|
|
2360
2470
|
role,
|
|
2361
2471
|
speaker: role,
|
|
2362
|
-
at
|
|
2472
|
+
at,
|
|
2363
2473
|
chars: content.length,
|
|
2364
|
-
|
|
2474
|
+
preview,
|
|
2475
|
+
content: preview,
|
|
2476
|
+
message: {
|
|
2477
|
+
role,
|
|
2478
|
+
at,
|
|
2479
|
+
content: role === 'system' ? '[system context hidden]' : truncate(content, 2000),
|
|
2480
|
+
truncated: content.length > 2000,
|
|
2481
|
+
},
|
|
2365
2482
|
});
|
|
2366
2483
|
});
|
|
2367
2484
|
};
|
|
@@ -2427,6 +2544,7 @@ const summarizeMemoryMessagesForSideChannel = (messages = []) => {
|
|
|
2427
2544
|
summary.payloadFormat = parsed.payloadFormat;
|
|
2428
2545
|
summary.options = cleanContextValue(parsed.options || {});
|
|
2429
2546
|
summary.intent = parsed.observations?.inferred_intent?.label || parsed.workingMemory?.last_user_intent || parsed.decisionState?.current_intent || undefined;
|
|
2547
|
+
const parsedTurnBrief = parsed.turnBrief || parsed.turn_brief || undefined;
|
|
2430
2548
|
summary.currentUserMessage = conversation.current_user_message ? truncate(conversation.current_user_message, 180) : undefined;
|
|
2431
2549
|
summary.recentMessages = Array.isArray(conversation.conversation_history_chronological) ? conversation.conversation_history_chronological.length : undefined;
|
|
2432
2550
|
summary.conversationTimeline = compactConversationTimelineForSideChannel(conversation, 12);
|
|
@@ -2442,6 +2560,16 @@ const summarizeMemoryMessagesForSideChannel = (messages = []) => {
|
|
|
2442
2560
|
at: tools.last_successful_tool.at,
|
|
2443
2561
|
}
|
|
2444
2562
|
: (toolItems.length ? { name: toolItems[toolItems.length - 1].name, at: toolItems[toolItems.length - 1].at } : undefined);
|
|
2563
|
+
summary.turnBrief = typeof parsedTurnBrief === 'string'
|
|
2564
|
+
? cleanContextValue({
|
|
2565
|
+
brief: parsedTurnBrief,
|
|
2566
|
+
intent: summary.intent,
|
|
2567
|
+
currentUserMessage: summary.currentUserMessage,
|
|
2568
|
+
messages: summary.recentMessages,
|
|
2569
|
+
toolCount: summary.toolCount,
|
|
2570
|
+
lastTool: summary.lastTool,
|
|
2571
|
+
})
|
|
2572
|
+
: parsedTurnBrief;
|
|
2445
2573
|
summary.counts = cleanContextValue({
|
|
2446
2574
|
conversationMessages: Array.isArray(conversation.conversation_history_chronological) ? conversation.conversation_history_chronological.length : undefined,
|
|
2447
2575
|
userMessages: Array.isArray(conversation.all_user_messages_chronological) ? conversation.all_user_messages_chronological.length : undefined,
|
|
@@ -2463,6 +2591,7 @@ const summarizeMemoryMessagesForSideChannel = (messages = []) => {
|
|
|
2463
2591
|
memoryCompression: Boolean(parsed.memoryCompression),
|
|
2464
2592
|
operationalState: Boolean(parsed.operationalState),
|
|
2465
2593
|
actionLedger: Array.isArray(parsed.actionLedger),
|
|
2594
|
+
turnBrief: Boolean(parsed.turnBrief || parsed.turn_brief),
|
|
2466
2595
|
memoryAudit: Boolean(memoryAudit && Object.keys(memoryAudit).length),
|
|
2467
2596
|
entityTimeline: Array.isArray(parsed.entityTimeline),
|
|
2468
2597
|
vectorMemories: Array.isArray(parsed.vectorMemories),
|
|
@@ -2472,10 +2601,16 @@ const summarizeMemoryMessagesForSideChannel = (messages = []) => {
|
|
|
2472
2601
|
});
|
|
2473
2602
|
summary.workingMemory = cleanContextValue({
|
|
2474
2603
|
currentGoal: parsed.workingMemory?.current_goal,
|
|
2604
|
+
currentGoalReason: parsed.workingMemory?.current_goal_reason,
|
|
2475
2605
|
currentTask: parsed.workingMemory?.current_task,
|
|
2476
2606
|
nextExpectedAction: parsed.workingMemory?.next_expected_action,
|
|
2477
2607
|
lastUserIntent: parsed.workingMemory?.last_user_intent,
|
|
2478
2608
|
lastUserMessage: parsed.workingMemory?.last_user_message ? truncate(parsed.workingMemory.last_user_message, 220) : undefined,
|
|
2609
|
+
conversation: parsed.workingMemory?.conversation_digest,
|
|
2610
|
+
tools: parsed.workingMemory?.tool_digest,
|
|
2611
|
+
turnFlags: parsed.workingMemory?.turn_flags,
|
|
2612
|
+
contextSources: parsed.workingMemory?.context_sources,
|
|
2613
|
+
agentGuidance: parsed.workingMemory?.agent_guidance,
|
|
2479
2614
|
});
|
|
2480
2615
|
summary.decisionState = cleanContextValue({
|
|
2481
2616
|
currentIntent: parsed.decisionState?.current_intent,
|
|
@@ -2582,6 +2717,12 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
2582
2717
|
value: currentTurnFocus,
|
|
2583
2718
|
});
|
|
2584
2719
|
}
|
|
2720
|
+
const turnBrief = buildTurnBriefForAgent({ query, recentMessages, toolHistory, operationalState, workingMemory, decisionState, diagnostics });
|
|
2721
|
+
sections.push({
|
|
2722
|
+
section: 'turn_brief',
|
|
2723
|
+
title: 'Turn brief',
|
|
2724
|
+
value: turnBrief,
|
|
2725
|
+
});
|
|
2585
2726
|
const actionDirective = buildActionDirective({ workingMemory, operationalState });
|
|
2586
2727
|
if (actionDirective) {
|
|
2587
2728
|
sections.push({
|
|
@@ -2679,6 +2820,10 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
2679
2820
|
const directive = sectionValue('action_directive');
|
|
2680
2821
|
const inferredIntent = deriveUserIntentObservation({ query, workingMemory, decisionState, recentMessages });
|
|
2681
2822
|
const memoryAudit = sectionValue('memory_audit');
|
|
2823
|
+
const compactSummary = cleanContextValue({
|
|
2824
|
+
vector_facts: vectorFacts,
|
|
2825
|
+
slm: hasToolLedger ? undefined : slmSummary,
|
|
2826
|
+
});
|
|
2682
2827
|
const minimalState = cleanContextValue({
|
|
2683
2828
|
next_expected_action: directive ? undefined : workingMemory.next_expected_action,
|
|
2684
2829
|
context_quality_score: diagnostics?.contextHealth?.quality_score || diagnostics?.quality_score,
|
|
@@ -2697,13 +2842,11 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
2697
2842
|
next_expected_action: directive.next_expected_action,
|
|
2698
2843
|
instruction: directive.instruction,
|
|
2699
2844
|
}) : undefined,
|
|
2845
|
+
turnBrief: compactTurnBriefForAgent(sectionValue('turn_brief')),
|
|
2700
2846
|
observations: {
|
|
2701
2847
|
inferred_intent: inferredIntent,
|
|
2702
2848
|
},
|
|
2703
|
-
summary:
|
|
2704
|
-
vector_facts: vectorFacts,
|
|
2705
|
-
slm: hasToolLedger ? undefined : slmSummary,
|
|
2706
|
-
},
|
|
2849
|
+
summary: Object.keys(compactSummary).length ? compactSummary : undefined,
|
|
2707
2850
|
state: minimalState,
|
|
2708
2851
|
workingMemory: sectionValue('working_memory'),
|
|
2709
2852
|
decisionState: sectionValue('decision_state'),
|
|
@@ -4340,6 +4483,7 @@ exports.__private = {
|
|
|
4340
4483
|
buildContextMessages,
|
|
4341
4484
|
inferToolGuard,
|
|
4342
4485
|
inferUserIntent,
|
|
4486
|
+
buildTurnBriefForAgent,
|
|
4343
4487
|
deriveUserIntentObservation,
|
|
4344
4488
|
deriveWorkingMemory,
|
|
4345
4489
|
deriveDecisionState,
|
package/package.json
CHANGED