agentic-qe
Version:
Agentic Quality Engineering Fleet System - AI-driven quality management platform
268 lines • 9.76 kB
JavaScript
;
/**
* Agent Attach Command
*
* Attaches to an agent's console for real-time monitoring of logs,
* metrics, and status updates. Provides interactive debugging capabilities.
*
* @module cli/commands/agent/attach
*/
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.AgentAttachCommand = 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 events_1 = require("events");
const logger = Logger_1.Logger.getInstance();
/**
* Agent Attach Command Implementation
*/
class AgentAttachCommand {
/**
* Execute agent attach
*
* @param options - Attach options
* @returns Attach session
*/
static async execute(options) {
const { agentId, follow = true, showMetrics = true, showLogs = true, showEvents = true, refreshRate = 1000, filter } = options;
logger.info(`Attaching to agent: ${agentId}`, { follow, showMetrics, showLogs });
try {
// Get agent registry
const registry = (0, AgentRegistry_1.getAgentRegistry)();
// Verify agent exists
const agent = registry.getRegisteredAgent(agentId);
if (!agent) {
throw new Error(`Agent not found: ${agentId}`);
}
// Check if already attached
const existing = this.activeSessions.get(agentId);
if (existing && existing.status === 'attached') {
logger.warn(`Already attached to agent: ${agentId}`);
return existing;
}
// Create attach session
const session = await this.createAttachSession(agentId, agent, {
follow,
showMetrics,
showLogs,
showEvents,
refreshRate,
filter
});
// Store active session
this.activeSessions.set(agentId, session);
// Start monitoring
if (follow) {
this.startMonitoring(session, options);
}
logger.info(`Attached to agent: ${agentId}`, { sessionId: session.sessionId });
return session;
}
catch (error) {
logger.error(`Failed to attach to agent ${agentId}:`, error);
throw new Error(`Agent attach failed: ${error instanceof Error ? error.message : String(error)}`);
}
}
/**
* Create attach session
*/
static async createAttachSession(agentId, agent, options) {
const sessionId = `attach-${agentId}-${Date.now()}`;
const session = {
sessionId,
agentId,
attachedAt: new Date(),
events: new events_1.EventEmitter(),
status: 'attached',
stats: {
logsReceived: 0,
eventsReceived: 0,
metricsReceived: 0
}
};
// Save session metadata
await this.saveSessionMetadata(session, options);
// Display initial status
this.displayInitialStatus(agent);
return session;
}
/**
* Save session metadata
*/
static async saveSessionMetadata(session, options) {
await fs.ensureDir(this.SESSIONS_DIR);
const sessionPath = path.join(this.SESSIONS_DIR, `${session.sessionId}.json`);
const metadata = {
sessionId: session.sessionId,
agentId: session.agentId,
attachedAt: session.attachedAt.toISOString(),
status: session.status,
options
};
await fs.writeJson(sessionPath, metadata, { spaces: 2 });
}
/**
* Display initial agent status
*/
static displayInitialStatus(agent) {
console.log('\n' + '='.repeat(60));
console.log(`📎 Attached to Agent: ${agent.id}`);
console.log('='.repeat(60));
console.log(`Type: ${agent.mcpType}`);
console.log(`Status: ${agent.status}`);
console.log(`Tasks Completed: ${agent.tasksCompleted}`);
console.log(`Last Activity: ${new Date(agent.lastActivity).toLocaleString()}`);
console.log('='.repeat(60) + '\n');
}
/**
* Start monitoring agent activity
*/
static startMonitoring(session, options) {
const { agentId, showMetrics, showLogs, showEvents, refreshRate, filter } = options;
// Monitor logs
if (showLogs) {
this.monitorLogs(session, filter);
}
// Monitor metrics
if (showMetrics) {
this.monitorMetrics(session, refreshRate);
}
// Monitor events
if (showEvents) {
this.monitorEvents(session);
}
// Setup event handlers
session.events.on('log', (log) => {
console.log(`[LOG] ${log}`);
session.stats.logsReceived++;
});
session.events.on('metric', (metric) => {
console.log(`[METRIC] ${JSON.stringify(metric)}`);
session.stats.metricsReceived++;
});
session.events.on('event', (event) => {
console.log(`[EVENT] ${event.type}: ${event.message}`);
session.stats.eventsReceived++;
});
}
/**
* Monitor agent logs
*/
static monitorLogs(session, filter) {
const logPath = path.join(this.LOGS_DIR, `${session.agentId}.log`);
let lastPosition = 0;
const checkLogs = async () => {
try {
if (!await fs.pathExists(logPath)) {
return;
}
const stats = await fs.stat(logPath);
if (stats.size > lastPosition) {
const stream = fs.createReadStream(logPath, {
start: lastPosition,
encoding: 'utf-8'
});
stream.on('data', (chunk) => {
const lines = chunk.toString().split('\n');
lines.forEach((line) => {
if (line.trim() && (!filter || line.includes(filter))) {
session.events.emit('log', line);
}
});
});
lastPosition = stats.size;
}
}
catch (error) {
logger.error('Error monitoring logs:', error);
}
};
// Check logs every second
const interval = setInterval(checkLogs, 1000);
// Store interval for cleanup
session.logInterval = interval;
}
/**
* Monitor agent metrics
*/
static monitorMetrics(session, refreshRate) {
const registry = (0, AgentRegistry_1.getAgentRegistry)();
const checkMetrics = () => {
try {
const metrics = registry.getAgentMetrics(session.agentId);
if (metrics) {
session.events.emit('metric', metrics);
}
}
catch (error) {
logger.error('Error monitoring metrics:', error);
}
};
const interval = setInterval(checkMetrics, refreshRate);
// Store interval for cleanup
session.metricsInterval = interval;
}
/**
* Monitor agent events
*/
static monitorEvents(session) {
// This would connect to the agent's event bus
// For now, simulate with periodic checks
const checkEvents = () => {
// Placeholder for event monitoring
// In real implementation, would subscribe to agent's EventBus
};
const interval = setInterval(checkEvents, 2000);
// Store interval for cleanup
session.eventsInterval = interval;
}
/**
* Get active session
*/
static getActiveSession(agentId) {
return this.activeSessions.get(agentId);
}
/**
* Get all active sessions
*/
static getAllActiveSessions() {
return Array.from(this.activeSessions.values());
}
/**
* Check if attached to agent
*/
static isAttached(agentId) {
const session = this.activeSessions.get(agentId);
return session !== undefined && session.status === 'attached';
}
}
exports.AgentAttachCommand = AgentAttachCommand;
AgentAttachCommand.LOGS_DIR = path.join(process.cwd(), '.aqe', 'logs');
AgentAttachCommand.SESSIONS_DIR = path.join(process.cwd(), '.aqe', 'sessions');
AgentAttachCommand.activeSessions = new Map();
//# sourceMappingURL=attach.js.map