UNPKG

agentic-qe

Version:

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

268 lines 9.76 kB
"use strict"; /** * 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