UNPKG

vibe-coder-mcp

Version:

Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.

151 lines (150 loc) 5.9 kB
import * as path from 'path'; import * as fs from 'fs'; import { DependencyCruiserAdapter } from './dependencyCruiserAdapter.js'; import { ExtendedPythonImportResolver } from './extendedPythonImportResolver.js'; import { ClangdAdapter } from './clangdAdapter.js'; import { SemgrepAdapter } from './semgrepAdapter.js'; import logger from '../../../logger.js'; export class ImportResolverFactory { options; dependencyCruiserAdapter = null; pythonImportResolver = null; clangdAdapter = null; semgrepAdapter = null; adapterLastUsed = new Map(); cleanupTimer = null; ADAPTER_TTL = 10 * 60 * 1000; constructor(options) { this.options = options; this.scheduleCleanup(); } getImportResolver(filePath) { const extension = path.extname(filePath).toLowerCase(); if (['.js', '.jsx', '.ts', '.tsx'].includes(extension)) { return this.getDependencyCruiserAdapter(); } if (['.py', '.pyw'].includes(extension)) { try { const absolutePath = path.isAbsolute(filePath) ? filePath : path.resolve(this.options.allowedDir, filePath); const stats = fs.statSync(absolutePath); if (stats.isFile()) { return this.getPythonImportResolver(); } } catch (error) { logger.debug({ filePath, error: error.message }, 'Error checking Python file'); return null; } } if (['.c', '.h', '.cpp', '.hpp', '.cc', '.cxx'].includes(extension)) { return this.getClangdAdapter(); } if (!this.options.disableSemgrepFallback) { return this.getSemgrepAdapter(); } logger.debug({ filePath, extension }, 'No enhanced import resolver available for this file type'); return null; } getDependencyCruiserAdapter() { this.adapterLastUsed.set('dependencyCruiser', Date.now()); if (!this.dependencyCruiserAdapter) { this.dependencyCruiserAdapter = new DependencyCruiserAdapter(this.options.allowedDir, this.options.outputDir); this.scheduleCleanup(); } return this.dependencyCruiserAdapter; } getPythonImportResolver() { this.adapterLastUsed.set('pythonImportResolver', Date.now()); if (!this.pythonImportResolver) { this.pythonImportResolver = new ExtendedPythonImportResolver(this.options.allowedDir, this.options.outputDir); this.scheduleCleanup(); } return this.pythonImportResolver; } getClangdAdapter() { this.adapterLastUsed.set('clangdAdapter', Date.now()); if (!this.clangdAdapter) { this.clangdAdapter = new ClangdAdapter(this.options.allowedDir, this.options.outputDir); this.scheduleCleanup(); } return this.clangdAdapter; } getSemgrepAdapter() { this.adapterLastUsed.set('semgrepAdapter', Date.now()); if (!this.semgrepAdapter) { this.semgrepAdapter = new SemgrepAdapter(this.options.allowedDir, this.options.outputDir); this.scheduleCleanup(); } return this.semgrepAdapter; } scheduleCleanup() { if (!this.cleanupTimer) { this.cleanupTimer = setTimeout(() => { this.cleanupUnusedAdapters(); this.cleanupTimer = null; }, 5 * 60 * 1000); } } cleanupUnusedAdapters() { const now = Date.now(); let unloadedCount = 0; if (this.dependencyCruiserAdapter && this.adapterLastUsed.has('dependencyCruiser') && now - this.adapterLastUsed.get('dependencyCruiser') > this.ADAPTER_TTL) { this.dependencyCruiserAdapter.dispose(); this.dependencyCruiserAdapter = null; unloadedCount++; } if (this.pythonImportResolver && this.adapterLastUsed.has('pythonImportResolver') && now - this.adapterLastUsed.get('pythonImportResolver') > this.ADAPTER_TTL) { this.pythonImportResolver.dispose(); this.pythonImportResolver = null; unloadedCount++; } if (this.clangdAdapter && this.adapterLastUsed.has('clangdAdapter') && now - this.adapterLastUsed.get('clangdAdapter') > this.ADAPTER_TTL) { this.clangdAdapter.dispose(); this.clangdAdapter = null; unloadedCount++; } if (this.semgrepAdapter && this.adapterLastUsed.has('semgrepAdapter') && now - this.adapterLastUsed.get('semgrepAdapter') > this.ADAPTER_TTL) { this.semgrepAdapter.dispose(); this.semgrepAdapter = null; unloadedCount++; } if (unloadedCount > 0) { logger.info(`Unloaded ${unloadedCount} unused import resolvers`); } if (this.dependencyCruiserAdapter || this.pythonImportResolver || this.clangdAdapter || this.semgrepAdapter) { this.scheduleCleanup(); } } dispose() { if (this.cleanupTimer) { clearTimeout(this.cleanupTimer); this.cleanupTimer = null; } if (this.dependencyCruiserAdapter) { this.dependencyCruiserAdapter.dispose(); this.dependencyCruiserAdapter = null; } if (this.pythonImportResolver) { this.pythonImportResolver.dispose(); this.pythonImportResolver = null; } if (this.clangdAdapter) { this.clangdAdapter.dispose(); this.clangdAdapter = null; } if (this.semgrepAdapter) { this.semgrepAdapter.dispose(); this.semgrepAdapter = null; } logger.debug('ImportResolverFactory disposed'); } }