claude-flow
Version:
Enterprise-grade AI agent orchestration with ruv-swarm integration (Alpha Release)
327 lines (275 loc) ⢠12 kB
JavaScript
// batch-manager.js - Batch configuration management utility
import { printSuccess, printError, printInfo, printWarning } from '../utils.js';
import { PROJECT_TEMPLATES, ENVIRONMENT_CONFIGS } from './init/batch-init.js';
import { Deno, cwd, exit, existsSync } from '../node-compat.js';
export async function batchManagerCommand(subArgs, flags) {
const command = subArgs[0];
switch (command) {
case 'create-config':
return await createBatchConfig(subArgs.slice(1), flags);
case 'validate-config':
return await validateBatchConfig(subArgs.slice(1), flags);
case 'list-templates':
return listTemplates();
case 'list-environments':
return listEnvironments();
case 'estimate':
return await estimateBatchOperation(subArgs.slice(1), flags);
case 'help':
default:
return showBatchManagerHelp();
}
}
async function createBatchConfig(args, flags) {
const outputFile = args[0] || 'batch-config.json';
const interactive = flags.interactive || flags.i;
if (interactive) {
return await createInteractiveConfig(outputFile);
}
// Create basic template
const config = {
projects: ['project1', 'project2', 'project3'],
baseOptions: {
sparc: true,
parallel: true,
maxConcurrency: 5,
template: 'web-api',
environments: ['dev']
}
};
try {
await Deno.writeTextFile(outputFile, JSON.stringify(config, null, 2));
printSuccess(`Created batch configuration template: ${outputFile}`);
console.log('Edit the file to customize your batch initialization setup.');
} catch (error) {
printError(`Failed to create config file: ${error.message}`);
}
}
async function createInteractiveConfig(outputFile) {
console.log('š Interactive Batch Configuration Creator');
console.log('==========================================\n');
// This would require a proper CLI prompt library in a real implementation
// For now, we'll create a comprehensive template with comments
const config = {
"_comment": "Batch initialization configuration",
"_templates": Object.keys(PROJECT_TEMPLATES),
"_environments": Object.keys(ENVIRONMENT_CONFIGS),
"baseOptions": {
"sparc": true,
"parallel": true,
"maxConcurrency": 5,
"force": false,
"minimal": false,
"progressTracking": true
},
"projects": {
"_simple_list": ["project1", "project2", "project3"],
"_or_use_projectConfigs_below": "for individual customization"
},
"projectConfigs": {
"example-api": {
"template": "web-api",
"environment": "dev",
"customConfig": {
"database": "postgresql",
"auth": "jwt"
}
},
"example-frontend": {
"template": "react-app",
"environment": "dev",
"customConfig": {
"ui": "material-ui",
"state": "redux"
}
}
}
};
try {
await Deno.writeTextFile(outputFile, JSON.stringify(config, null, 2));
printSuccess(`Created interactive batch configuration: ${outputFile}`);
console.log('\nNext steps:');
console.log('1. Edit the configuration file to match your needs');
console.log('2. Remove the "_comment" and example entries');
console.log('3. Use either "projects" array OR "projectConfigs" object');
console.log(`4. Run: claude-flow init --config ${outputFile}`);
} catch (error) {
printError(`Failed to create interactive config: ${error.message}`);
}
}
async function validateBatchConfig(args, flags) {
const configFile = args[0];
if (!configFile) {
printError('Please specify a configuration file to validate');
return;
}
try {
const content = await Deno.readTextFile(configFile);
const config = JSON.parse(content);
console.log(`š Validating batch configuration: ${configFile}`);
console.log('================================================\n');
const issues = [];
const warnings = [];
// Validate structure
if (!config.projects && !config.projectConfigs) {
issues.push('Missing "projects" array or "projectConfigs" object');
}
if (config.projects && config.projectConfigs) {
warnings.push('Both "projects" and "projectConfigs" specified. "projectConfigs" will take precedence.');
}
// Validate base options
if (config.baseOptions) {
const { maxConcurrency, template, environments } = config.baseOptions;
if (maxConcurrency && (maxConcurrency < 1 || maxConcurrency > 20)) {
issues.push('maxConcurrency must be between 1 and 20');
}
if (template && !PROJECT_TEMPLATES[template]) {
issues.push(`Unknown template: ${template}. Available: ${Object.keys(PROJECT_TEMPLATES).join(', ')}`);
}
if (environments) {
for (const env of environments) {
if (!ENVIRONMENT_CONFIGS[env]) {
issues.push(`Unknown environment: ${env}. Available: ${Object.keys(ENVIRONMENT_CONFIGS).join(', ')}`);
}
}
}
}
// Validate project configs
if (config.projectConfigs) {
for (const [projectName, projectConfig] of Object.entries(config.projectConfigs)) {
if (projectConfig.template && !PROJECT_TEMPLATES[projectConfig.template]) {
issues.push(`Project ${projectName}: Unknown template ${projectConfig.template}`);
}
if (projectConfig.environment && !ENVIRONMENT_CONFIGS[projectConfig.environment]) {
issues.push(`Project ${projectName}: Unknown environment ${projectConfig.environment}`);
}
}
}
// Report results
if (issues.length === 0) {
printSuccess('ā
Configuration is valid!');
if (warnings.length > 0) {
console.log('\nā ļø Warnings:');
warnings.forEach(warning => console.log(` - ${warning}`));
}
// Summary
console.log('\nš Configuration Summary:');
const projectCount = config.projects ? config.projects.length :
config.projectConfigs ? Object.keys(config.projectConfigs).length : 0;
console.log(` Projects: ${projectCount}`);
if (config.baseOptions) {
console.log(` Parallel: ${config.baseOptions.parallel ? 'Yes' : 'No'}`);
console.log(` Max Concurrency: ${config.baseOptions.maxConcurrency || 5}`);
console.log(` SPARC: ${config.baseOptions.sparc ? 'Enabled' : 'Disabled'}`);
console.log(` Template: ${config.baseOptions.template || 'default'}`);
}
} else {
printError('ā Configuration has issues:');
issues.forEach(issue => console.error(` - ${issue}`));
if (warnings.length > 0) {
console.log('\nā ļø Warnings:');
warnings.forEach(warning => console.log(` - ${warning}`));
}
}
} catch (error) {
if (error instanceof Deno.errors.NotFound) {
printError(`Configuration file not found: ${configFile}`);
} else if (error instanceof SyntaxError) {
printError(`Invalid JSON in configuration file: ${error.message}`);
} else {
printError(`Failed to validate configuration: ${error.message}`);
}
}
}
function listTemplates() {
console.log('š Available Project Templates');
console.log('==============================\n');
for (const [key, template] of Object.entries(PROJECT_TEMPLATES)) {
console.log(`šļø ${key}`);
console.log(` Name: ${template.name}`);
console.log(` Description: ${template.description}`);
console.log(` Extra Directories: ${template.extraDirs ? template.extraDirs.length : 0}`);
console.log(` Extra Files: ${template.extraFiles ? Object.keys(template.extraFiles).length : 0}`);
console.log();
}
}
function listEnvironments() {
console.log('š Available Environment Configurations');
console.log('=======================================\n');
for (const [key, env] of Object.entries(ENVIRONMENT_CONFIGS)) {
console.log(`āļø ${key}`);
console.log(` Name: ${env.name}`);
console.log(` Features: ${env.features.join(', ')}`);
console.log(` Config Variables: ${Object.keys(env.config).length}`);
console.log();
}
}
async function estimateBatchOperation(args, flags) {
const configFile = args[0];
if (!configFile) {
printError('Please specify a configuration file to estimate');
return;
}
try {
const content = await Deno.readTextFile(configFile);
const config = JSON.parse(content);
console.log('ā±ļø Batch Operation Estimation');
console.log('=============================\n');
let projectCount = 0;
let totalEnvironments = 0;
if (config.projects) {
projectCount = config.projects.length;
const environments = config.baseOptions?.environments || ['dev'];
totalEnvironments = projectCount * environments.length;
} else if (config.projectConfigs) {
projectCount = Object.keys(config.projectConfigs).length;
totalEnvironments = projectCount; // Each project has its own environment
}
const parallel = config.baseOptions?.parallel !== false;
const maxConcurrency = config.baseOptions?.maxConcurrency || 5;
const avgTimePerProject = 15; // seconds estimate
const sequentialTime = totalEnvironments * avgTimePerProject;
const parallelTime = parallel ? Math.ceil(totalEnvironments / maxConcurrency) * avgTimePerProject : sequentialTime;
console.log(`š Project Count: ${projectCount}`);
console.log(`š Total Environments: ${totalEnvironments}`);
console.log(`ā” Parallel Processing: ${parallel ? 'Enabled' : 'Disabled'}`);
console.log(`š Max Concurrency: ${maxConcurrency}`);
console.log();
console.log(`ā±ļø Estimated Time:`);
console.log(` Sequential: ~${Math.ceil(sequentialTime / 60)} minutes`);
console.log(` Parallel: ~${Math.ceil(parallelTime / 60)} minutes`);
console.log(` Time Savings: ${Math.ceil((sequentialTime - parallelTime) / 60)} minutes`);
console.log();
console.log(`š¾ Estimated Disk Usage:`);
console.log(` Per Project: ~50-200 MB`);
console.log(` Total: ~${Math.ceil(totalEnvironments * 125 / 1024)} GB`);
} catch (error) {
printError(`Failed to estimate batch operation: ${error.message}`);
}
}
function showBatchManagerHelp() {
console.log('š ļø Batch Manager - Configuration and Estimation Tools');
console.log('====================================================\n');
console.log('USAGE:');
console.log(' claude-flow batch <command> [options]\n');
console.log('COMMANDS:');
console.log(' create-config [file] Create batch configuration template');
console.log(' validate-config <file> Validate batch configuration file');
console.log(' list-templates Show available project templates');
console.log(' list-environments Show available environment configs');
console.log(' estimate <config> Estimate time and resources for batch operation');
console.log(' help Show this help message\n');
console.log('OPTIONS:');
console.log(' --interactive, -i Create interactive configuration');
console.log(' --help, -h Show command help\n');
console.log('EXAMPLES:');
console.log(' claude-flow batch create-config my-batch.json');
console.log(' claude-flow batch create-config --interactive');
console.log(' claude-flow batch validate-config my-batch.json');
console.log(' claude-flow batch estimate my-batch.json');
console.log(' claude-flow batch list-templates');
console.log(' claude-flow batch list-environments\n');
console.log('INTEGRATION:');
console.log(' Use created configs with: claude-flow init --config <file>');
console.log(' Or batch init directly: claude-flow init --batch-init project1,project2');
}