UNPKG

snow-flow

Version:

Snow-Flow v3.2.0: Complete ServiceNow Enterprise Suite with 180+ MCP Tools. ATF Testing, Knowledge Management, Service Catalog, Change Management with CAB scheduling, Virtual Agent chatbots with NLU, Performance Analytics KPIs, Flow Designer automation, A

1,175 lines 47.9 kB
"use strict"; /** * Queen Agent Core with Enhanced 403 Error Handling * Master coordinator that analyzes objectives and spawns specialized agents * Works through Claude Code interface using TodoWrite for task coordination * Now with intelligent 403 error handling using Gap Analysis Engine */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.QueenAgent = void 0; const eventemitter3_1 = require("eventemitter3"); const queen_memory_1 = require("../queen/queen-memory"); // AgentCoordinator removed - using dynamic agent system const parallel_agent_engine_1 = require("../queen/parallel-agent-engine"); // Queen403Handler removed - using Gap Analysis Engine directly const logger_1 = require("../utils/logger"); const crypto = __importStar(require("crypto")); class QueenAgent extends eventemitter3_1.EventEmitter { constructor(config = {}) { super(); this.config = { memoryPath: config.memoryPath, maxConcurrentAgents: config.maxConcurrentAgents || 8, debugMode: config.debugMode || false, autoSpawn: config.autoSpawn !== false, claudeCodeInterface: config.claudeCodeInterface !== false, mcpTools: config.mcpTools || {} }; // Initialize logger first this.logger = new logger_1.Logger('QueenAgent'); // Initialize core systems this.memory = new queen_memory_1.QueenMemorySystem(this.config.memoryPath); this.parallelEngine = new parallel_agent_engine_1.ParallelAgentEngine(this.memory); // Dynamic agent system - no more hardcoded coordinator/handler this.activeObjectives = new Map(); this.todoCoordinations = new Map(); this.activeAgents = new Map(); this.setupEventHandlers(); if (this.config.debugMode) { console.log('👑 Queen Agent initialized with Claude Code interface and 403 handling'); } } /** * Update MCP tools configuration (useful when tools become available later) */ updateMCPTools(mcpTools) { this.config.mcpTools = mcpTools; // 403 handling now done through Gap Analysis Engine } /** * Analyze objective and create coordinated execution plan */ async analyzeObjective(objective) { const queenObjective = typeof objective === 'string' ? { id: this.generateId('obj'), description: objective } : objective; this.activeObjectives.set(queenObjective.id, queenObjective); this.emit('objective:analyzing', queenObjective); try { // Analyze objective using memory patterns and neural learning const _analysis = await this.performObjectiveAnalysis(queenObjective); // Store _analysis in memory for coordination await this.memory.store(`analysis_${queenObjective.id}`, { objective: queenObjective, _analysis, timestamp: new Date().toISOString() }); // Create TodoWrite coordination structure const todoCoordination = await this.createTodoCoordination(queenObjective, _analysis); this.todoCoordinations.set(queenObjective.id, todoCoordination); this.emit('objective:analyzed', { objective: queenObjective, _analysis, todos: todoCoordination.todos }); return _analysis; } catch (error) { this.emit('objective:error', { objective: queenObjective, error }); throw error; } } /** * Handle deployment error with intelligent 403 detection and resolution */ async handleDeploymentError(error, context) { // Check if it's a 403 permission error if (this.is403Error(error)) { console.log('🚨 Queen Agent: Detected 403 permission error - activating intelligent _analysis'); const objective = this.activeObjectives.get(context.objectiveId); if (!objective) { console.error('No objective found for error context'); return false; } // 403 handling now done through Gap Analysis Engine directly const result = { success: false, recommendations: ['Use Gap Analysis Engine for 403 error handling'], manualSteps: [], updatedConfig: {}, nextSteps: [], resolved: false }; // Update todos based on analysis if (result.nextSteps.length > 0) { await this.updateTodosWithPermissionFixes(context.objectiveId, result); } // If automatic fixes were applied, return true to retry if (result.resolved) { console.log('✅ Queen Agent: Automatic fixes applied - suggesting retry'); this.emit('permission:auto-fixed', { context, result }); return true; } // Emit event for manual intervention needed this.emit('permission:manual-required', { context, result }); return false; } return false; } /** * Check if error is a 403 permission error */ is403Error(error) { const errorStr = error?.toString() || ''; const errorMsg = error?.message || ''; const statusCode = error?.status || error?.statusCode || error?.response?.status; return statusCode === 403 || errorStr.includes('403') || errorMsg.includes('403') || errorMsg.includes('permission') || errorMsg.includes('access denied') || errorMsg.includes('insufficient privileges'); } /** * Update todos with permission fix steps */ async updateTodosWithPermissionFixes(objectiveId, permissionResult) { const todoCoordination = this.todoCoordinations.get(objectiveId); if (!todoCoordination) return; // Add new todos for permission fixes const newTodos = []; // Add retry todo if automatic fixes were applied if (permissionResult.resolved) { newTodos.push({ id: this.generateId('todo'), content: '🔄 Retry deployment after automatic permission fixes', status: 'pending', priority: 'high' }); } // Add manual action todos permissionResult.nextSteps.forEach((step) => { newTodos.push({ id: this.generateId('todo'), content: step, status: 'pending', priority: 'high' }); }); // Insert new todos at the beginning of pending todos const pendingIndex = todoCoordination.todos.findIndex(t => t.status === 'pending'); if (pendingIndex >= 0) { todoCoordination.todos.splice(pendingIndex, 0, ...newTodos); } else { todoCoordination.todos.push(...newTodos); } // Emit update event this.emit('todos:updated', { objectiveId, todos: todoCoordination.todos }); } /** * Spawn agents based on objective requirements with intelligent parallelization */ async spawnAgents(objectiveId) { const todoCoordination = this.todoCoordinations.get(objectiveId); if (!todoCoordination) { throw new Error(`No todo coordination found for objective: ${objectiveId}`); } const _analysis = await this.memory.get(`analysis_${objectiveId}`); if (!_analysis) { throw new Error(`No _analysis found for objective: ${objectiveId}`); } console.log('🧠 Queen Agent: Analyzing parallelization opportunities...'); // 🚀 NEW: Detect parallelization opportunities const opportunities = await this.parallelEngine.detectParallelizationOpportunities(todoCoordination.todos, _analysis._analysis.type, Array.from(this.activeAgents.values())); if (opportunities.length > 0) { console.log(`🎯 Found ${opportunities.length} parallelization opportunities!`); return await this.spawnParallelAgents(objectiveId, todoCoordination, opportunities); } else { console.log('📋 No parallelization opportunities found, using sequential approach'); return await this.spawnSequentialAgents(objectiveId, todoCoordination, _analysis._analysis); } } /** * 🚀 NEW: Spawn parallel agents based on opportunities */ async spawnParallelAgents(objectiveId, todoCoordination, opportunities) { console.log('🚀 Queen Agent: Spawning parallel agent teams...'); // Create execution plan const executionPlan = await this.parallelEngine.createExecutionPlan(opportunities, todoCoordination.todos, this.config.maxConcurrentAgents); // Execute the plan and get spawned agents const result = await this.parallelEngine.executeParallelPlan(executionPlan, async (type, specialization) => { return await this.spawnSpecializedAgent(type, objectiveId, specialization); }); console.log(`✅ Spawned ${result.spawnedAgents.length} specialized agents in parallel`); console.log(`⚡ Estimated speedup: ${result.executionDetails.estimatedSpeedup}`); return result.spawnedAgents; } /** * Fallback to sequential agent spawning */ async spawnSequentialAgents(objectiveId, todoCoordination, _analysis) { const agents = []; const requiredAgentTypes = new Set(_analysis.requiredAgents); // Spawn agents for each required type for (const agentType of requiredAgentTypes) { const agent = await this.spawnSpecializedAgent(agentType, objectiveId); agents.push(agent); } return agents; } /** * Spawn a specialized agent with optional specialization */ async spawnSpecializedAgent(type, objectiveId, specialization) { const agentId = this.generateId('agent'); const agent = { id: agentId, type, status: 'active', objectiveId, specialization, startTime: Date.now(), capabilities: [], mcpTools: [] }; this.activeAgents.set(agentId, agent); // Store agent info in memory for coordination await this.memory.store(`agent_${agentId}`, { agent, objective: this.activeObjectives.get(objectiveId), assignedTodos: [], status: 'initializing' }); this.emit('agent:spawned', agent); // Assign todos to agent based on capabilities await this.assignTodosToAgent(agent, objectiveId); return agent; } /** * Analyze objective to determine requirements */ async performObjectiveAnalysis(objective) { const description = objective.description.toLowerCase(); // Determine task type let type = 'unknown'; let requiredAgents = []; let estimatedComplexity = 5; let suggestedPattern = { taskType: 'standard', successRate: 0.8, agentSequence: [], mcpSequence: [], avgDuration: 300, lastUsed: new Date() }; const dependencies = []; // Portal page detection - check for specific page keywords if ((description.includes('portal') && description.includes('page')) || description.includes('portal page') || (description.includes('widget') && description.includes('page')) || (description.includes('widget') && description.includes('plaats')) || (description.includes('widget') && description.includes('add')) || description.includes('service portal page')) { type = 'portal_page'; requiredAgents = ['widget-creator', 'page-designer', 'script-writer', 'tester']; if (description.includes('dashboard') || description.includes('multi')) { estimatedComplexity = 8; requiredAgents.push('ui-ux-specialist'); } } // Widget development detection (only if not portal page) else if (description.includes('widget') || description.includes('ui component')) { type = 'widget'; requiredAgents = ['widget-creator', 'script-writer', 'tester']; if (description.includes('complex') || description.includes('interactive')) { estimatedComplexity = 8; requiredAgents.push('ui-ux-specialist'); } } // Flow development detection else if (description.includes('flow') || description.includes('workflow') || description.includes('automation')) { type = 'flow'; requiredAgents = ['flow-builder', 'integration-specialist', 'tester']; if (description.includes('approval')) { requiredAgents.push('approval-specialist'); dependencies.push('user_management', 'notification_system'); } } // Application development else if (description.includes('application') || description.includes('app') || description.includes('complete solution')) { type = 'application'; requiredAgents = ['app-architect', 'widget-creator', 'flow-builder', 'script-writer', 'tester']; estimatedComplexity = 10; suggestedPattern = { taskType: 'modular', successRate: 0.8, agentSequence: requiredAgents, mcpSequence: [], avgDuration: 900, lastUsed: new Date() }; } // Script development else if (description.includes('script') || description.includes('business rule') || description.includes('api')) { type = 'script'; requiredAgents = ['script-writer', 'tester']; if (description.includes('integration')) { requiredAgents.push('integration-specialist'); } } // Integration development else if (description.includes('integration') || description.includes('connect') || description.includes('external')) { type = 'integration'; requiredAgents = ['integration-specialist', 'script-writer', 'tester']; dependencies.push('authentication', 'data_transformation'); } // Add security agent if mentioned if (description.includes('secure') || description.includes('security') || description.includes('permission')) { requiredAgents.push('security-specialist'); } return { type, complexity: estimatedComplexity.toString(), requiredAgents: [...new Set(requiredAgents)], // Remove duplicates estimatedComplexity: Math.min(10, Math.max(1, estimatedComplexity)), suggestedPattern, dependencies }; } /** * Create todo coordination structure for Claude Code interface */ async createTodoCoordination(objective, _analysis) { const todos = this.generateTodosForObjective(objective, _analysis); const coordination = { objectiveId: objective.id, todos, agentAssignments: new Map(), dependencies: this.analyzeTodoDependencies(todos) }; // Store coordination info in memory await this.memory.store(`coordination_${objective.id}`, coordination); return coordination; } /** * Generate todos based on objective type */ generateTodosForObjective(objective, _analysis) { const baseTodos = [ { id: this.generateId('todo'), content: `Initialize swarm memory session for: ${objective.description}`, status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Validate ServiceNow authentication and permissions', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Check for existing similar artifacts', status: 'pending', priority: 'medium' }, { id: this.generateId('todo'), content: 'Create Update Set for tracking changes', status: 'pending', priority: 'high' } ]; // Add type-specific todos switch (_analysis.type) { case 'widget': baseTodos.push(...this.createWidgetTodos(objective, _analysis)); break; case 'portal_page': baseTodos.push(...this.createPortalPageTodos(objective, _analysis)); break; case 'flow': baseTodos.push(...this.createFlowTodos(objective, _analysis)); break; case 'application': baseTodos.push(...this.createApplicationTodos(objective, _analysis)); break; case 'script': baseTodos.push(...this.createScriptTodos(objective, _analysis)); break; case 'integration': baseTodos.push(...this.createIntegrationTodos(objective, _analysis)); break; default: baseTodos.push(...this.createGenericTodos(objective, _analysis)); } // Add final todos baseTodos.push({ id: this.generateId('todo'), content: 'Validate solution completeness', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Generate documentation and handoff materials', status: 'pending', priority: 'medium' }); return baseTodos; } /** * Create widget-specific todos */ createWidgetTodos(objective, _analysis) { // 🚀 ENHANCED: More specific todos to trigger parallel agent specialization const todos = [ { id: this.generateId('todo'), content: `Analyze portal requirements and user experience design: ${objective.description}`, status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Create widget HTML structure with responsive design and accessibility features', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Develop server-side script for backend data processing and API integration', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Build client-side controller with interactive features and event handling', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Style widget with CSS including responsive design and theme compliance', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Implement performance optimization and caching strategies', status: 'pending', priority: 'medium' }, { id: this.generateId('todo'), content: 'Test widget functionality including cross-browser and mobile testing', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Ensure security best practices and vulnerability scanning', status: 'pending', priority: 'high' } ]; return todos; } /** * Create portal page-specific todos */ createPortalPageTodos(objective, _analysis) { const todos = [ { id: this.generateId('todo'), content: `Analyze portal page requirements: ${objective.description}`, status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Create or identify widget to be placed on the page', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Design portal page layout (single column, multi-column, or with sidebar)', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Determine target portal (Service Portal or Employee Service Center)', status: 'pending', priority: 'medium' }, { id: this.generateId('todo'), content: 'Create portal page with proper page ID and title', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Configure page structure (containers, rows, columns)', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Place widget instance on the portal page with proper sizing', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Apply custom CSS styling for page layout and responsiveness', status: 'pending', priority: 'medium' }, { id: this.generateId('todo'), content: 'Configure page permissions and accessibility settings', status: 'pending', priority: 'medium' }, { id: this.generateId('todo'), content: 'Test portal page across different devices and browsers', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Add page to portal navigation menu if needed', status: 'pending', priority: 'low' } ]; return todos; } /** * Create flow-specific todos */ createFlowTodos(objective, _analysis) { const todos = [ { id: this.generateId('todo'), content: `Analyze flow requirements: ${objective.description}`, status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Design flow trigger conditions and events', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Map out flow steps and decision points', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Configure flow actions and integrations', status: 'pending', priority: 'medium' }, { id: this.generateId('todo'), content: 'Set up data transformations and variables', status: 'pending', priority: 'medium' }, { id: this.generateId('todo'), content: 'Create flow using natural language API', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Test flow with mock data scenarios', status: 'pending', priority: 'high' } ]; return todos; } /** * Create application-specific todos */ createApplicationTodos(objective, _analysis) { const todos = [ { id: this.generateId('todo'), content: `Design application architecture: ${objective.description}`, status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Create application scope and structure', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Design data model and tables', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Create UI components and widgets', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Implement business logic and workflows', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Configure security and access controls', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Create integration points', status: 'pending', priority: 'medium' }, { id: this.generateId('todo'), content: 'Test application end-to-end', status: 'pending', priority: 'high' } ]; return todos; } /** * Create script-specific todos */ createScriptTodos(objective, _analysis) { const todos = [ { id: this.generateId('todo'), content: `Analyze script requirements: ${objective.description}`, status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Design script logic and error handling', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Implement core functionality', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Add logging and debugging capabilities', status: 'pending', priority: 'medium' }, { id: this.generateId('todo'), content: 'Optimize performance', status: 'pending', priority: 'medium' }, { id: this.generateId('todo'), content: 'Create unit tests', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Deploy and validate in ServiceNow', status: 'pending', priority: 'high' } ]; return todos; } /** * Create integration-specific todos */ createIntegrationTodos(objective, _analysis) { const todos = [ { id: this.generateId('todo'), content: `Analyze integration requirements: ${objective.description}`, status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Identify external systems and APIs', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Design data mapping and transformation', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Configure authentication and security', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Create REST/SOAP message configurations', status: 'pending', priority: 'medium' }, { id: this.generateId('todo'), content: 'Implement error handling and retry logic', status: 'pending', priority: 'medium' }, { id: this.generateId('todo'), content: 'Test integration with mock endpoints', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Deploy and monitor integration', status: 'pending', priority: 'high' } ]; return todos; } /** * Create generic todos for unknown task types */ createGenericTodos(objective, _analysis) { const todos = [ { id: this.generateId('todo'), content: `Analyze requirements: ${objective.description}`, status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Research existing ServiceNow capabilities', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Design solution architecture', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Implement core functionality', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Create necessary configurations', status: 'pending', priority: 'medium' }, { id: this.generateId('todo'), content: 'Test solution thoroughly', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Deploy to ServiceNow', status: 'pending', priority: 'high' }, { id: this.generateId('todo'), content: 'Monitor and validate deployment', status: 'pending', priority: 'medium' } ]; return todos; } /** * Analyze todo dependencies */ analyzeTodoDependencies(todos) { const dependencies = new Map(); // Simple dependency _analysis - each todo depends on all previous high priority todos const highPriorityTodos = todos.filter(t => t.priority === 'high'); highPriorityTodos.forEach((todo, index) => { if (index > 0) { const prevHighPriorityIds = highPriorityTodos .slice(0, index) .map(t => t.id); dependencies.set(todo.id, prevHighPriorityIds); } }); return dependencies; } /** * Assign todos to agent based on capabilities */ async assignTodosToAgent(agent, objectiveId) { const todoCoordination = this.todoCoordinations.get(objectiveId); if (!todoCoordination) return; const unassignedTodos = todoCoordination.todos.filter(todo => !Array.from(todoCoordination.agentAssignments.values()).includes(todo.id) && todo.status === 'pending'); // Assign todos based on agent type and specialization const assignableTodos = unassignedTodos.filter(todo => this.canAgentHandleTodo(agent, todo)); for (const todo of assignableTodos) { todoCoordination.agentAssignments.set(todo.id, agent.id); // Update agent's assigned todos in memory const agentData = await this.memory.get(`agent_${agent.id}`); if (agentData) { agentData.assignedTodos.push(todo.id); await this.memory.store(`agent_${agent.id}`, agentData); } } this.emit('todos:assigned', { agent, todos: assignableTodos }); } /** * Check if agent can handle specific todo */ canAgentHandleTodo(agent, todo) { const todoContent = todo.content.toLowerCase(); switch (agent.type) { case 'widget-creator': return todoContent.includes('widget') || todoContent.includes('html') || todoContent.includes('portal') || todoContent.includes('ui'); case 'css-specialist': return todoContent.includes('style') || todoContent.includes('css') || todoContent.includes('responsive') || todoContent.includes('theme'); case 'backend-specialist': return todoContent.includes('server') || todoContent.includes('backend') || todoContent.includes('data') || todoContent.includes('api'); case 'frontend-specialist': return todoContent.includes('client') || todoContent.includes('controller') || todoContent.includes('interactive') || todoContent.includes('event'); case 'flow-builder': return todoContent.includes('flow') || todoContent.includes('workflow') || todoContent.includes('trigger') || todoContent.includes('action'); case 'script-writer': return todoContent.includes('script') || todoContent.includes('logic') || todoContent.includes('function'); case 'integration-specialist': return todoContent.includes('integration') || todoContent.includes('external') || todoContent.includes('api') || todoContent.includes('rest'); case 'tester': return todoContent.includes('test') || todoContent.includes('validate') || todoContent.includes('verify'); case 'security-specialist': return todoContent.includes('security') || todoContent.includes('permission') || todoContent.includes('access') || todoContent.includes('vulnerability'); case 'performance-specialist': return todoContent.includes('performance') || todoContent.includes('optimization') || todoContent.includes('caching'); case 'ui-ux-specialist': return todoContent.includes('user experience') || todoContent.includes('design') || todoContent.includes('ux'); case 'page-designer': return todoContent.includes('portal page') || todoContent.includes('page layout') || todoContent.includes('page structure') || todoContent.includes('place widget') || todoContent.includes('configure page') || todoContent.includes('containers') || todoContent.includes('rows') || todoContent.includes('columns') || todoContent.includes('page permissions') || todoContent.includes('portal navigation'); default: // Generic agents can handle setup and coordination tasks return todoContent.includes('initialize') || todoContent.includes('validate') || todoContent.includes('create update set') || todoContent.includes('documentation'); } } /** * Monitor agent progress through todo updates */ async monitorProgress(objectiveId) { const todoCoordination = this.todoCoordinations.get(objectiveId); if (!todoCoordination) { throw new Error(`No todo coordination found for objective: ${objectiveId}`); } // Calculate progress from todos const completedTodos = todoCoordination.todos.filter(t => t.status === 'completed').length; const totalTodos = todoCoordination.todos.length; const overallProgress = totalTodos > 0 ? (completedTodos / totalTodos) * 100 : 0; // Calculate per-agent progress const byAgent = new Map(); for (const [todoId, agentId] of todoCoordination.agentAssignments) { const agentTodos = Array.from(todoCoordination.agentAssignments.entries()) .filter(([_, aid]) => aid === agentId); const agentCompleted = agentTodos.filter(([tid, _]) => todoCoordination.todos.find(t => t.id === tid)?.status === 'completed').length; const agentProgress = agentTodos.length > 0 ? (agentCompleted / agentTodos.length) * 100 : 0; byAgent.set(agentId, agentProgress); } // Identify blocking issues const blockingIssues = await this.identifyBlockingIssues(todoCoordination); // Estimate completion based on current velocity const estimatedCompletion = this.estimateCompletion(todoCoordination, overallProgress); // Store progress in memory await this.memory.store(`progress_${objectiveId}`, { overall: overallProgress, byAgent: Object.fromEntries(byAgent), blockingIssues, estimatedCompletion: estimatedCompletion.toISOString(), timestamp: new Date().toISOString() }); this.emit('progress:updated', { objectiveId, overall: overallProgress, byAgent, blockingIssues }); return { overall: overallProgress, byAgent, blockingIssues, estimatedCompletion }; } /** * Make memory-driven decisions based on past patterns */ async makeDecision(context) { // Query memory for similar past decisions const similarPatterns = await this.memory.findSimilarPatterns(context.objective); // Analyze success rates of past decisions const successRates = new Map(); for (const option of context.options) { const pastOutcomes = similarPatterns.filter(p => p.decision === option); const successRate = pastOutcomes.length > 0 ? pastOutcomes.filter(p => p.outcome === 'success').length / pastOutcomes.length : 0.5; // Default to 50% if no history successRates.set(option, successRate); } // Choose option with highest success rate let bestOption = context.options[0]; let highestRate = 0; for (const [option, rate] of successRates) { if (rate > highestRate) { highestRate = rate; bestOption = option; } } const confidence = highestRate > 0.7 ? 0.9 : highestRate > 0.5 ? 0.7 : 0.5; const decision = { decision: bestOption, confidence, reasoning: `Based on ${similarPatterns.length} similar past scenarios, "${bestOption}" has a ${(highestRate * 100).toFixed(0)}% success rate.` }; // Store decision for future learning await this.memory.storeDecision('decision', { context, decision: decision.decision, confidence: decision.confidence, timestamp: new Date().toISOString() }); this.emit('decision:made', decision); return decision; } /** * Setup event handlers for coordination */ setupEventHandlers() { // Dynamic agent system - event handlers removed // Agents are now orchestrated through the dynamic system // Events are handled by the Queen's executeObjective flow /* Legacy coordinator event handlers removed - kept for reference this.coordinator.on('agent:ready', ...) this.coordinator.on('agent:completed', ...) this.coordinator.on('agent:error', ...) */ // New dynamic system handles agent lifecycle internally if (this.config.debugMode) { console.log('🔄 Dynamic agent event system initialized'); } } /** * Check if more agents need to be spawned */ async checkAndSpawnAgents(objectiveId) { const todoCoordination = this.todoCoordinations.get(objectiveId); if (!todoCoordination) return; const unassignedTodos = todoCoordination.todos.filter(todo => !Array.from(todoCoordination.agentAssignments.values()).includes(todo.id) && todo.status === 'pending'); if (unassignedTodos.length > 0 && this.activeAgents.size < this.config.maxConcurrentAgents) { // Spawn additional agents if needed await this.spawnAgents(objectiveId); } } /** * Handle coordination errors */ async handleCoordinationError(error, context) { console.error('❌ Coordination error:', error); // Store error in memory for learning - using store method await this.memory.store('error', { error: error.message || error, context, timestamp: new Date().toISOString(), recovery: null }); this.emit('coordination:error', { error, context }); } /** * Identify blocking issues from todos */ async identifyBlockingIssues(todoCoordination) { const issues = []; // Check for failed todos const failedTodos = todoCoordination.todos.filter(t => t.status === 'failed'); if (failedTodos.length > 0) { issues.push(`${failedTodos.length} failed tasks blocking progress`); } // Check for stuck in-progress todos (older than 10 minutes) const stuckTodos = todoCoordination.todos.filter(t => { if (t.status !== 'in_progress') return false; const todoData = this.memory.get(`todo_${t.id}`); if (!todoData || !todoData.startTime) return false; return Date.now() - todoData.startTime > 10 * 60 * 1000; // 10 minutes }); if (stuckTodos.length > 0) { issues.push(`${stuckTodos.length} tasks stuck in progress`); } // Check for dependency bottlenecks const pendingWithDeps = todoCoordination.todos.filter(t => t.status === 'pending' && todoCoordination.dependencies.has(t.id)); for (const todo of pendingWithDeps) { const deps = todoCoordination.dependencies.get(todo.id) || []; const incompleteDeps = deps.filter(depId => { const depTodo = todoCoordination.todos.find(t => t.id === depId); return depTodo && depTodo.status !== 'completed'; }); if (incompleteDeps.length === deps.length) { issues.push(`Task "${todo.content}" blocked by dependencies`); } } return issues; } /** * Estimate completion time based on current progress */ estimateCompletion(todoCoordination, currentProgress) { if (currentProgress === 0) { return new Date(Date.now() + 24 * 60 * 60 * 1000); // 24 hours if no progress } const completedTodos = todoCoordination.todos.filter(t => t.status === 'completed').length; const startTime = this.activeObjectives.get(todoCoordination.objectiveId)?.metadata?.startTime || Date.now(); const elapsedTime = Date.now() - startTime; const averageTimePerTodo = elapsedTime / completedTodos; const remainingTodos = todoCoordination.todos.filter(t => t.status !== 'completed').length; const estimatedRemainingTime = averageTimePerTodo * remainingTodos; return new Date(Date.now() + estimatedRemainingTime); } /** * Generate unique ID for entities */ generateId(prefix) { return `${prefix}_${Date.now()}_${crypto.randomBytes(4).toString('hex')}`; } /** * Shutdown queen agent gracefully */ async shutdown() { console.log('👑 Queen Agent shutting down...'); // Save current state for (const [objectiveId, objective] of this.activeObjectives) { await this.memory.store(`objective_state_${objectiveId}`, { objective, todoCoordination: this.todoCoordinations.get(objectiveId), activeAgents: Array.from(this.activeAgents.values()).filter(a => a.objectiveId === objectiveId), timestamp: new Date().toISOString() }); } // Notify all active agents for (const agent of this.activeAgents.values()) { this.emit('agent:shutdown', agent); } await this.memory.close(); this.removeAllListeners(); console.log('✅ Queen Agent shutdown complete'); } } exports.QueenAgent = QueenAgent; //# sourceMappingURL=queen-agent.js.map