diff --git a/src/triple/TripleIntelligence.ts b/src/triple/TripleIntelligence.ts index 2a170cfd..94c7d488 100644 --- a/src/triple/TripleIntelligence.ts +++ b/src/triple/TripleIntelligence.ts @@ -283,7 +283,9 @@ export class TripleIntelligenceEngine { * Vector similarity search */ private async vectorSearch(query: string | Vector | any, limit?: number): Promise { - return this.brain.search(query, limit || 100) + // CRITICAL FIX: Use _legacySearch to avoid circular dependency + // search() → find() → vectorSearch() must NOT call search() again! + return (this.brain as any)._legacySearch(query, limit || 100) } /** @@ -325,7 +327,8 @@ export class TripleIntelligenceEngine { // Use BrainyData's advanced metadata filtering with Brain Patterns if (!where || Object.keys(where).length === 0) { - return this.brain.search('*', 1000) // Return all if no filter + // CRITICAL FIX: Use _legacySearch to avoid circular dependency + return (this.brain as any)._legacySearch('*', 1000) // Return all if no filter } // Pass Brain Patterns directly - the metadata index now supports them natively! @@ -337,7 +340,8 @@ export class TripleIntelligenceEngine { // { tags: { contains: 'javascript' } } - array contains // The metadata index handles all Brain Pattern operators natively now - return this.brain.search('*', 1000, { metadata: where }) + // CRITICAL FIX: Use _legacySearch to avoid circular dependency + return (this.brain as any)._legacySearch('*', 1000, { metadata: where }) } /** diff --git a/test-direct-search.js b/test-direct-search.js new file mode 100644 index 00000000..020480b8 --- /dev/null +++ b/test-direct-search.js @@ -0,0 +1,109 @@ +#!/usr/bin/env node + +/** + * DIRECT SEARCH TEST + * + * Tests search functionality directly, bypassing Triple Intelligence + * to identify where the timeout occurs + */ + +import { BrainyData } from './dist/index.js' + +async function testDirectSearch() { + console.log('šŸ” DIRECT SEARCH TEST') + console.log('====================\n') + + try { + // 1. Initialize + console.log('1. Initializing Brainy...') + const brain = new BrainyData({ + storage: { forceMemoryStorage: true }, + verbose: false + }) + + await brain.init() + await brain.clearAll({ force: true }) + console.log('āœ… Initialized\n') + + // 2. Add simple test data + console.log('2. Adding test data...') + const id1 = await brain.addNoun('JavaScript programming') + const id2 = await brain.addNoun('Python programming') + const id3 = await brain.addNoun('React framework') + console.log(`āœ… Added 3 items\n`) + + // 3. Test direct embedding generation + console.log('3. Testing direct embedding...') + const startEmbed = Date.now() + const embedding = await brain.embed('programming language') + console.log(`āœ… Generated ${embedding.length}D embedding in ${Date.now() - startEmbed}ms\n`) + + // 4. Get the HNSW index directly + console.log('4. Accessing HNSW index directly...') + const index = brain.index // This should be the HNSW index + console.log(`āœ… Index has ${index.getNouns().size} nouns\n`) + + // 5. Try legacy search if available + console.log('5. Testing legacy search (if available)...') + try { + // Access the private _legacySearch method + const legacySearch = brain._legacySearch || brain.legacySearch + if (legacySearch) { + const startSearch = Date.now() + const results = await legacySearch.call(brain, 'programming', 2) + console.log(`āœ… Legacy search returned ${results.length} results in ${Date.now() - startSearch}ms`) + } else { + console.log('āš ļø Legacy search not available') + } + } catch (error) { + console.log(`āš ļø Legacy search error: ${error.message}`) + } + + // 6. Test simple search WITHOUT Triple Intelligence + console.log('\n6. Testing simple HNSW search...') + try { + // Generate embedding first + const queryEmbedding = await brain.embed('programming') + console.log('āœ… Query embedding generated') + + // Direct HNSW search using the embedding vector + const startHNSW = Date.now() + const hnswResults = index.search(queryEmbedding, 2) + console.log(`āœ… HNSW search completed in ${Date.now() - startHNSW}ms`) + console.log(` Found ${hnswResults.length} results`) + + } catch (error) { + console.log(`āŒ HNSW search error: ${error.message}`) + } + + // 7. Test the public search() method with timeout + console.log('\n7. Testing public search() with 10s timeout...') + const searchPromise = brain.search('programming', 2) + const timeoutPromise = new Promise((_, reject) => { + setTimeout(() => reject(new Error('Search timeout')), 10000) + }) + + try { + const startPublic = Date.now() + const results = await Promise.race([searchPromise, timeoutPromise]) + console.log(`āœ… Public search completed in ${Date.now() - startPublic}ms`) + console.log(` Found ${results.length} results`) + } catch (error) { + console.log(`āŒ Public search error: ${error.message}`) + } + + // 8. Memory check + const mem = process.memoryUsage() + console.log(`\nšŸ“Š Memory usage: ${Math.round(mem.heapUsed / 1024 / 1024)} MB`) + + console.log('\n✨ Test complete!') + + } catch (error) { + console.error('āŒ Fatal error:', error.message) + console.error(error.stack) + } + + process.exit(0) +} + +testDirectSearch() \ No newline at end of file diff --git a/test-production-ready.js b/test-production-ready.js new file mode 100755 index 00000000..468047f9 --- /dev/null +++ b/test-production-ready.js @@ -0,0 +1,283 @@ +#!/usr/bin/env node + +/** + * PRODUCTION READINESS TEST + * + * Verifies ALL critical functionality works in production-like environment + * Tests: search(), find(), clustering, Triple Intelligence, Brain Patterns + */ + +import { BrainyData } from './dist/index.js' + +const TEST_TIMEOUT = 30000 // 30 seconds per operation + +async function withTimeout(promise, operation, timeoutMs = TEST_TIMEOUT) { + const timeout = new Promise((_, reject) => { + setTimeout(() => reject(new Error(`${operation} timeout after ${timeoutMs}ms`)), timeoutMs) + }) + + try { + const result = await Promise.race([promise, timeout]) + console.log(`āœ… ${operation} completed successfully`) + return result + } catch (error) { + console.error(`āŒ ${operation} failed: ${error.message}`) + throw error + } +} + +async function testProductionFunctionality() { + console.log('šŸš€ PRODUCTION READINESS TEST - Brainy 2.0') + console.log('=========================================\n') + + const results = { + passed: [], + failed: [], + warnings: [] + } + + try { + // 1. Initialize Brainy + console.log('1ļøāƒ£ Initializing Brainy with real AI models...') + const brain = new BrainyData({ + storage: { forceMemoryStorage: true }, + verbose: false + }) + + await withTimeout(brain.init(), 'Initialization', 60000) + await brain.clearAll({ force: true }) + + // 2. Test data creation with real embeddings + console.log('\n2ļøāƒ£ Testing data creation with real embeddings...') + const testData = [ + { content: 'JavaScript is a programming language', category: 'programming', year: 1995 }, + { content: 'Python is used for machine learning', category: 'programming', year: 1991 }, + { content: 'React is a frontend framework', category: 'framework', year: 2013 }, + { content: 'Docker enables containerization', category: 'devops', year: 2013 }, + { content: 'PostgreSQL is a relational database', category: 'database', year: 1996 } + ] + + const ids = [] + for (const item of testData) { + try { + const id = await withTimeout( + brain.addNoun(item.content, item), + `Add: ${item.content.substring(0, 30)}...`, + 10000 + ) + ids.push(id) + results.passed.push(`addNoun: ${item.category}`) + } catch (error) { + results.failed.push(`addNoun: ${item.category}`) + } + } + + // 3. Test search() with semantic understanding + console.log('\n3ļøāƒ£ Testing search() with semantic understanding...') + try { + const searchResults = await withTimeout( + brain.search('programming languages', 3), + 'search(): programming languages' + ) + + if (searchResults && searchResults.length > 0) { + console.log(` Found ${searchResults.length} results`) + results.passed.push('search() basic') + } else { + results.failed.push('search() returned no results') + } + } catch (error) { + results.failed.push('search() functionality') + } + + // 4. Test find() with natural language + console.log('\n4ļøāƒ£ Testing find() with natural language...') + try { + const findResults = await withTimeout( + brain.find('show me backend technologies'), + 'find(): natural language query' + ) + + if (findResults && findResults.length > 0) { + console.log(` Found ${findResults.length} results via NLP`) + results.passed.push('find() NLP') + } else { + results.warnings.push('find() returned no results') + } + } catch (error) { + results.failed.push('find() functionality') + } + + // 5. Test Brain Patterns (metadata filtering) + console.log('\n5ļøāƒ£ Testing Brain Patterns (metadata filtering)...') + try { + const patternResults = await withTimeout( + brain.search('*', 10, { + metadata: { + category: 'programming', + year: { greaterThan: 1990 } + } + }), + 'Brain Patterns: range queries' + ) + + if (patternResults && patternResults.length > 0) { + console.log(` Found ${patternResults.length} with metadata filters`) + results.passed.push('Brain Patterns') + } else { + results.warnings.push('Brain Patterns returned no results') + } + } catch (error) { + results.failed.push('Brain Patterns') + } + + // 6. Test Triple Intelligence + console.log('\n6ļøāƒ£ Testing Triple Intelligence...') + try { + const tripleResults = await withTimeout( + brain.find({ + like: 'web development', + where: { category: 'framework' }, + limit: 3 + }), + 'Triple Intelligence: vector + metadata' + ) + + if (tripleResults && tripleResults.length >= 0) { + console.log(` Found ${tripleResults.length} via Triple Intelligence`) + results.passed.push('Triple Intelligence') + } else { + results.warnings.push('Triple Intelligence returned unexpected results') + } + } catch (error) { + results.failed.push('Triple Intelligence') + } + + // 7. Test direct embedding generation + console.log('\n7ļøāƒ£ Testing direct embedding generation...') + try { + const embedding = await withTimeout( + brain.embed('test embedding'), + 'Direct embedding generation', + 10000 + ) + + if (embedding && embedding.length === 384) { + console.log(` Generated ${embedding.length}D embedding`) + results.passed.push('embed() function') + } else { + results.failed.push('embed() wrong dimensions') + } + } catch (error) { + results.failed.push('embed() function') + } + + // 8. Test statistics + console.log('\n8ļøāƒ£ Testing statistics and monitoring...') + try { + const stats = await withTimeout( + brain.getStatistics(), + 'Statistics retrieval', + 5000 + ) + + if (stats && stats.totalItems >= ids.length) { + console.log(` Stats: ${stats.totalItems} items, ${stats.dimensions}D`) + results.passed.push('Statistics') + } else { + results.failed.push('Statistics incorrect') + } + } catch (error) { + results.failed.push('Statistics') + } + + // 9. Test CRUD operations + console.log('\n9ļøāƒ£ Testing CRUD operations...') + if (ids.length > 0) { + try { + // Get + const item = await withTimeout( + brain.getNoun(ids[0]), + 'getNoun', + 5000 + ) + if (item) results.passed.push('getNoun') + else results.failed.push('getNoun') + + // Update (pass metadata only, not null data) + await withTimeout( + brain.updateNoun(ids[0], undefined, { updated: true }), + 'updateNoun', + 5000 + ) + results.passed.push('updateNoun') + + // Delete + const deleted = await withTimeout( + brain.deleteNoun(ids[0]), + 'deleteNoun', + 5000 + ) + if (deleted) results.passed.push('deleteNoun') + else results.warnings.push('deleteNoun returned false') + + } catch (error) { + results.failed.push('CRUD operations') + } + } + + // 10. Memory check + console.log('\nšŸ”Ÿ Checking memory usage...') + const mem = process.memoryUsage() + const heapMB = Math.round(mem.heapUsed / 1024 / 1024) + console.log(` Heap used: ${heapMB} MB`) + if (heapMB < 4000) { + results.passed.push('Memory usage acceptable') + } else { + results.warnings.push(`High memory usage: ${heapMB} MB`) + } + + } catch (error) { + console.error('\nāŒ Fatal error:', error.message) + results.failed.push('Fatal error: ' + error.message) + } + + // Final Report + console.log('\n' + '='.repeat(50)) + console.log('šŸ“Š PRODUCTION READINESS REPORT') + console.log('='.repeat(50)) + + console.log(`\nāœ… PASSED (${results.passed.length}):`) + results.passed.forEach(test => console.log(` - ${test}`)) + + if (results.warnings.length > 0) { + console.log(`\nāš ļø WARNINGS (${results.warnings.length}):`) + results.warnings.forEach(test => console.log(` - ${test}`)) + } + + if (results.failed.length > 0) { + console.log(`\nāŒ FAILED (${results.failed.length}):`) + results.failed.forEach(test => console.log(` - ${test}`)) + } + + const totalTests = results.passed.length + results.failed.length + const passRate = Math.round((results.passed.length / totalTests) * 100) + + console.log('\n' + '='.repeat(50)) + console.log(`šŸ“ˆ OVERALL: ${passRate}% Pass Rate (${results.passed.length}/${totalTests})`) + + if (passRate >= 90) { + console.log('šŸŽ‰ PRODUCTION READY!') + } else if (passRate >= 70) { + console.log('āš ļø MOSTLY READY - Fix critical issues') + } else { + console.log('āŒ NOT READY - Major issues found') + } + + console.log('='.repeat(50)) + + process.exit(results.failed.length > 0 ? 1 : 0) +} + +// Run the test +testProductionFunctionality().catch(console.error) \ No newline at end of file