UNPKG

tlnt

Version:

TLNT - HMS-Powered Multi-Agent Platform with Government Agency Analysis, Deep Research, and Enterprise-Ready Deployment. Self-optimizing multi-domain AI agent with continuous learning and enterprise-grade performance monitoring.

461 lines 15.8 kB
import { EventEmitter } from 'events'; export var AgentState; (function (AgentState) { AgentState["RUNNING"] = "running"; AgentState["PAUSED"] = "paused"; AgentState["MUTED"] = "muted"; AgentState["KILLED"] = "killed"; AgentState["ESCALATED"] = "escalated"; AgentState["ERROR"] = "error"; AgentState["INITIALIZING"] = "initializing"; })(AgentState || (AgentState = {})); /** * Control-aware agent mixin for HITL interactions * Handles control commands and state management */ export class ControlAwareAgent extends EventEmitter { agentStatus; messageBus; capabilities; controlChannel; heartbeatInterval; pausedOperations = []; constructor(agentId, messageBus, capabilities) { super(); this.messageBus = messageBus; this.controlChannel = `agent.${agentId}.ctl`; this.agentStatus = { agentId, state: AgentState.INITIALIZING, lastHeartbeat: new Date(), progress: 0, metadata: {} }; this.capabilities = { canPause: capabilities?.canPause ?? true, canMute: capabilities?.canMute ?? true, canKill: capabilities?.canKill ?? true, canEscalate: capabilities?.canEscalate ?? true, requiresApproval: capabilities?.requiresApproval ?? [], maxAutonomyLevel: capabilities?.maxAutonomyLevel ?? 0.8, ...capabilities }; this.setupControlListener(); this.startHeartbeat(); } /** * Initialize the agent and set up control channels */ async initialize() { try { await this.messageBus.subscribe(this.controlChannel, this.handleControlMessage.bind(this)); this.updateState(AgentState.RUNNING); this.emit('initialized', this.agentStatus); } catch (error) { this.updateState(AgentState.ERROR, { errorDetails: { message: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined, timestamp: new Date() } }); throw error; } } /** * Shutdown the agent and cleanup resources */ async shutdown() { if (this.heartbeatInterval) { clearInterval(this.heartbeatInterval); } await this.messageBus.unsubscribe(this.controlChannel); this.updateState(AgentState.KILLED); this.emit('shutdown', this.agentStatus); } /** * Handle incoming control messages */ async handleControlMessage(message) { try { const controlData = message.data; const controlMessage = { command: controlData.command, agentId: controlData.agentId, operatorId: controlData.operatorId, reason: controlData.reason, timestamp: new Date(message.timestamp), metadata: controlData.metadata }; this.emit('controlMessageReceived', controlMessage); switch (controlMessage.command) { case 'PAUSE': await this.handlePause(controlMessage); break; case 'RESUME': await this.handleResume(controlMessage); break; case 'MUTE': await this.handleMute(controlMessage); break; case 'UNMUTE': await this.handleUnmute(controlMessage); break; case 'KILL': await this.handleKill(controlMessage); break; case 'ESCALATE': await this.handleEscalate(controlMessage); break; default: this.emit('unknownControlCommand', controlMessage); } } catch (error) { this.emit('controlError', { error, message }); } } /** * Handle pause command */ async handlePause(controlMessage) { if (!this.capabilities.canPause) { this.emit('controlRejected', { controlMessage, reason: 'Pause not supported' }); return; } if (this.agentStatus.state === AgentState.RUNNING) { this.updateState(AgentState.PAUSED, { pausedSince: new Date(), metadata: { ...this.agentStatus.metadata, pauseReason: controlMessage.reason, pausedBy: controlMessage.operatorId } }); this.emit('paused', { controlMessage, agentStatus: this.agentStatus }); } } /** * Handle resume command */ async handleResume(controlMessage) { if (this.agentStatus.state === AgentState.PAUSED) { this.updateState(AgentState.RUNNING, { pausedSince: undefined, metadata: { ...this.agentStatus.metadata, resumedBy: controlMessage.operatorId, resumedAt: new Date() } }); // Resume any paused operations await this.resumePausedOperations(); this.emit('resumed', { controlMessage, agentStatus: this.agentStatus }); } } /** * Handle mute command */ async handleMute(controlMessage) { if (!this.capabilities.canMute) { this.emit('controlRejected', { controlMessage, reason: 'Mute not supported' }); return; } if (this.agentStatus.state !== AgentState.KILLED) { this.updateState(AgentState.MUTED, { mutedSince: new Date(), metadata: { ...this.agentStatus.metadata, muteReason: controlMessage.reason, mutedBy: controlMessage.operatorId } }); this.emit('muted', { controlMessage, agentStatus: this.agentStatus }); } } /** * Handle unmute command */ async handleUnmute(controlMessage) { if (this.agentStatus.state === AgentState.MUTED) { this.updateState(AgentState.RUNNING, { mutedSince: undefined, metadata: { ...this.agentStatus.metadata, unmutedBy: controlMessage.operatorId, unmutedAt: new Date() } }); this.emit('unmuted', { controlMessage, agentStatus: this.agentStatus }); } } /** * Handle kill command */ async handleKill(controlMessage) { if (!this.capabilities.canKill) { this.emit('controlRejected', { controlMessage, reason: 'Kill not supported' }); return; } this.updateState(AgentState.KILLED, { metadata: { ...this.agentStatus.metadata, killedBy: controlMessage.operatorId, killReason: controlMessage.reason, killedAt: new Date() } }); this.emit('killed', { controlMessage, agentStatus: this.agentStatus }); // Shutdown the agent await this.shutdown(); } /** * Handle escalate command */ async handleEscalate(controlMessage) { if (!this.capabilities.canEscalate) { this.emit('controlRejected', { controlMessage, reason: 'Escalation not supported' }); return; } this.updateState(AgentState.ESCALATED, { escalationReason: controlMessage.reason, metadata: { ...this.agentStatus.metadata, escalatedBy: controlMessage.operatorId, escalatedAt: new Date() } }); // Create escalation request const escalationRequest = { agentId: this.agentStatus.agentId, reason: controlMessage.reason || 'Manual escalation', severity: 'medium', context: { controlMessage, agentStatus: this.agentStatus }, requiredResponse: 'intervention', timeout: 300000, // 5 minutes escalatedAt: new Date() }; this.emit('escalated', { controlMessage, escalationRequest, agentStatus: this.agentStatus }); // Send escalation to monitoring system await this.sendEscalationNotification(escalationRequest); } /** * Check if agent can execute an action */ canExecuteAction(actionType) { // Check state if (this.agentStatus.state === AgentState.PAUSED) { return false; } if (this.agentStatus.state === AgentState.KILLED) { return false; } if (this.agentStatus.state === AgentState.ESCALATED) { return false; } // Check if action requires approval if (this.capabilities.requiresApproval.includes(actionType)) { return false; // Would need to request approval first } return true; } /** * Request approval for an action */ async requestApproval(actionType, context, timeout = 300000 // 5 minutes ) { const approvalRequest = { agentId: this.agentStatus.agentId, actionType, context, requestedAt: new Date(), timeout }; this.emit('approvalRequested', approvalRequest); // Send approval request to oversight system await this.messageBus.publish('approval.request', { type: 'approval_request', source: this.agentStatus.agentId, data: approvalRequest, priority: 2 }); // Wait for approval (simplified - in real implementation would use promises/callbacks) return new Promise((resolve) => { const timeoutId = setTimeout(() => resolve(false), timeout); this.once('approvalReceived', (approval) => { clearTimeout(timeoutId); resolve(approval.approved); }); }); } /** * Self-escalate when encountering issues */ async selfEscalate(reason, severity = 'medium', requiredResponse = 'advisory') { if (!this.capabilities.canEscalate) { return; } const escalationRequest = { agentId: this.agentStatus.agentId, reason, severity, context: { currentTask: this.agentStatus.currentTask, progress: this.agentStatus.progress, agentStatus: this.agentStatus }, requiredResponse, timeout: severity === 'critical' ? 60000 : 300000, // 1 min for critical, 5 min for others escalatedAt: new Date() }; this.updateState(AgentState.ESCALATED, { escalationReason: reason }); this.emit('selfEscalated', escalationRequest); await this.sendEscalationNotification(escalationRequest); } /** * Update agent progress */ updateProgress(progress, currentTask) { this.agentStatus.progress = Math.max(0, Math.min(1, progress)); if (currentTask) { this.agentStatus.currentTask = currentTask; } this.agentStatus.lastHeartbeat = new Date(); this.emit('progressUpdated', { progress: this.agentStatus.progress, currentTask: this.agentStatus.currentTask }); } /** * Report agent status */ async reportStatus() { this.agentStatus.lastHeartbeat = new Date(); // Update status in message bus await this.messageBus.updateAgentStatus(this.agentStatus.agentId, { state: this.agentStatus.state, lastHeartbeat: this.agentStatus.lastHeartbeat.getTime(), progress: this.agentStatus.progress, currentTask: this.agentStatus.currentTask, metadata: this.agentStatus.metadata }); return { ...this.agentStatus }; } /** * Get agent capabilities */ getCapabilities() { return { ...this.capabilities }; } /** * Get current status */ getStatus() { return { ...this.agentStatus }; } updateState(newState, updates) { const oldState = this.agentStatus.state; this.agentStatus = { ...this.agentStatus, state: newState, lastHeartbeat: new Date(), ...updates }; this.emit('stateChanged', { oldState, newState, agentStatus: this.agentStatus }); } setupControlListener() { // Already handled in handleControlMessage } startHeartbeat() { this.heartbeatInterval = setInterval(async () => { if (this.agentStatus.state !== AgentState.KILLED) { await this.reportStatus(); } }, 30000); // Every 30 seconds } async resumePausedOperations() { const operations = [...this.pausedOperations]; this.pausedOperations = []; for (const operation of operations) { try { await operation(); } catch (error) { this.emit('operationResumeError', { error, operation }); } } } async sendEscalationNotification(escalationRequest) { await this.messageBus.publish('escalation.alert', { type: 'escalation', source: this.agentStatus.agentId, data: escalationRequest, priority: escalationRequest.severity === 'critical' ? 3 : 2 }); } /** * Add operation to pause queue (for resuming later) */ addPausedOperation(operation) { if (this.agentStatus.state === AgentState.PAUSED) { this.pausedOperations.push(operation); } } /** * Check if agent should pause execution */ shouldPause() { return this.agentStatus.state === AgentState.PAUSED; } /** * Check if agent should stop execution */ shouldStop() { return this.agentStatus.state === AgentState.KILLED || this.agentStatus.state === AgentState.ERROR; } /** * Wait for resume if paused */ async waitForResume() { if (this.agentStatus.state === AgentState.PAUSED) { return new Promise((resolve) => { const checkState = () => { if (this.agentStatus.state !== AgentState.PAUSED) { resolve(); } else { setTimeout(checkState, 1000); } }; checkState(); }); } } /** * Health check */ async healthCheck() { const isHealthy = this.agentStatus.state !== AgentState.ERROR && this.agentStatus.state !== AgentState.KILLED; return { status: isHealthy ? 'healthy' : 'unhealthy', details: { agentId: this.agentStatus.agentId, state: this.agentStatus.state, lastHeartbeat: this.agentStatus.lastHeartbeat, progress: this.agentStatus.progress, capabilities: this.capabilities, pausedOperationsCount: this.pausedOperations.length } }; } } //# sourceMappingURL=controlAwareAgent.js.map