claude-mpm 4.2.44__py3-none-any.whl → 4.2.51__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.
Files changed (148) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_PM.md +43 -1
  3. claude_mpm/agents/INSTRUCTIONS.md +75 -1
  4. claude_mpm/agents/WORKFLOW.md +46 -1
  5. claude_mpm/agents/frontmatter_validator.py +20 -12
  6. claude_mpm/agents/templates/nextjs_engineer.json +277 -0
  7. claude_mpm/agents/templates/python_engineer.json +289 -0
  8. claude_mpm/agents/templates/react_engineer.json +11 -3
  9. claude_mpm/agents/templates/security.json +50 -9
  10. claude_mpm/cli/commands/agents.py +2 -2
  11. claude_mpm/cli/commands/uninstall.py +1 -2
  12. claude_mpm/cli/interactive/agent_wizard.py +3 -3
  13. claude_mpm/cli/parsers/agent_manager_parser.py +3 -3
  14. claude_mpm/cli/parsers/agents_parser.py +1 -1
  15. claude_mpm/constants.py +1 -1
  16. claude_mpm/core/error_handler.py +2 -4
  17. claude_mpm/core/file_utils.py +4 -12
  18. claude_mpm/core/log_manager.py +8 -5
  19. claude_mpm/core/logger.py +1 -1
  20. claude_mpm/core/logging_utils.py +6 -6
  21. claude_mpm/core/unified_agent_registry.py +18 -4
  22. claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +188 -0
  23. claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +156 -0
  24. claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +38 -0
  25. claude_mpm/dashboard/react/components/shared/FilterBar.module.css +92 -0
  26. claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +248 -0
  27. claude_mpm/dashboard/static/archive/activity_dashboard_test.html +61 -0
  28. claude_mpm/dashboard/static/archive/test_activity_connection.html +179 -0
  29. claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +68 -0
  30. claude_mpm/dashboard/static/archive/test_dashboard.html +409 -0
  31. claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +519 -0
  32. claude_mpm/dashboard/static/archive/test_dashboard_verification.html +181 -0
  33. claude_mpm/dashboard/static/archive/test_file_data.html +315 -0
  34. claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +243 -0
  35. claude_mpm/dashboard/static/archive/test_file_tree_fix.html +234 -0
  36. claude_mpm/dashboard/static/archive/test_file_tree_rename.html +117 -0
  37. claude_mpm/dashboard/static/archive/test_file_tree_tab.html +115 -0
  38. claude_mpm/dashboard/static/archive/test_file_viewer.html +224 -0
  39. claude_mpm/dashboard/static/archive/test_final_activity.html +220 -0
  40. claude_mpm/dashboard/static/archive/test_tab_fix.html +139 -0
  41. claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +1 -0
  42. claude_mpm/dashboard/static/built/components/activity-tree.js +1 -1
  43. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +777 -0
  44. claude_mpm/dashboard/static/built/components/agent-inference.js +1 -1
  45. claude_mpm/dashboard/static/built/components/build-tracker.js +333 -0
  46. claude_mpm/dashboard/static/built/components/code-simple.js +857 -0
  47. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +353 -0
  48. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +235 -0
  49. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +409 -0
  50. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +435 -0
  51. claude_mpm/dashboard/static/built/components/code-viewer.js +2 -1076
  52. claude_mpm/dashboard/static/built/components/connection-debug.js +654 -0
  53. claude_mpm/dashboard/static/built/components/diff-viewer.js +891 -0
  54. claude_mpm/dashboard/static/built/components/event-processor.js +1 -1
  55. claude_mpm/dashboard/static/built/components/event-viewer.js +1 -1
  56. claude_mpm/dashboard/static/built/components/export-manager.js +1 -1
  57. claude_mpm/dashboard/static/built/components/file-change-tracker.js +443 -0
  58. claude_mpm/dashboard/static/built/components/file-change-viewer.js +690 -0
  59. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +1 -1
  60. claude_mpm/dashboard/static/built/components/module-viewer.js +1 -1
  61. claude_mpm/dashboard/static/built/components/nav-bar.js +145 -0
  62. claude_mpm/dashboard/static/built/components/page-structure.js +429 -0
  63. claude_mpm/dashboard/static/built/components/session-manager.js +1 -1
  64. claude_mpm/dashboard/static/built/components/ui-state-manager.js +2 -465
  65. claude_mpm/dashboard/static/built/components/working-directory.js +1 -1
  66. claude_mpm/dashboard/static/built/connection-manager.js +536 -0
  67. claude_mpm/dashboard/static/built/dashboard.js +1 -1
  68. claude_mpm/dashboard/static/built/extension-error-handler.js +164 -0
  69. claude_mpm/dashboard/static/built/react/events.js +30 -0
  70. claude_mpm/dashboard/static/built/shared/dom-helpers.js +396 -0
  71. claude_mpm/dashboard/static/built/shared/event-bus.js +330 -0
  72. claude_mpm/dashboard/static/built/shared/event-filter-service.js +540 -0
  73. claude_mpm/dashboard/static/built/shared/logger.js +385 -0
  74. claude_mpm/dashboard/static/built/shared/page-structure.js +251 -0
  75. claude_mpm/dashboard/static/built/shared/tooltip-service.js +253 -0
  76. claude_mpm/dashboard/static/built/socket-client.js +1 -1
  77. claude_mpm/dashboard/static/built/tab-isolation-fix.js +185 -0
  78. claude_mpm/dashboard/static/css/dashboard.css +28 -5
  79. claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +1 -0
  80. claude_mpm/dashboard/static/dist/components/activity-tree.js +1 -1
  81. claude_mpm/dashboard/static/dist/components/agent-inference.js +1 -1
  82. claude_mpm/dashboard/static/dist/components/code-viewer.js +2 -0
  83. claude_mpm/dashboard/static/dist/components/event-processor.js +1 -1
  84. claude_mpm/dashboard/static/dist/components/event-viewer.js +1 -1
  85. claude_mpm/dashboard/static/dist/components/export-manager.js +1 -1
  86. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +1 -1
  87. claude_mpm/dashboard/static/dist/components/module-viewer.js +1 -1
  88. claude_mpm/dashboard/static/dist/components/session-manager.js +1 -1
  89. claude_mpm/dashboard/static/dist/components/working-directory.js +1 -1
  90. claude_mpm/dashboard/static/dist/dashboard.js +1 -1
  91. claude_mpm/dashboard/static/dist/react/events.js +30 -0
  92. claude_mpm/dashboard/static/dist/socket-client.js +1 -1
  93. claude_mpm/dashboard/static/events.html +607 -0
  94. claude_mpm/dashboard/static/index.html +713 -0
  95. claude_mpm/dashboard/static/js/components/activity-tree.js +3 -17
  96. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +4 -1
  97. claude_mpm/dashboard/static/js/components/agent-inference.js +3 -0
  98. claude_mpm/dashboard/static/js/components/build-tracker.js +8 -0
  99. claude_mpm/dashboard/static/js/components/code-viewer.js +306 -66
  100. claude_mpm/dashboard/static/js/components/event-processor.js +3 -0
  101. claude_mpm/dashboard/static/js/components/event-viewer.js +39 -2
  102. claude_mpm/dashboard/static/js/components/export-manager.js +3 -0
  103. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +30 -10
  104. claude_mpm/dashboard/static/js/components/socket-manager.js +4 -0
  105. claude_mpm/dashboard/static/js/components/ui-state-manager.js +285 -85
  106. claude_mpm/dashboard/static/js/components/working-directory.js +3 -0
  107. claude_mpm/dashboard/static/js/dashboard.js +61 -33
  108. claude_mpm/dashboard/static/js/socket-client.js +12 -8
  109. claude_mpm/dashboard/static/js/stores/dashboard-store.js +562 -0
  110. claude_mpm/dashboard/static/js/tab-isolation-fix.js +185 -0
  111. claude_mpm/dashboard/static/legacy/activity.html +736 -0
  112. claude_mpm/dashboard/static/legacy/agents.html +786 -0
  113. claude_mpm/dashboard/static/legacy/files.html +747 -0
  114. claude_mpm/dashboard/static/legacy/tools.html +831 -0
  115. claude_mpm/dashboard/static/monitors-index.html +218 -0
  116. claude_mpm/dashboard/static/monitors.html +431 -0
  117. claude_mpm/dashboard/static/production/events.html +659 -0
  118. claude_mpm/dashboard/static/production/main.html +715 -0
  119. claude_mpm/dashboard/static/production/monitors.html +483 -0
  120. claude_mpm/dashboard/static/socket.io.min.js +7 -0
  121. claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +7 -0
  122. claude_mpm/dashboard/static/test-archive/dashboard.html +635 -0
  123. claude_mpm/dashboard/static/test-archive/debug-events.html +147 -0
  124. claude_mpm/dashboard/static/test-archive/test-navigation.html +256 -0
  125. claude_mpm/dashboard/static/test-archive/test-react-exports.html +180 -0
  126. claude_mpm/dashboard/templates/index.html +79 -9
  127. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +1 -1
  128. claude_mpm/services/agents/deployment/agent_discovery_service.py +3 -0
  129. claude_mpm/services/agents/deployment/agent_template_builder.py +25 -8
  130. claude_mpm/services/agents/deployment/agent_validator.py +3 -0
  131. claude_mpm/services/agents/deployment/validation/template_validator.py +13 -4
  132. claude_mpm/services/agents/local_template_manager.py +2 -6
  133. claude_mpm/services/monitor/daemon.py +1 -2
  134. claude_mpm/services/monitor/daemon_manager.py +2 -5
  135. claude_mpm/services/monitor/event_emitter.py +2 -2
  136. claude_mpm/services/monitor/handlers/code_analysis.py +4 -6
  137. claude_mpm/services/monitor/handlers/hooks.py +2 -4
  138. claude_mpm/services/monitor/server.py +27 -4
  139. claude_mpm/tools/code_tree_analyzer.py +2 -2
  140. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/METADATA +1 -1
  141. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/RECORD +146 -81
  142. claude_mpm/dashboard/static/test-browser-monitor.html +0 -470
  143. claude_mpm/dashboard/static/test-simple.html +0 -97
  144. /claude_mpm/dashboard/static/{test_debug.html → test-archive/test_debug.html} +0 -0
  145. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/WHEEL +0 -0
  146. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/entry_points.txt +0 -0
  147. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/licenses/LICENSE +0 -0
  148. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,786 @@
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 - Agents Dashboard</title>
7
+
8
+ <!-- Load Socket.IO -->
9
+ <script src="/static/socket.io.min.js"></script>
10
+
11
+ <!-- Verify Socket.IO is loaded -->
12
+ <script>
13
+ // Check if Socket.IO is loaded and available
14
+ if (typeof io === 'undefined') {
15
+ console.error('Socket.IO not loaded, attempting to load from CDN...');
16
+ var script = document.createElement('script');
17
+ script.src = 'https://cdn.socket.io/4.8.1/socket.io.min.js';
18
+ script.onerror = function() {
19
+ console.error('Failed to load Socket.IO from CDN');
20
+ };
21
+ document.head.appendChild(script);
22
+ } else {
23
+ console.log('Socket.IO loaded successfully, version:', io.version || 'unknown');
24
+ }
25
+ </script>
26
+
27
+ <style>
28
+ * {
29
+ margin: 0;
30
+ padding: 0;
31
+ box-sizing: border-box;
32
+ }
33
+
34
+ body {
35
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
36
+ background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
37
+ color: #e0e0e0;
38
+ width: 100vw;
39
+ height: 100vh;
40
+ overflow: hidden;
41
+ display: flex;
42
+ flex-direction: column;
43
+ }
44
+
45
+ .container {
46
+ width: 100%;
47
+ height: 100%;
48
+ padding: 20px;
49
+ overflow-y: auto;
50
+ display: flex;
51
+ flex-direction: column;
52
+ }
53
+
54
+ .header {
55
+ background: rgba(255, 255, 255, 0.05);
56
+ backdrop-filter: blur(10px);
57
+ border-radius: 12px;
58
+ padding: 20px;
59
+ margin-bottom: 20px;
60
+ border: 1px solid rgba(255, 255, 255, 0.1);
61
+ }
62
+
63
+ .header h1 {
64
+ font-size: 24px;
65
+ margin-bottom: 10px;
66
+ background: linear-gradient(135deg, #10b981 0%, #06b6d4 100%);
67
+ -webkit-background-clip: text;
68
+ -webkit-text-fill-color: transparent;
69
+ }
70
+
71
+ .status-bar {
72
+ display: flex;
73
+ gap: 20px;
74
+ align-items: center;
75
+ flex-wrap: wrap;
76
+ }
77
+
78
+ .status-indicator {
79
+ display: flex;
80
+ align-items: center;
81
+ gap: 8px;
82
+ padding: 8px 16px;
83
+ background: rgba(255, 255, 255, 0.05);
84
+ border-radius: 20px;
85
+ font-size: 14px;
86
+ }
87
+
88
+ .status-dot {
89
+ width: 10px;
90
+ height: 10px;
91
+ border-radius: 50%;
92
+ animation: pulse 2s infinite;
93
+ }
94
+
95
+ .status-dot.connected {
96
+ background: #4ade80;
97
+ box-shadow: 0 0 10px #4ade80;
98
+ }
99
+
100
+ .status-dot.disconnected {
101
+ background: #f87171;
102
+ box-shadow: 0 0 10px #f87171;
103
+ }
104
+
105
+ @keyframes pulse {
106
+ 0%, 100% { opacity: 1; }
107
+ 50% { opacity: 0.5; }
108
+ }
109
+
110
+ .stats-panel {
111
+ display: grid;
112
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
113
+ gap: 15px;
114
+ margin-bottom: 20px;
115
+ }
116
+
117
+ .stat-card {
118
+ background: rgba(255, 255, 255, 0.05);
119
+ backdrop-filter: blur(10px);
120
+ border: 1px solid rgba(255, 255, 255, 0.1);
121
+ border-radius: 10px;
122
+ padding: 15px;
123
+ display: flex;
124
+ align-items: center;
125
+ gap: 15px;
126
+ }
127
+
128
+ .stat-icon {
129
+ font-size: 24px;
130
+ background: linear-gradient(135deg, #10b981 0%, #06b6d4 100%);
131
+ -webkit-background-clip: text;
132
+ -webkit-text-fill-color: transparent;
133
+ }
134
+
135
+ .stat-info {
136
+ flex: 1;
137
+ }
138
+
139
+ .stat-label {
140
+ font-size: 12px;
141
+ color: #94a3b8;
142
+ text-transform: uppercase;
143
+ letter-spacing: 0.5px;
144
+ }
145
+
146
+ .stat-value {
147
+ font-size: 24px;
148
+ font-weight: 600;
149
+ color: #e0e0e0;
150
+ }
151
+
152
+ .controls-panel {
153
+ background: rgba(255, 255, 255, 0.05);
154
+ backdrop-filter: blur(10px);
155
+ border: 1px solid rgba(255, 255, 255, 0.1);
156
+ border-radius: 10px;
157
+ padding: 15px;
158
+ margin-bottom: 20px;
159
+ display: flex;
160
+ gap: 15px;
161
+ align-items: center;
162
+ flex-wrap: wrap;
163
+ }
164
+
165
+ .control-group {
166
+ display: flex;
167
+ align-items: center;
168
+ gap: 10px;
169
+ }
170
+
171
+ .control-label {
172
+ font-size: 14px;
173
+ color: #94a3b8;
174
+ }
175
+
176
+ select, input[type="text"] {
177
+ padding: 8px 12px;
178
+ background: rgba(255, 255, 255, 0.1);
179
+ border: 1px solid rgba(255, 255, 255, 0.2);
180
+ border-radius: 6px;
181
+ color: #e0e0e0;
182
+ font-size: 14px;
183
+ }
184
+
185
+ select option {
186
+ background: #1e293b;
187
+ }
188
+
189
+ .btn {
190
+ padding: 8px 16px;
191
+ background: linear-gradient(135deg, #10b981 0%, #06b6d4 100%);
192
+ border: none;
193
+ border-radius: 6px;
194
+ color: white;
195
+ cursor: pointer;
196
+ font-size: 14px;
197
+ font-weight: 500;
198
+ transition: all 0.3s;
199
+ }
200
+
201
+ .btn:hover {
202
+ transform: translateY(-2px);
203
+ box-shadow: 0 5px 15px rgba(16, 185, 129, 0.3);
204
+ }
205
+
206
+ .btn.btn-secondary {
207
+ background: rgba(255, 255, 255, 0.1);
208
+ }
209
+
210
+ .btn.btn-secondary:hover {
211
+ background: rgba(255, 255, 255, 0.15);
212
+ }
213
+
214
+ .agents-list {
215
+ background: rgba(255, 255, 255, 0.05);
216
+ backdrop-filter: blur(10px);
217
+ border: 1px solid rgba(255, 255, 255, 0.1);
218
+ border-radius: 10px;
219
+ padding: 20px;
220
+ max-height: 600px;
221
+ overflow-y: auto;
222
+ }
223
+
224
+ .agent-item {
225
+ background: rgba(255, 255, 255, 0.03);
226
+ border-radius: 8px;
227
+ padding: 15px;
228
+ margin-bottom: 10px;
229
+ border-left: 3px solid #a78bfa;
230
+ transition: all 0.3s;
231
+ cursor: pointer;
232
+ }
233
+
234
+ .agent-item:hover {
235
+ background: rgba(255, 255, 255, 0.08);
236
+ transform: translateX(5px);
237
+ }
238
+
239
+ .agent-header {
240
+ display: flex;
241
+ justify-content: space-between;
242
+ align-items: center;
243
+ margin-bottom: 10px;
244
+ }
245
+
246
+ .agent-name {
247
+ font-family: 'Monaco', 'Menlo', monospace;
248
+ font-size: 14px;
249
+ color: #a78bfa;
250
+ word-break: break-all;
251
+ }
252
+
253
+ .agent-status-badges {
254
+ display: flex;
255
+ gap: 10px;
256
+ }
257
+
258
+ .status-badge {
259
+ padding: 3px 8px;
260
+ border-radius: 12px;
261
+ font-size: 11px;
262
+ font-weight: 600;
263
+ }
264
+
265
+ .status-badge.active {
266
+ background: rgba(74, 222, 128, 0.2);
267
+ color: #4ade80;
268
+ }
269
+
270
+ .status-badge.completed {
271
+ background: rgba(96, 165, 250, 0.2);
272
+ color: #60a5fa;
273
+ }
274
+
275
+ .status-badge.error {
276
+ background: rgba(248, 113, 113, 0.2);
277
+ color: #f87171;
278
+ }
279
+
280
+ .status-badge.idle {
281
+ background: rgba(148, 163, 184, 0.2);
282
+ color: #94a3b8;
283
+ }
284
+
285
+ .agent-stats {
286
+ display: flex;
287
+ gap: 20px;
288
+ font-size: 13px;
289
+ color: #94a3b8;
290
+ }
291
+
292
+ .agent-stat {
293
+ display: flex;
294
+ align-items: center;
295
+ gap: 5px;
296
+ }
297
+
298
+ .agent-timeline {
299
+ margin-top: 10px;
300
+ padding-top: 10px;
301
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
302
+ max-height: 200px;
303
+ overflow-y: auto;
304
+ }
305
+
306
+ .timeline-event {
307
+ display: flex;
308
+ align-items: center;
309
+ gap: 10px;
310
+ padding: 5px 0;
311
+ font-size: 12px;
312
+ }
313
+
314
+ .timeline-time {
315
+ color: #64748b;
316
+ min-width: 60px;
317
+ }
318
+
319
+ .timeline-action {
320
+ padding: 2px 6px;
321
+ border-radius: 8px;
322
+ font-size: 11px;
323
+ }
324
+
325
+ .timeline-task {
326
+ flex: 1;
327
+ color: #94a3b8;
328
+ overflow: hidden;
329
+ text-overflow: ellipsis;
330
+ white-space: nowrap;
331
+ }
332
+
333
+ .no-agents {
334
+ text-align: center;
335
+ padding: 60px 20px;
336
+ color: rgba(255, 255, 255, 0.5);
337
+ }
338
+
339
+ /* Navigation styles will be injected by nav-bar.js */
340
+
341
+ /* Scrollbar styling */
342
+ ::-webkit-scrollbar {
343
+ width: 8px;
344
+ height: 8px;
345
+ }
346
+
347
+ ::-webkit-scrollbar-track {
348
+ background: rgba(255, 255, 255, 0.05);
349
+ border-radius: 4px;
350
+ }
351
+
352
+ ::-webkit-scrollbar-thumb {
353
+ background: rgba(255, 255, 255, 0.2);
354
+ border-radius: 4px;
355
+ }
356
+
357
+ ::-webkit-scrollbar-thumb:hover {
358
+ background: rgba(255, 255, 255, 0.3);
359
+ }
360
+ </style>
361
+ </head>
362
+ <body>
363
+ <div class="container">
364
+ <!-- Header with standardized structure -->
365
+ <div class="header">
366
+ <h1>🤖 Agents Dashboard</h1>
367
+ <div class="status-bar">
368
+ <div class="status-indicator">
369
+ <span class="status-dot disconnected" id="connection-status"></span>
370
+ <span id="connection-text">Disconnected</span>
371
+ </div>
372
+ <div class="status-indicator">
373
+ <span>🤖</span>
374
+ <span id="total-agents">0 agents</span>
375
+ </div>
376
+ <div class="status-indicator">
377
+ <span>🔄</span>
378
+ <span id="active-agents">0 active</span>
379
+ </div>
380
+ <div class="status-indicator">
381
+ <span>✅</span>
382
+ <span id="completed-tasks">0 completed</span>
383
+ </div>
384
+ </div>
385
+ </div>
386
+
387
+ <!-- Navigation Bar -->
388
+ <div id="navigation-container"></div>
389
+
390
+ <!-- Statistics Panel -->
391
+ <div class="stats-panel">
392
+ <div class="stat-card">
393
+ <div class="stat-icon">🤖</div>
394
+ <div class="stat-info">
395
+ <div class="stat-label">Total Agents</div>
396
+ <div class="stat-value" id="totalAgents">0</div>
397
+ </div>
398
+ </div>
399
+ <div class="stat-card">
400
+ <div class="stat-icon">🔄</div>
401
+ <div class="stat-info">
402
+ <div class="stat-label">Active Agents</div>
403
+ <div class="stat-value" id="activeAgentsCount">0</div>
404
+ </div>
405
+ </div>
406
+ <div class="stat-card">
407
+ <div class="stat-icon">✅</div>
408
+ <div class="stat-info">
409
+ <div class="stat-label">Completed Tasks</div>
410
+ <div class="stat-value" id="completedTasksCount">0</div>
411
+ </div>
412
+ </div>
413
+ <div class="stat-card">
414
+ <div class="stat-icon">⏱️</div>
415
+ <div class="stat-info">
416
+ <div class="stat-label">Total Duration</div>
417
+ <div class="stat-value" id="totalDuration">0s</div>
418
+ </div>
419
+ </div>
420
+ </div>
421
+
422
+ <!-- Controls Panel -->
423
+ <div class="controls-panel">
424
+ <div class="control-group">
425
+ <input type="text" id="searchBox" placeholder="Search agents...">
426
+ </div>
427
+ <div class="control-group">
428
+ <label class="control-label">Status:</label>
429
+ <select id="statusFilter">
430
+ <option value="">All Status</option>
431
+ <option value="active">Active</option>
432
+ <option value="completed">Completed</option>
433
+ <option value="error">Error</option>
434
+ <option value="idle">Idle</option>
435
+ </select>
436
+ </div>
437
+ <div class="control-group">
438
+ <label class="control-label">Sort by:</label>
439
+ <select id="sortBy">
440
+ <option value="recent">Most Recent</option>
441
+ <option value="duration">Longest Duration</option>
442
+ <option value="name">Agent Name</option>
443
+ </select>
444
+ </div>
445
+ <button class="btn btn-secondary" id="refreshAgents">Refresh</button>
446
+ <button class="btn" id="clearAgents">Clear All</button>
447
+ </div>
448
+
449
+ <!-- Agents List -->
450
+ <div class="agents-list" id="agentsList">
451
+ <div class="no-agents">
452
+ <h3>No Agent Activity Yet</h3>
453
+ <p>Waiting for agent events from the server...</p>
454
+ </div>
455
+ </div>
456
+ </div>
457
+
458
+ <script type="module">
459
+ // Wait for Socket.IO to be available
460
+ function waitForSocketIO() {
461
+ return new Promise((resolve) => {
462
+ if (typeof io !== 'undefined') {
463
+ console.log('Socket.IO is ready');
464
+ resolve();
465
+ } else {
466
+ console.log('Waiting for Socket.IO...');
467
+ setTimeout(() => waitForSocketIO().then(resolve), 100);
468
+ }
469
+ });
470
+ }
471
+
472
+ // Initialize after Socket.IO is ready
473
+ await waitForSocketIO();
474
+ console.log('Starting dashboard initialization...');
475
+ // Import navigation component
476
+ import { NavBar } from '/static/built/components/nav-bar.js';
477
+
478
+ // Initialize navigation
479
+ const navBar = new NavBar();
480
+ navBar.initialize('navigation-container');
481
+ </script>
482
+
483
+ <script>
484
+ // Agent storage and state management
485
+ const appState = {
486
+ agents: new Map(),
487
+ isConnected: false,
488
+ stats: {
489
+ totalAgents: 0,
490
+ activeAgents: 0,
491
+ completedTasks: 0,
492
+ totalDuration: 0
493
+ }
494
+ };
495
+
496
+ // Socket.IO connection
497
+ const socket = io('http://localhost:8765', {
498
+ transports: ['polling', 'websocket'],
499
+ reconnection: true,
500
+ reconnectionDelay: 1000,
501
+ reconnectionDelayMax: 5000,
502
+ reconnectionAttempts: Infinity
503
+ });
504
+
505
+ console.log('Initializing Socket.IO connection for agents monitoring');
506
+
507
+ // Socket event handlers
508
+ socket.on('connect', () => {
509
+ console.log('Connected to Socket.IO server');
510
+ appState.isConnected = true;
511
+ updateConnectionStatus(true);
512
+
513
+ // Request agent data - be more comprehensive
514
+ socket.emit('get_history', { type: 'agent', limit: 100 });
515
+ socket.emit('get_history', { type: 'subagent', limit: 100 });
516
+ });
517
+
518
+ socket.on('disconnect', () => {
519
+ console.log('Disconnected from Socket.IO server');
520
+ appState.isConnected = false;
521
+ updateConnectionStatus(false);
522
+ });
523
+
524
+ // Handle claude events - be more comprehensive in event capture
525
+ socket.on('claude_event', (data) => {
526
+ console.log('Received event:', data);
527
+
528
+ // Check for agent-related events in multiple ways
529
+ const isAgentEvent =
530
+ (data.type && (
531
+ data.type.includes('agent') ||
532
+ data.type.includes('subagent') ||
533
+ data.type === 'SubagentStart' ||
534
+ data.type === 'SubagentStop' ||
535
+ data.type === 'agent_start' ||
536
+ data.type === 'agent_complete'
537
+ )) ||
538
+ (data.event_type && (
539
+ data.event_type.includes('agent') ||
540
+ data.event_type.includes('subagent')
541
+ )) ||
542
+ data.agent_name ||
543
+ data.agent_id ||
544
+ data.data?.agent_name ||
545
+ data.data?.agent_id ||
546
+ (data.data?.type && data.data.type.includes('agent'));
547
+
548
+ if (isAgentEvent) {
549
+ console.log('Processing agent event:', data);
550
+ processAgentEvent(data);
551
+ }
552
+ });
553
+
554
+ // Update connection status
555
+ function updateConnectionStatus(connected) {
556
+ const statusDot = document.getElementById('connection-status');
557
+ const statusText = document.getElementById('connection-text');
558
+
559
+ if (statusDot && statusText) {
560
+ statusDot.className = `status-dot ${connected ? 'connected' : 'disconnected'}`;
561
+ statusText.textContent = connected ? 'Connected' : 'Disconnected';
562
+ }
563
+ }
564
+
565
+ // Process agent events
566
+ function processAgentEvent(event) {
567
+ const agentId = event.agent_id || event.data?.agent_id ||
568
+ event.agent_name || event.data?.agent_name ||
569
+ `agent_${Date.now()}`;
570
+
571
+ const agentName = event.agent_name || event.data?.agent_name ||
572
+ event.name || event.data?.name || 'Unknown Agent';
573
+
574
+ const taskInfo = event.task || event.data?.task ||
575
+ event.instruction || event.data?.instruction ||
576
+ event.message || event.data?.message ||
577
+ 'Processing task...';
578
+
579
+ if (!appState.agents.has(agentId)) {
580
+ appState.agents.set(agentId, {
581
+ id: agentId,
582
+ name: agentName,
583
+ status: 'idle',
584
+ startTime: null,
585
+ endTime: null,
586
+ duration: 0,
587
+ task: taskInfo,
588
+ events: []
589
+ });
590
+ appState.stats.totalAgents++;
591
+ }
592
+
593
+ const agent = appState.agents.get(agentId);
594
+ agent.lastActivity = Date.now();
595
+ agent.task = taskInfo;
596
+ agent.events.push({
597
+ timestamp: Date.now(),
598
+ type: event.type || event.event_type || 'update',
599
+ data: event
600
+ });
601
+
602
+ // Update agent status based on event type
603
+ const eventType = (event.type || event.event_type || '').toLowerCase();
604
+
605
+ if (eventType.includes('start') || eventType === 'subagentstart') {
606
+ agent.status = 'active';
607
+ agent.startTime = Date.now();
608
+ appState.stats.activeAgents++;
609
+ } else if (eventType.includes('stop') || eventType.includes('complete') ||
610
+ eventType === 'subagentstop') {
611
+ if (agent.status === 'active') {
612
+ appState.stats.activeAgents = Math.max(0, appState.stats.activeAgents - 1);
613
+ }
614
+ agent.status = 'completed';
615
+ agent.endTime = Date.now();
616
+ if (agent.startTime) {
617
+ agent.duration = (agent.endTime - agent.startTime) / 1000;
618
+ appState.stats.totalDuration += agent.duration;
619
+ }
620
+ appState.stats.completedTasks++;
621
+ } else if (eventType.includes('error') || eventType.includes('fail')) {
622
+ if (agent.status === 'active') {
623
+ appState.stats.activeAgents = Math.max(0, appState.stats.activeAgents - 1);
624
+ }
625
+ agent.status = 'error';
626
+ agent.endTime = Date.now();
627
+ if (agent.startTime) {
628
+ agent.duration = (agent.endTime - agent.startTime) / 1000;
629
+ }
630
+ }
631
+
632
+ // Keep only last 10 events per agent
633
+ if (agent.events.length > 10) {
634
+ agent.events = agent.events.slice(-10);
635
+ }
636
+
637
+ updateUI();
638
+ }
639
+
640
+ // Format duration
641
+ function formatDuration(seconds) {
642
+ if (seconds < 60) return `${Math.round(seconds)}s`;
643
+ const minutes = Math.floor(seconds / 60);
644
+ const secs = Math.round(seconds % 60);
645
+ return `${minutes}m ${secs}s`;
646
+ }
647
+
648
+ // Format time ago
649
+ function formatTimeAgo(timestamp) {
650
+ const diff = Date.now() - timestamp;
651
+ const seconds = Math.floor(diff / 1000);
652
+ const minutes = Math.floor(seconds / 60);
653
+ const hours = Math.floor(minutes / 60);
654
+
655
+ if (hours > 0) return `${hours}h ago`;
656
+ if (minutes > 0) return `${minutes}m ago`;
657
+ return `${seconds}s ago`;
658
+ }
659
+
660
+ // Render agent item
661
+ function renderAgentItem(agent) {
662
+ const recentEvents = agent.events.slice(-5).reverse();
663
+
664
+ return `
665
+ <div class="agent-item" data-agent-id="${agent.id}">
666
+ <div class="agent-header">
667
+ <div class="agent-name">${agent.name}</div>
668
+ <div class="agent-status-badges">
669
+ <span class="status-badge ${agent.status}">${agent.status.toUpperCase()}</span>
670
+ ${agent.duration > 0 ? `<span class="status-badge">${formatDuration(agent.duration)}</span>` : ''}
671
+ </div>
672
+ </div>
673
+ <div class="agent-stats">
674
+ <div class="agent-stat">
675
+ 📝 ${agent.task}
676
+ </div>
677
+ <div class="agent-stat">
678
+ ⏱️ ${formatTimeAgo(agent.lastActivity)}
679
+ </div>
680
+ </div>
681
+ ${recentEvents.length > 0 ? `
682
+ <div class="agent-timeline">
683
+ ${recentEvents.map(evt => `
684
+ <div class="timeline-event">
685
+ <span class="timeline-time">${new Date(evt.timestamp).toLocaleTimeString('en-US', {
686
+ hour: '2-digit',
687
+ minute: '2-digit',
688
+ second: '2-digit'
689
+ })}</span>
690
+ <span class="timeline-action status-badge ${evt.type.includes('start') ? 'active' : evt.type.includes('stop') || evt.type.includes('complete') ? 'completed' : 'idle'}">
691
+ ${evt.type.toUpperCase().replace(/_/g, ' ')}
692
+ </span>
693
+ <span class="timeline-task">${evt.data.task || evt.data.message || ''}</span>
694
+ </div>
695
+ `).join('')}
696
+ </div>
697
+ ` : ''}
698
+ </div>
699
+ `;
700
+ }
701
+
702
+ // Update UI
703
+ function updateUI() {
704
+ // Update header stats
705
+ document.getElementById('total-agents').textContent = `${appState.stats.totalAgents} agents`;
706
+ document.getElementById('active-agents').textContent = `${appState.stats.activeAgents} active`;
707
+ document.getElementById('completed-tasks').textContent = `${appState.stats.completedTasks} completed`;
708
+
709
+ // Update statistics cards
710
+ document.getElementById('totalAgents').textContent = appState.stats.totalAgents;
711
+ document.getElementById('activeAgentsCount').textContent = appState.stats.activeAgents;
712
+ document.getElementById('completedTasksCount').textContent = appState.stats.completedTasks;
713
+ document.getElementById('totalDuration').textContent = formatDuration(appState.stats.totalDuration);
714
+
715
+ // Get filters
716
+ const searchTerm = document.getElementById('searchBox').value.toLowerCase();
717
+ const statusFilter = document.getElementById('statusFilter').value;
718
+ const sortBy = document.getElementById('sortBy').value;
719
+
720
+ // Filter agents
721
+ let filteredAgents = Array.from(appState.agents.values());
722
+
723
+ if (searchTerm) {
724
+ filteredAgents = filteredAgents.filter(agent =>
725
+ agent.name.toLowerCase().includes(searchTerm) ||
726
+ agent.task.toLowerCase().includes(searchTerm)
727
+ );
728
+ }
729
+
730
+ if (statusFilter) {
731
+ filteredAgents = filteredAgents.filter(agent => agent.status === statusFilter);
732
+ }
733
+
734
+ // Sort agents
735
+ if (sortBy === 'recent') {
736
+ filteredAgents.sort((a, b) => b.lastActivity - a.lastActivity);
737
+ } else if (sortBy === 'duration') {
738
+ filteredAgents.sort((a, b) => b.duration - a.duration);
739
+ } else if (sortBy === 'name') {
740
+ filteredAgents.sort((a, b) => a.name.localeCompare(b.name));
741
+ }
742
+
743
+ // Render agents list
744
+ const agentsList = document.getElementById('agentsList');
745
+ if (filteredAgents.length === 0) {
746
+ agentsList.innerHTML = `
747
+ <div class="no-agents">
748
+ <h3>No Agents Found</h3>
749
+ <p>${searchTerm || statusFilter ? 'Try different filters' : 'Waiting for agent events from the server...'}</p>
750
+ </div>
751
+ `;
752
+ } else {
753
+ agentsList.innerHTML = filteredAgents.map(renderAgentItem).join('');
754
+ }
755
+ }
756
+
757
+ // Event handlers
758
+ document.getElementById('searchBox').addEventListener('input', updateUI);
759
+ document.getElementById('statusFilter').addEventListener('change', updateUI);
760
+ document.getElementById('sortBy').addEventListener('change', updateUI);
761
+
762
+ document.getElementById('refreshAgents').addEventListener('click', () => {
763
+ socket.emit('get_history', { type: 'agent', limit: 100 });
764
+ socket.emit('get_history', { type: 'subagent', limit: 100 });
765
+ });
766
+
767
+ document.getElementById('clearAgents').addEventListener('click', () => {
768
+ if (confirm('Clear all agent data?')) {
769
+ appState.agents.clear();
770
+ appState.stats = {
771
+ totalAgents: 0,
772
+ activeAgents: 0,
773
+ completedTasks: 0,
774
+ totalDuration: 0
775
+ };
776
+ updateUI();
777
+ }
778
+ });
779
+
780
+ // Initial UI update
781
+ updateUI();
782
+
783
+ console.log('Agents monitor initialized');
784
+ </script>
785
+ </body>
786
+ </html>