n8n-nodes-tembory 1.0.9 → 1.0.12
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 +5 -1
- package/dist/nodes/Mem0/Mem0Memory.node.js +352 -130
- package/package.json +1 -1
- package/scripts/simulate-agent-context.js +6 -6
package/README.md
CHANGED
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Node de memoria operacional da Tembory para agentes de IA no n8n.
|
|
4
4
|
|
|
5
|
-
Versao atual: `1.0.
|
|
5
|
+
Versao atual: `1.0.12`.
|
|
6
6
|
|
|
7
7
|
O Tembory entrega contexto rico para o AI Agent sem depender apenas do historico textual da conversa. Ele combina memoria semantica, working memory, decision state, fatos estaveis do lead, historico de tools, estado operacional, action ledger, timeline de entidades, compressao de memoria, grafo, mensagens recentes e diagnosticos.
|
|
8
8
|
|
|
9
|
+
Nos presets de producao, o contexto e organizado como um pacote acionavel: secoes vazias sao removidas, evidencias de tools ficam canonicas em `tool_history`/`operational_state`, e blocos como `decision_state`, `working_memory` e `memory_compression` sao compactados sem perder IDs, proximas acoes, slots, reservas, confirmacoes e bloqueios de repeticao.
|
|
10
|
+
|
|
11
|
+
Quando um modelo barato esta conectado ao Tembory, os presets de producao usam esse SLM para gerar um resumo ativo do contexto. Em modo `auto`, ele organiza tanto o estado atual (`working_memory`, `tool_history`, `operational_state`, `decision_state`) quanto memorias vetoriais recuperadas. Assim o primeiro turno ja pode receber highlights uteis mesmo antes de haver resultados do banco vetorial.
|
|
12
|
+
|
|
9
13
|
## Smoke tecnico
|
|
10
14
|
|
|
11
15
|
Antes de publicar uma versao, rode:
|
|
@@ -27,7 +27,7 @@ const snapshotJson = (value) => {
|
|
|
27
27
|
}
|
|
28
28
|
};
|
|
29
29
|
const truncate = (value, max = MAX_TEXT) => {
|
|
30
|
-
const text = typeof value === 'string' ? value : safeStringify(value);
|
|
30
|
+
const text = value === undefined || value === null ? '' : (typeof value === 'string' ? value : safeStringify(value));
|
|
31
31
|
if (text.length <= max)
|
|
32
32
|
return text;
|
|
33
33
|
return `${text.slice(0, max)}\n... [truncated ${text.length - max} chars]`;
|
|
@@ -53,7 +53,7 @@ const saveClientVectorMemories = async (ctx, memories, ids = {}) => {
|
|
|
53
53
|
const valid = memories.filter((memory) => String(memory === null || memory === void 0 ? void 0 : memory.text || '').trim());
|
|
54
54
|
if (!valid.length)
|
|
55
55
|
return null;
|
|
56
|
-
return GenericFunctions_1.mem0ApiRequest.call(ctx, 'POST', '/
|
|
56
|
+
return GenericFunctions_1.mem0ApiRequest.call(ctx, 'POST', '/tembory/v1/vector-memories', {
|
|
57
57
|
memories: valid,
|
|
58
58
|
user_id: ids.user_id,
|
|
59
59
|
agent_id: ids.agent_id,
|
|
@@ -64,7 +64,7 @@ const searchClientVectorMemories = async (ctx, embedding, query, body = {}) => {
|
|
|
64
64
|
const text = String(query || '').trim();
|
|
65
65
|
if (!text)
|
|
66
66
|
return { results: [] };
|
|
67
|
-
return GenericFunctions_1.mem0ApiRequest.call(ctx, 'POST', '/
|
|
67
|
+
return GenericFunctions_1.mem0ApiRequest.call(ctx, 'POST', '/tembory/v1/vector-memories/search', {
|
|
68
68
|
...body,
|
|
69
69
|
query: text,
|
|
70
70
|
embedding: await embedQueryCached(embedding, text),
|
|
@@ -167,11 +167,11 @@ const scoreOf = (m) => {
|
|
|
167
167
|
var _a, _b, _c, _d;
|
|
168
168
|
return (_d = (_c = (_b = (_a = m === null || m === void 0 ? void 0 : m.score) !== null && _a !== void 0 ? _a : m === null || m === void 0 ? void 0 : m.similarity) !== null && _b !== void 0 ? _b : m === null || m === void 0 ? void 0 : m.relevance) !== null && _c !== void 0 ? _c : m === null || m === void 0 ? void 0 : m.distance) !== null && _d !== void 0 ? _d : undefined;
|
|
169
169
|
};
|
|
170
|
-
const scoreMetaOf = (m) => (m && typeof m === 'object' && (m.
|
|
171
|
-
const
|
|
170
|
+
const scoreMetaOf = (m) => (m && typeof m === 'object' && (m.temboryScore || m._temboryScore)) || {};
|
|
171
|
+
const withTemboryScore = (m, temboryScore) => {
|
|
172
172
|
if (!m || typeof m !== 'object')
|
|
173
173
|
return m;
|
|
174
|
-
return { ...m,
|
|
174
|
+
return { ...m, temboryScore };
|
|
175
175
|
};
|
|
176
176
|
const normalizeFactValue = (value) => String(value || '').replace(/\*\*/g, '').replace(/\s+/g, ' ').replace(/[.,;:]+$/g, '').trim();
|
|
177
177
|
const profileSourceRank = (source = '') => {
|
|
@@ -504,8 +504,8 @@ const deriveEntityTimeline = (profileFacts = {}, graph = [], recentMessages = []
|
|
|
504
504
|
}
|
|
505
505
|
return pruneByLimit(deduped.sort((a, b) => String(a.at || '').localeCompare(String(b.at || ''))), maxItems || 24);
|
|
506
506
|
};
|
|
507
|
-
const RECENT_MESSAGE_MARKER = '
|
|
508
|
-
const TOOL_HISTORY_MARKER = '
|
|
507
|
+
const RECENT_MESSAGE_MARKER = '__tembory_recent_message_v1__';
|
|
508
|
+
const TOOL_HISTORY_MARKER = '__tembory_tool_history_v1__';
|
|
509
509
|
const encodeRecentMessage = (recent, threadId) => `${RECENT_MESSAGE_MARKER}${safeStringify({
|
|
510
510
|
role: recent.role || 'user',
|
|
511
511
|
content: recent.content || '',
|
|
@@ -855,21 +855,21 @@ const extractToolCalls = (outputValues = {}) => {
|
|
|
855
855
|
const getMemoryStore = (ctx) => {
|
|
856
856
|
try {
|
|
857
857
|
const data = ctx.getWorkflowStaticData('global');
|
|
858
|
-
data.
|
|
859
|
-
data.
|
|
860
|
-
data.
|
|
861
|
-
data.
|
|
862
|
-
data.
|
|
863
|
-
data.
|
|
864
|
-
data.
|
|
865
|
-
return data.
|
|
858
|
+
data.tembory = data.tembory || {};
|
|
859
|
+
data.tembory.toolHistory = data.tembory.toolHistory || {};
|
|
860
|
+
data.tembory.recentMessages = data.tembory.recentMessages || {};
|
|
861
|
+
data.tembory.profileFacts = data.tembory.profileFacts || {};
|
|
862
|
+
data.tembory.workingMemory = data.tembory.workingMemory || {};
|
|
863
|
+
data.tembory.decisionState = data.tembory.decisionState || {};
|
|
864
|
+
data.tembory.memoryCompression = data.tembory.memoryCompression || {};
|
|
865
|
+
return data.tembory;
|
|
866
866
|
}
|
|
867
867
|
catch {
|
|
868
|
-
global.
|
|
869
|
-
global.
|
|
870
|
-
global.
|
|
871
|
-
global.
|
|
872
|
-
return global.
|
|
868
|
+
global.__temboryMemory = global.__temboryMemory || { toolHistory: {}, recentMessages: {}, profileFacts: {}, workingMemory: {}, decisionState: {}, memoryCompression: {} };
|
|
869
|
+
global.__temboryMemory.workingMemory = global.__temboryMemory.workingMemory || {};
|
|
870
|
+
global.__temboryMemory.decisionState = global.__temboryMemory.decisionState || {};
|
|
871
|
+
global.__temboryMemory.memoryCompression = global.__temboryMemory.memoryCompression || {};
|
|
872
|
+
return global.__temboryMemory;
|
|
873
873
|
}
|
|
874
874
|
};
|
|
875
875
|
const namespacePart = (value) => String(value || '').trim().replace(/\s+/g, '_').replace(/[:|]+/g, '-');
|
|
@@ -882,6 +882,8 @@ const applyOperationalPreset = (advanced = {}) => {
|
|
|
882
882
|
const preset = String(advanced.operationPreset || 'custom');
|
|
883
883
|
const presets = {
|
|
884
884
|
diagnostic: {
|
|
885
|
+
summarySource: 'auto',
|
|
886
|
+
includeConnectedModelSummary: true,
|
|
885
887
|
includeContextHeader: true,
|
|
886
888
|
includeSummary: true,
|
|
887
889
|
includeScores: true,
|
|
@@ -906,6 +908,9 @@ const applyOperationalPreset = (advanced = {}) => {
|
|
|
906
908
|
recentMessagesLastN: 8,
|
|
907
909
|
},
|
|
908
910
|
productionBalanced: {
|
|
911
|
+
summarySource: 'auto',
|
|
912
|
+
includeConnectedModelSummary: true,
|
|
913
|
+
compactStateSections: true,
|
|
909
914
|
includeContextHeader: true,
|
|
910
915
|
includeSummary: true,
|
|
911
916
|
includeScores: false,
|
|
@@ -928,8 +933,15 @@ const applyOperationalPreset = (advanced = {}) => {
|
|
|
928
933
|
lastN: 8,
|
|
929
934
|
toolHistoryLastN: 10,
|
|
930
935
|
recentMessagesLastN: 6,
|
|
936
|
+
vectorMemoryMaxChars: 360,
|
|
937
|
+
contextMaxChars: 10000,
|
|
938
|
+
connectedModelSummaryMaxChars: 900,
|
|
939
|
+
connectedModelSummaryInputMaxChars: 3200,
|
|
931
940
|
},
|
|
932
941
|
productionCheap: {
|
|
942
|
+
summarySource: 'activeContext',
|
|
943
|
+
includeConnectedModelSummary: true,
|
|
944
|
+
compactStateSections: true,
|
|
933
945
|
includeContextHeader: true,
|
|
934
946
|
includeSummary: false,
|
|
935
947
|
includeScores: false,
|
|
@@ -952,8 +964,14 @@ const applyOperationalPreset = (advanced = {}) => {
|
|
|
952
964
|
lastN: 4,
|
|
953
965
|
toolHistoryLastN: 5,
|
|
954
966
|
recentMessagesLastN: 4,
|
|
967
|
+
vectorMemoryMaxChars: 260,
|
|
968
|
+
contextMaxChars: 7000,
|
|
969
|
+
connectedModelSummaryMaxChars: 700,
|
|
970
|
+
connectedModelSummaryInputMaxChars: 2400,
|
|
955
971
|
},
|
|
956
972
|
productionNano: {
|
|
973
|
+
summarySource: 'auto',
|
|
974
|
+
includeConnectedModelSummary: true,
|
|
957
975
|
compactForAgent: true,
|
|
958
976
|
includeContextHeader: true,
|
|
959
977
|
includeSummary: true,
|
|
@@ -980,8 +998,12 @@ const applyOperationalPreset = (advanced = {}) => {
|
|
|
980
998
|
recentMessagesLastN: 2,
|
|
981
999
|
vectorMemoryMaxChars: 220,
|
|
982
1000
|
contextMaxChars: 6000,
|
|
1001
|
+
connectedModelSummaryMaxChars: 700,
|
|
1002
|
+
connectedModelSummaryInputMaxChars: 2200,
|
|
983
1003
|
},
|
|
984
1004
|
audit: {
|
|
1005
|
+
summarySource: 'auto',
|
|
1006
|
+
includeConnectedModelSummary: true,
|
|
985
1007
|
includeContextHeader: true,
|
|
986
1008
|
includeSummary: true,
|
|
987
1009
|
includeScores: true,
|
|
@@ -1328,7 +1350,7 @@ const deriveContextHealth = ({ userId = '', project = '', vectorMemories = [], r
|
|
|
1328
1350
|
const missing = Object.entries(checks).filter(([, ok]) => !ok).map(([key]) => key);
|
|
1329
1351
|
const agenda = operationalState.agenda_state || {};
|
|
1330
1352
|
return {
|
|
1331
|
-
kind: '
|
|
1353
|
+
kind: 'tembory.context_health.v1',
|
|
1332
1354
|
namespace: userId || null,
|
|
1333
1355
|
project: project || null,
|
|
1334
1356
|
quality_score: Math.max(0, Math.min(1000, score)),
|
|
@@ -1409,12 +1431,63 @@ const compactToolResult = (result, max = 360) => {
|
|
|
1409
1431
|
return truncate(text, max);
|
|
1410
1432
|
};
|
|
1411
1433
|
const compactToolHistoryForAgent = (toolHistory = [], maxItems = 6, includeResults = true) => pruneByLimit(toolHistory || [], maxItems).map((tool) => ({
|
|
1434
|
+
id: tool.call_id || tool.id,
|
|
1412
1435
|
name: tool.name,
|
|
1413
1436
|
status: tool.ok === false ? 'failed' : 'ok',
|
|
1414
1437
|
at: tool.at,
|
|
1415
1438
|
input: truncate(String(tool.input || ''), 180) || undefined,
|
|
1416
1439
|
result: includeResults ? compactToolResult(tool.result, 360) : undefined,
|
|
1417
1440
|
}));
|
|
1441
|
+
const cleanContextValue = (value) => {
|
|
1442
|
+
if (Array.isArray(value)) {
|
|
1443
|
+
return value.map(cleanContextValue).filter((item) => item !== undefined && item !== null && !(Array.isArray(item) && item.length === 0) && !(typeof item === 'object' && !Array.isArray(item) && Object.keys(item).length === 0));
|
|
1444
|
+
}
|
|
1445
|
+
if (!value || typeof value !== 'object')
|
|
1446
|
+
return value === '' ? undefined : value;
|
|
1447
|
+
const out = {};
|
|
1448
|
+
for (const [key, item] of Object.entries(value)) {
|
|
1449
|
+
const cleaned = cleanContextValue(item);
|
|
1450
|
+
if (cleaned === undefined || cleaned === null)
|
|
1451
|
+
continue;
|
|
1452
|
+
if (Array.isArray(cleaned) && cleaned.length === 0)
|
|
1453
|
+
continue;
|
|
1454
|
+
if (typeof cleaned === 'object' && !Array.isArray(cleaned) && Object.keys(cleaned).length === 0)
|
|
1455
|
+
continue;
|
|
1456
|
+
out[key] = cleaned;
|
|
1457
|
+
}
|
|
1458
|
+
return out;
|
|
1459
|
+
};
|
|
1460
|
+
const compactWorkingMemoryForAgent = (memory = {}) => cleanContextValue({
|
|
1461
|
+
current_goal: memory.current_goal,
|
|
1462
|
+
current_task: memory.current_task,
|
|
1463
|
+
last_user_intent: memory.last_user_intent,
|
|
1464
|
+
last_user_message: truncate(memory.last_user_message, 220),
|
|
1465
|
+
active_entities: memory.active_entities,
|
|
1466
|
+
open_decisions: memory.open_decisions,
|
|
1467
|
+
last_error: memory.last_error,
|
|
1468
|
+
next_expected_action: memory.next_expected_action,
|
|
1469
|
+
updated_at: memory.updated_at,
|
|
1470
|
+
});
|
|
1471
|
+
const compactDecisionStateForAgent = (state = {}) => cleanContextValue({
|
|
1472
|
+
current_intent: state.current_intent,
|
|
1473
|
+
active_decisions: (state.active_decisions || []).slice(-4).map((decision) => cleanContextValue({
|
|
1474
|
+
id: decision.id,
|
|
1475
|
+
status: decision.status,
|
|
1476
|
+
decision: truncate(decision.decision || decision.summary || decision.reason, 260),
|
|
1477
|
+
tool: decision.tool || decision.next_tool || decision.required_tool,
|
|
1478
|
+
reservation_id: decision.reservation_id,
|
|
1479
|
+
confirmation_id: decision.confirmation_id,
|
|
1480
|
+
at: decision.at || decision.updated_at,
|
|
1481
|
+
})),
|
|
1482
|
+
do_not_repeat_tools: state.do_not_repeat_tools,
|
|
1483
|
+
agenda_decision_state: state.agenda_decision_state,
|
|
1484
|
+
latest_tool: state.latest_tool ? cleanContextValue({
|
|
1485
|
+
name: state.latest_tool.name,
|
|
1486
|
+
status: state.latest_tool.status || (state.latest_tool.ok === false ? 'failed' : 'ok'),
|
|
1487
|
+
at: state.latest_tool.at,
|
|
1488
|
+
}) : undefined,
|
|
1489
|
+
conflict_policy: state.conflict_policy,
|
|
1490
|
+
});
|
|
1418
1491
|
const compactOperationalStateForAgent = (state = {}) => {
|
|
1419
1492
|
const agenda = state.agenda_state || {};
|
|
1420
1493
|
return {
|
|
@@ -1444,6 +1517,21 @@ const compactMemoryCompressionForAgent = (compression = {}) => ({
|
|
|
1444
1517
|
} : undefined,
|
|
1445
1518
|
active_memory_count: ((compression.workflow_summary || {}).active_memory_count) || 0,
|
|
1446
1519
|
});
|
|
1520
|
+
const compactActionLedgerForAgent = (ledger = [], maxItems = 6, includeResults = true) => pruneByLimit(ledger || [], maxItems).map((item) => cleanContextValue({
|
|
1521
|
+
action_id: item.action_id,
|
|
1522
|
+
kind: item.kind,
|
|
1523
|
+
tool: item.tool || item.name,
|
|
1524
|
+
status: item.status,
|
|
1525
|
+
at: item.at,
|
|
1526
|
+
result: includeResults ? compactToolResult(item.result, 260) : undefined,
|
|
1527
|
+
}));
|
|
1528
|
+
const compactEntityTimelineForAgent = (timeline = [], maxItems = 8) => pruneByLimit(timeline || [], maxItems).map((item) => cleanContextValue({
|
|
1529
|
+
entity: item.entity || item.source || item.name,
|
|
1530
|
+
event: truncate(item.event || item.fact || item.relation || item.kind || item.value, 220),
|
|
1531
|
+
target: item.target,
|
|
1532
|
+
at: item.at,
|
|
1533
|
+
source: item.source_type || item.source,
|
|
1534
|
+
}));
|
|
1447
1535
|
const compactVectorMemoriesForAgent = (vectorMemories = [], toolHistory = [], maxItems = 3) => {
|
|
1448
1536
|
const hasStructuredTools = Array.isArray(toolHistory) && toolHistory.length > 0;
|
|
1449
1537
|
return (vectorMemories || [])
|
|
@@ -1452,6 +1540,87 @@ const compactVectorMemoriesForAgent = (vectorMemories = [], toolHistory = [], ma
|
|
|
1452
1540
|
.filter((text) => !hasStructuredTools || !/^\[tool_events_extracted\]/i.test(text))
|
|
1453
1541
|
.slice(0, maxItems);
|
|
1454
1542
|
};
|
|
1543
|
+
const modelResponseText = (response) => {
|
|
1544
|
+
const content = response === null || response === void 0 ? void 0 : response.content;
|
|
1545
|
+
if (typeof content === 'string')
|
|
1546
|
+
return content;
|
|
1547
|
+
if (Array.isArray(content)) {
|
|
1548
|
+
return content.map((item) => {
|
|
1549
|
+
if (typeof item === 'string')
|
|
1550
|
+
return item;
|
|
1551
|
+
if (item && typeof item === 'object' && typeof item.text === 'string')
|
|
1552
|
+
return item.text;
|
|
1553
|
+
if (item && typeof item === 'object' && typeof item.content === 'string')
|
|
1554
|
+
return item.content;
|
|
1555
|
+
return '';
|
|
1556
|
+
}).filter(Boolean).join('\n');
|
|
1557
|
+
}
|
|
1558
|
+
if (typeof (response === null || response === void 0 ? void 0 : response.text) === 'string')
|
|
1559
|
+
return response.text;
|
|
1560
|
+
return response === undefined || response === null ? '' : String(response);
|
|
1561
|
+
};
|
|
1562
|
+
const cleanModelSummaryText = (value, max = 900) => {
|
|
1563
|
+
let text = modelResponseText(value).trim();
|
|
1564
|
+
if (!text)
|
|
1565
|
+
return '';
|
|
1566
|
+
try {
|
|
1567
|
+
const parsed = JSON.parse(text);
|
|
1568
|
+
text = modelResponseText(parsed) || (Array.isArray(parsed) ? parsed.map(modelResponseText).filter(Boolean).join('\n') : '');
|
|
1569
|
+
if (!text && parsed && typeof parsed === 'object') {
|
|
1570
|
+
const bullets = parsed.highlights || parsed.current_summary || parsed.summary || parsed.facts;
|
|
1571
|
+
if (Array.isArray(bullets))
|
|
1572
|
+
text = bullets.map((item) => `- ${typeof item === 'string' ? item : safeStringify(item)}`).join('\n');
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
catch { }
|
|
1576
|
+
text = text
|
|
1577
|
+
.replace(/^\s*\[\s*\{\s*"type"\s*:\s*"text"\s*,\s*"text"\s*:\s*"/, '')
|
|
1578
|
+
.replace(/"\s*,\s*"annotations"\s*:\s*\[\s*\]\s*\}\s*\]\s*$/, '')
|
|
1579
|
+
.replace(/\\n/g, '\n')
|
|
1580
|
+
.trim();
|
|
1581
|
+
return truncate(text, max);
|
|
1582
|
+
};
|
|
1583
|
+
const buildConnectedModelSummaryInput = ({ query, profileFacts, workingMemory, decisionState, memoryCompression, operationalState, toolHistory, recentMessages, vectorMemories, highlights, adv }) => {
|
|
1584
|
+
const source = String(adv.summarySource || 'auto');
|
|
1585
|
+
if (source === 'off' || source === 'disabled' || adv.includeConnectedModelSummary === false)
|
|
1586
|
+
return '';
|
|
1587
|
+
const includeVectors = source === 'auto' || source === 'vectorOnly' || source === 'vectors';
|
|
1588
|
+
const includeActive = source === 'auto' || source === 'activeContext' || source === 'active';
|
|
1589
|
+
const payload = cleanContextValue({
|
|
1590
|
+
query: String(query || ''),
|
|
1591
|
+
active_context: includeActive ? {
|
|
1592
|
+
profile_facts: renderProfileFacts(profileFacts),
|
|
1593
|
+
working_memory: compactWorkingMemoryForAgent(workingMemory || {}),
|
|
1594
|
+
decision_state: compactDecisionStateForAgent(decisionState || {}),
|
|
1595
|
+
operational_state: compactOperationalStateForAgent(operationalState || {}),
|
|
1596
|
+
memory_compression: compactMemoryCompressionForAgent(memoryCompression || {}),
|
|
1597
|
+
tool_history: compactToolHistoryForAgent(toolHistory || [], adv.summaryToolHistoryLastN || adv.toolHistoryLastN || 6, adv.includeToolResults !== false),
|
|
1598
|
+
recent_messages: pruneByLimit(recentMessages || [], adv.summaryRecentMessagesLastN || 4).map((message) => cleanContextValue({
|
|
1599
|
+
role: message.role,
|
|
1600
|
+
content: truncate(message.content, 240),
|
|
1601
|
+
at: message.at,
|
|
1602
|
+
})),
|
|
1603
|
+
highlights: (highlights || []).slice(0, adv.summaryHighlightsMaxItems || 4),
|
|
1604
|
+
} : undefined,
|
|
1605
|
+
vector_memories: includeVectors ? compactVectorMemoriesForAgent(vectorMemories || [], toolHistory || [], adv.summaryMaxFacts || 4) : undefined,
|
|
1606
|
+
});
|
|
1607
|
+
const hasActiveSignal = includeActive && Boolean((payload.active_context && Object.keys(payload.active_context).length) || payload.query);
|
|
1608
|
+
const hasVectorSignal = includeVectors && Array.isArray(payload.vector_memories) && payload.vector_memories.length > 0;
|
|
1609
|
+
if (!hasActiveSignal && !hasVectorSignal)
|
|
1610
|
+
return '';
|
|
1611
|
+
return truncate(safeStringify(payload), Number(adv.connectedModelSummaryInputMaxChars || 3000));
|
|
1612
|
+
};
|
|
1613
|
+
const invokeConnectedModelSummary = async (connectedLanguageModel, summaryInput, adv = {}) => {
|
|
1614
|
+
if (!connectedLanguageModel || typeof connectedLanguageModel.invoke !== 'function' || !summaryInput)
|
|
1615
|
+
return '';
|
|
1616
|
+
const response = await connectedLanguageModel.invoke([
|
|
1617
|
+
toBaseMessage({
|
|
1618
|
+
role: 'user',
|
|
1619
|
+
content: `Organize the Tembory memory context for the next agent turn. Return concise Portuguese bullets only. Preserve IDs, dates, tool names, next action, do-not-repeat instructions, and contradictions. Do not invent facts.\n\nContext:\n${summaryInput}`,
|
|
1620
|
+
}),
|
|
1621
|
+
]);
|
|
1622
|
+
return cleanModelSummaryText(response, Number(adv.connectedModelSummaryMaxChars || 900));
|
|
1623
|
+
};
|
|
1455
1624
|
const contextSizeOfMessages = (messages = []) => {
|
|
1456
1625
|
const perMessage = (messages || []).map((message, index) => {
|
|
1457
1626
|
const content = String(message.content || '');
|
|
@@ -1460,7 +1629,7 @@ const contextSizeOfMessages = (messages = []) => {
|
|
|
1460
1629
|
const chars = perMessage.reduce((sum, item) => sum + item.chars, 0);
|
|
1461
1630
|
return { chars, approx_tokens: approxTokenCount((messages || []).map((m) => m.content || '').join('\n')), messages: perMessage };
|
|
1462
1631
|
};
|
|
1463
|
-
const
|
|
1632
|
+
const wrapTemboryMemory = (memory, ctx, memoryKey) => new Proxy(memory, {
|
|
1464
1633
|
get(target, prop) {
|
|
1465
1634
|
if (prop === 'loadMemoryVariables') {
|
|
1466
1635
|
return async (values = {}) => {
|
|
@@ -1469,7 +1638,7 @@ const wrapElefaiMemory = (memory, ctx, memoryKey) => new Proxy(memory, {
|
|
|
1469
1638
|
]);
|
|
1470
1639
|
try {
|
|
1471
1640
|
const response = await target.loadMemoryVariables(values);
|
|
1472
|
-
const cacheHit = Boolean(response.
|
|
1641
|
+
const cacheHit = Boolean(response.temboryDiagnostics && response.temboryDiagnostics.cacheHit);
|
|
1473
1642
|
const chatHistory = cacheHit
|
|
1474
1643
|
? [{ cached: true, messages: Array.isArray(response[memoryKey] || response.chatHistory) ? (response[memoryKey] || response.chatHistory).length : 0 }]
|
|
1475
1644
|
: snapshotJson(response[memoryKey] || response.chatHistory || []);
|
|
@@ -1479,23 +1648,23 @@ const wrapElefaiMemory = (memory, ctx, memoryKey) => new Proxy(memory, {
|
|
|
1479
1648
|
action: 'loadMemoryVariables',
|
|
1480
1649
|
cached: cacheHit || undefined,
|
|
1481
1650
|
chatHistory,
|
|
1482
|
-
context: response.
|
|
1483
|
-
contextText: response.
|
|
1484
|
-
summary: response.
|
|
1485
|
-
connectedModelSummary: response.
|
|
1486
|
-
workingMemory: response.
|
|
1487
|
-
decisionState: response.
|
|
1488
|
-
memoryCompression: response.
|
|
1489
|
-
profileFacts: response.
|
|
1490
|
-
operationalState: response.
|
|
1491
|
-
actionLedger: response.
|
|
1492
|
-
entityTimeline: response.
|
|
1493
|
-
vectorMemories: response.
|
|
1494
|
-
graph: response.
|
|
1495
|
-
recentMessages: response.
|
|
1496
|
-
recentHighlights: response.
|
|
1497
|
-
toolHistory: response.
|
|
1498
|
-
diagnostics: response.
|
|
1651
|
+
context: response.temboryContext,
|
|
1652
|
+
contextText: response.temboryContextText,
|
|
1653
|
+
summary: response.temborySummary,
|
|
1654
|
+
connectedModelSummary: response.temboryConnectedModelSummary,
|
|
1655
|
+
workingMemory: response.temboryWorkingMemory,
|
|
1656
|
+
decisionState: response.temboryDecisionState,
|
|
1657
|
+
memoryCompression: response.temboryMemoryCompression,
|
|
1658
|
+
profileFacts: response.temboryProfileFacts,
|
|
1659
|
+
operationalState: response.temboryOperationalState,
|
|
1660
|
+
actionLedger: response.temboryActionLedger,
|
|
1661
|
+
entityTimeline: response.temboryEntityTimeline,
|
|
1662
|
+
vectorMemories: response.temboryVectorMemories,
|
|
1663
|
+
graph: response.temboryGraph,
|
|
1664
|
+
recentMessages: response.temboryRecentMessages,
|
|
1665
|
+
recentHighlights: response.temboryRecentHighlights,
|
|
1666
|
+
toolHistory: response.temboryToolHistory,
|
|
1667
|
+
diagnostics: response.temboryDiagnostics,
|
|
1499
1668
|
},
|
|
1500
1669
|
}],
|
|
1501
1670
|
]);
|
|
@@ -1529,17 +1698,18 @@ const wrapElefaiMemory = (memory, ctx, memoryKey) => new Proxy(memory, {
|
|
|
1529
1698
|
return target[prop];
|
|
1530
1699
|
},
|
|
1531
1700
|
});
|
|
1532
|
-
const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, workingMemory, decisionState, memoryCompression, operationalState, actionLedger, entityTimeline, vectorMemories, recentMessages, toolHistory, highlights, graph, diagnostics, adv }) => {
|
|
1701
|
+
const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, workingMemory, decisionState, memoryCompression, operationalState, actionLedger, entityTimeline, vectorMemories, recentMessages, toolHistory, highlights, graph, diagnostics, connectedModelSummary, adv }) => {
|
|
1533
1702
|
const includeHeader = adv.includeContextHeader !== false;
|
|
1534
1703
|
const includeSummary = adv.includeSummary !== false;
|
|
1535
1704
|
const includeScores = adv.includeScores !== false;
|
|
1536
1705
|
const compactForAgent = Boolean(adv.compactForAgent);
|
|
1706
|
+
const compactStateSections = Boolean(adv.compactStateSections);
|
|
1537
1707
|
const sections = [];
|
|
1538
1708
|
if (includeHeader) {
|
|
1539
1709
|
sections.push({
|
|
1540
1710
|
section: 'context_header',
|
|
1541
1711
|
title: 'Tembory context',
|
|
1542
|
-
value: compactForAgent
|
|
1712
|
+
value: compactForAgent || compactStateSections
|
|
1543
1713
|
? 'Read-only memory. Follow next_expected_action when present. Before calling downstream tools, verify required prior tool context in tool_history or operational_state. Do not repeat tools listed in do_not_repeat_tools.'
|
|
1544
1714
|
: 'Use this context as read-only memory. Prefer it over guessing. Do not mention internal section names to the user. Treat next_expected_action as an instruction, not as a suggestion. If it says to call a tool now, call that tool instead of asking the user the same question again. If the user asks to continue, chooses a slot, says ok/sim, reserve, confirm, update, cancel, or performs any downstream action that depends on a prior tool result, first verify the required prior result in tool_history, recent_messages, or vector memories. If the required prior result is absent, do not call the downstream tool; ask for the missing context or call the appropriate prerequisite tool.',
|
|
1545
1715
|
});
|
|
@@ -1549,6 +1719,9 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
1549
1719
|
const summary = compactVectorMemoriesForAgent(vectorMemories, toolHistory, Number(adv.summaryMaxFacts || 3));
|
|
1550
1720
|
sections.push({ section: 'summary', title: 'Summary', value: summary.length ? summary : null, why_null: summary.length ? undefined : 'no non-tool vector memories to summarize' });
|
|
1551
1721
|
}
|
|
1722
|
+
if (connectedModelSummary && adv.includeConnectedModelSummary !== false) {
|
|
1723
|
+
sections.push({ section: 'connected_model_summary', title: 'SLM summary', value: connectedModelSummary });
|
|
1724
|
+
}
|
|
1552
1725
|
sections.push({
|
|
1553
1726
|
section: 'working_memory',
|
|
1554
1727
|
title: 'Working memory',
|
|
@@ -1588,7 +1761,7 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
1588
1761
|
why_null: adv.includeMemoryCompression === false ? 'memory compression disabled' : undefined,
|
|
1589
1762
|
});
|
|
1590
1763
|
const audit = {
|
|
1591
|
-
kind: '
|
|
1764
|
+
kind: 'tembory.context.v1',
|
|
1592
1765
|
meta: { user_id: userId, payloadFormat, query, compact_for_agent: true },
|
|
1593
1766
|
sections,
|
|
1594
1767
|
diagnostics,
|
|
@@ -1609,13 +1782,18 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
1609
1782
|
return [{ role: 'system', content: truncate(sections.map(renderCompactSection).join('\n\n'), Number(adv.contextMaxChars || 6000)) }];
|
|
1610
1783
|
}
|
|
1611
1784
|
if (includeSummary) {
|
|
1612
|
-
const summary =
|
|
1785
|
+
const summary = compactStateSections
|
|
1786
|
+
? compactVectorMemoriesForAgent(vectorMemories, toolHistory, Number(adv.summaryMaxFacts || 4))
|
|
1787
|
+
: vectorMemories.slice(0, Number(adv.summaryMaxFacts || 4)).map((memory) => contextMemoryText(memory, 360)).filter(Boolean);
|
|
1613
1788
|
sections.push({ section: 'summary', title: 'Summary', value: summary.length ? summary : null, why_null: summary.length ? undefined : 'no vector memories to summarize' });
|
|
1614
1789
|
}
|
|
1790
|
+
if (connectedModelSummary && adv.includeConnectedModelSummary !== false) {
|
|
1791
|
+
sections.push({ section: 'connected_model_summary', title: 'SLM summary', value: connectedModelSummary });
|
|
1792
|
+
}
|
|
1615
1793
|
sections.push({
|
|
1616
1794
|
section: 'working_memory',
|
|
1617
1795
|
title: 'Working memory',
|
|
1618
|
-
value: adv.includeWorkingMemory === false ? null : (workingMemory || {}),
|
|
1796
|
+
value: adv.includeWorkingMemory === false ? null : (compactStateSections ? compactWorkingMemoryForAgent(workingMemory || {}) : (workingMemory || {})),
|
|
1619
1797
|
why_null: adv.includeWorkingMemory === false ? 'working memory disabled' : undefined,
|
|
1620
1798
|
});
|
|
1621
1799
|
sections.push({
|
|
@@ -1639,31 +1817,31 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
1639
1817
|
sections.push({
|
|
1640
1818
|
section: 'decision_state',
|
|
1641
1819
|
title: 'Decision state',
|
|
1642
|
-
value: adv.includeDecisionState === false ? null : (decisionState || {}),
|
|
1820
|
+
value: adv.includeDecisionState === false ? null : (compactStateSections ? compactDecisionStateForAgent(decisionState || {}) : (decisionState || {})),
|
|
1643
1821
|
why_null: adv.includeDecisionState === false ? 'decision state disabled' : undefined,
|
|
1644
1822
|
});
|
|
1645
1823
|
sections.push({
|
|
1646
1824
|
section: 'operational_state',
|
|
1647
1825
|
title: 'Operational state',
|
|
1648
|
-
value: adv.includeOperationalState === false ? null : operationalState,
|
|
1826
|
+
value: adv.includeOperationalState === false ? null : (compactStateSections ? compactOperationalStateForAgent(operationalState || {}) : operationalState),
|
|
1649
1827
|
why_null: adv.includeOperationalState === false ? 'operational state disabled' : undefined,
|
|
1650
1828
|
});
|
|
1651
1829
|
sections.push({
|
|
1652
1830
|
section: 'action_ledger',
|
|
1653
1831
|
title: 'Action ledger',
|
|
1654
|
-
value: adv.includeActionLedger === false ? null : (actionLedger || []),
|
|
1832
|
+
value: adv.includeActionLedger === false ? null : (compactStateSections ? compactActionLedgerForAgent(actionLedger || [], adv.actionLedgerMaxItems || 6, adv.includeToolResults !== false) : (actionLedger || [])),
|
|
1655
1833
|
why_null: adv.includeActionLedger === false ? 'action ledger disabled' : undefined,
|
|
1656
1834
|
});
|
|
1657
1835
|
sections.push({
|
|
1658
1836
|
section: 'entity_timeline',
|
|
1659
1837
|
title: 'Entity timeline',
|
|
1660
|
-
value: adv.includeEntityTimeline === false ? null : (entityTimeline || []),
|
|
1838
|
+
value: adv.includeEntityTimeline === false ? null : (compactStateSections ? compactEntityTimelineForAgent(entityTimeline || [], adv.entityTimelineMaxItems || 8) : (entityTimeline || [])),
|
|
1661
1839
|
why_null: adv.includeEntityTimeline === false ? 'entity timeline disabled' : undefined,
|
|
1662
1840
|
});
|
|
1663
1841
|
sections.push({
|
|
1664
1842
|
section: 'vector',
|
|
1665
1843
|
title: 'Vector memories',
|
|
1666
|
-
value: vectorMemories.map((m) => {
|
|
1844
|
+
value: compactStateSections ? compactVectorMemoriesForAgent(vectorMemories, toolHistory, Number(adv.maxReturn || adv.topK || 4)) : vectorMemories.map((m) => {
|
|
1667
1845
|
const scoreMeta = scoreMetaOf(m);
|
|
1668
1846
|
const rawScore = scoreOf(m);
|
|
1669
1847
|
return {
|
|
@@ -1681,7 +1859,7 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
1681
1859
|
sections.push({
|
|
1682
1860
|
section: 'memory_compression',
|
|
1683
1861
|
title: 'Memory compression',
|
|
1684
|
-
value: adv.includeMemoryCompression === false ? null : (memoryCompression || {}),
|
|
1862
|
+
value: adv.includeMemoryCompression === false ? null : (compactStateSections ? compactMemoryCompressionForAgent(memoryCompression || {}) : (memoryCompression || {})),
|
|
1685
1863
|
why_null: adv.includeMemoryCompression === false ? 'memory compression disabled' : undefined,
|
|
1686
1864
|
});
|
|
1687
1865
|
sections.push({
|
|
@@ -1693,7 +1871,11 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
1693
1871
|
sections.push({
|
|
1694
1872
|
section: 'recent_messages',
|
|
1695
1873
|
title: 'Recent messages',
|
|
1696
|
-
value: recentMessages || [],
|
|
1874
|
+
value: compactStateSections ? pruneByLimit(recentMessages || [], adv.recentMessagesLastN || 4).map((message) => cleanContextValue({
|
|
1875
|
+
role: message.role,
|
|
1876
|
+
content: truncate(message.content, 260),
|
|
1877
|
+
at: message.at,
|
|
1878
|
+
})) : recentMessages || [],
|
|
1697
1879
|
});
|
|
1698
1880
|
sections.push({
|
|
1699
1881
|
section: 'recent_highlights',
|
|
@@ -1704,18 +1886,18 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
1704
1886
|
section: 'tool_history',
|
|
1705
1887
|
title: 'Tool history',
|
|
1706
1888
|
value: {
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1889
|
+
enabled: adv.includeToolHistory !== false,
|
|
1890
|
+
items: adv.includeToolHistory === false ? [] : (compactStateSections ? compactToolHistoryForAgent(toolHistory, adv.toolHistoryLastN || 8, adv.includeToolResults !== false) : toolHistory.map((tool) => ({
|
|
1891
|
+
id: tool.id,
|
|
1892
|
+
turnId: tool.turnId,
|
|
1893
|
+
sequence: tool.sequence,
|
|
1712
1894
|
name: tool.name,
|
|
1713
1895
|
input: tool.input,
|
|
1714
1896
|
ok: tool.ok,
|
|
1715
1897
|
at: tool.at,
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
})),
|
|
1898
|
+
source: tool.source,
|
|
1899
|
+
result: adv.includeToolResults === false ? undefined : tool.result,
|
|
1900
|
+
}))),
|
|
1719
1901
|
},
|
|
1720
1902
|
});
|
|
1721
1903
|
if (adv.includeDiagnostics) {
|
|
@@ -1726,7 +1908,7 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
1726
1908
|
});
|
|
1727
1909
|
}
|
|
1728
1910
|
const audit = {
|
|
1729
|
-
kind: '
|
|
1911
|
+
kind: 'tembory.context.v1',
|
|
1730
1912
|
meta: { user_id: userId, payloadFormat, query },
|
|
1731
1913
|
sections,
|
|
1732
1914
|
diagnostics,
|
|
@@ -1740,17 +1922,32 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
1740
1922
|
return `## ${section.title}\n${section.value.length ? section.value.map((item) => typeof item === 'string' ? `- ${item}` : `- ${truncate(safeStringify(item), 900)}`).join('\n') : '(empty)'}`;
|
|
1741
1923
|
return `## ${section.title}\n${truncate(safeStringify(section.value), 1600)}`;
|
|
1742
1924
|
};
|
|
1925
|
+
const sectionIsEmpty = (section) => {
|
|
1926
|
+
if (!compactStateSections)
|
|
1927
|
+
return false;
|
|
1928
|
+
if (section.section === 'context_header' || section.section === 'tool_guard' || section.section === 'working_memory' || section.section === 'decision_state' || section.section === 'operational_state' || section.section === 'tool_history')
|
|
1929
|
+
return false;
|
|
1930
|
+
if (section.value === null || section.value === undefined)
|
|
1931
|
+
return true;
|
|
1932
|
+
if (Array.isArray(section.value) && section.value.length === 0)
|
|
1933
|
+
return true;
|
|
1934
|
+
if (typeof section.value === 'object' && !Array.isArray(section.value) && Object.keys(section.value).length === 0)
|
|
1935
|
+
return true;
|
|
1936
|
+
return false;
|
|
1937
|
+
};
|
|
1938
|
+
const renderableSections = compactStateSections ? sections.filter((section) => !sectionIsEmpty(section)) : sections;
|
|
1743
1939
|
if (payloadFormat === 'auditJson') {
|
|
1744
1940
|
return [{ role: 'system', content: JSON.stringify(audit, null, 2) }];
|
|
1745
1941
|
}
|
|
1746
1942
|
if (payloadFormat === 'auditBlocks') {
|
|
1747
|
-
return
|
|
1943
|
+
return renderableSections.map((section) => ({ role: 'system', content: renderSection(section) }));
|
|
1748
1944
|
}
|
|
1749
|
-
const text =
|
|
1945
|
+
const text = renderableSections.map(renderSection).join('\n\n');
|
|
1946
|
+
const maxChars = Number(adv.contextMaxChars || 16000);
|
|
1750
1947
|
if (payloadFormat === 'auditText' || payloadFormat === 'singleSystemMessage' || payloadFormat === 'structured') {
|
|
1751
|
-
return [{ role: 'system', content: truncate(text,
|
|
1948
|
+
return [{ role: 'system', content: truncate(text, maxChars) }];
|
|
1752
1949
|
}
|
|
1753
|
-
return [{ role: 'system', content: truncate(text,
|
|
1950
|
+
return [{ role: 'system', content: truncate(text, maxChars) }];
|
|
1754
1951
|
};
|
|
1755
1952
|
class Mem0Memory {
|
|
1756
1953
|
constructor() {
|
|
@@ -1898,8 +2095,25 @@ class Mem0Memory {
|
|
|
1898
2095
|
{ displayName: 'MMR Lambda', name: 'mmrLambda', type: 'number', typeOptions: { minValue: 0, maxValue: 1, numberPrecision: 2 }, default: 0.5, description: 'Equilíbrio entre relevância e diversidade no MMR', displayOptions: { show: { '/retrievalMode': ['hybrid'] } } },
|
|
1899
2096
|
{ displayName: 'Incluir Cabeçalho de Contexto', name: 'includeContextHeader', type: 'boolean', default: true },
|
|
1900
2097
|
{ displayName: 'Compactar Contexto Para Agente', name: 'compactForAgent', type: 'boolean', default: false, description: 'Entrega ao agente apenas o estado acionável: working memory, decisões, estado operacional e histórico de tools compacto. Mantém detalhes completos no audit/debug.' },
|
|
1901
|
-
{ displayName: '
|
|
2098
|
+
{ displayName: 'Organizar Seções de Produção', name: 'compactStateSections', type: 'boolean', default: false, description: 'Renderiza blocos de produção com campos canônicos, remove seções vazias e evita duplicar evidências já presentes em tool_history/operational_state.' },
|
|
2099
|
+
{ displayName: 'Máximo de Caracteres do Contexto', name: 'contextMaxChars', type: 'number', default: 6000, description: 'Limite final aplicado ao contexto entregue ao agente em modos estruturados de produção.' },
|
|
1902
2100
|
{ displayName: 'Incluir Resumo', name: 'includeSummary', type: 'boolean', default: true },
|
|
2101
|
+
{ displayName: 'Incluir Resumo do SLM', name: 'includeConnectedModelSummary', type: 'boolean', default: true, description: 'Usa o modelo barato conectado ao Tembory para organizar contexto ativo e/ou memórias vetoriais em bullets curtos.' },
|
|
2102
|
+
{
|
|
2103
|
+
displayName: 'Fonte do Resumo do SLM',
|
|
2104
|
+
name: 'summarySource',
|
|
2105
|
+
type: 'options',
|
|
2106
|
+
options: [
|
|
2107
|
+
{ name: 'Automático', value: 'auto' },
|
|
2108
|
+
{ name: 'Contexto Ativo', value: 'activeContext' },
|
|
2109
|
+
{ name: 'Somente Vetores', value: 'vectorOnly' },
|
|
2110
|
+
{ name: 'Desligado', value: 'off' },
|
|
2111
|
+
],
|
|
2112
|
+
default: 'auto',
|
|
2113
|
+
description: 'Define se o SLM resume working memory/tool state, memórias vetoriais, ambos ou nada.',
|
|
2114
|
+
},
|
|
2115
|
+
{ displayName: 'Máximo de Caracteres de Entrada do SLM', name: 'connectedModelSummaryInputMaxChars', type: 'number', default: 3000 },
|
|
2116
|
+
{ displayName: 'Máximo de Caracteres do Resumo do SLM', name: 'connectedModelSummaryMaxChars', type: 'number', default: 900 },
|
|
1903
2117
|
{ displayName: 'Máximo de Fatos no Resumo', name: 'summaryMaxFacts', type: 'number', default: 4 },
|
|
1904
2118
|
{ displayName: 'Incluir Scores', name: 'includeScores', type: 'boolean', default: true },
|
|
1905
2119
|
{ displayName: 'Incluir Diagnóstico', name: 'includeDiagnostics', type: 'boolean', default: false },
|
|
@@ -1968,24 +2182,24 @@ class Mem0Memory {
|
|
|
1968
2182
|
if (loadCache.has(cacheKey)) {
|
|
1969
2183
|
result = snapshotJson(loadCache.get(cacheKey));
|
|
1970
2184
|
result.response = result.response || {};
|
|
1971
|
-
result.response.
|
|
1972
|
-
...(result.response.
|
|
2185
|
+
result.response.temboryDiagnostics = {
|
|
2186
|
+
...(result.response.temboryDiagnostics || {}),
|
|
1973
2187
|
cacheHit: true,
|
|
1974
2188
|
cacheScope: 'supplyData.loadMemoryVariables',
|
|
1975
2189
|
};
|
|
1976
|
-
if (result.response.
|
|
1977
|
-
result.response.
|
|
1978
|
-
kind: result.response.
|
|
1979
|
-
userId: result.response.
|
|
1980
|
-
project: result.response.
|
|
1981
|
-
query: result.response.
|
|
1982
|
-
retrievalMode: result.response.
|
|
1983
|
-
payloadFormat: result.response.
|
|
1984
|
-
contextQualityScore: result.response.
|
|
2190
|
+
if (result.response.temboryContext) {
|
|
2191
|
+
result.response.temboryContext = {
|
|
2192
|
+
kind: result.response.temboryContext.kind,
|
|
2193
|
+
userId: result.response.temboryContext.userId,
|
|
2194
|
+
project: result.response.temboryContext.project,
|
|
2195
|
+
query: result.response.temboryContext.query,
|
|
2196
|
+
retrievalMode: result.response.temboryContext.retrievalMode,
|
|
2197
|
+
payloadFormat: result.response.temboryContext.payloadFormat,
|
|
2198
|
+
contextQualityScore: result.response.temboryContext.contextQualityScore,
|
|
1985
2199
|
cacheHit: true,
|
|
1986
2200
|
};
|
|
1987
2201
|
}
|
|
1988
|
-
delete result.response.
|
|
2202
|
+
delete result.response.temboryContextText;
|
|
1989
2203
|
}
|
|
1990
2204
|
else {
|
|
1991
2205
|
result = await Mem0Memory.prototype.loadMemoryVariablesForItem.call(this, itemIndex, inputValues);
|
|
@@ -2016,7 +2230,7 @@ class Mem0Memory {
|
|
|
2016
2230
|
await Mem0Memory.prototype.saveContextForItem.call(this, itemIndex, inputValues, outputValues);
|
|
2017
2231
|
},
|
|
2018
2232
|
};
|
|
2019
|
-
return { response:
|
|
2233
|
+
return { response: wrapTemboryMemory(memory, this, memoryKey) };
|
|
2020
2234
|
}
|
|
2021
2235
|
async saveMessagesForItem(itemIndex, messages = []) {
|
|
2022
2236
|
const inputValues = {};
|
|
@@ -2427,7 +2641,7 @@ class Mem0Memory {
|
|
|
2427
2641
|
}
|
|
2428
2642
|
ranked = selected;
|
|
2429
2643
|
}
|
|
2430
|
-
const finalMemories = ranked.slice(0, maxReturn).map((r) =>
|
|
2644
|
+
const finalMemories = ranked.slice(0, maxReturn).map((r) => withTemboryScore(r.m, {
|
|
2431
2645
|
semanticScore: r.semanticScore,
|
|
2432
2646
|
recencyScore: r.recencyScore,
|
|
2433
2647
|
hybridScore: r.hybrid,
|
|
@@ -2437,7 +2651,7 @@ class Mem0Memory {
|
|
|
2437
2651
|
payload = finalMemories.map((m) => { var _a, _b; return ({ role: 'system', content: (_b = (_a = m.memory) !== null && _a !== void 0 ? _a : m.text) !== null && _b !== void 0 ? _b : JSON.stringify(m) }); });
|
|
2438
2652
|
}
|
|
2439
2653
|
else {
|
|
2440
|
-
vectorMemories = semMemories.map((m) =>
|
|
2654
|
+
vectorMemories = semMemories.map((m) => withTemboryScore(m, {
|
|
2441
2655
|
semanticScore: scoreOf(m),
|
|
2442
2656
|
source: 'semantic',
|
|
2443
2657
|
}));
|
|
@@ -2528,34 +2742,6 @@ class Mem0Memory {
|
|
|
2528
2742
|
}
|
|
2529
2743
|
catch { }
|
|
2530
2744
|
}
|
|
2531
|
-
let connectedModelSummary = '';
|
|
2532
|
-
if (connectedLanguageModel && typeof connectedLanguageModel.invoke === 'function' && vectorMemories.length && adv.includeSummary !== false) {
|
|
2533
|
-
try {
|
|
2534
|
-
const facts = vectorMemories.slice(0, Number(adv.summaryMaxFacts || 4)).map((memory) => contextMemoryText(memory, 500)).filter(Boolean).join('\n') || '(no vector memories found)';
|
|
2535
|
-
if (facts) {
|
|
2536
|
-
const response = await connectedLanguageModel.invoke([
|
|
2537
|
-
toBaseMessage({
|
|
2538
|
-
role: 'user',
|
|
2539
|
-
content: `Summarize available Tembory context as concise factual bullets. If there are no memories, return exactly "(empty)".\n\nQuery: ${String(query || '')}\n\nMemories:\n${truncate(facts, 3000)}`,
|
|
2540
|
-
}),
|
|
2541
|
-
]);
|
|
2542
|
-
connectedModelSummary = truncate(response?.content || response?.text || String(response || ''), 1200);
|
|
2543
|
-
connectedAi.languageModelSummary = true;
|
|
2544
|
-
}
|
|
2545
|
-
}
|
|
2546
|
-
catch (error) {
|
|
2547
|
-
connectedAi.errors.push(`languageModel.invoke: ${error.message || String(error)}`);
|
|
2548
|
-
}
|
|
2549
|
-
}
|
|
2550
|
-
const diagnostics = {
|
|
2551
|
-
vectorMemories: vectorMemories.length,
|
|
2552
|
-
recentMessages: recentMessages.length,
|
|
2553
|
-
toolHistory: toolHistory.length,
|
|
2554
|
-
graph: graph.length,
|
|
2555
|
-
project: project || null,
|
|
2556
|
-
memoryNamespace: key,
|
|
2557
|
-
connectedAi,
|
|
2558
|
-
};
|
|
2559
2745
|
const includeToolResults = adv.includeToolResults !== false;
|
|
2560
2746
|
const operationalState = deriveOperationalState(toolHistory, renderProfileFacts(profileFacts), recentMessages, includeToolResults);
|
|
2561
2747
|
const actionLedger = deriveActionLedger(toolHistory, adv.actionLedgerMaxItems || adv.toolHistoryLastN || 20, includeToolResults);
|
|
@@ -2582,6 +2768,38 @@ class Mem0Memory {
|
|
|
2582
2768
|
vectorMemories,
|
|
2583
2769
|
maxItems: adv.compressionMaxItems || 6,
|
|
2584
2770
|
});
|
|
2771
|
+
let connectedModelSummary = '';
|
|
2772
|
+
if (connectedLanguageModel && typeof connectedLanguageModel.invoke === 'function' && adv.includeSummary !== false && adv.includeConnectedModelSummary !== false) {
|
|
2773
|
+
try {
|
|
2774
|
+
const summaryInput = buildConnectedModelSummaryInput({
|
|
2775
|
+
query,
|
|
2776
|
+
profileFacts,
|
|
2777
|
+
workingMemory,
|
|
2778
|
+
decisionState,
|
|
2779
|
+
memoryCompression,
|
|
2780
|
+
operationalState,
|
|
2781
|
+
toolHistory,
|
|
2782
|
+
recentMessages,
|
|
2783
|
+
vectorMemories,
|
|
2784
|
+
highlights,
|
|
2785
|
+
adv,
|
|
2786
|
+
});
|
|
2787
|
+
connectedModelSummary = await invokeConnectedModelSummary(connectedLanguageModel, summaryInput, adv);
|
|
2788
|
+
connectedAi.languageModelSummary = Boolean(connectedModelSummary);
|
|
2789
|
+
}
|
|
2790
|
+
catch (error) {
|
|
2791
|
+
connectedAi.errors.push(`languageModel.invoke: ${error.message || String(error)}`);
|
|
2792
|
+
}
|
|
2793
|
+
}
|
|
2794
|
+
const diagnostics = {
|
|
2795
|
+
vectorMemories: vectorMemories.length,
|
|
2796
|
+
recentMessages: recentMessages.length,
|
|
2797
|
+
toolHistory: toolHistory.length,
|
|
2798
|
+
graph: graph.length,
|
|
2799
|
+
project: project || null,
|
|
2800
|
+
memoryNamespace: key,
|
|
2801
|
+
connectedAi,
|
|
2802
|
+
};
|
|
2585
2803
|
const contextHealth = deriveContextHealth({
|
|
2586
2804
|
userId: key,
|
|
2587
2805
|
project,
|
|
@@ -2619,6 +2837,7 @@ class Mem0Memory {
|
|
|
2619
2837
|
highlights,
|
|
2620
2838
|
graph,
|
|
2621
2839
|
diagnostics,
|
|
2840
|
+
connectedModelSummary,
|
|
2622
2841
|
adv,
|
|
2623
2842
|
});
|
|
2624
2843
|
diagnostics.contextSize = contextSizeOfMessages(payload);
|
|
@@ -2645,7 +2864,7 @@ class Mem0Memory {
|
|
|
2645
2864
|
const summary = vectorMemories.slice(0, Number(adv.summaryMaxFacts || 4)).map((memory) => contextMemoryText(memory, 360)).filter(Boolean);
|
|
2646
2865
|
const contextText = payload.map((message) => String(message.content || '')).join('\n\n');
|
|
2647
2866
|
const audit = {
|
|
2648
|
-
kind: '
|
|
2867
|
+
kind: 'tembory.context.v1',
|
|
2649
2868
|
userId: key,
|
|
2650
2869
|
project: project || undefined,
|
|
2651
2870
|
query,
|
|
@@ -2716,25 +2935,25 @@ class Mem0Memory {
|
|
|
2716
2935
|
return {
|
|
2717
2936
|
response: {
|
|
2718
2937
|
[memoryKey]: payload,
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2938
|
+
temboryContext: audit,
|
|
2939
|
+
temboryContextText: contextText,
|
|
2940
|
+
temborySummary: summary,
|
|
2941
|
+
temboryConnectedModelSummary: connectedModelSummary,
|
|
2942
|
+
temboryContextHealth: contextHealth,
|
|
2943
|
+
temboryContextQualityScore: contextHealth.quality_score,
|
|
2944
|
+
temboryWorkingMemory: workingMemory,
|
|
2945
|
+
temboryDecisionState: decisionState,
|
|
2946
|
+
temboryMemoryCompression: memoryCompression,
|
|
2947
|
+
temboryProfileFacts: renderProfileFacts(profileFacts),
|
|
2948
|
+
temboryOperationalState: operationalState,
|
|
2949
|
+
temboryActionLedger: actionLedger,
|
|
2950
|
+
temboryEntityTimeline: entityTimeline,
|
|
2951
|
+
temboryVectorMemories: normalizedVectorMemories,
|
|
2952
|
+
temboryGraph: graph,
|
|
2953
|
+
temboryRecentMessages: recentMessages,
|
|
2954
|
+
temboryRecentHighlights: highlights,
|
|
2955
|
+
temboryToolHistory: audit.toolHistory,
|
|
2956
|
+
temboryDiagnostics: diagnostics,
|
|
2738
2957
|
},
|
|
2739
2958
|
};
|
|
2740
2959
|
}
|
|
@@ -2854,4 +3073,7 @@ exports.__private = {
|
|
|
2854
3073
|
compactToolResult,
|
|
2855
3074
|
compactToolHistoryForAgent,
|
|
2856
3075
|
compactOperationalStateForAgent,
|
|
3076
|
+
buildConnectedModelSummaryInput,
|
|
3077
|
+
cleanModelSummaryText,
|
|
3078
|
+
invokeConnectedModelSummary,
|
|
2857
3079
|
};
|
package/package.json
CHANGED
|
@@ -42,20 +42,20 @@ const toolHistory = [
|
|
|
42
42
|
ok: true,
|
|
43
43
|
at: '2026-05-14T05:34:34.017Z',
|
|
44
44
|
source: 'used_tools_text',
|
|
45
|
-
result: '[{"args":{"tool":"agenda_pre_reservar_horario","reservation_id":"RES-
|
|
45
|
+
result: '[{"args":{"tool":"agenda_pre_reservar_horario","reservation_id":"RES-TEMBORY-LAB-001","selected_from_message":"dia 13","status":"pre_reserved","next_step":"confirmar_agendamento"}}]',
|
|
46
46
|
},
|
|
47
47
|
];
|
|
48
48
|
|
|
49
49
|
const vectorMemories = [
|
|
50
50
|
{
|
|
51
|
-
memory: '[Used tools: Tool: agenda_pre_reservar_horario, Input: , Result: [{"args":{"tool":"agenda_pre_reservar_horario","reservation_id":"RES-
|
|
51
|
+
memory: '[Used tools: Tool: agenda_pre_reservar_horario, Input: , Result: [{"args":{"tool":"agenda_pre_reservar_horario","reservation_id":"RES-TEMBORY-LAB-001","selected_from_message":"dia 13","status":"pre_reserved","next_step":"confirmar_agendamento"}}]] Calling agenda_pre_reservar_horario with input: {"id":"call_bfHlltcjI1vCagRkav0fj8Ha"}\nPré-reserva feita para o dia 13.\nSe quiser, posso confirmar agora.',
|
|
52
52
|
created_at: '2026-05-14T05:34:35.373020Z',
|
|
53
|
-
|
|
53
|
+
temboryScore: { semanticScore: 0.71, recencyScore: 0.99, hybridScore: 0.81, source: 'semantic' },
|
|
54
54
|
},
|
|
55
55
|
{
|
|
56
56
|
memory: '[Used tools: Tool: agenda_consultar_disponibilidade, Input: , Result: [{"args":{"tool":"agenda_consultar_disponibilidade","available_slots":"2026-05-12T09:00,2026-05-12T14:00,2026-05-13T10:30","timezone":"America/Sao_Paulo","next_step":"escolher_um_horario"}}]] Temos estes horários vagos:\n- 12/05 às 09:00\n- 12/05 às 14:00\n- 13/05 às 10:30',
|
|
57
57
|
created_at: '2026-05-14T05:34:14.717988Z',
|
|
58
|
-
|
|
58
|
+
temboryScore: { semanticScore: 0.7, recencyScore: 0.99, hybridScore: 0.8, source: 'semantic' },
|
|
59
59
|
},
|
|
60
60
|
{ memory: 'Oi! Como posso ajudar?', created_at: '2026-05-14T05:33:47.194630Z' },
|
|
61
61
|
{ memory: 'oi', created_at: '2026-05-14T05:33:47.194355Z' },
|
|
@@ -87,7 +87,7 @@ const common = {
|
|
|
87
87
|
toolHistory,
|
|
88
88
|
highlights: [
|
|
89
89
|
'tool agenda_consultar_disponibilidade: [{"args":{"available_slots":"2026-05-12T09:00,2026-05-12T14:00,2026-05-13T10:30"}}]',
|
|
90
|
-
'tool agenda_pre_reservar_horario: [{"args":{"reservation_id":"RES-
|
|
90
|
+
'tool agenda_pre_reservar_horario: [{"args":{"reservation_id":"RES-TEMBORY-LAB-001","status":"pre_reserved"}}]',
|
|
91
91
|
],
|
|
92
92
|
graph: [],
|
|
93
93
|
diagnostics: {},
|
|
@@ -106,7 +106,7 @@ for (const [name, adv] of modes) {
|
|
|
106
106
|
size: core.contextSizeOfMessages(messages),
|
|
107
107
|
has_next_expected_action: /next_expected_action/.test(text),
|
|
108
108
|
has_do_not_repeat_tools: /do_not_repeat_tools/.test(text),
|
|
109
|
-
has_reservation_id: /RES-
|
|
109
|
+
has_reservation_id: /RES-TEMBORY-LAB-001/.test(text),
|
|
110
110
|
has_available_slots: /available_slots/.test(text),
|
|
111
111
|
has_duplicate_calling_text: /Calling agenda_pre_reservar_horario/.test(text),
|
|
112
112
|
}, null, 2));
|