UNPKG

mirror-magi-meta-agent

Version:

AI-powered development planning and execution system with Supabase integration

417 lines (348 loc) โ€ข 13.5 kB
#!/usr/bin/env node const fs = require('fs').promises; const path = require('path'); const readline = require('readline'); /** * Plan Discussion Mode * Conversational interface for discussing and refining plans with AI assistance */ class PlanDiscussion { constructor() { this.rl = readline.createInterface({ input: process.stdin, output: process.stdout }); this.plan = null; this.originalPlan = null; this.conversationHistory = []; } async start() { console.log('๐Ÿ’ฌ Plan Discussion Mode'); console.log('โ•'.repeat(50)); console.log('Discuss and refine your plan conversationally'); console.log('Maintains proper structure while you talk through ideas\n'); try { await this.loadPlan(); await this.startConversation(); } catch (error) { console.error('โŒ Error:', error.message); } finally { this.rl.close(); } } async loadPlan() { try { const planPath = path.join('state', 'master-plan.json'); const planData = await fs.readFile(planPath, 'utf8'); this.plan = JSON.parse(planData); this.originalPlan = JSON.parse(planData); // Keep backup console.log('๐Ÿ“‹ Plan loaded:', this.plan.goal); console.log('โœ… Ready for discussion\n'); } catch (error) { throw new Error('No plan found. Create a plan first with "npm run plan:interactive"'); } } async startConversation() { this.showConversationHelp(); while (true) { console.log('\n๐Ÿ’ฌ DISCUSSION MODE'); console.log('โ”€'.repeat(30)); const input = await this.askQuestion('\nWhat would you like to discuss about your plan?\n(Type "help" for options, "done" to finish): '); if (input.toLowerCase() === 'done') { await this.finishDiscussion(); break; } if (input.toLowerCase() === 'help') { this.showConversationHelp(); continue; } if (input.toLowerCase() === 'view') { await this.showCurrentPlan(); continue; } if (input.toLowerCase() === 'validate') { await this.validateCurrentPlan(); continue; } if (input.toLowerCase().startsWith('save')) { await this.saveCurrentState(); continue; } // Process the discussion input await this.processDiscussion(input); } } showConversationHelp() { console.log('๐Ÿ”ง DISCUSSION COMMANDS:'); console.log('โ”€'.repeat(25)); console.log('โ€ข Just type your thoughts about the plan naturally'); console.log('โ€ข "view" - Show current plan structure'); console.log('โ€ข "validate" - Check plan structure integrity'); console.log('โ€ข "save" - Save current changes'); console.log('โ€ข "help" - Show this help'); console.log('โ€ข "done" - Finish discussion and save'); console.log('\n๐Ÿ’ก DISCUSSION IDEAS:'); console.log('โ€ข "I think we need a security phase"'); console.log('โ€ข "The API integration seems too complex"'); console.log('โ€ข "Can we split the UI phase into smaller parts?"'); console.log('โ€ข "What about adding error handling tasks?"'); console.log('โ€ข "The order of phases doesn\'t feel right"'); } async processDiscussion(input) { // Add to conversation history this.conversationHistory.push({ timestamp: new Date().toISOString(), user: input, type: 'discussion' }); console.log('\n๐Ÿค– AI ANALYSIS:'); console.log('โ”€'.repeat(20)); // Analyze the input and provide suggestions const analysis = this.analyzeDiscussionInput(input); console.log(analysis.response); // If suggestions were made, ask if user wants to apply them if (analysis.suggestions.length > 0) { console.log('\n๐Ÿ’ก SUGGESTED ACTIONS:'); analysis.suggestions.forEach((suggestion, index) => { console.log(`${index + 1}. ${suggestion.description}`); }); const applyChanges = await this.askQuestion('\nApply any of these suggestions? (y/n or specify numbers like "1,3"): '); if (applyChanges.toLowerCase().startsWith('y')) { // Apply all suggestions for (const suggestion of analysis.suggestions) { await this.applySuggestion(suggestion); } } else if (applyChanges.match(/\d/)) { // Apply specific suggestions const indices = applyChanges.split(',').map(s => parseInt(s.trim()) - 1); for (const index of indices) { if (analysis.suggestions[index]) { await this.applySuggestion(analysis.suggestions[index]); } } } } // Validate plan structure after changes await this.validateCurrentPlan(false); } analyzeDiscussionInput(input) { const inputLower = input.toLowerCase(); const suggestions = []; let response = ''; // Analyze for common discussion topics if (inputLower.includes('security') || inputLower.includes('auth')) { response += '๐Ÿ” Security consideration detected. '; suggestions.push({ type: 'add_phase', description: 'Add security implementation phase', data: { name: 'Security Implementation', description: 'Implement authentication, authorization, and security measures' } }); } if (inputLower.includes('error') || inputLower.includes('handling')) { response += 'โš ๏ธ Error handling consideration noted. '; suggestions.push({ type: 'add_tasks', description: 'Add error handling tasks to existing phases', data: { tasks: [ 'Implement error boundaries', 'Add try-catch blocks', 'Create error logging system' ] } }); } if (inputLower.includes('split') || inputLower.includes('smaller')) { response += 'โœ‚๏ธ Complexity reduction suggestion understood. '; suggestions.push({ type: 'analyze_complexity', description: 'Analyze phases for potential splitting', data: {} }); } if (inputLower.includes('order') || inputLower.includes('sequence')) { response += '๐Ÿ”„ Phase ordering concern noted. '; suggestions.push({ type: 'review_dependencies', description: 'Review phase order and dependencies', data: {} }); } if (inputLower.includes('testing') || inputLower.includes('test')) { response += '๐Ÿงช Testing consideration identified. '; suggestions.push({ type: 'add_testing_tasks', description: 'Add comprehensive testing tasks', data: {} }); } if (inputLower.includes('performance') || inputLower.includes('optimize')) { response += 'โšก Performance optimization noted. '; suggestions.push({ type: 'add_phase', description: 'Add performance optimization phase', data: { name: 'Performance Optimization', description: 'Optimize application performance and user experience' } }); } // Generic response if no specific patterns matched if (!response) { response = '๐Ÿค” I understand your concern about the plan. Let me analyze the current structure...'; } response += '\n\nBased on your input, I\'ve identified some potential improvements to consider.'; return { response, suggestions }; } async applySuggestion(suggestion) { console.log(`\n๐Ÿ”ง Applying: ${suggestion.description}`); switch (suggestion.type) { case 'add_phase': this.plan.phases.push({ id: `phase_${Date.now()}`, name: suggestion.data.name, description: suggestion.data.description, tasks: [] }); console.log(`โœ… Added phase: ${suggestion.data.name}`); break; case 'add_testing_tasks': this.plan.phases.forEach(phase => { if (!phase.tasks) phase.tasks = []; const hasTestingTask = phase.tasks.some(task => task.description.toLowerCase().includes('test') ); if (!hasTestingTask) { phase.tasks.push({ id: `task_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`, description: `Add tests for ${phase.name} functionality`, type: 'testing_implementation', dependencies: [], specifics: {} }); } }); console.log('โœ… Added testing tasks to phases'); break; case 'analyze_complexity': console.log('๐Ÿ“Š Analyzing phase complexity...'); this.plan.phases.forEach((phase, index) => { const taskCount = phase.tasks ? phase.tasks.length : 0; if (taskCount > 5) { console.log(` โš ๏ธ Phase ${index + 1} (${phase.name}) has ${taskCount} tasks - consider splitting`); } }); break; case 'review_dependencies': console.log('๐Ÿ”— Reviewing phase dependencies...'); this.plan.phases.forEach((phase, index) => { console.log(` ${index + 1}. ${phase.name}`); }); console.log(' ๐Ÿ’ก Consider if this order makes logical sense for your project'); break; } // Update modification timestamp this.plan.lastModified = new Date().toISOString(); this.plan.status = 'discussed'; } async showCurrentPlan() { console.log('\n๐Ÿ“‹ CURRENT PLAN STRUCTURE'); console.log('โ•'.repeat(40)); console.log(`๐ŸŽฏ Goal: ${this.plan.goal}`); console.log(`๐Ÿ“Š Phases: ${this.plan.phases.length}`); this.plan.phases.forEach((phase, index) => { const taskCount = phase.tasks ? phase.tasks.length : 0; console.log(`${index + 1}. ${phase.name} (${taskCount} tasks)`); console.log(` ${phase.description}`); }); const totalTasks = this.plan.phases.reduce((sum, phase) => sum + (phase.tasks ? phase.tasks.length : 0), 0 ); console.log(`\n๐Ÿ“ Total Tasks: ${totalTasks}`); } async validateCurrentPlan(showDetails = true) { const CompletePlanViewer = require('./view-complete-plan'); const viewer = new CompletePlanViewer(); viewer.plan = this.plan; const checks = viewer.validatePlanStructure(); const allPassed = checks.every(check => check.passed); if (showDetails) { console.log('\nโœ… PLAN STRUCTURE VALIDATION'); console.log('โ”€'.repeat(40)); checks.forEach(check => { const icon = check.passed ? 'โœ…' : 'โŒ'; console.log(`${icon} ${check.description}`); }); } console.log(`\n${allPassed ? '๐ŸŽ‰' : 'โš ๏ธ'} Plan Structure: ${allPassed ? 'VALID' : 'NEEDS ATTENTION'}`); return allPassed; } async saveCurrentState() { console.log('\n๐Ÿ’พ Saving current plan state...'); // Validate before saving const isValid = await this.validateCurrentPlan(false); if (isValid) { const planPath = path.join('state', 'master-plan.json'); await fs.writeFile(planPath, JSON.stringify(this.plan, null, 2)); console.log('โœ… Plan saved successfully!'); } else { console.log('โš ๏ธ Plan has structure issues. Fix them before saving.'); } } async finishDiscussion() { console.log('\n๐ŸŽฏ FINISHING DISCUSSION'); console.log('โ”€'.repeat(30)); // Show changes summary this.showChangesSummary(); const saveChanges = await this.askQuestion('\nSave your refined plan? (y/n): '); if (saveChanges.toLowerCase().startsWith('y')) { await this.saveCurrentState(); console.log('\n๐Ÿ’ก Next steps:'); console.log('โ€ข View complete plan: node view-complete-plan.js'); console.log('โ€ข Continue editing: npm run plan:edit'); console.log('โ€ข Start execution: npm run plan:continue'); } else { console.log('โœ… Changes discarded'); } } showChangesSummary() { console.log('\n๐Ÿ“‹ DISCUSSION SUMMARY:'); const phaseDiff = this.plan.phases.length - this.originalPlan.phases.length; if (phaseDiff > 0) { console.log(`โž• Added ${phaseDiff} phase(s)`); } else if (phaseDiff < 0) { console.log(`โž– Removed ${Math.abs(phaseDiff)} phase(s)`); } const originalTasks = this.originalPlan.phases.reduce((sum, p) => sum + (p.tasks?.length || 0), 0); const currentTasks = this.plan.phases.reduce((sum, p) => sum + (p.tasks?.length || 0), 0); const taskDiff = currentTasks - originalTasks; if (taskDiff > 0) { console.log(`โž• Added ${taskDiff} task(s)`); } else if (taskDiff < 0) { console.log(`โž– Removed ${Math.abs(taskDiff)} task(s)`); } if (this.conversationHistory.length > 0) { console.log(`๐Ÿ’ฌ Had ${this.conversationHistory.length} discussion point(s)`); } if (this.plan.goal !== this.originalPlan.goal) { console.log('๐ŸŽฏ Goal was modified'); } } askQuestion(question) { return new Promise((resolve) => { this.rl.question(question, resolve); }); } } // Run the plan discussion mode if (require.main === module) { const discussion = new PlanDiscussion(); discussion.start().catch(console.error); } module.exports = PlanDiscussion;