claude-mpm 4.2.39__py3-none-any.whl → 4.2.42__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_ENGINEER.md +114 -1
  3. claude_mpm/agents/BASE_OPS.md +156 -1
  4. claude_mpm/agents/INSTRUCTIONS.md +120 -11
  5. claude_mpm/agents/WORKFLOW.md +160 -10
  6. claude_mpm/agents/templates/agentic-coder-optimizer.json +17 -12
  7. claude_mpm/agents/templates/react_engineer.json +217 -0
  8. claude_mpm/agents/templates/web_qa.json +40 -4
  9. claude_mpm/cli/__init__.py +3 -5
  10. claude_mpm/commands/mpm-browser-monitor.md +370 -0
  11. claude_mpm/commands/mpm-monitor.md +177 -0
  12. claude_mpm/dashboard/static/built/components/code-viewer.js +1076 -2
  13. claude_mpm/dashboard/static/built/components/ui-state-manager.js +465 -2
  14. claude_mpm/dashboard/static/css/dashboard.css +2 -0
  15. claude_mpm/dashboard/static/js/browser-console-monitor.js +495 -0
  16. claude_mpm/dashboard/static/js/components/browser-log-viewer.js +763 -0
  17. claude_mpm/dashboard/static/js/components/code-viewer.js +931 -340
  18. claude_mpm/dashboard/static/js/components/diff-viewer.js +891 -0
  19. claude_mpm/dashboard/static/js/components/file-change-tracker.js +443 -0
  20. claude_mpm/dashboard/static/js/components/file-change-viewer.js +690 -0
  21. claude_mpm/dashboard/static/js/components/ui-state-manager.js +307 -19
  22. claude_mpm/dashboard/static/js/socket-client.js +2 -2
  23. claude_mpm/dashboard/static/test-browser-monitor.html +470 -0
  24. claude_mpm/dashboard/templates/index.html +62 -99
  25. claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
  26. claude_mpm/services/monitor/daemon.py +69 -36
  27. claude_mpm/services/monitor/daemon_manager.py +186 -29
  28. claude_mpm/services/monitor/handlers/browser.py +451 -0
  29. claude_mpm/services/monitor/server.py +272 -5
  30. {claude_mpm-4.2.39.dist-info → claude_mpm-4.2.42.dist-info}/METADATA +1 -1
  31. {claude_mpm-4.2.39.dist-info → claude_mpm-4.2.42.dist-info}/RECORD +35 -29
  32. claude_mpm/agents/templates/agentic-coder-optimizer.md +0 -44
  33. claude_mpm/agents/templates/agentic_coder_optimizer.json +0 -238
  34. claude_mpm/agents/templates/test-non-mpm.json +0 -20
  35. claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
  36. {claude_mpm-4.2.39.dist-info → claude_mpm-4.2.42.dist-info}/WHEEL +0 -0
  37. {claude_mpm-4.2.39.dist-info → claude_mpm-4.2.42.dist-info}/entry_points.txt +0 -0
  38. {claude_mpm-4.2.39.dist-info → claude_mpm-4.2.42.dist-info}/licenses/LICENSE +0 -0
  39. {claude_mpm-4.2.39.dist-info → claude_mpm-4.2.42.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,495 @@
1
+ /**
2
+ * Browser Console Monitor for Claude MPM
3
+ * =====================================
4
+ *
5
+ * Injectable script that captures browser console events and sends them
6
+ * to the Claude MPM monitor server for centralized logging and debugging.
7
+ *
8
+ * DESIGN DECISIONS:
9
+ * - Generates unique browser ID for session tracking
10
+ * - Intercepts all console methods without disrupting normal operation
11
+ * - Provides real-time streaming to monitor server via Socket.IO
12
+ * - Includes visual indicator showing monitoring status
13
+ * - Handles reconnection gracefully for reliability
14
+ * - Captures stack traces for error context
15
+ *
16
+ * USAGE:
17
+ * Include this script in any page: <script src="http://localhost:8765/api/browser-monitor.js"></script>
18
+ * The script will automatically connect to the monitor server and start capturing console events.
19
+ */
20
+
21
+ (function() {
22
+ 'use strict';
23
+
24
+ // Configuration - MONITOR_PORT will be replaced dynamically by server
25
+ const MONITOR_PORT = __MONITOR_PORT__;
26
+ const MONITOR_HOST = 'localhost';
27
+
28
+ // Generate unique browser ID for this session
29
+ const BROWSER_ID = `browser-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
30
+
31
+ // Console levels to intercept
32
+ const CONSOLE_LEVELS = ['log', 'warn', 'error', 'info', 'debug', 'trace'];
33
+
34
+ // State management
35
+ let socket = null;
36
+ let isConnected = false;
37
+ let eventQueue = [];
38
+ let indicator = null;
39
+ let originalConsole = {};
40
+
41
+ // Connection retry configuration
42
+ const RETRY_CONFIG = {
43
+ maxRetries: 5,
44
+ retryDelay: 1000,
45
+ currentRetries: 0
46
+ };
47
+
48
+ /**
49
+ * Initialize the browser console monitoring system
50
+ */
51
+ function initializeMonitor() {
52
+ try {
53
+ console.log(`[Browser Monitor] Initializing for browser ID: ${BROWSER_ID}`);
54
+
55
+ // Store original console methods before interception
56
+ storeOriginalConsoleMethods();
57
+
58
+ // Setup Socket.IO connection
59
+ setupSocketConnection();
60
+
61
+ // Intercept console methods
62
+ interceptConsoleMethods();
63
+
64
+ // Create visual indicator
65
+ createStatusIndicator();
66
+
67
+ // Setup cleanup handlers
68
+ setupCleanupHandlers();
69
+
70
+ } catch (error) {
71
+ console.error('[Browser Monitor] Failed to initialize:', error);
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Store references to original console methods
77
+ */
78
+ function storeOriginalConsoleMethods() {
79
+ CONSOLE_LEVELS.forEach(level => {
80
+ if (console[level] && typeof console[level] === 'function') {
81
+ originalConsole[level] = console[level].bind(console);
82
+ }
83
+ });
84
+ }
85
+
86
+ /**
87
+ * Setup Socket.IO connection to monitor server
88
+ */
89
+ function setupSocketConnection() {
90
+ try {
91
+ // Load Socket.IO if not already available
92
+ if (typeof io === 'undefined') {
93
+ loadSocketIO(() => {
94
+ createSocketConnection();
95
+ });
96
+ } else {
97
+ createSocketConnection();
98
+ }
99
+ } catch (error) {
100
+ console.error('[Browser Monitor] Socket setup error:', error);
101
+ updateIndicatorStatus('error', 'Socket setup failed');
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Load Socket.IO library dynamically
107
+ */
108
+ function loadSocketIO(callback) {
109
+ const script = document.createElement('script');
110
+ script.src = `http://${MONITOR_HOST}:${MONITOR_PORT}/socket.io/socket.io.js`;
111
+ script.onload = callback;
112
+ script.onerror = () => {
113
+ console.error('[Browser Monitor] Failed to load Socket.IO');
114
+ updateIndicatorStatus('error', 'Failed to load Socket.IO');
115
+ };
116
+ document.head.appendChild(script);
117
+ }
118
+
119
+ /**
120
+ * Create the actual Socket.IO connection
121
+ */
122
+ function createSocketConnection() {
123
+ try {
124
+ socket = io(`http://${MONITOR_HOST}:${MONITOR_PORT}`, {
125
+ transports: ['websocket', 'polling'],
126
+ timeout: 5000,
127
+ reconnection: true,
128
+ reconnectionDelay: 1000,
129
+ reconnectionAttempts: RETRY_CONFIG.maxRetries
130
+ });
131
+
132
+ // Connection event handlers
133
+ socket.on('connect', handleSocketConnect);
134
+ socket.on('disconnect', handleSocketDisconnect);
135
+ socket.on('error', handleSocketError);
136
+ socket.on('reconnect', handleSocketReconnect);
137
+
138
+ // Send initial connection event
139
+ setTimeout(() => {
140
+ if (socket && socket.connected) {
141
+ sendBrowserEvent('connect', {
142
+ browser_id: BROWSER_ID,
143
+ user_agent: navigator.userAgent,
144
+ url: window.location.href,
145
+ timestamp: new Date().toISOString()
146
+ });
147
+ }
148
+ }, 100);
149
+
150
+ } catch (error) {
151
+ console.error('[Browser Monitor] Socket connection error:', error);
152
+ updateIndicatorStatus('error', 'Connection failed');
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Handle socket connection
158
+ */
159
+ function handleSocketConnect() {
160
+ isConnected = true;
161
+ RETRY_CONFIG.currentRetries = 0;
162
+
163
+ updateIndicatorStatus('connected', `Connected: ${BROWSER_ID}`);
164
+
165
+ // Send queued events
166
+ flushEventQueue();
167
+
168
+ console.log(`[Browser Monitor] Connected to monitor server: ${BROWSER_ID}`);
169
+ }
170
+
171
+ /**
172
+ * Handle socket disconnection
173
+ */
174
+ function handleSocketDisconnect(reason) {
175
+ isConnected = false;
176
+ updateIndicatorStatus('disconnected', `Disconnected: ${reason}`);
177
+ console.log(`[Browser Monitor] Disconnected from monitor server: ${reason}`);
178
+ }
179
+
180
+ /**
181
+ * Handle socket errors
182
+ */
183
+ function handleSocketError(error) {
184
+ console.error('[Browser Monitor] Socket error:', error);
185
+ updateIndicatorStatus('error', 'Connection error');
186
+ }
187
+
188
+ /**
189
+ * Handle socket reconnection
190
+ */
191
+ function handleSocketReconnect() {
192
+ console.log('[Browser Monitor] Reconnected to monitor server');
193
+ updateIndicatorStatus('connected', `Reconnected: ${BROWSER_ID}`);
194
+ }
195
+
196
+ /**
197
+ * Intercept console methods and capture events
198
+ */
199
+ function interceptConsoleMethods() {
200
+ CONSOLE_LEVELS.forEach(level => {
201
+ if (originalConsole[level]) {
202
+ console[level] = function(...args) {
203
+ // Capture the console event
204
+ captureConsoleEvent(level, args);
205
+
206
+ // Call original console method
207
+ return originalConsole[level].apply(console, args);
208
+ };
209
+ }
210
+ });
211
+ }
212
+
213
+ /**
214
+ * Capture console event and send to monitor server
215
+ */
216
+ function captureConsoleEvent(level, args) {
217
+ try {
218
+ const timestamp = new Date().toISOString();
219
+ const stack = (new Error()).stack;
220
+
221
+ // Serialize arguments safely
222
+ const serializedArgs = args.map(arg => {
223
+ if (arg === null) return 'null';
224
+ if (arg === undefined) return 'undefined';
225
+
226
+ if (typeof arg === 'object') {
227
+ try {
228
+ return JSON.stringify(arg, null, 2);
229
+ } catch (e) {
230
+ return '[Circular Object]';
231
+ }
232
+ } else if (typeof arg === 'function') {
233
+ return `[Function: ${arg.name || 'anonymous'}]`;
234
+ } else {
235
+ return String(arg);
236
+ }
237
+ });
238
+
239
+ const message = serializedArgs.join(' ');
240
+
241
+ // Create event data
242
+ const eventData = {
243
+ browser_id: BROWSER_ID,
244
+ level: level.toUpperCase(),
245
+ timestamp: timestamp,
246
+ message: message,
247
+ args: serializedArgs,
248
+ stack: stack,
249
+ url: window.location.href,
250
+ line_info: extractLineInfo(stack)
251
+ };
252
+
253
+ // Send to monitor server
254
+ sendBrowserEvent('console', eventData);
255
+
256
+ } catch (error) {
257
+ // Use original console to avoid infinite recursion
258
+ originalConsole.error('[Browser Monitor] Error capturing console event:', error);
259
+ }
260
+ }
261
+
262
+ /**
263
+ * Extract line information from stack trace
264
+ */
265
+ function extractLineInfo(stack) {
266
+ if (!stack) return null;
267
+
268
+ try {
269
+ const lines = stack.split('\n');
270
+ // Find the first line that's not from this monitoring script
271
+ for (let i = 1; i < lines.length; i++) {
272
+ const line = lines[i].trim();
273
+ if (line && !line.includes('browser-console-monitor.js')) {
274
+ return line;
275
+ }
276
+ }
277
+ return lines[1] || null;
278
+ } catch (error) {
279
+ return null;
280
+ }
281
+ }
282
+
283
+ /**
284
+ * Send browser event to monitor server
285
+ */
286
+ function sendBrowserEvent(eventType, data) {
287
+ const event = {
288
+ type: eventType,
289
+ data: data,
290
+ timestamp: new Date().toISOString()
291
+ };
292
+
293
+ if (isConnected && socket) {
294
+ socket.emit('browser:' + eventType, data);
295
+ } else {
296
+ // Queue event for later sending
297
+ eventQueue.push(event);
298
+
299
+ // Limit queue size to prevent memory issues
300
+ if (eventQueue.length > 1000) {
301
+ eventQueue = eventQueue.slice(-500); // Keep last 500 events
302
+ }
303
+ }
304
+ }
305
+
306
+ /**
307
+ * Flush queued events when connection is restored
308
+ */
309
+ function flushEventQueue() {
310
+ if (eventQueue.length > 0 && isConnected && socket) {
311
+ console.log(`[Browser Monitor] Sending ${eventQueue.length} queued events`);
312
+
313
+ eventQueue.forEach(event => {
314
+ socket.emit('browser:' + event.type, event.data);
315
+ });
316
+
317
+ eventQueue = [];
318
+ }
319
+ }
320
+
321
+ /**
322
+ * Create visual status indicator
323
+ */
324
+ function createStatusIndicator() {
325
+ try {
326
+ indicator = document.createElement('div');
327
+ indicator.id = 'browser-console-monitor-indicator';
328
+ indicator.style.cssText = `
329
+ position: fixed !important;
330
+ bottom: 10px !important;
331
+ right: 10px !important;
332
+ background: #2d3748 !important;
333
+ color: #e2e8f0 !important;
334
+ padding: 8px 12px !important;
335
+ border-radius: 6px !important;
336
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace !important;
337
+ font-size: 11px !important;
338
+ z-index: 999999 !important;
339
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15) !important;
340
+ border: 1px solid #4a5568 !important;
341
+ cursor: pointer !important;
342
+ transition: all 0.2s ease !important;
343
+ min-width: 180px !important;
344
+ text-align: left !important;
345
+ `;
346
+
347
+ // Add hover effect
348
+ indicator.onmouseover = () => {
349
+ indicator.style.transform = 'scale(1.05)';
350
+ indicator.style.boxShadow = '0 6px 20px rgba(0,0,0,0.25)';
351
+ };
352
+
353
+ indicator.onmouseout = () => {
354
+ indicator.style.transform = 'scale(1)';
355
+ indicator.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)';
356
+ };
357
+
358
+ // Add click to toggle detailed info
359
+ indicator.onclick = () => {
360
+ showMonitorInfo();
361
+ };
362
+
363
+ updateIndicatorStatus('connecting', 'Connecting...');
364
+
365
+ // Wait for DOM to be ready
366
+ if (document.readyState === 'loading') {
367
+ document.addEventListener('DOMContentLoaded', () => {
368
+ document.body.appendChild(indicator);
369
+ });
370
+ } else {
371
+ document.body.appendChild(indicator);
372
+ }
373
+
374
+ } catch (error) {
375
+ console.error('[Browser Monitor] Error creating indicator:', error);
376
+ }
377
+ }
378
+
379
+ /**
380
+ * Update status indicator
381
+ */
382
+ function updateIndicatorStatus(status, message) {
383
+ if (!indicator) return;
384
+
385
+ const statusColors = {
386
+ connecting: '#f6ad55', // orange
387
+ connected: '#48bb78', // green
388
+ disconnected: '#f56565', // red
389
+ error: '#e53e3e' // dark red
390
+ };
391
+
392
+ const statusIcons = {
393
+ connecting: '🔄',
394
+ connected: '✅',
395
+ disconnected: '❌',
396
+ error: '⚠️'
397
+ };
398
+
399
+ indicator.style.backgroundColor = statusColors[status] || '#2d3748';
400
+ indicator.innerHTML = `
401
+ <div style="display: flex; align-items: center; gap: 6px;">
402
+ <span style="font-size: 12px;">${statusIcons[status] || '📡'}</span>
403
+ <span style="font-weight: 500;">Console Monitor</span>
404
+ </div>
405
+ <div style="font-size: 10px; opacity: 0.9; margin-top: 2px;">
406
+ ${message || status}
407
+ </div>
408
+ `;
409
+ }
410
+
411
+ /**
412
+ * Show detailed monitor information
413
+ */
414
+ function showMonitorInfo() {
415
+ const info = {
416
+ browserID: BROWSER_ID,
417
+ status: isConnected ? 'Connected' : 'Disconnected',
418
+ server: `${MONITOR_HOST}:${MONITOR_PORT}`,
419
+ queuedEvents: eventQueue.length,
420
+ url: window.location.href,
421
+ userAgent: navigator.userAgent.substring(0, 50) + '...'
422
+ };
423
+
424
+ console.group('📡 Browser Console Monitor Info');
425
+ Object.entries(info).forEach(([key, value]) => {
426
+ console.log(`${key}:`, value);
427
+ });
428
+ console.groupEnd();
429
+ }
430
+
431
+ /**
432
+ * Setup cleanup handlers for page unload
433
+ */
434
+ function setupCleanupHandlers() {
435
+ window.addEventListener('beforeunload', () => {
436
+ if (socket && isConnected) {
437
+ sendBrowserEvent('disconnect', {
438
+ browser_id: BROWSER_ID,
439
+ timestamp: new Date().toISOString()
440
+ });
441
+ }
442
+ });
443
+
444
+ // Cleanup on page hide (mobile support)
445
+ document.addEventListener('visibilitychange', () => {
446
+ if (document.hidden && socket && isConnected) {
447
+ sendBrowserEvent('hide', {
448
+ browser_id: BROWSER_ID,
449
+ timestamp: new Date().toISOString()
450
+ });
451
+ }
452
+ });
453
+ }
454
+
455
+ /**
456
+ * Restore original console methods (for cleanup)
457
+ */
458
+ function restoreConsole() {
459
+ CONSOLE_LEVELS.forEach(level => {
460
+ if (originalConsole[level]) {
461
+ console[level] = originalConsole[level];
462
+ }
463
+ });
464
+ }
465
+
466
+ // Expose cleanup function globally for manual cleanup if needed
467
+ window.browserConsoleMonitor = {
468
+ disconnect: () => {
469
+ if (socket) {
470
+ socket.disconnect();
471
+ }
472
+ restoreConsole();
473
+ if (indicator && indicator.parentNode) {
474
+ indicator.parentNode.removeChild(indicator);
475
+ }
476
+ },
477
+ getInfo: () => ({
478
+ browserID: BROWSER_ID,
479
+ isConnected: isConnected,
480
+ queuedEvents: eventQueue.length
481
+ })
482
+ };
483
+
484
+ // Initialize when DOM is ready
485
+ if (document.readyState === 'loading') {
486
+ document.addEventListener('DOMContentLoaded', initializeMonitor);
487
+ } else {
488
+ // DOM already loaded
489
+ initializeMonitor();
490
+ }
491
+
492
+ // Also initialize immediately in case DOMContentLoaded has already fired
493
+ setTimeout(initializeMonitor, 100);
494
+
495
+ })();