UNPKG

remcode

Version:

Turn your AI assistant into a codebase expert. Intelligent code analysis, semantic search, and software engineering guidance through MCP integration.

184 lines (183 loc) 7.96 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.SemanticSearch = void 0; const logger_1 = require("../utils/logger"); const pinecone_1 = require("../vectorizers/storage/pinecone"); const manager_1 = require("../vectorizers/embedders/manager"); const dotenv = __importStar(require("dotenv")); // Load environment variables dotenv.config(); const logger = (0, logger_1.getLogger)('SemanticSearch'); /** * Handles semantic code search using vector embeddings */ class SemanticSearch { constructor(options = {}) { this.storage = null; this.embeddingManager = null; this.initialized = false; this.options = { pineconeApiKey: options.pineconeApiKey || process.env.PINECONE_API_KEY, pineconeIndexName: options.pineconeIndexName || 'remcode-default', pineconeEnvironment: options.pineconeEnvironment || 'gcp-starter', pineconeNamespace: options.pineconeNamespace || 'default', huggingfaceToken: options.huggingfaceToken || process.env.HUGGINGFACE_TOKEN, embeddingModel: options.embeddingModel || 'BAAI/bge-base-en-v1.5', fallbackModel: options.fallbackModel || 'BAAI/bge-small-en-v1.5', embeddingDimension: options.embeddingDimension || 768, batchSize: options.batchSize || 10 }; } async initialize() { logger.info('Initializing semantic search...'); if (!this.options.pineconeApiKey) { throw new Error('Pinecone API key is required for semantic search'); } if (!this.options.huggingfaceToken) { throw new Error('HuggingFace token is required for semantic search'); } try { // Initialize Pinecone storage this.storage = new pinecone_1.PineconeStorage({ apiKey: this.options.pineconeApiKey, indexName: this.options.pineconeIndexName, namespace: this.options.pineconeNamespace, dimension: this.options.embeddingDimension || 768 }); await this.storage.initialize(); // Initialize embedding manager this.embeddingManager = new manager_1.EmbeddingManager({ primary: this.options.embeddingModel, fallback: this.options.fallbackModel, batchSize: this.options.batchSize, token: this.options.huggingfaceToken, dimension: this.options.embeddingDimension || 768 }); this.initialized = true; logger.info('Semantic search initialized successfully'); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`Failed to initialize semantic search: ${errorMessage}`); throw new Error(`Initialization failed: ${errorMessage}`); } } async search(query, topK = 10, filters) { if (!this.initialized || !this.storage || !this.embeddingManager) { throw new Error('Semantic search not initialized. Call initialize() first.'); } if (!query.trim()) { throw new Error('Search query cannot be empty'); } logger.info(`Searching for: "${query}" (top ${topK} results)`); try { // 1. Generate embedding for the query const queryChunk = { content: query, metadata: { file_path: 'query', strategy: 'query', chunk_type: 'query' } }; const embeddedQueries = await this.embeddingManager.embedChunks([queryChunk]); if (!embeddedQueries[0].embedding) { throw new Error('Failed to generate embedding for query'); } // 2. Search Pinecone for similar vectors const matches = await this.storage.queryVectors(embeddedQueries[0].embedding, topK, filters, this.options.pineconeNamespace); // 3. Format results for consistent API const formattedResults = matches.map(match => ({ id: match.id || '', score: match.score || 0, content: match.metadata?.content || '', metadata: { filePath: match.metadata?.file_path || '', language: match.metadata?.language || '', chunkType: match.metadata?.chunk_type || '', startLine: match.metadata?.start_line, endLine: match.metadata?.end_line, functionName: match.metadata?.function_name, className: match.metadata?.class_name, ...match.metadata } })); logger.info(`Found ${formattedResults.length} results for query: "${query}"`); return formattedResults; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`Search failed: ${errorMessage}`); throw new Error(`Search failed: ${errorMessage}`); } } async searchSimilarCode(codeSnippet, topK = 5) { return this.search(`code: ${codeSnippet}`, topK, { chunk_type: 'function' }); } async searchPatterns(pattern, topK = 10) { return this.search(`pattern: ${pattern}`, topK); } async searchFunctionality(description, topK = 10) { return this.search(`functionality: ${description}`, topK); } formatSearchResults(matches) { return matches.map(match => ({ id: match.id, score: match.score, content: match.metadata?.content || '', metadata: { filePath: match.metadata?.file_path || '', language: match.metadata?.language || '', chunkType: match.metadata?.chunk_type || '', startLine: match.metadata?.start_line, endLine: match.metadata?.end_line, functionName: match.metadata?.function_name, className: match.metadata?.class_name, ...match.metadata } })); } async getStats() { if (!this.initialized || !this.storage) { throw new Error('Semantic search not initialized'); } return await this.storage.getIndexStats(); } isInitialized() { return this.initialized; } } exports.SemanticSearch = SemanticSearch;