mirror-magi-meta-agent
Version:
AI-powered development planning and execution system with Supabase integration
417 lines (348 loc) โข 13.5 kB
JavaScript
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;