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.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/BASE_PM.md +43 -1
- claude_mpm/agents/INSTRUCTIONS.md +75 -1
- claude_mpm/agents/WORKFLOW.md +46 -1
- claude_mpm/agents/frontmatter_validator.py +20 -12
- claude_mpm/agents/templates/nextjs_engineer.json +277 -0
- claude_mpm/agents/templates/python_engineer.json +289 -0
- claude_mpm/agents/templates/react_engineer.json +11 -3
- claude_mpm/agents/templates/security.json +50 -9
- claude_mpm/cli/commands/agents.py +2 -2
- claude_mpm/cli/commands/uninstall.py +1 -2
- claude_mpm/cli/interactive/agent_wizard.py +3 -3
- claude_mpm/cli/parsers/agent_manager_parser.py +3 -3
- claude_mpm/cli/parsers/agents_parser.py +1 -1
- claude_mpm/constants.py +1 -1
- claude_mpm/core/error_handler.py +2 -4
- claude_mpm/core/file_utils.py +4 -12
- claude_mpm/core/log_manager.py +8 -5
- claude_mpm/core/logger.py +1 -1
- claude_mpm/core/logging_utils.py +6 -6
- claude_mpm/core/unified_agent_registry.py +18 -4
- claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +188 -0
- claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +156 -0
- claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +38 -0
- claude_mpm/dashboard/react/components/shared/FilterBar.module.css +92 -0
- claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +248 -0
- claude_mpm/dashboard/static/archive/activity_dashboard_test.html +61 -0
- claude_mpm/dashboard/static/archive/test_activity_connection.html +179 -0
- claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +68 -0
- claude_mpm/dashboard/static/archive/test_dashboard.html +409 -0
- claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +519 -0
- claude_mpm/dashboard/static/archive/test_dashboard_verification.html +181 -0
- claude_mpm/dashboard/static/archive/test_file_data.html +315 -0
- claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +243 -0
- claude_mpm/dashboard/static/archive/test_file_tree_fix.html +234 -0
- claude_mpm/dashboard/static/archive/test_file_tree_rename.html +117 -0
- claude_mpm/dashboard/static/archive/test_file_tree_tab.html +115 -0
- claude_mpm/dashboard/static/archive/test_file_viewer.html +224 -0
- claude_mpm/dashboard/static/archive/test_final_activity.html +220 -0
- claude_mpm/dashboard/static/archive/test_tab_fix.html +139 -0
- claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +1 -0
- claude_mpm/dashboard/static/built/components/activity-tree.js +1 -1
- claude_mpm/dashboard/static/built/components/agent-hierarchy.js +777 -0
- claude_mpm/dashboard/static/built/components/agent-inference.js +1 -1
- claude_mpm/dashboard/static/built/components/build-tracker.js +333 -0
- claude_mpm/dashboard/static/built/components/code-simple.js +857 -0
- claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +353 -0
- claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +235 -0
- claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +409 -0
- claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +435 -0
- claude_mpm/dashboard/static/built/components/code-viewer.js +2 -1076
- claude_mpm/dashboard/static/built/components/connection-debug.js +654 -0
- claude_mpm/dashboard/static/built/components/diff-viewer.js +891 -0
- claude_mpm/dashboard/static/built/components/event-processor.js +1 -1
- claude_mpm/dashboard/static/built/components/event-viewer.js +1 -1
- claude_mpm/dashboard/static/built/components/export-manager.js +1 -1
- claude_mpm/dashboard/static/built/components/file-change-tracker.js +443 -0
- claude_mpm/dashboard/static/built/components/file-change-viewer.js +690 -0
- claude_mpm/dashboard/static/built/components/file-tool-tracker.js +1 -1
- claude_mpm/dashboard/static/built/components/module-viewer.js +1 -1
- claude_mpm/dashboard/static/built/components/nav-bar.js +145 -0
- claude_mpm/dashboard/static/built/components/page-structure.js +429 -0
- claude_mpm/dashboard/static/built/components/session-manager.js +1 -1
- claude_mpm/dashboard/static/built/components/ui-state-manager.js +2 -465
- claude_mpm/dashboard/static/built/components/working-directory.js +1 -1
- claude_mpm/dashboard/static/built/connection-manager.js +536 -0
- claude_mpm/dashboard/static/built/dashboard.js +1 -1
- claude_mpm/dashboard/static/built/extension-error-handler.js +164 -0
- claude_mpm/dashboard/static/built/react/events.js +30 -0
- claude_mpm/dashboard/static/built/shared/dom-helpers.js +396 -0
- claude_mpm/dashboard/static/built/shared/event-bus.js +330 -0
- claude_mpm/dashboard/static/built/shared/event-filter-service.js +540 -0
- claude_mpm/dashboard/static/built/shared/logger.js +385 -0
- claude_mpm/dashboard/static/built/shared/page-structure.js +251 -0
- claude_mpm/dashboard/static/built/shared/tooltip-service.js +253 -0
- claude_mpm/dashboard/static/built/socket-client.js +1 -1
- claude_mpm/dashboard/static/built/tab-isolation-fix.js +185 -0
- claude_mpm/dashboard/static/css/dashboard.css +28 -5
- claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +1 -0
- claude_mpm/dashboard/static/dist/components/activity-tree.js +1 -1
- claude_mpm/dashboard/static/dist/components/agent-inference.js +1 -1
- claude_mpm/dashboard/static/dist/components/code-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/event-processor.js +1 -1
- claude_mpm/dashboard/static/dist/components/event-viewer.js +1 -1
- claude_mpm/dashboard/static/dist/components/export-manager.js +1 -1
- claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +1 -1
- claude_mpm/dashboard/static/dist/components/module-viewer.js +1 -1
- claude_mpm/dashboard/static/dist/components/session-manager.js +1 -1
- claude_mpm/dashboard/static/dist/components/working-directory.js +1 -1
- claude_mpm/dashboard/static/dist/dashboard.js +1 -1
- claude_mpm/dashboard/static/dist/react/events.js +30 -0
- claude_mpm/dashboard/static/dist/socket-client.js +1 -1
- claude_mpm/dashboard/static/events.html +607 -0
- claude_mpm/dashboard/static/index.html +713 -0
- claude_mpm/dashboard/static/js/components/activity-tree.js +3 -17
- claude_mpm/dashboard/static/js/components/agent-hierarchy.js +4 -1
- claude_mpm/dashboard/static/js/components/agent-inference.js +3 -0
- claude_mpm/dashboard/static/js/components/build-tracker.js +8 -0
- claude_mpm/dashboard/static/js/components/code-viewer.js +306 -66
- claude_mpm/dashboard/static/js/components/event-processor.js +3 -0
- claude_mpm/dashboard/static/js/components/event-viewer.js +39 -2
- claude_mpm/dashboard/static/js/components/export-manager.js +3 -0
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +30 -10
- claude_mpm/dashboard/static/js/components/socket-manager.js +4 -0
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +285 -85
- claude_mpm/dashboard/static/js/components/working-directory.js +3 -0
- claude_mpm/dashboard/static/js/dashboard.js +61 -33
- claude_mpm/dashboard/static/js/socket-client.js +12 -8
- claude_mpm/dashboard/static/js/stores/dashboard-store.js +562 -0
- claude_mpm/dashboard/static/js/tab-isolation-fix.js +185 -0
- claude_mpm/dashboard/static/legacy/activity.html +736 -0
- claude_mpm/dashboard/static/legacy/agents.html +786 -0
- claude_mpm/dashboard/static/legacy/files.html +747 -0
- claude_mpm/dashboard/static/legacy/tools.html +831 -0
- claude_mpm/dashboard/static/monitors-index.html +218 -0
- claude_mpm/dashboard/static/monitors.html +431 -0
- claude_mpm/dashboard/static/production/events.html +659 -0
- claude_mpm/dashboard/static/production/main.html +715 -0
- claude_mpm/dashboard/static/production/monitors.html +483 -0
- claude_mpm/dashboard/static/socket.io.min.js +7 -0
- claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +7 -0
- claude_mpm/dashboard/static/test-archive/dashboard.html +635 -0
- claude_mpm/dashboard/static/test-archive/debug-events.html +147 -0
- claude_mpm/dashboard/static/test-archive/test-navigation.html +256 -0
- claude_mpm/dashboard/static/test-archive/test-react-exports.html +180 -0
- claude_mpm/dashboard/templates/index.html +79 -9
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +1 -1
- claude_mpm/services/agents/deployment/agent_discovery_service.py +3 -0
- claude_mpm/services/agents/deployment/agent_template_builder.py +25 -8
- claude_mpm/services/agents/deployment/agent_validator.py +3 -0
- claude_mpm/services/agents/deployment/validation/template_validator.py +13 -4
- claude_mpm/services/agents/local_template_manager.py +2 -6
- claude_mpm/services/monitor/daemon.py +1 -2
- claude_mpm/services/monitor/daemon_manager.py +2 -5
- claude_mpm/services/monitor/event_emitter.py +2 -2
- claude_mpm/services/monitor/handlers/code_analysis.py +4 -6
- claude_mpm/services/monitor/handlers/hooks.py +2 -4
- claude_mpm/services/monitor/server.py +27 -4
- claude_mpm/tools/code_tree_analyzer.py +2 -2
- {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/METADATA +1 -1
- {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/RECORD +146 -81
- claude_mpm/dashboard/static/test-browser-monitor.html +0 -470
- claude_mpm/dashboard/static/test-simple.html +0 -97
- /claude_mpm/dashboard/static/{test_debug.html → test-archive/test_debug.html} +0 -0
- {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/WHEEL +0 -0
- {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/licenses/LICENSE +0 -0
- {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>
|