vibe-coder-mcp
Version:
Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.
300 lines (299 loc) • 12.5 kB
JavaScript
import path from 'path';
import { readFile } from 'fs/promises';
import { pathExists } from 'fs-extra';
import logger from '../../../logger.js';
import { getProjectRoot } from '../../code-map-generator/utils/pathUtils.enhanced.js';
import { contextCuratorConfigSchema, validateContextCuratorConfig } from '../types/context-curator.js';
export class ContextCuratorConfigLoader {
static instance = null;
config = null;
llmConfig = null;
configLoaded = false;
lastLoadTime = 0;
cacheTTL = 300000;
llmConfigPath;
contextCuratorConfigPath;
constructor() {
const projectRoot = getProjectRoot();
this.llmConfigPath = path.join(projectRoot, 'llm_config.json');
this.contextCuratorConfigPath = path.join(projectRoot, 'context-curator-config.json');
}
static getInstance() {
if (!ContextCuratorConfigLoader.instance) {
ContextCuratorConfigLoader.instance = new ContextCuratorConfigLoader();
}
return ContextCuratorConfigLoader.instance;
}
async loadConfig() {
try {
const now = Date.now();
if (this.configLoaded && (now - this.lastLoadTime) < this.cacheTTL && this.config) {
logger.debug('Using cached Context Curator configuration');
return {
success: true,
config: this.config,
source: 'mixed',
warnings: []
};
}
logger.info('Loading Context Curator configuration...');
const warnings = [];
const llmResult = await this.loadLLMConfig();
if (!llmResult.success) {
warnings.push(`LLM config warning: ${llmResult.error}`);
}
const envConfig = this.loadEnvironmentConfig();
const fileConfig = await this.loadFileConfig();
if (fileConfig.warnings.length > 0) {
warnings.push(...fileConfig.warnings);
}
const mergedConfig = this.mergeConfigurations(envConfig, fileConfig.config);
const validatedConfig = validateContextCuratorConfig(mergedConfig);
this.config = validatedConfig;
this.configLoaded = true;
this.lastLoadTime = now;
logger.info('Context Curator configuration loaded successfully');
return {
success: true,
config: validatedConfig,
source: this.determineConfigSource(envConfig, fileConfig.config),
warnings
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
logger.error('Failed to load Context Curator configuration:', errorMessage);
const now = Date.now();
const defaultConfig = contextCuratorConfigSchema.parse({});
this.config = defaultConfig;
this.configLoaded = true;
this.lastLoadTime = now;
return {
success: false,
config: defaultConfig,
error: errorMessage,
source: 'defaults',
warnings: ['Using default configuration due to load failure']
};
}
}
getConfig() {
return this.config;
}
getLLMModel(operation) {
if (!this.llmConfig) {
return this.getEnvironmentFallbackModel();
}
const prefixedOperation = `context_curator_${operation}`;
return this.llmConfig.llm_mapping[prefixedOperation] ||
this.llmConfig.llm_mapping[operation] ||
this.llmConfig.llm_mapping['default_generation'] ||
this.getEnvironmentFallbackModel();
}
getEnvironmentFallbackModel() {
return process.env.GEMINI_MODEL ||
process.env.VIBE_DEFAULT_LLM_MODEL ||
'google/gemini-2.5-flash-preview-05-20';
}
async reloadConfig() {
this.configLoaded = false;
this.lastLoadTime = 0;
return this.loadConfig();
}
validateConfiguration() {
if (!this.config) {
return { valid: false, errors: ['No configuration loaded'] };
}
try {
validateContextCuratorConfig(this.config);
return { valid: true, errors: [] };
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown validation error';
return { valid: false, errors: [errorMessage] };
}
}
getConfigSummary() {
return {
loaded: this.configLoaded,
lastLoadTime: new Date(this.lastLoadTime).toISOString(),
hasConfig: !!this.config,
hasLLMConfig: !!this.llmConfig,
cacheAge: Date.now() - this.lastLoadTime,
cacheTTL: this.cacheTTL
};
}
async loadLLMConfig() {
try {
if (!(await pathExists(this.llmConfigPath))) {
return { success: false, error: 'LLM config file not found' };
}
const content = await readFile(this.llmConfigPath, 'utf-8');
const llmConfig = JSON.parse(content);
if (!llmConfig.llm_mapping || typeof llmConfig.llm_mapping !== 'object') {
return { success: false, error: 'Invalid LLM config format' };
}
this.llmConfig = llmConfig;
logger.debug('LLM configuration loaded successfully');
return { success: true };
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
logger.warn('Failed to load LLM configuration:', errorMessage);
return { success: false, error: errorMessage };
}
}
loadEnvironmentConfig() {
const envConfig = {};
const contentDensity = {};
if (process.env.VIBE_CONTEXT_CURATOR_MAX_CONTENT_LENGTH) {
const parsed = parseInt(process.env.VIBE_CONTEXT_CURATOR_MAX_CONTENT_LENGTH, 10);
if (!isNaN(parsed)) {
contentDensity.maxContentLength = parsed;
}
}
if (process.env.VIBE_CONTEXT_CURATOR_OPTIMIZATION_THRESHOLD) {
const parsed = parseInt(process.env.VIBE_CONTEXT_CURATOR_OPTIMIZATION_THRESHOLD, 10);
if (!isNaN(parsed)) {
contentDensity.optimizationThreshold = parsed;
}
}
if (process.env.VIBE_CONTEXT_CURATOR_PRESERVE_COMMENTS) {
contentDensity.preserveComments = process.env.VIBE_CONTEXT_CURATOR_PRESERVE_COMMENTS === 'true';
}
if (process.env.VIBE_CONTEXT_CURATOR_PRESERVE_TYPES) {
contentDensity.preserveTypes = process.env.VIBE_CONTEXT_CURATOR_PRESERVE_TYPES === 'true';
}
if (Object.keys(contentDensity).length > 0) {
envConfig.contentDensity = contentDensity;
}
const relevanceScoring = {};
if (process.env.VIBE_CONTEXT_CURATOR_KEYWORD_WEIGHT) {
const parsed = parseFloat(process.env.VIBE_CONTEXT_CURATOR_KEYWORD_WEIGHT);
if (!isNaN(parsed)) {
relevanceScoring.keywordWeight = parsed;
}
}
if (process.env.VIBE_CONTEXT_CURATOR_SEMANTIC_WEIGHT) {
const parsed = parseFloat(process.env.VIBE_CONTEXT_CURATOR_SEMANTIC_WEIGHT);
if (!isNaN(parsed)) {
relevanceScoring.semanticWeight = parsed;
}
}
if (process.env.VIBE_CONTEXT_CURATOR_STRUCTURAL_WEIGHT) {
const parsed = parseFloat(process.env.VIBE_CONTEXT_CURATOR_STRUCTURAL_WEIGHT);
if (!isNaN(parsed)) {
relevanceScoring.structuralWeight = parsed;
}
}
if (process.env.VIBE_CONTEXT_CURATOR_MIN_RELEVANCE_THRESHOLD) {
const parsed = parseFloat(process.env.VIBE_CONTEXT_CURATOR_MIN_RELEVANCE_THRESHOLD);
if (!isNaN(parsed)) {
relevanceScoring.minRelevanceThreshold = parsed;
}
}
if (Object.keys(relevanceScoring).length > 0) {
envConfig.relevanceScoring = relevanceScoring;
}
const outputFormat = {};
if (process.env.VIBE_CONTEXT_CURATOR_INCLUDE_META_PROMPT) {
outputFormat.includeMetaPrompt = process.env.VIBE_CONTEXT_CURATOR_INCLUDE_META_PROMPT === 'true';
}
if (process.env.VIBE_CONTEXT_CURATOR_INCLUDE_FILE_CONTENT) {
outputFormat.includeFileContent = process.env.VIBE_CONTEXT_CURATOR_INCLUDE_FILE_CONTENT === 'true';
}
if (process.env.VIBE_CONTEXT_CURATOR_MAX_TOKENS_PER_FILE) {
const parsed = parseInt(process.env.VIBE_CONTEXT_CURATOR_MAX_TOKENS_PER_FILE, 10);
if (!isNaN(parsed)) {
outputFormat.maxTokensPerFile = parsed;
}
}
if (process.env.VIBE_CONTEXT_CURATOR_XML_VALIDATION) {
outputFormat.xmlValidation = process.env.VIBE_CONTEXT_CURATOR_XML_VALIDATION === 'true';
}
if (Object.keys(outputFormat).length > 0) {
envConfig.outputFormat = outputFormat;
}
const llmIntegration = {};
if (process.env.VIBE_CONTEXT_CURATOR_MAX_RETRIES) {
const parsed = parseInt(process.env.VIBE_CONTEXT_CURATOR_MAX_RETRIES, 10);
if (!isNaN(parsed)) {
llmIntegration.maxRetries = parsed;
}
}
if (process.env.VIBE_CONTEXT_CURATOR_TIMEOUT_MS) {
const parsed = parseInt(process.env.VIBE_CONTEXT_CURATOR_TIMEOUT_MS, 10);
if (!isNaN(parsed)) {
llmIntegration.timeoutMs = parsed;
}
}
if (process.env.VIBE_CONTEXT_CURATOR_FALLBACK_MODEL) {
llmIntegration.fallbackModel = process.env.VIBE_CONTEXT_CURATOR_FALLBACK_MODEL;
}
if (Object.keys(llmIntegration).length > 0) {
envConfig.llmIntegration = llmIntegration;
}
if (Object.keys(envConfig).length > 0) {
logger.debug('Environment configuration loaded');
}
return envConfig;
}
async loadFileConfig() {
const warnings = [];
try {
if (!(await pathExists(this.contextCuratorConfigPath))) {
logger.debug('Context Curator config file not found, using defaults');
return { config: {}, warnings };
}
const content = await readFile(this.contextCuratorConfigPath, 'utf-8');
const fileConfig = JSON.parse(content);
logger.debug('File configuration loaded successfully');
return { config: fileConfig, warnings };
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
warnings.push(`Failed to load file configuration: ${errorMessage}`);
logger.warn('Failed to load file configuration:', errorMessage);
return { config: {}, warnings };
}
}
mergeConfigurations(envConfig, fileConfig) {
const merged = {};
if (fileConfig.contentDensity || envConfig.contentDensity) {
merged.contentDensity = {
...fileConfig.contentDensity,
...envConfig.contentDensity
};
}
if (fileConfig.relevanceScoring || envConfig.relevanceScoring) {
merged.relevanceScoring = {
...fileConfig.relevanceScoring,
...envConfig.relevanceScoring
};
}
if (fileConfig.outputFormat || envConfig.outputFormat) {
merged.outputFormat = {
...fileConfig.outputFormat,
...envConfig.outputFormat
};
}
if (fileConfig.llmIntegration || envConfig.llmIntegration) {
merged.llmIntegration = {
...fileConfig.llmIntegration,
...envConfig.llmIntegration
};
}
return merged;
}
determineConfigSource(envConfig, fileConfig) {
const hasEnvConfig = Object.keys(envConfig).length > 0;
const hasFileConfig = Object.keys(fileConfig).length > 0;
if (hasEnvConfig && hasFileConfig)
return 'mixed';
if (hasEnvConfig)
return 'environment';
if (hasFileConfig)
return 'file';
return 'defaults';
}
}