@stackmemoryai/stackmemory 0.3.25 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/ralph.js +12 -0
- package/dist/cli/commands/ralph.js.map +2 -2
- package/dist/features/tui/swarm-monitor.js +488 -0
- package/dist/features/tui/swarm-monitor.js.map +7 -0
- package/dist/integrations/ralph/coordination/enhanced-coordination.js +406 -0
- package/dist/integrations/ralph/coordination/enhanced-coordination.js.map +7 -0
- package/dist/integrations/ralph/monitoring/swarm-dashboard.js +290 -0
- package/dist/integrations/ralph/monitoring/swarm-dashboard.js.map +7 -0
- package/dist/integrations/ralph/monitoring/swarm-registry.js +95 -0
- package/dist/integrations/ralph/monitoring/swarm-registry.js.map +7 -0
- package/dist/integrations/ralph/recovery/crash-recovery.js +458 -0
- package/dist/integrations/ralph/recovery/crash-recovery.js.map +7 -0
- package/dist/integrations/ralph/swarm/swarm-coordinator.js +4 -0
- package/dist/integrations/ralph/swarm/swarm-coordinator.js.map +2 -2
- package/package.json +2 -1
- package/scripts/test-swarm-tui.ts +34 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
import { logger } from "../../../core/monitoring/logger.js";
|
|
3
|
+
class SwarmDashboard extends EventEmitter {
|
|
4
|
+
metrics = /* @__PURE__ */ new Map();
|
|
5
|
+
alerts = [];
|
|
6
|
+
monitoringInterval;
|
|
7
|
+
swarmCoordinator;
|
|
8
|
+
constructor(swarmCoordinator) {
|
|
9
|
+
super();
|
|
10
|
+
this.swarmCoordinator = swarmCoordinator;
|
|
11
|
+
this.setupDefaultAlerts();
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Start real-time monitoring
|
|
15
|
+
*/
|
|
16
|
+
startMonitoring(intervalMs = 5e3) {
|
|
17
|
+
this.monitoringInterval = setInterval(() => {
|
|
18
|
+
this.collectMetrics();
|
|
19
|
+
this.checkAlerts();
|
|
20
|
+
}, intervalMs);
|
|
21
|
+
logger.info("Swarm monitoring dashboard started");
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Stop monitoring
|
|
25
|
+
*/
|
|
26
|
+
stopMonitoring() {
|
|
27
|
+
if (this.monitoringInterval) {
|
|
28
|
+
clearInterval(this.monitoringInterval);
|
|
29
|
+
this.monitoringInterval = void 0;
|
|
30
|
+
}
|
|
31
|
+
logger.info("Swarm monitoring dashboard stopped");
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get current metrics for a swarm
|
|
35
|
+
*/
|
|
36
|
+
getSwarmMetrics(swarmId) {
|
|
37
|
+
return this.metrics.get(swarmId);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get all active swarm metrics
|
|
41
|
+
*/
|
|
42
|
+
getAllMetrics() {
|
|
43
|
+
return Array.from(this.metrics.values());
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Add custom alert rule
|
|
47
|
+
*/
|
|
48
|
+
addAlert(rule) {
|
|
49
|
+
this.alerts.push(rule);
|
|
50
|
+
logger.info(`Added alert rule: ${rule.id}`);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Generate real-time dashboard HTML
|
|
54
|
+
*/
|
|
55
|
+
generateDashboardHTML() {
|
|
56
|
+
const metrics = this.getAllMetrics();
|
|
57
|
+
return `
|
|
58
|
+
<!DOCTYPE html>
|
|
59
|
+
<html>
|
|
60
|
+
<head>
|
|
61
|
+
<title>Ralph Swarm Dashboard</title>
|
|
62
|
+
<style>
|
|
63
|
+
body { font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }
|
|
64
|
+
.dashboard { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
|
|
65
|
+
.card { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
|
|
66
|
+
.metric { display: flex; justify-content: space-between; margin: 10px 0; }
|
|
67
|
+
.status-active { color: #28a745; }
|
|
68
|
+
.status-error { color: #dc3545; }
|
|
69
|
+
.status-idle { color: #6c757d; }
|
|
70
|
+
.alert-critical { color: #dc3545; font-weight: bold; }
|
|
71
|
+
.progress { background: #e9ecef; border-radius: 4px; height: 8px; }
|
|
72
|
+
.progress-bar { background: #007bff; height: 100%; border-radius: 4px; }
|
|
73
|
+
</style>
|
|
74
|
+
<script>
|
|
75
|
+
setTimeout(() => location.reload(), 5000); // Auto-refresh
|
|
76
|
+
</script>
|
|
77
|
+
</head>
|
|
78
|
+
<body>
|
|
79
|
+
<h1>\u{1F9BE} Ralph Swarm Dashboard</h1>
|
|
80
|
+
<div class="dashboard">
|
|
81
|
+
${metrics.map(
|
|
82
|
+
(swarm) => `
|
|
83
|
+
<div class="card">
|
|
84
|
+
<h3>Swarm ${swarm.swarmId.substring(0, 8)}</h3>
|
|
85
|
+
<div class="metric">
|
|
86
|
+
<span>Status:</span>
|
|
87
|
+
<span class="status-${swarm.status}">${swarm.status.toUpperCase()}</span>
|
|
88
|
+
</div>
|
|
89
|
+
<div class="metric">
|
|
90
|
+
<span>Agents:</span>
|
|
91
|
+
<span>${swarm.activeAgents}/${swarm.totalAgents}</span>
|
|
92
|
+
</div>
|
|
93
|
+
<div class="metric">
|
|
94
|
+
<span>Tasks:</span>
|
|
95
|
+
<span>${swarm.completedTasks}/${swarm.activeTasks + swarm.completedTasks}</span>
|
|
96
|
+
</div>
|
|
97
|
+
<div class="metric">
|
|
98
|
+
<span>Throughput:</span>
|
|
99
|
+
<span>${swarm.performance.throughput.toFixed(2)} tasks/min</span>
|
|
100
|
+
</div>
|
|
101
|
+
<div class="metric">
|
|
102
|
+
<span>Memory:</span>
|
|
103
|
+
<span>${swarm.resourceUsage.memoryMB} MB</span>
|
|
104
|
+
</div>
|
|
105
|
+
<div class="metric">
|
|
106
|
+
<span>Uptime:</span>
|
|
107
|
+
<span>${Math.round(swarm.performance.uptime / 1e3)}s</span>
|
|
108
|
+
</div>
|
|
109
|
+
<div style="margin-top: 15px;">
|
|
110
|
+
<h4>Agents:</h4>
|
|
111
|
+
${swarm.agents.map(
|
|
112
|
+
(agent) => `
|
|
113
|
+
<div class="metric">
|
|
114
|
+
<span>${agent.role}:</span>
|
|
115
|
+
<span class="status-${agent.status}">${agent.status}</span>
|
|
116
|
+
</div>
|
|
117
|
+
`
|
|
118
|
+
).join("")}
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
`
|
|
122
|
+
).join("")}
|
|
123
|
+
</div>
|
|
124
|
+
|
|
125
|
+
<div class="card" style="margin-top: 20px;">
|
|
126
|
+
<h3>\u{1F6A8} Active Alerts</h3>
|
|
127
|
+
<div id="alerts">${this.getActiveAlerts().map(
|
|
128
|
+
(alert) => `<div class="alert-${alert.severity}">${alert.message}</div>`
|
|
129
|
+
).join("")}</div>
|
|
130
|
+
</div>
|
|
131
|
+
</body>
|
|
132
|
+
</html>`;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Export metrics to JSON
|
|
136
|
+
*/
|
|
137
|
+
exportMetrics() {
|
|
138
|
+
return JSON.stringify(
|
|
139
|
+
{
|
|
140
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
141
|
+
swarms: this.getAllMetrics(),
|
|
142
|
+
alerts: this.getActiveAlerts()
|
|
143
|
+
},
|
|
144
|
+
null,
|
|
145
|
+
2
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
collectMetrics() {
|
|
149
|
+
const usage = this.swarmCoordinator.getResourceUsage();
|
|
150
|
+
const swarmState = this.swarmCoordinator.swarmState;
|
|
151
|
+
if (!swarmState || !swarmState.id) return;
|
|
152
|
+
const metrics = {
|
|
153
|
+
swarmId: swarmState.id,
|
|
154
|
+
status: swarmState.status,
|
|
155
|
+
totalAgents: usage.activeAgents,
|
|
156
|
+
activeAgents: usage.activeAgents,
|
|
157
|
+
completedTasks: swarmState.completedTaskCount || 0,
|
|
158
|
+
activeTasks: swarmState.activeTaskCount || 0,
|
|
159
|
+
averageTaskTime: 0,
|
|
160
|
+
// Calculate from agent metrics
|
|
161
|
+
resourceUsage: {
|
|
162
|
+
memoryMB: usage.memoryEstimate,
|
|
163
|
+
cpuPercent: this.estimateCpuUsage(),
|
|
164
|
+
diskMB: this.estimateDiskUsage()
|
|
165
|
+
},
|
|
166
|
+
performance: {
|
|
167
|
+
throughput: swarmState.performance?.throughput || 0,
|
|
168
|
+
efficiency: swarmState.performance?.efficiency || 0,
|
|
169
|
+
uptime: Date.now() - swarmState.startTime
|
|
170
|
+
},
|
|
171
|
+
agents: this.collectAgentMetrics()
|
|
172
|
+
};
|
|
173
|
+
this.metrics.set(swarmState.id, metrics);
|
|
174
|
+
this.emit("metricsUpdated", metrics);
|
|
175
|
+
}
|
|
176
|
+
collectAgentMetrics() {
|
|
177
|
+
const agents = this.swarmCoordinator.activeAgents;
|
|
178
|
+
if (!agents) return [];
|
|
179
|
+
return Array.from(agents.values()).map(
|
|
180
|
+
(agent) => ({
|
|
181
|
+
id: agent.id,
|
|
182
|
+
role: agent.role,
|
|
183
|
+
status: agent.status,
|
|
184
|
+
currentTask: agent.currentTask || void 0,
|
|
185
|
+
tasksCompleted: agent.performance?.tasksCompleted || 0,
|
|
186
|
+
averageTaskTime: agent.performance?.averageTaskTime || 0,
|
|
187
|
+
successRate: agent.performance?.successRate || 1,
|
|
188
|
+
lastActivity: agent.performance?.lastFreshStart || Date.now(),
|
|
189
|
+
resourceUsage: {
|
|
190
|
+
memoryMB: 50,
|
|
191
|
+
// Estimate per agent
|
|
192
|
+
iterations: agent.performance?.tasksCompleted || 0
|
|
193
|
+
}
|
|
194
|
+
})
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
checkAlerts() {
|
|
198
|
+
const metrics = this.getAllMetrics();
|
|
199
|
+
for (const swarmMetrics of metrics) {
|
|
200
|
+
for (const alert of this.alerts) {
|
|
201
|
+
if (this.evaluateAlertCondition(alert, swarmMetrics)) {
|
|
202
|
+
this.emit("alert", {
|
|
203
|
+
...alert,
|
|
204
|
+
swarmId: swarmMetrics.swarmId,
|
|
205
|
+
timestamp: Date.now(),
|
|
206
|
+
value: this.getMetricValue(alert.condition, swarmMetrics)
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
evaluateAlertCondition(alert, metrics) {
|
|
213
|
+
const value = this.getMetricValue(alert.condition, metrics);
|
|
214
|
+
switch (alert.type) {
|
|
215
|
+
case "performance":
|
|
216
|
+
return value < alert.threshold;
|
|
217
|
+
case "error":
|
|
218
|
+
return 1 - metrics.performance.efficiency > alert.threshold;
|
|
219
|
+
case "resource":
|
|
220
|
+
return metrics.resourceUsage.memoryMB > alert.threshold;
|
|
221
|
+
case "completion":
|
|
222
|
+
return metrics.performance.uptime > alert.threshold;
|
|
223
|
+
default:
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
getMetricValue(condition, metrics) {
|
|
228
|
+
if (condition.includes("throughput")) return metrics.performance.throughput;
|
|
229
|
+
if (condition.includes("efficiency")) return metrics.performance.efficiency;
|
|
230
|
+
if (condition.includes("memory")) return metrics.resourceUsage.memoryMB;
|
|
231
|
+
if (condition.includes("uptime")) return metrics.performance.uptime;
|
|
232
|
+
return 0;
|
|
233
|
+
}
|
|
234
|
+
getActiveAlerts() {
|
|
235
|
+
return [];
|
|
236
|
+
}
|
|
237
|
+
estimateCpuUsage() {
|
|
238
|
+
const activeAgents = this.collectAgentMetrics().filter(
|
|
239
|
+
(a) => a.status === "active"
|
|
240
|
+
).length;
|
|
241
|
+
return Math.min(activeAgents * 15, 100);
|
|
242
|
+
}
|
|
243
|
+
estimateDiskUsage() {
|
|
244
|
+
const usage = this.swarmCoordinator.getResourceUsage();
|
|
245
|
+
return usage.workingDirectories.length * 10;
|
|
246
|
+
}
|
|
247
|
+
setupDefaultAlerts() {
|
|
248
|
+
this.alerts = [
|
|
249
|
+
{
|
|
250
|
+
id: "low-throughput",
|
|
251
|
+
type: "performance",
|
|
252
|
+
condition: "throughput < 0.5",
|
|
253
|
+
threshold: 0.5,
|
|
254
|
+
message: "Low throughput detected: Less than 0.5 tasks per minute",
|
|
255
|
+
severity: "medium"
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
id: "high-memory",
|
|
259
|
+
type: "resource",
|
|
260
|
+
condition: "memory > 500",
|
|
261
|
+
threshold: 500,
|
|
262
|
+
message: "High memory usage detected: Over 500MB",
|
|
263
|
+
severity: "high"
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
id: "long-running",
|
|
267
|
+
type: "completion",
|
|
268
|
+
condition: "uptime > 1800000",
|
|
269
|
+
threshold: 18e5,
|
|
270
|
+
// 30 minutes
|
|
271
|
+
message: "Long running swarm detected: Over 30 minutes",
|
|
272
|
+
severity: "low"
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
id: "low-efficiency",
|
|
276
|
+
type: "error",
|
|
277
|
+
condition: "errorRate > 0.3",
|
|
278
|
+
threshold: 0.3,
|
|
279
|
+
message: "High error rate detected: Over 30% failure rate",
|
|
280
|
+
severity: "critical"
|
|
281
|
+
}
|
|
282
|
+
];
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
var swarm_dashboard_default = SwarmDashboard;
|
|
286
|
+
export {
|
|
287
|
+
SwarmDashboard,
|
|
288
|
+
swarm_dashboard_default as default
|
|
289
|
+
};
|
|
290
|
+
//# sourceMappingURL=swarm-dashboard.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/integrations/ralph/monitoring/swarm-dashboard.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Real-time Swarm Monitoring Dashboard\n * Provides live metrics and visualization for active swarms\n */\n\nimport { EventEmitter } from 'events';\nimport { logger } from '../../../core/monitoring/logger.js';\nimport { SwarmCoordinator } from '../swarm/swarm-coordinator.js';\nimport { Agent, SwarmState } from '../types.js';\n\nexport interface SwarmMetrics {\n swarmId: string;\n status: 'active' | 'idle' | 'completed' | 'error';\n totalAgents: number;\n activeAgents: number;\n completedTasks: number;\n activeTasks: number;\n averageTaskTime: number;\n resourceUsage: {\n memoryMB: number;\n cpuPercent: number;\n diskMB: number;\n };\n performance: {\n throughput: number; // tasks per minute\n efficiency: number; // completion rate\n uptime: number; // milliseconds\n };\n agents: AgentMetrics[];\n}\n\nexport interface AgentMetrics {\n id: string;\n role: string;\n status: 'active' | 'idle' | 'error' | 'completed';\n currentTask?: string;\n tasksCompleted: number;\n averageTaskTime: number;\n successRate: number;\n lastActivity: number;\n resourceUsage: {\n memoryMB: number;\n iterations: number;\n };\n}\n\nexport interface AlertRule {\n id: string;\n type: 'performance' | 'error' | 'resource' | 'completion';\n condition: string; // e.g., \"throughput < 0.5\" or \"errorRate > 0.1\"\n threshold: number;\n message: string;\n severity: 'low' | 'medium' | 'high' | 'critical';\n}\n\nexport class SwarmDashboard extends EventEmitter {\n private metrics: Map<string, SwarmMetrics> = new Map();\n private alerts: AlertRule[] = [];\n private monitoringInterval?: NodeJS.Timeout;\n private swarmCoordinator: SwarmCoordinator;\n\n constructor(swarmCoordinator: SwarmCoordinator) {\n super();\n this.swarmCoordinator = swarmCoordinator;\n this.setupDefaultAlerts();\n }\n\n /**\n * Start real-time monitoring\n */\n startMonitoring(intervalMs: number = 5000): void {\n this.monitoringInterval = setInterval(() => {\n this.collectMetrics();\n this.checkAlerts();\n }, intervalMs);\n\n logger.info('Swarm monitoring dashboard started');\n }\n\n /**\n * Stop monitoring\n */\n stopMonitoring(): void {\n if (this.monitoringInterval) {\n clearInterval(this.monitoringInterval);\n this.monitoringInterval = undefined;\n }\n logger.info('Swarm monitoring dashboard stopped');\n }\n\n /**\n * Get current metrics for a swarm\n */\n getSwarmMetrics(swarmId: string): SwarmMetrics | undefined {\n return this.metrics.get(swarmId);\n }\n\n /**\n * Get all active swarm metrics\n */\n getAllMetrics(): SwarmMetrics[] {\n return Array.from(this.metrics.values());\n }\n\n /**\n * Add custom alert rule\n */\n addAlert(rule: AlertRule): void {\n this.alerts.push(rule);\n logger.info(`Added alert rule: ${rule.id}`);\n }\n\n /**\n * Generate real-time dashboard HTML\n */\n generateDashboardHTML(): string {\n const metrics = this.getAllMetrics();\n\n return `\n<!DOCTYPE html>\n<html>\n<head>\n <title>Ralph Swarm Dashboard</title>\n <style>\n body { font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }\n .dashboard { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }\n .card { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }\n .metric { display: flex; justify-content: space-between; margin: 10px 0; }\n .status-active { color: #28a745; }\n .status-error { color: #dc3545; }\n .status-idle { color: #6c757d; }\n .alert-critical { color: #dc3545; font-weight: bold; }\n .progress { background: #e9ecef; border-radius: 4px; height: 8px; }\n .progress-bar { background: #007bff; height: 100%; border-radius: 4px; }\n </style>\n <script>\n setTimeout(() => location.reload(), 5000); // Auto-refresh\n </script>\n</head>\n<body>\n <h1>\uD83E\uDDBE Ralph Swarm Dashboard</h1>\n <div class=\"dashboard\">\n ${metrics\n .map(\n (swarm) => `\n <div class=\"card\">\n <h3>Swarm ${swarm.swarmId.substring(0, 8)}</h3>\n <div class=\"metric\">\n <span>Status:</span>\n <span class=\"status-${swarm.status}\">${swarm.status.toUpperCase()}</span>\n </div>\n <div class=\"metric\">\n <span>Agents:</span>\n <span>${swarm.activeAgents}/${swarm.totalAgents}</span>\n </div>\n <div class=\"metric\">\n <span>Tasks:</span>\n <span>${swarm.completedTasks}/${swarm.activeTasks + swarm.completedTasks}</span>\n </div>\n <div class=\"metric\">\n <span>Throughput:</span>\n <span>${swarm.performance.throughput.toFixed(2)} tasks/min</span>\n </div>\n <div class=\"metric\">\n <span>Memory:</span>\n <span>${swarm.resourceUsage.memoryMB} MB</span>\n </div>\n <div class=\"metric\">\n <span>Uptime:</span>\n <span>${Math.round(swarm.performance.uptime / 1000)}s</span>\n </div>\n <div style=\"margin-top: 15px;\">\n <h4>Agents:</h4>\n ${swarm.agents\n .map(\n (agent) => `\n <div class=\"metric\">\n <span>${agent.role}:</span>\n <span class=\"status-${agent.status}\">${agent.status}</span>\n </div>\n `\n )\n .join('')}\n </div>\n </div>\n `\n )\n .join('')}\n </div>\n \n <div class=\"card\" style=\"margin-top: 20px;\">\n <h3>\uD83D\uDEA8 Active Alerts</h3>\n <div id=\"alerts\">${this.getActiveAlerts()\n .map(\n (alert) =>\n `<div class=\"alert-${alert.severity}\">${alert.message}</div>`\n )\n .join('')}</div>\n </div>\n</body>\n</html>`;\n }\n\n /**\n * Export metrics to JSON\n */\n exportMetrics(): string {\n return JSON.stringify(\n {\n timestamp: new Date().toISOString(),\n swarms: this.getAllMetrics(),\n alerts: this.getActiveAlerts(),\n },\n null,\n 2\n );\n }\n\n private collectMetrics(): void {\n const usage = this.swarmCoordinator.getResourceUsage();\n const swarmState = (this.swarmCoordinator as any).swarmState;\n\n if (!swarmState || !swarmState.id) return;\n\n const metrics: SwarmMetrics = {\n swarmId: swarmState.id,\n status: swarmState.status,\n totalAgents: usage.activeAgents,\n activeAgents: usage.activeAgents,\n completedTasks: swarmState.completedTaskCount || 0,\n activeTasks: swarmState.activeTaskCount || 0,\n averageTaskTime: 0, // Calculate from agent metrics\n resourceUsage: {\n memoryMB: usage.memoryEstimate,\n cpuPercent: this.estimateCpuUsage(),\n diskMB: this.estimateDiskUsage(),\n },\n performance: {\n throughput: swarmState.performance?.throughput || 0,\n efficiency: swarmState.performance?.efficiency || 0,\n uptime: Date.now() - swarmState.startTime,\n },\n agents: this.collectAgentMetrics(),\n };\n\n this.metrics.set(swarmState.id, metrics);\n this.emit('metricsUpdated', metrics);\n }\n\n private collectAgentMetrics(): AgentMetrics[] {\n const agents = (this.swarmCoordinator as any).activeAgents;\n if (!agents) return [];\n\n return Array.from(agents.values()).map(\n (agent: Agent): AgentMetrics => ({\n id: agent.id,\n role: agent.role,\n status: agent.status,\n currentTask: agent.currentTask || undefined,\n tasksCompleted: agent.performance?.tasksCompleted || 0,\n averageTaskTime: agent.performance?.averageTaskTime || 0,\n successRate: agent.performance?.successRate || 1.0,\n lastActivity: agent.performance?.lastFreshStart || Date.now(),\n resourceUsage: {\n memoryMB: 50, // Estimate per agent\n iterations: agent.performance?.tasksCompleted || 0,\n },\n })\n );\n }\n\n private checkAlerts(): void {\n const metrics = this.getAllMetrics();\n\n for (const swarmMetrics of metrics) {\n for (const alert of this.alerts) {\n if (this.evaluateAlertCondition(alert, swarmMetrics)) {\n this.emit('alert', {\n ...alert,\n swarmId: swarmMetrics.swarmId,\n timestamp: Date.now(),\n value: this.getMetricValue(alert.condition, swarmMetrics),\n });\n }\n }\n }\n }\n\n private evaluateAlertCondition(\n alert: AlertRule,\n metrics: SwarmMetrics\n ): boolean {\n const value = this.getMetricValue(alert.condition, metrics);\n\n switch (alert.type) {\n case 'performance':\n return value < alert.threshold;\n case 'error':\n return 1 - metrics.performance.efficiency > alert.threshold;\n case 'resource':\n return metrics.resourceUsage.memoryMB > alert.threshold;\n case 'completion':\n return metrics.performance.uptime > alert.threshold;\n default:\n return false;\n }\n }\n\n private getMetricValue(condition: string, metrics: SwarmMetrics): number {\n // Simple metric extraction - could be enhanced with expression parser\n if (condition.includes('throughput')) return metrics.performance.throughput;\n if (condition.includes('efficiency')) return metrics.performance.efficiency;\n if (condition.includes('memory')) return metrics.resourceUsage.memoryMB;\n if (condition.includes('uptime')) return metrics.performance.uptime;\n return 0;\n }\n\n private getActiveAlerts(): any[] {\n // Return recent alerts - implementation would track alert history\n return [];\n }\n\n private estimateCpuUsage(): number {\n // Estimate CPU usage based on active agents\n const activeAgents = this.collectAgentMetrics().filter(\n (a) => a.status === 'active'\n ).length;\n return Math.min(activeAgents * 15, 100); // ~15% per active agent\n }\n\n private estimateDiskUsage(): number {\n // Estimate disk usage from working directories\n const usage = this.swarmCoordinator.getResourceUsage();\n return usage.workingDirectories.length * 10; // ~10MB per directory\n }\n\n private setupDefaultAlerts(): void {\n this.alerts = [\n {\n id: 'low-throughput',\n type: 'performance',\n condition: 'throughput < 0.5',\n threshold: 0.5,\n message: 'Low throughput detected: Less than 0.5 tasks per minute',\n severity: 'medium',\n },\n {\n id: 'high-memory',\n type: 'resource',\n condition: 'memory > 500',\n threshold: 500,\n message: 'High memory usage detected: Over 500MB',\n severity: 'high',\n },\n {\n id: 'long-running',\n type: 'completion',\n condition: 'uptime > 1800000',\n threshold: 1800000, // 30 minutes\n message: 'Long running swarm detected: Over 30 minutes',\n severity: 'low',\n },\n {\n id: 'low-efficiency',\n type: 'error',\n condition: 'errorRate > 0.3',\n threshold: 0.3,\n message: 'High error rate detected: Over 30% failure rate',\n severity: 'critical',\n },\n ];\n }\n}\n\nexport default SwarmDashboard;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
import { logger } from "../../../core/monitoring/logger.js";
|
|
3
|
+
class SwarmRegistry extends EventEmitter {
|
|
4
|
+
static instance = null;
|
|
5
|
+
swarms = /* @__PURE__ */ new Map();
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
logger.info("SwarmRegistry initialized");
|
|
9
|
+
}
|
|
10
|
+
static getInstance() {
|
|
11
|
+
if (!SwarmRegistry.instance) {
|
|
12
|
+
SwarmRegistry.instance = new SwarmRegistry();
|
|
13
|
+
}
|
|
14
|
+
return SwarmRegistry.instance;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Register a swarm coordinator
|
|
18
|
+
*/
|
|
19
|
+
registerSwarm(coordinator, description) {
|
|
20
|
+
const swarmId = this.generateSwarmId();
|
|
21
|
+
const registration = {
|
|
22
|
+
id: swarmId,
|
|
23
|
+
coordinator,
|
|
24
|
+
startTime: Date.now(),
|
|
25
|
+
status: "active",
|
|
26
|
+
description
|
|
27
|
+
};
|
|
28
|
+
this.swarms.set(swarmId, registration);
|
|
29
|
+
this.emit("swarmRegistered", registration);
|
|
30
|
+
logger.info(`Swarm registered: ${swarmId} - ${description}`);
|
|
31
|
+
return swarmId;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Unregister a swarm
|
|
35
|
+
*/
|
|
36
|
+
unregisterSwarm(swarmId) {
|
|
37
|
+
const swarm = this.swarms.get(swarmId);
|
|
38
|
+
if (swarm) {
|
|
39
|
+
this.swarms.delete(swarmId);
|
|
40
|
+
this.emit("swarmUnregistered", { id: swarmId });
|
|
41
|
+
logger.info(`Swarm unregistered: ${swarmId}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get a specific swarm by ID
|
|
46
|
+
*/
|
|
47
|
+
getSwarm(swarmId) {
|
|
48
|
+
return this.swarms.get(swarmId) || null;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* List all active swarms
|
|
52
|
+
*/
|
|
53
|
+
listActiveSwarms() {
|
|
54
|
+
return Array.from(this.swarms.values()).filter(
|
|
55
|
+
(swarm) => swarm.status === "active"
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Update swarm status
|
|
60
|
+
*/
|
|
61
|
+
updateSwarmStatus(swarmId, status) {
|
|
62
|
+
const swarm = this.swarms.get(swarmId);
|
|
63
|
+
if (swarm) {
|
|
64
|
+
swarm.status = status;
|
|
65
|
+
this.emit("swarmStatusChanged", { id: swarmId, status });
|
|
66
|
+
logger.debug(`Swarm ${swarmId} status updated: ${status}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get swarm statistics
|
|
71
|
+
*/
|
|
72
|
+
getStatistics() {
|
|
73
|
+
const active = this.listActiveSwarms();
|
|
74
|
+
const completed = Array.from(this.swarms.values()).filter((s) => s.status === "completed");
|
|
75
|
+
const totalUptime = active.reduce(
|
|
76
|
+
(sum, swarm) => sum + (Date.now() - swarm.startTime),
|
|
77
|
+
0
|
|
78
|
+
);
|
|
79
|
+
return {
|
|
80
|
+
totalSwarms: this.swarms.size,
|
|
81
|
+
activeSwarms: active.length,
|
|
82
|
+
completedSwarms: completed.length,
|
|
83
|
+
averageUptime: active.length > 0 ? totalUptime / active.length : 0
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
generateSwarmId() {
|
|
87
|
+
return `swarm_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
var swarm_registry_default = SwarmRegistry;
|
|
91
|
+
export {
|
|
92
|
+
SwarmRegistry,
|
|
93
|
+
swarm_registry_default as default
|
|
94
|
+
};
|
|
95
|
+
//# sourceMappingURL=swarm-registry.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/integrations/ralph/monitoring/swarm-registry.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Global swarm registry for tracking active swarms\n * Allows TUI to connect to running swarms\n */\n\nimport { EventEmitter } from 'events';\nimport { SwarmCoordinator } from '../swarm/swarm-coordinator.js';\nimport { logger } from '../../../core/monitoring/logger.js';\n\nexport interface RegisteredSwarm {\n id: string;\n coordinator: SwarmCoordinator;\n startTime: number;\n status: 'active' | 'idle' | 'completed' | 'error';\n description: string;\n}\n\nexport class SwarmRegistry extends EventEmitter {\n private static instance: SwarmRegistry | null = null;\n private swarms: Map<string, RegisteredSwarm> = new Map();\n \n private constructor() {\n super();\n logger.info('SwarmRegistry initialized');\n }\n\n static getInstance(): SwarmRegistry {\n if (!SwarmRegistry.instance) {\n SwarmRegistry.instance = new SwarmRegistry();\n }\n return SwarmRegistry.instance;\n }\n\n /**\n * Register a swarm coordinator\n */\n registerSwarm(coordinator: SwarmCoordinator, description: string): string {\n const swarmId = this.generateSwarmId();\n \n const registration: RegisteredSwarm = {\n id: swarmId,\n coordinator,\n startTime: Date.now(),\n status: 'active',\n description\n };\n \n this.swarms.set(swarmId, registration);\n this.emit('swarmRegistered', registration);\n \n logger.info(`Swarm registered: ${swarmId} - ${description}`);\n return swarmId;\n }\n\n /**\n * Unregister a swarm\n */\n unregisterSwarm(swarmId: string): void {\n const swarm = this.swarms.get(swarmId);\n if (swarm) {\n this.swarms.delete(swarmId);\n this.emit('swarmUnregistered', { id: swarmId });\n logger.info(`Swarm unregistered: ${swarmId}`);\n }\n }\n\n /**\n * Get a specific swarm by ID\n */\n getSwarm(swarmId: string): RegisteredSwarm | null {\n return this.swarms.get(swarmId) || null;\n }\n\n /**\n * List all active swarms\n */\n listActiveSwarms(): RegisteredSwarm[] {\n return Array.from(this.swarms.values()).filter(\n swarm => swarm.status === 'active'\n );\n }\n\n /**\n * Update swarm status\n */\n updateSwarmStatus(swarmId: string, status: 'active' | 'idle' | 'completed' | 'error'): void {\n const swarm = this.swarms.get(swarmId);\n if (swarm) {\n swarm.status = status;\n this.emit('swarmStatusChanged', { id: swarmId, status });\n logger.debug(`Swarm ${swarmId} status updated: ${status}`);\n }\n }\n\n /**\n * Get swarm statistics\n */\n getStatistics(): {\n totalSwarms: number;\n activeSwarms: number;\n completedSwarms: number;\n averageUptime: number;\n } {\n const active = this.listActiveSwarms();\n const completed = Array.from(this.swarms.values()).filter(s => s.status === 'completed');\n \n const totalUptime = active.reduce((sum, swarm) => \n sum + (Date.now() - swarm.startTime), 0\n );\n \n return {\n totalSwarms: this.swarms.size,\n activeSwarms: active.length,\n completedSwarms: completed.length,\n averageUptime: active.length > 0 ? totalUptime / active.length : 0\n };\n }\n\n private generateSwarmId(): string {\n return `swarm_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;\n }\n}\n\nexport default SwarmRegistry;"],
|
|
5
|
+
"mappings": "AAKA,SAAS,oBAAoB;AAE7B,SAAS,cAAc;AAUhB,MAAM,sBAAsB,aAAa;AAAA,EAC9C,OAAe,WAAiC;AAAA,EACxC,SAAuC,oBAAI,IAAI;AAAA,EAE/C,cAAc;AACpB,UAAM;AACN,WAAO,KAAK,2BAA2B;AAAA,EACzC;AAAA,EAEA,OAAO,cAA6B;AAClC,QAAI,CAAC,cAAc,UAAU;AAC3B,oBAAc,WAAW,IAAI,cAAc;AAAA,IAC7C;AACA,WAAO,cAAc;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,aAA+B,aAA6B;AACxE,UAAM,UAAU,KAAK,gBAAgB;AAErC,UAAM,eAAgC;AAAA,MACpC,IAAI;AAAA,MACJ;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,MACpB,QAAQ;AAAA,MACR;AAAA,IACF;AAEA,SAAK,OAAO,IAAI,SAAS,YAAY;AACrC,SAAK,KAAK,mBAAmB,YAAY;AAEzC,WAAO,KAAK,qBAAqB,OAAO,MAAM,WAAW,EAAE;AAC3D,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,SAAuB;AACrC,UAAM,QAAQ,KAAK,OAAO,IAAI,OAAO;AACrC,QAAI,OAAO;AACT,WAAK,OAAO,OAAO,OAAO;AAC1B,WAAK,KAAK,qBAAqB,EAAE,IAAI,QAAQ,CAAC;AAC9C,aAAO,KAAK,uBAAuB,OAAO,EAAE;AAAA,IAC9C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,SAAyC;AAChD,WAAO,KAAK,OAAO,IAAI,OAAO,KAAK;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAsC;AACpC,WAAO,MAAM,KAAK,KAAK,OAAO,OAAO,CAAC,EAAE;AAAA,MACtC,WAAS,MAAM,WAAW;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB,SAAiB,QAAyD;AAC1F,UAAM,QAAQ,KAAK,OAAO,IAAI,OAAO;AACrC,QAAI,OAAO;AACT,YAAM,SAAS;AACf,WAAK,KAAK,sBAAsB,EAAE,IAAI,SAAS,OAAO,CAAC;AACvD,aAAO,MAAM,SAAS,OAAO,oBAAoB,MAAM,EAAE;AAAA,IAC3D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,gBAKE;AACA,UAAM,SAAS,KAAK,iBAAiB;AACrC,UAAM,YAAY,MAAM,KAAK,KAAK,OAAO,OAAO,CAAC,EAAE,OAAO,OAAK,EAAE,WAAW,WAAW;AAEvF,UAAM,cAAc,OAAO;AAAA,MAAO,CAAC,KAAK,UACtC,OAAO,KAAK,IAAI,IAAI,MAAM;AAAA,MAAY;AAAA,IACxC;AAEA,WAAO;AAAA,MACL,aAAa,KAAK,OAAO;AAAA,MACzB,cAAc,OAAO;AAAA,MACrB,iBAAiB,UAAU;AAAA,MAC3B,eAAe,OAAO,SAAS,IAAI,cAAc,OAAO,SAAS;AAAA,IACnE;AAAA,EACF;AAAA,EAEQ,kBAA0B;AAChC,WAAO,SAAS,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,CAAC,CAAC;AAAA,EAC1E;AACF;AAEA,IAAO,yBAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|