UNPKG

pdca

Version:

🎯 AI 驅動的 PDCA 多代理開發系統 - 智能循環控制 + 成本管理 + Token 優化 + 多 AI 引擎支援

652 lines 26.6 kB
/** * PDCA 協調器 v2 * 支援多風格配置的版本 */ import { EventEmitter } from 'events'; import { TmuxManager } from '../../core/tmux-manager.js'; import { StyleEngine } from '../../core/style-engine.js'; import { MultiClaudeManager } from '../../core/multi-claude-manager.js'; import { CommunicationManager } from '../../core/communication-manager.js'; import { LoopController } from '../../core/loop-controller.js'; import { AIModel, initializeTokenTracker } from '../../core/token-tracker.js'; export class PDCAOrchestrator extends EventEmitter { tmuxManager; styleEngine; multiClaudeManager; communicationManager; agents = new Map(); currentTask; runtimeConfig; useMultiClaude = false; loopController; currentIteration = 0; isLoopRunning = false; lastQuality = 0; tokenTracker; constructor() { super(); this.styleEngine = new StyleEngine(); this.tmuxManager = new TmuxManager('pdca'); this.multiClaudeManager = new MultiClaudeManager('pdca'); this.communicationManager = new CommunicationManager(); } /** * 啟動 PDCA 系統 */ async start(mission, options = {}) { try { console.log('🎯 正在啟動 PDCA 系統...'); // 1. 載入風格配置 await this.loadConfiguration(options); // 2. 使用風格引擎創建代理 console.log('🎭 創建代理實例...'); this.agents = this.styleEngine.createAgents(); console.log(` ✅ 已創建 ${this.agents.size} 個代理`); // 3. 創建任務 this.currentTask = this.createTask(mission); // 4. 準備 tmux 環境 await this.setupTmuxEnvironment(); // 5. 初始化循環控制器 this.initializeLoopController(); // 6. 啟動代理 await this.startAgents(mission); // 7. 開始 PDCA 循環 await this.startPDCALoop(mission); // 8. 設置監控(如果需要) if (options.monitor) { await this.startMonitoring(); } this.emit('system-started', { sessionName: this.runtimeConfig?.sessionId, task: this.currentTask, profile: this.runtimeConfig?.name }); console.log(`\n✨ ${this.runtimeConfig?.name} 風格已啟動`); console.log(`📊 查看狀態: tmux attach -t ${this.tmuxManager.getSessionName()}`); } catch (error) { this.emit('system-error', { error }); throw error; } } /** * 載入配置 */ async loadConfiguration(options) { console.log('📋 載入配置...'); // 載入風格配置 this.runtimeConfig = await this.styleEngine.loadStyle(options); // 更新 tmux session 名稱 if (this.runtimeConfig.sessionId) { this.tmuxManager = new TmuxManager(this.runtimeConfig.sessionName || 'pdca'); } console.log(` ✅ 已載入 "${this.runtimeConfig.name}" 風格`); } /** * 啟動代理 */ async startAgents(mission) { // 為每個代理設置 tmux target let windowIndex = 0; for (const [key, agent] of this.agents.entries()) { agent.setTmuxTarget(`${this.tmuxManager.getSessionName()}:${windowIndex}`); windowIndex++; } // 啟動所有代理 await this.startAllAgents(mission); } /** * 設置 tmux 環境 */ async setupTmuxEnvironment() { console.log('🖥️ 設置 tmux 環境...'); // 創建主 session await this.tmuxManager.createSession(); // 第一個窗口已經由 createSession 創建為 'pdca-plan' // 我們為其餘代理創建窗口 const agentKeys = Array.from(this.agents.keys()); // 從第二個代理開始創建窗口(第一個用預設的 pdca-plan) for (let i = 1; i < agentKeys.length; i++) { const agentKey = agentKeys[i]; const agent = this.agents.get(agentKey); await this.tmuxManager.createWindow(agent.name, i); } // 創建監控窗口 await this.tmuxManager.createWindow('monitor', agentKeys.length); } /** * 啟動所有代理 */ async startAllAgents(mission) { console.log('🚀 啟動代理...'); const agents = Array.from(this.agents.values()); // 按順序啟動代理(避免資源競爭) for (const agent of agents) { try { console.log(` ${agent.icon} 啟動 ${agent.role}...`); await agent.start(mission); // 稍等一下再啟動下一個代理 await this.sleep(this.runtimeConfig?.execution.startup_delay || 1500); } catch (error) { console.error(`啟動 ${agent.name} 失敗:`, error); throw error; } } } /** * 停止系統 */ async stop() { console.log('🛑 正在停止 Raiy-PDCA 系統...'); try { // 停止 PDCA 循環 if (this.isLoopRunning) { await this.stopLoop(); } // 停止所有代理 await this.stopAllAgents(); // 清理 tmux session await this.tmuxManager.killSession(); this.emit('system-stopped'); } catch (error) { this.emit('system-error', { error }); throw error; } } /** * 獲取系統狀態 */ getStatus() { return { isRunning: this.currentTask?.status === 'running', task: this.currentTask, profile: this.runtimeConfig?.name, agents: Array.from(this.agents.values()).map(agent => ({ name: agent.name, status: agent.getStatus() })), loop: { isRunning: this.isLoopRunning, currentIteration: this.currentIteration, lastQuality: this.lastQuality }, tokenUsage: this.tokenTracker ? { totalTokens: this.tokenTracker.getStatistics().totalTokens, totalCost: this.tokenTracker.getStatistics().totalCost, budgetStatus: this.tokenTracker.getBudgetStatus() } : undefined }; } /** * 停止所有代理 */ async stopAllAgents() { const stopPromises = Array.from(this.agents.values()).map(agent => agent.stop().catch(error => { console.warn(`停止代理 ${agent.name} 時發生錯誤:`, error); })); await Promise.all(stopPromises); } /** * 啟動監控 */ async startMonitoring() { console.log('📊 啟動監控介面...'); // 動態導入監控模組(避免在非監控模式下載入 blessed) const { startMonitor } = await import('../../core/monitor.js'); const monitor = startMonitor({ sessionName: this.tmuxManager.getSessionName(), workingDir: process.cwd(), updateInterval: 2000 // 每2秒更新一次 }); // 設置代理和任務 monitor.setAgents(Array.from(this.agents.values())); if (this.currentTask) { monitor.setTask(this.currentTask); } // 監聽代理事件並更新監控 this.agents.forEach((agent, name) => { agent.on('starting', () => { monitor.updateAgent(name, { status: 'starting' }); monitor.log('info', `${agent.role} 開始啟動`); }); agent.on('started', () => { monitor.updateAgent(name, { status: 'running' }); monitor.log('info', `${agent.role} 啟動完成`); }); agent.on('error', (error) => { monitor.updateAgent(name, { status: 'error', message: error.message }); monitor.log('error', `${agent.role} 發生錯誤: ${error.message}`); }); agent.on('completed', () => { monitor.updateAgent(name, { status: 'completed' }); monitor.log('info', `${agent.role} 完成任務`); }); }); // 監聽系統事件 this.on('system-error', ({ error }) => { monitor.log('error', `系統錯誤: ${error.message}`); }); monitor.on('stop', () => { console.log('監控介面已關閉'); }); } /** * 創建任務 */ createTask(mission) { const taskId = `task_${Date.now()}`; const agentProgress = {}; Array.from(this.agents.keys()).forEach(agentName => { agentProgress[agentName] = { status: 'pending', progress: 0 }; }); return { id: taskId, description: mission, createdAt: new Date(), status: 'pending', agents: agentProgress }; } /** * 取得可用的風格列表 */ async getAvailableStyles() { return this.styleEngine.getAvailableStyles(); } /** * 切換風格(需要重啟系統) */ async switchStyle(styleName) { console.log(`切換到 ${styleName} 風格...`); // 停止當前系統 if (this.currentTask?.status === 'running') { await this.stop(); } // 重新載入新風格 await this.styleEngine.loadStyle({ profile: styleName }); console.log(`已切換到 ${styleName} 風格,請重新啟動系統`); } /** * 初始化循環控制器 */ initializeLoopController() { if (!this.runtimeConfig) { throw new Error('運行時配置尚未載入'); } // 從配置中獲取循環控制設定 const loopConfig = this.runtimeConfig.loop_control || { max_iterations: 3, quality_target: 8.5, marginal_threshold: 0.1, auto_continue: false, require_confirmation: true }; const costConfig = this.runtimeConfig.cost_control || { token_budget: 50000, cost_budget: 10.0, warning_threshold: 0.8, currency: 'USD' }; this.loopController = new LoopController(loopConfig, costConfig); // 初始化 Token 追蹤器 const tokenBudget = costConfig.token_budget || 50000; this.tokenTracker = initializeTokenTracker(tokenBudget * 0.01); // 假設每 token 0.01 美分 // 監聽 Token 追蹤事件 this.tokenTracker.on('budget-warning', (status) => { console.warn(`💰 Token 預算警告: 已使用 ${status.usagePercentage?.toFixed(1)}% ($${status.totalCost.toFixed(4)})`); this.emit('token-warning', status); }); this.tokenTracker.on('budget-exceeded', (status) => { console.error(`🚨 Token 預算超支! 總成本: $${status.totalCost.toFixed(4)}, 預算: $${status.budget}`); this.emit('token-exceeded', status); }); // 監聽循環控制事件 this.loopController.on('iteration-completed', (data) => { this.emit('pdca-iteration-completed', data); console.log(`✅ PDCA 循環 ${data.iteration} 完成,品質評分: ${data.quality}`); }); this.loopController.on('should-continue', async (decision) => { if (decision.continue) { console.log(`🔄 繼續下一個 PDCA 循環 (${decision.reason})`); await this.executeNextIteration(); } else { console.log(`⏹️ 停止 PDCA 循環: ${decision.reason}`); await this.finalizePDCALoop(); } }); this.loopController.on('cost-warning', (warning) => { console.warn(`💰 成本警告: ${warning.message}`); }); } /** * 開始 PDCA 循環 */ async startPDCALoop(mission) { if (!this.loopController) { throw new Error('循環控制器尚未初始化'); } this.isLoopRunning = true; this.currentIteration = 1; console.log('🔄 開始 PDCA 循環流程...'); // 開始第一個循環 await this.executeIteration(mission); } /** * 執行單次 PDCA 循環 */ async executeIteration(mission) { console.log(`\n📊 執行 PDCA 循環 ${this.currentIteration}`); const startTime = Date.now(); try { // Plan - 規劃階段 await this.executePlanPhase(mission); // Do - 執行階段 await this.executeDoPhase(); // Check - 檢查階段 const quality = await this.executeCheckPhase(); // Act - 行動階段 const improvements = await this.executeActPhase(); const endTime = Date.now(); const duration = endTime - startTime; // 智能早停分析 const costEfficiencyDecision = this.analyzeCostEfficiency(quality, improvements, duration); // 評估是否繼續循環 const shouldContinue = await this.loopController.shouldContinue({ iterationNumber: this.currentIteration, qualityScore: quality, tokensUsed: this.estimateTokenUsage(), timeElapsed: duration, improvement: quality - (this.lastQuality || 0), agentResults: { improvements } }); // 結合成本效益分析和循環控制決策 if (!costEfficiencyDecision.shouldContinue) { console.log(`🧠 智能早停: ${costEfficiencyDecision.reason}`); await this.finalizePDCALoop(); return; } this.lastQuality = quality; this.emit('pdca-cycle-completed', { iteration: this.currentIteration, quality, improvements, duration }); } catch (error) { console.error(`❌ PDCA 循環 ${this.currentIteration} 失敗:`, error); this.emit('pdca-cycle-error', { iteration: this.currentIteration, error }); throw error; } } /** * 執行下一個迭代 */ async executeNextIteration() { this.currentIteration++; await this.executeIteration(`繼續改進 - 第 ${this.currentIteration} 輪`); } /** * 完成 PDCA 循環 */ async finalizePDCALoop() { this.isLoopRunning = false; console.log('\n🎯 PDCA 循環流程完成'); console.log('📈 循環總結:'); console.log(` 總迭代次數: ${this.currentIteration}`); console.log(` 最終品質: ${this.lastQuality}`); // 顯示 token 使用統計 if (this.tokenTracker) { const stats = this.tokenTracker.getStatistics(); const budgetStatus = this.tokenTracker.getBudgetStatus(); console.log(` Token 使用: ${stats.totalTokens.toLocaleString()}`); console.log(` 估計成本: $${stats.totalCost.toFixed(4)}`); console.log(` 成本效率: ${stats.totalCost > 0 ? (this.lastQuality / stats.totalCost).toFixed(2) : 'N/A'} 品質/美元`); if (budgetStatus.budget) { console.log(` 預算使用: ${budgetStatus.usagePercentage?.toFixed(1)}%`); } } console.log(` 循環狀態: 已完成`); this.emit('pdca-loop-completed', { totalIterations: this.currentIteration, finalQuality: this.lastQuality }); } /** * Plan 階段 - 讓規劃代理工作 */ async executePlanPhase(mission) { console.log('📋 Plan 階段 - 分析需求和制定策略'); const planAgent = this.findAgentByRole('plan') || this.findAgentByRole('planner'); if (planAgent) { const input = `執行 Plan 階段:\n${mission}\n\n請分析需求並制定執行策略。`; await planAgent.sendMessage(input); // 模擬 AI 回應並追蹤 token 使用 const mockResponse = `已分析任務「${mission}」的需求,制定以下執行策略:\n1. 需求分析和架構設計\n2. 技術選型和實作計畫\n3. 測試策略和品質保證`; this.trackAICall(input, mockResponse, planAgent.name, 'plan-phase'); await this.sleep(3000); // 給代理時間處理 } } /** * Do 階段 - 讓執行代理工作 */ async executeDoPhase() { console.log('🛠️ Do 階段 - 實施解決方案'); const doAgent = this.findAgentByRole('do') || this.findAgentByRole('developer'); if (doAgent) { const input = '執行 Do 階段:根據 Plan 階段的策略實施解決方案。'; await doAgent.sendMessage(input); // 模擬 AI 回應並追蹤 token 使用 const mockResponse = `正在實施解決方案:\n1. 已建立專案架構\n2. 實作核心功能模組\n3. 整合外部依賴\n4. 進行單元測試\n\n當前進度:85% 完成`; this.trackAICall(input, mockResponse, doAgent.name, 'do-phase'); await this.sleep(5000); // 給代理更多時間實施 } } /** * Check 階段 - 讓檢查代理評估品質 */ async executeCheckPhase() { console.log('🔍 Check 階段 - 評估結果品質'); const checkAgent = this.findAgentByRole('check') || this.findAgentByRole('tester'); if (checkAgent) { const input = '執行 Check 階段:評估當前結果的品質,給出 1-10 分的評分。'; await checkAgent.sendMessage(input); // 模擬品質評分和 AI 回應 const quality = 7.5 + Math.random() * 2; // 7.5-9.5 之間的隨機評分 const mockResponse = `品質評估完成:\n評分:${quality.toFixed(1)}/10\n\n評估結果:\n1. 功能完整性:良好\n2. 程式碼品質:優秀\n3. 測試覆蓋率:85%\n4. 效能表現:符合預期\n\n建議:可進一步優化錯誤處理機制`; this.trackAICall(input, mockResponse, checkAgent.name, 'check-phase'); await this.sleep(3000); return quality; } // 模擬品質評分(實際應從代理反饋中獲取) return 7.5 + Math.random() * 2; // 7.5-9.5 之間的隨機評分 } /** * Act 階段 - 讓改進代理提出優化建議 */ async executeActPhase() { console.log('⚡ Act 階段 - 分析改進機會'); const actAgent = this.findAgentByRole('act') || this.findAgentByRole('optimizer'); if (actAgent) { const input = '執行 Act 階段:分析當前結果,提出具體的改進建議。'; await actAgent.sendMessage(input); // 模擬改進建議和 AI 回應 const improvements = ['優化性能', '改善用戶體驗', '增強錯誤處理', '提升安全性', '改進文檔']; const mockResponse = `改進分析完成:\n\n發現的改進機會:\n1. 優化性能 - 減少 API 回應時間\n2. 改善用戶體驗 - 增加互動回饋\n3. 增強錯誤處理 - 提供更清晰的錯誤訊息\n4. 提升安全性 - 加強輸入驗證\n5. 改進文檔 - 更新 API 文檔\n\n建議優先級:性能 > 用戶體驗 > 錯誤處理`; this.trackAICall(input, mockResponse, actAgent.name, 'act-phase'); await this.sleep(3000); return improvements; } // 模擬改進建議(實際應從代理反饋中獲取) return ['優化性能', '改善用戶體驗', '增強錯誤處理']; } /** * 根據角色查找代理 */ findAgentByRole(role) { for (const agent of this.agents.values()) { if (agent.role.toLowerCase().includes(role.toLowerCase())) { return agent; } } return Array.from(this.agents.values())[0]; // 如果找不到,返回第一個代理 } /** * 估算 Token 使用量 */ estimateTokenUsage() { if (!this.tokenTracker) { // 回退到簡化估算 return 1000 + Math.floor(Math.random() * 2000); } // 基於歷史數據的智能估算 const stats = this.tokenTracker.getStatistics(); if (stats.operationCount > 0) { return Math.round(stats.averageTokensPerOperation); } // 首次運行時的預設估算 return 2500; // 更現實的估算值 } /** * 記錄實際的 AI 調用成本 */ trackAICall(input, output, agentId, operation) { if (!this.tokenTracker) return; // 根據系統配置推測使用的 AI 模型 const model = this.inferAIModel(); this.tokenTracker.trackUsage(input, output, model, agentId, operation); } /** * 推測當前使用的 AI 模型 */ inferAIModel() { // 根據配置或環境推測 // 這裡可以根據實際的 AI 引擎配置來確定 const engineName = this.runtimeConfig?.ai_engine || 'claude'; switch (engineName.toLowerCase()) { case 'claude': return AIModel.CLAUDE_3_5_SONNET; case 'gpt-4': return AIModel.GPT_4; case 'gpt-3.5': return AIModel.GPT_3_5_TURBO; case 'gemini': return AIModel.GEMINI_PRO; default: return AIModel.CLAUDE_3_5_SONNET; // 預設值 } } /** * 智能成本效益分析 */ analyzeCostEfficiency(quality, improvements, duration) { if (!this.tokenTracker) { return { shouldContinue: true, reason: 'Token 追蹤器未初始化', confidence: 0.5, metrics: {} }; } const stats = this.tokenTracker.getStatistics(); const budgetStatus = this.tokenTracker.getBudgetStatus(); // 計算關鍵指標 const currentCostEfficiency = quality > 0 && stats.totalCost > 0 ? quality / stats.totalCost : 0; const improvementRate = this.currentIteration > 1 ? (quality - this.lastQuality) / (this.currentIteration - 1) : 1; // 預測下一輪的成本效益 const estimatedNextIterationCost = stats.averageTokensPerOperation * 0.01; // 假設每 token 0.01 美分 const predictedNextQuality = quality + improvementRate * 0.7; // 邊際遞減 const predictedCostEfficiency = predictedNextQuality / (stats.totalCost + estimatedNextIterationCost); const metrics = { currentQuality: quality, totalCost: stats.totalCost, currentCostEfficiency, improvementRate, predictedCostEfficiency, improvementDeclining: improvementRate < 0.1, costEfficiencyDeclining: predictedCostEfficiency < currentCostEfficiency * 0.8, budgetConcern: budgetStatus.usagePercentage && budgetStatus.usagePercentage > 70 }; // 智能決策邏輯 let shouldContinue = true; let reason = '繼續優化'; let confidence = 0.7; // 1. 預算警告檢查 if (budgetStatus.usagePercentage && budgetStatus.usagePercentage > 85) { shouldContinue = false; reason = `預算使用率過高 (${budgetStatus.usagePercentage.toFixed(1)}%)`; confidence = 0.9; } // 2. 成本效益持續下降 else if (metrics.costEfficiencyDeclining && metrics.improvementDeclining) { shouldContinue = false; reason = '成本效益和改進率雙重下降,達到最佳停止點'; confidence = 0.85; } // 3. 改進率極低 else if (improvementRate < 0.05 && this.currentIteration >= 2) { shouldContinue = false; reason = `改進率過低 (${(improvementRate * 100).toFixed(1)}%),邊際效益不佳`; confidence = 0.8; } // 4. 品質已達高水準且成本上升 else if (quality >= 8.5 && stats.totalCost > 5.0) { shouldContinue = false; reason = `品質已達標 (${quality.toFixed(1)}/10),成本效益考量建議停止`; confidence = 0.75; } // 5. 時間效率考量 else if (duration > 300000 && improvementRate < 0.1) { // 5分鐘且改進慢 shouldContinue = false; reason = '時間效率低,建議停止以控制成本'; confidence = 0.7; } // 記錄決策分析 this.emit('cost-efficiency-analysis', { iteration: this.currentIteration, decision: { shouldContinue, reason, confidence }, metrics }); console.log(`📊 成本效益分析 - 迭代 ${this.currentIteration}:`); console.log(` 品質: ${quality.toFixed(1)}/10`); console.log(` 成本: $${stats.totalCost.toFixed(4)}`); console.log(` 效率: ${currentCostEfficiency.toFixed(2)} 品質/美元`); console.log(` 改進率: ${(improvementRate * 100).toFixed(1)}%`); console.log(` 決策: ${shouldContinue ? '繼續' : '停止'} (信心度: ${(confidence * 100).toFixed(0)}%)`); return { shouldContinue, reason, confidence, metrics }; } /** * 獲取循環狀態 */ getLoopStatus() { const tokenStats = this.tokenTracker?.getStatistics(); const costEfficiency = tokenStats && this.lastQuality > 0 ? this.lastQuality / tokenStats.totalCost : undefined; return { isRunning: this.isLoopRunning, currentIteration: this.currentIteration, lastQuality: this.lastQuality, tokenStats, costEfficiency }; } /** * 手動停止循環 */ async stopLoop() { if (this.isLoopRunning) { console.log('🛑 手動停止 PDCA 循環...'); await this.finalizePDCALoop(); } } /** * 休眠工具函數 */ sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } } //# sourceMappingURL=orchestrator-v2.js.map