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
JavaScript
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