UNPKG

claude-flow

Version:

Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration

243 lines 7.98 kB
/** * Vector Database Module * * Provides optional ruvector WASM-accelerated vector operations for: * - Semantic similarity search * - HNSW indexing (150x faster) * - Embedding generation * * Gracefully degrades when ruvector is not installed. * * Created with love by ruv.io */ // ============================================================================ // Fallback Implementation (when ruvector not available) // ============================================================================ class FallbackVectorDB { vectors = new Map(); dimensions; constructor(dimensions) { this.dimensions = dimensions; } insert(embedding, id, metadata) { this.vectors.set(id, { embedding, metadata }); } search(query, k = 10) { const results = []; for (const [id, { embedding, metadata }] of this.vectors) { const score = cosineSimilarity(query, embedding); results.push({ id, score, metadata }); } return results .sort((a, b) => b.score - a.score) .slice(0, k); } remove(id) { return this.vectors.delete(id); } size() { return this.vectors.size; } clear() { this.vectors.clear(); } } /** * Compute cosine similarity between two vectors */ function cosineSimilarity(a, b) { if (a.length !== b.length) { throw new Error(`Vector dimension mismatch: ${a.length} vs ${b.length}`); } let dotProduct = 0; let normA = 0; let normB = 0; for (let i = 0; i < a.length; i++) { dotProduct += a[i] * b[i]; normA += a[i] * a[i]; normB += b[i] * b[i]; } const denom = Math.sqrt(normA) * Math.sqrt(normB); return denom === 0 ? 0 : dotProduct / denom; } /** * Generate a simple hash-based embedding (fallback when ruvector not available) */ function generateHashEmbedding(text, dimensions = 768) { const embedding = new Float32Array(dimensions); const normalized = text.toLowerCase().trim(); // Simple hash function let hash = 0; for (let i = 0; i < normalized.length; i++) { hash = ((hash << 5) - hash) + normalized.charCodeAt(i); hash = hash & hash; // Convert to 32bit integer } // Generate pseudo-random embedding based on hash for (let i = 0; i < dimensions; i++) { embedding[i] = Math.sin(hash * (i + 1) * 0.001) * 0.5 + 0.5; } // Normalize let norm = 0; for (let i = 0; i < dimensions; i++) { norm += embedding[i] * embedding[i]; } norm = Math.sqrt(norm); for (let i = 0; i < dimensions; i++) { embedding[i] /= norm; } return embedding; } // ============================================================================ // Module State // ============================================================================ let ruvectorModule = null; let loadAttempted = false; let isAvailable = false; // ============================================================================ // Public API // ============================================================================ /** * Attempt to load the ruvector module * Returns true if successfully loaded, false otherwise */ export async function loadRuVector() { if (loadAttempted) { return isAvailable; } loadAttempted = true; try { // Dynamic import to handle missing dependency gracefully const ruvector = await import('ruvector').catch(() => null); // ruvector exports VectorDB class, not createVectorDB function if (ruvector && (typeof ruvector.VectorDB === 'function' || typeof ruvector.VectorDb === 'function')) { // Create adapter module that matches our expected interface const VectorDBClass = ruvector.VectorDB || ruvector.VectorDb; ruvectorModule = { createVectorDB: async (dimensions) => { const db = new VectorDBClass({ dimensions }); // Wrap ruvector's VectorDB to match our interface return { insert: (embedding, id, metadata) => { db.insert({ id, vector: embedding, metadata }); }, search: async (query, k = 10) => { const results = await db.search({ vector: query, k }); return results.map((r) => ({ id: r.id, score: r.score, metadata: r.metadata, })); }, remove: (id) => { db.delete(id); return true; }, size: async () => { const len = await db.len(); return len; }, clear: () => { // Not directly supported - would need to recreate }, }; }, generateEmbedding: (text, dimensions = 768) => { // ruvector may not have this - use fallback return generateHashEmbedding(text, dimensions); }, cosineSimilarity: (a, b) => { return cosineSimilarity(a, b); }, isWASMAccelerated: () => { return ruvector.isWasm?.() ?? false; }, }; isAvailable = true; return true; } } catch { // Silently fail - ruvector is optional } isAvailable = false; return false; } /** * Check if ruvector is available */ export function isRuVectorAvailable() { return isAvailable; } /** * Check if WASM acceleration is enabled */ export function isWASMAccelerated() { if (ruvectorModule && typeof ruvectorModule.isWASMAccelerated === 'function') { return ruvectorModule.isWASMAccelerated(); } return false; } /** * Create a vector database * Uses ruvector HNSW if available, falls back to brute-force search */ export async function createVectorDB(dimensions = 768) { await loadRuVector(); if (ruvectorModule && typeof ruvectorModule.createVectorDB === 'function') { try { return await ruvectorModule.createVectorDB(dimensions); } catch { // Fall back to simple implementation } } return new FallbackVectorDB(dimensions); } /** * Generate an embedding for text * Uses ruvector if available, falls back to hash-based embedding */ export function generateEmbedding(text, dimensions = 768) { if (ruvectorModule && typeof ruvectorModule.generateEmbedding === 'function') { try { return ruvectorModule.generateEmbedding(text, dimensions); } catch { // Fall back to hash-based embedding } } return generateHashEmbedding(text, dimensions); } /** * Compute cosine similarity between two vectors */ export function computeSimilarity(a, b) { if (ruvectorModule && typeof ruvectorModule.cosineSimilarity === 'function') { try { return ruvectorModule.cosineSimilarity(a, b); } catch { // Fall back to JS implementation } } return cosineSimilarity(a, b); } /** * Get status information about the ruvector module */ export function getStatus() { if (!isAvailable) { return { available: false, wasmAccelerated: false, backend: 'fallback', }; } const wasmAccelerated = isWASMAccelerated(); return { available: true, wasmAccelerated, backend: wasmAccelerated ? 'ruvector-wasm' : 'ruvector', }; } //# sourceMappingURL=vector-db.js.map