claude-mpm 4.2.40__py3-none-any.whl → 4.2.43__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_ENGINEER.md +114 -1
- claude_mpm/agents/BASE_OPS.md +156 -1
- claude_mpm/agents/INSTRUCTIONS.md +120 -11
- claude_mpm/agents/WORKFLOW.md +160 -10
- claude_mpm/agents/templates/agentic-coder-optimizer.json +17 -12
- claude_mpm/agents/templates/react_engineer.json +217 -0
- claude_mpm/agents/templates/web_qa.json +40 -4
- claude_mpm/commands/mpm-browser-monitor.md +370 -0
- claude_mpm/commands/mpm-monitor.md +177 -0
- claude_mpm/dashboard/static/built/components/code-viewer.js +1076 -2
- claude_mpm/dashboard/static/built/components/ui-state-manager.js +465 -2
- claude_mpm/dashboard/static/css/dashboard.css +2 -0
- claude_mpm/dashboard/static/js/browser-console-monitor.js +495 -0
- claude_mpm/dashboard/static/js/components/browser-log-viewer.js +763 -0
- claude_mpm/dashboard/static/js/components/code-viewer.js +931 -340
- claude_mpm/dashboard/static/js/components/diff-viewer.js +891 -0
- claude_mpm/dashboard/static/js/components/file-change-tracker.js +443 -0
- claude_mpm/dashboard/static/js/components/file-change-viewer.js +690 -0
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +156 -19
- claude_mpm/dashboard/static/js/dashboard.js +16 -0
- claude_mpm/dashboard/static/js/socket-client.js +2 -2
- claude_mpm/dashboard/static/test-browser-monitor.html +470 -0
- claude_mpm/dashboard/templates/index.html +64 -99
- claude_mpm/services/monitor/handlers/browser.py +451 -0
- claude_mpm/services/monitor/server.py +267 -4
- {claude_mpm-4.2.40.dist-info → claude_mpm-4.2.43.dist-info}/METADATA +1 -1
- {claude_mpm-4.2.40.dist-info → claude_mpm-4.2.43.dist-info}/RECORD +32 -26
- claude_mpm/agents/templates/agentic-coder-optimizer.md +0 -44
- claude_mpm/agents/templates/agentic_coder_optimizer.json +0 -238
- claude_mpm/agents/templates/test-non-mpm.json +0 -20
- claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
- {claude_mpm-4.2.40.dist-info → claude_mpm-4.2.43.dist-info}/WHEEL +0 -0
- {claude_mpm-4.2.40.dist-info → claude_mpm-4.2.43.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.2.40.dist-info → claude_mpm-4.2.43.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.2.40.dist-info → claude_mpm-4.2.43.dist-info}/top_level.txt +0 -0
@@ -14,8 +14,31 @@
|
|
14
14
|
*/
|
15
15
|
class UIStateManager {
|
16
16
|
constructor() {
|
17
|
-
//
|
18
|
-
this.
|
17
|
+
// Hash to tab mapping
|
18
|
+
this.hashToTab = {
|
19
|
+
'#events': 'events',
|
20
|
+
'#agents': 'agents',
|
21
|
+
'#tools': 'tools',
|
22
|
+
'#files': 'files',
|
23
|
+
'#activity': 'activity',
|
24
|
+
'#file_tree': 'claude-tree',
|
25
|
+
'#browser_logs': 'browser-logs',
|
26
|
+
'': 'events', // default
|
27
|
+
};
|
28
|
+
|
29
|
+
// Tab to hash mapping (reverse lookup)
|
30
|
+
this.tabToHash = {
|
31
|
+
'events': '#events',
|
32
|
+
'agents': '#agents',
|
33
|
+
'tools': '#tools',
|
34
|
+
'files': '#files',
|
35
|
+
'activity': '#activity',
|
36
|
+
'claude-tree': '#file_tree',
|
37
|
+
'browser-logs': '#browser_logs'
|
38
|
+
};
|
39
|
+
|
40
|
+
// Current active tab - will be set based on URL hash
|
41
|
+
this.currentTab = this.getTabFromHash();
|
19
42
|
|
20
43
|
// Auto-scroll behavior
|
21
44
|
this.autoScroll = true;
|
@@ -37,30 +60,64 @@ class UIStateManager {
|
|
37
60
|
};
|
38
61
|
|
39
62
|
this.setupEventHandlers();
|
40
|
-
console.log('UI state manager initialized');
|
63
|
+
console.log('UI state manager initialized with hash navigation');
|
64
|
+
|
65
|
+
// Initialize with current hash
|
66
|
+
this.handleHashChange();
|
67
|
+
}
|
68
|
+
|
69
|
+
/**
|
70
|
+
* Get tab name from current URL hash
|
71
|
+
* @returns {string} - Tab name based on hash
|
72
|
+
*/
|
73
|
+
getTabFromHash() {
|
74
|
+
const hash = window.location.hash || '';
|
75
|
+
return this.hashToTab[hash] || 'events';
|
41
76
|
}
|
42
77
|
|
43
78
|
/**
|
44
79
|
* Set up event handlers for UI interactions
|
45
80
|
*/
|
46
81
|
setupEventHandlers() {
|
47
|
-
this.
|
82
|
+
this.setupHashNavigation();
|
48
83
|
this.setupUnifiedKeyboardNavigation();
|
49
84
|
}
|
50
85
|
|
51
86
|
/**
|
52
|
-
* Set up
|
87
|
+
* Set up hash-based navigation
|
53
88
|
*/
|
54
|
-
|
55
|
-
//
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
89
|
+
setupHashNavigation() {
|
90
|
+
// Handle hash changes
|
91
|
+
window.addEventListener('hashchange', (e) => {
|
92
|
+
console.log('[Hash Navigation] Hash changed from', new URL(e.oldURL).hash, 'to', window.location.hash);
|
93
|
+
this.handleHashChange();
|
94
|
+
});
|
95
|
+
|
96
|
+
// Handle initial page load
|
97
|
+
document.addEventListener('DOMContentLoaded', () => {
|
98
|
+
console.log('[Hash Navigation] Initial hash:', window.location.hash);
|
99
|
+
this.handleHashChange();
|
61
100
|
});
|
62
101
|
}
|
63
102
|
|
103
|
+
/**
|
104
|
+
* Handle hash change events
|
105
|
+
*/
|
106
|
+
handleHashChange() {
|
107
|
+
const hash = window.location.hash || '';
|
108
|
+
const tabName = this.hashToTab[hash] || 'events';
|
109
|
+
console.log('[Hash Navigation] Switching to tab:', tabName, 'from hash:', hash);
|
110
|
+
this.switchTab(tabName, false); // false = don't update hash (we're responding to hash change)
|
111
|
+
}
|
112
|
+
|
113
|
+
/**
|
114
|
+
* DEPRECATED: Tab navigation is now handled by hash navigation
|
115
|
+
* This method is kept for backward compatibility but does nothing
|
116
|
+
*/
|
117
|
+
setupTabNavigation() {
|
118
|
+
console.log('[Hash Navigation] setupTabNavigation is deprecated - using hash navigation instead');
|
119
|
+
}
|
120
|
+
|
64
121
|
/**
|
65
122
|
* Set up unified keyboard navigation across all tabs
|
66
123
|
*/
|
@@ -90,12 +147,19 @@ class UIStateManager {
|
|
90
147
|
* @returns {string} - Tab name
|
91
148
|
*/
|
92
149
|
getTabNameFromButton(button) {
|
150
|
+
// First check for data-tab attribute
|
151
|
+
const dataTab = button.getAttribute('data-tab');
|
152
|
+
if (dataTab) return dataTab;
|
153
|
+
|
154
|
+
// Fallback to text content matching
|
93
155
|
const text = button.textContent.toLowerCase();
|
94
156
|
if (text.includes('events')) return 'events';
|
95
157
|
if (text.includes('activity')) return 'activity';
|
96
158
|
if (text.includes('agents')) return 'agents';
|
97
159
|
if (text.includes('tools')) return 'tools';
|
160
|
+
if (text.includes('browser')) return 'browser-logs'; // Added browser logs support
|
98
161
|
if (text.includes('files')) return 'files';
|
162
|
+
if (text.includes('file tree')) return 'claude-tree';
|
99
163
|
if (text.includes('code')) return 'code';
|
100
164
|
if (text.includes('sessions')) return 'sessions';
|
101
165
|
if (text.includes('system')) return 'system';
|
@@ -105,28 +169,70 @@ class UIStateManager {
|
|
105
169
|
/**
|
106
170
|
* Switch to specified tab
|
107
171
|
* @param {string} tabName - Name of tab to switch to
|
172
|
+
* @param {boolean} updateHash - Whether to update URL hash (default: true)
|
108
173
|
*/
|
109
|
-
switchTab(tabName) {
|
110
|
-
console.log(`[
|
174
|
+
switchTab(tabName, updateHash = true) {
|
175
|
+
console.log(`[Hash Navigation] switchTab called with tabName: ${tabName}, updateHash: ${updateHash}`);
|
176
|
+
|
177
|
+
// Update URL hash if requested (when triggered by user action, not hash change)
|
178
|
+
if (updateHash && this.tabToHash[tabName]) {
|
179
|
+
const newHash = this.tabToHash[tabName];
|
180
|
+
if (window.location.hash !== newHash) {
|
181
|
+
console.log(`[Hash Navigation] Updating hash to: ${newHash}`);
|
182
|
+
window.location.hash = newHash;
|
183
|
+
return; // The hashchange event will trigger switchTab again
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
111
187
|
const previousTab = this.currentTab;
|
112
188
|
this.currentTab = tabName;
|
113
189
|
|
114
|
-
// Update tab button active states
|
115
|
-
document.querySelectorAll('.tab-button')
|
190
|
+
// Update tab button active states - ensure ALL tabs are deselected first
|
191
|
+
const allTabButtons = document.querySelectorAll('.tab-button');
|
192
|
+
allTabButtons.forEach(btn => {
|
116
193
|
btn.classList.remove('active');
|
117
|
-
|
194
|
+
});
|
195
|
+
|
196
|
+
// Now add active class ONLY to the selected tab
|
197
|
+
allTabButtons.forEach(btn => {
|
198
|
+
const btnTabName = this.getTabNameFromButton(btn);
|
199
|
+
if (btnTabName === tabName) {
|
118
200
|
btn.classList.add('active');
|
201
|
+
console.log(`[DEBUG] Set active on button with data-tab: ${btn.getAttribute('data-tab')}`);
|
119
202
|
}
|
120
203
|
});
|
121
204
|
|
122
|
-
// Show/hide tab content using CSS classes
|
123
|
-
document.querySelectorAll('.tab-content')
|
205
|
+
// Show/hide tab content using CSS classes - ensure ALL are hidden first
|
206
|
+
const allTabContents = document.querySelectorAll('.tab-content');
|
207
|
+
allTabContents.forEach(content => {
|
124
208
|
content.classList.remove('active');
|
125
209
|
});
|
126
210
|
|
211
|
+
// Now show ONLY the selected tab content
|
127
212
|
const activeTab = document.getElementById(`${tabName}-tab`);
|
128
213
|
if (activeTab) {
|
129
214
|
activeTab.classList.add('active');
|
215
|
+
console.log(`[DEBUG] Set active on content: ${tabName}-tab`);
|
216
|
+
|
217
|
+
// Special handling for File Tree tab - ensure it never shows events
|
218
|
+
if (tabName === 'claude-tree') {
|
219
|
+
const claudeTreeContainer = document.getElementById('claude-tree-container');
|
220
|
+
if (claudeTreeContainer) {
|
221
|
+
// Check if events list somehow got into this container
|
222
|
+
const eventsList = claudeTreeContainer.querySelector('#events-list');
|
223
|
+
if (eventsList) {
|
224
|
+
console.warn('[UIStateManager] Found events-list in File Tree container, removing it!');
|
225
|
+
eventsList.remove();
|
226
|
+
}
|
227
|
+
|
228
|
+
// Check for event items
|
229
|
+
const eventItems = claudeTreeContainer.querySelectorAll('.event-item');
|
230
|
+
if (eventItems.length > 0) {
|
231
|
+
console.warn('[UIStateManager] Found event items in File Tree container, clearing!');
|
232
|
+
eventItems.forEach(item => item.remove());
|
233
|
+
}
|
234
|
+
}
|
235
|
+
}
|
130
236
|
}
|
131
237
|
|
132
238
|
// Clear previous selections when switching tabs
|
@@ -145,6 +251,37 @@ class UIStateManager {
|
|
145
251
|
if (this.autoScroll) {
|
146
252
|
this.scrollCurrentTabToBottom();
|
147
253
|
}
|
254
|
+
|
255
|
+
// Special handling for File Tree tab - trigger the tree render
|
256
|
+
// But DON'T let it manipulate tabs itself
|
257
|
+
if (tabName === 'claude-tree' && window.CodeViewer) {
|
258
|
+
// Call a new method that only renders content, not tab switching
|
259
|
+
if (window.CodeViewer.renderContent) {
|
260
|
+
window.CodeViewer.renderContent();
|
261
|
+
} else {
|
262
|
+
// Fallback to show() but it should be fixed to not switch tabs
|
263
|
+
window.CodeViewer.show();
|
264
|
+
}
|
265
|
+
}
|
266
|
+
|
267
|
+
// SIMPLEST POSSIBLE Browser Logs tab - just static text
|
268
|
+
if (tabName === 'browser-logs') {
|
269
|
+
console.log('[UIStateManager] Switching to Browser Logs tab - simple mode');
|
270
|
+
|
271
|
+
const container = document.getElementById('browser-logs-container');
|
272
|
+
if (container) {
|
273
|
+
// Clear EVERYTHING - no complex logic, just clear it
|
274
|
+
container.innerHTML = '';
|
275
|
+
|
276
|
+
// Set the simplest possible content - just text
|
277
|
+
container.innerHTML = '<h2 style="padding: 20px;">Browser Logs</h2>';
|
278
|
+
|
279
|
+
// That's it. Nothing else. No event listeners, no watchers, nothing.
|
280
|
+
console.log('[UIStateManager] Browser Logs tab set to simple text');
|
281
|
+
} else {
|
282
|
+
console.warn('[UIStateManager] Browser logs container not found');
|
283
|
+
}
|
284
|
+
}
|
148
285
|
}, 100);
|
149
286
|
}
|
150
287
|
|
@@ -493,6 +493,22 @@ class Dashboard {
|
|
493
493
|
case 'files':
|
494
494
|
this.renderFiles();
|
495
495
|
break;
|
496
|
+
case 'browser-logs':
|
497
|
+
// Simple browser logs display - no events
|
498
|
+
const browserLogsContainer = document.getElementById('browser-logs-container');
|
499
|
+
if (browserLogsContainer) {
|
500
|
+
// Only set content if it's not already set
|
501
|
+
if (!browserLogsContainer.querySelector('.browser-logs-simple')) {
|
502
|
+
browserLogsContainer.innerHTML = `
|
503
|
+
<div class="browser-logs-simple" style="padding: 20px;">
|
504
|
+
<h2>Browser Logs</h2>
|
505
|
+
<p style="color: #666;">Browser console monitoring - no events shown here</p>
|
506
|
+
</div>
|
507
|
+
`;
|
508
|
+
}
|
509
|
+
}
|
510
|
+
console.log('[Dashboard] Browser Logs tab rendered (simple mode)');
|
511
|
+
break;
|
496
512
|
}
|
497
513
|
|
498
514
|
// Update selection UI if we have a selected card
|
@@ -351,8 +351,8 @@ class SocketClient {
|
|
351
351
|
timeout: 30000, // Increased connection timeout to 30 seconds
|
352
352
|
forceNew: true,
|
353
353
|
transports: ['websocket', 'polling'],
|
354
|
-
|
355
|
-
|
354
|
+
// Remove client-side ping configuration - let server control this
|
355
|
+
// The server now properly configures: ping_interval=30s, ping_timeout=60s
|
356
356
|
});
|
357
357
|
|
358
358
|
this.setupSocketHandlers();
|