claude-mpm 4.1.7__py3-none-any.whl → 4.1.10__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/INSTRUCTIONS.md +26 -1
- claude_mpm/agents/OUTPUT_STYLE.md +73 -0
- claude_mpm/agents/agents_metadata.py +57 -0
- claude_mpm/agents/templates/.claude-mpm/memories/README.md +17 -0
- claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +3 -0
- claude_mpm/agents/templates/agent-manager.json +263 -17
- claude_mpm/agents/templates/agent-manager.md +248 -10
- claude_mpm/agents/templates/agentic_coder_optimizer.json +222 -0
- claude_mpm/agents/templates/code_analyzer.json +18 -8
- claude_mpm/agents/templates/engineer.json +1 -1
- claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +39 -0
- claude_mpm/agents/templates/qa.json +1 -1
- claude_mpm/agents/templates/research.json +1 -1
- claude_mpm/cli/__init__.py +4 -0
- claude_mpm/cli/commands/__init__.py +6 -0
- claude_mpm/cli/commands/analyze.py +547 -0
- claude_mpm/cli/commands/analyze_code.py +524 -0
- claude_mpm/cli/commands/configure.py +223 -25
- claude_mpm/cli/commands/configure_tui.py +65 -61
- claude_mpm/cli/commands/debug.py +1387 -0
- claude_mpm/cli/parsers/analyze_code_parser.py +170 -0
- claude_mpm/cli/parsers/analyze_parser.py +135 -0
- claude_mpm/cli/parsers/base_parser.py +29 -0
- claude_mpm/cli/parsers/configure_parser.py +23 -0
- claude_mpm/cli/parsers/debug_parser.py +319 -0
- claude_mpm/config/socketio_config.py +21 -21
- claude_mpm/constants.py +3 -1
- claude_mpm/core/framework_loader.py +148 -6
- claude_mpm/core/log_manager.py +16 -13
- claude_mpm/core/logger.py +1 -1
- claude_mpm/core/unified_agent_registry.py +1 -1
- claude_mpm/dashboard/.claude-mpm/socketio-instances.json +1 -0
- claude_mpm/dashboard/analysis_runner.py +428 -0
- claude_mpm/dashboard/static/built/components/activity-tree.js +2 -0
- claude_mpm/dashboard/static/built/components/agent-inference.js +1 -1
- claude_mpm/dashboard/static/built/components/event-viewer.js +1 -1
- 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/session-manager.js +1 -1
- claude_mpm/dashboard/static/built/components/working-directory.js +1 -1
- claude_mpm/dashboard/static/built/dashboard.js +1 -1
- claude_mpm/dashboard/static/built/socket-client.js +1 -1
- claude_mpm/dashboard/static/css/activity.css +549 -0
- claude_mpm/dashboard/static/css/code-tree.css +846 -0
- claude_mpm/dashboard/static/css/dashboard.css +245 -0
- claude_mpm/dashboard/static/dist/components/activity-tree.js +2 -0
- claude_mpm/dashboard/static/dist/components/code-tree.js +2 -0
- claude_mpm/dashboard/static/dist/components/code-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/event-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/socket-client.js +1 -1
- claude_mpm/dashboard/static/js/components/activity-tree.js +1139 -0
- claude_mpm/dashboard/static/js/components/code-tree.js +1357 -0
- claude_mpm/dashboard/static/js/components/code-viewer.js +480 -0
- claude_mpm/dashboard/static/js/components/event-viewer.js +11 -0
- claude_mpm/dashboard/static/js/components/session-manager.js +40 -4
- claude_mpm/dashboard/static/js/components/socket-manager.js +12 -0
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +4 -0
- claude_mpm/dashboard/static/js/components/working-directory.js +17 -1
- claude_mpm/dashboard/static/js/dashboard.js +39 -0
- claude_mpm/dashboard/static/js/socket-client.js +414 -20
- claude_mpm/dashboard/templates/index.html +184 -4
- claude_mpm/hooks/claude_hooks/hook_handler.py +182 -5
- claude_mpm/hooks/claude_hooks/installer.py +728 -0
- claude_mpm/scripts/claude-hook-handler.sh +161 -0
- claude_mpm/scripts/socketio_daemon.py +121 -8
- claude_mpm/services/agents/deployment/agent_config_provider.py +127 -27
- claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +2 -2
- claude_mpm/services/agents/deployment/agent_record_service.py +1 -2
- claude_mpm/services/agents/memory/memory_format_service.py +1 -5
- claude_mpm/services/cli/agent_cleanup_service.py +1 -2
- claude_mpm/services/cli/agent_dependency_service.py +1 -1
- claude_mpm/services/cli/agent_validation_service.py +3 -4
- claude_mpm/services/cli/dashboard_launcher.py +2 -3
- claude_mpm/services/cli/startup_checker.py +0 -10
- claude_mpm/services/core/cache_manager.py +1 -2
- claude_mpm/services/core/path_resolver.py +1 -4
- claude_mpm/services/core/service_container.py +2 -2
- claude_mpm/services/diagnostics/checks/instructions_check.py +2 -5
- claude_mpm/services/event_bus/direct_relay.py +98 -20
- claude_mpm/services/infrastructure/monitoring/__init__.py +11 -11
- claude_mpm/services/infrastructure/monitoring.py +11 -11
- claude_mpm/services/project/architecture_analyzer.py +1 -1
- claude_mpm/services/project/dependency_analyzer.py +4 -4
- claude_mpm/services/project/language_analyzer.py +3 -3
- claude_mpm/services/project/metrics_collector.py +3 -6
- claude_mpm/services/socketio/handlers/__init__.py +2 -0
- claude_mpm/services/socketio/handlers/code_analysis.py +170 -0
- claude_mpm/services/socketio/handlers/registry.py +2 -0
- claude_mpm/services/socketio/server/connection_manager.py +95 -65
- claude_mpm/services/socketio/server/core.py +125 -17
- claude_mpm/services/socketio/server/main.py +44 -5
- claude_mpm/services/visualization/__init__.py +19 -0
- claude_mpm/services/visualization/mermaid_generator.py +938 -0
- claude_mpm/tools/__main__.py +208 -0
- claude_mpm/tools/code_tree_analyzer.py +778 -0
- claude_mpm/tools/code_tree_builder.py +632 -0
- claude_mpm/tools/code_tree_events.py +318 -0
- claude_mpm/tools/socketio_debug.py +671 -0
- {claude_mpm-4.1.7.dist-info → claude_mpm-4.1.10.dist-info}/METADATA +1 -1
- {claude_mpm-4.1.7.dist-info → claude_mpm-4.1.10.dist-info}/RECORD +108 -77
- claude_mpm/agents/schema/agent_schema.json +0 -314
- {claude_mpm-4.1.7.dist-info → claude_mpm-4.1.10.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.7.dist-info → claude_mpm-4.1.10.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.1.7.dist-info → claude_mpm-4.1.10.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.7.dist-info → claude_mpm-4.1.10.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Viewer Component
|
|
3
|
+
*
|
|
4
|
+
* Modal window for displaying source code with syntax highlighting.
|
|
5
|
+
* Supports navigation between parent/child nodes and shows code metrics.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
class CodeViewer {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.modal = null;
|
|
11
|
+
this.currentNode = null;
|
|
12
|
+
this.socket = null;
|
|
13
|
+
this.initialized = false;
|
|
14
|
+
this.codeCache = new Map();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Initialize the code viewer
|
|
19
|
+
*/
|
|
20
|
+
initialize() {
|
|
21
|
+
if (this.initialized) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
this.createModal();
|
|
26
|
+
this.setupEventHandlers();
|
|
27
|
+
this.subscribeToEvents();
|
|
28
|
+
|
|
29
|
+
this.initialized = true;
|
|
30
|
+
console.log('Code viewer initialized');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Create modal DOM structure
|
|
35
|
+
*/
|
|
36
|
+
createModal() {
|
|
37
|
+
const modalHtml = `
|
|
38
|
+
<div class="code-viewer-modal" id="code-viewer-modal">
|
|
39
|
+
<div class="code-viewer-content">
|
|
40
|
+
<div class="code-viewer-header">
|
|
41
|
+
<div class="code-viewer-title" id="code-viewer-title">
|
|
42
|
+
Loading...
|
|
43
|
+
</div>
|
|
44
|
+
<div class="code-viewer-info">
|
|
45
|
+
<span id="code-viewer-type">Type: --</span>
|
|
46
|
+
<span id="code-viewer-lines">Lines: --</span>
|
|
47
|
+
<span id="code-viewer-complexity">Complexity: --</span>
|
|
48
|
+
</div>
|
|
49
|
+
<button class="code-viewer-close" id="code-viewer-close">×</button>
|
|
50
|
+
</div>
|
|
51
|
+
<div class="code-viewer-body">
|
|
52
|
+
<pre class="code-viewer-code line-numbers" id="code-viewer-code">
|
|
53
|
+
<code class="language-python" id="code-viewer-code-content"></code>
|
|
54
|
+
</pre>
|
|
55
|
+
</div>
|
|
56
|
+
<div class="code-viewer-navigation">
|
|
57
|
+
<div class="nav-group">
|
|
58
|
+
<button class="code-nav-button" id="code-nav-parent" disabled>
|
|
59
|
+
⬆️ Parent
|
|
60
|
+
</button>
|
|
61
|
+
<button class="code-nav-button" id="code-nav-prev" disabled>
|
|
62
|
+
⬅️ Previous
|
|
63
|
+
</button>
|
|
64
|
+
<button class="code-nav-button" id="code-nav-next" disabled>
|
|
65
|
+
➡️ Next
|
|
66
|
+
</button>
|
|
67
|
+
</div>
|
|
68
|
+
<div class="nav-info">
|
|
69
|
+
<span id="code-nav-position">-- / --</span>
|
|
70
|
+
</div>
|
|
71
|
+
<div class="nav-actions">
|
|
72
|
+
<button class="code-nav-button" id="code-copy">
|
|
73
|
+
📋 Copy
|
|
74
|
+
</button>
|
|
75
|
+
<button class="code-nav-button" id="code-open-file">
|
|
76
|
+
📂 Open File
|
|
77
|
+
</button>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
`;
|
|
83
|
+
|
|
84
|
+
// Add modal to body
|
|
85
|
+
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
|
86
|
+
this.modal = document.getElementById('code-viewer-modal');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Setup event handlers
|
|
91
|
+
*/
|
|
92
|
+
setupEventHandlers() {
|
|
93
|
+
// Close button
|
|
94
|
+
document.getElementById('code-viewer-close').addEventListener('click', () => {
|
|
95
|
+
this.hide();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Close on backdrop click
|
|
99
|
+
this.modal.addEventListener('click', (e) => {
|
|
100
|
+
if (e.target === this.modal) {
|
|
101
|
+
this.hide();
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Close on ESC key
|
|
106
|
+
document.addEventListener('keydown', (e) => {
|
|
107
|
+
if (e.key === 'Escape' && this.modal.classList.contains('show')) {
|
|
108
|
+
this.hide();
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Navigation buttons
|
|
113
|
+
document.getElementById('code-nav-parent').addEventListener('click', () => {
|
|
114
|
+
this.navigateToParent();
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
document.getElementById('code-nav-prev').addEventListener('click', () => {
|
|
118
|
+
this.navigateToPrevious();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
document.getElementById('code-nav-next').addEventListener('click', () => {
|
|
122
|
+
this.navigateToNext();
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Action buttons
|
|
126
|
+
document.getElementById('code-copy').addEventListener('click', () => {
|
|
127
|
+
this.copyCode();
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
document.getElementById('code-open-file').addEventListener('click', () => {
|
|
131
|
+
this.openInEditor();
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Subscribe to Socket.IO events
|
|
137
|
+
*/
|
|
138
|
+
subscribeToEvents() {
|
|
139
|
+
if (window.socket) {
|
|
140
|
+
this.socket = window.socket;
|
|
141
|
+
|
|
142
|
+
// Listen for code content responses
|
|
143
|
+
this.socket.on('code:content:response', (data) => {
|
|
144
|
+
this.handleCodeContent(data);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Show the code viewer with node data
|
|
151
|
+
*/
|
|
152
|
+
show(nodeData) {
|
|
153
|
+
if (!this.initialized) {
|
|
154
|
+
this.initialize();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
this.currentNode = nodeData;
|
|
158
|
+
this.modal.classList.add('show');
|
|
159
|
+
|
|
160
|
+
// Update header
|
|
161
|
+
this.updateHeader(nodeData);
|
|
162
|
+
|
|
163
|
+
// Load code content
|
|
164
|
+
this.loadCode(nodeData);
|
|
165
|
+
|
|
166
|
+
// Update navigation
|
|
167
|
+
this.updateNavigation(nodeData);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Hide the code viewer
|
|
172
|
+
*/
|
|
173
|
+
hide() {
|
|
174
|
+
this.modal.classList.remove('show');
|
|
175
|
+
this.currentNode = null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Update modal header
|
|
180
|
+
*/
|
|
181
|
+
updateHeader(nodeData) {
|
|
182
|
+
// Update title
|
|
183
|
+
const title = document.getElementById('code-viewer-title');
|
|
184
|
+
title.textContent = `${nodeData.name} (${nodeData.path || 'Unknown'})`;
|
|
185
|
+
|
|
186
|
+
// Update info
|
|
187
|
+
document.getElementById('code-viewer-type').textContent = `Type: ${nodeData.type}`;
|
|
188
|
+
document.getElementById('code-viewer-lines').textContent = `Lines: ${nodeData.lines || '--'}`;
|
|
189
|
+
document.getElementById('code-viewer-complexity').textContent = `Complexity: ${nodeData.complexity || '--'}`;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Load code content
|
|
194
|
+
*/
|
|
195
|
+
loadCode(nodeData) {
|
|
196
|
+
const codeContent = document.getElementById('code-viewer-code-content');
|
|
197
|
+
|
|
198
|
+
// Check cache first
|
|
199
|
+
const cacheKey = `${nodeData.path}:${nodeData.line}`;
|
|
200
|
+
if (this.codeCache.has(cacheKey)) {
|
|
201
|
+
this.displayCode(this.codeCache.get(cacheKey));
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Show loading state
|
|
206
|
+
codeContent.textContent = 'Loading code...';
|
|
207
|
+
|
|
208
|
+
// Request code from server
|
|
209
|
+
if (this.socket) {
|
|
210
|
+
this.socket.emit('code:content:request', {
|
|
211
|
+
path: nodeData.path,
|
|
212
|
+
line: nodeData.line,
|
|
213
|
+
type: nodeData.type,
|
|
214
|
+
name: nodeData.name
|
|
215
|
+
});
|
|
216
|
+
} else {
|
|
217
|
+
// Fallback: show mock code for demo
|
|
218
|
+
this.displayMockCode(nodeData);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Handle code content response
|
|
224
|
+
*/
|
|
225
|
+
handleCodeContent(data) {
|
|
226
|
+
if (!data.success) {
|
|
227
|
+
this.displayError(data.error || 'Failed to load code');
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Cache the content
|
|
232
|
+
const cacheKey = `${data.path}:${data.line}`;
|
|
233
|
+
this.codeCache.set(cacheKey, data.content);
|
|
234
|
+
|
|
235
|
+
// Display the code
|
|
236
|
+
this.displayCode(data.content);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Display code with syntax highlighting
|
|
241
|
+
*/
|
|
242
|
+
displayCode(code) {
|
|
243
|
+
const codeContent = document.getElementById('code-viewer-code-content');
|
|
244
|
+
const codeElement = document.getElementById('code-viewer-code');
|
|
245
|
+
|
|
246
|
+
// Set the code content
|
|
247
|
+
codeContent.textContent = code;
|
|
248
|
+
|
|
249
|
+
// Update language class based on file extension
|
|
250
|
+
const language = this.detectLanguage(this.currentNode.path);
|
|
251
|
+
codeContent.className = `language-${language}`;
|
|
252
|
+
|
|
253
|
+
// Apply Prism syntax highlighting
|
|
254
|
+
if (window.Prism) {
|
|
255
|
+
Prism.highlightElement(codeContent);
|
|
256
|
+
|
|
257
|
+
// Add line numbers if plugin is available
|
|
258
|
+
if (Prism.plugins && Prism.plugins.lineNumbers) {
|
|
259
|
+
Prism.plugins.lineNumbers.resize(codeElement);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Display mock code for demo purposes
|
|
266
|
+
*/
|
|
267
|
+
displayMockCode(nodeData) {
|
|
268
|
+
let mockCode = '';
|
|
269
|
+
|
|
270
|
+
switch (nodeData.type) {
|
|
271
|
+
case 'class':
|
|
272
|
+
mockCode = `class ${nodeData.name}:
|
|
273
|
+
"""
|
|
274
|
+
${nodeData.docstring || 'A sample class implementation.'}
|
|
275
|
+
"""
|
|
276
|
+
|
|
277
|
+
def __init__(self):
|
|
278
|
+
"""Initialize the ${nodeData.name} class."""
|
|
279
|
+
self._data = {}
|
|
280
|
+
self._initialized = False
|
|
281
|
+
|
|
282
|
+
def process(self, input_data):
|
|
283
|
+
"""Process the input data."""
|
|
284
|
+
if not self._initialized:
|
|
285
|
+
self._initialize()
|
|
286
|
+
return self._transform(input_data)
|
|
287
|
+
|
|
288
|
+
def _initialize(self):
|
|
289
|
+
"""Initialize internal state."""
|
|
290
|
+
self._initialized = True
|
|
291
|
+
|
|
292
|
+
def _transform(self, data):
|
|
293
|
+
"""Transform the data."""
|
|
294
|
+
return data`;
|
|
295
|
+
break;
|
|
296
|
+
|
|
297
|
+
case 'function':
|
|
298
|
+
mockCode = `def ${nodeData.name}(${nodeData.params ? nodeData.params.join(', ') : ''}):
|
|
299
|
+
"""
|
|
300
|
+
${nodeData.docstring || 'A sample function implementation.'}
|
|
301
|
+
|
|
302
|
+
Args:
|
|
303
|
+
${nodeData.params ? nodeData.params.map(p => `${p}: Description of ${p}`).join('\n ') : 'None'}
|
|
304
|
+
|
|
305
|
+
Returns:
|
|
306
|
+
${nodeData.returns || 'None'}: Return value description
|
|
307
|
+
"""
|
|
308
|
+
# Implementation here
|
|
309
|
+
result = None
|
|
310
|
+
|
|
311
|
+
# Process logic
|
|
312
|
+
for item in range(10):
|
|
313
|
+
result = process_item(item)
|
|
314
|
+
|
|
315
|
+
return result`;
|
|
316
|
+
break;
|
|
317
|
+
|
|
318
|
+
case 'method':
|
|
319
|
+
mockCode = ` def ${nodeData.name}(self${nodeData.params ? ', ' + nodeData.params.join(', ') : ''}):
|
|
320
|
+
"""
|
|
321
|
+
${nodeData.docstring || 'A sample method implementation.'}
|
|
322
|
+
"""
|
|
323
|
+
# Method implementation
|
|
324
|
+
self._validate()
|
|
325
|
+
result = self._process()
|
|
326
|
+
return result`;
|
|
327
|
+
break;
|
|
328
|
+
|
|
329
|
+
default:
|
|
330
|
+
mockCode = `# ${nodeData.name}
|
|
331
|
+
# Type: ${nodeData.type}
|
|
332
|
+
# Path: ${nodeData.path || 'Unknown'}
|
|
333
|
+
# Line: ${nodeData.line || 'Unknown'}
|
|
334
|
+
|
|
335
|
+
# Code content would appear here
|
|
336
|
+
# This is a placeholder for demonstration purposes`;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
this.displayCode(mockCode);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Display error message
|
|
344
|
+
*/
|
|
345
|
+
displayError(message) {
|
|
346
|
+
const codeContent = document.getElementById('code-viewer-code-content');
|
|
347
|
+
codeContent.textContent = `# Error loading code\n# ${message}`;
|
|
348
|
+
codeContent.className = 'language-python';
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Detect language from file path
|
|
353
|
+
*/
|
|
354
|
+
detectLanguage(path) {
|
|
355
|
+
if (!path) return 'python';
|
|
356
|
+
|
|
357
|
+
const ext = path.split('.').pop().toLowerCase();
|
|
358
|
+
const languageMap = {
|
|
359
|
+
'py': 'python',
|
|
360
|
+
'js': 'javascript',
|
|
361
|
+
'ts': 'typescript',
|
|
362
|
+
'jsx': 'jsx',
|
|
363
|
+
'tsx': 'tsx',
|
|
364
|
+
'css': 'css',
|
|
365
|
+
'html': 'html',
|
|
366
|
+
'json': 'json',
|
|
367
|
+
'yaml': 'yaml',
|
|
368
|
+
'yml': 'yaml',
|
|
369
|
+
'md': 'markdown',
|
|
370
|
+
'sh': 'bash',
|
|
371
|
+
'bash': 'bash',
|
|
372
|
+
'sql': 'sql',
|
|
373
|
+
'go': 'go',
|
|
374
|
+
'rs': 'rust',
|
|
375
|
+
'cpp': 'cpp',
|
|
376
|
+
'c': 'c',
|
|
377
|
+
'h': 'c',
|
|
378
|
+
'hpp': 'cpp',
|
|
379
|
+
'java': 'java',
|
|
380
|
+
'rb': 'ruby',
|
|
381
|
+
'php': 'php'
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
return languageMap[ext] || 'plaintext';
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Update navigation buttons
|
|
389
|
+
*/
|
|
390
|
+
updateNavigation(nodeData) {
|
|
391
|
+
// For now, disable navigation buttons
|
|
392
|
+
// In a real implementation, these would navigate through the AST
|
|
393
|
+
document.getElementById('code-nav-parent').disabled = true;
|
|
394
|
+
document.getElementById('code-nav-prev').disabled = true;
|
|
395
|
+
document.getElementById('code-nav-next').disabled = true;
|
|
396
|
+
document.getElementById('code-nav-position').textContent = '1 / 1';
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Navigate to parent node
|
|
401
|
+
*/
|
|
402
|
+
navigateToParent() {
|
|
403
|
+
console.log('Navigate to parent node');
|
|
404
|
+
// Implementation would load parent node's code
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Navigate to previous sibling
|
|
409
|
+
*/
|
|
410
|
+
navigateToPrevious() {
|
|
411
|
+
console.log('Navigate to previous sibling');
|
|
412
|
+
// Implementation would load previous sibling's code
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Navigate to next sibling
|
|
417
|
+
*/
|
|
418
|
+
navigateToNext() {
|
|
419
|
+
console.log('Navigate to next sibling');
|
|
420
|
+
// Implementation would load next sibling's code
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Copy code to clipboard
|
|
425
|
+
*/
|
|
426
|
+
async copyCode() {
|
|
427
|
+
const codeContent = document.getElementById('code-viewer-code-content');
|
|
428
|
+
const code = codeContent.textContent;
|
|
429
|
+
|
|
430
|
+
try {
|
|
431
|
+
await navigator.clipboard.writeText(code);
|
|
432
|
+
|
|
433
|
+
// Show feedback
|
|
434
|
+
const button = document.getElementById('code-copy');
|
|
435
|
+
const originalText = button.textContent;
|
|
436
|
+
button.textContent = '✅ Copied!';
|
|
437
|
+
setTimeout(() => {
|
|
438
|
+
button.textContent = originalText;
|
|
439
|
+
}, 2000);
|
|
440
|
+
} catch (err) {
|
|
441
|
+
console.error('Failed to copy code:', err);
|
|
442
|
+
alert('Failed to copy code to clipboard');
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Open file in editor
|
|
448
|
+
*/
|
|
449
|
+
openInEditor() {
|
|
450
|
+
if (!this.currentNode || !this.currentNode.path) {
|
|
451
|
+
alert('File path not available');
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Emit event to open file
|
|
456
|
+
if (this.socket) {
|
|
457
|
+
this.socket.emit('file:open', {
|
|
458
|
+
path: this.currentNode.path,
|
|
459
|
+
line: this.currentNode.line
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
console.log('Opening file in editor:', this.currentNode.path);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// Create singleton instance
|
|
468
|
+
const codeViewer = new CodeViewer();
|
|
469
|
+
|
|
470
|
+
// Export for use in other modules
|
|
471
|
+
if (typeof window !== 'undefined') {
|
|
472
|
+
window.CodeViewer = codeViewer;
|
|
473
|
+
|
|
474
|
+
// Initialize when DOM is ready
|
|
475
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
476
|
+
codeViewer.initialize();
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
export default codeViewer;
|
|
@@ -110,6 +110,17 @@ class EventViewer {
|
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
this.filteredEvents = this.events.filter(event => {
|
|
113
|
+
// Filter out info level log messages
|
|
114
|
+
if (event.type === 'log' && event.data && event.data.level === 'info') {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Filter out code analysis events (they're shown in footer status bar)
|
|
119
|
+
if (event.type === 'code' ||
|
|
120
|
+
(event.type === 'unknown' && event.originalEventName && event.originalEventName.startsWith('code:'))) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
|
|
113
124
|
// Search filter
|
|
114
125
|
if (this.searchFilter) {
|
|
115
126
|
const searchableText = [
|
|
@@ -65,6 +65,8 @@ class SessionManager {
|
|
|
65
65
|
setupSocketListeners() {
|
|
66
66
|
// Listen for socket event updates
|
|
67
67
|
this.socketClient.onEventUpdate((events, sessions) => {
|
|
68
|
+
// Log the sessions data to debug
|
|
69
|
+
console.log('[SESSION-MANAGER] Received sessions update:', sessions);
|
|
68
70
|
this.sessions = sessions;
|
|
69
71
|
this.updateSessionSelect();
|
|
70
72
|
// Update footer info when new events arrive
|
|
@@ -90,9 +92,28 @@ class SessionManager {
|
|
|
90
92
|
// Store current selection
|
|
91
93
|
const currentSelection = sessionSelect.value;
|
|
92
94
|
|
|
93
|
-
//
|
|
95
|
+
// Get the default working directory from various sources
|
|
96
|
+
let defaultWorkingDir = '/Users/masa/Projects/claude-mpm';
|
|
97
|
+
|
|
98
|
+
// Try to get from working directory manager
|
|
99
|
+
if (window.dashboard && window.dashboard.workingDirectoryManager) {
|
|
100
|
+
defaultWorkingDir = window.dashboard.workingDirectoryManager.getDefaultWorkingDir();
|
|
101
|
+
} else {
|
|
102
|
+
// Fallback: Try to get from header display element
|
|
103
|
+
const headerWorkingDir = document.getElementById('working-dir-path');
|
|
104
|
+
if (headerWorkingDir?.textContent?.trim()) {
|
|
105
|
+
const headerPath = headerWorkingDir.textContent.trim();
|
|
106
|
+
if (headerPath !== 'Loading...' && headerPath !== 'Unknown') {
|
|
107
|
+
defaultWorkingDir = headerPath;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
console.log('[SESSION-MANAGER] Using default working directory:', defaultWorkingDir);
|
|
113
|
+
|
|
114
|
+
// Update "All Sessions" option to show working directory
|
|
94
115
|
sessionSelect.innerHTML = `
|
|
95
|
-
<option value=""
|
|
116
|
+
<option value="">${defaultWorkingDir} | All Sessions</option>
|
|
96
117
|
`;
|
|
97
118
|
|
|
98
119
|
// Add sessions from the sessions map
|
|
@@ -108,8 +129,23 @@ class SessionManager {
|
|
|
108
129
|
const startTime = new Date(session.startTime || session.last_activity).toLocaleString();
|
|
109
130
|
const eventCount = session.eventCount || session.event_count || 0;
|
|
110
131
|
const isActive = session.id === this.currentSessionId;
|
|
111
|
-
|
|
112
|
-
|
|
132
|
+
|
|
133
|
+
// Extract working directory from session or events
|
|
134
|
+
let workingDir = session.working_directory || session.workingDirectory || '';
|
|
135
|
+
|
|
136
|
+
// Log for debugging
|
|
137
|
+
console.log(`[SESSION-DROPDOWN] Session ${session.id.substring(0, 8)} working_directory:`, workingDir);
|
|
138
|
+
|
|
139
|
+
if (!workingDir) {
|
|
140
|
+
const sessionData = this.extractSessionInfoFromEvents(session.id);
|
|
141
|
+
workingDir = sessionData.workingDir || defaultWorkingDir;
|
|
142
|
+
console.log(`[SESSION-DROPDOWN] Extracted working directory from events:`, workingDir);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Format display: working_directory | session_id...
|
|
146
|
+
const shortId = session.id.substring(0, 8);
|
|
147
|
+
const dirDisplay = workingDir || defaultWorkingDir;
|
|
148
|
+
option.textContent = `${dirDisplay} | ${shortId}...${isActive ? ' [ACTIVE]' : ''}`;
|
|
113
149
|
sessionSelect.appendChild(option);
|
|
114
150
|
});
|
|
115
151
|
}
|
|
@@ -81,6 +81,10 @@ class SocketManager {
|
|
|
81
81
|
|
|
82
82
|
// Set up git branch listener when connected
|
|
83
83
|
if (type === 'connected' && this.socketClient && this.socketClient.socket) {
|
|
84
|
+
// Expose socket globally for components like CodeTree
|
|
85
|
+
window.socket = this.socketClient.socket;
|
|
86
|
+
console.log('SocketManager: Exposed socket globally as window.socket');
|
|
87
|
+
|
|
84
88
|
this.setupGitBranchListener();
|
|
85
89
|
}
|
|
86
90
|
}
|
|
@@ -105,6 +109,9 @@ class SocketManager {
|
|
|
105
109
|
|
|
106
110
|
if (this.socketClient.socket.connected) {
|
|
107
111
|
console.log('SocketManager: Socket is already connected, updating status');
|
|
112
|
+
// Expose socket globally for components like CodeTree
|
|
113
|
+
window.socket = this.socketClient.socket;
|
|
114
|
+
console.log('SocketManager: Exposed socket globally as window.socket');
|
|
108
115
|
this.updateConnectionStatus('Connected', 'connected');
|
|
109
116
|
} else if (this.socketClient.isConnecting || this.socketClient.socket.connecting) {
|
|
110
117
|
console.log('SocketManager: Socket is connecting, updating status');
|
|
@@ -123,6 +130,11 @@ class SocketManager {
|
|
|
123
130
|
console.log('SocketManager: Secondary status check after 1 second');
|
|
124
131
|
if (this.socketClient && this.socketClient.socket && this.socketClient.socket.connected) {
|
|
125
132
|
console.log('SocketManager: Socket connected in secondary check, updating status');
|
|
133
|
+
// Expose socket globally if not already done
|
|
134
|
+
if (!window.socket) {
|
|
135
|
+
window.socket = this.socketClient.socket;
|
|
136
|
+
console.log('SocketManager: Exposed socket globally as window.socket (secondary check)');
|
|
137
|
+
}
|
|
126
138
|
this.updateConnectionStatus('Connected', 'connected');
|
|
127
139
|
}
|
|
128
140
|
}, 1000);
|
|
@@ -92,9 +92,13 @@ class UIStateManager {
|
|
|
92
92
|
getTabNameFromButton(button) {
|
|
93
93
|
const text = button.textContent.toLowerCase();
|
|
94
94
|
if (text.includes('events')) return 'events';
|
|
95
|
+
if (text.includes('activity')) return 'activity';
|
|
95
96
|
if (text.includes('agents')) return 'agents';
|
|
96
97
|
if (text.includes('tools')) return 'tools';
|
|
97
98
|
if (text.includes('files')) return 'files';
|
|
99
|
+
if (text.includes('code')) return 'code';
|
|
100
|
+
if (text.includes('sessions')) return 'sessions';
|
|
101
|
+
if (text.includes('system')) return 'system';
|
|
98
102
|
return 'events';
|
|
99
103
|
}
|
|
100
104
|
|
|
@@ -310,8 +310,24 @@ class WorkingDirectoryManager {
|
|
|
310
310
|
*/
|
|
311
311
|
getDefaultWorkingDir() {
|
|
312
312
|
console.log('[WORKING-DIR-DEBUG] getDefaultWorkingDir called');
|
|
313
|
+
|
|
314
|
+
// Try to get from the current working directory if set
|
|
315
|
+
if (this.currentWorkingDir && this.validateDirectoryPath(this.currentWorkingDir)) {
|
|
316
|
+
console.log('[WORKING-DIR-DEBUG] Using current working directory:', this.currentWorkingDir);
|
|
317
|
+
return this.currentWorkingDir;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Try to get from header display
|
|
321
|
+
const headerWorkingDir = document.querySelector('.working-dir-text');
|
|
322
|
+
if (headerWorkingDir?.textContent?.trim()) {
|
|
323
|
+
const headerPath = headerWorkingDir.textContent.trim();
|
|
324
|
+
if (headerPath !== 'Loading...' && headerPath !== 'Unknown' && this.validateDirectoryPath(headerPath)) {
|
|
325
|
+
console.log('[WORKING-DIR-DEBUG] Using header working directory:', headerPath);
|
|
326
|
+
return headerPath;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
313
329
|
|
|
314
|
-
// Try to get from footer
|
|
330
|
+
// Try to get from footer
|
|
315
331
|
const footerDir = document.getElementById('footer-working-dir');
|
|
316
332
|
if (footerDir?.textContent?.trim()) {
|
|
317
333
|
const footerPath = footerDir.textContent.trim();
|
|
@@ -372,6 +372,45 @@ class Dashboard {
|
|
|
372
372
|
case 'events':
|
|
373
373
|
// Events tab is handled by EventViewer
|
|
374
374
|
break;
|
|
375
|
+
case 'activity':
|
|
376
|
+
// Trigger Activity tab rendering through the component
|
|
377
|
+
// Check if ActivityTree class is available (from built module)
|
|
378
|
+
if (window.ActivityTree && typeof window.ActivityTree === 'function') {
|
|
379
|
+
// Create or get instance
|
|
380
|
+
if (!window.activityTreeInstance) {
|
|
381
|
+
console.log('Creating new ActivityTree instance...');
|
|
382
|
+
window.activityTreeInstance = new window.ActivityTree();
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Initialize if needed and render
|
|
386
|
+
if (window.activityTreeInstance) {
|
|
387
|
+
if (!window.activityTreeInstance.initialized) {
|
|
388
|
+
console.log('Initializing ActivityTree...');
|
|
389
|
+
window.activityTreeInstance.initialize();
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
if (typeof window.activityTreeInstance.renderWhenVisible === 'function') {
|
|
393
|
+
console.log('Dashboard triggering activity tree render...');
|
|
394
|
+
window.activityTreeInstance.renderWhenVisible();
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
} else if (window.activityTree && typeof window.activityTree === 'function') {
|
|
398
|
+
// Fallback to legacy approach if available
|
|
399
|
+
const activityTreeInstance = window.activityTree();
|
|
400
|
+
if (activityTreeInstance && typeof activityTreeInstance.renderWhenVisible === 'function') {
|
|
401
|
+
console.log('Dashboard triggering activity tree render (legacy)...');
|
|
402
|
+
activityTreeInstance.renderWhenVisible();
|
|
403
|
+
}
|
|
404
|
+
} else {
|
|
405
|
+
// Module not loaded yet, retry after a delay
|
|
406
|
+
console.warn('Activity tree component not available, retrying in 100ms...');
|
|
407
|
+
setTimeout(() => {
|
|
408
|
+
if (this.currentTab === 'activity') {
|
|
409
|
+
this.renderCurrentTab();
|
|
410
|
+
}
|
|
411
|
+
}, 100);
|
|
412
|
+
}
|
|
413
|
+
break;
|
|
375
414
|
case 'agents':
|
|
376
415
|
this.renderAgents();
|
|
377
416
|
break;
|