claude-mpm 3.4.3__py3-none-any.whl → 3.4.5__py3-none-any.whl
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.
- claude_mpm/agents/INSTRUCTIONS.md +20 -3
- claude_mpm/agents/backups/INSTRUCTIONS.md +119 -5
- claude_mpm/cli/__init__.py +3 -1
- claude_mpm/cli/commands/__init__.py +3 -1
- claude_mpm/cli/commands/monitor.py +328 -0
- claude_mpm/cli/commands/run.py +9 -17
- claude_mpm/cli/parser.py +69 -1
- claude_mpm/constants.py +9 -0
- claude_mpm/ticket_wrapper.py +29 -0
- {claude_mpm-3.4.3.dist-info → claude_mpm-3.4.5.dist-info}/METADATA +1 -1
- {claude_mpm-3.4.3.dist-info → claude_mpm-3.4.5.dist-info}/RECORD +15 -23
- claude_mpm/scripts/__init__.py +0 -1
- claude_mpm/scripts/claude-mpm-socketio +0 -32
- claude_mpm/scripts/claude_mpm_monitor.html +0 -567
- claude_mpm/scripts/install_socketio_server.py +0 -407
- claude_mpm/scripts/launch_monitor.py +0 -132
- claude_mpm/scripts/launch_socketio_dashboard.py +0 -261
- claude_mpm/scripts/manage_version.py +0 -479
- claude_mpm/scripts/socketio_daemon.py +0 -221
- claude_mpm/scripts/socketio_server_manager.py +0 -753
- claude_mpm/scripts/ticket.py +0 -269
- {claude_mpm-3.4.3.dist-info → claude_mpm-3.4.5.dist-info}/WHEEL +0 -0
- {claude_mpm-3.4.3.dist-info → claude_mpm-3.4.5.dist-info}/entry_points.txt +0 -0
- {claude_mpm-3.4.3.dist-info → claude_mpm-3.4.5.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-3.4.3.dist-info → claude_mpm-3.4.5.dist-info}/top_level.txt +0 -0
|
@@ -1,567 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>Claude MPM Monitor</title>
|
|
7
|
-
<script src="https://cdn.socket.io/4.7.2/socket.io.min.js"></script>
|
|
8
|
-
<style>
|
|
9
|
-
* {
|
|
10
|
-
box-sizing: border-box;
|
|
11
|
-
margin: 0;
|
|
12
|
-
padding: 0;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
body {
|
|
16
|
-
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
17
|
-
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
18
|
-
min-height: 100vh;
|
|
19
|
-
padding: 20px;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.container {
|
|
23
|
-
max-width: 1400px;
|
|
24
|
-
margin: 0 auto;
|
|
25
|
-
background: rgba(255, 255, 255, 0.95);
|
|
26
|
-
border-radius: 15px;
|
|
27
|
-
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
|
28
|
-
overflow: hidden;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
.header {
|
|
32
|
-
background: linear-gradient(135deg, #4a90e2 0%, #357abd 100%);
|
|
33
|
-
color: white;
|
|
34
|
-
padding: 30px;
|
|
35
|
-
text-align: center;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.header h1 {
|
|
39
|
-
font-size: 2.5rem;
|
|
40
|
-
margin-bottom: 10px;
|
|
41
|
-
font-weight: 300;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
.header p {
|
|
45
|
-
font-size: 1.1rem;
|
|
46
|
-
opacity: 0.9;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.connection-panel {
|
|
50
|
-
background: #f8f9fa;
|
|
51
|
-
border-bottom: 1px solid #e9ecef;
|
|
52
|
-
padding: 20px 30px;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
.connection-controls {
|
|
56
|
-
display: flex;
|
|
57
|
-
align-items: center;
|
|
58
|
-
gap: 15px;
|
|
59
|
-
flex-wrap: wrap;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
.connection-controls label {
|
|
63
|
-
font-weight: 600;
|
|
64
|
-
color: #495057;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
.connection-controls input {
|
|
68
|
-
padding: 8px 12px;
|
|
69
|
-
border: 2px solid #dee2e6;
|
|
70
|
-
border-radius: 6px;
|
|
71
|
-
font-size: 14px;
|
|
72
|
-
width: 100px;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
.connection-controls button {
|
|
76
|
-
padding: 8px 20px;
|
|
77
|
-
border: none;
|
|
78
|
-
border-radius: 6px;
|
|
79
|
-
font-weight: 600;
|
|
80
|
-
cursor: pointer;
|
|
81
|
-
transition: all 0.3s ease;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
.btn-connect {
|
|
85
|
-
background: #28a745;
|
|
86
|
-
color: white;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
.btn-connect:hover {
|
|
90
|
-
background: #218838;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
.btn-disconnect {
|
|
94
|
-
background: #dc3545;
|
|
95
|
-
color: white;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
.btn-disconnect:hover {
|
|
99
|
-
background: #c82333;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
.status {
|
|
103
|
-
margin-left: auto;
|
|
104
|
-
padding: 6px 12px;
|
|
105
|
-
border-radius: 20px;
|
|
106
|
-
font-weight: 600;
|
|
107
|
-
font-size: 14px;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
.status.connected {
|
|
111
|
-
background: #d4edda;
|
|
112
|
-
color: #155724;
|
|
113
|
-
border: 1px solid #c3e6cb;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.status.disconnected {
|
|
117
|
-
background: #f8d7da;
|
|
118
|
-
color: #721c24;
|
|
119
|
-
border: 1px solid #f5c6cb;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
.status.connecting {
|
|
123
|
-
background: #fff3cd;
|
|
124
|
-
color: #856404;
|
|
125
|
-
border: 1px solid #ffeaa7;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
.main-content {
|
|
129
|
-
display: grid;
|
|
130
|
-
grid-template-columns: 1fr 1fr;
|
|
131
|
-
gap: 30px;
|
|
132
|
-
padding: 30px;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
.panel {
|
|
136
|
-
background: white;
|
|
137
|
-
border-radius: 10px;
|
|
138
|
-
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
|
|
139
|
-
overflow: hidden;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
.panel-header {
|
|
143
|
-
background: #f8f9fa;
|
|
144
|
-
border-bottom: 1px solid #e9ecef;
|
|
145
|
-
padding: 15px 20px;
|
|
146
|
-
font-weight: 600;
|
|
147
|
-
color: #495057;
|
|
148
|
-
display: flex;
|
|
149
|
-
justify-content: between;
|
|
150
|
-
align-items: center;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
.panel-content {
|
|
154
|
-
padding: 20px;
|
|
155
|
-
max-height: 400px;
|
|
156
|
-
overflow-y: auto;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
.event-log {
|
|
160
|
-
font-family: 'Courier New', monospace;
|
|
161
|
-
font-size: 13px;
|
|
162
|
-
line-height: 1.4;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
.event-item {
|
|
166
|
-
margin-bottom: 10px;
|
|
167
|
-
padding: 8px;
|
|
168
|
-
border-radius: 4px;
|
|
169
|
-
border-left: 4px solid #6c757d;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
.event-item.hook {
|
|
173
|
-
border-left-color: #28a745;
|
|
174
|
-
background: #f8fff9;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
.event-item.memory {
|
|
178
|
-
border-left-color: #007bff;
|
|
179
|
-
background: #f8f9ff;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
.event-item.system {
|
|
183
|
-
border-left-color: #ffc107;
|
|
184
|
-
background: #fffdf8;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
.event-item.error {
|
|
188
|
-
border-left-color: #dc3545;
|
|
189
|
-
background: #fff8f8;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
.event-timestamp {
|
|
193
|
-
color: #6c757d;
|
|
194
|
-
font-size: 11px;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
.event-type {
|
|
198
|
-
font-weight: bold;
|
|
199
|
-
color: #495057;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
.event-data {
|
|
203
|
-
margin-top: 4px;
|
|
204
|
-
color: #6c757d;
|
|
205
|
-
white-space: pre-wrap;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
.memory-item {
|
|
209
|
-
margin-bottom: 15px;
|
|
210
|
-
padding: 12px;
|
|
211
|
-
border: 1px solid #e9ecef;
|
|
212
|
-
border-radius: 6px;
|
|
213
|
-
background: #f8f9fa;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
.memory-agent {
|
|
217
|
-
font-weight: bold;
|
|
218
|
-
color: #495057;
|
|
219
|
-
margin-bottom: 5px;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
.memory-data {
|
|
223
|
-
font-family: 'Courier New', monospace;
|
|
224
|
-
font-size: 13px;
|
|
225
|
-
color: #6c757d;
|
|
226
|
-
white-space: pre-wrap;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
.stats-grid {
|
|
230
|
-
display: grid;
|
|
231
|
-
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
232
|
-
gap: 15px;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
.stat-card {
|
|
236
|
-
background: #f8f9fa;
|
|
237
|
-
padding: 15px;
|
|
238
|
-
border-radius: 8px;
|
|
239
|
-
text-align: center;
|
|
240
|
-
border: 1px solid #e9ecef;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
.stat-value {
|
|
244
|
-
font-size: 2rem;
|
|
245
|
-
font-weight: bold;
|
|
246
|
-
color: #495057;
|
|
247
|
-
margin-bottom: 5px;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
.stat-label {
|
|
251
|
-
color: #6c757d;
|
|
252
|
-
font-size: 14px;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
.clear-btn {
|
|
256
|
-
background: #6c757d;
|
|
257
|
-
color: white;
|
|
258
|
-
border: none;
|
|
259
|
-
padding: 5px 10px;
|
|
260
|
-
border-radius: 4px;
|
|
261
|
-
font-size: 12px;
|
|
262
|
-
cursor: pointer;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
.clear-btn:hover {
|
|
266
|
-
background: #545b62;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
@media (max-width: 768px) {
|
|
270
|
-
.main-content {
|
|
271
|
-
grid-template-columns: 1fr;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
.connection-controls {
|
|
275
|
-
flex-direction: column;
|
|
276
|
-
align-items: stretch;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
.connection-controls input,
|
|
280
|
-
.connection-controls button {
|
|
281
|
-
width: 100%;
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
.full-width {
|
|
286
|
-
grid-column: 1 / -1;
|
|
287
|
-
}
|
|
288
|
-
</style>
|
|
289
|
-
</head>
|
|
290
|
-
<body>
|
|
291
|
-
<div class="container">
|
|
292
|
-
<div class="header">
|
|
293
|
-
<h1>Claude MPM Monitor</h1>
|
|
294
|
-
<p>Real-time monitoring of agent activities, memory operations, and hook events</p>
|
|
295
|
-
</div>
|
|
296
|
-
|
|
297
|
-
<div class="connection-panel">
|
|
298
|
-
<div class="connection-controls">
|
|
299
|
-
<label for="port">Server Port:</label>
|
|
300
|
-
<input type="number" id="port" value="8765" min="1" max="65535">
|
|
301
|
-
|
|
302
|
-
<button id="connectBtn" class="btn-connect">Connect</button>
|
|
303
|
-
<button id="disconnectBtn" class="btn-disconnect" style="display: none;">Disconnect</button>
|
|
304
|
-
|
|
305
|
-
<div id="status" class="status disconnected">Disconnected</div>
|
|
306
|
-
</div>
|
|
307
|
-
</div>
|
|
308
|
-
|
|
309
|
-
<div class="main-content">
|
|
310
|
-
<div class="panel">
|
|
311
|
-
<div class="panel-header">
|
|
312
|
-
Event Log
|
|
313
|
-
<button class="clear-btn" onclick="clearEvents()">Clear</button>
|
|
314
|
-
</div>
|
|
315
|
-
<div class="panel-content">
|
|
316
|
-
<div id="eventLog" class="event-log"></div>
|
|
317
|
-
</div>
|
|
318
|
-
</div>
|
|
319
|
-
|
|
320
|
-
<div class="panel">
|
|
321
|
-
<div class="panel-header">
|
|
322
|
-
Connection Statistics
|
|
323
|
-
</div>
|
|
324
|
-
<div class="panel-content">
|
|
325
|
-
<div class="stats-grid">
|
|
326
|
-
<div class="stat-card">
|
|
327
|
-
<div id="totalEvents" class="stat-value">0</div>
|
|
328
|
-
<div class="stat-label">Total Events</div>
|
|
329
|
-
</div>
|
|
330
|
-
<div class="stat-card">
|
|
331
|
-
<div id="hookEvents" class="stat-value">0</div>
|
|
332
|
-
<div class="stat-label">Hook Events</div>
|
|
333
|
-
</div>
|
|
334
|
-
<div class="stat-card">
|
|
335
|
-
<div id="memoryEvents" class="stat-value">0</div>
|
|
336
|
-
<div class="stat-label">Memory Events</div>
|
|
337
|
-
</div>
|
|
338
|
-
<div class="stat-card">
|
|
339
|
-
<div id="uptime" class="stat-value">00:00</div>
|
|
340
|
-
<div class="stat-label">Connected Time</div>
|
|
341
|
-
</div>
|
|
342
|
-
</div>
|
|
343
|
-
</div>
|
|
344
|
-
</div>
|
|
345
|
-
|
|
346
|
-
<div class="panel full-width">
|
|
347
|
-
<div class="panel-header">
|
|
348
|
-
Agent Memory States
|
|
349
|
-
<button class="clear-btn" onclick="clearMemory()">Clear</button>
|
|
350
|
-
</div>
|
|
351
|
-
<div class="panel-content">
|
|
352
|
-
<div id="memoryLog"></div>
|
|
353
|
-
</div>
|
|
354
|
-
</div>
|
|
355
|
-
</div>
|
|
356
|
-
</div>
|
|
357
|
-
|
|
358
|
-
<script>
|
|
359
|
-
let socket = null;
|
|
360
|
-
let isConnected = false;
|
|
361
|
-
let connectionStartTime = null;
|
|
362
|
-
let uptimeInterval = null;
|
|
363
|
-
let stats = {
|
|
364
|
-
totalEvents: 0,
|
|
365
|
-
hookEvents: 0,
|
|
366
|
-
memoryEvents: 0
|
|
367
|
-
};
|
|
368
|
-
|
|
369
|
-
// Parse URL parameters
|
|
370
|
-
const urlParams = new URLSearchParams(window.location.search);
|
|
371
|
-
const defaultPort = urlParams.get('port') || '8765';
|
|
372
|
-
document.getElementById('port').value = defaultPort;
|
|
373
|
-
|
|
374
|
-
// Auto-connect if port is provided in URL
|
|
375
|
-
if (urlParams.get('port')) {
|
|
376
|
-
setTimeout(() => connect(), 500);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
function connect() {
|
|
380
|
-
const port = document.getElementById('port').value;
|
|
381
|
-
const serverUrl = `http://localhost:${port}`;
|
|
382
|
-
|
|
383
|
-
updateStatus('connecting', 'Connecting...');
|
|
384
|
-
|
|
385
|
-
socket = io(serverUrl, {
|
|
386
|
-
transports: ['websocket', 'polling'],
|
|
387
|
-
timeout: 10000,
|
|
388
|
-
forceNew: true,
|
|
389
|
-
reconnection: true,
|
|
390
|
-
reconnectionDelay: 1000,
|
|
391
|
-
reconnectionDelayMax: 10000,
|
|
392
|
-
maxReconnectionAttempts: 10
|
|
393
|
-
});
|
|
394
|
-
|
|
395
|
-
socket.on('connect', () => {
|
|
396
|
-
isConnected = true;
|
|
397
|
-
connectionStartTime = Date.now();
|
|
398
|
-
updateStatus('connected', `Connected to ${serverUrl}`);
|
|
399
|
-
startUptimeTimer();
|
|
400
|
-
|
|
401
|
-
document.getElementById('connectBtn').style.display = 'none';
|
|
402
|
-
document.getElementById('disconnectBtn').style.display = 'inline-block';
|
|
403
|
-
|
|
404
|
-
addEvent('system', 'Connected to server', { port, url: serverUrl });
|
|
405
|
-
});
|
|
406
|
-
|
|
407
|
-
socket.on('disconnect', (reason) => {
|
|
408
|
-
isConnected = false;
|
|
409
|
-
updateStatus('disconnected', `Disconnected: ${reason}`);
|
|
410
|
-
stopUptimeTimer();
|
|
411
|
-
|
|
412
|
-
document.getElementById('connectBtn').style.display = 'inline-block';
|
|
413
|
-
document.getElementById('disconnectBtn').style.display = 'none';
|
|
414
|
-
|
|
415
|
-
addEvent('system', 'Disconnected from server', { reason });
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
socket.on('connect_error', (error) => {
|
|
419
|
-
updateStatus('disconnected', `Connection failed: ${error.message}`);
|
|
420
|
-
addEvent('error', 'Connection failed', { error: error.message });
|
|
421
|
-
|
|
422
|
-
document.getElementById('connectBtn').style.display = 'inline-block';
|
|
423
|
-
document.getElementById('disconnectBtn').style.display = 'none';
|
|
424
|
-
});
|
|
425
|
-
|
|
426
|
-
// Listen for all events
|
|
427
|
-
socket.onAny((eventName, data) => {
|
|
428
|
-
if (['connect', 'disconnect', 'connect_error'].includes(eventName)) {
|
|
429
|
-
return; // Skip connection events, already handled
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
let eventType = 'system';
|
|
433
|
-
if (eventName.includes('hook')) {
|
|
434
|
-
eventType = 'hook';
|
|
435
|
-
stats.hookEvents++;
|
|
436
|
-
} else if (eventName.includes('memory')) {
|
|
437
|
-
eventType = 'memory';
|
|
438
|
-
stats.memoryEvents++;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
stats.totalEvents++;
|
|
442
|
-
updateStats();
|
|
443
|
-
|
|
444
|
-
addEvent(eventType, eventName, data);
|
|
445
|
-
|
|
446
|
-
// Update memory display for memory events
|
|
447
|
-
if (eventType === 'memory' && data) {
|
|
448
|
-
updateMemoryDisplay(data);
|
|
449
|
-
}
|
|
450
|
-
});
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
function disconnect() {
|
|
454
|
-
if (socket) {
|
|
455
|
-
socket.disconnect();
|
|
456
|
-
socket = null;
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
function updateStatus(type, message) {
|
|
461
|
-
const statusEl = document.getElementById('status');
|
|
462
|
-
statusEl.className = `status ${type}`;
|
|
463
|
-
statusEl.textContent = message;
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
function addEvent(type, name, data) {
|
|
467
|
-
const eventLog = document.getElementById('eventLog');
|
|
468
|
-
const eventItem = document.createElement('div');
|
|
469
|
-
eventItem.className = `event-item ${type}`;
|
|
470
|
-
|
|
471
|
-
const timestamp = new Date().toLocaleTimeString();
|
|
472
|
-
const dataStr = data ? JSON.stringify(data, null, 2) : '';
|
|
473
|
-
|
|
474
|
-
eventItem.innerHTML = `
|
|
475
|
-
<div class="event-timestamp">[${timestamp}]</div>
|
|
476
|
-
<div class="event-type">${name}</div>
|
|
477
|
-
${dataStr ? `<div class="event-data">${dataStr}</div>` : ''}
|
|
478
|
-
`;
|
|
479
|
-
|
|
480
|
-
eventLog.insertBefore(eventItem, eventLog.firstChild);
|
|
481
|
-
|
|
482
|
-
// Keep only last 100 events
|
|
483
|
-
while (eventLog.children.length > 100) {
|
|
484
|
-
eventLog.removeChild(eventLog.lastChild);
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
function updateMemoryDisplay(data) {
|
|
489
|
-
const memoryLog = document.getElementById('memoryLog');
|
|
490
|
-
|
|
491
|
-
if (data.agent && data.memory) {
|
|
492
|
-
// Find existing memory item for this agent or create new one
|
|
493
|
-
let memoryItem = memoryLog.querySelector(`[data-agent="${data.agent}"]`);
|
|
494
|
-
if (!memoryItem) {
|
|
495
|
-
memoryItem = document.createElement('div');
|
|
496
|
-
memoryItem.className = 'memory-item';
|
|
497
|
-
memoryItem.setAttribute('data-agent', data.agent);
|
|
498
|
-
memoryLog.appendChild(memoryItem);
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
const timestamp = new Date().toLocaleTimeString();
|
|
502
|
-
memoryItem.innerHTML = `
|
|
503
|
-
<div class="memory-agent">${data.agent} <span style="font-size: 12px; color: #6c757d;">[${timestamp}]</span></div>
|
|
504
|
-
<div class="memory-data">${JSON.stringify(data.memory, null, 2)}</div>
|
|
505
|
-
`;
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
function updateStats() {
|
|
510
|
-
document.getElementById('totalEvents').textContent = stats.totalEvents;
|
|
511
|
-
document.getElementById('hookEvents').textContent = stats.hookEvents;
|
|
512
|
-
document.getElementById('memoryEvents').textContent = stats.memoryEvents;
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
function startUptimeTimer() {
|
|
516
|
-
if (uptimeInterval) {
|
|
517
|
-
clearInterval(uptimeInterval);
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
uptimeInterval = setInterval(() => {
|
|
521
|
-
if (connectionStartTime) {
|
|
522
|
-
const uptime = Date.now() - connectionStartTime;
|
|
523
|
-
const minutes = Math.floor(uptime / 60000);
|
|
524
|
-
const seconds = Math.floor((uptime % 60000) / 1000);
|
|
525
|
-
document.getElementById('uptime').textContent =
|
|
526
|
-
`${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
|
527
|
-
}
|
|
528
|
-
}, 1000);
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
function stopUptimeTimer() {
|
|
532
|
-
if (uptimeInterval) {
|
|
533
|
-
clearInterval(uptimeInterval);
|
|
534
|
-
uptimeInterval = null;
|
|
535
|
-
}
|
|
536
|
-
document.getElementById('uptime').textContent = '00:00';
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
function clearEvents() {
|
|
540
|
-
document.getElementById('eventLog').innerHTML = '';
|
|
541
|
-
stats = { totalEvents: 0, hookEvents: 0, memoryEvents: 0 };
|
|
542
|
-
updateStats();
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
function clearMemory() {
|
|
546
|
-
document.getElementById('memoryLog').innerHTML = '';
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
// Event listeners
|
|
550
|
-
document.getElementById('connectBtn').addEventListener('click', connect);
|
|
551
|
-
document.getElementById('disconnectBtn').addEventListener('click', disconnect);
|
|
552
|
-
|
|
553
|
-
document.getElementById('port').addEventListener('keypress', (e) => {
|
|
554
|
-
if (e.key === 'Enter') {
|
|
555
|
-
connect();
|
|
556
|
-
}
|
|
557
|
-
});
|
|
558
|
-
|
|
559
|
-
// Cleanup on page unload
|
|
560
|
-
window.addEventListener('beforeunload', () => {
|
|
561
|
-
if (socket) {
|
|
562
|
-
socket.disconnect();
|
|
563
|
-
}
|
|
564
|
-
});
|
|
565
|
-
</script>
|
|
566
|
-
</body>
|
|
567
|
-
</html>
|