UNPKG

@codemafia0000/d0

Version:

Claude Multi-Agent Automated Development AI - Revolutionary development environment where multiple AI agents collaborate to automate software development

574 lines (489 loc) β€’ 20.5 kB
const fs = require('fs'); const path = require('path'); const { execSync } = require('child_process'); const chalk = require('chalk'); const CONSTANTS = require('../constants'); const { isProjectSetup, getProjectConfig } = require('../setup/project-setup'); // Generate instruction template function generateInstructionTemplate(role, roleName, emoji, description) { const currentYear = new Date().getFullYear(); return `# ${emoji} ${roleName} Instructions ## Your Role As ${description}, develop high-quality deliverables quickly and contribute to team success. ## Immediate Actions 1. **Task Understanding (within 5 minutes)** - Confirm requirements, ask questions immediately for unclear points - Understand success criteria numerically - Confirm dependencies 2. **Implementation Plan Creation (within 10 minutes)** - Break down task into subtasks - Estimate effort for each subtask - Include test plan 3. **Start Implementation** - Follow coding conventions - Record progress every 30 minutes - Report blockers immediately ## Practical Task Management ### Task Breakdown Template \`\`\`markdown ## Task: [${role} Implementation] ### Subtasks and Effort - [ ] Requirements analysis and design (0.5h) - [ ] Basic implementation (2h) - [ ] Test creation (1h) - [ ] Quality check (0.5h) - [ ] Documentation creation (0.5h) - [ ] Code review response (0.5h) ### Total: 5h ### With buffer: 6h \`\`\` ### Progress Report Format \`\`\`bash # 30-minute progress recording echo "[\$(date +%H:%M)] Task: [task name] - Progress: [X]% - Status: [smooth/problematic]" >> progress.log # Standard progress report d0 tell boss "【Progress Report】${roleName} \$(date +%H:%M) Task: [task name] Progress: [X]% completed Completed items: βœ… [completed subtask] Working on: πŸ”„ [currently working subtask] Next action: β†’ [next subtask to work on] Scheduled completion time: [HH:MM] Issues: [none/present (details)]" \`\`\` ## Completion Report Template ### Task Completion Report \`\`\`bash d0 tell boss "【Task Completed】${roleName} \$(date +%H:%M) ## Task: [task name] βœ… Completed successfully ## Deliverables - [specific file/feature 1] - [specific file/feature 2] ## Quality Metrics - Test coverage: [X]% - Performance: [metric] - Standards compliance: βœ… ## Next Steps - [suggested next task] - [dependencies for other team members]" \`\`\` --- *Generated by d0 CLI v${CONSTANTS.VERSION} - ${new Date().getFullYear()}*`; } // Generate instruction command handler function handleGenerateInstruction(role) { if (!isProjectSetup()) { console.log(chalk.red('❌ Claude agents environment not found.')); console.log(chalk.yellow('Run "d0 init" first.')); return; } // Get role configuration const roleConfig = CONSTANTS.WORKER_SPECIALIZATIONS.find(spec => spec.title.toLowerCase().includes(role.toLowerCase()) || role.toLowerCase().includes(spec.title.toLowerCase().split(' ')[0]) ); if (!roleConfig) { console.log(chalk.red(`❌ Unknown role: ${role}`)); console.log(chalk.yellow('Available roles:')); CONSTANTS.WORKER_SPECIALIZATIONS.forEach(spec => { console.log(` β€’ ${spec.title}`); }); return; } const template = generateInstructionTemplate( role, roleConfig.title, roleConfig.emoji, roleConfig.description ); const filename = `${role.toLowerCase().replace(/\s+/g, '_')}_instructions.md`; const filepath = path.join(CONSTANTS.INSTRUCTIONS_DIR, filename); try { fs.writeFileSync(filepath, template); console.log(chalk.green(`βœ… Instruction template generated: ${filename}`)); console.log(chalk.blue(`πŸ“ Location: ${filepath}`)); console.log(chalk.gray('\nπŸ’‘ You can customize this template for your specific needs.')); } catch (error) { console.error(chalk.red('❌ Error generating template:'), error.message); process.exit(1); } } // List agents command handler function handleAgents() { if (!isProjectSetup()) { console.log(chalk.red('❌ Claude agents environment not found.')); console.log(chalk.yellow('Run "d0 init" first.')); return; } try { const config = getProjectConfig(); const numWorkers = config.workers || CONSTANTS.DEFAULT_WORKERS; console.log(chalk.blue('πŸ‘₯ Agent Configuration')); console.log('─'.repeat(40)); // Core agents console.log(chalk.green('πŸ“Š Management Agents:')); console.log(' πŸ›οΈ PRESIDENT - Project oversight and client relations'); console.log(' 🎯 BOSS - Technical leadership and coordination'); // Worker agents console.log(chalk.blue(`\nβš™οΈ Worker Agents (${numWorkers}):`)); for (let i = 1; i <= numWorkers; i++) { const specialization = CONSTANTS.WORKER_SPECIALIZATIONS[(i - 1) % CONSTANTS.WORKER_SPECIALIZATIONS.length]; console.log(` ${specialization.emoji} WORKER${i} - ${specialization.title}`); console.log(chalk.gray(` ${specialization.description}`)); } // Session status console.log(chalk.yellow('\nπŸ“‘ Session Status:')); if (fs.existsSync(CONSTANTS.SESSIONS_FILE)) { console.log(chalk.green(' βœ… Active - agents are running')); } else { console.log(chalk.red(' ❌ Inactive - run "d0 start" to begin')); } // Communication info console.log(chalk.blue('\nπŸ’¬ Communication:')); console.log(chalk.gray(' d0 tell president "message" - Communicate with management')); console.log(chalk.gray(' d0 tell worker1 "message" - Direct worker communication')); console.log(chalk.gray(' d0 tell everyone "message" - Broadcast to all agents')); } catch (error) { console.error(chalk.red('❌ Error reading configuration:'), error.message); process.exit(1); } } // List sessions command handler function handleList() { if (!isProjectSetup()) { console.log(chalk.red('❌ Claude agents environment not found.')); console.log(chalk.yellow('Run "d0 init" first.')); return; } console.log(chalk.blue('πŸ“‹ Available Sessions')); console.log('─'.repeat(40)); try { const config = getProjectConfig(); const numWorkers = config.workers || CONSTANTS.DEFAULT_WORKERS; const roles = CONSTANTS.getWorkerRoles(numWorkers); // Check if sessions are active let activeSessions = []; if (fs.existsSync(CONSTANTS.SESSIONS_FILE)) { const sessionData = JSON.parse(fs.readFileSync(CONSTANTS.SESSIONS_FILE, 'utf8')); activeSessions = sessionData.sessions || []; } roles.forEach(role => { const status = activeSessions.includes(role) ? chalk.green('🟒 ACTIVE') : chalk.red('πŸ”΄ INACTIVE'); console.log(`${role.padEnd(12)} ${status}`); }); if (activeSessions.length > 0) { console.log(chalk.blue('\nπŸ”Œ Connect to a session:')); console.log(chalk.gray(' d0 hi <session> - Quick connect')); console.log(chalk.gray(' d0 connect <session> - Connect with status')); } else { console.log(chalk.yellow('\n⚠️ No active sessions found.')); console.log(chalk.gray(' d0 start - Start all sessions')); } } catch (error) { console.error(chalk.red('❌ Error reading sessions:'), error.message); process.exit(1); } } // Shell completion command handler function handleCompletion(shell) { const validShells = ['bash', 'zsh', 'powershell', 'pwsh']; if (!validShells.includes(shell)) { console.log(chalk.red(`❌ Unsupported shell: ${shell}`)); console.log(chalk.yellow('Supported shells: bash, zsh, powershell, pwsh')); return; } console.log(chalk.blue(`🐚 Setting up ${shell} completion for d0...`)); // Generate completion script based on shell let completionScript = ''; let installPath = ''; let fileExtension = '.sh'; if (shell === 'bash') { completionScript = generateBashCompletion(); installPath = path.join(process.env.HOME || '', '.bash_completion'); } else if (shell === 'zsh') { completionScript = generateZshCompletion(); installPath = path.join(process.env.HOME || '', '.zshrc'); } else if (shell === 'powershell' || shell === 'pwsh') { completionScript = generatePowerShellCompletion(); installPath = path.join(process.env.HOME || process.env.USERPROFILE || '', 'Documents', 'PowerShell', 'Microsoft.PowerShell_profile.ps1'); fileExtension = '.ps1'; } try { // Create completion directory in user's home const homeDir = process.env.HOME || process.env.USERPROFILE || ''; const completionDir = path.join(homeDir, '.d0', 'completion'); if (!fs.existsSync(completionDir)) { fs.mkdirSync(completionDir, { recursive: true }); } // Write completion script to permanent location const completionFile = path.join(completionDir, `d0_completion_${shell}${fileExtension}`); fs.writeFileSync(completionFile, completionScript); console.log(chalk.green('βœ… Completion script generated')); console.log(chalk.blue(`πŸ“ Location: ${completionFile}`)); console.log(chalk.yellow('\nπŸ“‹ Installation Instructions:')); console.log(chalk.gray(`1. Add to your ${shell} configuration:`)); if (shell === 'bash') { console.log(chalk.cyan(` echo 'source ${completionFile}' >> ~/.bashrc`)); console.log(chalk.gray('2. Reload your shell:')); console.log(chalk.cyan(' source ~/.bashrc')); } else if (shell === 'zsh') { console.log(chalk.cyan(` echo 'source ${completionFile}' >> ~/.zshrc`)); console.log(chalk.gray('2. Reload your shell:')); console.log(chalk.cyan(' source ~/.zshrc')); } else if (shell === 'powershell' || shell === 'pwsh') { console.log(chalk.cyan(` Add-Content $PROFILE '. ${completionFile}'`)); console.log(chalk.gray('2. Reload PowerShell:')); console.log(chalk.cyan(' . $PROFILE')); console.log(chalk.gray('\nNote: If $PROFILE doesn\'t exist, create it first:')); console.log(chalk.cyan(' New-Item -ItemType File -Path $PROFILE -Force')); } console.log(chalk.blue('\nπŸ”§ Or install automatically:')); if (shell === 'bash') { console.log(chalk.cyan(` d0 completion bash && echo 'source ${completionFile}' >> ~/.bashrc && source ~/.bashrc`)); } else if (shell === 'zsh') { console.log(chalk.cyan(` d0 completion zsh && echo 'source ${completionFile}' >> ~/.zshrc && source ~/.zshrc`)); } else if (shell === 'powershell' || shell === 'pwsh') { console.log(chalk.cyan(` d0 completion ${shell} && Add-Content $PROFILE '. ${completionFile}' && . $PROFILE`)); } console.log(chalk.green('\nπŸŽ‰ After installation, you can use Tab completion with d0 commands!')); console.log(chalk.gray('\nπŸ’‘ Test completion by typing: d0 <TAB> or d0 tell <TAB>')); } catch (error) { console.error(chalk.red('❌ Failed to install completion:'), error.message); process.exit(1); } } function generateBashCompletion() { return `# d0 CLI bash completion _d0_completion() { local cur prev opts COMPREPLY=() cur="\${COMP_WORDS[COMP_CWORD]}" prev="\${COMP_WORDS[COMP_CWORD-1]}" # Updated command list (removed setup and connect) opts="init start stop status tell comm team hi list agents history analytics analyze-project auto-setup generate-instruction completion monitor" case \${prev} in tell) COMPREPLY=( \$(compgen -W "president boss worker1 worker2 worker3 everyone" -- \${cur}) ) return 0 ;; hi) COMPREPLY=( \$(compgen -W "president boss worker1 worker2 worker3" -- \${cur}) ) return 0 ;; completion) COMPREPLY=( \$(compgen -W "bash zsh powershell pwsh" -- \${cur}) ) return 0 ;; comm) COMPREPLY=( \$(compgen -W "--clear" -- \${cur}) ) return 0 ;; team) COMPREPLY=( \$(compgen -W "--status-only --reset --workers" -- \${cur}) ) return 0 ;; init) COMPREPLY=( \$(compgen -W "--force --workers" -- \${cur}) ) return 0 ;; *) ;; esac COMPREPLY=( \$(compgen -W "\${opts}" -- \${cur}) ) } complete -F _d0_completion d0`; } function generateZshCompletion() { return `# d0 CLI zsh completion #compdef d0 _d0() { local context curcontext="\$curcontext" state line _arguments -C \\ '1: :->commands' \\ '*: :->args' \\ case \$state in commands) _arguments '1:Commands:(init start stop status tell comm team hi list agents history analytics analyze-project auto-setup generate-instruction completion monitor)' ;; args) case \$line[1] in tell) _arguments '2:Recipients:(president boss worker1 worker2 worker3 everyone)' ;; hi) _arguments '2:Sessions:(president boss worker1 worker2 worker3)' ;; completion) _arguments '2:Shells:(bash zsh powershell pwsh)' ;; comm) _arguments '--clear[Clear message notifications]' ;; team) _arguments \\ '--status-only[Only show status, do not send notifications]' \\ '--reset[Reset all completion markers]' \\ '--workers[Number of workers to check]:workers:' ;; init) _arguments \\ '--force[Force initialization even if already exists]' \\ '--workers[Number of worker agents]:workers:(1 2 3 4 5 6 7 8 9 10)' ;; esac ;; esac } _d0 "\$@"`; } function generatePowerShellCompletion() { return `# d0 CLI PowerShell completion Register-ArgumentCompleter -Native -CommandName d0 -ScriptBlock { param($commandName, $wordToComplete, $cursorPosition) $command = $wordToComplete $words = $command.Split(' ', [StringSplitOptions]::RemoveEmptyEntries) # Main commands $commands = @('init', 'start', 'stop', 'status', 'tell', 'comm', 'team', 'hi', 'list', 'agents', 'history', 'analytics', 'analyze-project', 'auto-setup', 'generate-instruction', 'completion', 'monitor') if ($words.Count -eq 1) { # Complete main commands $commands | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'Command', $_) } } elseif ($words.Count -ge 2) { $subCommand = $words[1] switch ($subCommand) { 'tell' { $recipients = @('president', 'boss', 'worker1', 'worker2', 'worker3', 'everyone') if ($words.Count -eq 2) { $recipients | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', "Send message to $_") } } } 'hi' { $sessions = @('president', 'boss', 'worker1', 'worker2', 'worker3') if ($words.Count -eq 2) { $sessions | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', "Connect to $_ session") } } } 'completion' { $shells = @('bash', 'zsh', 'powershell', 'pwsh') if ($words.Count -eq 2) { $shells | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', "Generate completion for $_") } } } 'comm' { if ($wordToComplete -like '--*') { $options = @('--clear') $options | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterName', 'Clear message notifications') } } } 'team' { if ($wordToComplete -like '--*') { $options = @('--status-only', '--reset', '--workers') $options | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { $description = switch ($_) { '--status-only' { 'Only show status, do not send notifications' } '--reset' { 'Reset all completion markers' } '--workers' { 'Number of workers to check' } } [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterName', $description) } } } 'init' { if ($wordToComplete -like '--*') { $options = @('--force', '--workers') $options | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { $description = switch ($_) { '--force' { 'Force initialization even if already exists' } '--workers' { 'Number of worker agents' } } [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterName', $description) } } } } } }`; } // Monitor command handler function handleMonitor(options) { if (!isProjectSetup()) { console.log(chalk.red('❌ Claude agents environment not found.')); console.log(chalk.yellow('Run "d0 init" first.')); return; } const refreshInterval = parseInt(options.refresh) || 2; console.log(chalk.bold.blue('πŸ” d0 Session Monitor\n')); console.log(chalk.gray(`Refreshing every ${refreshInterval} seconds. Press Ctrl+C to exit.\n`)); // Simple monitoring display function displayMonitor() { console.clear(); console.log(chalk.bold.blue('πŸ” d0 Session Monitor\n')); // Show session status if (fs.existsSync(CONSTANTS.SESSIONS_FILE)) { const sessions = JSON.parse(fs.readFileSync(CONSTANTS.SESSIONS_FILE, 'utf8')); console.log(chalk.green('πŸ“Š Sessions: ACTIVE')); console.log(chalk.gray(`Started: ${new Date(sessions.started).toLocaleString()}`)); console.log(chalk.gray(`Agents: ${sessions.sessions.join(', ')}`)); } else { console.log(chalk.red('πŸ“Š Sessions: INACTIVE')); } // Show recent activity console.log(chalk.blue('\nπŸ’¬ Recent Communication:')); if (fs.existsSync(CONSTANTS.MESSAGE_STATUS_FILE)) { try { const messageStatus = JSON.parse(fs.readFileSync(CONSTANTS.MESSAGE_STATUS_FILE, 'utf8')); const recent = Object.values(messageStatus) .sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp)) .slice(0, 5); if (recent.length > 0) { recent.forEach(msg => { const time = new Date(msg.timestamp).toLocaleTimeString(); console.log(chalk.gray(`${time} β†’ ${msg.recipient}: ${msg.message}`)); }); } else { console.log(chalk.gray('No recent messages')); } } catch (error) { console.log(chalk.gray('Error reading message status')); } } else { console.log(chalk.gray('No message history')); } console.log(chalk.blue(`\nπŸ”„ Last updated: ${new Date().toLocaleTimeString()}`)); console.log(chalk.gray('Press Ctrl+C to exit')); } // Initial display displayMonitor(); // Set up refresh interval const intervalId = setInterval(displayMonitor, refreshInterval * 1000); // Handle graceful shutdown process.on('SIGINT', () => { clearInterval(intervalId); console.log(chalk.yellow('\nπŸ‘‹ Monitor stopped')); process.exit(0); }); } module.exports = { handleGenerateInstruction, handleAgents, handleList, handleCompletion, handleMonitor, generateInstructionTemplate };