n8n-nodes-zep-memory-v3
Version:
n8n community node for Zep v3 Memory - replaces discontinued official node
273 lines (272 loc) • 11.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ZepMemory = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const zep_cloud_1 = require("@langchain/community/memory/zep_cloud");
const zep_1 = require("@langchain/community/memory/zep");
class WhiteSpaceTrimmedZepCloudMemory extends zep_cloud_1.ZepCloudMemory {
async loadMemoryVariables(values) {
const memoryVariables = await super.loadMemoryVariables(values);
memoryVariables.chat_history = memoryVariables.chat_history.filter((m) => m.content.toString().trim());
return memoryVariables;
}
}
// MANTIDO: BaseChatMemoryWrapper para compatibilidade máxima
class BaseChatMemoryWrapper {
constructor(memory) {
this.memory = memory;
}
async loadMemoryVariables(values) {
var _a;
const startTime = Date.now();
const response = await this.memory.loadMemoryVariables(values);
const duration = Date.now() - startTime;
// Logging seguro para visibilidade nos logs do Docker/console
console.log(`[Zep Memory v3] loadMemoryVariables completed in ${duration}ms`, {
hasHistory: !!(response === null || response === void 0 ? void 0 : response.chat_history),
messageCount: ((_a = response === null || response === void 0 ? void 0 : response.chat_history) === null || _a === void 0 ? void 0 : _a.length) || 0,
});
return response;
}
async saveContext(inputValues, outputValues) {
const startTime = Date.now();
const response = await this.memory.saveContext(inputValues, outputValues);
const duration = Date.now() - startTime;
// Logging seguro para visibilidade nos logs do Docker/console
console.log(`[Zep Memory v3] saveContext completed in ${duration}ms`, {
input: (inputValues === null || inputValues === void 0 ? void 0 : inputValues.input) || 'N/A',
output: (outputValues === null || outputValues === void 0 ? void 0 : outputValues.output) || 'N/A',
});
return response;
}
async clear() {
console.log('[Zep Memory v3] Clearing memory');
const response = await this.memory.clear();
console.log('[Zep Memory v3] Memory cleared successfully');
return response;
}
get memoryKey() {
return this.memory.memoryKey;
}
get returnMessages() {
return this.memory.returnMessages;
}
get inputKey() {
return this.memory.inputKey;
}
get outputKey() {
return this.memory.outputKey;
}
}
class ZepMemory {
constructor() {
this.description = {
displayName: 'Zep Memory v3',
name: 'zepMemoryV3',
icon: 'file:zep.png',
group: ['transform'],
version: [1, 2, 3, 4],
description: 'Use Zep Memory v3 for AI agent conversations',
defaults: {
name: 'Zep Memory v3',
},
codex: {
categories: ['AI'],
subcategories: {
AI: ['Memory'],
Memory: ['Other memories'],
},
resources: {
primaryDocumentation: [
{
url: 'https://docs.getzep.com',
},
],
},
},
inputs: [],
outputs: ['ai_memory'],
outputNames: ['Memory'],
credentials: [
{
name: 'zepApi',
required: true,
},
],
properties: [
{
displayName: 'Connect to AI Agent',
name: 'connectionHint',
type: 'notice',
default: '',
description: 'Connect this node to an AI Agent node to provide memory functionality',
},
{
displayName: 'Works with Zep Cloud v3 and enhanced context retrieval',
name: 'supportedVersions',
type: 'notice',
default: '',
},
// Thread ID para versão 1
{
displayName: 'Thread ID',
name: 'threadId',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
'@version': [1],
},
},
},
// Thread ID para versão 1.1
{
displayName: 'Thread ID',
name: 'threadId',
type: 'string',
default: '={{ $json.threadId }}',
description: 'The thread ID to use to store the memory',
displayOptions: {
show: {
'@version': [2],
},
},
},
// Thread ID Type para versões 1.2+
{
displayName: 'Thread ID',
name: 'threadIdType',
type: 'options',
options: [
{
name: 'Connected Chat Trigger Node',
value: 'fromInput',
description: 'Looks for an input field called "threadId" from a connected Chat Trigger',
},
{
name: 'Define below',
value: 'customKey',
description: 'Use an expression to reference data in previous nodes or enter static text',
},
],
default: 'fromInput',
displayOptions: {
show: {
'@version': [{ _cnd: { gte: 3 } }],
},
},
},
// Thread Key From Previous Node (versão 1.3+)
{
displayName: 'Thread Key From Previous Node',
name: 'threadKey',
type: 'string',
default: '={{ $json.threadId }}',
displayOptions: {
show: {
threadIdType: ['fromInput'],
'@version': [{ _cnd: { gte: 4 } }],
},
},
},
// Custom Thread Key
{
displayName: 'Key',
name: 'threadKey',
type: 'string',
default: '',
description: 'The key to use to store thread ID in the memory',
displayOptions: {
show: {
threadIdType: ['customKey'],
},
},
},
],
};
}
async supplyData(itemIndex) {
var _a, _b;
// Helper de logging seguro - funciona mesmo se this.logger não estiver disponível
const log = (level, message, meta) => {
try {
if (this.logger && typeof this.logger[level] === 'function') {
this.logger[level](message, meta);
}
}
catch (error) {
// Fallback silencioso para console (aparece nos logs do Docker)
console.log(`[Zep Memory v3 ${level.toUpperCase()}] ${message}`, meta || '');
}
};
log('info', '🚀 Zep Memory v3 - Starting initialization');
const credentials = await this.getCredentials('zepApi');
const nodeVersion = this.getNode().typeVersion;
log('debug', `Node version: ${nodeVersion}`);
let threadId;
if (nodeVersion >= 3) {
const threadIdType = this.getNodeParameter('threadIdType', itemIndex);
if (threadIdType === 'fromInput') {
const threadKey = this.getNodeParameter('threadKey', itemIndex, 'threadId');
const inputData = this.getInputData(itemIndex);
threadId = String(((_b = (_a = inputData === null || inputData === void 0 ? void 0 : inputData[0]) === null || _a === void 0 ? void 0 : _a.json) === null || _b === void 0 ? void 0 : _b[threadKey]) || '');
log('debug', `Thread ID from input: ${threadId}`);
}
else {
threadId = this.getNodeParameter('threadKey', itemIndex);
log('debug', `Thread ID from custom key: ${threadId}`);
}
}
else {
threadId = this.getNodeParameter('threadId', itemIndex);
log('debug', `Thread ID (legacy): ${threadId}`);
}
if (!threadId) {
log('error', '❌ Thread ID is missing');
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Thread ID is required. Please provide a valid thread ID.');
}
log('info', `✓ Using thread ID: ${threadId}`);
let baseMemory;
if (credentials.cloud) {
if (!credentials.apiKey) {
log('error', '❌ API key is missing for Zep Cloud');
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'API key is required for Zep Cloud');
}
log('info', '☁️ Initializing Zep Cloud memory');
baseMemory = new WhiteSpaceTrimmedZepCloudMemory({
sessionId: threadId,
apiKey: credentials.apiKey,
memoryType: 'perpetual',
memoryKey: 'chat_history',
returnMessages: true,
inputKey: 'input',
outputKey: 'output',
separateMessages: false,
});
}
else {
if (!credentials.apiUrl) {
log('error', '❌ API URL is missing for Zep Open Source');
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'API URL is required for Zep Open Source');
}
log('info', `🔧 Initializing Zep Open Source memory at ${credentials.apiUrl}`);
baseMemory = new zep_1.ZepMemory({
sessionId: threadId,
baseURL: credentials.apiUrl,
apiKey: credentials.apiKey,
memoryKey: 'chat_history',
returnMessages: true,
inputKey: 'input',
outputKey: 'output',
});
}
// Wrapper para compatibilidade - SEM logWrapper customizado
const wrappedMemory = new BaseChatMemoryWrapper(baseMemory);
log('info', '✅ Zep Memory v3 initialized successfully');
return {
response: wrappedMemory,
};
}
}
exports.ZepMemory = ZepMemory;