UNPKG

agentic-qe

Version:

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

390 lines 14 kB
"use strict"; /** * BaseAgent - Abstract base class for all QE agents * Implements core lifecycle hooks, event handling, and memory access * Based on SPARC Phase 2 Pseudocode and Phase 3 Architecture */ Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseAgentFactory = exports.BaseAgent = void 0; const events_1 = require("events"); const types_1 = require("../types"); class BaseAgent extends events_1.EventEmitter { constructor(config) { super(); this.status = types_1.AgentStatus.INITIALIZING; this.eventHandlers = new Map(); this.performanceMetrics = { tasksCompleted: 0, averageExecutionTime: 0, errorCount: 0, lastActivity: new Date() }; this.agentId = { id: config.id || this.generateAgentId(config.type), type: config.type, created: new Date() }; this.capabilities = new Map(config.capabilities.map(cap => [cap.name, cap])); this.context = config.context; this.memoryStore = config.memoryStore; this.eventBus = config.eventBus; this.setupEventHandlers(); this.setupLifecycleHooks(); } // ============================================================================ // Public Interface // ============================================================================ /** * Initialize the agent - must be called after construction */ async initialize() { try { this.status = types_1.AgentStatus.INITIALIZING; // Execute pre-initialization hooks await this.executeHook('pre-initialization'); // Load agent knowledge and state await this.loadKnowledge(); await this.restoreState(); // Initialize agent-specific components await this.initializeComponents(); // Execute post-initialization hooks await this.executeHook('post-initialization'); this.status = types_1.AgentStatus.ACTIVE; this.emitEvent('agent.initialized', { agentId: this.agentId }); // Report initialization to coordination system await this.reportStatus('initialized'); } catch (error) { this.status = types_1.AgentStatus.ERROR; this.emitEvent('agent.error', { agentId: this.agentId, error }); throw error; } } /** * Execute a task assignment */ async executeTask(assignment) { const startTime = Date.now(); try { // Validate task assignment this.validateTaskAssignment(assignment); this.currentTask = assignment; this.status = types_1.AgentStatus.ACTIVE; // Execute pre-task hooks await this.executeHook('pre-task', { assignment }); // Broadcast task start await this.broadcastMessage('task-start', assignment); // Execute the actual task const result = await this.performTask(assignment.task); // Execute post-task hooks await this.executeHook('post-task', { assignment, result }); // Update performance metrics this.updatePerformanceMetrics(startTime, true); // Store task completion in memory await this.storeTaskResult(assignment.id, result); this.currentTask = undefined; this.status = types_1.AgentStatus.IDLE; return result; } catch (error) { this.updatePerformanceMetrics(startTime, false); this.currentTask = undefined; this.status = types_1.AgentStatus.ERROR; // Execute error hooks await this.executeHook('task-error', { assignment, error }); throw error; } } /** * Terminate the agent gracefully */ async terminate() { try { this.status = types_1.AgentStatus.TERMINATING; // Execute pre-termination hooks await this.executeHook('pre-termination'); // Save current state await this.saveState(); // Clean up resources await this.cleanup(); // Remove all event handlers from EventBus for (const [eventType, handlers] of this.eventHandlers.entries()) { for (const handler of handlers) { this.eventBus.off(eventType, handler.handler); } } this.eventHandlers.clear(); // Execute post-termination hooks await this.executeHook('post-termination'); this.status = types_1.AgentStatus.TERMINATED; this.emitEvent('agent.terminated', { agentId: this.agentId }); // Remove all listeners from this agent (EventEmitter) this.removeAllListeners(); } catch (error) { this.status = types_1.AgentStatus.ERROR; throw error; } } /** * Get current agent status and metrics */ getStatus() { return { agentId: this.agentId, status: this.status, currentTask: this.currentTask?.id, capabilities: Array.from(this.capabilities.keys()), performanceMetrics: { ...this.performanceMetrics } }; } /** * Check if agent has a specific capability */ hasCapability(capabilityName) { return this.capabilities.has(capabilityName); } /** * Get capability details */ getCapability(capabilityName) { return this.capabilities.get(capabilityName); } /** * Get all capabilities */ getCapabilities() { return Array.from(this.capabilities.values()); } /** * Start the agent (alias for initialize) */ async start() { await this.initialize(); } /** * Assign a task to the agent */ async assignTask(task) { const assignment = { id: `task-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, task, agentId: this.agentId.id, assignedAt: new Date(), status: 'assigned' }; await this.executeTask(assignment); } // ============================================================================ // Event System // ============================================================================ /** * Register an event handler */ registerEventHandler(handler) { const handlers = this.eventHandlers.get(handler.eventType) || []; handlers.push(handler); this.eventHandlers.set(handler.eventType, handlers); this.eventBus.on(handler.eventType, handler.handler); } /** * Emit an event */ emitEvent(type, data, priority = 'medium') { const event = { id: this.generateEventId(), type, source: this.agentId, data, timestamp: new Date(), priority, scope: 'global' }; this.eventBus.emit(type, event); } /** * Broadcast message to other agents */ async broadcastMessage(type, payload) { const message = { id: this.generateMessageId(), from: this.agentId, to: { id: 'broadcast', type: 'all', created: new Date() }, type: type, payload, timestamp: new Date(), priority: 'medium' }; this.eventBus.emit('agent.message', message); } // ============================================================================ // Memory Operations // ============================================================================ /** * Store data in memory with automatic namespacing */ async storeMemory(key, value, ttl) { if (!this.memoryStore) { console.warn(`[WARN] Memory store not available for ${this.agentId.id}`); return; } const namespacedKey = `agent:${this.agentId.id}:${key}`; await this.memoryStore.store(namespacedKey, value, ttl); } /** * Retrieve data from memory */ async retrieveMemory(key) { if (!this.memoryStore) { console.warn(`[WARN] Memory store not available for ${this.agentId.id}`); return null; } const namespacedKey = `agent:${this.agentId.id}:${key}`; return await this.memoryStore.retrieve(namespacedKey); } /** * Store shared data accessible by other agents */ async storeSharedMemory(key, value, ttl) { if (!this.memoryStore) { console.warn(`[WARN] Memory store not available for ${this.agentId.id}`); return; } const sharedKey = `shared:${this.agentId.type}:${key}`; await this.memoryStore.store(sharedKey, value, ttl); } /** * Retrieve shared data from other agents */ async retrieveSharedMemory(agentType, key) { if (!this.memoryStore) { console.warn(`[WARN] Memory store not available for ${this.agentId.id}`); return null; } const sharedKey = `shared:${agentType}:${key}`; return await this.memoryStore.retrieve(sharedKey); } // ============================================================================ // Lifecycle Hooks // ============================================================================ async executeHook(hookName, data) { try { const method = `on${hookName.charAt(0).toUpperCase()}${hookName.slice(1).replace(/-/g, '')}`; if (typeof this[method] === 'function') { await this[method](data); } } catch (error) { console.error(`Hook ${hookName} failed for agent ${this.agentId.id}:`, error); } } // ============================================================================ // Helper Methods // ============================================================================ setupEventHandlers() { // Set up base event handlers that all agents should have this.registerEventHandler({ eventType: 'fleet.shutdown', handler: async () => { await this.terminate(); } }); this.registerEventHandler({ eventType: 'agent.ping', handler: async (event) => { if (event.target?.id === this.agentId.id) { this.emitEvent('agent.pong', { agentId: this.agentId }); } } }); } setupLifecycleHooks() { // Setup default lifecycle behavior this.on('error', (error) => { this.status = types_1.AgentStatus.ERROR; this.emitEvent('agent.error', { agentId: this.agentId, error }); }); } validateTaskAssignment(assignment) { if (!assignment || !assignment.task) { throw new Error('Invalid task assignment'); } // Check if agent has required capabilities const requiredCapabilities = assignment.task.requirements?.capabilities || []; for (const capability of requiredCapabilities) { if (!this.hasCapability(capability)) { throw new Error(`Agent ${this.agentId.id} missing required capability: ${capability}`); } } } updatePerformanceMetrics(startTime, success) { const executionTime = Date.now() - startTime; if (success) { this.performanceMetrics.tasksCompleted++; this.performanceMetrics.averageExecutionTime = (this.performanceMetrics.averageExecutionTime * (this.performanceMetrics.tasksCompleted - 1) + executionTime) / this.performanceMetrics.tasksCompleted; } else { this.performanceMetrics.errorCount++; } this.performanceMetrics.lastActivity = new Date(); } async storeTaskResult(taskId, result) { await this.storeMemory(`task:${taskId}:result`, { result, timestamp: new Date(), agentId: this.agentId.id }); } async restoreState() { try { const state = await this.retrieveMemory('state'); if (state) { this.performanceMetrics = { ...this.performanceMetrics, ...state.performanceMetrics }; } } catch (error) { // State restoration is optional console.warn(`Could not restore state for agent ${this.agentId.id}:`, error); } } async saveState() { try { await this.storeMemory('state', { performanceMetrics: this.performanceMetrics, timestamp: new Date() }); } catch (error) { console.error(`Could not save state for agent ${this.agentId.id}:`, error); } } async reportStatus(status) { try { await this.storeSharedMemory('status', { agentId: this.agentId.id, status, timestamp: new Date(), metrics: this.performanceMetrics }); } catch (error) { console.warn(`Could not report status for agent ${this.agentId.id}:`, error); } } generateAgentId(type) { return `${type}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; } generateEventId() { return `event-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; } generateMessageId() { return `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; } } exports.BaseAgent = BaseAgent; class BaseAgentFactory { } exports.BaseAgentFactory = BaseAgentFactory; //# sourceMappingURL=BaseAgent.js.map