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,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>