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.

275 lines (274 loc) 12.2 kB
import { ENVIRONMENT_VARIABLES, getEnvironmentValue, getEnvironmentVariableDocumentation } from './config-defaults.js'; import { ValidationError, createErrorContext } from './enhanced-errors.js'; import { existsSync } from 'fs'; export class EnvironmentValidator { static instance; constructor() { } static getInstance() { if (!EnvironmentValidator.instance) { EnvironmentValidator.instance = new EnvironmentValidator(); } return EnvironmentValidator.instance; } async validateEnvironment() { const context = createErrorContext('EnvironmentValidator', 'validateEnvironment') .metadata({ totalVariables: Object.keys(ENVIRONMENT_VARIABLES).length }) .build(); try { const errors = []; const warnings = []; const recommendations = []; let validVariables = 0; let invalidVariables = 0; let missingRequired = 0; let usingDefaults = 0; for (const [name, config] of Object.entries(ENVIRONMENT_VARIABLES)) { try { const value = getEnvironmentValue(config, 'validation'); const rawValue = process.env[config.key]; if (!rawValue) { usingDefaults++; if (config.required) { missingRequired++; errors.push({ variable: name, error: `Required environment variable ${config.key} is not set`, severity: 'critical', suggestion: `Set ${config.key}=${config.defaultValue} in your environment` }); invalidVariables++; } else { warnings.push({ variable: name, warning: `Using default value for ${config.key}`, currentValue: value, defaultValue: config.defaultValue, impact: 'May not be optimized for your environment' }); validVariables++; } } else { validVariables++; } await this.performAdditionalValidation(name, config, value, errors, warnings); } catch (error) { invalidVariables++; errors.push({ variable: name, error: error instanceof Error ? error.message : String(error), severity: config.required ? 'critical' : 'medium', suggestion: `Check the format and value of ${config.key}` }); } } recommendations.push(...this.generateRecommendations()); const totalVariables = Object.keys(ENVIRONMENT_VARIABLES).length; return { valid: errors.length === 0, errors, warnings, recommendations, summary: { totalVariables, validVariables, invalidVariables, missingRequired, usingDefaults } }; } catch (error) { throw new ValidationError(`Environment validation failed: ${error instanceof Error ? error.message : String(error)}`, context, { cause: error instanceof Error ? error : undefined }); } } async performAdditionalValidation(name, config, value, errors, warnings) { if (name.includes('DIR') || name.includes('PATH')) { if (typeof value === 'string' && !existsSync(value)) { warnings.push({ variable: name, warning: `Directory/path does not exist: ${value}`, currentValue: value, defaultValue: config.defaultValue, impact: 'May cause runtime errors when accessing files' }); } } if (name.includes('TIMEOUT') && typeof value === 'number') { if (value < 1000) { warnings.push({ variable: name, warning: `Timeout value ${value}ms may be too low`, currentValue: value, defaultValue: config.defaultValue, impact: 'May cause premature timeouts' }); } else if (value > 600000) { warnings.push({ variable: name, warning: `Timeout value ${value}ms may be too high`, currentValue: value, defaultValue: config.defaultValue, impact: 'May cause long waits for failed operations' }); } } if (name.includes('MEMORY') && typeof value === 'number') { if (value > 2048) { warnings.push({ variable: name, warning: `Memory limit ${value}MB is very high`, currentValue: value, defaultValue: config.defaultValue, impact: 'May consume excessive system resources' }); } } if (name.includes('CONCURRENT') || name.includes('MAX_AGENTS')) { if (typeof value === 'number' && value > 20) { warnings.push({ variable: name, warning: `High concurrency value ${value} may overwhelm system`, currentValue: value, defaultValue: config.defaultValue, impact: 'May cause resource contention and performance issues' }); } } } generateRecommendations() { const recommendations = []; recommendations.push({ category: 'performance', recommendation: 'Consider setting VIBE_MAX_RESPONSE_TIME to 30ms for better performance', variables: ['VIBE_MAX_RESPONSE_TIME'], priority: 'medium' }); recommendations.push({ category: 'security', recommendation: 'Use strict security mode in production environments', variables: ['VIBE_TASK_MANAGER_SECURITY_MODE'], priority: 'high' }); recommendations.push({ category: 'development', recommendation: 'Set up dedicated output directory for better organization', variables: ['VIBE_CODER_OUTPUT_DIR'], priority: 'medium' }); return recommendations; } async performHealthCheck() { const startTime = performance.now(); const issues = []; let score = 100; try { const validation = await this.validateEnvironment(); score -= validation.errors.length * 20; score -= validation.warnings.length * 5; validation.errors.forEach(error => { issues.push({ type: 'error', category: 'configuration', message: error.error, variable: error.variable, impact: error.severity === 'critical' ? 'high' : 'medium', resolution: error.suggestion }); }); validation.warnings.forEach(warning => { issues.push({ type: 'warning', category: 'configuration', message: warning.warning, variable: warning.variable, impact: 'low', resolution: `Consider setting ${warning.variable} explicitly` }); }); const memoryUsage = process.memoryUsage(); if (memoryUsage.heapUsed > 100 * 1024 * 1024) { issues.push({ type: 'warning', category: 'performance', message: `High memory usage: ${Math.round(memoryUsage.heapUsed / 1024 / 1024)}MB`, impact: 'medium', resolution: 'Monitor memory usage and consider optimization' }); score -= 10; } const configLoadTime = performance.now() - startTime; if (configLoadTime > 50) { issues.push({ type: 'warning', category: 'performance', message: `Slow configuration loading: ${configLoadTime.toFixed(2)}ms`, impact: 'medium', resolution: 'Enable configuration caching or optimize environment setup' }); score -= 5; } score = Math.max(0, score); return { healthy: score >= 80, score, issues, performance: { configLoadTime, memoryUsage: Math.round(memoryUsage.heapUsed / 1024 / 1024), diskSpace: 0 } }; } catch (error) { issues.push({ type: 'error', category: 'configuration', message: `Health check failed: ${error instanceof Error ? error.message : String(error)}`, impact: 'high', resolution: 'Check environment configuration and system resources' }); return { healthy: false, score: 0, issues, performance: { configLoadTime: performance.now() - startTime, memoryUsage: Math.round(process.memoryUsage().heapUsed / 1024 / 1024), diskSpace: 0 } }; } } generateDocumentation() { const docs = getEnvironmentVariableDocumentation(); let documentation = '# Vibe Task Manager Environment Variables\n\n'; documentation += 'This document describes all environment variables used by the Vibe Task Manager.\n\n'; const categories = { 'Core Configuration': ['VIBE_CODER_OUTPUT_DIR', 'VIBE_TASK_MANAGER_READ_DIR'], 'Task Manager Settings': ['VIBE_MAX_CONCURRENT_TASKS', 'VIBE_DEFAULT_TASK_TEMPLATE'], 'Performance Targets': ['VIBE_MAX_RESPONSE_TIME', 'VIBE_MAX_MEMORY_USAGE', 'VIBE_MIN_TEST_COVERAGE'], 'Agent Settings': ['VIBE_MAX_AGENTS', 'VIBE_DEFAULT_AGENT', 'VIBE_COORDINATION_STRATEGY', 'VIBE_HEALTH_CHECK_INTERVAL'], 'NLP Settings': ['VIBE_PRIMARY_NLP_METHOD', 'VIBE_FALLBACK_NLP_METHOD', 'VIBE_MIN_CONFIDENCE', 'VIBE_MAX_NLP_PROCESSING_TIME'], 'Timeout Settings': ['VIBE_TASK_EXECUTION_TIMEOUT', 'VIBE_TASK_DECOMPOSITION_TIMEOUT', 'VIBE_TASK_REFINEMENT_TIMEOUT', 'VIBE_AGENT_COMMUNICATION_TIMEOUT', 'VIBE_LLM_REQUEST_TIMEOUT', 'VIBE_FILE_OPERATIONS_TIMEOUT', 'VIBE_DATABASE_OPERATIONS_TIMEOUT', 'VIBE_NETWORK_OPERATIONS_TIMEOUT'], 'Retry Policy': ['VIBE_MAX_RETRIES', 'VIBE_BACKOFF_MULTIPLIER', 'VIBE_INITIAL_DELAY_MS', 'VIBE_MAX_DELAY_MS', 'VIBE_ENABLE_EXPONENTIAL_BACKOFF'], 'Security Settings': ['VIBE_TASK_MANAGER_SECURITY_MODE'], 'LLM Configuration': ['VIBE_DEFAULT_LLM_MODEL'] }; for (const [category, variables] of Object.entries(categories)) { documentation += `## ${category}\n\n`; for (const variable of variables) { if (docs[variable]) { documentation += `### ${variable}\n`; documentation += `${docs[variable]}\n\n`; } } } return documentation; } }