UNPKG

universal-ai-brain

Version:

🧠 UNIVERSAL AI BRAIN 3.3 - The world's most advanced cognitive architecture with 24 specialized systems, MongoDB 8.1 $rankFusion hybrid search, latest Voyage 3.5 embeddings, and framework-agnostic design. Works with Mastra, Vercel AI, LangChain, OpenAI A

302 lines (265 loc) 9.23 kB
/** * @file Test Configuration for Universal AI Brain * Real MongoDB Atlas and OpenAI configuration for production testing */ import { MongoClient, Db } from 'mongodb'; import { OpenAIEmbeddingProvider } from '../embeddings/OpenAIEmbeddingProvider'; import { VoyageAIEmbeddingProvider } from '../embeddings/VoyageAIEmbeddingProvider'; export interface TestConfig { mongoUri: string; databaseName: string; openaiApiKey: string; voyageApiKey: string; testTimeout: number; embeddingProvider: 'openai' | 'voyage'; } export const testConfig: TestConfig = { mongoUri: process.env.MONGODB_URI || 'mongodb://localhost:27017', databaseName: process.env.DATABASE_NAME || 'universal_ai_brain_test', openaiApiKey: process.env.OPENAI_API_KEY || '', voyageApiKey: process.env.VOYAGE_API_KEY || '', testTimeout: 120000, // Increased timeout for real API calls embeddingProvider: (process.env.EMBEDDING_PROVIDER as 'openai' | 'voyage') || 'voyage' // Prefer Voyage AI as requested }; // Global test database connection let testDb: Db | null = null; let testClient: MongoClient | null = null; export async function setupTestDatabase(): Promise<{ client: MongoClient; db: Db }> { if (testDb && testClient) { return { client: testClient, db: testDb }; } try { // Follow official MongoDB Node.js driver patterns from docs testClient = new MongoClient(testConfig.mongoUri, { // Connection pool settings (following MongoDB docs) maxPoolSize: 150, // Increased for better performance as per docs minPoolSize: 5, maxIdleTimeMS: 30000, // Timeout settings (following MongoDB docs) serverSelectionTimeoutMS: 10000, socketTimeoutMS: 45000, connectTimeoutMS: 10000, // Reliability settings (following MongoDB docs) retryWrites: true, retryReads: true, // Atlas-specific optimizations compressors: ['snappy', 'zlib'], readPreference: 'primary', writeConcern: { w: 'majority', j: true } }); // Explicit connection as recommended in MongoDB docs for testing await testClient.connect(); // Verify connection with ping as shown in MongoDB docs await testClient.db('admin').command({ ping: 1 }); testDb = testClient.db(testConfig.databaseName); console.log(`✅ Connected to MongoDB Atlas test database: ${testConfig.databaseName}`); console.log(`🔗 Connection verified with ping command`); return { client: testClient, db: testDb }; } catch (error) { console.error('❌ Failed to connect to MongoDB Atlas:', error); throw error; } } export async function cleanupTestDatabase(client?: MongoClient): Promise<void> { const clientToClose = client || testClient; const dbToClean = client ? client.db(testConfig.databaseName) : testDb; if (dbToClean) { try { // Clean up test collections following MongoDB best practices const collections = await dbToClean.listCollections().toArray(); for (const collection of collections) { if (collection.name.includes('test') || collection.name.includes('temp')) { await dbToClean.collection(collection.name).deleteMany({}); } } console.log('🧹 Cleaned up test collections'); } catch (error) { console.warn('⚠️ Warning: Could not clean up test collections:', error); } } if (clientToClose) { try { // Follow MongoDB docs pattern for graceful shutdown await clientToClose.close(); // Reset global variables only if using global client if (!client) { testClient = null; testDb = null; } console.log('✅ MongoDB Atlas connection closed gracefully'); } catch (error) { console.warn('⚠️ Warning: Could not close MongoDB connection:', error); // Don't throw - allow tests to continue } } } export function createTestEmbeddingProvider(): OpenAIEmbeddingProvider | VoyageAIEmbeddingProvider { if (testConfig.embeddingProvider === 'voyage') { return new VoyageAIEmbeddingProvider({ apiKey: testConfig.voyageApiKey, model: 'voyage-3', // Latest Voyage model dimensions: 1024 }); } else { return new OpenAIEmbeddingProvider({ apiKey: testConfig.openaiApiKey, model: 'text-embedding-3-small', // Use smaller model for faster tests dimensions: 1536 }); } } export function createVoyageEmbeddingProvider(): VoyageAIEmbeddingProvider { return new VoyageAIEmbeddingProvider({ apiKey: testConfig.voyageApiKey, model: 'voyage-3', dimensions: 1024 }); } export function createOpenAIEmbeddingProvider(): OpenAIEmbeddingProvider { return new OpenAIEmbeddingProvider({ apiKey: testConfig.openaiApiKey, model: 'text-embedding-3-small', dimensions: 1536 }); } export function generateTestId(): string { return `test_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } export function createTestMemory() { return { id: generateTestId(), content: 'Test memory content for Universal AI Brain', metadata: { type: 'test' as const, importance: 0.8, confidence: 0.9, source: 'test_suite', framework: 'universal', sessionId: generateTestId(), tags: ['test', 'memory'], relationships: [], accessCount: 0, lastAccessed: new Date(), created: new Date(), updated: new Date() } }; } export function createTestContext() { return { contextId: generateTestId(), content: 'Test context for Universal AI Brain', source: 'test_suite', relevanceScore: 0.85, metadata: { type: 'test' as const, framework: 'universal', sessionId: generateTestId(), userId: 'test_user', tags: ['test', 'context'], importance: 0.8, confidence: 0.9, lastUsed: new Date(), usageCount: 0 }, embedding: { values: Array.from({ length: 1536 }, () => Math.random() - 0.5), model: 'text-embedding-3-small', dimensions: 1536 } }; } // Test utilities for MongoDB Atlas Vector Search export const vectorSearchTestUtils = { createVectorSearchIndex: async (db: Db, collectionName: string, indexName: string) => { try { // Note: Vector search indexes must be created through Atlas UI or API // This is a placeholder for documentation console.log(`📝 Vector search index '${indexName}' should be created for collection '${collectionName}'`); console.log('Index definition:'); console.log(JSON.stringify({ mappings: { fields: { 'embedding.values': { type: 'knnVector', dimensions: 1536, similarity: 'cosine' } } } }, null, 2)); } catch (error) { console.warn(`⚠️ Could not create vector search index: ${error}`); } }, testVectorSearchQuery: (queryVector: number[]) => [ { $vectorSearch: { index: 'memory_vector_index', path: 'embedding.values', queryVector: queryVector, numCandidates: 150, limit: 10, filter: { 'metadata.type': 'test' } } }, { $addFields: { vectorScore: { $meta: 'vectorSearchScore' } } }, { $match: { vectorScore: { $gte: 0.7 } } } ] }; // Error handling utilities export function isMongoAtlasError(error: any): boolean { return error?.message?.includes('$vectorSearch') || error?.message?.includes('Atlas') || error?.code === 40324; // Vector search not available } export function isOpenAIError(error: any): boolean { return error?.message?.includes('OpenAI') || error?.status === 401 || error?.status === 429; } export function shouldSkipTest(error?: any): boolean { // Skip tests if MongoDB URI is not available if (!testConfig.mongoUri || testConfig.mongoUri.includes('your-connection-string')) { console.log('⏭️ Skipping test: MongoDB URI not available'); return true; } // Skip tests that require Atlas Vector Search if not available if (error && isMongoAtlasError(error)) { console.log('⏭️ Skipping test: MongoDB Atlas Vector Search not available'); return true; } // Skip tests that require OpenAI if API key is invalid if (error && isOpenAIError(error)) { console.log('⏭️ Skipping test: OpenAI API not available'); return true; } return false; } export function shouldSkipEmbeddingTest(): boolean { // Skip embedding tests if no API keys are available if (!hasRealApiKeys()) { console.log('⏭️ Skipping embedding test: No valid API keys available'); return true; } return false; } export function hasRealApiKeys(): boolean { // Check if we have real API keys (not placeholder values) const hasOpenAI = testConfig.openaiApiKey && testConfig.openaiApiKey.startsWith('sk-') && testConfig.openaiApiKey.length > 20; const hasVoyage = testConfig.voyageApiKey && testConfig.voyageApiKey.startsWith('pa-') && testConfig.voyageApiKey.length > 20; console.log(`🔑 API Keys Status: OpenAI=${hasOpenAI}, Voyage=${hasVoyage}`); return hasOpenAI || hasVoyage; }