UNPKG

@stackmemoryai/stackmemory

Version:

Project-scoped memory for AI coding tools. Durable context across sessions with MCP integration, frames, smart retrieval, Claude Code skills, and automatic hooks.

295 lines (293 loc) 9.29 kB
import { fileURLToPath as __fileURLToPath } from 'url'; import { dirname as __pathDirname } from 'path'; const __filename = __fileURLToPath(import.meta.url); const __dirname = __pathDirname(__filename); import { EventEmitter } from "events"; import { logger } from "../../../core/monitoring/logger.js"; class SwarmDashboard extends EventEmitter { metrics = /* @__PURE__ */ new Map(); alerts = []; monitoringInterval; swarmCoordinator; constructor(swarmCoordinator) { super(); this.swarmCoordinator = swarmCoordinator; this.setupDefaultAlerts(); } /** * Start real-time monitoring */ startMonitoring(intervalMs = 5e3) { this.monitoringInterval = setInterval(() => { this.collectMetrics(); this.checkAlerts(); }, intervalMs); logger.info("Swarm monitoring dashboard started"); } /** * Stop monitoring */ stopMonitoring() { if (this.monitoringInterval) { clearInterval(this.monitoringInterval); this.monitoringInterval = void 0; } logger.info("Swarm monitoring dashboard stopped"); } /** * Get current metrics for a swarm */ getSwarmMetrics(swarmId) { return this.metrics.get(swarmId); } /** * Get all active swarm metrics */ getAllMetrics() { return Array.from(this.metrics.values()); } /** * Add custom alert rule */ addAlert(rule) { this.alerts.push(rule); logger.info(`Added alert rule: ${rule.id}`); } /** * Generate real-time dashboard HTML */ generateDashboardHTML() { const metrics = this.getAllMetrics(); return ` <!DOCTYPE html> <html> <head> <title>Ralph Swarm Dashboard</title> <style> body { font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; } .dashboard { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; } .card { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .metric { display: flex; justify-content: space-between; margin: 10px 0; } .status-active { color: #28a745; } .status-error { color: #dc3545; } .status-idle { color: #6c757d; } .alert-critical { color: #dc3545; font-weight: bold; } .progress { background: #e9ecef; border-radius: 4px; height: 8px; } .progress-bar { background: #007bff; height: 100%; border-radius: 4px; } </style> <script> setTimeout(() => location.reload(), 5000); // Auto-refresh </script> </head> <body> <h1>\u{1F9BE} Ralph Swarm Dashboard</h1> <div class="dashboard"> ${metrics.map( (swarm) => ` <div class="card"> <h3>Swarm ${swarm.swarmId.substring(0, 8)}</h3> <div class="metric"> <span>Status:</span> <span class="status-${swarm.status}">${swarm.status.toUpperCase()}</span> </div> <div class="metric"> <span>Agents:</span> <span>${swarm.activeAgents}/${swarm.totalAgents}</span> </div> <div class="metric"> <span>Tasks:</span> <span>${swarm.completedTasks}/${swarm.activeTasks + swarm.completedTasks}</span> </div> <div class="metric"> <span>Throughput:</span> <span>${swarm.performance.throughput.toFixed(2)} tasks/min</span> </div> <div class="metric"> <span>Memory:</span> <span>${swarm.resourceUsage.memoryMB} MB</span> </div> <div class="metric"> <span>Uptime:</span> <span>${Math.round(swarm.performance.uptime / 1e3)}s</span> </div> <div style="margin-top: 15px;"> <h4>Agents:</h4> ${swarm.agents.map( (agent) => ` <div class="metric"> <span>${agent.role}:</span> <span class="status-${agent.status}">${agent.status}</span> </div> ` ).join("")} </div> </div> ` ).join("")} </div> <div class="card" style="margin-top: 20px;"> <h3>\u{1F6A8} Active Alerts</h3> <div id="alerts">${this.getActiveAlerts().map( (alert) => `<div class="alert-${alert.severity}">${alert.message}</div>` ).join("")}</div> </div> </body> </html>`; } /** * Export metrics to JSON */ exportMetrics() { return JSON.stringify( { timestamp: (/* @__PURE__ */ new Date()).toISOString(), swarms: this.getAllMetrics(), alerts: this.getActiveAlerts() }, null, 2 ); } collectMetrics() { const usage = this.swarmCoordinator.getResourceUsage(); const swarmState = this.swarmCoordinator.swarmState; if (!swarmState || !swarmState.id) return; const metrics = { swarmId: swarmState.id, status: swarmState.status, totalAgents: usage.activeAgents, activeAgents: usage.activeAgents, completedTasks: swarmState.completedTaskCount || 0, activeTasks: swarmState.activeTaskCount || 0, averageTaskTime: 0, // Calculate from agent metrics resourceUsage: { memoryMB: usage.memoryEstimate, cpuPercent: this.estimateCpuUsage(), diskMB: this.estimateDiskUsage() }, performance: { throughput: swarmState.performance?.throughput || 0, efficiency: swarmState.performance?.efficiency || 0, uptime: Date.now() - swarmState.startTime }, agents: this.collectAgentMetrics() }; this.metrics.set(swarmState.id, metrics); this.emit("metricsUpdated", metrics); } collectAgentMetrics() { const agents = this.swarmCoordinator.activeAgents; if (!agents) return []; return Array.from(agents.values()).map( (agent) => ({ id: agent.id, role: agent.role, status: agent.status, currentTask: agent.currentTask || void 0, tasksCompleted: agent.performance?.tasksCompleted || 0, averageTaskTime: agent.performance?.averageTaskTime || 0, successRate: agent.performance?.successRate || 1, lastActivity: agent.performance?.lastFreshStart || Date.now(), resourceUsage: { memoryMB: 50, // Estimate per agent iterations: agent.performance?.tasksCompleted || 0 } }) ); } checkAlerts() { const metrics = this.getAllMetrics(); for (const swarmMetrics of metrics) { for (const alert of this.alerts) { if (this.evaluateAlertCondition(alert, swarmMetrics)) { this.emit("alert", { ...alert, swarmId: swarmMetrics.swarmId, timestamp: Date.now(), value: this.getMetricValue(alert.condition, swarmMetrics) }); } } } } evaluateAlertCondition(alert, metrics) { const value = this.getMetricValue(alert.condition, metrics); switch (alert.type) { case "performance": return value < alert.threshold; case "error": return 1 - metrics.performance.efficiency > alert.threshold; case "resource": return metrics.resourceUsage.memoryMB > alert.threshold; case "completion": return metrics.performance.uptime > alert.threshold; default: return false; } } getMetricValue(condition, metrics) { if (condition.includes("throughput")) return metrics.performance.throughput; if (condition.includes("efficiency")) return metrics.performance.efficiency; if (condition.includes("memory")) return metrics.resourceUsage.memoryMB; if (condition.includes("uptime")) return metrics.performance.uptime; return 0; } getActiveAlerts() { return []; } estimateCpuUsage() { const activeAgents = this.collectAgentMetrics().filter( (a) => a.status === "active" ).length; return Math.min(activeAgents * 15, 100); } estimateDiskUsage() { const usage = this.swarmCoordinator.getResourceUsage(); return usage.workingDirectories.length * 10; } setupDefaultAlerts() { this.alerts = [ { id: "low-throughput", type: "performance", condition: "throughput < 0.5", threshold: 0.5, message: "Low throughput detected: Less than 0.5 tasks per minute", severity: "medium" }, { id: "high-memory", type: "resource", condition: "memory > 500", threshold: 500, message: "High memory usage detected: Over 500MB", severity: "high" }, { id: "long-running", type: "completion", condition: "uptime > 1800000", threshold: 18e5, // 30 minutes message: "Long running swarm detected: Over 30 minutes", severity: "low" }, { id: "low-efficiency", type: "error", condition: "errorRate > 0.3", threshold: 0.3, message: "High error rate detected: Over 30% failure rate", severity: "critical" } ]; } } var swarm_dashboard_default = SwarmDashboard; export { SwarmDashboard, swarm_dashboard_default as default }; //# sourceMappingURL=swarm-dashboard.js.map