agentic-qe
Version:
Agentic Quality Engineering Fleet System - AI-driven quality management platform
745 lines (730 loc) ⢠35.3 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FleetCommand = void 0;
const chalk_1 = __importDefault(require("chalk"));
const ora_1 = __importDefault(require("ora"));
const fs = __importStar(require("fs-extra"));
class FleetCommand {
static async execute(action, options) {
console.log(chalk_1.default.blue.bold('\nš Fleet Management Operations\n'));
try {
// Validate inputs
await this.validateInputs(action, options);
const spinner = (0, ora_1.default)('Initializing fleet operation...').start();
// Execute the requested action
switch (action) {
case 'status':
await this.showFleetStatus(options, spinner);
break;
case 'scale':
await this.scaleFleet(options, spinner);
break;
case 'deploy':
await this.deployFleet(options, spinner);
break;
case 'destroy':
await this.destroyFleet(options, spinner);
break;
case 'health':
await this.healthCheck(options, spinner);
break;
default:
await this.showFleetStatus(options, spinner);
}
}
catch (error) {
console.error(chalk_1.default.red('ā Fleet operation failed:'), error.message);
if (options.verbose) {
console.error(chalk_1.default.gray(error.stack));
}
process.exit(1);
}
}
static async validateInputs(action, options) {
const validActions = ['status', 'scale', 'deploy', 'destroy', 'health'];
if (!validActions.includes(action)) {
throw new Error(`Invalid action '${action}'. Must be one of: ${validActions.join(', ')}`);
}
if (action === 'scale' && !options.agents) {
throw new Error('Agent count required for scaling operation');
}
if (action === 'scale' && options.agents) {
const agentCount = parseInt(options.agents);
if (agentCount < 1 || agentCount > 50) {
throw new Error('Agent count must be between 1 and 50');
}
}
// Check if fleet configuration exists
if (!await fs.pathExists('.agentic-qe/config/fleet.json')) {
throw new Error('Fleet not initialized. Run: agentic-qe init');
}
}
static async showFleetStatus(options, spinner) {
spinner.text = 'Loading fleet configuration...';
// Load fleet configuration
const fleetConfig = await fs.readJson('.agentic-qe/config/fleet.json');
const agentConfig = await fs.readJson('.agentic-qe/config/agents.json');
spinner.text = 'Analyzing fleet status...';
// Load fleet registry
const registryPath = '.agentic-qe/data/registry.json';
let fleetRegistry = { fleet: { agents: [], status: 'unknown' } };
if (await fs.pathExists(registryPath)) {
fleetRegistry = await fs.readJson(registryPath);
}
// Get execution history
const executionHistory = await this.getExecutionHistory();
// Analyze agent performance
const agentPerformance = await this.analyzeAgentPerformance();
spinner.succeed(chalk_1.default.green('Fleet status loaded successfully!'));
// Display comprehensive status
this.displayFleetStatus(fleetConfig, agentConfig, fleetRegistry, executionHistory, agentPerformance, options);
// Store status check in coordination
await this.storeStatusCheck();
}
static async scaleFleet(options, spinner) {
const targetAgents = parseInt(options.agents);
spinner.text = `Scaling fleet to ${targetAgents} agents...`;
// Load current configuration
const fleetConfig = await fs.readJson('.agentic-qe/config/fleet.json');
const agentConfig = await fs.readJson('.agentic-qe/config/agents.json');
// Calculate scaling changes
const currentAgents = fleetConfig.maxAgents;
const scalingOperation = targetAgents > currentAgents ? 'scale-up' : 'scale-down';
spinner.text = `Performing ${scalingOperation} operation...`;
// Update configuration
fleetConfig.maxAgents = targetAgents;
fleetConfig.lastModified = new Date().toISOString();
// Update agent distribution
const agentTypes = agentConfig.fleet.agents;
const agentsPerType = Math.ceil(targetAgents / agentTypes.length);
agentTypes.forEach((agent) => {
agent.count = Math.min(agentsPerType, targetAgents);
});
agentConfig.fleet.maxAgents = targetAgents;
spinner.text = 'Updating configuration files...';
// Save updated configurations
await fs.writeJson('.agentic-qe/config/fleet.json', fleetConfig, { spaces: 2 });
await fs.writeJson('.agentic-qe/config/agents.json', agentConfig, { spaces: 2 });
// Generate scaling script
await this.generateScalingScript(scalingOperation, currentAgents, targetAgents, options);
spinner.succeed(chalk_1.default.green(`Fleet scaled from ${currentAgents} to ${targetAgents} agents!`));
// Display scaling summary
this.displayScalingSummary(currentAgents, targetAgents, scalingOperation);
// Store scaling operation in coordination
await this.storeScalingOperation(currentAgents, targetAgents);
}
static async deployFleet(options, spinner) {
spinner.text = `Deploying fleet to ${options.env} environment...`;
// Load configurations
const fleetConfig = await fs.readJson('.agentic-qe/config/fleet.json');
const envConfig = await this.loadEnvironmentConfig(options.env);
spinner.text = 'Preparing deployment manifests...';
// Generate deployment configuration
const deploymentConfig = await this.generateDeploymentConfig(fleetConfig, envConfig, options);
spinner.text = 'Creating deployment artifacts...';
// Create deployment directory
const deploymentDir = `.agentic-qe/deployments/${options.env}-${Date.now()}`;
await fs.ensureDir(deploymentDir);
// Write deployment artifacts
await fs.writeJson(`${deploymentDir}/deployment.json`, deploymentConfig, { spaces: 2 });
// Generate deployment scripts
await this.generateDeploymentScripts(deploymentDir, deploymentConfig, options);
spinner.text = 'Validating deployment configuration...';
// Validate deployment
const validation = await this.validateDeployment(deploymentConfig);
if (!validation.valid) {
throw new Error(`Deployment validation failed: ${validation.errors.join(', ')}`);
}
spinner.succeed(chalk_1.default.green(`Fleet deployment prepared for ${options.env} environment!`));
// Display deployment summary
this.displayDeploymentSummary(deploymentConfig, validation, options);
// Store deployment operation
await this.storeDeploymentOperation(deploymentConfig);
}
static async destroyFleet(options, spinner) {
spinner.text = 'Initiating fleet destruction...';
// Load current configuration
const fleetConfig = await fs.readJson('.agentic-qe/config/fleet.json');
spinner.text = 'Stopping all agents gracefully...';
// Generate destruction script
const destructionScript = `#!/bin/bash
# Fleet Destruction Script
echo "Stopping Agentic QE Fleet..."
# Stop coordination
npx claude-flow@alpha hooks notify --message "Fleet destruction initiated"
# Archive current state
mkdir -p .agentic-qe/archive/$(date +%Y%m%d-%H%M%S)
cp -r .agentic-qe/data/* .agentic-qe/archive/$(date +%Y%m%d-%H%M%S)/
cp -r .agentic-qe/reports/* .agentic-qe/archive/$(date +%Y%m%d-%H%M%S)/
# Clear runtime data
rm -rf .agentic-qe/data/registry.json
rm -rf .agentic-qe/executions/*
echo "Fleet destroyed successfully"
npx claude-flow@alpha hooks notify --message "Fleet destruction completed"
`;
await fs.writeFile('.agentic-qe/scripts/destroy-fleet.sh', destructionScript);
await fs.chmod('.agentic-qe/scripts/destroy-fleet.sh', '755');
spinner.text = 'Archiving fleet data...';
// Create archive
const archiveDir = `.agentic-qe/archive/${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}`;
await fs.ensureDir(archiveDir);
// Archive important data
const dataToArchive = [
'.agentic-qe/config',
'.agentic-qe/data',
'.agentic-qe/reports'
];
for (const dataPath of dataToArchive) {
if (await fs.pathExists(dataPath)) {
await fs.copy(dataPath, `${archiveDir}/${dataPath.split('/').pop()}`);
}
}
spinner.text = 'Cleaning up fleet resources...';
// Update fleet status
const destructionRecord = {
fleet: {
id: fleetConfig.fleet?.id || 'unknown',
status: 'destroyed',
destroyedAt: new Date().toISOString(),
reason: 'user_requested',
agentCount: fleetConfig.maxAgents
}
};
await fs.writeJson('.agentic-qe/data/destruction.json', destructionRecord, { spaces: 2 });
spinner.succeed(chalk_1.default.green('Fleet destroyed successfully!'));
// Display destruction summary
this.displayDestructionSummary(fleetConfig, archiveDir);
// Store destruction operation
await this.storeDestructionOperation(destructionRecord);
}
static async healthCheck(options, spinner) {
spinner.text = 'Running comprehensive health check...';
const healthReport = {
timestamp: new Date().toISOString(),
overall: 'unknown',
components: {},
issues: [],
recommendations: []
};
// Check configuration files
spinner.text = 'Checking configuration integrity...';
healthReport.components.configuration = await this.checkConfigurationHealth();
// Check data integrity
spinner.text = 'Checking data integrity...';
healthReport.components.data = await this.checkDataHealth();
// Check recent executions
spinner.text = 'Checking execution history...';
healthReport.components.executions = await this.checkExecutionHealth();
// Check coordination status
spinner.text = 'Checking coordination status...';
healthReport.components.coordination = await this.checkCoordinationHealth();
// Calculate overall health
const componentStatuses = Object.values(healthReport.components).map((c) => c.status);
const healthyCount = componentStatuses.filter((status) => status === 'healthy').length;
const totalCount = componentStatuses.length;
if (healthyCount === totalCount) {
healthReport.overall = 'healthy';
}
else if (healthyCount >= totalCount * 0.7) {
healthReport.overall = 'degraded';
}
else {
healthReport.overall = 'critical';
}
// Generate recommendations
healthReport.recommendations = this.generateHealthRecommendations(healthReport.components);
spinner.succeed(chalk_1.default.green('Health check completed!'));
// Display health report
this.displayHealthReport(healthReport, options);
// Store health check results
await this.storeHealthCheck(healthReport);
}
static async getExecutionHistory() {
const reportsDir = '.agentic-qe/reports';
if (!await fs.pathExists(reportsDir)) {
return [];
}
const reportFiles = await fs.readdir(reportsDir);
const executionFiles = reportFiles
.filter(file => file.startsWith('execution-') && file.endsWith('.json'))
.sort()
.reverse()
.slice(0, 10); // Last 10 executions
const history = [];
for (const file of executionFiles) {
try {
const execution = await fs.readJson(`${reportsDir}/${file}`);
history.push(execution);
}
catch (error) {
// Skip corrupted files
}
}
return history;
}
static async analyzeAgentPerformance() {
const executionHistory = await this.getExecutionHistory();
const performance = {
totalExecutions: executionHistory.length,
averageSuccess: 0,
averageDuration: 0,
agentUtilization: {},
trends: 'stable'
};
if (executionHistory.length === 0) {
return performance;
}
// Calculate averages
const totalTests = executionHistory.reduce((sum, exec) => sum + (exec.summary?.total || 0), 0);
const passedTests = executionHistory.reduce((sum, exec) => sum + (exec.summary?.passed || 0), 0);
const totalDuration = executionHistory.reduce((sum, exec) => sum + (exec.summary?.duration || 0), 0);
performance.averageSuccess = totalTests > 0 ? (passedTests / totalTests) * 100 : 0;
performance.averageDuration = totalDuration / executionHistory.length;
// Analyze agent utilization
executionHistory.forEach(exec => {
Object.entries(exec.agents || {}).forEach(([agent, data]) => {
if (!performance.agentUtilization[agent]) {
performance.agentUtilization[agent] = {
usage: 0,
tasks: 0,
avgDuration: 0
};
}
performance.agentUtilization[agent].usage++;
performance.agentUtilization[agent].tasks += data.tasks || 0;
performance.agentUtilization[agent].avgDuration += data.duration || 0;
});
});
// Normalize agent utilization
Object.values(performance.agentUtilization).forEach((agent) => {
agent.avgDuration = agent.avgDuration / agent.usage;
});
return performance;
}
static displayFleetStatus(fleetConfig, agentConfig, registry, history, performance, options) {
console.log(chalk_1.default.yellow('\nš Fleet Status Dashboard\n'));
// Basic fleet information
console.log(chalk_1.default.blue('š Fleet Configuration:'));
console.log(chalk_1.default.gray(` Topology: ${fleetConfig.topology}`));
console.log(chalk_1.default.gray(` Max Agents: ${fleetConfig.maxAgents}`));
console.log(chalk_1.default.gray(` Testing Focus: ${fleetConfig.testingFocus?.join(', ') || 'Not specified'}`));
console.log(chalk_1.default.gray(` Environments: ${fleetConfig.environments?.join(', ') || 'Not specified'}`));
// Agent configuration
console.log(chalk_1.default.blue('\nš¤ Agent Configuration:'));
const agents = agentConfig.fleet?.agents || [];
agents.forEach((agent) => {
console.log(chalk_1.default.gray(` ${agent.type}: ${agent.count} instances`));
});
// Fleet status
console.log(chalk_1.default.blue('\nš Fleet Metrics:'));
console.log(chalk_1.default.gray(` Registry Status: ${registry.fleet?.status || 'Unknown'}`));
console.log(chalk_1.default.gray(` Total Executions: ${performance.totalExecutions}`));
console.log(chalk_1.default.gray(` Average Success Rate: ${performance.averageSuccess.toFixed(1)}%`));
console.log(chalk_1.default.gray(` Average Execution Time: ${(performance.averageDuration / 1000).toFixed(2)}s`));
// Recent activity
if (history.length > 0) {
console.log(chalk_1.default.blue('\nš Recent Activity:'));
const latest = history[0];
console.log(chalk_1.default.gray(` Latest Execution: ${new Date(latest.timestamp).toLocaleString()}`));
console.log(chalk_1.default.gray(` Tests: ${latest.summary?.passed || 0}/${latest.summary?.total || 0} passed`));
console.log(chalk_1.default.gray(` Duration: ${((latest.summary?.duration || 0) / 1000).toFixed(2)}s`));
}
// Agent utilization (if verbose)
if (options.verbose && Object.keys(performance.agentUtilization).length > 0) {
console.log(chalk_1.default.blue('\nš§ Agent Utilization:'));
Object.entries(performance.agentUtilization).forEach(([agent, data]) => {
console.log(chalk_1.default.gray(` ${agent}: ${data.usage} uses, ${data.tasks} tasks, ${(data.avgDuration / 1000).toFixed(2)}s avg`));
});
}
// Health indicators
const healthStatus = this.calculateFleetHealth(fleetConfig, history, performance);
console.log(chalk_1.default.blue('\nš Health Status:'));
console.log(chalk_1.default.gray(` Overall: ${this.getHealthColor(healthStatus.overall)}${healthStatus.overall}`));
if (healthStatus.warnings.length > 0) {
console.log(chalk_1.default.yellow('\nā ļø Warnings:'));
healthStatus.warnings.forEach((warning) => {
console.log(chalk_1.default.yellow(` ⢠${warning}`));
});
}
// Next actions
console.log(chalk_1.default.yellow('\nš” Recommended Actions:'));
if (performance.totalExecutions === 0) {
console.log(chalk_1.default.gray(' 1. Run initial tests: agentic-qe run tests'));
}
else {
console.log(chalk_1.default.gray(' 1. Monitor fleet performance regularly'));
if (performance.averageSuccess < 90) {
console.log(chalk_1.default.gray(' 2. Investigate failing tests'));
}
}
console.log(chalk_1.default.gray(' 3. Scale fleet if needed: agentic-qe fleet scale --agents <count>'));
}
static calculateFleetHealth(fleetConfig, history, performance) {
const health = {
overall: 'healthy',
warnings: []
};
// Check configuration issues
if (!fleetConfig.testingFocus || fleetConfig.testingFocus.length === 0) {
health.warnings.push('No testing focus areas configured');
}
// Check execution history
if (history.length === 0) {
health.warnings.push('No test execution history found');
health.overall = 'unknown';
}
else {
// Check success rate
if (performance.averageSuccess < 80) {
health.warnings.push(`Low success rate: ${performance.averageSuccess.toFixed(1)}%`);
health.overall = 'degraded';
}
// Check recent activity
const latestExecution = new Date(history[0].timestamp);
const daysSinceLastExecution = (Date.now() - latestExecution.getTime()) / (1000 * 60 * 60 * 24);
if (daysSinceLastExecution > 7) {
health.warnings.push('No recent test executions (>7 days)');
health.overall = 'stale';
}
}
// Critical issues
if (health.warnings.length > 3) {
health.overall = 'critical';
}
return health;
}
static getHealthColor(status) {
const colors = {
'healthy': chalk_1.default.green,
'degraded': chalk_1.default.yellow,
'critical': chalk_1.default.red,
'unknown': chalk_1.default.gray,
'stale': chalk_1.default.yellow
};
return (colors[status] || chalk_1.default.white);
}
static displayScalingSummary(current, target, operation) {
console.log(chalk_1.default.yellow('\nš Scaling Summary:'));
console.log(chalk_1.default.gray(` Operation: ${operation}`));
console.log(chalk_1.default.gray(` Previous Agent Count: ${current}`));
console.log(chalk_1.default.gray(` New Agent Count: ${target}`));
console.log(chalk_1.default.gray(` Change: ${target > current ? '+' : ''}${target - current} agents`));
console.log(chalk_1.default.yellow('\nš” Next Steps:'));
console.log(chalk_1.default.gray(' 1. Verify agent allocation with: agentic-qe fleet status --verbose'));
console.log(chalk_1.default.gray(' 2. Run tests to validate scaled fleet: agentic-qe run tests'));
}
static displayDeploymentSummary(config, validation, options) {
console.log(chalk_1.default.yellow('\nš¦ Deployment Summary:'));
console.log(chalk_1.default.gray(` Environment: ${options.env}`));
console.log(chalk_1.default.gray(` Agents: ${config.agentCount}`));
console.log(chalk_1.default.gray(` Components: ${config.components?.length || 0}`));
console.log(chalk_1.default.gray(` Validation: ${validation.valid ? 'Passed' : 'Failed'}`));
if (validation.warnings?.length > 0) {
console.log(chalk_1.default.yellow('\nā ļø Deployment Warnings:'));
validation.warnings.forEach((warning) => {
console.log(chalk_1.default.yellow(` ⢠${warning}`));
});
}
console.log(chalk_1.default.yellow('\nš” Next Steps:'));
console.log(chalk_1.default.gray(' 1. Review deployment artifacts in .agentic-qe/deployments/'));
console.log(chalk_1.default.gray(' 2. Execute deployment script to apply changes'));
console.log(chalk_1.default.gray(' 3. Monitor deployment status after execution'));
}
static displayDestructionSummary(fleetConfig, archiveDir) {
console.log(chalk_1.default.yellow('\nš„ Fleet Destruction Summary:'));
console.log(chalk_1.default.gray(` Fleet ID: ${fleetConfig.fleet?.id || 'Unknown'}`));
console.log(chalk_1.default.gray(` Agents Destroyed: ${fleetConfig.maxAgents}`));
console.log(chalk_1.default.gray(` Data Archived: ${archiveDir}`));
console.log(chalk_1.default.gray(` Destruction Time: ${new Date().toLocaleString()}`));
console.log(chalk_1.default.yellow('\nš” Important Notes:'));
console.log(chalk_1.default.gray(' ⢠All fleet data has been archived for recovery'));
console.log(chalk_1.default.gray(' ⢠Run agentic-qe init to create a new fleet'));
console.log(chalk_1.default.gray(' ⢠Historical data remains accessible in archive'));
}
static displayHealthReport(healthReport, options) {
console.log(chalk_1.default.yellow('\nš„ Fleet Health Report\n'));
// Overall status
const overallColor = this.getHealthColor(healthReport.overall);
console.log(chalk_1.default.blue('š Overall Health:'));
console.log(` Status: ${overallColor(healthReport.overall.toUpperCase())}`);
// Component health
console.log(chalk_1.default.blue('\nš§ Component Health:'));
Object.entries(healthReport.components).forEach(([component, data]) => {
const statusColor = this.getHealthColor(data.status);
console.log(` ${component}: ${statusColor(data.status)} ${data.message ? `- ${data.message}` : ''}`);
});
// Issues
if (healthReport.issues.length > 0) {
console.log(chalk_1.default.red('\nšØ Issues Found:'));
healthReport.issues.forEach((issue) => {
console.log(chalk_1.default.red(` ⢠${issue.severity.toUpperCase()}: ${issue.description}`));
});
}
// Recommendations
if (healthReport.recommendations.length > 0) {
console.log(chalk_1.default.yellow('\nš” Recommendations:'));
healthReport.recommendations.forEach((rec) => {
console.log(chalk_1.default.gray(` ⢠${rec}`));
});
}
console.log(chalk_1.default.yellow('\nš Health Report Saved:'));
console.log(chalk_1.default.gray(' Location: .agentic-qe/reports/health-check-[timestamp].json'));
}
// Helper methods for deployment and health checks
static async loadEnvironmentConfig(env) {
const envConfigPath = `.agentic-qe/config/environments.json`;
if (await fs.pathExists(envConfigPath)) {
const envConfigs = await fs.readJson(envConfigPath);
return envConfigs[env] || {};
}
return {};
}
static async generateDeploymentConfig(fleetConfig, envConfig, options) {
return {
version: '1.0',
environment: options.env,
fleet: fleetConfig,
environment_config: envConfig,
agentCount: fleetConfig.maxAgents,
components: [
'fleet-manager',
'agent-registry',
'coordination-service',
'monitoring-dashboard'
],
resources: {
memory: `${fleetConfig.maxAgents * 100}MB`,
cpu: `${fleetConfig.maxAgents * 0.5}`,
storage: '1GB'
},
metadata: {
generatedAt: new Date().toISOString(),
topology: fleetConfig.topology
}
};
}
static async generateDeploymentScripts(deploymentDir, config, options) {
const deployScript = `#!/bin/bash
# Deployment script for ${options.env} environment
echo "Deploying Agentic QE Fleet to ${options.env}..."
# Pre-deployment hooks
npx claude-flow@alpha hooks pre-task --description "Fleet deployment to ${options.env}"
# Deploy components
echo "Deploying ${config.agentCount} agents..."
# Post-deployment validation
echo "Validating deployment..."
# Store deployment status
npx claude-flow@alpha memory store --key "agentic-qe/deployment/status" --value "deployed"
npx claude-flow@alpha hooks notify --message "Fleet deployed to ${options.env}"
echo "Deployment completed successfully!"
`;
await fs.writeFile(`${deploymentDir}/deploy.sh`, deployScript);
await fs.chmod(`${deploymentDir}/deploy.sh`, '755');
}
static async validateDeployment(config) {
const validation = {
valid: true,
errors: [],
warnings: []
};
// Validate agent count
if (config.agentCount < 1) {
validation.errors.push('Agent count must be at least 1');
validation.valid = false;
}
// Validate resources
if (!config.resources) {
validation.warnings.push('No resource limits specified');
}
// Validate environment
if (!config.environment) {
validation.errors.push('Environment not specified');
validation.valid = false;
}
return validation;
}
static async generateScalingScript(operation, current, target, options) {
const script = `#!/bin/bash
# Fleet scaling script: ${operation}
echo "Scaling fleet from ${current} to ${target} agents..."
# Pre-scaling coordination
npx claude-flow@alpha hooks pre-task --description "Fleet scaling: ${operation}"
# Update agent configurations
echo "Updating agent configurations..."
# Restart services if needed
if [ "${operation}" = "scale-up" ]; then
echo "Starting additional agents..."
else
echo "Stopping excess agents..."
fi
# Post-scaling validation
echo "Validating scaled fleet..."
# Store scaling results
npx claude-flow@alpha memory store --key "agentic-qe/scaling/latest" --value '{"from":${current},"to":${target},"operation":"${operation}"}'
npx claude-flow@alpha hooks notify --message "Fleet scaled: ${operation} from ${current} to ${target} agents"
echo "Scaling completed successfully!"
`;
await fs.writeFile('.agentic-qe/scripts/scale-fleet.sh', script);
await fs.chmod('.agentic-qe/scripts/scale-fleet.sh', '755');
}
static async checkConfigurationHealth() {
const health = { status: 'healthy', issues: [] };
const requiredFiles = [
'.agentic-qe/config/fleet.json',
'.agentic-qe/config/agents.json'
];
for (const file of requiredFiles) {
if (!await fs.pathExists(file)) {
health.issues.push(`Missing configuration file: ${file}`);
health.status = 'critical';
}
}
return health;
}
static async checkDataHealth() {
const health = { status: 'healthy', issues: [] };
// Check if data directory exists
if (!await fs.pathExists('.agentic-qe/data')) {
health.issues.push('Data directory missing');
health.status = 'degraded';
}
return health;
}
static async checkExecutionHealth() {
const health = { status: 'healthy', issues: [] };
const executionHistory = await this.getExecutionHistory();
if (executionHistory.length === 0) {
health.issues.push('No execution history found');
health.status = 'unknown';
}
else {
const latestExecution = executionHistory[0];
const failureRate = latestExecution.summary?.failed / latestExecution.summary?.total;
if (failureRate > 0.2) {
health.issues.push(`High failure rate: ${(failureRate * 100).toFixed(1)}%`);
health.status = 'degraded';
}
}
return health;
}
static async checkCoordinationHealth() {
const health = { status: 'healthy', issues: [] };
// Check if coordination scripts exist
const coordinationScripts = [
'.agentic-qe/scripts/pre-execution.sh',
'.agentic-qe/scripts/post-execution.sh'
];
let scriptsFound = 0;
for (const script of coordinationScripts) {
if (await fs.pathExists(script)) {
scriptsFound++;
}
}
if (scriptsFound === 0) {
health.issues.push('No coordination scripts found');
health.status = 'degraded';
}
return health;
}
static generateHealthRecommendations(components) {
const recommendations = [];
Object.entries(components).forEach(([component, data]) => {
if (data.status !== 'healthy') {
switch (component) {
case 'configuration':
recommendations.push('Run agentic-qe init to recreate missing configuration files');
break;
case 'data':
recommendations.push('Ensure data directory exists and has proper permissions');
break;
case 'executions':
recommendations.push('Run agentic-qe run tests to generate execution history');
break;
case 'coordination':
recommendations.push('Check Claude Flow integration and coordination scripts');
break;
}
}
});
if (recommendations.length === 0) {
recommendations.push('Fleet is healthy - continue regular monitoring');
}
return recommendations;
}
// Coordination storage methods
static async storeStatusCheck() {
const script = `npx claude-flow@alpha hooks notify --message "Fleet status check completed"`;
await this.executeCoordinationScript(script);
}
static async storeScalingOperation(current, target) {
const script = `npx claude-flow@alpha memory store --key "agentic-qe/fleet/scaling" --value '{"from":${current},"to":${target},"timestamp":"${new Date().toISOString()}"}'`;
await this.executeCoordinationScript(script);
}
static async storeDeploymentOperation(config) {
const script = `npx claude-flow@alpha memory store --key "agentic-qe/fleet/deployment" --value '${JSON.stringify(config)}'`;
await this.executeCoordinationScript(script);
}
static async storeDestructionOperation(record) {
const script = `npx claude-flow@alpha memory store --key "agentic-qe/fleet/destruction" --value '${JSON.stringify(record)}'`;
await this.executeCoordinationScript(script);
}
static async storeHealthCheck(healthReport) {
// Save health report to file
const reportsDir = '.agentic-qe/reports';
await fs.ensureDir(reportsDir);
const timestamp = new Date().toISOString().replace(/:/g, '-');
const reportFile = `${reportsDir}/health-check-${timestamp}.json`;
await fs.writeJson(reportFile, healthReport, { spaces: 2 });
// Store in coordination
const script = `npx claude-flow@alpha memory store --key "agentic-qe/fleet/health" --value '{"status":"${healthReport.overall}","timestamp":"${healthReport.timestamp}"}'`;
await this.executeCoordinationScript(script);
}
static async executeCoordinationScript(script) {
try {
const { execSecure } = require('../../../security/secure-command-executor');
// Validate the script contains only safe coordination commands
const allowedCommands = ['npx claude-flow@alpha memory store', 'npx claude-flow@alpha hooks'];
const isAllowedScript = allowedCommands.some(cmd => script.startsWith(cmd));
if (!isAllowedScript) {
console.warn(chalk_1.default.yellow(`ā ļø Script not allowed: ${script}`));
return;
}
execSecure(script, (error) => {
if (error) {
console.warn(chalk_1.default.yellow(`ā ļø Coordination warning: ${error.message}`));
}
});
}
catch (error) {
// Silently handle coordination errors
}
}
}
exports.FleetCommand = FleetCommand;
//# sourceMappingURL=fleet.js.map