UNPKG

@oliverlessa/gemini-agent-lib

Version:

Uma biblioteca NodeJS para criar agentes de IA com Gemini LLM

140 lines (130 loc) 5.77 kB
const ConversationMemory = require('./conversation-memory'); const { MongoClient } = require('mongodb'); const debug = require('../debug').create('memory:mongodb'); /** * Adaptador de memória de conversação que utiliza MongoDB para persistência. * Implementa a interface ConversationMemory. */ class MongoDBConversationMemoryAdapter extends ConversationMemory { /** * Construtor para o adaptador de memória MongoDB. * @param {Object} options - Opções de configuração. * @param {Object} options.dbConfig - Configuração do banco de dados MongoDB. * @param {string} options.dbConfig.connectionUri - URI de conexão do MongoDB. * @param {string} options.dbConfig.dbName - Nome do banco de dados MongoDB. * @param {string} [options.dbConfig.collectionName='chat_history'] - Nome da collection para o histórico. */ constructor({ dbConfig }) { if (!dbConfig || !dbConfig.connectionUri) { throw new Error("MongoDBConversationMemoryAdapter requer 'dbConfig.connectionUri'."); } if (!dbConfig || !dbConfig.dbName) { throw new Error("MongoDBConversationMemoryAdapter requer 'dbConfig.dbName'."); } super({ dbType: 'mongodb', dbConfig }); this.connectionUri = dbConfig.connectionUri; this.dbName = dbConfig.dbName; this.collectionName = dbConfig.collectionName || 'chat_history'; this.client = new MongoClient(this.connectionUri); this.historyCollection = null; } /** * Conecta ao banco de dados MongoDB e obtém a collection de histórico. * Deve ser chamado e aguardado antes de usar o adaptador. * @returns {Promise<void>} */ async initialize() { try { await this.client.connect(); const db = this.client.db(this.dbName); this.historyCollection = db.collection(this.collectionName); // Criar índice para buscas eficientes (operação idempotente - não causa erro se o índice já existir) await this.historyCollection.createIndex({ chat_id: 1, message_index: 1 }, { background: true }); debug(`Conectado ao MongoDB, database: '${this.dbName}', collection: '${this.collectionName}'`); } catch (error) { console.error("[MongoDBConversationMemoryAdapter] Erro ao conectar ao MongoDB:", error); throw error; } } /** * Carrega o histórico de conversas do MongoDB para um determinado ID de chat. * @param {string} chatId - Identificador único da conversa. * @returns {Promise<ChatMessage[]>} - Array de mensagens do histórico. */ async loadHistory(chatId) { try { if (!this.historyCollection) { throw new Error("[MongoDBConversationMemoryAdapter] Não conectado ao MongoDB."); } const cursor = this.historyCollection.find({ chat_id: chatId }).sort({ message_index: 1 }); const messages = []; await cursor.forEach(doc => { messages.push({ role: doc.role, content: doc.content }); }); return messages; } catch (error) { console.error("[MongoDBConversationMemoryAdapter] Erro ao carregar histórico do MongoDB:", error); throw error; } } /** * Adiciona uma nova mensagem ao histórico no MongoDB. * @param {string} chatId - Identificador único da conversa. * @param {string} role - Papel do autor da mensagem. * @param {string} content - Conteúdo da mensagem. * @returns {Promise<void>} */ async appendMessage(chatId, role, content) { try { if (!this.historyCollection) { throw new Error("[MongoDBConversationMemoryAdapter] Não conectado ao MongoDB."); } const lastMessage = await this.historyCollection.find({ chat_id: chatId }).sort({ message_index: -1 }).limit(1).toArray(); const nextIndex = (lastMessage.length > 0) ? lastMessage[0].message_index + 1 : 0; await this.historyCollection.insertOne({ chat_id: chatId, message_index: nextIndex, role: role, content: content, timestamp: new Date() }); } catch (error) { console.error("[MongoDBConversationMemoryAdapter] Erro ao adicionar mensagem ao MongoDB:", error); throw error; } } /** * Limpa o histórico de conversas no MongoDB para um determinado ID de chat. * @param {string} chatId - Identificador único da conversa. * @returns {Promise<void>} */ async clearHistory(chatId) { try { if (!this.historyCollection) { throw new Error("[MongoDBConversationMemoryAdapter] Não conectado ao MongoDB."); } await this.historyCollection.deleteMany({ chat_id: chatId }); } catch (error) { console.error("[MongoDBConversationMemoryAdapter] Erro ao limpar histórico do MongoDB:", error); throw error; } } /** * Fecha a conexão com o banco de dados MongoDB. * @returns {Promise<void>} */ async close() { if (this.client) { try { await this.client.close(); debug("Conexão com o banco de dados MongoDB fechada."); this.client = null; this.historyCollection = null; } catch (error) { console.error("[MongoDBConversationMemoryAdapter] Erro ao fechar conexão MongoDB:", error); throw error; } } } } module.exports = MongoDBConversationMemoryAdapter;