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.

225 lines (224 loc) 8.87 kB
import resolve from 'resolve'; import * as path from 'path'; import * as fs from 'fs'; import logger from '../../../logger.js'; export function resolveImport(importPath, options) { if (options.includeAbsolutePath !== true) { return resolveImportLegacy(importPath, options); } if (isBuiltinModule(importPath)) { return { relativePath: importPath }; } if (isExternalPackage(importPath)) { return { relativePath: importPath }; } try { const basedir = path.dirname(options.fromFile); const extensions = options.extensions || getDefaultExtensions(options.language); let resolvedPath = null; try { try { resolvedPath = resolve.sync(importPath, { basedir, extensions, preserveSymlinks: false }); logger.debug({ importPath, resolvedPath, securityExpanded: true }, 'Resolved import path with expanded security boundary'); } catch (expandedError) { logger.debug({ err: expandedError, importPath, basedir }, 'Error resolving import with expanded boundary'); try { const potentialPath = path.resolve(basedir, importPath); for (const ext of extensions) { const fullPath = `${potentialPath}${ext}`; if (fs.existsSync(fullPath)) { resolvedPath = fullPath; logger.debug({ importPath, resolvedPath, method: 'direct-fs' }, 'Resolved import path with direct filesystem check'); break; } } if (!resolvedPath) { throw new Error('Could not resolve with direct filesystem check'); } } catch (directError) { logger.debug({ err: directError, importPath, basedir }, 'Error resolving import with direct filesystem check'); resolvedPath = resolve.sync(importPath, { basedir, extensions, preserveSymlinks: false }); } } let relativePath = importPath; if (options.projectRoot && resolvedPath.startsWith(options.projectRoot)) { relativePath = path.relative(options.projectRoot, resolvedPath); relativePath = relativePath.replace(/\\/g, '/'); if (!relativePath.startsWith('./') && !relativePath.startsWith('../')) { relativePath = `./${relativePath}`; } logger.debug({ originalPath: importPath, resolvedPath, relativePath, projectRoot: options.projectRoot }, 'Resolved import path relative to project root'); } else { logger.debug({ originalPath: importPath, resolvedPath, projectRoot: options.projectRoot }, 'Resolved import path is outside project root'); } return { relativePath, absolutePath: resolvedPath }; } catch (error) { logger.debug({ err: error, importPath, fromFile: options.fromFile }, 'Error resolving absolute path'); return { relativePath: importPath }; } } catch (error) { logger.debug({ err: error, importPath, fromFile: options.fromFile }, 'Error in import resolution'); return { relativePath: importPath }; } } export function clearImportCache() { } export function getImportCacheSize() { return 0; } function resolveImportLegacy(importPath, options) { if (isBuiltinModule(importPath)) { return importPath; } if (isExternalPackage(importPath)) { return importPath; } try { const basedir = path.dirname(options.fromFile); const extensions = options.extensions || getDefaultExtensions(options.language); let resolvedPath = null; try { resolvedPath = resolve.sync(importPath, { basedir, extensions, preserveSymlinks: false }); logger.debug({ importPath, resolvedPath, securityExpanded: true }, 'Resolved import path with expanded security boundary'); } catch (expandedError) { logger.debug({ err: expandedError, importPath, basedir }, 'Error resolving import with expanded boundary'); try { const potentialPath = path.resolve(basedir, importPath); let found = false; for (const ext of extensions) { const fullPath = `${potentialPath}${ext}`; if (fs.existsSync(fullPath)) { resolvedPath = fullPath; found = true; logger.debug({ importPath, resolvedPath, method: 'direct-fs' }, 'Resolved import path with direct filesystem check'); break; } } if (!found) { throw new Error('Could not resolve with direct filesystem check'); } } catch (directError) { logger.debug({ err: directError, importPath, basedir }, 'Error resolving import with direct filesystem check'); resolvedPath = resolve.sync(importPath, { basedir, extensions, preserveSymlinks: false }); } } let finalPath = importPath; if (resolvedPath && options.projectRoot) { if (resolvedPath.startsWith(options.projectRoot)) { finalPath = path.relative(options.projectRoot, resolvedPath); finalPath = finalPath.replace(/\\/g, '/'); if (!finalPath.startsWith('./') && !finalPath.startsWith('../')) { finalPath = `./${finalPath}`; } logger.debug({ originalPath: importPath, resolvedPath, finalPath, projectRoot: options.projectRoot }, 'Resolved import path relative to project root'); } else { logger.debug({ originalPath: importPath, resolvedPath, projectRoot: options.projectRoot }, 'Resolved import path is outside project root'); } } return finalPath; } catch (error) { logger.debug({ err: error, importPath, fromFile: options.fromFile }, 'Error resolving import'); return importPath; } } function isBuiltinModule(moduleName) { const builtinModules = [ 'assert', 'buffer', 'child_process', 'cluster', 'console', 'constants', 'crypto', 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'https', 'module', 'net', 'os', 'path', 'perf_hooks', 'process', 'punycode', 'querystring', 'readline', 'repl', 'stream', 'string_decoder', 'timers', 'tls', 'tty', 'url', 'util', 'v8', 'vm', 'wasi', 'worker_threads', 'zlib' ]; return builtinModules.includes(moduleName); } function isExternalPackage(moduleName) { return !moduleName.startsWith('.') && !moduleName.startsWith('/') && !isBuiltinModule(moduleName); } function getDefaultExtensions(language) { switch (language) { case 'javascript': return ['.js', '.json', '.node', '.mjs', '.cjs']; case 'typescript': return ['.ts', '.tsx', '.js', '.jsx', '.json', '.node']; case 'python': return ['.py', '.pyw', '.pyc', '.pyo', '.pyd']; case 'java': return ['.java', '.class', '.jar']; case 'csharp': return ['.cs', '.dll']; case 'go': return ['.go']; case 'ruby': return ['.rb', '.rake', '.gemspec']; case 'rust': return ['.rs']; case 'php': return ['.php']; default: return ['.js', '.json', '.node']; } }