UNPKG

agentic-qe

Version:

Agentic Quality Engineering Fleet System - AI-driven quality management platform

280 lines 11 kB
"use strict"; /** * Agent Assign Command * * Assigns tasks to agents with intelligent load balancing, capability matching, * and resource optimization. Supports auto-assignment and manual assignment. * * @module cli/commands/agent/assign */ 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 (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AgentAssignCommand = void 0; const fs = __importStar(require("fs-extra")); const path = __importStar(require("path")); const AgentRegistry_1 = require("../../../mcp/services/AgentRegistry"); const Logger_1 = require("../../../utils/Logger"); const logger = Logger_1.Logger.getInstance(); /** * Agent Assign Command Implementation */ class AgentAssignCommand { /** * Execute task assignment * * @param options - Assignment options * @returns Assignment result */ static async execute(options) { const { agentId, taskId, taskType, requireCapability, autoBalance = false, priority = 'medium', timeout = 300000, retryOnFailure = true } = options; logger.info(`Assigning task: ${taskId}`, { agentId, autoBalance, priority }); try { // Get agent registry const registry = (0, AgentRegistry_1.getAgentRegistry)(); // Read task definition const task = await this.readTask(taskId); // Determine target agent let targetAgentId; let targetAgent; if (agentId) { // Manual assignment targetAgent = registry.getRegisteredAgent(agentId); if (!targetAgent) { throw new Error(`Agent not found: ${agentId}`); } targetAgentId = agentId; // Validate capability if required if (requireCapability) { this.validateCapability(targetAgent, requireCapability); } } else if (autoBalance) { // Auto-assignment with load balancing const selected = await this.selectBestAgent(registry, taskType || task.type, requireCapability); targetAgentId = selected.id; targetAgent = selected.agent; } else { throw new Error('Either agentId or autoBalance must be provided'); } // Check agent availability const availability = await this.checkAgentAvailability(targetAgent); let result; if (availability.available) { // Assign immediately result = await this.assignToAgent(targetAgentId, targetAgent, taskId, task, priority, timeout); } else { // Queue for later execution result = await this.queueTask(targetAgentId, targetAgent, taskId, task, priority); } // Save assignment record await this.saveAssignment(result); logger.info(`Task assigned: ${taskId} -> ${targetAgentId}`, { status: result.status, queuePosition: result.queuePosition }); return result; } catch (error) { logger.error(`Failed to assign task ${taskId}:`, error); throw new Error(`Task assignment failed: ${error instanceof Error ? error.message : String(error)}`); } } /** * Read task definition */ static async readTask(taskId) { const taskPath = path.join(this.TASKS_DIR, `${taskId}.json`); if (!await fs.pathExists(taskPath)) { throw new Error(`Task not found: ${taskId}`); } return await fs.readJson(taskPath); } /** * Validate agent capability */ static validateCapability(agent, capability) { const capabilities = agent.agent?.config?.capabilities?.map((c) => c.name) || []; if (!capabilities.includes(capability)) { throw new Error(`Agent lacks required capability: ${capability}`); } } /** * Select best agent using load balancing algorithm */ static async selectBestAgent(registry, taskType, requireCapability) { const allAgents = registry.getAllAgents(); if (allAgents.length === 0) { throw new Error('No agents available'); } // Filter by capability if required let candidates = allAgents; if (requireCapability) { candidates = allAgents.filter((agent) => { const capabilities = agent.agent?.config?.capabilities?.map((c) => c.name) || []; return capabilities.includes(requireCapability); }); if (candidates.length === 0) { throw new Error(`No agents with required capability: ${requireCapability}`); } } // Score agents based on load, status, and performance const scores = candidates.map((agent) => { let score = 100; // Penalize by current load score -= agent.tasksCompleted * 0.1; // Penalize busy agents if (agent.status === 'busy') { score -= 50; } // Penalize error agents if (agent.status === 'error') { score -= 80; } // Bonus for idle agents if (agent.status === 'idle') { score += 20; } // Bonus for low execution time const avgTime = agent.tasksCompleted > 0 ? agent.totalExecutionTime / agent.tasksCompleted : 0; score += Math.max(0, 20 - (avgTime / 1000)); return { agent, score }; }); // Sort by score descending scores.sort((a, b) => b.score - a.score); const selected = scores[0].agent; logger.debug('Agent selected by load balancing:', { agentId: selected.id, score: scores[0].score, status: selected.status }); return { id: selected.id, agent: selected }; } /** * Check agent availability */ static async checkAgentAvailability(agent) { if (agent.status === 'error') { return { available: false, reason: 'Agent in error state' }; } if (agent.status === 'terminated') { return { available: false, reason: 'Agent terminated' }; } if (agent.status === 'busy') { // Check queue size const queueSize = await this.getAgentQueueSize(agent.id); if (queueSize >= 10) { return { available: false, reason: 'Queue full' }; } } return { available: true }; } /** * Get agent queue size */ static async getAgentQueueSize(agentId) { const queuePath = path.join(this.QUEUE_DIR, `${agentId}.json`); if (!await fs.pathExists(queuePath)) { return 0; } const queue = await fs.readJson(queuePath); return queue.tasks?.length || 0; } /** * Assign task to agent immediately */ static async assignToAgent(agentId, agent, taskId, task, priority, timeout) { // Update agent config with assigned task const configPath = path.join(this.AGENT_DIR, `${agentId}.json`); const config = await fs.readJson(configPath); config.assignedTasks = config.assignedTasks || []; config.assignedTasks.push(taskId); await fs.writeJson(configPath, config, { spaces: 2 }); // Estimate completion time const avgTime = agent.tasksCompleted > 0 ? agent.totalExecutionTime / agent.tasksCompleted : 30000; const estimatedCompletion = new Date(Date.now() + avgTime); return { taskId, agentId, agentType: agent.mcpType, status: 'assigned', assignedAt: new Date(), estimatedCompletion, capabilities: agent.agent?.config?.capabilities?.map((c) => c.name) || [] }; } /** * Queue task for later execution */ static async queueTask(agentId, agent, taskId, task, priority) { const queuePath = path.join(this.QUEUE_DIR, `${agentId}.json`); await fs.ensureDir(this.QUEUE_DIR); let queue = { tasks: [] }; if (await fs.pathExists(queuePath)) { queue = await fs.readJson(queuePath); } // Add to queue with priority const queueEntry = { taskId, task, priority, queuedAt: new Date().toISOString() }; queue.tasks = queue.tasks || []; queue.tasks.push(queueEntry); // Sort by priority const priorityOrder = { critical: 0, high: 1, medium: 2, low: 3 }; queue.tasks.sort((a, b) => priorityOrder[a.priority] - priorityOrder[b.priority]); await fs.writeJson(queuePath, queue, { spaces: 2 }); const queuePosition = queue.tasks.findIndex((t) => t.taskId === taskId); return { taskId, agentId, agentType: agent.mcpType, status: 'queued', assignedAt: new Date(), queuePosition, capabilities: agent.agent?.config?.capabilities?.map((c) => c.name) || [] }; } /** * Save assignment record */ static async saveAssignment(result) { const assignmentPath = path.join(this.TASKS_DIR, `${result.taskId}.assignment.json`); await fs.writeJson(assignmentPath, result, { spaces: 2 }); } } exports.AgentAssignCommand = AgentAssignCommand; AgentAssignCommand.TASKS_DIR = path.join(process.cwd(), '.aqe', 'tasks'); AgentAssignCommand.AGENT_DIR = path.join(process.cwd(), '.aqe', 'agents'); AgentAssignCommand.QUEUE_DIR = path.join(process.cwd(), '.aqe', 'queue'); //# sourceMappingURL=assign.js.map