UNPKG

@oliverlessa/gemini-agent-lib

Version:

Uma biblioteca NodeJS para criar agentes de IA com Gemini LLM

173 lines (162 loc) 6.84 kB
const FactMemory = require('./fact-memory'); const { MongoClient } = require('mongodb'); const debug = require('../debug').create('memory:mongodb'); /** * Adaptador de memória de fatos que utiliza MongoDB para persistência. * Implementa a interface FactMemory. */ class MongoDBFactMemoryAdapter extends FactMemory { /** * Construtor para o adaptador de memória de fatos 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='facts'] - Nome da collection para os fatos. */ constructor({ dbConfig }) { if (!dbConfig || !dbConfig.connectionUri) { throw new Error("MongoDBFactMemoryAdapter requer 'dbConfig.connectionUri'."); } if (!dbConfig || !dbConfig.dbName) { throw new Error("MongoDBFactMemoryAdapter requer 'dbConfig.dbName'."); } super({ dbType: 'mongodb', dbConfig }); this.connectionUri = dbConfig.connectionUri; this.dbName = dbConfig.dbName; this.collectionName = dbConfig.collectionName || 'facts'; this.client = new MongoClient(this.connectionUri); this.factsCollection = null; } /** * Conecta ao banco de dados MongoDB e obtém a collection de fatos. * 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.factsCollection = db.collection(this.collectionName); // Criar índice para buscas eficientes (operação idempotente - não causa erro se o índice já existir) await this.factsCollection.createIndex({ context_id: 1, key: 1 }, { unique: true, background: true }); debug(`Conectado ao MongoDB, database: '${this.dbName}', collection: '${this.collectionName}'`); } catch (error) { console.error("[MongoDBFactMemoryAdapter] Erro ao conectar ao MongoDB:", error); throw error; } } /** * Armazena ou atualiza um fato para um contexto específico. * @param {string} contextId - Identificador único do contexto. * @param {string} key - A chave do fato. * @param {any} value - O valor do fato. * @returns {Promise<void>} */ async setFact(contextId, key, value) { try { if (!this.factsCollection) { throw new Error("[MongoDBFactMemoryAdapter] Não conectado ao MongoDB."); } // Usa updateOne com upsert:true para inserir ou atualizar await this.factsCollection.updateOne( { context_id: contextId, key: key }, // Filtro para encontrar o fato { $set: { value: value, timestamp: new Date() } }, // Define/atualiza o valor e timestamp { upsert: true } // Cria o documento se não existir ); } catch (error) { console.error("[MongoDBFactMemoryAdapter] Erro ao definir fato:", error); throw error; } } /** * Recupera o valor de um fato específico. * @param {string} contextId - Identificador único do contexto. * @param {string} key - A chave do fato. * @returns {Promise<any|null>} - O valor do fato, ou null se não encontrado. */ async getFact(contextId, key) { try { if (!this.factsCollection) { throw new Error("[MongoDBFactMemoryAdapter] Não conectado ao MongoDB."); } const factDoc = await this.factsCollection.findOne({ context_id: contextId, key: key }); return factDoc ? factDoc.value : null; // Retorna o valor ou null } catch (error) { console.error("[MongoDBFactMemoryAdapter] Erro ao obter fato:", error); throw error; } } /** * Recupera todos os fatos para um contexto específico. * @param {string} contextId - Identificador único do contexto. * @returns {Promise<Object<string, any>>} - Um objeto com todos os fatos. */ async getAllFacts(contextId) { try { if (!this.factsCollection) { throw new Error("[MongoDBFactMemoryAdapter] Não conectado ao MongoDB."); } const cursor = this.factsCollection.find({ context_id: contextId }); const facts = {}; await cursor.forEach(doc => { facts[doc.key] = doc.value; }); return facts; } catch (error) { console.error("[MongoDBFactMemoryAdapter] Erro ao obter todos os fatos:", error); throw error; } } /** * Deleta um fato específico. * @param {string} contextId - Identificador único do contexto. * @param {string} key - A chave do fato a ser deletado. * @returns {Promise<void>} */ async deleteFact(contextId, key) { try { if (!this.factsCollection) { throw new Error("[MongoDBFactMemoryAdapter] Não conectado ao MongoDB."); } await this.factsCollection.deleteOne({ context_id: contextId, key: key }); } catch (error) { console.error("[MongoDBFactMemoryAdapter] Erro ao deletar fato:", error); throw error; } } /** * Deleta todos os fatos para um contexto específico. * @param {string} contextId - Identificador único do contexto. * @returns {Promise<void>} */ async deleteAllFacts(contextId) { try { if (!this.factsCollection) { throw new Error("[MongoDBFactMemoryAdapter] Não conectado ao MongoDB."); } await this.factsCollection.deleteMany({ context_id: contextId }); } catch (error) { console.error("[MongoDBFactMemoryAdapter] Erro ao deletar todos os fatos:", 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.factsCollection = null; } catch (error) { console.error("[MongoDBFactMemoryAdapter] Erro ao fechar conexão MongoDB:", error); throw error; } } } } module.exports = MongoDBFactMemoryAdapter;