// DYNAMIC CONFIGURATION MANAGER
// All paths and settings in ONE place - no hardcoded paths anywhere!
// Agents read from this file, making moves/changes safe
import { promises as fs } from 'fs';
import path from 'path';
export class ConfigManager {
constructor() {
this.configPath = null;
this.config = null;
this.initialized = false;
}
// Initialize - finds config file dynamically
async initialize() {
if (this.initialized) return this.config;
// Try common locations
const possiblePaths = [
'C:/MCP/config.json',
process.cwd() + '/config.json',
process.env.MCP_CONFIG_PATH
];
for (const testPath of possiblePaths) {
if (testPath && await this.fileExists(testPath)) {
this.configPath = testPath;
break;
}
}
// If no config found, create default
if (!this.configPath) {
this.configPath = 'C:/MCP/config.json';
await this.createDefaultConfig();
}
// Load config
this.config = await this.loadConfig();
this.initialized = true;
return this.config;
}
// Create default configuration
async createDefaultConfig() {
const defaultConfig = {
version: '1.0.0',
environment: 'development',
// PATHS - All dynamic, change here to move everything
paths: {
root: 'C:/MCP',
agents: {
core: 'C:/MCP/src/agents/core',
specialized: 'C:/MCP/src/agents/specialized'
},
tools: 'C:/MCP/src/tools',
integrations: 'C:/MCP/src/integrations',
logs: {
actions: 'C:/MCP/logs/agent-actions',
system: 'C:/MCP/logs/system',
rollback: 'C:/MCP/logs/rollback'
},
backups: {
daily: 'C:/MCP/backups/daily',
manual: 'C:/MCP/backups/manual'
},
inventory: 'C:/MCP/inventory',
workflows: 'C:/MCP/workflows',
aiProjects: 'C:/AI Projects',
agentSystem: 'C:/AgentSystem',
tools: 'C:/tools'
},
// API KEY ROTATION - Spread load across services
apiKeys: {
rotationEnabled: true,
currentProvider: 'claude',
providers: {
claude: {
enabled: true,
tokensUsed: 0,
dailyLimit: 150000,
priority: 1
},
gpt4: {
enabled: false,
tokensUsed: 0,
dailyLimit: 100000,
priority: 2,
apiKey: 'CONFIGURE_ME'
},
perplexity: {
enabled: false,
tokensUsed: 0,
dailyLimit: 50000,
priority: 3,
apiKey: 'CONFIGURE_ME'
}
}
},
// AGENT SETTINGS
agents: {
autoStart: true,
delegationMode: 'automatic',
active: {
docControl: true,
docOrganizer: true,
qualityAgent: true,
orchestrator: true
}
},
// CODE INTEGRITY CHECKS
integrity: {
enabled: true,
checkBeforeMove: true,
validateImports: true,
backupBeforeChange: true
},
// QNAP/NAS SETTINGS
qnap: {
enabled: false,
host: 'CONFIGURE_ME',
containers: {
n8n: {
name: 'n8n',
port: 5678,
dataPath: '/share/Container/n8n'
}
}
},
// LOGGING SETTINGS
logging: {
level: 'info',
rollbackEnabled: true,
sessionTracking: true,
maxRollbackDays: 7
}
};
await fs.writeFile(
this.configPath,
JSON.stringify(defaultConfig, null, 2)
);
console.log(`📝 Created default config: ${this.configPath}`);
}
// Load configuration
async loadConfig() {
const data = await fs.readFile(this.configPath, 'utf-8');
return JSON.parse(data);
}
// Save configuration
async saveConfig() {
await fs.writeFile(
this.configPath,
JSON.stringify(this.config, null, 2)
);
}
// Get any config value
get(path) {
const keys = path.split('.');
let value = this.config;
for (const key of keys) {
if (value && typeof value === 'object') {
value = value[key];
} else {
return null;
}
}
return value;
}
// Set any config value
async set(path, value) {
const keys = path.split('.');
let current = this.config;
for (let i = 0; i < keys.length - 1; i++) {
if (!current[keys[i]]) {
current[keys[i]] = {};
}
current = current[keys[i]];
}
current[keys[keys.length - 1]] = value;
await this.saveConfig();
}
// API Key rotation methods
getNextAvailableProvider() {
const providers = Object.entries(this.config.apiKeys.providers)
.filter(([_, config]) => config.enabled)
.sort((a, b) => a[1].priority - b[1].priority);
for (const [name, config] of providers) {
if (config.tokensUsed < config.dailyLimit) {
return name;
}
}
return null; // All providers maxed out
}
async trackTokenUsage(provider, tokens) {
const path = `apiKeys.providers.${provider}.tokensUsed`;
const current = this.get(path) || 0;
await this.set(path, current + tokens);
}
async resetDailyTokens() {
for (const provider in this.config.apiKeys.providers) {
await this.set(`apiKeys.providers.${provider}.tokensUsed`, 0);
}
}
// Helper: Check if file exists
async fileExists(filePath) {
try {
await fs.access(filePath);
return true;
} catch {
return false;
}
}
}
// Export singleton
export const configManager = new ConfigManager();