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
JavaScript
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;
}
}