UNPKG

jay-code

Version:

Streamlined AI CLI orchestration engine with mathematical rigor and enterprise-grade reliability

463 lines (407 loc) 12.4 kB
/** * Memory Migration Utility * * Helps migrate from old CollectiveMemory to new SharedMemory/SwarmMemory * * @module memory/migration */ import Database from 'better-sqlite3'; import path from 'path'; import fs from 'fs/promises'; import { SharedMemory } from './shared-memory.js'; import { SwarmMemory } from './swarm-memory.js'; export class MemoryMigration { constructor(options = {}) { this.options = { oldDbPath: path.join(process.cwd(), '.hive-mind', 'hive.db'), newDbPath: path.join(process.cwd(), '.hive-mind', 'memory.db'), swarmDbPath: path.join(process.cwd(), '.swarm', 'swarm-memory.db'), dryRun: options.dryRun || false, verbose: options.verbose || false, ...options, }; this.stats = { total: 0, migrated: 0, skipped: 0, errors: 0, }; } /** * Run the migration */ async migrate() { console.log('Starting memory migration...'); try { // Check if old database exists const oldDbExists = await this._fileExists(this.options.oldDbPath); if (!oldDbExists) { console.log('No old database found. Nothing to migrate.'); return { success: true, stats: this.stats }; } // Initialize new memory systems const sharedMemory = new SharedMemory({ directory: path.dirname(this.options.newDbPath), filename: path.basename(this.options.newDbPath), }); const swarmMemory = new SwarmMemory({ directory: path.dirname(this.options.swarmDbPath), filename: path.basename(this.options.swarmDbPath), }); if (!this.options.dryRun) { await sharedMemory.initialize(); await swarmMemory.initialize(); } // Open old database const oldDb = new Database(this.options.oldDbPath, { readonly: true }); // Migrate collective_memory table await this._migrateCollectiveMemory(oldDb, sharedMemory); // Migrate memory table await this._migrateMemoryTable(oldDb, sharedMemory); // Migrate swarm-specific data await this._migrateSwarmData(oldDb, swarmMemory); // Close connections oldDb.close(); if (!this.options.dryRun) { await sharedMemory.close(); await swarmMemory.close(); } console.log('\nMigration completed!'); console.log(`Total entries: ${this.stats.total}`); console.log(`Migrated: ${this.stats.migrated}`); console.log(`Skipped: ${this.stats.skipped}`); console.log(`Errors: ${this.stats.errors}`); return { success: true, stats: this.stats, }; } catch (error) { console.error('Migration failed:', error); return { success: false, error: error.message, stats: this.stats, }; } } /** * Migrate collective_memory table */ async _migrateCollectiveMemory(oldDb, sharedMemory) { console.log('\nMigrating collective_memory entries...'); try { const rows = oldDb .prepare( ` SELECT * FROM collective_memory ORDER BY created_at ASC `, ) .all(); for (const row of rows) { this.stats.total++; try { // Parse the swarm_id from the key if needed const keyParts = row.key.split(':'); const namespace = this._determineNamespace(row.type); // Prepare value let value = row.value; if (row.compressed) { // Handle compressed data if needed value = JSON.parse(value); } if (this.options.dryRun) { if (this.options.verbose) { console.log(`Would migrate: ${row.key} -> ${namespace}`); } } else { await sharedMemory.store(row.key, value, { namespace, ttl: this._calculateTTL(row.type), metadata: { originalId: row.id, swarmId: row.swarm_id, createdBy: row.created_by, confidence: row.confidence, migratedAt: new Date().toISOString(), }, }); } this.stats.migrated++; } catch (error) { console.error(`Error migrating ${row.key}:`, error.message); this.stats.errors++; } // Progress indicator if (this.stats.total % 100 === 0) { process.stdout.write('.'); } } } catch (error) { if (error.message.includes('no such table')) { console.log('collective_memory table not found, skipping...'); } else { throw error; } } } /** * Migrate memory table (from hive-mind schema) */ async _migrateMemoryTable(oldDb, sharedMemory) { console.log('\n\nMigrating memory table entries...'); try { const rows = oldDb .prepare( ` SELECT * FROM memory ORDER BY created_at ASC `, ) .all(); for (const row of rows) { this.stats.total++; try { if (this.options.dryRun) { if (this.options.verbose) { console.log(`Would migrate: ${row.key} (${row.namespace})`); } } else { await sharedMemory.store(row.key, row.value, { namespace: row.namespace, ttl: row.ttl, metadata: row.metadata ? JSON.parse(row.metadata) : null, }); } this.stats.migrated++; } catch (error) { console.error(`Error migrating ${row.key}:`, error.message); this.stats.errors++; } // Progress indicator if (this.stats.total % 100 === 0) { process.stdout.write('.'); } } } catch (error) { if (error.message.includes('no such table')) { console.log('memory table not found, skipping...'); } else { throw error; } } } /** * Migrate swarm-specific data */ async _migrateSwarmData(oldDb, swarmMemory) { console.log('\n\nMigrating swarm-specific data...'); // Migrate agents await this._migrateAgents(oldDb, swarmMemory); // Migrate tasks await this._migrateTasks(oldDb, swarmMemory); // Migrate neural patterns await this._migratePatterns(oldDb, swarmMemory); // Migrate consensus data await this._migrateConsensus(oldDb, swarmMemory); } /** * Migrate agents table */ async _migrateAgents(oldDb, swarmMemory) { try { const agents = oldDb .prepare( ` SELECT * FROM agents `, ) .all(); console.log(`\nMigrating ${agents.length} agents...`); for (const agent of agents) { if (!this.options.dryRun) { await swarmMemory.storeAgent(agent.id, { id: agent.id, name: agent.name, type: agent.type, status: agent.status, capabilities: JSON.parse(agent.capabilities), currentTaskId: agent.current_task_id, messageCount: agent.message_count, errorCount: agent.error_count, successCount: agent.success_count, createdAt: agent.created_at, lastActiveAt: agent.last_active_at, metadata: agent.metadata ? JSON.parse(agent.metadata) : {}, }); } this.stats.migrated++; } } catch (error) { if (!error.message.includes('no such table')) { console.error('Error migrating agents:', error.message); } } } /** * Migrate tasks table */ async _migrateTasks(oldDb, swarmMemory) { try { const tasks = oldDb .prepare( ` SELECT * FROM tasks `, ) .all(); console.log(`\nMigrating ${tasks.length} tasks...`); for (const task of tasks) { if (!this.options.dryRun) { await swarmMemory.storeTask(task.id, { id: task.id, description: task.description, priority: task.priority, strategy: task.strategy, status: task.status, progress: task.progress, result: task.result ? JSON.parse(task.result) : null, error: task.error, dependencies: task.dependencies ? JSON.parse(task.dependencies) : [], assignedAgents: task.assigned_agents ? JSON.parse(task.assigned_agents) : [], requireConsensus: !!task.require_consensus, consensusAchieved: !!task.consensus_achieved, maxAgents: task.max_agents, requiredCapabilities: task.required_capabilities ? JSON.parse(task.required_capabilities) : [], createdAt: task.created_at, assignedAt: task.assigned_at, startedAt: task.started_at, completedAt: task.completed_at, metadata: task.metadata ? JSON.parse(task.metadata) : {}, }); } this.stats.migrated++; } } catch (error) { if (!error.message.includes('no such table')) { console.error('Error migrating tasks:', error.message); } } } /** * Migrate neural patterns */ async _migratePatterns(oldDb, swarmMemory) { try { const patterns = oldDb .prepare( ` SELECT * FROM neural_patterns `, ) .all(); console.log(`\nMigrating ${patterns.length} neural patterns...`); for (const pattern of patterns) { if (!this.options.dryRun) { await swarmMemory.storePattern(pattern.id, { id: pattern.id, type: pattern.pattern_type, data: JSON.parse(pattern.pattern_data), confidence: pattern.confidence, usageCount: pattern.usage_count, successRate: pattern.success_rate, createdAt: pattern.created_at, lastUsedAt: pattern.last_used_at, metadata: pattern.metadata ? JSON.parse(pattern.metadata) : {}, }); } this.stats.migrated++; } } catch (error) { if (!error.message.includes('no such table')) { console.error('Error migrating patterns:', error.message); } } } /** * Migrate consensus data */ async _migrateConsensus(oldDb, swarmMemory) { try { const consensus = oldDb .prepare( ` SELECT * FROM consensus `, ) .all(); console.log(`\nMigrating ${consensus.length} consensus records...`); for (const record of consensus) { if (!this.options.dryRun) { await swarmMemory.storeConsensus(record.id, { id: record.id, taskId: record.task_id, proposal: JSON.parse(record.proposal), threshold: record.required_threshold, currentVotes: record.current_votes, totalVoters: record.total_voters, votes: JSON.parse(record.votes), status: record.status, createdAt: record.created_at, deadlineAt: record.deadline_at, completedAt: record.completed_at, }); } this.stats.migrated++; } } catch (error) { if (!error.message.includes('no such table')) { console.error('Error migrating consensus:', error.message); } } } /** * Helper methods */ _determineNamespace(type) { const typeMap = { knowledge: 'hive:knowledge', context: 'hive:context', task: 'hive:task', result: 'hive:result', error: 'hive:error', metric: 'hive:metric', consensus: 'hive:consensus', system: 'hive:system', }; return typeMap[type] || 'default'; } _calculateTTL(type) { const ttlMap = { context: 3600, // 1 hour task: 1800, // 30 minutes error: 86400, // 24 hours metric: 3600, // 1 hour }; return ttlMap[type] || null; } async _fileExists(filepath) { try { await fs.access(filepath); return true; } catch { return false; } } } /** * CLI interface for migration */ export async function runMigration(options = {}) { const migration = new MemoryMigration(options); return await migration.migrate(); } // Export default export default MemoryMigration;