UNPKG

@versatil/claude-opera

Version:

šŸŽ­ Claude Opera by VERSATIL v6.4.0 - Production-ready OPERA orchestration with 17 agents (7 core + 10 language-specific sub-agents), automatic roadmap generation, 11-MCP ecosystem, RAG memory achieving 98%+ context retention, proactive daemon with file-ba

294 lines (242 loc) • 10.2 kB
#!/usr/bin/env node /** * VERSATIL SDLC Framework - Vector Store Migration CLI * * Command-line interface for migrating from Enhanced Vector Memory Store * to Supabase Vector Store with progress tracking and validation. */ const { Command } = require('commander'); const chalk = require('chalk'); const { VectorStoreMigration } = require('../dist/migration/vector-store-migration.js'); class MigrationCLI { constructor() { this.program = new Command(); this.setupCommands(); } setupCommands() { this.program .name('migrate-vector-store') .description('Migrate VERSATIL vector store from local to Supabase') .version('1.2.1'); // Main migration command this.program .command('migrate') .description('Execute vector store migration') .option('--dry-run', 'Show what would be migrated without making changes') .option('--no-backup', 'Skip creating backup (not recommended)') .option('--no-preserve-local', 'Remove local data after migration') .option('--batch-size <number>', 'Number of items to process in each batch', '50') .option('--no-skip-duplicates', 'Migrate duplicate patterns') .option('--no-preserve-embeddings', 'Regenerate all embeddings') .option('--agent-filter <agents...>', 'Only migrate specified agents') .option('--time-range <start,end>', 'Migrate only items in time range (timestamps)') .option('--no-validate-integrity', 'Skip post-migration validation') .option('--progress-interval <ms>', 'Progress update interval in milliseconds', '5000') .action(this.handleMigrate.bind(this)); // Status command this.program .command('status') .description('Check migration prerequisites and current state') .action(this.handleStatus.bind(this)); // Validate command this.program .command('validate') .description('Validate migration results') .action(this.handleValidate.bind(this)); // Rollback command (future) this.program .command('rollback') .description('Rollback migration (if supported)') .action(this.handleRollback.bind(this)); } async handleMigrate(options) { console.log(chalk.blue.bold('\nšŸš€ VERSATIL Vector Store Migration\n')); try { // Parse options const migrationOptions = { dryRun: options.dryRun || false, preserveLocal: options.preserveLocal !== false, batchSize: parseInt(options.batchSize) || 50, skipDuplicates: options.skipDuplicates !== false, preserveEmbeddings: options.preserveEmbeddings !== false, agentFilter: options.agentFilter || undefined, timeRange: this.parseTimeRange(options.timeRange), validateIntegrity: options.validateIntegrity !== false, createBackup: options.backup !== false }; if (migrationOptions.dryRun) { console.log(chalk.yellow('šŸ” Running in DRY RUN mode - no changes will be made\n')); } // Initialize migration const migration = new VectorStoreMigration(); // Setup progress tracking let lastUpdate = 0; const progressInterval = parseInt(options.progressInterval) || 5000; const unsubscribe = migration.onProgress((progress) => { const now = Date.now(); if (now - lastUpdate >= progressInterval) { this.displayProgress(progress); lastUpdate = now; } }); // Execute migration console.log(chalk.green('Starting migration...\n')); const report = await migration.migrate(migrationOptions); // Cleanup unsubscribe(); // Display results this.displayReport(report); } catch (error) { console.error(chalk.red.bold('\nāŒ Migration failed:')); console.error(chalk.red(error.message)); if (error.stack) { console.error(chalk.gray('\nStack trace:')); console.error(chalk.gray(error.stack)); } process.exit(1); } } async handleStatus() { console.log(chalk.blue.bold('\nšŸ“Š Migration Status Check\n')); try { // Check Supabase configuration const { supabaseConfig } = require('../dist/config/supabase-config.js'); const status = supabaseConfig.getConfigStatus(); console.log(chalk.blue('šŸ”§ Configuration Status:')); console.log(` Supabase Configured: ${status.isConfigured ? chalk.green('āœ“') : chalk.red('āœ—')}`); console.log(` Embedding Provider: ${chalk.cyan(status.embeddingProvider)}`); console.log(` Environment: ${chalk.cyan(status.environment)}`); console.log(` Features Enabled: ${status.featuresEnabled.join(', ') || 'none'}`); if (status.missingRequirements.length > 0) { console.log(chalk.red('\nāš ļø Missing Requirements:')); status.missingRequirements.forEach(req => { console.log(` - ${req}`); }); } // Check source data const { EnhancedVectorMemoryStore } = require('../dist/rag/enhanced-vector-memory-store.js'); const sourceStore = new EnhancedVectorMemoryStore(); await sourceStore.initialize(); const memories = await sourceStore.getAllMemories(); console.log(chalk.blue('\nšŸ“ Source Data:')); console.log(` Total Memories: ${chalk.cyan(memories.length)}`); const agentBreakdown = {}; memories.forEach(m => { const agent = m.metadata.agentId; agentBreakdown[agent] = (agentBreakdown[agent] || 0) + 1; }); console.log(` Agent Breakdown:`); Object.entries(agentBreakdown).forEach(([agent, count]) => { console.log(` ${agent}: ${chalk.cyan(count)}`); }); // Check target availability console.log(chalk.blue('\nšŸŽÆ Target Store:')); if (status.isConfigured) { console.log(chalk.green(' āœ“ Supabase Vector Store available')); } else { console.log(chalk.red(' āœ— Supabase Vector Store not configured')); } } catch (error) { console.error(chalk.red('Error checking status:'), error.message); process.exit(1); } } async handleValidate() { console.log(chalk.blue.bold('\nšŸ” Validating Migration Results\n')); try { // Implementation would check migration integrity console.log(chalk.yellow('Validation functionality coming soon...')); } catch (error) { console.error(chalk.red('Validation failed:'), error.message); process.exit(1); } } async handleRollback() { console.log(chalk.yellow.bold('\nāŖ Migration Rollback\n')); console.log(chalk.yellow('Rollback functionality is not yet implemented.')); console.log(chalk.gray('If you need to rollback, restore from backup manually.')); } displayProgress(progress) { const percent = progress.totalItems > 0 ? Math.round((progress.processed / progress.totalItems) * 100) : 0; const bar = this.createProgressBar(percent); const estimated = progress.estimated > 0 ? ` (${Math.round(progress.estimated / 1000)}s remaining)` : ''; console.log( `${chalk.blue(progress.phase)} ${bar} ${percent}% ` + `(${progress.processed}/${progress.totalItems})` + `${estimated}` ); if (progress.errors > 0) { console.log(chalk.red(` Errors: ${progress.errors}`)); } if (progress.warnings > 0) { console.log(chalk.yellow(` Warnings: ${progress.warnings}`)); } } displayReport(report) { console.log(chalk.green.bold('\nāœ… Migration Completed\n')); // Summary console.log(chalk.blue('šŸ“ˆ Summary:')); console.log(` Status: ${report.success ? chalk.green('Success') : chalk.red('Failed')}`); console.log(` Duration: ${chalk.cyan(Math.round(report.duration / 1000))}s`); // Statistics console.log(chalk.blue('\nšŸ“Š Statistics:')); const stats = report.finalStats; console.log(` Total Memories: ${chalk.cyan(stats.totalMemories)}`); console.log(` Migrated Patterns: ${chalk.cyan(stats.migratedPatterns)}`); console.log(` Migrated Solutions: ${chalk.cyan(stats.migratedSolutions)}`); console.log(` Migrated Interactions: ${chalk.cyan(stats.migratedInteractions)}`); console.log(` Preserved Embeddings: ${chalk.cyan(stats.preservedEmbeddings)}`); console.log(` Duplicates Skipped: ${chalk.cyan(stats.duplicatesSkipped)}`); // Phase breakdown console.log(chalk.blue('\nšŸ”„ Phase Results:')); Object.entries(report.phases).forEach(([phase, data]) => { const status = data.completed ? chalk.green('āœ“') : chalk.red('āœ—'); console.log(` ${status} ${phase}: ${data.success}/${data.items} (${data.errors} errors)`); if (data.warnings.length > 0) { data.warnings.forEach(warning => { console.log(` ${chalk.yellow('āš ļø')} ${warning}`); }); } }); // Recommendations if (report.recommendations.length > 0) { console.log(chalk.blue('\nšŸ’” Recommendations:')); report.recommendations.forEach(rec => { console.log(` • ${rec}`); }); } console.log(chalk.green('\nšŸŽ‰ Migration process completed successfully!')); console.log(chalk.gray('\nNext steps:')); console.log(chalk.gray(' 1. Test agent RAG functionality')); console.log(chalk.gray(' 2. Update agent configurations')); console.log(chalk.gray(' 3. Monitor Supabase performance')); } createProgressBar(percent, width = 30) { const filled = Math.round((percent / 100) * width); const empty = width - filled; return chalk.green('ā–ˆ'.repeat(filled)) + chalk.gray('ā–‘'.repeat(empty)); } parseTimeRange(timeRange) { if (!timeRange) return undefined; try { const [start, end] = timeRange.split(',').map(t => parseInt(t.trim())); return { start, end }; } catch { console.warn(chalk.yellow('Invalid time range format. Use: start,end')); return undefined; } } run() { this.program.parse(); } } // Run CLI if called directly if (require.main === module) { const cli = new MigrationCLI(); cli.run(); } module.exports = { MigrationCLI };