UNPKG

mongodb-memory-bank-mcp

Version:

FIXED: MongoDB Memory Bank MCP with bulletproof error handling, smart operations, and session state management. Eliminates [object Object] errors and user confusion.

146 lines (145 loc) 6.44 kB
import { MongoDBConnection } from '../connection/mongodb-connection.js'; import { getCollectionNames } from '../../../main/config/mongodb-config.js'; export class MongoDBProjectRepository { db; collection; constructor() { // Initialize lazily to avoid connection issues } async ensureConnection() { if (!this.db) { this.db = await MongoDBConnection.getInstance().getDatabase(); this.collection = this.db.collection(getCollectionNames().projects); } } async ensureProject(projectName) { await this.ensureConnection(); const existing = await this.collection.findOne({ name: projectName }); if (!existing) { // 🚨 CRITICAL FIX: Create project WITH complete 6-file Cline structure console.log(`[ENSURE-PROJECT] Creating new project with complete Cline structure: ${projectName}`); const project = { name: projectName, createdAt: new Date(), lastAccessed: new Date(), memoryCount: 6, // Will have 6 core files tags: ['cline-structure'] }; await this.collection.insertOne(project); // 🎯 CREATE ALL 6 CORE FILES IMMEDIATELY (Same as create_project) const { ClineMemoryStructure, CLINE_CORE_FILES } = await import('../../../shared/services/cline-memory-structure.js'); const { MongoDBConnection } = await import('../connection/mongodb-connection.js'); const db = await MongoDBConnection.getInstance().getDatabase(); const memoriesCollection = db.collection('memories'); const coreFiles = Object.values(CLINE_CORE_FILES); // 🔍 HYBRID SEARCH: Initialize for project creation analysis let embeddingService = null; try { const { VoyageEmbeddingService } = await import('../../ai/voyage-embedding-service.js'); embeddingService = new VoyageEmbeddingService(); console.log(`[ENSURE-PROJECT] Hybrid search enabled for project: ${projectName}`); } catch (error) { console.warn(`[ENSURE-PROJECT] Hybrid search unavailable: ${error}`); } for (const coreFile of coreFiles) { const template = ClineMemoryStructure.getCoreFileTemplate(coreFile, projectName); const memory = { projectName, fileName: coreFile, content: template, tags: ['core', 'cline-structure', 'auto-created'], lastModified: new Date(), wordCount: template.split(/\s+/).length, memoryType: 'documentation', summary: `Core memory file: ${coreFile}`, metadata: { aiContextType: 'structural', codeRelevance: 0.8, technicalDepth: 0.7, isCore: true, coreFileType: coreFile } }; const insertResult = await memoriesCollection.insertOne(memory); console.log(`[ENSURE-PROJECT] Created core file: ${coreFile}`); // 🔍 HYBRID SEARCH: Generate vector embeddings immediately if (embeddingService && insertResult.insertedId) { try { const vector = await embeddingService.generateEmbedding(template); await memoriesCollection.updateOne({ _id: insertResult.insertedId }, { $set: { contentVector: vector } }); console.log(`[ENSURE-PROJECT] Generated vector for: ${coreFile}`); } catch (vectorError) { console.warn(`[ENSURE-PROJECT] Vector generation failed for ${coreFile}: ${vectorError}`); } } } console.log(`[ENSURE-PROJECT] ✅ Project '${projectName}' created with complete 6-file structure`); } else { // Update last accessed time await this.collection.updateOne({ name: projectName }, { $set: { lastAccessed: new Date() } }); } } async listProjects() { await this.ensureConnection(); const docs = await this.collection .find({}) .sort({ lastAccessed: -1 }) .toArray(); return docs.map(doc => doc.name); } async projectExists(name) { await this.ensureConnection(); const doc = await this.collection.findOne({ name }); return doc !== null; } async getProject(projectName) { await this.ensureConnection(); const doc = await this.collection.findOne({ name: projectName }); return doc ? this.documentToProject(doc) : null; } async updateProject(project) { await this.ensureConnection(); const doc = { name: project.name, description: project.description, createdAt: project.createdAt, lastAccessed: new Date(), memoryCount: project.memoryCount, tags: project.tags }; await this.collection.replaceOne({ name: project.name }, doc, { upsert: true }); return this.documentToProject(doc); } async deleteProject(projectName) { await this.ensureConnection(); const result = await this.collection.deleteOne({ name: projectName }); return result.deletedCount > 0; } async incrementMemoryCount(projectName) { await this.ensureConnection(); await this.collection.updateOne({ name: projectName }, { $inc: { memoryCount: 1 }, $set: { lastAccessed: new Date() } }); } async decrementMemoryCount(projectName) { await this.ensureConnection(); await this.collection.updateOne({ name: projectName }, { $inc: { memoryCount: -1 }, $set: { lastAccessed: new Date() } }); } documentToProject(doc) { return { name: doc.name, description: doc.description, createdAt: doc.createdAt, lastAccessed: doc.lastAccessed, memoryCount: doc.memoryCount, tags: doc.tags }; } }