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,747 @@
|
|
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 - Files 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
|
+
.files-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
|
+
.file-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 #06b6d4;
|
230
|
+
transition: all 0.3s;
|
231
|
+
cursor: pointer;
|
232
|
+
}
|
233
|
+
|
234
|
+
.file-item:hover {
|
235
|
+
background: rgba(255, 255, 255, 0.08);
|
236
|
+
transform: translateX(5px);
|
237
|
+
}
|
238
|
+
|
239
|
+
.file-header {
|
240
|
+
display: flex;
|
241
|
+
justify-content: space-between;
|
242
|
+
align-items: center;
|
243
|
+
margin-bottom: 10px;
|
244
|
+
}
|
245
|
+
|
246
|
+
.file-path {
|
247
|
+
font-family: 'Monaco', 'Menlo', monospace;
|
248
|
+
font-size: 14px;
|
249
|
+
color: #06b6d4;
|
250
|
+
word-break: break-all;
|
251
|
+
}
|
252
|
+
|
253
|
+
.file-operations {
|
254
|
+
display: flex;
|
255
|
+
gap: 10px;
|
256
|
+
}
|
257
|
+
|
258
|
+
.operation-badge {
|
259
|
+
padding: 3px 8px;
|
260
|
+
border-radius: 12px;
|
261
|
+
font-size: 11px;
|
262
|
+
font-weight: 600;
|
263
|
+
}
|
264
|
+
|
265
|
+
.operation-badge.read {
|
266
|
+
background: rgba(96, 165, 250, 0.2);
|
267
|
+
color: #60a5fa;
|
268
|
+
}
|
269
|
+
|
270
|
+
.operation-badge.write {
|
271
|
+
background: rgba(74, 222, 128, 0.2);
|
272
|
+
color: #4ade80;
|
273
|
+
}
|
274
|
+
|
275
|
+
.operation-badge.edit {
|
276
|
+
background: rgba(251, 191, 36, 0.2);
|
277
|
+
color: #fbbf24;
|
278
|
+
}
|
279
|
+
|
280
|
+
.file-stats {
|
281
|
+
display: flex;
|
282
|
+
gap: 20px;
|
283
|
+
font-size: 13px;
|
284
|
+
color: #94a3b8;
|
285
|
+
}
|
286
|
+
|
287
|
+
.file-stat {
|
288
|
+
display: flex;
|
289
|
+
align-items: center;
|
290
|
+
gap: 5px;
|
291
|
+
}
|
292
|
+
|
293
|
+
.file-timeline {
|
294
|
+
margin-top: 10px;
|
295
|
+
padding-top: 10px;
|
296
|
+
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
297
|
+
max-height: 200px;
|
298
|
+
overflow-y: auto;
|
299
|
+
}
|
300
|
+
|
301
|
+
.timeline-event {
|
302
|
+
display: flex;
|
303
|
+
align-items: center;
|
304
|
+
gap: 10px;
|
305
|
+
padding: 5px 0;
|
306
|
+
font-size: 12px;
|
307
|
+
}
|
308
|
+
|
309
|
+
.timeline-time {
|
310
|
+
color: #64748b;
|
311
|
+
min-width: 60px;
|
312
|
+
}
|
313
|
+
|
314
|
+
.timeline-operation {
|
315
|
+
padding: 2px 6px;
|
316
|
+
border-radius: 8px;
|
317
|
+
font-size: 11px;
|
318
|
+
}
|
319
|
+
|
320
|
+
.no-files {
|
321
|
+
text-align: center;
|
322
|
+
padding: 60px 20px;
|
323
|
+
color: rgba(255, 255, 255, 0.5);
|
324
|
+
}
|
325
|
+
|
326
|
+
/* Navigation styles will be injected by nav-bar.js */
|
327
|
+
|
328
|
+
/* Scrollbar styling */
|
329
|
+
::-webkit-scrollbar {
|
330
|
+
width: 8px;
|
331
|
+
height: 8px;
|
332
|
+
}
|
333
|
+
|
334
|
+
::-webkit-scrollbar-track {
|
335
|
+
background: rgba(255, 255, 255, 0.05);
|
336
|
+
border-radius: 4px;
|
337
|
+
}
|
338
|
+
|
339
|
+
::-webkit-scrollbar-thumb {
|
340
|
+
background: rgba(255, 255, 255, 0.2);
|
341
|
+
border-radius: 4px;
|
342
|
+
}
|
343
|
+
|
344
|
+
::-webkit-scrollbar-thumb:hover {
|
345
|
+
background: rgba(255, 255, 255, 0.3);
|
346
|
+
}
|
347
|
+
</style>
|
348
|
+
</head>
|
349
|
+
<body>
|
350
|
+
<div class="container">
|
351
|
+
<!-- Header with standardized structure -->
|
352
|
+
<div class="header">
|
353
|
+
<h1>📁 Files Dashboard</h1>
|
354
|
+
<div class="status-bar">
|
355
|
+
<div class="status-indicator">
|
356
|
+
<span class="status-dot disconnected" id="connection-status"></span>
|
357
|
+
<span id="connection-text">Disconnected</span>
|
358
|
+
</div>
|
359
|
+
<div class="status-indicator">
|
360
|
+
<span>📖</span>
|
361
|
+
<span id="total-reads">0 reads</span>
|
362
|
+
</div>
|
363
|
+
<div class="status-indicator">
|
364
|
+
<span>✍️</span>
|
365
|
+
<span id="total-writes">0 writes</span>
|
366
|
+
</div>
|
367
|
+
<div class="status-indicator">
|
368
|
+
<span>✏️</span>
|
369
|
+
<span id="total-edits">0 edits</span>
|
370
|
+
</div>
|
371
|
+
</div>
|
372
|
+
</div>
|
373
|
+
|
374
|
+
<!-- Navigation Bar -->
|
375
|
+
<div id="navigation-container"></div>
|
376
|
+
|
377
|
+
<!-- Statistics Panel -->
|
378
|
+
<div class="stats-panel">
|
379
|
+
<div class="stat-card">
|
380
|
+
<div class="stat-icon">📖</div>
|
381
|
+
<div class="stat-info">
|
382
|
+
<div class="stat-label">Reads</div>
|
383
|
+
<div class="stat-value" id="readCount">0</div>
|
384
|
+
</div>
|
385
|
+
</div>
|
386
|
+
<div class="stat-card">
|
387
|
+
<div class="stat-icon">✍️</div>
|
388
|
+
<div class="stat-info">
|
389
|
+
<div class="stat-label">Writes</div>
|
390
|
+
<div class="stat-value" id="writeCount">0</div>
|
391
|
+
</div>
|
392
|
+
</div>
|
393
|
+
<div class="stat-card">
|
394
|
+
<div class="stat-icon">✏️</div>
|
395
|
+
<div class="stat-info">
|
396
|
+
<div class="stat-label">Edits</div>
|
397
|
+
<div class="stat-value" id="editCount">0</div>
|
398
|
+
</div>
|
399
|
+
</div>
|
400
|
+
<div class="stat-card">
|
401
|
+
<div class="stat-icon">📊</div>
|
402
|
+
<div class="stat-info">
|
403
|
+
<div class="stat-label">Total Operations</div>
|
404
|
+
<div class="stat-value" id="totalOperations">0</div>
|
405
|
+
</div>
|
406
|
+
</div>
|
407
|
+
</div>
|
408
|
+
|
409
|
+
<!-- Controls Panel -->
|
410
|
+
<div class="controls-panel">
|
411
|
+
<div class="control-group">
|
412
|
+
<input type="text" id="searchBox" placeholder="Search files...">
|
413
|
+
</div>
|
414
|
+
<div class="control-group">
|
415
|
+
<label class="control-label">Operation:</label>
|
416
|
+
<select id="operationFilter">
|
417
|
+
<option value="">All Operations</option>
|
418
|
+
<option value="read">Read</option>
|
419
|
+
<option value="write">Write</option>
|
420
|
+
<option value="edit">Edit</option>
|
421
|
+
</select>
|
422
|
+
</div>
|
423
|
+
<div class="control-group">
|
424
|
+
<label class="control-label">Sort by:</label>
|
425
|
+
<select id="sortBy">
|
426
|
+
<option value="recent">Most Recent</option>
|
427
|
+
<option value="operations">Most Operations</option>
|
428
|
+
<option value="name">File Name</option>
|
429
|
+
</select>
|
430
|
+
</div>
|
431
|
+
<button class="btn btn-secondary" id="refreshFiles">Refresh</button>
|
432
|
+
<button class="btn" id="clearFiles">Clear All</button>
|
433
|
+
</div>
|
434
|
+
|
435
|
+
<!-- Files List -->
|
436
|
+
<div class="files-list" id="filesList">
|
437
|
+
<div class="no-files">
|
438
|
+
<h3>No File Operations Yet</h3>
|
439
|
+
<p>Waiting for file events from the server...</p>
|
440
|
+
</div>
|
441
|
+
</div>
|
442
|
+
</div>
|
443
|
+
|
444
|
+
<script type="module">
|
445
|
+
// Wait for Socket.IO to be available
|
446
|
+
function waitForSocketIO() {
|
447
|
+
return new Promise((resolve) => {
|
448
|
+
if (typeof io !== 'undefined') {
|
449
|
+
console.log('Socket.IO is ready');
|
450
|
+
resolve();
|
451
|
+
} else {
|
452
|
+
console.log('Waiting for Socket.IO...');
|
453
|
+
setTimeout(() => waitForSocketIO().then(resolve), 100);
|
454
|
+
}
|
455
|
+
});
|
456
|
+
}
|
457
|
+
|
458
|
+
// Initialize after Socket.IO is ready
|
459
|
+
await waitForSocketIO();
|
460
|
+
console.log('Starting dashboard initialization...');
|
461
|
+
// Import navigation component
|
462
|
+
import { NavBar } from '/static/built/components/nav-bar.js';
|
463
|
+
|
464
|
+
// Initialize navigation
|
465
|
+
const navBar = new NavBar();
|
466
|
+
navBar.initialize('navigation-container');
|
467
|
+
</script>
|
468
|
+
|
469
|
+
<script>
|
470
|
+
// File storage and state management
|
471
|
+
const appState = {
|
472
|
+
files: new Map(),
|
473
|
+
isConnected: false,
|
474
|
+
stats: {
|
475
|
+
readCount: 0,
|
476
|
+
writeCount: 0,
|
477
|
+
editCount: 0
|
478
|
+
}
|
479
|
+
};
|
480
|
+
|
481
|
+
// Socket.IO connection
|
482
|
+
const socket = io('http://localhost:8765', {
|
483
|
+
transports: ['polling', 'websocket'],
|
484
|
+
reconnection: true,
|
485
|
+
reconnectionDelay: 1000,
|
486
|
+
reconnectionDelayMax: 5000,
|
487
|
+
reconnectionAttempts: Infinity
|
488
|
+
});
|
489
|
+
|
490
|
+
console.log('Initializing Socket.IO connection for files monitoring');
|
491
|
+
|
492
|
+
// Socket event handlers
|
493
|
+
socket.on('connect', () => {
|
494
|
+
console.log('Connected to Socket.IO server');
|
495
|
+
appState.isConnected = true;
|
496
|
+
updateConnectionStatus(true);
|
497
|
+
|
498
|
+
// Request file data
|
499
|
+
socket.emit('get_history', { type: 'file', limit: 100 });
|
500
|
+
});
|
501
|
+
|
502
|
+
socket.on('disconnect', () => {
|
503
|
+
console.log('Disconnected from Socket.IO server');
|
504
|
+
appState.isConnected = false;
|
505
|
+
updateConnectionStatus(false);
|
506
|
+
});
|
507
|
+
|
508
|
+
// Handle claude events
|
509
|
+
socket.on('claude_event', (data) => {
|
510
|
+
if (data.type && (data.type.includes('file') ||
|
511
|
+
data.type === 'read' ||
|
512
|
+
data.type === 'write' ||
|
513
|
+
data.type === 'edit')) {
|
514
|
+
console.log('Received file event:', data);
|
515
|
+
processFileEvent(data);
|
516
|
+
} else if (data.file_path || data.data?.file_path) {
|
517
|
+
console.log('Received file-related event:', data);
|
518
|
+
processFileEvent(data);
|
519
|
+
}
|
520
|
+
});
|
521
|
+
|
522
|
+
// Update connection status
|
523
|
+
function updateConnectionStatus(connected) {
|
524
|
+
const statusDot = document.getElementById('connection-status');
|
525
|
+
const statusText = document.getElementById('connection-text');
|
526
|
+
|
527
|
+
if (statusDot && statusText) {
|
528
|
+
statusDot.className = `status-dot ${connected ? 'connected' : 'disconnected'}`;
|
529
|
+
statusText.textContent = connected ? 'Connected' : 'Disconnected';
|
530
|
+
}
|
531
|
+
}
|
532
|
+
|
533
|
+
// Process file events
|
534
|
+
function processFileEvent(event) {
|
535
|
+
const filePath = event.file_path || event.data?.file_path || event.data?.path || 'unknown';
|
536
|
+
const operation = detectOperation(event);
|
537
|
+
|
538
|
+
if (!appState.files.has(filePath)) {
|
539
|
+
appState.files.set(filePath, {
|
540
|
+
path: filePath,
|
541
|
+
reads: 0,
|
542
|
+
writes: 0,
|
543
|
+
edits: 0,
|
544
|
+
lastActivity: Date.now(),
|
545
|
+
events: []
|
546
|
+
});
|
547
|
+
}
|
548
|
+
|
549
|
+
const file = appState.files.get(filePath);
|
550
|
+
file.lastActivity = Date.now();
|
551
|
+
file.events.push({
|
552
|
+
operation: operation,
|
553
|
+
timestamp: Date.now(),
|
554
|
+
event: event
|
555
|
+
});
|
556
|
+
|
557
|
+
// Update stats based on operation
|
558
|
+
if (operation === 'read') {
|
559
|
+
file.reads++;
|
560
|
+
appState.stats.readCount++;
|
561
|
+
} else if (operation === 'write') {
|
562
|
+
file.writes++;
|
563
|
+
appState.stats.writeCount++;
|
564
|
+
} else if (operation === 'edit') {
|
565
|
+
file.edits++;
|
566
|
+
appState.stats.editCount++;
|
567
|
+
}
|
568
|
+
|
569
|
+
updateUI();
|
570
|
+
}
|
571
|
+
|
572
|
+
// Detect operation type from event
|
573
|
+
function detectOperation(event) {
|
574
|
+
const type = (event.type || '').toLowerCase();
|
575
|
+
const tool = (event.tool_name || event.data?.tool || '').toLowerCase();
|
576
|
+
|
577
|
+
if (type.includes('read') || tool.includes('read')) return 'read';
|
578
|
+
if (type.includes('write') || tool.includes('write')) return 'write';
|
579
|
+
if (type.includes('edit') || tool.includes('edit')) return 'edit';
|
580
|
+
|
581
|
+
// Default based on common patterns
|
582
|
+
if (type === 'file_read') return 'read';
|
583
|
+
if (type === 'file_write') return 'write';
|
584
|
+
if (type === 'file_edit' || type === 'file_modified') return 'edit';
|
585
|
+
|
586
|
+
return 'read'; // default
|
587
|
+
}
|
588
|
+
|
589
|
+
// Format file path for display
|
590
|
+
function formatPath(path) {
|
591
|
+
// Shorten long paths
|
592
|
+
if (path.length > 60) {
|
593
|
+
const parts = path.split('/');
|
594
|
+
if (parts.length > 4) {
|
595
|
+
return `.../${parts.slice(-3).join('/')}`;
|
596
|
+
}
|
597
|
+
}
|
598
|
+
return path;
|
599
|
+
}
|
600
|
+
|
601
|
+
// Format time ago
|
602
|
+
function formatTimeAgo(timestamp) {
|
603
|
+
const diff = Date.now() - timestamp;
|
604
|
+
const seconds = Math.floor(diff / 1000);
|
605
|
+
const minutes = Math.floor(seconds / 60);
|
606
|
+
const hours = Math.floor(minutes / 60);
|
607
|
+
|
608
|
+
if (hours > 0) return `${hours}h ago`;
|
609
|
+
if (minutes > 0) return `${minutes}m ago`;
|
610
|
+
return `${seconds}s ago`;
|
611
|
+
}
|
612
|
+
|
613
|
+
// Render file item
|
614
|
+
function renderFileItem(file) {
|
615
|
+
const totalOps = file.reads + file.writes + file.edits;
|
616
|
+
const recentEvents = file.events.slice(-5).reverse();
|
617
|
+
|
618
|
+
return `
|
619
|
+
<div class="file-item" data-file-path="${file.path}">
|
620
|
+
<div class="file-header">
|
621
|
+
<div class="file-path">${formatPath(file.path)}</div>
|
622
|
+
<div class="file-operations">
|
623
|
+
${file.reads > 0 ? `<span class="operation-badge read">R: ${file.reads}</span>` : ''}
|
624
|
+
${file.writes > 0 ? `<span class="operation-badge write">W: ${file.writes}</span>` : ''}
|
625
|
+
${file.edits > 0 ? `<span class="operation-badge edit">E: ${file.edits}</span>` : ''}
|
626
|
+
</div>
|
627
|
+
</div>
|
628
|
+
<div class="file-stats">
|
629
|
+
<div class="file-stat">
|
630
|
+
📊 ${totalOps} operations
|
631
|
+
</div>
|
632
|
+
<div class="file-stat">
|
633
|
+
⏱️ ${formatTimeAgo(file.lastActivity)}
|
634
|
+
</div>
|
635
|
+
</div>
|
636
|
+
${recentEvents.length > 0 ? `
|
637
|
+
<div class="file-timeline">
|
638
|
+
${recentEvents.map(evt => `
|
639
|
+
<div class="timeline-event">
|
640
|
+
<span class="timeline-time">${new Date(evt.timestamp).toLocaleTimeString('en-US', {
|
641
|
+
hour: '2-digit',
|
642
|
+
minute: '2-digit',
|
643
|
+
second: '2-digit'
|
644
|
+
})}</span>
|
645
|
+
<span class="timeline-operation operation-badge ${evt.operation}">
|
646
|
+
${evt.operation.toUpperCase()}
|
647
|
+
</span>
|
648
|
+
</div>
|
649
|
+
`).join('')}
|
650
|
+
</div>
|
651
|
+
` : ''}
|
652
|
+
</div>
|
653
|
+
`;
|
654
|
+
}
|
655
|
+
|
656
|
+
// Update UI
|
657
|
+
function updateUI() {
|
658
|
+
// Update header stats
|
659
|
+
document.getElementById('total-reads').textContent = `${appState.stats.readCount} reads`;
|
660
|
+
document.getElementById('total-writes').textContent = `${appState.stats.writeCount} writes`;
|
661
|
+
document.getElementById('total-edits').textContent = `${appState.stats.editCount} edits`;
|
662
|
+
|
663
|
+
// Update statistics cards
|
664
|
+
document.getElementById('readCount').textContent = appState.stats.readCount;
|
665
|
+
document.getElementById('writeCount').textContent = appState.stats.writeCount;
|
666
|
+
document.getElementById('editCount').textContent = appState.stats.editCount;
|
667
|
+
document.getElementById('totalOperations').textContent =
|
668
|
+
appState.stats.readCount + appState.stats.writeCount + appState.stats.editCount;
|
669
|
+
|
670
|
+
// Get filters
|
671
|
+
const searchTerm = document.getElementById('searchBox').value.toLowerCase();
|
672
|
+
const operationFilter = document.getElementById('operationFilter').value;
|
673
|
+
const sortBy = document.getElementById('sortBy').value;
|
674
|
+
|
675
|
+
// Filter files
|
676
|
+
let filteredFiles = Array.from(appState.files.values());
|
677
|
+
|
678
|
+
if (searchTerm) {
|
679
|
+
filteredFiles = filteredFiles.filter(file =>
|
680
|
+
file.path.toLowerCase().includes(searchTerm)
|
681
|
+
);
|
682
|
+
}
|
683
|
+
|
684
|
+
if (operationFilter) {
|
685
|
+
filteredFiles = filteredFiles.filter(file => {
|
686
|
+
if (operationFilter === 'read') return file.reads > 0;
|
687
|
+
if (operationFilter === 'write') return file.writes > 0;
|
688
|
+
if (operationFilter === 'edit') return file.edits > 0;
|
689
|
+
return true;
|
690
|
+
});
|
691
|
+
}
|
692
|
+
|
693
|
+
// Sort files
|
694
|
+
if (sortBy === 'recent') {
|
695
|
+
filteredFiles.sort((a, b) => b.lastActivity - a.lastActivity);
|
696
|
+
} else if (sortBy === 'operations') {
|
697
|
+
filteredFiles.sort((a, b) => {
|
698
|
+
const aOps = a.reads + a.writes + a.edits;
|
699
|
+
const bOps = b.reads + b.writes + b.edits;
|
700
|
+
return bOps - aOps;
|
701
|
+
});
|
702
|
+
} else if (sortBy === 'name') {
|
703
|
+
filteredFiles.sort((a, b) => a.path.localeCompare(b.path));
|
704
|
+
}
|
705
|
+
|
706
|
+
// Render files list
|
707
|
+
const filesList = document.getElementById('filesList');
|
708
|
+
if (filteredFiles.length === 0) {
|
709
|
+
filesList.innerHTML = `
|
710
|
+
<div class="no-files">
|
711
|
+
<h3>No Files Found</h3>
|
712
|
+
<p>${searchTerm || operationFilter ? 'Try different filters' : 'Waiting for file events from the server...'}</p>
|
713
|
+
</div>
|
714
|
+
`;
|
715
|
+
} else {
|
716
|
+
filesList.innerHTML = filteredFiles.map(renderFileItem).join('');
|
717
|
+
}
|
718
|
+
}
|
719
|
+
|
720
|
+
// Event handlers
|
721
|
+
document.getElementById('searchBox').addEventListener('input', updateUI);
|
722
|
+
document.getElementById('operationFilter').addEventListener('change', updateUI);
|
723
|
+
document.getElementById('sortBy').addEventListener('change', updateUI);
|
724
|
+
|
725
|
+
document.getElementById('refreshFiles').addEventListener('click', () => {
|
726
|
+
socket.emit('get_history', { type: 'file', limit: 100 });
|
727
|
+
});
|
728
|
+
|
729
|
+
document.getElementById('clearFiles').addEventListener('click', () => {
|
730
|
+
if (confirm('Clear all file data?')) {
|
731
|
+
appState.files.clear();
|
732
|
+
appState.stats = {
|
733
|
+
readCount: 0,
|
734
|
+
writeCount: 0,
|
735
|
+
editCount: 0
|
736
|
+
};
|
737
|
+
updateUI();
|
738
|
+
}
|
739
|
+
});
|
740
|
+
|
741
|
+
// Initial UI update
|
742
|
+
updateUI();
|
743
|
+
|
744
|
+
console.log('Files monitor initialized');
|
745
|
+
</script>
|
746
|
+
</body>
|
747
|
+
</html>
|