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,831 @@
|
|
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 - Tools 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
|
+
.tools-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
|
+
.tool-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 #10b981;
|
230
|
+
transition: all 0.3s;
|
231
|
+
cursor: pointer;
|
232
|
+
}
|
233
|
+
|
234
|
+
.tool-item:hover {
|
235
|
+
background: rgba(255, 255, 255, 0.08);
|
236
|
+
transform: translateX(5px);
|
237
|
+
}
|
238
|
+
|
239
|
+
.tool-header {
|
240
|
+
display: flex;
|
241
|
+
justify-content: space-between;
|
242
|
+
align-items: center;
|
243
|
+
margin-bottom: 10px;
|
244
|
+
}
|
245
|
+
|
246
|
+
.tool-name {
|
247
|
+
font-family: 'Monaco', 'Menlo', monospace;
|
248
|
+
font-size: 14px;
|
249
|
+
color: #10b981;
|
250
|
+
word-break: break-all;
|
251
|
+
display: flex;
|
252
|
+
align-items: center;
|
253
|
+
gap: 8px;
|
254
|
+
}
|
255
|
+
|
256
|
+
.tool-icon {
|
257
|
+
font-size: 16px;
|
258
|
+
}
|
259
|
+
|
260
|
+
.tool-badges {
|
261
|
+
display: flex;
|
262
|
+
gap: 10px;
|
263
|
+
}
|
264
|
+
|
265
|
+
.tool-badge {
|
266
|
+
padding: 3px 8px;
|
267
|
+
border-radius: 12px;
|
268
|
+
font-size: 11px;
|
269
|
+
font-weight: 600;
|
270
|
+
}
|
271
|
+
|
272
|
+
.tool-badge.success {
|
273
|
+
background: rgba(74, 222, 128, 0.2);
|
274
|
+
color: #4ade80;
|
275
|
+
}
|
276
|
+
|
277
|
+
.tool-badge.error {
|
278
|
+
background: rgba(248, 113, 113, 0.2);
|
279
|
+
color: #f87171;
|
280
|
+
}
|
281
|
+
|
282
|
+
.tool-badge.running {
|
283
|
+
background: rgba(251, 191, 36, 0.2);
|
284
|
+
color: #fbbf24;
|
285
|
+
}
|
286
|
+
|
287
|
+
.tool-stats {
|
288
|
+
display: flex;
|
289
|
+
gap: 20px;
|
290
|
+
font-size: 13px;
|
291
|
+
color: #94a3b8;
|
292
|
+
}
|
293
|
+
|
294
|
+
.tool-stat {
|
295
|
+
display: flex;
|
296
|
+
align-items: center;
|
297
|
+
gap: 5px;
|
298
|
+
}
|
299
|
+
|
300
|
+
.tool-timeline {
|
301
|
+
margin-top: 10px;
|
302
|
+
padding-top: 10px;
|
303
|
+
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
304
|
+
max-height: 200px;
|
305
|
+
overflow-y: auto;
|
306
|
+
}
|
307
|
+
|
308
|
+
.timeline-event {
|
309
|
+
display: flex;
|
310
|
+
align-items: center;
|
311
|
+
gap: 10px;
|
312
|
+
padding: 5px 0;
|
313
|
+
font-size: 12px;
|
314
|
+
}
|
315
|
+
|
316
|
+
.timeline-time {
|
317
|
+
color: #64748b;
|
318
|
+
min-width: 60px;
|
319
|
+
}
|
320
|
+
|
321
|
+
.timeline-status {
|
322
|
+
padding: 2px 6px;
|
323
|
+
border-radius: 8px;
|
324
|
+
font-size: 11px;
|
325
|
+
}
|
326
|
+
|
327
|
+
.timeline-agent {
|
328
|
+
flex: 1;
|
329
|
+
color: #94a3b8;
|
330
|
+
overflow: hidden;
|
331
|
+
text-overflow: ellipsis;
|
332
|
+
white-space: nowrap;
|
333
|
+
}
|
334
|
+
|
335
|
+
.no-tools {
|
336
|
+
text-align: center;
|
337
|
+
padding: 60px 20px;
|
338
|
+
color: rgba(255, 255, 255, 0.5);
|
339
|
+
}
|
340
|
+
|
341
|
+
/* Navigation styles will be injected by nav-bar.js */
|
342
|
+
|
343
|
+
/* Scrollbar styling */
|
344
|
+
::-webkit-scrollbar {
|
345
|
+
width: 8px;
|
346
|
+
height: 8px;
|
347
|
+
}
|
348
|
+
|
349
|
+
::-webkit-scrollbar-track {
|
350
|
+
background: rgba(255, 255, 255, 0.05);
|
351
|
+
border-radius: 4px;
|
352
|
+
}
|
353
|
+
|
354
|
+
::-webkit-scrollbar-thumb {
|
355
|
+
background: rgba(255, 255, 255, 0.2);
|
356
|
+
border-radius: 4px;
|
357
|
+
}
|
358
|
+
|
359
|
+
::-webkit-scrollbar-thumb:hover {
|
360
|
+
background: rgba(255, 255, 255, 0.3);
|
361
|
+
}
|
362
|
+
</style>
|
363
|
+
</head>
|
364
|
+
<body>
|
365
|
+
<div class="container">
|
366
|
+
<!-- Header with standardized structure -->
|
367
|
+
<div class="header">
|
368
|
+
<h1>🔧 Tools Dashboard</h1>
|
369
|
+
<div class="status-bar">
|
370
|
+
<div class="status-indicator">
|
371
|
+
<span class="status-dot disconnected" id="connection-status"></span>
|
372
|
+
<span id="connection-text">Disconnected</span>
|
373
|
+
</div>
|
374
|
+
<div class="status-indicator">
|
375
|
+
<span>🔧</span>
|
376
|
+
<span id="total-calls">0 calls</span>
|
377
|
+
</div>
|
378
|
+
<div class="status-indicator">
|
379
|
+
<span>✅</span>
|
380
|
+
<span id="successful-calls">0 successful</span>
|
381
|
+
</div>
|
382
|
+
<div class="status-indicator">
|
383
|
+
<span>❌</span>
|
384
|
+
<span id="failed-calls">0 failed</span>
|
385
|
+
</div>
|
386
|
+
</div>
|
387
|
+
</div>
|
388
|
+
|
389
|
+
<!-- Navigation Bar -->
|
390
|
+
<div id="navigation-container"></div>
|
391
|
+
|
392
|
+
<!-- Statistics Panel -->
|
393
|
+
<div class="stats-panel">
|
394
|
+
<div class="stat-card">
|
395
|
+
<div class="stat-icon">🔧</div>
|
396
|
+
<div class="stat-info">
|
397
|
+
<div class="stat-label">Total Tools</div>
|
398
|
+
<div class="stat-value" id="totalTools">0</div>
|
399
|
+
</div>
|
400
|
+
</div>
|
401
|
+
<div class="stat-card">
|
402
|
+
<div class="stat-icon">📊</div>
|
403
|
+
<div class="stat-info">
|
404
|
+
<div class="stat-label">Total Calls</div>
|
405
|
+
<div class="stat-value" id="totalCalls">0</div>
|
406
|
+
</div>
|
407
|
+
</div>
|
408
|
+
<div class="stat-card">
|
409
|
+
<div class="stat-icon">✅</div>
|
410
|
+
<div class="stat-info">
|
411
|
+
<div class="stat-label">Success Rate</div>
|
412
|
+
<div class="stat-value" id="successRate">0%</div>
|
413
|
+
</div>
|
414
|
+
</div>
|
415
|
+
<div class="stat-card">
|
416
|
+
<div class="stat-icon">⏱️</div>
|
417
|
+
<div class="stat-info">
|
418
|
+
<div class="stat-label">Avg Duration</div>
|
419
|
+
<div class="stat-value" id="avgDuration">0ms</div>
|
420
|
+
</div>
|
421
|
+
</div>
|
422
|
+
</div>
|
423
|
+
|
424
|
+
<!-- Controls Panel -->
|
425
|
+
<div class="controls-panel">
|
426
|
+
<div class="control-group">
|
427
|
+
<input type="text" id="searchBox" placeholder="Search tools...">
|
428
|
+
</div>
|
429
|
+
<div class="control-group">
|
430
|
+
<label class="control-label">Type:</label>
|
431
|
+
<select id="typeFilter">
|
432
|
+
<option value="">All Types</option>
|
433
|
+
<option value="Read">Read</option>
|
434
|
+
<option value="Write">Write</option>
|
435
|
+
<option value="Edit">Edit</option>
|
436
|
+
<option value="MultiEdit">MultiEdit</option>
|
437
|
+
<option value="Bash">Bash</option>
|
438
|
+
<option value="Grep">Grep</option>
|
439
|
+
<option value="Glob">Glob</option>
|
440
|
+
<option value="WebSearch">WebSearch</option>
|
441
|
+
<option value="WebFetch">WebFetch</option>
|
442
|
+
<option value="TodoWrite">TodoWrite</option>
|
443
|
+
</select>
|
444
|
+
</div>
|
445
|
+
<div class="control-group">
|
446
|
+
<label class="control-label">Sort by:</label>
|
447
|
+
<select id="sortBy">
|
448
|
+
<option value="recent">Most Recent</option>
|
449
|
+
<option value="calls">Most Calls</option>
|
450
|
+
<option value="name">Tool Name</option>
|
451
|
+
</select>
|
452
|
+
</div>
|
453
|
+
<button class="btn btn-secondary" id="refreshTools">Refresh</button>
|
454
|
+
<button class="btn" id="clearTools">Clear All</button>
|
455
|
+
</div>
|
456
|
+
|
457
|
+
<!-- Tools List -->
|
458
|
+
<div class="tools-list" id="toolsList">
|
459
|
+
<div class="no-tools">
|
460
|
+
<h3>No Tool Usage Yet</h3>
|
461
|
+
<p>Waiting for tool events from the server...</p>
|
462
|
+
</div>
|
463
|
+
</div>
|
464
|
+
</div>
|
465
|
+
|
466
|
+
<script type="module">
|
467
|
+
// Wait for Socket.IO to be available
|
468
|
+
function waitForSocketIO() {
|
469
|
+
return new Promise((resolve) => {
|
470
|
+
if (typeof io !== 'undefined') {
|
471
|
+
console.log('Socket.IO is ready');
|
472
|
+
resolve();
|
473
|
+
} else {
|
474
|
+
console.log('Waiting for Socket.IO...');
|
475
|
+
setTimeout(() => waitForSocketIO().then(resolve), 100);
|
476
|
+
}
|
477
|
+
});
|
478
|
+
}
|
479
|
+
|
480
|
+
// Initialize after Socket.IO is ready
|
481
|
+
await waitForSocketIO();
|
482
|
+
console.log('Starting dashboard initialization...');
|
483
|
+
// Import navigation component
|
484
|
+
import { NavBar } from '/static/built/components/nav-bar.js';
|
485
|
+
|
486
|
+
// Initialize navigation
|
487
|
+
const navBar = new NavBar();
|
488
|
+
navBar.initialize('navigation-container');
|
489
|
+
</script>
|
490
|
+
|
491
|
+
<script>
|
492
|
+
// Tool storage and state management
|
493
|
+
const appState = {
|
494
|
+
tools: new Map(),
|
495
|
+
isConnected: false,
|
496
|
+
stats: {
|
497
|
+
totalCalls: 0,
|
498
|
+
successfulCalls: 0,
|
499
|
+
failedCalls: 0,
|
500
|
+
totalDuration: 0
|
501
|
+
}
|
502
|
+
};
|
503
|
+
|
504
|
+
// Socket.IO connection
|
505
|
+
const socket = io('http://localhost:8765', {
|
506
|
+
transports: ['polling', 'websocket'],
|
507
|
+
reconnection: true,
|
508
|
+
reconnectionDelay: 1000,
|
509
|
+
reconnectionDelayMax: 5000,
|
510
|
+
reconnectionAttempts: Infinity
|
511
|
+
});
|
512
|
+
|
513
|
+
console.log('Initializing Socket.IO connection for tools monitoring');
|
514
|
+
|
515
|
+
// Socket event handlers
|
516
|
+
socket.on('connect', () => {
|
517
|
+
console.log('Connected to Socket.IO server');
|
518
|
+
appState.isConnected = true;
|
519
|
+
updateConnectionStatus(true);
|
520
|
+
|
521
|
+
// Request tool data
|
522
|
+
socket.emit('get_history', { type: 'tool', limit: 100 });
|
523
|
+
});
|
524
|
+
|
525
|
+
socket.on('disconnect', () => {
|
526
|
+
console.log('Disconnected from Socket.IO server');
|
527
|
+
appState.isConnected = false;
|
528
|
+
updateConnectionStatus(false);
|
529
|
+
});
|
530
|
+
|
531
|
+
// Handle claude events - be more comprehensive
|
532
|
+
socket.on('claude_event', (data) => {
|
533
|
+
console.log('Received event:', data);
|
534
|
+
|
535
|
+
// Check for tool-related events in multiple ways
|
536
|
+
const isToolEvent =
|
537
|
+
(data.type && (
|
538
|
+
data.type.includes('tool') ||
|
539
|
+
data.type === 'ToolCall' ||
|
540
|
+
data.type === 'tool_call' ||
|
541
|
+
data.type === 'tool_start' ||
|
542
|
+
data.type === 'tool_complete' ||
|
543
|
+
data.type === 'tool_error'
|
544
|
+
)) ||
|
545
|
+
(data.event_type && data.event_type.includes('tool')) ||
|
546
|
+
data.tool_name ||
|
547
|
+
data.tool ||
|
548
|
+
data.data?.tool_name ||
|
549
|
+
data.data?.tool ||
|
550
|
+
(data.data?.type && data.data.type.includes('tool'));
|
551
|
+
|
552
|
+
if (isToolEvent) {
|
553
|
+
console.log('Processing tool event:', data);
|
554
|
+
processToolEvent(data);
|
555
|
+
}
|
556
|
+
});
|
557
|
+
|
558
|
+
// Update connection status
|
559
|
+
function updateConnectionStatus(connected) {
|
560
|
+
const statusDot = document.getElementById('connection-status');
|
561
|
+
const statusText = document.getElementById('connection-text');
|
562
|
+
|
563
|
+
if (statusDot && statusText) {
|
564
|
+
statusDot.className = `status-dot ${connected ? 'connected' : 'disconnected'}`;
|
565
|
+
statusText.textContent = connected ? 'Connected' : 'Disconnected';
|
566
|
+
}
|
567
|
+
}
|
568
|
+
|
569
|
+
// Get tool icon based on name/type
|
570
|
+
function getToolIcon(toolName) {
|
571
|
+
const name = toolName.toLowerCase();
|
572
|
+
if (name.includes('read')) return '📖';
|
573
|
+
if (name.includes('write')) return '✍️';
|
574
|
+
if (name.includes('edit')) return '✏️';
|
575
|
+
if (name.includes('bash') || name.includes('shell')) return '💻';
|
576
|
+
if (name.includes('grep') || name.includes('search')) return '🔍';
|
577
|
+
if (name.includes('glob') || name.includes('find')) return '📁';
|
578
|
+
if (name.includes('web')) return '🌐';
|
579
|
+
if (name.includes('todo')) return '📝';
|
580
|
+
if (name.includes('notebook')) return '📓';
|
581
|
+
return '🔧';
|
582
|
+
}
|
583
|
+
|
584
|
+
// Process tool events
|
585
|
+
function processToolEvent(event) {
|
586
|
+
const toolName = event.tool_name || event.tool || event.data?.tool_name ||
|
587
|
+
event.data?.tool || 'Unknown Tool';
|
588
|
+
|
589
|
+
const agentName = event.agent_name || event.data?.agent_name ||
|
590
|
+
event.agent || event.data?.agent || 'Unknown Agent';
|
591
|
+
|
592
|
+
const params = event.parameters || event.data?.parameters ||
|
593
|
+
event.params || event.data?.params || {};
|
594
|
+
|
595
|
+
if (!appState.tools.has(toolName)) {
|
596
|
+
appState.tools.set(toolName, {
|
597
|
+
name: toolName,
|
598
|
+
icon: getToolIcon(toolName),
|
599
|
+
calls: 0,
|
600
|
+
successful: 0,
|
601
|
+
failed: 0,
|
602
|
+
running: 0,
|
603
|
+
totalDuration: 0,
|
604
|
+
lastActivity: Date.now(),
|
605
|
+
lastAgent: agentName,
|
606
|
+
events: []
|
607
|
+
});
|
608
|
+
}
|
609
|
+
|
610
|
+
const tool = appState.tools.get(toolName);
|
611
|
+
tool.lastActivity = Date.now();
|
612
|
+
tool.lastAgent = agentName;
|
613
|
+
tool.events.push({
|
614
|
+
timestamp: Date.now(),
|
615
|
+
type: event.type || event.event_type || 'call',
|
616
|
+
agent: agentName,
|
617
|
+
params: params,
|
618
|
+
data: event
|
619
|
+
});
|
620
|
+
|
621
|
+
// Update tool stats based on event type
|
622
|
+
const eventType = (event.type || event.event_type || '').toLowerCase();
|
623
|
+
|
624
|
+
if (eventType.includes('start') || eventType.includes('call') || eventType === 'toolcall') {
|
625
|
+
tool.calls++;
|
626
|
+
tool.running++;
|
627
|
+
appState.stats.totalCalls++;
|
628
|
+
} else if (eventType.includes('complete') || eventType.includes('success')) {
|
629
|
+
tool.successful++;
|
630
|
+
if (tool.running > 0) tool.running--;
|
631
|
+
appState.stats.successfulCalls++;
|
632
|
+
|
633
|
+
// Update duration if available
|
634
|
+
if (event.duration) {
|
635
|
+
tool.totalDuration += event.duration;
|
636
|
+
appState.stats.totalDuration += event.duration;
|
637
|
+
}
|
638
|
+
} else if (eventType.includes('error') || eventType.includes('fail')) {
|
639
|
+
tool.failed++;
|
640
|
+
if (tool.running > 0) tool.running--;
|
641
|
+
appState.stats.failedCalls++;
|
642
|
+
}
|
643
|
+
|
644
|
+
// Keep only last 10 events per tool
|
645
|
+
if (tool.events.length > 10) {
|
646
|
+
tool.events = tool.events.slice(-10);
|
647
|
+
}
|
648
|
+
|
649
|
+
updateUI();
|
650
|
+
}
|
651
|
+
|
652
|
+
// Format time ago
|
653
|
+
function formatTimeAgo(timestamp) {
|
654
|
+
const diff = Date.now() - timestamp;
|
655
|
+
const seconds = Math.floor(diff / 1000);
|
656
|
+
const minutes = Math.floor(seconds / 60);
|
657
|
+
const hours = Math.floor(minutes / 60);
|
658
|
+
|
659
|
+
if (hours > 0) return `${hours}h ago`;
|
660
|
+
if (minutes > 0) return `${minutes}m ago`;
|
661
|
+
return `${seconds}s ago`;
|
662
|
+
}
|
663
|
+
|
664
|
+
// Format parameter for display
|
665
|
+
function formatParam(key, value) {
|
666
|
+
if (typeof value === 'string' && value.length > 50) {
|
667
|
+
return `${key}: ${value.substring(0, 50)}...`;
|
668
|
+
}
|
669
|
+
if (typeof value === 'object') {
|
670
|
+
return `${key}: [object]`;
|
671
|
+
}
|
672
|
+
return `${key}: ${value}`;
|
673
|
+
}
|
674
|
+
|
675
|
+
// Render tool item
|
676
|
+
function renderToolItem(tool) {
|
677
|
+
const successRate = tool.calls > 0
|
678
|
+
? Math.round((tool.successful / tool.calls) * 100)
|
679
|
+
: 100;
|
680
|
+
|
681
|
+
const avgDuration = tool.successful > 0
|
682
|
+
? Math.round(tool.totalDuration / tool.successful)
|
683
|
+
: 0;
|
684
|
+
|
685
|
+
const recentEvents = tool.events.slice(-5).reverse();
|
686
|
+
|
687
|
+
return `
|
688
|
+
<div class="tool-item" data-tool-name="${tool.name}">
|
689
|
+
<div class="tool-header">
|
690
|
+
<div class="tool-name">
|
691
|
+
<span class="tool-icon">${tool.icon}</span>
|
692
|
+
<span>${tool.name}</span>
|
693
|
+
</div>
|
694
|
+
<div class="tool-badges">
|
695
|
+
<span class="tool-badge success">✓ ${tool.successful}</span>
|
696
|
+
${tool.failed > 0 ? `<span class="tool-badge error">✗ ${tool.failed}</span>` : ''}
|
697
|
+
${tool.running > 0 ? `<span class="tool-badge running">⟳ ${tool.running}</span>` : ''}
|
698
|
+
</div>
|
699
|
+
</div>
|
700
|
+
<div class="tool-stats">
|
701
|
+
<div class="tool-stat">
|
702
|
+
📊 ${tool.calls} calls
|
703
|
+
</div>
|
704
|
+
<div class="tool-stat">
|
705
|
+
✅ ${successRate}% success
|
706
|
+
</div>
|
707
|
+
<div class="tool-stat">
|
708
|
+
⏱️ ${avgDuration}ms avg
|
709
|
+
</div>
|
710
|
+
<div class="tool-stat">
|
711
|
+
🤖 ${tool.lastAgent}
|
712
|
+
</div>
|
713
|
+
<div class="tool-stat">
|
714
|
+
🕐 ${formatTimeAgo(tool.lastActivity)}
|
715
|
+
</div>
|
716
|
+
</div>
|
717
|
+
${recentEvents.length > 0 ? `
|
718
|
+
<div class="tool-timeline">
|
719
|
+
${recentEvents.map(evt => `
|
720
|
+
<div class="timeline-event">
|
721
|
+
<span class="timeline-time">${new Date(evt.timestamp).toLocaleTimeString('en-US', {
|
722
|
+
hour: '2-digit',
|
723
|
+
minute: '2-digit',
|
724
|
+
second: '2-digit'
|
725
|
+
})}</span>
|
726
|
+
<span class="timeline-status tool-badge ${evt.type.includes('error') ? 'error' : evt.type.includes('complete') || evt.type.includes('success') ? 'success' : 'running'}">
|
727
|
+
${evt.type.toUpperCase().replace(/_/g, ' ')}
|
728
|
+
</span>
|
729
|
+
<span class="timeline-agent">by ${evt.agent}</span>
|
730
|
+
</div>
|
731
|
+
`).join('')}
|
732
|
+
</div>
|
733
|
+
` : ''}
|
734
|
+
</div>
|
735
|
+
`;
|
736
|
+
}
|
737
|
+
|
738
|
+
// Update UI
|
739
|
+
function updateUI() {
|
740
|
+
// Update header stats
|
741
|
+
document.getElementById('total-calls').textContent = `${appState.stats.totalCalls} calls`;
|
742
|
+
document.getElementById('successful-calls').textContent = `${appState.stats.successfulCalls} successful`;
|
743
|
+
document.getElementById('failed-calls').textContent = `${appState.stats.failedCalls} failed`;
|
744
|
+
|
745
|
+
// Update statistics cards
|
746
|
+
document.getElementById('totalTools').textContent = appState.tools.size;
|
747
|
+
document.getElementById('totalCalls').textContent = appState.stats.totalCalls;
|
748
|
+
|
749
|
+
const successRate = appState.stats.totalCalls > 0
|
750
|
+
? Math.round((appState.stats.successfulCalls / appState.stats.totalCalls) * 100)
|
751
|
+
: 100;
|
752
|
+
document.getElementById('successRate').textContent = `${successRate}%`;
|
753
|
+
|
754
|
+
const avgDuration = appState.stats.successfulCalls > 0
|
755
|
+
? Math.round(appState.stats.totalDuration / appState.stats.successfulCalls)
|
756
|
+
: 0;
|
757
|
+
document.getElementById('avgDuration').textContent = `${avgDuration}ms`;
|
758
|
+
|
759
|
+
// Get filters
|
760
|
+
const searchTerm = document.getElementById('searchBox').value.toLowerCase();
|
761
|
+
const typeFilter = document.getElementById('typeFilter').value;
|
762
|
+
const sortBy = document.getElementById('sortBy').value;
|
763
|
+
|
764
|
+
// Filter tools
|
765
|
+
let filteredTools = Array.from(appState.tools.values());
|
766
|
+
|
767
|
+
if (searchTerm) {
|
768
|
+
filteredTools = filteredTools.filter(tool =>
|
769
|
+
tool.name.toLowerCase().includes(searchTerm) ||
|
770
|
+
tool.lastAgent.toLowerCase().includes(searchTerm)
|
771
|
+
);
|
772
|
+
}
|
773
|
+
|
774
|
+
if (typeFilter) {
|
775
|
+
filteredTools = filteredTools.filter(tool =>
|
776
|
+
tool.name.includes(typeFilter)
|
777
|
+
);
|
778
|
+
}
|
779
|
+
|
780
|
+
// Sort tools
|
781
|
+
if (sortBy === 'recent') {
|
782
|
+
filteredTools.sort((a, b) => b.lastActivity - a.lastActivity);
|
783
|
+
} else if (sortBy === 'calls') {
|
784
|
+
filteredTools.sort((a, b) => b.calls - a.calls);
|
785
|
+
} else if (sortBy === 'name') {
|
786
|
+
filteredTools.sort((a, b) => a.name.localeCompare(b.name));
|
787
|
+
}
|
788
|
+
|
789
|
+
// Render tools list
|
790
|
+
const toolsList = document.getElementById('toolsList');
|
791
|
+
if (filteredTools.length === 0) {
|
792
|
+
toolsList.innerHTML = `
|
793
|
+
<div class="no-tools">
|
794
|
+
<h3>No Tools Found</h3>
|
795
|
+
<p>${searchTerm || typeFilter ? 'Try different filters' : 'Waiting for tool events from the server...'}</p>
|
796
|
+
</div>
|
797
|
+
`;
|
798
|
+
} else {
|
799
|
+
toolsList.innerHTML = filteredTools.map(renderToolItem).join('');
|
800
|
+
}
|
801
|
+
}
|
802
|
+
|
803
|
+
// Event handlers
|
804
|
+
document.getElementById('searchBox').addEventListener('input', updateUI);
|
805
|
+
document.getElementById('typeFilter').addEventListener('change', updateUI);
|
806
|
+
document.getElementById('sortBy').addEventListener('change', updateUI);
|
807
|
+
|
808
|
+
document.getElementById('refreshTools').addEventListener('click', () => {
|
809
|
+
socket.emit('get_history', { type: 'tool', limit: 100 });
|
810
|
+
});
|
811
|
+
|
812
|
+
document.getElementById('clearTools').addEventListener('click', () => {
|
813
|
+
if (confirm('Clear all tool data?')) {
|
814
|
+
appState.tools.clear();
|
815
|
+
appState.stats = {
|
816
|
+
totalCalls: 0,
|
817
|
+
successfulCalls: 0,
|
818
|
+
failedCalls: 0,
|
819
|
+
totalDuration: 0
|
820
|
+
};
|
821
|
+
updateUI();
|
822
|
+
}
|
823
|
+
});
|
824
|
+
|
825
|
+
// Initial UI update
|
826
|
+
updateUI();
|
827
|
+
|
828
|
+
console.log('Tools monitor initialized');
|
829
|
+
</script>
|
830
|
+
</body>
|
831
|
+
</html>
|