n8n-nodes-tembory 1.0.23 → 1.0.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.
- package/README.md +13 -1
- package/dist/nodes/Mem0/Mem0Memory.node.js +69 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,19 @@
|
|
|
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.25`.
|
|
6
|
+
|
|
7
|
+
## 1.0.25
|
|
8
|
+
|
|
9
|
+
- Carrega a janela recente tambem a partir de memorias vetoriais com `kind=recent_message`.
|
|
10
|
+
- Adiciona uma busca auxiliar de transcript recente no modo BYO-AI para perguntas como "qual foi minha ultima mensagem" e "o que eu ja disse".
|
|
11
|
+
- Evita depender do endpoint legado `/v1/memories/` para reconstruir conversa curta.
|
|
12
|
+
|
|
13
|
+
## 1.0.24
|
|
14
|
+
|
|
15
|
+
- Corrige falha `409 Backend LLM/embedder is disabled` no `saveContext` quando o node usa embeddings conectados pelo n8n.
|
|
16
|
+
- Writes legados de transcript/tool markers agora sao best-effort no modo BYO-AI, sem derrubar a execucao do agente.
|
|
17
|
+
- Remove o prefixo tecnico `THREAD:<id>` usado em testes MCP antes de montar query/contexto de memoria.
|
|
6
18
|
|
|
7
19
|
## 1.0.23
|
|
8
20
|
|
|
@@ -70,6 +70,22 @@ const searchClientVectorMemories = async (ctx, embedding, query, body = {}) => {
|
|
|
70
70
|
embedding: await embedQueryCached(embedding, text),
|
|
71
71
|
});
|
|
72
72
|
};
|
|
73
|
+
const safePersistLegacyMemory = async (ctx, body, diagnostics = {}) => {
|
|
74
|
+
try {
|
|
75
|
+
return await GenericFunctions_1.mem0ApiRequest.call(ctx, 'POST', '/v1/memories/', body);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
try {
|
|
79
|
+
ctx.logger?.warn('Tembory skipped legacy memory write after BYO-AI vector persistence', {
|
|
80
|
+
...diagnostics,
|
|
81
|
+
message: error.message || String(error),
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
catch { }
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const stripThreadTestPrefix = (value = '') => String(value || '').replace(/^THREAD:[A-Za-z0-9_-]+\s+/, '');
|
|
73
89
|
const stableStringify = (value) => {
|
|
74
90
|
if (value === null || typeof value !== 'object')
|
|
75
91
|
return JSON.stringify(value);
|
|
@@ -2616,7 +2632,7 @@ class Mem0Memory {
|
|
|
2616
2632
|
const adv = applyOperationalPreset(readAdvancedOptions(this, itemIndex));
|
|
2617
2633
|
const store = getMemoryStore(this);
|
|
2618
2634
|
const key = userKeyFrom(threadId, adv, project);
|
|
2619
|
-
const input = pickText(inputValues, ['input', 'chatInput', 'text', 'query', 'question']);
|
|
2635
|
+
const input = stripThreadTestPrefix(pickText(inputValues, ['input', 'chatInput', 'text', 'query', 'question']));
|
|
2620
2636
|
const output = pickText(outputValues, ['output', 'response', 'text', 'answer']);
|
|
2621
2637
|
const toolCalls = extractToolCalls(outputValues);
|
|
2622
2638
|
const recentForMem0 = [];
|
|
@@ -2758,7 +2774,7 @@ class Mem0Memory {
|
|
|
2758
2774
|
await saveClientVectorMemories(this, clientMemories, ids);
|
|
2759
2775
|
if (adv.includeRecentMessages !== false && recentForMem0.length) {
|
|
2760
2776
|
for (const recent of recentForMem0) {
|
|
2761
|
-
await
|
|
2777
|
+
await safePersistLegacyMemory(this, {
|
|
2762
2778
|
messages: [{ role: 'system', content: encodeRecentMessage(recent, threadId) }],
|
|
2763
2779
|
infer: false,
|
|
2764
2780
|
user_id: body.user_id,
|
|
@@ -2773,12 +2789,15 @@ class Mem0Memory {
|
|
|
2773
2789
|
project: project || undefined,
|
|
2774
2790
|
source: 'tembory_transcript',
|
|
2775
2791
|
},
|
|
2792
|
+
}, {
|
|
2793
|
+
kind: 'recent_message',
|
|
2794
|
+
user_id: body.user_id,
|
|
2776
2795
|
});
|
|
2777
2796
|
}
|
|
2778
2797
|
}
|
|
2779
2798
|
if (adv.includeToolHistory !== false && toolCalls.length) {
|
|
2780
2799
|
for (const tool of toolCalls) {
|
|
2781
|
-
await
|
|
2800
|
+
await safePersistLegacyMemory(this, {
|
|
2782
2801
|
messages: [{ role: 'system', content: encodeToolCall(tool, threadId) }],
|
|
2783
2802
|
infer: false,
|
|
2784
2803
|
user_id: body.user_id,
|
|
@@ -2798,6 +2817,10 @@ class Mem0Memory {
|
|
|
2798
2817
|
thread_id: threadId,
|
|
2799
2818
|
project: project || undefined,
|
|
2800
2819
|
},
|
|
2820
|
+
}, {
|
|
2821
|
+
kind: 'tool_history',
|
|
2822
|
+
user_id: body.user_id,
|
|
2823
|
+
tool: tool.name,
|
|
2801
2824
|
});
|
|
2802
2825
|
}
|
|
2803
2826
|
}
|
|
@@ -2892,7 +2915,7 @@ class Mem0Memory {
|
|
|
2892
2915
|
const store = getMemoryStore(this);
|
|
2893
2916
|
const key = userKeyFrom(threadId, adv, project);
|
|
2894
2917
|
const queryParam = this.getNodeParameter('query', itemIndex, '');
|
|
2895
|
-
const query = asSearchQuery(queryParam) || asSearchQuery(inputValues.query) || asSearchQuery(inputValues.input) || asSearchQuery(inputValues.chatInput);
|
|
2918
|
+
const query = stripThreadTestPrefix(asSearchQuery(queryParam) || asSearchQuery(inputValues.query) || asSearchQuery(inputValues.input) || asSearchQuery(inputValues.chatInput));
|
|
2896
2919
|
let connectedLanguageModel;
|
|
2897
2920
|
let connectedEmbedding;
|
|
2898
2921
|
const connectedAi = {
|
|
@@ -3109,6 +3132,41 @@ class Mem0Memory {
|
|
|
3109
3132
|
connectedAi.errors.push(`graph.relations: ${error.message || String(error)}`);
|
|
3110
3133
|
}
|
|
3111
3134
|
}
|
|
3135
|
+
if (connectedEmbedding && adv.includeRecentMessages !== false) {
|
|
3136
|
+
try {
|
|
3137
|
+
const transcriptProbe = [
|
|
3138
|
+
'recent conversation transcript',
|
|
3139
|
+
'last user messages previous message',
|
|
3140
|
+
query,
|
|
3141
|
+
].filter(Boolean).join('\n');
|
|
3142
|
+
const transcriptBody = {
|
|
3143
|
+
user_id: key,
|
|
3144
|
+
agent_id: adv.agentId ? String(adv.agentId) : undefined,
|
|
3145
|
+
run_id: adv.runId ? String(adv.runId) : undefined,
|
|
3146
|
+
top_k: Math.max(Number(adv.recentMessagesLastN || 8) * 3, 20),
|
|
3147
|
+
filters: { kind: 'recent_message' },
|
|
3148
|
+
};
|
|
3149
|
+
const transcriptRes = await searchClientVectorMemories(this, connectedEmbedding, transcriptProbe, transcriptBody);
|
|
3150
|
+
const transcriptMemories = normalizeResults(transcriptRes).map((memory) => withTemboryScore(memory, {
|
|
3151
|
+
semanticScore: scoreOf(memory),
|
|
3152
|
+
source: 'recent_message_probe',
|
|
3153
|
+
}));
|
|
3154
|
+
if (transcriptMemories.length) {
|
|
3155
|
+
const seen = new Set(vectorMemories.map((memory) => stableHash(memoryText(memory) || safeStringify(memory))));
|
|
3156
|
+
for (const memory of transcriptMemories) {
|
|
3157
|
+
const hash = stableHash(memoryText(memory) || safeStringify(memory));
|
|
3158
|
+
if (!seen.has(hash)) {
|
|
3159
|
+
seen.add(hash);
|
|
3160
|
+
vectorMemories.push(memory);
|
|
3161
|
+
}
|
|
3162
|
+
}
|
|
3163
|
+
connectedAi.recentMessageProbe = true;
|
|
3164
|
+
}
|
|
3165
|
+
}
|
|
3166
|
+
catch (error) {
|
|
3167
|
+
connectedAi.errors.push(`recentMessageProbe: ${error.message || String(error)}`);
|
|
3168
|
+
}
|
|
3169
|
+
}
|
|
3112
3170
|
let persistedRecentMessages = [];
|
|
3113
3171
|
let persistedToolHistory = [];
|
|
3114
3172
|
let persistedMemoryItems = [];
|
|
@@ -3132,12 +3190,16 @@ class Mem0Memory {
|
|
|
3132
3190
|
.filter(Boolean)
|
|
3133
3191
|
.sort((a, b) => new Date(a.at || 0).getTime() - new Date(b.at || 0).getTime());
|
|
3134
3192
|
}
|
|
3193
|
+
const vectorRecentMessages = adv.includeRecentMessages === false ? [] : vectorMemories
|
|
3194
|
+
.map(recentMessageFromMemory)
|
|
3195
|
+
.filter(Boolean)
|
|
3196
|
+
.sort((a, b) => new Date(a.at || 0).getTime() - new Date(b.at || 0).getTime());
|
|
3135
3197
|
if (adv.includeToolHistory !== false) {
|
|
3136
3198
|
persistedToolHistory = persistedMemoryItems
|
|
3137
3199
|
.flatMap(toolHistoryItemsFromMemory)
|
|
3138
3200
|
.sort((a, b) => new Date(a.at || 0).getTime() - new Date(b.at || 0).getTime());
|
|
3139
3201
|
}
|
|
3140
|
-
const storedRecentMessages = adv.includeRecentMessages === false ? [] : (store.recentMessages[key] || []).concat(persistedRecentMessages);
|
|
3202
|
+
const storedRecentMessages = adv.includeRecentMessages === false ? [] : (store.recentMessages[key] || []).concat(persistedRecentMessages, vectorRecentMessages);
|
|
3141
3203
|
const allRecentMessages = dedupeRecentMessages(appendCurrentUserMessage(storedRecentMessages, query));
|
|
3142
3204
|
const recentMessages = pruneByLimit(allRecentMessages, Math.max(Number(adv.recentMessagesLastN || 8), 8));
|
|
3143
3205
|
const toolHistoryFromRecentMessages = [];
|
|
@@ -3517,6 +3579,8 @@ exports.__private = {
|
|
|
3517
3579
|
applyOperationalPreset,
|
|
3518
3580
|
flattenAdvancedGroups,
|
|
3519
3581
|
asSearchQuery,
|
|
3582
|
+
safePersistLegacyMemory,
|
|
3583
|
+
stripThreadTestPrefix,
|
|
3520
3584
|
canonicalToolInput,
|
|
3521
3585
|
buildContextMessages,
|
|
3522
3586
|
inferToolGuard,
|
package/package.json
CHANGED