claude-mpm 5.1.9__py3-none-any.whl → 5.4.14__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.
Potentially problematic release.
This version of claude-mpm might be problematic. Click here for more details.
- claude_mpm/VERSION +1 -1
- claude_mpm/__init__.py +4 -0
- claude_mpm/agents/PM_INSTRUCTIONS.md +85 -0
- claude_mpm/agents/agent_loader.py +13 -44
- claude_mpm/agents/templates/circuit-breakers.md +138 -1
- claude_mpm/cli/__main__.py +4 -0
- claude_mpm/cli/commands/agent_state_manager.py +8 -17
- claude_mpm/cli/commands/auto_configure.py +210 -25
- claude_mpm/cli/commands/config.py +88 -2
- claude_mpm/cli/commands/configure.py +1097 -158
- claude_mpm/cli/commands/configure_agent_display.py +15 -6
- claude_mpm/cli/commands/mpm_init/core.py +160 -46
- claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
- claude_mpm/cli/commands/mpm_init/prompts.py +280 -0
- claude_mpm/cli/commands/skills.py +21 -2
- claude_mpm/cli/commands/summarize.py +413 -0
- claude_mpm/cli/executor.py +11 -3
- claude_mpm/cli/parsers/base_parser.py +5 -0
- claude_mpm/cli/parsers/config_parser.py +153 -83
- claude_mpm/cli/parsers/skills_parser.py +3 -2
- claude_mpm/cli/startup.py +333 -89
- claude_mpm/commands/mpm-config.md +266 -0
- claude_mpm/commands/{mpm-ticket-organize.md → mpm-organize.md} +4 -5
- claude_mpm/config/agent_sources.py +27 -0
- claude_mpm/core/framework/formatters/content_formatter.py +3 -13
- claude_mpm/core/framework/loaders/agent_loader.py +8 -5
- claude_mpm/core/framework_loader.py +4 -2
- claude_mpm/core/logger.py +13 -0
- claude_mpm/core/socketio_pool.py +3 -3
- claude_mpm/core/unified_agent_registry.py +5 -15
- claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +206 -78
- claude_mpm/hooks/claude_hooks/hook_handler.py +6 -0
- claude_mpm/hooks/claude_hooks/installer.py +33 -10
- claude_mpm/hooks/claude_hooks/memory_integration.py +26 -9
- claude_mpm/hooks/claude_hooks/response_tracking.py +2 -3
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +4 -0
- claude_mpm/hooks/memory_integration_hook.py +46 -1
- claude_mpm/init.py +0 -19
- claude_mpm/scripts/claude-hook-handler.sh +58 -18
- claude_mpm/scripts/launch_monitor.py +93 -13
- claude_mpm/services/agents/agent_recommendation_service.py +278 -0
- claude_mpm/services/agents/agent_review_service.py +280 -0
- claude_mpm/services/agents/deployment/agent_discovery_service.py +2 -3
- claude_mpm/services/agents/deployment/agent_template_builder.py +4 -2
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +78 -9
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +335 -53
- claude_mpm/services/agents/git_source_manager.py +34 -0
- claude_mpm/services/agents/loading/base_agent_manager.py +1 -13
- claude_mpm/services/agents/sources/git_source_sync_service.py +8 -1
- claude_mpm/services/agents/toolchain_detector.py +10 -6
- claude_mpm/services/analysis/__init__.py +11 -1
- claude_mpm/services/analysis/clone_detector.py +1030 -0
- claude_mpm/services/command_deployment_service.py +71 -10
- claude_mpm/services/event_bus/config.py +3 -1
- claude_mpm/services/git/git_operations_service.py +93 -8
- claude_mpm/services/monitor/daemon.py +9 -2
- claude_mpm/services/monitor/daemon_manager.py +39 -3
- claude_mpm/services/monitor/server.py +225 -19
- claude_mpm/services/self_upgrade_service.py +120 -12
- claude_mpm/services/skills/__init__.py +3 -0
- claude_mpm/services/skills/git_skill_source_manager.py +32 -2
- claude_mpm/services/skills/selective_skill_deployer.py +230 -0
- claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
- claude_mpm/services/skills_deployer.py +64 -3
- claude_mpm/services/socketio/event_normalizer.py +15 -1
- claude_mpm/services/socketio/server/core.py +160 -21
- claude_mpm/services/version_control/git_operations.py +103 -0
- claude_mpm/utils/agent_filters.py +17 -44
- {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.14.dist-info}/METADATA +47 -84
- {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.14.dist-info}/RECORD +76 -150
- claude_mpm-5.4.14.dist-info/entry_points.txt +5 -0
- claude_mpm-5.4.14.dist-info/licenses/LICENSE +94 -0
- claude_mpm-5.4.14.dist-info/licenses/LICENSE-FAQ.md +153 -0
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -292
- claude_mpm/agents/BASE_DOCUMENTATION.md +0 -53
- claude_mpm/agents/BASE_ENGINEER.md +0 -658
- claude_mpm/agents/BASE_OPS.md +0 -219
- claude_mpm/agents/BASE_PM.md +0 -480
- claude_mpm/agents/BASE_PROMPT_ENGINEER.md +0 -787
- claude_mpm/agents/BASE_QA.md +0 -167
- claude_mpm/agents/BASE_RESEARCH.md +0 -53
- claude_mpm/agents/base_agent.json +0 -31
- claude_mpm/agents/base_agent_loader.py +0 -601
- claude_mpm/cli/ticket_cli.py +0 -35
- claude_mpm/commands/mpm-config-view.md +0 -150
- claude_mpm/dashboard/analysis_runner.py +0 -455
- claude_mpm/dashboard/index.html +0 -13
- claude_mpm/dashboard/open_dashboard.py +0 -66
- claude_mpm/dashboard/static/css/activity.css +0 -1958
- claude_mpm/dashboard/static/css/connection-status.css +0 -370
- claude_mpm/dashboard/static/css/dashboard.css +0 -4701
- claude_mpm/dashboard/static/js/components/activity-tree.js +0 -1871
- claude_mpm/dashboard/static/js/components/agent-hierarchy.js +0 -777
- claude_mpm/dashboard/static/js/components/agent-inference.js +0 -956
- claude_mpm/dashboard/static/js/components/build-tracker.js +0 -333
- claude_mpm/dashboard/static/js/components/code-simple.js +0 -857
- claude_mpm/dashboard/static/js/components/connection-debug.js +0 -654
- claude_mpm/dashboard/static/js/components/diff-viewer.js +0 -891
- claude_mpm/dashboard/static/js/components/event-processor.js +0 -542
- claude_mpm/dashboard/static/js/components/event-viewer.js +0 -1155
- claude_mpm/dashboard/static/js/components/export-manager.js +0 -368
- claude_mpm/dashboard/static/js/components/file-change-tracker.js +0 -443
- claude_mpm/dashboard/static/js/components/file-change-viewer.js +0 -690
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +0 -724
- claude_mpm/dashboard/static/js/components/file-viewer.js +0 -580
- claude_mpm/dashboard/static/js/components/hud-library-loader.js +0 -211
- claude_mpm/dashboard/static/js/components/hud-manager.js +0 -671
- claude_mpm/dashboard/static/js/components/hud-visualizer.js +0 -1718
- claude_mpm/dashboard/static/js/components/module-viewer.js +0 -2764
- claude_mpm/dashboard/static/js/components/session-manager.js +0 -579
- claude_mpm/dashboard/static/js/components/socket-manager.js +0 -368
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +0 -749
- claude_mpm/dashboard/static/js/components/unified-data-viewer.js +0 -1824
- claude_mpm/dashboard/static/js/components/working-directory.js +0 -920
- claude_mpm/dashboard/static/js/connection-manager.js +0 -536
- claude_mpm/dashboard/static/js/dashboard.js +0 -1914
- claude_mpm/dashboard/static/js/extension-error-handler.js +0 -164
- claude_mpm/dashboard/static/js/socket-client.js +0 -1474
- claude_mpm/dashboard/static/js/tab-isolation-fix.js +0 -185
- claude_mpm/dashboard/static/socket.io.min.js +0 -7
- claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +0 -7
- claude_mpm/dashboard/templates/code_simple.html +0 -153
- claude_mpm/dashboard/templates/index.html +0 -606
- claude_mpm/dashboard/test_dashboard.html +0 -372
- claude_mpm/scripts/mcp_server.py +0 -75
- claude_mpm/scripts/mcp_wrapper.py +0 -39
- claude_mpm/services/mcp_gateway/__init__.py +0 -159
- claude_mpm/services/mcp_gateway/auto_configure.py +0 -369
- claude_mpm/services/mcp_gateway/config/__init__.py +0 -17
- claude_mpm/services/mcp_gateway/config/config_loader.py +0 -296
- claude_mpm/services/mcp_gateway/config/config_schema.py +0 -243
- claude_mpm/services/mcp_gateway/config/configuration.py +0 -429
- claude_mpm/services/mcp_gateway/core/__init__.py +0 -43
- claude_mpm/services/mcp_gateway/core/base.py +0 -312
- claude_mpm/services/mcp_gateway/core/exceptions.py +0 -253
- claude_mpm/services/mcp_gateway/core/interfaces.py +0 -443
- claude_mpm/services/mcp_gateway/core/process_pool.py +0 -977
- claude_mpm/services/mcp_gateway/core/singleton_manager.py +0 -315
- claude_mpm/services/mcp_gateway/core/startup_verification.py +0 -316
- claude_mpm/services/mcp_gateway/main.py +0 -589
- claude_mpm/services/mcp_gateway/registry/__init__.py +0 -12
- claude_mpm/services/mcp_gateway/registry/service_registry.py +0 -412
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +0 -489
- claude_mpm/services/mcp_gateway/server/__init__.py +0 -15
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +0 -414
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +0 -372
- claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -712
- claude_mpm/services/mcp_gateway/tools/__init__.py +0 -36
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +0 -485
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +0 -789
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +0 -654
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +0 -456
- claude_mpm/services/mcp_gateway/tools/hello_world.py +0 -551
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +0 -555
- claude_mpm/services/mcp_gateway/utils/__init__.py +0 -14
- claude_mpm/services/mcp_gateway/utils/package_version_checker.py +0 -160
- claude_mpm/services/mcp_gateway/utils/update_preferences.py +0 -170
- claude_mpm-5.1.9.dist-info/entry_points.txt +0 -10
- claude_mpm-5.1.9.dist-info/licenses/LICENSE +0 -21
- {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.14.dist-info}/WHEEL +0 -0
- {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.14.dist-info}/top_level.txt +0 -0
|
@@ -1,580 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* File Viewer Component
|
|
3
|
-
*
|
|
4
|
-
* A simple file content viewer that displays file contents in a modal window.
|
|
5
|
-
* This component handles file loading via HTTP requests and displays the content
|
|
6
|
-
* with basic syntax highlighting support.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
class FileViewer {
|
|
10
|
-
constructor() {
|
|
11
|
-
this.modal = null;
|
|
12
|
-
this.currentFile = null;
|
|
13
|
-
this.initialized = false;
|
|
14
|
-
this.contentCache = new Map();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Initialize the file viewer
|
|
19
|
-
*/
|
|
20
|
-
initialize() {
|
|
21
|
-
if (this.initialized) {
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
this.createModal();
|
|
26
|
-
this.setupEventHandlers();
|
|
27
|
-
|
|
28
|
-
this.initialized = true;
|
|
29
|
-
console.log('File viewer initialized');
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Create modal DOM structure
|
|
34
|
-
*/
|
|
35
|
-
createModal() {
|
|
36
|
-
const modalHtml = `
|
|
37
|
-
<div class="file-viewer-modal" id="file-viewer-modal">
|
|
38
|
-
<div class="file-viewer-content">
|
|
39
|
-
<div class="file-viewer-header">
|
|
40
|
-
<h2>📄 File Viewer</h2>
|
|
41
|
-
<button class="file-viewer-close" id="file-viewer-close">×</button>
|
|
42
|
-
</div>
|
|
43
|
-
<div class="file-viewer-path" id="file-viewer-path">
|
|
44
|
-
Loading...
|
|
45
|
-
</div>
|
|
46
|
-
<div class="file-viewer-body">
|
|
47
|
-
<pre class="file-viewer-code" id="file-viewer-code">
|
|
48
|
-
<code id="file-viewer-code-content">Loading file content...</code>
|
|
49
|
-
</pre>
|
|
50
|
-
</div>
|
|
51
|
-
<div class="file-viewer-footer">
|
|
52
|
-
<div class="file-viewer-info">
|
|
53
|
-
<span id="file-viewer-type">Type: --</span>
|
|
54
|
-
<span id="file-viewer-lines">Lines: --</span>
|
|
55
|
-
<span id="file-viewer-size">Size: --</span>
|
|
56
|
-
</div>
|
|
57
|
-
<button class="file-viewer-copy" id="file-viewer-copy">📋 Copy</button>
|
|
58
|
-
</div>
|
|
59
|
-
</div>
|
|
60
|
-
</div>
|
|
61
|
-
`;
|
|
62
|
-
|
|
63
|
-
// Add modal to body
|
|
64
|
-
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
|
65
|
-
this.modal = document.getElementById('file-viewer-modal');
|
|
66
|
-
|
|
67
|
-
// Add styles if not already present
|
|
68
|
-
if (!document.getElementById('file-viewer-styles')) {
|
|
69
|
-
const styles = `
|
|
70
|
-
<style id="file-viewer-styles">
|
|
71
|
-
.file-viewer-modal {
|
|
72
|
-
display: none;
|
|
73
|
-
position: fixed;
|
|
74
|
-
top: 0;
|
|
75
|
-
left: 0;
|
|
76
|
-
width: 100%;
|
|
77
|
-
height: 100%;
|
|
78
|
-
background: rgba(0, 0, 0, 0.7);
|
|
79
|
-
z-index: 10000;
|
|
80
|
-
animation: fadeIn 0.2s;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
.file-viewer-modal.show {
|
|
84
|
-
display: flex;
|
|
85
|
-
align-items: center;
|
|
86
|
-
justify-content: center;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
.file-viewer-content {
|
|
90
|
-
background: #1e1e1e;
|
|
91
|
-
border-radius: 8px;
|
|
92
|
-
width: 90%;
|
|
93
|
-
max-width: 1200px;
|
|
94
|
-
height: 80%;
|
|
95
|
-
display: flex;
|
|
96
|
-
flex-direction: column;
|
|
97
|
-
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
.file-viewer-header {
|
|
101
|
-
display: flex;
|
|
102
|
-
justify-content: space-between;
|
|
103
|
-
align-items: center;
|
|
104
|
-
padding: 15px 20px;
|
|
105
|
-
background: #2d2d30;
|
|
106
|
-
border-radius: 8px 8px 0 0;
|
|
107
|
-
border-bottom: 1px solid #3e3e42;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
.file-viewer-header h2 {
|
|
111
|
-
margin: 0;
|
|
112
|
-
color: #cccccc;
|
|
113
|
-
font-size: 18px;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.file-viewer-close {
|
|
117
|
-
background: none;
|
|
118
|
-
border: none;
|
|
119
|
-
color: #999;
|
|
120
|
-
font-size: 24px;
|
|
121
|
-
cursor: pointer;
|
|
122
|
-
padding: 0;
|
|
123
|
-
width: 30px;
|
|
124
|
-
height: 30px;
|
|
125
|
-
display: flex;
|
|
126
|
-
align-items: center;
|
|
127
|
-
justify-content: center;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
.file-viewer-close:hover {
|
|
131
|
-
color: #fff;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
.file-viewer-path {
|
|
135
|
-
padding: 10px 20px;
|
|
136
|
-
background: #252526;
|
|
137
|
-
color: #8b8b8b;
|
|
138
|
-
font-family: 'Consolas', 'Monaco', monospace;
|
|
139
|
-
font-size: 12px;
|
|
140
|
-
border-bottom: 1px solid #3e3e42;
|
|
141
|
-
word-break: break-all;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
.file-viewer-body {
|
|
145
|
-
flex: 1;
|
|
146
|
-
overflow: auto;
|
|
147
|
-
padding: 20px;
|
|
148
|
-
background: #1e1e1e;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
.file-viewer-code {
|
|
152
|
-
margin: 0;
|
|
153
|
-
padding: 0;
|
|
154
|
-
background: transparent;
|
|
155
|
-
overflow: visible;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
.file-viewer-code code {
|
|
159
|
-
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
|
|
160
|
-
font-size: 13px;
|
|
161
|
-
line-height: 1.5;
|
|
162
|
-
color: #d4d4d4;
|
|
163
|
-
white-space: pre;
|
|
164
|
-
display: block;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
.file-viewer-footer {
|
|
168
|
-
padding: 15px 20px;
|
|
169
|
-
background: #2d2d30;
|
|
170
|
-
border-top: 1px solid #3e3e42;
|
|
171
|
-
display: flex;
|
|
172
|
-
justify-content: space-between;
|
|
173
|
-
align-items: center;
|
|
174
|
-
border-radius: 0 0 8px 8px;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
.file-viewer-info {
|
|
178
|
-
display: flex;
|
|
179
|
-
gap: 20px;
|
|
180
|
-
color: #8b8b8b;
|
|
181
|
-
font-size: 12px;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
.file-viewer-copy {
|
|
185
|
-
background: #0e639c;
|
|
186
|
-
color: white;
|
|
187
|
-
border: none;
|
|
188
|
-
padding: 6px 12px;
|
|
189
|
-
border-radius: 4px;
|
|
190
|
-
cursor: pointer;
|
|
191
|
-
font-size: 12px;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
.file-viewer-copy:hover {
|
|
195
|
-
background: #1177bb;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
.file-viewer-copy.copied {
|
|
199
|
-
background: #4ec9b0;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
.file-viewer-error {
|
|
203
|
-
color: #f48771;
|
|
204
|
-
padding: 20px;
|
|
205
|
-
text-align: center;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
@keyframes fadeIn {
|
|
209
|
-
from { opacity: 0; }
|
|
210
|
-
to { opacity: 1; }
|
|
211
|
-
}
|
|
212
|
-
</style>
|
|
213
|
-
`;
|
|
214
|
-
document.head.insertAdjacentHTML('beforeend', styles);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Setup event handlers
|
|
220
|
-
*/
|
|
221
|
-
setupEventHandlers() {
|
|
222
|
-
// Close button
|
|
223
|
-
document.getElementById('file-viewer-close').addEventListener('click', () => {
|
|
224
|
-
this.hide();
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
// Close on backdrop click
|
|
228
|
-
this.modal.addEventListener('click', (e) => {
|
|
229
|
-
if (e.target === this.modal) {
|
|
230
|
-
this.hide();
|
|
231
|
-
}
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
// Close on ESC key
|
|
235
|
-
document.addEventListener('keydown', (e) => {
|
|
236
|
-
if (e.key === 'Escape' && this.modal.classList.contains('show')) {
|
|
237
|
-
this.hide();
|
|
238
|
-
}
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
// Copy button
|
|
242
|
-
document.getElementById('file-viewer-copy').addEventListener('click', () => {
|
|
243
|
-
this.copyContent();
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Show the file viewer with file content
|
|
249
|
-
*/
|
|
250
|
-
async show(filePath) {
|
|
251
|
-
console.log('[FileViewer] show() called with path:', filePath);
|
|
252
|
-
console.log('[FileViewer] initialized:', this.initialized);
|
|
253
|
-
|
|
254
|
-
if (!this.initialized) {
|
|
255
|
-
console.log('[FileViewer] Not initialized, initializing now...');
|
|
256
|
-
this.initialize();
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
this.currentFile = filePath;
|
|
260
|
-
this.modal.classList.add('show');
|
|
261
|
-
|
|
262
|
-
// Update path
|
|
263
|
-
document.getElementById('file-viewer-path').textContent = filePath;
|
|
264
|
-
|
|
265
|
-
console.log('[FileViewer] Modal shown, loading file content...');
|
|
266
|
-
// Load file content
|
|
267
|
-
await this.loadFileContent(filePath);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* Hide the file viewer
|
|
272
|
-
*/
|
|
273
|
-
hide() {
|
|
274
|
-
this.modal.classList.remove('show');
|
|
275
|
-
this.currentFile = null;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* Load file content
|
|
280
|
-
*/
|
|
281
|
-
async loadFileContent(filePath) {
|
|
282
|
-
const codeContent = document.getElementById('file-viewer-code-content');
|
|
283
|
-
|
|
284
|
-
console.log('[FileViewer] loadFileContent called with path:', filePath);
|
|
285
|
-
|
|
286
|
-
// Check cache first
|
|
287
|
-
if (this.contentCache.has(filePath)) {
|
|
288
|
-
console.log('[FileViewer] Using cached content for:', filePath);
|
|
289
|
-
this.displayContent(this.contentCache.get(filePath));
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// Show loading state
|
|
294
|
-
codeContent.textContent = 'Loading file content...';
|
|
295
|
-
|
|
296
|
-
try {
|
|
297
|
-
// Check if we have a socket connection available
|
|
298
|
-
if (window.socket && window.socket.connected) {
|
|
299
|
-
console.log('[FileViewer] Using Socket.IO to load file:', filePath);
|
|
300
|
-
|
|
301
|
-
// Create a promise to wait for the response
|
|
302
|
-
const responsePromise = new Promise((resolve, reject) => {
|
|
303
|
-
const timeoutId = setTimeout(() => {
|
|
304
|
-
console.error('[FileViewer] Socket.IO request timed out for:', filePath);
|
|
305
|
-
reject(new Error('Socket.IO request timed out'));
|
|
306
|
-
}, 10000); // 10 second timeout
|
|
307
|
-
|
|
308
|
-
// Set up one-time listener for the response
|
|
309
|
-
window.socket.once('file_content_response', (data) => {
|
|
310
|
-
clearTimeout(timeoutId);
|
|
311
|
-
console.log('[FileViewer] Received file_content_response:', data);
|
|
312
|
-
resolve(data);
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
// Emit the read_file event
|
|
316
|
-
console.log('[FileViewer] Emitting read_file event with data:', {
|
|
317
|
-
file_path: filePath,
|
|
318
|
-
working_dir: window.workingDirectory || '/',
|
|
319
|
-
max_size: 5 * 1024 * 1024 // 5MB limit
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
window.socket.emit('read_file', {
|
|
323
|
-
file_path: filePath,
|
|
324
|
-
working_dir: window.workingDirectory || '/',
|
|
325
|
-
max_size: 5 * 1024 * 1024 // 5MB limit
|
|
326
|
-
});
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
// Wait for the response
|
|
330
|
-
const data = await responsePromise;
|
|
331
|
-
|
|
332
|
-
if (data.success && data.content !== undefined) {
|
|
333
|
-
console.log('[FileViewer] Successfully loaded file content, caching...');
|
|
334
|
-
// Cache the content
|
|
335
|
-
this.contentCache.set(filePath, data.content);
|
|
336
|
-
|
|
337
|
-
// Display the content
|
|
338
|
-
this.displayContent(data.content);
|
|
339
|
-
|
|
340
|
-
// Update file info
|
|
341
|
-
this.updateFileInfo(data);
|
|
342
|
-
} else {
|
|
343
|
-
console.error('[FileViewer] Server returned error:', data.error);
|
|
344
|
-
throw new Error(data.error || 'Failed to load file content');
|
|
345
|
-
}
|
|
346
|
-
} else {
|
|
347
|
-
console.error('[FileViewer] No Socket.IO connection available');
|
|
348
|
-
throw new Error('No socket connection available. Please ensure the dashboard is connected to the monitoring server.');
|
|
349
|
-
}
|
|
350
|
-
} catch (error) {
|
|
351
|
-
console.error('[FileViewer] Error loading file:', error);
|
|
352
|
-
console.error('[FileViewer] Error stack:', error.stack);
|
|
353
|
-
|
|
354
|
-
// If API fails, show error message with helpful information
|
|
355
|
-
this.displayError(filePath, error.message);
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
/**
|
|
360
|
-
* Display file content
|
|
361
|
-
*/
|
|
362
|
-
displayContent(content) {
|
|
363
|
-
const codeContent = document.getElementById('file-viewer-code-content');
|
|
364
|
-
|
|
365
|
-
// Set the content
|
|
366
|
-
codeContent.textContent = content || '(Empty file)';
|
|
367
|
-
|
|
368
|
-
// Update line count
|
|
369
|
-
const lines = content ? content.split('\n').length : 0;
|
|
370
|
-
document.getElementById('file-viewer-lines').textContent = `Lines: ${lines}`;
|
|
371
|
-
|
|
372
|
-
// Update file size
|
|
373
|
-
const size = content ? new Blob([content]).size : 0;
|
|
374
|
-
document.getElementById('file-viewer-size').textContent = `Size: ${this.formatFileSize(size)}`;
|
|
375
|
-
|
|
376
|
-
// Detect and set file type
|
|
377
|
-
const fileType = this.detectFileType(this.currentFile);
|
|
378
|
-
document.getElementById('file-viewer-type').textContent = `Type: ${fileType}`;
|
|
379
|
-
|
|
380
|
-
// Apply syntax highlighting if Prism is available
|
|
381
|
-
if (window.Prism) {
|
|
382
|
-
const language = this.detectLanguage(this.currentFile);
|
|
383
|
-
codeContent.className = `language-${language}`;
|
|
384
|
-
Prism.highlightElement(codeContent);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
/**
|
|
389
|
-
* Display error message
|
|
390
|
-
*/
|
|
391
|
-
displayError(filePath, errorMessage) {
|
|
392
|
-
const codeContent = document.getElementById('file-viewer-code-content');
|
|
393
|
-
|
|
394
|
-
// For now, show a helpful message since the API endpoint doesn't exist yet
|
|
395
|
-
const errorHtml = `
|
|
396
|
-
<div class="file-viewer-error">
|
|
397
|
-
⚠️ File content loading is not yet implemented
|
|
398
|
-
|
|
399
|
-
File path: ${filePath}
|
|
400
|
-
|
|
401
|
-
The file viewing functionality requires:
|
|
402
|
-
1. A server-side /api/file endpoint
|
|
403
|
-
2. Proper file reading permissions
|
|
404
|
-
3. Security validation for file access
|
|
405
|
-
|
|
406
|
-
Error: ${errorMessage}
|
|
407
|
-
|
|
408
|
-
This feature will be available once the backend API is implemented.
|
|
409
|
-
</div>
|
|
410
|
-
`;
|
|
411
|
-
|
|
412
|
-
codeContent.innerHTML = errorHtml;
|
|
413
|
-
|
|
414
|
-
// Update info
|
|
415
|
-
document.getElementById('file-viewer-lines').textContent = 'Lines: --';
|
|
416
|
-
document.getElementById('file-viewer-size').textContent = 'Size: --';
|
|
417
|
-
document.getElementById('file-viewer-type').textContent = 'Type: --';
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
/**
|
|
421
|
-
* Update file info
|
|
422
|
-
*/
|
|
423
|
-
updateFileInfo(data) {
|
|
424
|
-
if (data.lines !== undefined) {
|
|
425
|
-
document.getElementById('file-viewer-lines').textContent = `Lines: ${data.lines}`;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
if (data.size !== undefined) {
|
|
429
|
-
document.getElementById('file-viewer-size').textContent = `Size: ${this.formatFileSize(data.size)}`;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
if (data.type) {
|
|
433
|
-
document.getElementById('file-viewer-type').textContent = `Type: ${data.type}`;
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
/**
|
|
438
|
-
* Format file size for display
|
|
439
|
-
*/
|
|
440
|
-
formatFileSize(bytes) {
|
|
441
|
-
if (bytes === 0) return '0 Bytes';
|
|
442
|
-
|
|
443
|
-
const k = 1024;
|
|
444
|
-
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
445
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
446
|
-
|
|
447
|
-
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
/**
|
|
451
|
-
* Detect file type from path
|
|
452
|
-
*/
|
|
453
|
-
detectFileType(path) {
|
|
454
|
-
if (!path) return 'Unknown';
|
|
455
|
-
|
|
456
|
-
const ext = path.split('.').pop()?.toLowerCase();
|
|
457
|
-
const typeMap = {
|
|
458
|
-
'py': 'Python',
|
|
459
|
-
'js': 'JavaScript',
|
|
460
|
-
'ts': 'TypeScript',
|
|
461
|
-
'jsx': 'React JSX',
|
|
462
|
-
'tsx': 'React TSX',
|
|
463
|
-
'html': 'HTML',
|
|
464
|
-
'css': 'CSS',
|
|
465
|
-
'json': 'JSON',
|
|
466
|
-
'xml': 'XML',
|
|
467
|
-
'yaml': 'YAML',
|
|
468
|
-
'yml': 'YAML',
|
|
469
|
-
'md': 'Markdown',
|
|
470
|
-
'txt': 'Text',
|
|
471
|
-
'sh': 'Shell Script',
|
|
472
|
-
'bash': 'Bash Script',
|
|
473
|
-
'sql': 'SQL',
|
|
474
|
-
'go': 'Go',
|
|
475
|
-
'rs': 'Rust',
|
|
476
|
-
'java': 'Java',
|
|
477
|
-
'cpp': 'C++',
|
|
478
|
-
'c': 'C',
|
|
479
|
-
'cs': 'C#',
|
|
480
|
-
'rb': 'Ruby',
|
|
481
|
-
'php': 'PHP'
|
|
482
|
-
};
|
|
483
|
-
|
|
484
|
-
return typeMap[ext] || 'Text';
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
/**
|
|
488
|
-
* Detect language for syntax highlighting
|
|
489
|
-
*/
|
|
490
|
-
detectLanguage(path) {
|
|
491
|
-
if (!path) return 'plaintext';
|
|
492
|
-
|
|
493
|
-
const ext = path.split('.').pop()?.toLowerCase();
|
|
494
|
-
const languageMap = {
|
|
495
|
-
'py': 'python',
|
|
496
|
-
'js': 'javascript',
|
|
497
|
-
'ts': 'typescript',
|
|
498
|
-
'jsx': 'jsx',
|
|
499
|
-
'tsx': 'tsx',
|
|
500
|
-
'html': 'html',
|
|
501
|
-
'css': 'css',
|
|
502
|
-
'json': 'json',
|
|
503
|
-
'xml': 'xml',
|
|
504
|
-
'yaml': 'yaml',
|
|
505
|
-
'yml': 'yaml',
|
|
506
|
-
'md': 'markdown',
|
|
507
|
-
'sh': 'bash',
|
|
508
|
-
'bash': 'bash',
|
|
509
|
-
'sql': 'sql',
|
|
510
|
-
'go': 'go',
|
|
511
|
-
'rs': 'rust',
|
|
512
|
-
'java': 'java',
|
|
513
|
-
'cpp': 'cpp',
|
|
514
|
-
'c': 'c',
|
|
515
|
-
'cs': 'csharp',
|
|
516
|
-
'rb': 'ruby',
|
|
517
|
-
'php': 'php'
|
|
518
|
-
};
|
|
519
|
-
|
|
520
|
-
return languageMap[ext] || 'plaintext';
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
/**
|
|
524
|
-
* Copy file content to clipboard
|
|
525
|
-
*/
|
|
526
|
-
async copyContent() {
|
|
527
|
-
const codeContent = document.getElementById('file-viewer-code-content');
|
|
528
|
-
const button = document.getElementById('file-viewer-copy');
|
|
529
|
-
const content = codeContent.textContent;
|
|
530
|
-
|
|
531
|
-
try {
|
|
532
|
-
await navigator.clipboard.writeText(content);
|
|
533
|
-
|
|
534
|
-
// Show feedback
|
|
535
|
-
const originalText = button.textContent;
|
|
536
|
-
button.textContent = '✅ Copied!';
|
|
537
|
-
button.classList.add('copied');
|
|
538
|
-
|
|
539
|
-
setTimeout(() => {
|
|
540
|
-
button.textContent = originalText;
|
|
541
|
-
button.classList.remove('copied');
|
|
542
|
-
}, 2000);
|
|
543
|
-
} catch (err) {
|
|
544
|
-
console.error('Failed to copy:', err);
|
|
545
|
-
alert('Failed to copy content to clipboard');
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
// Create singleton instance
|
|
551
|
-
const fileViewer = new FileViewer();
|
|
552
|
-
|
|
553
|
-
// Create global function for easy access
|
|
554
|
-
// Only set if not already defined by dashboard.js
|
|
555
|
-
if (!window.showFileViewerModal) {
|
|
556
|
-
window.showFileViewerModal = (filePath) => {
|
|
557
|
-
console.log('[FileViewer] showFileViewerModal called with path:', filePath);
|
|
558
|
-
fileViewer.show(filePath);
|
|
559
|
-
};
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
// Expose the singleton for debugging
|
|
563
|
-
window.fileViewerInstance = fileViewer;
|
|
564
|
-
|
|
565
|
-
// Export for use in other modules
|
|
566
|
-
if (typeof window !== 'undefined') {
|
|
567
|
-
window.FileViewer = fileViewer;
|
|
568
|
-
|
|
569
|
-
// Initialize when DOM is ready
|
|
570
|
-
if (document.readyState === 'loading') {
|
|
571
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
572
|
-
fileViewer.initialize();
|
|
573
|
-
});
|
|
574
|
-
} else {
|
|
575
|
-
// DOM is already loaded
|
|
576
|
-
fileViewer.initialize();
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
export default fileViewer;
|