n8n-nodes-tembory 1.0.37 → 1.0.38
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/dist/nodes/Mem0/Mem0Memory.node.js +134 -22
- package/package.json +1 -1
|
@@ -852,10 +852,13 @@ const makeToolEventId = (tool, sequence = 0) => {
|
|
|
852
852
|
return `tool_${hashString(base)}`;
|
|
853
853
|
};
|
|
854
854
|
const canonicalToolInput = (value) => {
|
|
855
|
-
const text =
|
|
856
|
-
|
|
855
|
+
const text = value === undefined || value === null
|
|
856
|
+
? ''
|
|
857
|
+
: (typeof value === 'string' ? value : stableStringify(value));
|
|
858
|
+
const trimmed = String(text).trim();
|
|
859
|
+
if (trimmed === '""' || trimmed === "''")
|
|
857
860
|
return '';
|
|
858
|
-
return
|
|
861
|
+
return trimmed;
|
|
859
862
|
};
|
|
860
863
|
const normalizeToolCall = (tool, sequence = 0, defaults = {}) => {
|
|
861
864
|
const at = tool.at || defaults.at || nowIso();
|
|
@@ -910,6 +913,73 @@ const readDeep = (value, visitor, seen = new Set()) => {
|
|
|
910
913
|
for (const item of Object.values(value))
|
|
911
914
|
readDeep(item, visitor, seen);
|
|
912
915
|
};
|
|
916
|
+
const messageTypeOf = (message) => {
|
|
917
|
+
if (typeof (message === null || message === void 0 ? void 0 : message._getType) === 'function')
|
|
918
|
+
return String(message._getType() || '');
|
|
919
|
+
return String((message === null || message === void 0 ? void 0 : message.role) || (message === null || message === void 0 ? void 0 : message.type) || (message === null || message === void 0 ? void 0 : message.lc_kwargs && message.lc_kwargs.type) || '').toLowerCase();
|
|
920
|
+
};
|
|
921
|
+
const messageContentOf = (message) => typeof (message === null || message === void 0 ? void 0 : message.content) === 'string' ? message.content : safeStringify(message === null || message === void 0 ? void 0 : message.content);
|
|
922
|
+
const extractToolCallsFromMessages = (messages = []) => {
|
|
923
|
+
const calls = [];
|
|
924
|
+
const toolCallById = new Map();
|
|
925
|
+
const push = (tool, index = calls.length) => {
|
|
926
|
+
if (!tool || !(tool.name || tool.tool || tool.toolName))
|
|
927
|
+
return;
|
|
928
|
+
const normalized = normalizeToolCall({
|
|
929
|
+
id: tool.id || tool.callId || tool.call_id || tool.toolCallId || tool.tool_call_id,
|
|
930
|
+
turnId: tool.turnId || tool.turn_id,
|
|
931
|
+
sequence: tool.sequence || index + 1,
|
|
932
|
+
name: tool.name || tool.tool || tool.toolName,
|
|
933
|
+
input: tool.input !== undefined ? tool.input : tool.args !== undefined ? tool.args : tool.toolInput !== undefined ? tool.toolInput : '',
|
|
934
|
+
ok: tool.ok !== false,
|
|
935
|
+
result: tool.result !== undefined ? tool.result : tool.output !== undefined ? tool.output : tool.observation !== undefined ? tool.observation : '',
|
|
936
|
+
at: tool.at || nowIso(),
|
|
937
|
+
source: tool.source || 'langchain_message',
|
|
938
|
+
}, calls.length + 1);
|
|
939
|
+
calls.push(normalized);
|
|
940
|
+
if (normalized.id)
|
|
941
|
+
toolCallById.set(String(normalized.id), normalized);
|
|
942
|
+
};
|
|
943
|
+
for (const [index, message] of (messages || []).entries()) {
|
|
944
|
+
const type = messageTypeOf(message);
|
|
945
|
+
const additional = (message && (message.additional_kwargs || message.additionalKwargs)) || {};
|
|
946
|
+
const kwargs = (message && message.lc_kwargs) || {};
|
|
947
|
+
const toolCalls = message && (message.tool_calls || message.toolCalls || additional.tool_calls || additional.toolCalls || kwargs.tool_calls || kwargs.toolCalls);
|
|
948
|
+
if (Array.isArray(toolCalls)) {
|
|
949
|
+
for (const tool of toolCalls)
|
|
950
|
+
push({ ...tool, source: 'ai_message_tool_calls' }, index);
|
|
951
|
+
}
|
|
952
|
+
const invalidToolCalls = message && (message.invalid_tool_calls || message.invalidToolCalls || additional.invalid_tool_calls || additional.invalidToolCalls);
|
|
953
|
+
if (Array.isArray(invalidToolCalls)) {
|
|
954
|
+
for (const tool of invalidToolCalls)
|
|
955
|
+
push({ ...tool, ok: false, source: 'ai_message_invalid_tool_calls' }, index);
|
|
956
|
+
}
|
|
957
|
+
if (type === 'tool') {
|
|
958
|
+
const id = message.tool_call_id || message.toolCallId || additional.tool_call_id || additional.toolCallId || message.id;
|
|
959
|
+
const name = message.name || message.toolName || message.tool || additional.name || additional.tool_name || additional.toolName || kwargs.name || 'tool';
|
|
960
|
+
const existing = id ? toolCallById.get(String(id)) : null;
|
|
961
|
+
if (existing) {
|
|
962
|
+
existing.result = summarizeToolResult(messageContentOf(message));
|
|
963
|
+
existing.result_summary = existing.result;
|
|
964
|
+
existing.ok = true;
|
|
965
|
+
existing.status = 'ok';
|
|
966
|
+
existing.result_hash = stableHash(existing.result || '');
|
|
967
|
+
existing.dedupe_key = toolEventKey(existing);
|
|
968
|
+
}
|
|
969
|
+
else {
|
|
970
|
+
push({
|
|
971
|
+
id,
|
|
972
|
+
name,
|
|
973
|
+
input: '',
|
|
974
|
+
result: messageContentOf(message),
|
|
975
|
+
ok: true,
|
|
976
|
+
source: 'tool_message',
|
|
977
|
+
}, index);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
return dedupeToolHistory(calls);
|
|
982
|
+
};
|
|
913
983
|
const extractToolCallsFromText = (text, at = nowIso()) => {
|
|
914
984
|
const calls = [];
|
|
915
985
|
const source = String(text || '');
|
|
@@ -1022,15 +1092,17 @@ const getMemoryStore = (ctx) => {
|
|
|
1022
1092
|
data.tembory.memoryCompression = data.tembory.memoryCompression || {};
|
|
1023
1093
|
data.tembory.activeSummary = data.tembory.activeSummary || {};
|
|
1024
1094
|
data.tembory.connectedModelSummaryCache = data.tembory.connectedModelSummaryCache || {};
|
|
1095
|
+
data.tembory.captureState = data.tembory.captureState || {};
|
|
1025
1096
|
return data.tembory;
|
|
1026
1097
|
}
|
|
1027
1098
|
catch {
|
|
1028
|
-
global.__temboryMemory = global.__temboryMemory || { toolHistory: {}, recentMessages: {}, profileFacts: {}, workingMemory: {}, decisionState: {}, memoryCompression: {}, activeSummary: {}, connectedModelSummaryCache: {} };
|
|
1099
|
+
global.__temboryMemory = global.__temboryMemory || { toolHistory: {}, recentMessages: {}, profileFacts: {}, workingMemory: {}, decisionState: {}, memoryCompression: {}, activeSummary: {}, connectedModelSummaryCache: {}, captureState: {} };
|
|
1029
1100
|
global.__temboryMemory.workingMemory = global.__temboryMemory.workingMemory || {};
|
|
1030
1101
|
global.__temboryMemory.decisionState = global.__temboryMemory.decisionState || {};
|
|
1031
1102
|
global.__temboryMemory.memoryCompression = global.__temboryMemory.memoryCompression || {};
|
|
1032
1103
|
global.__temboryMemory.activeSummary = global.__temboryMemory.activeSummary || {};
|
|
1033
1104
|
global.__temboryMemory.connectedModelSummaryCache = global.__temboryMemory.connectedModelSummaryCache || {};
|
|
1105
|
+
global.__temboryMemory.captureState = global.__temboryMemory.captureState || {};
|
|
1034
1106
|
return global.__temboryMemory;
|
|
1035
1107
|
}
|
|
1036
1108
|
};
|
|
@@ -1824,9 +1896,20 @@ const compactEntityTimelineForAgent = (timeline = [], maxItems = 8) => pruneByLi
|
|
|
1824
1896
|
at: item.at,
|
|
1825
1897
|
source: item.source_type || item.source,
|
|
1826
1898
|
}));
|
|
1899
|
+
const isConversationEchoMemory = (memory) => {
|
|
1900
|
+
const meta = metadataOf(memory);
|
|
1901
|
+
const kind = String(meta.kind || meta.type || '').toLowerCase();
|
|
1902
|
+
if (/^(recent_message|conversation_ledger|conversation_message)$/i.test(kind))
|
|
1903
|
+
return true;
|
|
1904
|
+
const raw = memoryText(memory);
|
|
1905
|
+
if (parseRecentMessageMarker(raw) || parseConversationLedgerMarker(raw).length)
|
|
1906
|
+
return true;
|
|
1907
|
+
return /__tembory_conversation_ledger_v1__/.test(String(raw || ''));
|
|
1908
|
+
};
|
|
1827
1909
|
const compactVectorMemoriesForAgent = (vectorMemories = [], toolHistory = [], maxItems = 3) => {
|
|
1828
1910
|
const hasStructuredTools = Array.isArray(toolHistory) && toolHistory.length > 0;
|
|
1829
1911
|
return (vectorMemories || [])
|
|
1912
|
+
.filter((memory) => !isConversationEchoMemory(memory))
|
|
1830
1913
|
.map((memory) => contextMemoryText(memory, 220))
|
|
1831
1914
|
.filter(Boolean)
|
|
1832
1915
|
.filter((text) => !/^\[recent_message\]/i.test(text))
|
|
@@ -2202,7 +2285,7 @@ const buildContextMessages = ({ payloadFormat, query, userId, profileFacts, work
|
|
|
2202
2285
|
sections.push({
|
|
2203
2286
|
section: 'vector',
|
|
2204
2287
|
title: 'Vector memories',
|
|
2205
|
-
value: compactStateSections ? compactVectorMemoriesForAgent(vectorMemories, toolHistory, Number(adv.maxReturn || adv.topK || 4)) : vectorMemories.map((m) => {
|
|
2288
|
+
value: compactStateSections ? compactVectorMemoriesForAgent(vectorMemories, toolHistory, Number(adv.maxReturn || adv.topK || 4)) : vectorMemories.filter((m) => !isConversationEchoMemory(m)).map((m) => {
|
|
2206
2289
|
const scoreMeta = scoreMetaOf(m);
|
|
2207
2290
|
const rawScore = scoreOf(m);
|
|
2208
2291
|
return {
|
|
@@ -2634,6 +2717,18 @@ class Mem0Memory {
|
|
|
2634
2717
|
const memoryKey = this.getNodeParameter('memoryKey', itemIndex);
|
|
2635
2718
|
let currentMessages = [];
|
|
2636
2719
|
const loadCache = new Map();
|
|
2720
|
+
const recordMemoryEvent = (action, payload = {}, error) => {
|
|
2721
|
+
const { index } = this.addInputData(n8n_workflow_1.NodeConnectionTypes.AiMemory, [
|
|
2722
|
+
[{ json: { action, ...(payload.input !== undefined ? { input: payload.input } : {}), ...(payload.values !== undefined ? { values: payload.values } : {}) } }],
|
|
2723
|
+
]);
|
|
2724
|
+
if (error) {
|
|
2725
|
+
this.addOutputData(n8n_workflow_1.NodeConnectionTypes.AiMemory, index, error);
|
|
2726
|
+
return;
|
|
2727
|
+
}
|
|
2728
|
+
this.addOutputData(n8n_workflow_1.NodeConnectionTypes.AiMemory, index, [
|
|
2729
|
+
[{ json: { action, ...payload } }],
|
|
2730
|
+
]);
|
|
2731
|
+
};
|
|
2637
2732
|
const memory = {
|
|
2638
2733
|
memoryKeys: [memoryKey],
|
|
2639
2734
|
inputKey: 'input',
|
|
@@ -2643,21 +2738,25 @@ class Mem0Memory {
|
|
|
2643
2738
|
getMessages: async () => currentMessages,
|
|
2644
2739
|
addMessage: async (message) => {
|
|
2645
2740
|
currentMessages.push(message);
|
|
2646
|
-
await Mem0Memory.prototype.saveMessagesForItem.call(this, itemIndex, [message]);
|
|
2741
|
+
const saved = await Mem0Memory.prototype.saveMessagesForItem.call(this, itemIndex, [message]);
|
|
2742
|
+
recordMemoryEvent('chatHistory.addMessage', { saved: Boolean(saved && saved.saved), toolCalls: (saved && saved.toolCalls) || [], messages: 1 });
|
|
2647
2743
|
},
|
|
2648
2744
|
addUserMessage: async (message) => {
|
|
2649
2745
|
const baseMessage = toBaseMessage({ role: 'user', content: message });
|
|
2650
2746
|
currentMessages.push(baseMessage);
|
|
2651
|
-
await Mem0Memory.prototype.saveMessagesForItem.call(this, itemIndex, [baseMessage]);
|
|
2747
|
+
const saved = await Mem0Memory.prototype.saveMessagesForItem.call(this, itemIndex, [baseMessage]);
|
|
2748
|
+
recordMemoryEvent('chatHistory.addUserMessage', { saved: Boolean(saved && saved.saved), toolCalls: (saved && saved.toolCalls) || [], messages: 1 });
|
|
2652
2749
|
},
|
|
2653
2750
|
addAIChatMessage: async (message) => {
|
|
2654
2751
|
const baseMessage = toBaseMessage({ role: 'assistant', content: message });
|
|
2655
2752
|
currentMessages.push(baseMessage);
|
|
2656
|
-
await Mem0Memory.prototype.saveMessagesForItem.call(this, itemIndex, [baseMessage]);
|
|
2753
|
+
const saved = await Mem0Memory.prototype.saveMessagesForItem.call(this, itemIndex, [baseMessage]);
|
|
2754
|
+
recordMemoryEvent('chatHistory.addAIChatMessage', { saved: Boolean(saved && saved.saved), toolCalls: (saved && saved.toolCalls) || [], messages: 1 });
|
|
2657
2755
|
},
|
|
2658
2756
|
addMessages: async (messages) => {
|
|
2659
2757
|
currentMessages.push(...messages);
|
|
2660
|
-
await Mem0Memory.prototype.saveMessagesForItem.call(this, itemIndex, messages);
|
|
2758
|
+
const saved = await Mem0Memory.prototype.saveMessagesForItem.call(this, itemIndex, messages);
|
|
2759
|
+
recordMemoryEvent('chatHistory.addMessages', { saved: Boolean(saved && saved.saved), toolCalls: (saved && saved.toolCalls) || [], messages: Array.isArray(messages) ? messages.length : 0 });
|
|
2661
2760
|
},
|
|
2662
2761
|
clear: async () => {
|
|
2663
2762
|
currentMessages = [];
|
|
@@ -2722,25 +2821,16 @@ class Mem0Memory {
|
|
|
2722
2821
|
async saveMessagesForItem(itemIndex, messages = []) {
|
|
2723
2822
|
const inputValues = {};
|
|
2724
2823
|
const outputValues = {};
|
|
2725
|
-
const toolCalls =
|
|
2824
|
+
const toolCalls = extractToolCallsFromMessages(messages);
|
|
2726
2825
|
const inputParts = [];
|
|
2727
2826
|
const outputParts = [];
|
|
2728
2827
|
for (const message of messages || []) {
|
|
2729
|
-
const type =
|
|
2730
|
-
const content =
|
|
2828
|
+
const type = messageTypeOf(message);
|
|
2829
|
+
const content = messageContentOf(message);
|
|
2731
2830
|
if (type === 'human' || type === 'user')
|
|
2732
2831
|
inputParts.push(content);
|
|
2733
2832
|
else if (type === 'ai' || type === 'assistant')
|
|
2734
2833
|
outputParts.push(content);
|
|
2735
|
-
else if (type === 'tool') {
|
|
2736
|
-
toolCalls.push({
|
|
2737
|
-
name: message.name || message.toolName || message.tool || (message.additional_kwargs && (message.additional_kwargs.name || message.additional_kwargs.tool_name)) || 'tool',
|
|
2738
|
-
input: '',
|
|
2739
|
-
ok: true,
|
|
2740
|
-
result: summarizeToolResult(content),
|
|
2741
|
-
at: nowIso(),
|
|
2742
|
-
});
|
|
2743
|
-
}
|
|
2744
2834
|
}
|
|
2745
2835
|
if (inputParts.length)
|
|
2746
2836
|
inputValues.input = inputParts.join('\n');
|
|
@@ -2751,8 +2841,11 @@ class Mem0Memory {
|
|
|
2751
2841
|
outputValues.output = outputParts.join('\n').trim();
|
|
2752
2842
|
if (toolContext.length)
|
|
2753
2843
|
outputValues.__temboryToolCalls = toolContext;
|
|
2754
|
-
if (inputValues.input || outputValues.output)
|
|
2844
|
+
if (inputValues.input || outputValues.output || toolContext.length) {
|
|
2755
2845
|
await Mem0Memory.prototype.saveContextForItem.call(this, itemIndex, inputValues, outputValues);
|
|
2846
|
+
return { saved: true, input: inputValues, output: outputValues, toolCalls: toolContext };
|
|
2847
|
+
}
|
|
2848
|
+
return { saved: false, input: inputValues, output: outputValues, toolCalls: toolContext };
|
|
2756
2849
|
}
|
|
2757
2850
|
async saveContextForItem(itemIndex, inputValues = {}, outputValues = {}) {
|
|
2758
2851
|
const threadId = this.getNodeParameter('threadId', itemIndex);
|
|
@@ -2764,6 +2857,14 @@ class Mem0Memory {
|
|
|
2764
2857
|
const rawOutput = pickText(outputValues, ['output', 'response', 'text', 'answer']);
|
|
2765
2858
|
const output = cleanAssistantTranscriptText(rawOutput);
|
|
2766
2859
|
const toolCalls = extractToolCalls(outputValues);
|
|
2860
|
+
store.captureState[key] = {
|
|
2861
|
+
last_save_at: nowIso(),
|
|
2862
|
+
last_save_had_input: Boolean(input),
|
|
2863
|
+
last_save_had_output: Boolean(output),
|
|
2864
|
+
last_save_tool_calls_captured: toolCalls.length,
|
|
2865
|
+
last_save_tool_names: toolCalls.map((tool) => tool.name).filter(Boolean).slice(0, 20),
|
|
2866
|
+
last_save_capture_sources: Array.from(new Set(toolCalls.map((tool) => tool.source).filter(Boolean))),
|
|
2867
|
+
};
|
|
2767
2868
|
const recentForMem0 = [];
|
|
2768
2869
|
const profileFromTurn = extractProfileFactsFromText(input, 'user_message', nowIso());
|
|
2769
2870
|
if (Object.keys(profileFromTurn).length) {
|
|
@@ -3559,6 +3660,14 @@ class Mem0Memory {
|
|
|
3559
3660
|
graph: graph.length,
|
|
3560
3661
|
project: project || null,
|
|
3561
3662
|
memoryNamespace: key,
|
|
3663
|
+
captureState: store.captureState[key] || {
|
|
3664
|
+
last_save_at: null,
|
|
3665
|
+
last_save_had_input: false,
|
|
3666
|
+
last_save_had_output: false,
|
|
3667
|
+
last_save_tool_calls_captured: 0,
|
|
3668
|
+
last_save_tool_names: [],
|
|
3669
|
+
last_save_capture_sources: [],
|
|
3670
|
+
},
|
|
3562
3671
|
connectedAi,
|
|
3563
3672
|
activeSummary: summaryDiagnostics,
|
|
3564
3673
|
};
|
|
@@ -3803,6 +3912,7 @@ exports.Mem0Memory = Mem0Memory;
|
|
|
3803
3912
|
exports.__private = {
|
|
3804
3913
|
extractToolCallsFromText,
|
|
3805
3914
|
extractToolCalls,
|
|
3915
|
+
extractToolCallsFromMessages,
|
|
3806
3916
|
toolHistoryItemsFromMemory,
|
|
3807
3917
|
explicitToolHistoryItemsFromMemory,
|
|
3808
3918
|
toolHistoryFromMemory,
|
|
@@ -3855,6 +3965,8 @@ exports.__private = {
|
|
|
3855
3965
|
embedQueryCached,
|
|
3856
3966
|
compactToolResult,
|
|
3857
3967
|
compactToolHistoryForAgent,
|
|
3968
|
+
compactVectorMemoriesForAgent,
|
|
3969
|
+
isConversationEchoMemory,
|
|
3858
3970
|
compactOperationalStateForAgent,
|
|
3859
3971
|
activeSummaryIsFresh,
|
|
3860
3972
|
readActiveSummary,
|
package/package.json
CHANGED