n8n-nodes-tembory 1.1.23 → 1.1.25
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.
|
@@ -143,6 +143,48 @@ const asSearchQuery = (value) => {
|
|
|
143
143
|
return String(value);
|
|
144
144
|
return pickText(value, ['query', 'input', 'chatInput', 'text', 'message', 'consolidated_text', 'lastUserMessage']);
|
|
145
145
|
};
|
|
146
|
+
const currentInputJsonFromContext = (ctx, itemIndex = 0) => {
|
|
147
|
+
try {
|
|
148
|
+
const inputData = typeof (ctx === null || ctx === void 0 ? void 0 : ctx.getInputData) === 'function' ? ctx.getInputData() : [];
|
|
149
|
+
const item = (Array.isArray(inputData) && (inputData[itemIndex] || inputData[0])) || {};
|
|
150
|
+
return item && typeof item.json === 'object' && item.json ? item.json : {};
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return {};
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
const resolveCurrentTurnQuery = (ctx, itemIndex = 0, inputValues = {}, queryParam = '') => {
|
|
157
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
158
|
+
const inputJson = currentInputJsonFromContext(ctx, itemIndex);
|
|
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],
|
|
180
|
+
];
|
|
181
|
+
for (const candidate of candidates) {
|
|
182
|
+
const query = asSearchQuery(candidate).trim();
|
|
183
|
+
if (query)
|
|
184
|
+
return stripThreadTestPrefix(query);
|
|
185
|
+
}
|
|
186
|
+
return '';
|
|
187
|
+
};
|
|
146
188
|
const memoryText = (memory) => {
|
|
147
189
|
if (!memory)
|
|
148
190
|
return '';
|
|
@@ -1224,6 +1266,8 @@ const mergeRemoteThreadState = (store, key, state) => {
|
|
|
1224
1266
|
store.decisionState[key] = { ...(store.decisionState[key] || {}), ...state.decisionState };
|
|
1225
1267
|
if (state.memoryCompression && typeof state.memoryCompression === 'object')
|
|
1226
1268
|
store.memoryCompression[key] = state.memoryCompression;
|
|
1269
|
+
if (state.captureState && typeof state.captureState === 'object')
|
|
1270
|
+
store.captureState[key] = { ...(store.captureState[key] || {}), ...state.captureState };
|
|
1227
1271
|
if (typeof state.activeSummary === 'string' && state.activeSummary)
|
|
1228
1272
|
store.activeSummary[key] = state.activeSummary;
|
|
1229
1273
|
};
|
|
@@ -1679,6 +1723,56 @@ const buildCurrentTurnFocus = ({ query = '', recentMessages = [], operationalSta
|
|
|
1679
1723
|
});
|
|
1680
1724
|
return focus;
|
|
1681
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
|
+
};
|
|
1682
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.';
|
|
1683
1777
|
const intentConfidence = (intent = '') => {
|
|
1684
1778
|
if (['conversation_recall', 'operational_status_question'].includes(intent))
|
|
@@ -1745,7 +1839,7 @@ const inferUserIntent = (query = '', recentMessages = []) => {
|
|
|
1745
1839
|
return 'selection_or_slot';
|
|
1746
1840
|
if (hasCommitIntent(text))
|
|
1747
1841
|
return 'commit_or_continue';
|
|
1748
|
-
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))
|
|
1749
1843
|
return 'tool_action_candidate';
|
|
1750
1844
|
if (/\b(meu nome|email|telefone|empresa|prefiro|preferencia)\b/.test(text))
|
|
1751
1845
|
return 'profile_update';
|
|
@@ -2311,13 +2405,22 @@ const compactConversationTimelineForSideChannel = (conversation = {}, maxItems =
|
|
|
2311
2405
|
return pruneByLimit(chronological, maxItems).map((message, index) => {
|
|
2312
2406
|
const role = normalizeConversationRoleForSideChannel(message.role || message.type);
|
|
2313
2407
|
const content = String(message.content || message.text || message.message || '');
|
|
2408
|
+
const at = message.at || message.timestamp || message.created_at || message.createdAt;
|
|
2409
|
+
const preview = role === 'system' ? '[system context hidden]' : truncate(content, 180);
|
|
2314
2410
|
return cleanContextValue({
|
|
2315
2411
|
index,
|
|
2316
2412
|
role,
|
|
2317
2413
|
speaker: role,
|
|
2318
|
-
at
|
|
2414
|
+
at,
|
|
2319
2415
|
chars: content.length,
|
|
2320
|
-
|
|
2416
|
+
preview,
|
|
2417
|
+
content: preview,
|
|
2418
|
+
message: {
|
|
2419
|
+
role,
|
|
2420
|
+
at,
|
|
2421
|
+
content: role === 'system' ? '[system context hidden]' : truncate(content, 2000),
|
|
2422
|
+
truncated: content.length > 2000,
|
|
2423
|
+
},
|
|
2321
2424
|
});
|
|
2322
2425
|
});
|
|
2323
2426
|
};
|
|
@@ -2383,6 +2486,7 @@ const summarizeMemoryMessagesForSideChannel = (messages = []) => {
|
|
|
2383
2486
|
summary.payloadFormat = parsed.payloadFormat;
|
|
2384
2487
|
summary.options = cleanContextValue(parsed.options || {});
|
|
2385
2488
|
summary.intent = parsed.observations?.inferred_intent?.label || parsed.workingMemory?.last_user_intent || parsed.decisionState?.current_intent || undefined;
|
|
2489
|
+
const parsedTurnBrief = parsed.turnBrief || parsed.turn_brief || undefined;
|
|
2386
2490
|
summary.currentUserMessage = conversation.current_user_message ? truncate(conversation.current_user_message, 180) : undefined;
|
|
2387
2491
|
summary.recentMessages = Array.isArray(conversation.conversation_history_chronological) ? conversation.conversation_history_chronological.length : undefined;
|
|
2388
2492
|
summary.conversationTimeline = compactConversationTimelineForSideChannel(conversation, 12);
|
|
@@ -2398,6 +2502,16 @@ const summarizeMemoryMessagesForSideChannel = (messages = []) => {
|
|
|
2398
2502
|
at: tools.last_successful_tool.at,
|
|
2399
2503
|
}
|
|
2400
2504
|
: (toolItems.length ? { name: toolItems[toolItems.length - 1].name, at: toolItems[toolItems.length - 1].at } : undefined);
|
|
2505
|
+
summary.turnBrief = typeof parsedTurnBrief === 'string'
|
|
2506
|
+
? cleanContextValue({
|
|
2507
|
+
brief: parsedTurnBrief,
|
|
2508
|
+
intent: summary.intent,
|
|
2509
|
+
currentUserMessage: summary.currentUserMessage,
|
|
2510
|
+
messages: summary.recentMessages,
|
|
2511
|
+
toolCount: summary.toolCount,
|
|
2512
|
+
lastTool: summary.lastTool,
|
|
2513
|
+
})
|
|
2514
|
+
: parsedTurnBrief;
|
|
2401
2515
|
summary.counts = cleanContextValue({
|
|
2402
2516
|
conversationMessages: Array.isArray(conversation.conversation_history_chronological) ? conversation.conversation_history_chronological.length : undefined,
|
|
2403
2517
|
userMessages: Array.isArray(conversation.all_user_messages_chronological) ? conversation.all_user_messages_chronological.length : undefined,
|
|
@@ -2419,6 +2533,7 @@ const summarizeMemoryMessagesForSideChannel = (messages = []) => {
|
|
|
2419
2533
|
memoryCompression: Boolean(parsed.memoryCompression),
|
|
2420
2534
|
operationalState: Boolean(parsed.operationalState),
|
|
2421
2535
|
actionLedger: Array.isArray(parsed.actionLedger),
|
|
2536
|
+
turnBrief: Boolean(parsed.turnBrief || parsed.turn_brief),
|
|
2422
2537
|
memoryAudit: Boolean(memoryAudit && Object.keys(memoryAudit).length),
|
|
2423
2538
|
entityTimeline: Array.isArray(parsed.entityTimeline),
|
|
2424
2539
|
vectorMemories: Array.isArray(parsed.vectorMemories),
|
|
@@ -2538,6 +2653,12 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
2538
2653
|
value: currentTurnFocus,
|
|
2539
2654
|
});
|
|
2540
2655
|
}
|
|
2656
|
+
const turnBrief = buildTurnBriefForAgent({ query, recentMessages, toolHistory, operationalState, workingMemory, decisionState, diagnostics });
|
|
2657
|
+
sections.push({
|
|
2658
|
+
section: 'turn_brief',
|
|
2659
|
+
title: 'Turn brief',
|
|
2660
|
+
value: turnBrief,
|
|
2661
|
+
});
|
|
2541
2662
|
const actionDirective = buildActionDirective({ workingMemory, operationalState });
|
|
2542
2663
|
if (actionDirective) {
|
|
2543
2664
|
sections.push({
|
|
@@ -2635,6 +2756,10 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
2635
2756
|
const directive = sectionValue('action_directive');
|
|
2636
2757
|
const inferredIntent = deriveUserIntentObservation({ query, workingMemory, decisionState, recentMessages });
|
|
2637
2758
|
const memoryAudit = sectionValue('memory_audit');
|
|
2759
|
+
const compactSummary = cleanContextValue({
|
|
2760
|
+
vector_facts: vectorFacts,
|
|
2761
|
+
slm: hasToolLedger ? undefined : slmSummary,
|
|
2762
|
+
});
|
|
2638
2763
|
const minimalState = cleanContextValue({
|
|
2639
2764
|
next_expected_action: directive ? undefined : workingMemory.next_expected_action,
|
|
2640
2765
|
context_quality_score: diagnostics?.contextHealth?.quality_score || diagnostics?.quality_score,
|
|
@@ -2653,13 +2778,11 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
2653
2778
|
next_expected_action: directive.next_expected_action,
|
|
2654
2779
|
instruction: directive.instruction,
|
|
2655
2780
|
}) : undefined,
|
|
2781
|
+
turnBrief: compactTurnBriefForAgent(sectionValue('turn_brief')),
|
|
2656
2782
|
observations: {
|
|
2657
2783
|
inferred_intent: inferredIntent,
|
|
2658
2784
|
},
|
|
2659
|
-
summary:
|
|
2660
|
-
vector_facts: vectorFacts,
|
|
2661
|
-
slm: hasToolLedger ? undefined : slmSummary,
|
|
2662
|
-
},
|
|
2785
|
+
summary: Object.keys(compactSummary).length ? compactSummary : undefined,
|
|
2663
2786
|
state: minimalState,
|
|
2664
2787
|
workingMemory: sectionValue('working_memory'),
|
|
2665
2788
|
decisionState: sectionValue('decision_state'),
|
|
@@ -2932,12 +3055,7 @@ class TemboryMemory {
|
|
|
2932
3055
|
name: 'query',
|
|
2933
3056
|
type: 'string',
|
|
2934
3057
|
default: '={{ $json.query || $json.lastUserMessage || $json.chatInput || $json.body?.consolidated_text || $json.body?.message || $json.body?.text || "" }}',
|
|
2935
|
-
description: '
|
|
2936
|
-
displayOptions: {
|
|
2937
|
-
show: {
|
|
2938
|
-
retrievalMode: ['semantic', 'semanticV2', 'hybrid'],
|
|
2939
|
-
},
|
|
2940
|
-
},
|
|
3058
|
+
description: 'Mensagem atual usada para montar o contexto operacional, inferir intenção e recuperar memórias relevantes. Em AI Agent, mantenha a expressão padrão para ler o chatInput do item.',
|
|
2941
3059
|
},
|
|
2942
3060
|
{
|
|
2943
3061
|
displayName: 'Chave de Memória',
|
|
@@ -3294,6 +3412,19 @@ class TemboryMemory {
|
|
|
3294
3412
|
body.app_id = String(adv.appId);
|
|
3295
3413
|
if (adv.runId)
|
|
3296
3414
|
body.run_id = String(adv.runId);
|
|
3415
|
+
const nextCaptureState = cleanContextValue({
|
|
3416
|
+
...(store.captureState[key] || {}),
|
|
3417
|
+
last_save_status: 'saved',
|
|
3418
|
+
last_save_saved: true,
|
|
3419
|
+
last_save_conversation_messages_after_save: recentForTurn.length,
|
|
3420
|
+
last_save_tool_history_after_save: toolHistoryForTurn.length,
|
|
3421
|
+
last_save_thread_state_saved: true,
|
|
3422
|
+
last_save_backend_memory_persistence: adv.persistBackendMemories === false
|
|
3423
|
+
? 'disabled'
|
|
3424
|
+
: adv.useVectorMemory === false
|
|
3425
|
+
? 'thread_state_only'
|
|
3426
|
+
: 'enabled',
|
|
3427
|
+
});
|
|
3297
3428
|
const threadStateSaved = await saveThreadState(this, key, threadId, project, {
|
|
3298
3429
|
kind: 'tembory.thread_state.v1',
|
|
3299
3430
|
threadId,
|
|
@@ -3306,20 +3437,12 @@ class TemboryMemory {
|
|
|
3306
3437
|
decisionState: decisionStateForTurn,
|
|
3307
3438
|
memoryCompression: compressionForTurn,
|
|
3308
3439
|
operationalState: operationalStateForTurn,
|
|
3440
|
+
captureState: nextCaptureState,
|
|
3309
3441
|
activeSummary: store.activeSummary[key] || '',
|
|
3310
3442
|
});
|
|
3311
3443
|
store.captureState[key] = cleanContextValue({
|
|
3312
|
-
...
|
|
3313
|
-
last_save_status: 'saved',
|
|
3314
|
-
last_save_saved: true,
|
|
3315
|
-
last_save_conversation_messages_after_save: recentForTurn.length,
|
|
3316
|
-
last_save_tool_history_after_save: toolHistoryForTurn.length,
|
|
3444
|
+
...nextCaptureState,
|
|
3317
3445
|
last_save_thread_state_saved: threadStateSaved,
|
|
3318
|
-
last_save_backend_memory_persistence: adv.persistBackendMemories === false
|
|
3319
|
-
? 'disabled'
|
|
3320
|
-
: adv.useVectorMemory === false
|
|
3321
|
-
? 'thread_state_only'
|
|
3322
|
-
: 'enabled',
|
|
3323
3446
|
});
|
|
3324
3447
|
try {
|
|
3325
3448
|
const globalData = this.getWorkflowStaticData('global');
|
|
@@ -3586,7 +3709,7 @@ class TemboryMemory {
|
|
|
3586
3709
|
const store = getMemoryStore(this);
|
|
3587
3710
|
const key = userKeyFrom(threadId, adv, project);
|
|
3588
3711
|
const queryParam = this.getNodeParameter('query', itemIndex, '');
|
|
3589
|
-
const query =
|
|
3712
|
+
const query = resolveCurrentTurnQuery(this, itemIndex, inputValues, queryParam);
|
|
3590
3713
|
const remoteThreadState = await loadThreadState(this, key, threadId, project);
|
|
3591
3714
|
mergeRemoteThreadState(store, key, remoteThreadState);
|
|
3592
3715
|
let connectedLanguageModel;
|
|
@@ -4030,7 +4153,7 @@ class TemboryMemory {
|
|
|
4030
4153
|
last_save_conversation_messages_after_save: 0,
|
|
4031
4154
|
last_save_tool_history_after_save: 0,
|
|
4032
4155
|
last_save_thread_state_saved: false,
|
|
4033
|
-
last_save_backend_memory_persistence: backendPersistenceEnabled ? 'enabled' : 'disabled',
|
|
4156
|
+
last_save_backend_memory_persistence: backendPersistenceEnabled ? (vectorMemoryEnabled ? 'enabled' : 'thread_state_only') : 'disabled',
|
|
4034
4157
|
},
|
|
4035
4158
|
connectedAi,
|
|
4036
4159
|
activeSummary: summaryDiagnostics,
|
|
@@ -4288,12 +4411,15 @@ exports.__private = {
|
|
|
4288
4411
|
applyOperationalPreset,
|
|
4289
4412
|
flattenAdvancedGroups,
|
|
4290
4413
|
asSearchQuery,
|
|
4414
|
+
currentInputJsonFromContext,
|
|
4415
|
+
resolveCurrentTurnQuery,
|
|
4291
4416
|
safePersistLegacyMemory,
|
|
4292
4417
|
stripThreadTestPrefix,
|
|
4293
4418
|
canonicalToolInput,
|
|
4294
4419
|
buildContextMessages,
|
|
4295
4420
|
inferToolGuard,
|
|
4296
4421
|
inferUserIntent,
|
|
4422
|
+
buildTurnBriefForAgent,
|
|
4297
4423
|
deriveUserIntentObservation,
|
|
4298
4424
|
deriveWorkingMemory,
|
|
4299
4425
|
deriveDecisionState,
|
package/package.json
CHANGED