agentic-qe
Version:
Agentic Quality Engineering Fleet System - AI-driven quality management platform
280 lines • 11 kB
JavaScript
;
/**
* 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