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.

240 lines (239 loc) 10.6 kB
import logger from '../../../logger.js'; import fs from 'fs/promises'; export class ConfigValidator { static instance; constructor() { } static getInstance() { if (!ConfigValidator.instance) { ConfigValidator.instance = new ConfigValidator(); } return ConfigValidator.instance; } async validateConfig(config) { const errors = []; const warnings = []; const suggestions = []; try { logger.debug('Starting comprehensive configuration validation'); const llmValidation = this.validateLLMConfig(config.llm); errors.push(...llmValidation.errors); warnings.push(...llmValidation.warnings); const mcpValidation = this.validateMCPConfig(config.mcp); errors.push(...mcpValidation.errors); warnings.push(...mcpValidation.warnings); const taskManagerValidation = this.validateTaskManagerConfig(config.taskManager); errors.push(...taskManagerValidation.errors); warnings.push(...taskManagerValidation.warnings); suggestions.push(...taskManagerValidation.suggestions); const performanceValidation = this.validatePerformanceConfig(config.taskManager.performance); errors.push(...performanceValidation.errors); warnings.push(...performanceValidation.warnings); const crossValidation = this.validateCrossConfigDependencies(config); errors.push(...crossValidation.errors); warnings.push(...crossValidation.warnings); const isValid = errors.length === 0; if (isValid) { logger.info('Configuration validation completed successfully'); } else { logger.warn({ errors, warnings }, 'Configuration validation found issues'); } return { isValid, errors, warnings, suggestions, validatedConfig: isValid ? config : undefined }; } catch (error) { logger.error({ error }, 'Configuration validation failed'); return { isValid: false, errors: [`Configuration validation error: ${error instanceof Error ? error.message : 'Unknown error'}`], warnings, suggestions }; } } validateEnvironmentVariables() { const required = [ 'OPENROUTER_API_KEY', 'VIBE_CODER_OUTPUT_DIR' ]; const missing = []; const invalid = []; const warnings = []; for (const envVar of required) { if (!process.env[envVar]) { missing.push(envVar); } } if (process.env.VIBE_SECURITY_PERFORMANCE_THRESHOLD) { const threshold = parseInt(process.env.VIBE_SECURITY_PERFORMANCE_THRESHOLD, 10); if (isNaN(threshold) || threshold < 10 || threshold > 10000) { invalid.push('VIBE_SECURITY_PERFORMANCE_THRESHOLD must be a number between 10 and 10000'); } } if (process.env.VIBE_TASK_MANAGER_SECURITY_MODE) { const mode = process.env.VIBE_TASK_MANAGER_SECURITY_MODE; if (!['strict', 'permissive'].includes(mode)) { invalid.push('VIBE_TASK_MANAGER_SECURITY_MODE must be either "strict" or "permissive"'); } } const deprecated = [ 'VIBE_TASK_MANAGER_CONFIG_PATH', 'VIBE_LEGACY_MODE' ]; for (const envVar of deprecated) { if (process.env[envVar]) { warnings.push(`Environment variable ${envVar} is deprecated and will be ignored`); } } const isValid = missing.length === 0 && invalid.length === 0; return { isValid, missing, invalid, warnings }; } async validateSecurityConfig(config) { const errors = []; const warnings = []; const suggestions = []; try { try { await fs.access(config.allowedReadDirectory, fs.constants.R_OK); } catch { errors.push(`Read directory not accessible: ${config.allowedReadDirectory}`); } try { await fs.access(config.allowedWriteDirectory, fs.constants.W_OK); } catch { try { await fs.mkdir(config.allowedWriteDirectory, { recursive: true }); suggestions.push(`Created write directory: ${config.allowedWriteDirectory}`); } catch { errors.push(`Write directory not accessible and cannot be created: ${config.allowedWriteDirectory}`); } } if (!['strict', 'permissive'].includes(config.securityMode)) { errors.push(`Invalid security mode: ${config.securityMode}. Must be 'strict' or 'permissive'`); } if (config.securityMode === 'permissive') { warnings.push('Security mode is set to permissive. Consider using strict mode for production'); } if (config.allowedReadDirectory === '/' || config.allowedWriteDirectory === '/') { errors.push('Root directory access is not allowed for security reasons'); } if (config.allowedReadDirectory.includes('..') || config.allowedWriteDirectory.includes('..')) { errors.push('Directory paths cannot contain ".." for security reasons'); } } catch (error) { errors.push(`Security configuration validation error: ${error instanceof Error ? error.message : 'Unknown error'}`); } return { isValid: errors.length === 0, errors, warnings, suggestions }; } validateLLMConfig(config) { const errors = []; const warnings = []; if (!config) { errors.push('LLM configuration is required'); return { errors, warnings }; } const llmConfig = config; if (!llmConfig.apiKey) { errors.push('LLM API key is required'); } if (!llmConfig.baseURL) { warnings.push('LLM base URL not specified, using default'); } if (llmConfig.timeout && (typeof llmConfig.timeout === 'number' && (llmConfig.timeout < 1000 || llmConfig.timeout > 300000))) { warnings.push('LLM timeout should be between 1 second and 5 minutes'); } return { errors, warnings }; } validateMCPConfig(config) { const errors = []; const warnings = []; if (!config) { errors.push('MCP configuration is required'); return { errors, warnings }; } const mcpConfig = config; if (mcpConfig.transport && typeof mcpConfig.transport === 'string' && !['stdio', 'sse', 'websocket', 'http'].includes(mcpConfig.transport)) { errors.push(`Invalid MCP transport: ${mcpConfig.transport}`); } return { errors, warnings }; } validateTaskManagerConfig(config) { const errors = []; const warnings = []; const suggestions = []; if (!config) { errors.push('Task Manager configuration is required'); return { errors, warnings, suggestions }; } const taskConfig = config; if (taskConfig.maxConcurrentTasks && typeof taskConfig.maxConcurrentTasks === 'number' && (taskConfig.maxConcurrentTasks < 1 || taskConfig.maxConcurrentTasks > 100)) { errors.push('maxConcurrentTasks must be between 1 and 100'); } const performanceTargets = taskConfig.performanceTargets; if (performanceTargets?.maxResponseTime && typeof performanceTargets.maxResponseTime === 'number' && performanceTargets.maxResponseTime > 1000) { warnings.push('Response time target above 1 second may impact user experience'); } const agentSettings = taskConfig.agentSettings; if (agentSettings?.maxAgents && typeof agentSettings.maxAgents === 'number' && agentSettings.maxAgents > 50) { warnings.push('High number of agents may impact performance'); } const validStrategies = ['round_robin', 'least_loaded', 'capability_based', 'priority_based']; if (agentSettings?.coordinationStrategy && typeof agentSettings.coordinationStrategy === 'string' && !validStrategies.includes(agentSettings.coordinationStrategy)) { errors.push(`Invalid coordination strategy: ${agentSettings.coordinationStrategy}`); } return { errors, warnings, suggestions }; } validatePerformanceConfig(config) { const errors = []; const warnings = []; if (!config) { warnings.push('Performance configuration not specified, using defaults'); return { errors, warnings }; } const perfConfig = config; const memoryManagement = perfConfig.memoryManagement; if (memoryManagement?.maxMemoryPercentage && typeof memoryManagement.maxMemoryPercentage === 'number' && (memoryManagement.maxMemoryPercentage < 10 || memoryManagement.maxMemoryPercentage > 90)) { errors.push('Memory percentage must be between 10% and 90%'); } const caching = perfConfig.caching; if (caching?.maxCacheSize && typeof caching.maxCacheSize === 'number' && caching.maxCacheSize < 1024 * 1024) { warnings.push('Cache size below 1MB may not be effective'); } return { errors, warnings }; } validateCrossConfigDependencies(config) { const errors = []; const warnings = []; const maxConcurrent = config.taskManager.maxConcurrentTasks; const responseTarget = config.taskManager.performanceTargets.maxResponseTime; if (maxConcurrent > 10 && responseTarget < 100) { warnings.push('High concurrency with low response time target may be difficult to achieve'); } const maxAgents = config.taskManager.agentSettings.maxAgents; if (maxAgents > maxConcurrent * 2) { warnings.push('Number of agents significantly exceeds concurrent tasks, may waste resources'); } return { errors, warnings }; } }