UNPKG

agentic-qe

Version:

Agentic Quality Engineering Fleet System - AI-driven quality management platform

280 lines (274 loc) โ€ข 12.4 kB
"use strict"; 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.FleetRestartCommand = void 0; const chalk_1 = __importDefault(require("chalk")); const fs = __importStar(require("fs-extra")); class FleetRestartCommand { static async execute(options) { // Check if fleet is initialized if (!await fs.pathExists('.agentic-qe/config/fleet.json')) { throw new Error('Fleet not initialized. Run: aqe fleet init'); } console.log(chalk_1.default.blue.bold('\n๐Ÿ”„ Fleet Restart\n')); const fleetConfig = await fs.readJson('.agentic-qe/config/fleet.json'); // Determine restart mode const mode = options.force ? 'force' : 'graceful'; if (options.force) { console.log(chalk_1.default.yellow('โš ๏ธ Force restart requested - agents will be stopped immediately')); } else { console.log(chalk_1.default.blue('๐Ÿ”„ Graceful restart - waiting for running tasks to complete')); } // Pre-restart backup await this.createRestartBackup(fleetConfig); // Update fleet status await this.updateFleetStatus('restarting'); // Stop agents gracefully or forcefully if (options.graceful) { await this.gracefulStop(); } else if (options.force) { await this.forceStop(); } // Clear runtime data await this.clearRuntimeData(); // Restart agents await this.restartAgents(fleetConfig); // Update fleet status await this.updateFleetStatus('running'); // Verify restart success const restartSuccess = await this.verifyRestart(); if (!restartSuccess && options.rollback) { console.log(chalk_1.default.red('โŒ Restart verification failed - rolling back...')); await this.rollbackRestart(); throw new Error('Fleet restart failed and was rolled back'); } console.log(chalk_1.default.green('\nโœ… Fleet restarted successfully')); // Store restart in coordination await this.storeRestartOperation(mode, restartSuccess); } static async createRestartBackup(fleetConfig) { console.log(chalk_1.default.blue('๐Ÿ’พ Creating pre-restart backup...')); const backupDir = `.agentic-qe/backups/restart-${Date.now()}`; await fs.ensureDir(backupDir); // Backup critical files const filesToBackup = [ '.agentic-qe/config/fleet.json', '.agentic-qe/config/agents.json', '.agentic-qe/data/registry.json' ]; for (const file of filesToBackup) { if (await fs.pathExists(file)) { const fileName = file.split('/').pop(); await fs.copy(file, `${backupDir}/${fileName}`); } } console.log(chalk_1.default.gray(` Backup saved: ${backupDir}`)); } static async updateFleetStatus(status) { const fleetConfig = await fs.readJson('.agentic-qe/config/fleet.json'); fleetConfig.status = status; fleetConfig.lastStatusUpdate = new Date().toISOString(); await fs.writeJson('.agentic-qe/config/fleet.json', fleetConfig, { spaces: 2 }); // Update registry if (await fs.pathExists('.agentic-qe/data/registry.json')) { const registry = await fs.readJson('.agentic-qe/data/registry.json'); registry.fleet = registry.fleet || {}; registry.fleet.status = status; await fs.writeJson('.agentic-qe/data/registry.json', registry, { spaces: 2 }); } } static async gracefulStop() { console.log(chalk_1.default.blue('๐Ÿ›‘ Stopping agents gracefully...')); // Load registry if (await fs.pathExists('.agentic-qe/data/registry.json')) { const registry = await fs.readJson('.agentic-qe/data/registry.json'); const runningTasks = registry.tasks?.filter((t) => t.status === 'running') || []; if (runningTasks.length > 0) { console.log(chalk_1.default.yellow(` Waiting for ${runningTasks.length} running tasks to complete...`)); // In production, this would actually wait for tasks // Simulate waiting await new Promise(resolve => setTimeout(resolve, 2000)); } // Update agent statuses if (registry.agents) { registry.agents.forEach((agent) => { agent.status = 'stopped'; agent.stoppedAt = new Date().toISOString(); }); await fs.writeJson('.agentic-qe/data/registry.json', registry, { spaces: 2 }); } } console.log(chalk_1.default.gray(' All agents stopped gracefully')); } static async forceStop() { console.log(chalk_1.default.yellow('โš ๏ธ Force stopping all agents...')); // Load registry and force stop if (await fs.pathExists('.agentic-qe/data/registry.json')) { const registry = await fs.readJson('.agentic-qe/data/registry.json'); if (registry.agents) { registry.agents.forEach((agent) => { agent.status = 'stopped'; agent.forceStopped = true; agent.stoppedAt = new Date().toISOString(); }); // Mark running tasks as interrupted if (registry.tasks) { registry.tasks.forEach((task) => { if (task.status === 'running') { task.status = 'interrupted'; task.interruptedAt = new Date().toISOString(); } }); } await fs.writeJson('.agentic-qe/data/registry.json', registry, { spaces: 2 }); } } console.log(chalk_1.default.gray(' All agents force stopped')); } static async clearRuntimeData() { console.log(chalk_1.default.blue('๐Ÿงน Clearing runtime data...')); // Clear temporary execution data const tempDirs = [ '.agentic-qe/tmp', '.agentic-qe/cache' ]; for (const dir of tempDirs) { if (await fs.pathExists(dir)) { await fs.remove(dir); await fs.ensureDir(dir); } } console.log(chalk_1.default.gray(' Runtime data cleared')); } static async restartAgents(fleetConfig) { console.log(chalk_1.default.blue('๐Ÿš€ Restarting agents...')); // Generate restart script const restartScript = `#!/bin/bash # Fleet Restart Script echo "Restarting Agentic QE Fleet..." # Pre-restart coordination npx claude-flow@alpha hooks notify --message "Fleet restart initiated" # Reinitialize agents echo "Reinitializing ${fleetConfig.maxAgents} agents..." # Restore coordination npx claude-flow@alpha hooks session-restore --session-id "fleet-restart" # Post-restart validation echo "Validating agent status..." npx claude-flow@alpha hooks notify --message "Fleet restart completed" echo "Fleet restarted successfully!" `; await fs.ensureDir('.agentic-qe/scripts'); await fs.writeFile('.agentic-qe/scripts/restart-fleet.sh', restartScript); await fs.chmod('.agentic-qe/scripts/restart-fleet.sh', '755'); // Update registry with restarted agents if (await fs.pathExists('.agentic-qe/data/registry.json')) { const registry = await fs.readJson('.agentic-qe/data/registry.json'); if (registry.agents) { registry.agents.forEach((agent) => { agent.status = 'active'; agent.restartedAt = new Date().toISOString(); agent.restartCount = (agent.restartCount || 0) + 1; }); await fs.writeJson('.agentic-qe/data/registry.json', registry, { spaces: 2 }); } } console.log(chalk_1.default.gray(` ${fleetConfig.maxAgents} agents restarted`)); } static async verifyRestart() { console.log(chalk_1.default.blue('โœ… Verifying restart...')); // Check if fleet configuration is intact if (!await fs.pathExists('.agentic-qe/config/fleet.json')) { console.log(chalk_1.default.red(' โŒ Fleet configuration missing')); return false; } // Check if agents are active if (await fs.pathExists('.agentic-qe/data/registry.json')) { const registry = await fs.readJson('.agentic-qe/data/registry.json'); const activeAgents = registry.agents?.filter((a) => a.status === 'active').length || 0; if (activeAgents === 0) { console.log(chalk_1.default.red(' โŒ No active agents after restart')); return false; } console.log(chalk_1.default.green(` โœ… ${activeAgents} agents active`)); } return true; } static async rollbackRestart() { console.log(chalk_1.default.yellow('๐Ÿ”™ Rolling back restart...')); // Find latest backup const backupsDir = '.agentic-qe/backups'; if (await fs.pathExists(backupsDir)) { const backups = await fs.readdir(backupsDir); const restartBackups = backups .filter(b => b.startsWith('restart-')) .sort() .reverse(); if (restartBackups.length > 0) { const latestBackup = `${backupsDir}/${restartBackups[0]}`; // Restore files const files = await fs.readdir(latestBackup); for (const file of files) { const source = `${latestBackup}/${file}`; let dest = ''; if (file === 'fleet.json') { dest = '.agentic-qe/config/fleet.json'; } else if (file === 'agents.json') { dest = '.agentic-qe/config/agents.json'; } else if (file === 'registry.json') { dest = '.agentic-qe/data/registry.json'; } if (dest) { await fs.copy(source, dest, { overwrite: true }); } } console.log(chalk_1.default.green(' โœ… Rollback completed')); } } } static async storeRestartOperation(mode, success) { try { const { execSync } = require('child_process'); const data = JSON.stringify({ mode, success, timestamp: new Date().toISOString() }); const command = `npx claude-flow@alpha memory store --key "aqe/swarm/fleet-cli-commands/restart" --value '${data}'`; execSync(command, { stdio: 'ignore', timeout: 5000 }); } catch (error) { // Silently handle coordination errors } } } exports.FleetRestartCommand = FleetRestartCommand; //# sourceMappingURL=restart.js.map