claude-mpm 4.1.23__py3-none-any.whl → 4.1.25__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 (26) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/dashboard/static/built/components/activity-tree.js +1 -1
  3. claude_mpm/dashboard/static/built/components/code-tree.js +1 -1
  4. claude_mpm/dashboard/static/built/components/event-viewer.js +1 -1
  5. claude_mpm/dashboard/static/built/components/module-viewer.js +1 -1
  6. claude_mpm/dashboard/static/built/components/unified-data-viewer.js +2 -0
  7. claude_mpm/dashboard/static/built/dashboard.js +1 -1
  8. claude_mpm/dashboard/static/css/activity.css +20 -0
  9. claude_mpm/dashboard/static/dist/components/activity-tree.js +1 -1
  10. claude_mpm/dashboard/static/dist/components/event-viewer.js +1 -1
  11. claude_mpm/dashboard/static/dist/components/module-viewer.js +1 -1
  12. claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +2 -0
  13. claude_mpm/dashboard/static/dist/dashboard.js +1 -1
  14. claude_mpm/dashboard/static/js/components/activity-tree.js +4 -2
  15. claude_mpm/dashboard/static/js/components/event-processor.js +0 -107
  16. claude_mpm/dashboard/static/js/components/module-viewer.js +21 -198
  17. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +109 -28
  18. claude_mpm/dashboard/static/js/dashboard.js +22 -428
  19. claude_mpm/tools/code_tree_analyzer.py +3 -1
  20. {claude_mpm-4.1.23.dist-info → claude_mpm-4.1.25.dist-info}/METADATA +1 -1
  21. {claude_mpm-4.1.23.dist-info → claude_mpm-4.1.25.dist-info}/RECORD +25 -24
  22. claude_mpm/dashboard/static/dist/chunks/unified-data-viewer.CvAmgM3l.js +0 -2
  23. {claude_mpm-4.1.23.dist-info → claude_mpm-4.1.25.dist-info}/WHEEL +0 -0
  24. {claude_mpm-4.1.23.dist-info → claude_mpm-4.1.25.dist-info}/entry_points.txt +0 -0
  25. {claude_mpm-4.1.23.dist-info → claude_mpm-4.1.25.dist-info}/licenses/LICENSE +0 -0
  26. {claude_mpm-4.1.23.dist-info → claude_mpm-4.1.25.dist-info}/top_level.txt +0 -0
@@ -1655,7 +1655,7 @@ class ModuleViewer {
1655
1655
  }
1656
1656
 
1657
1657
  /**
1658
- * Show file operations details (backward compatibility method)
1658
+ * Show file operations using UnifiedDataViewer for consistency
1659
1659
  * @param {Object} fileData - The file operations data
1660
1660
  * @param {string} filePath - The file path
1661
1661
  */
@@ -1665,92 +1665,31 @@ class ModuleViewer {
1665
1665
  return;
1666
1666
  }
1667
1667
 
1668
- // Get file name from path for header
1669
- const fileName = filePath.split('/').pop() || filePath;
1670
- const operations = fileData.operations || [];
1671
- const lastOp = operations[operations.length - 1];
1672
- const headerTimestamp = lastOp ? this.formatTimestamp(lastOp.timestamp) : '';
1673
-
1674
- // Create contextual header
1675
- const contextualHeader = `
1676
- <div class="contextual-header">
1677
- <h3 class="contextual-header-text">File: ${fileName} ${headerTimestamp}</h3>
1678
- </div>
1679
- `;
1680
-
1681
- const content = `
1682
- <div class="structured-view-section">
1683
- <div class="file-details">
1684
- <div class="file-path-display">
1685
- <strong>Full Path:</strong> ${this.createClickableFilePath(filePath)}
1686
- <div id="git-track-status-${filePath.replace(/[^a-zA-Z0-9]/g, '-')}" class="git-track-status" style="margin-top: 8px;">
1687
- <!-- Git tracking status will be populated here -->
1688
- </div>
1689
- </div>
1690
- <div class="operations-list">
1691
- ${operations.map(op => `
1692
- <div class="operation-item">
1693
- <div class="operation-header">
1694
- <span class="operation-icon">${this.getOperationIcon(op.operation)}</span>
1695
- <span class="operation-type">${op.operation}</span>
1696
- <span class="operation-timestamp">${new Date(op.timestamp).toLocaleString()}</span>
1697
- ${this.isReadOnlyOperation(op.operation) ? `
1698
- <!-- Read-only operation: show only file viewer -->
1699
- <span class="file-viewer-icon"
1700
- onclick="showFileViewerModal('${filePath}')"
1701
- title="View file contents with syntax highlighting"
1702
- style="margin-left: 8px; cursor: pointer; font-size: 16px;">
1703
- 👁️
1704
- </span>
1705
- ` : `
1706
- <!-- Edit operation: show both file viewer and git diff -->
1707
- <span class="file-viewer-icon"
1708
- onclick="showFileViewerModal('${filePath}')"
1709
- title="View file contents with syntax highlighting"
1710
- style="margin-left: 8px; cursor: pointer; font-size: 16px;">
1711
- 👁️
1712
- </span>
1713
- <span class="git-diff-icon"
1714
- onclick="showGitDiffModal('${filePath}', '${op.timestamp}')"
1715
- title="View git diff for this file operation"
1716
- style="margin-left: 8px; cursor: pointer; font-size: 16px; display: none;"
1717
- data-file-path="${filePath}"
1718
- data-operation-timestamp="${op.timestamp}">
1719
- 📋
1720
- </span>
1721
- `}
1722
- </div>
1723
- <div class="operation-details">
1724
- <strong>Agent:</strong> ${op.agent}<br>
1725
- <strong>Session:</strong> ${op.sessionId ? op.sessionId.substring(0, 8) + '...' : 'Unknown'}
1726
- ${op.details ? this.formatOperationDetails(op.details) : ''}
1727
- </div>
1728
- </div>
1729
- `).join('')}
1730
- </div>
1731
- </div>
1732
- </div>
1733
- `;
1734
-
1735
- // Check git tracking status and show track control if needed
1736
- this.checkAndShowTrackControl(filePath);
1668
+ // Initialize UnifiedDataViewer if not already available
1669
+ if (!this.unifiedViewer) {
1670
+ this.unifiedViewer = new UnifiedDataViewer('module-data-content');
1671
+ }
1737
1672
 
1738
- // Check git status and conditionally show git diff icons
1739
- this.checkAndShowGitDiffIcons(filePath);
1673
+ // Convert file data to standardized format
1674
+ const standardizedFileData = {
1675
+ file_path: filePath,
1676
+ operations: fileData.operations || [],
1677
+ lastOperation: fileData.lastOperation,
1678
+ ...fileData // Preserve any additional data
1679
+ };
1740
1680
 
1741
- // Create collapsible JSON section for file data
1742
- const collapsibleJsonSection = this.createCollapsibleJsonSection(fileData);
1681
+ // Use UnifiedDataViewer for consistent display
1682
+ this.unifiedViewer.display(standardizedFileData, 'file_operation');
1743
1683
 
1744
- // Show structured data with JSON section in data pane
1745
- if (this.dataContainer) {
1746
- this.dataContainer.innerHTML = contextualHeader + content + collapsibleJsonSection;
1684
+ // Update module header for consistency
1685
+ const moduleHeader = document.querySelector('.module-data-header h5');
1686
+ if (moduleHeader) {
1687
+ const fileName = filePath.split('/').pop() || filePath;
1688
+ moduleHeader.textContent = `📄 File: ${fileName}`;
1747
1689
  }
1748
1690
 
1749
- // Initialize JSON toggle functionality
1750
- this.initializeJsonToggle();
1751
-
1752
- // Hide JSON pane since data is integrated above
1753
- // JSON container no longer exists - handled via collapsible sections
1691
+ // Check git tracking status and show track control if needed
1692
+ this.checkAndShowTrackControl(filePath);
1754
1693
  }
1755
1694
 
1756
1695
  /**
@@ -2653,122 +2592,6 @@ class ModuleViewer {
2653
2592
  }
2654
2593
  }
2655
2594
 
2656
- /**
2657
- * Check git status and conditionally show git diff icons
2658
- * Only shows git diff icons if git status check succeeds
2659
- * @param {string} filePath - Path to the file to check
2660
- */
2661
- async checkAndShowGitDiffIcons(filePath) {
2662
- if (!filePath) {
2663
- console.debug('[GIT-DIFF-ICONS] No filePath provided, skipping git diff icon check');
2664
- return;
2665
- }
2666
-
2667
- console.debug('[GIT-DIFF-ICONS] Checking git diff icons for file:', filePath);
2668
-
2669
- try {
2670
- // Get the Socket.IO client
2671
- const socket = window.socket || window.dashboard?.socketClient?.socket;
2672
- if (!socket) {
2673
- console.warn('[GIT-DIFF-ICONS] No socket connection available for git status check');
2674
- return;
2675
- }
2676
-
2677
- console.debug('[GIT-DIFF-ICONS] Socket connection available, proceeding');
2678
-
2679
- // Get working directory from dashboard with proper fallback
2680
- let workingDir = window.dashboard?.currentWorkingDir;
2681
-
2682
- // Don't use 'Unknown' as a working directory
2683
- if (!workingDir || workingDir === 'Unknown' || workingDir.trim() === '') {
2684
- // Try to get from footer element
2685
- const footerDir = document.getElementById('footer-working-dir');
2686
- if (footerDir?.textContent?.trim() && footerDir.textContent.trim() !== 'Unknown') {
2687
- workingDir = footerDir.textContent.trim();
2688
- } else {
2689
- // Final fallback to current directory
2690
- workingDir = '.';
2691
- }
2692
- console.log('[GIT-DIFF-ICONS] Working directory fallback used:', workingDir);
2693
- } else {
2694
- console.debug('[GIT-DIFF-ICONS] Using working directory:', workingDir);
2695
- }
2696
-
2697
- // Set up one-time listener for git status response
2698
- const responsePromise = new Promise((resolve, reject) => {
2699
- const responseHandler = (data) => {
2700
- console.debug('[GIT-DIFF-ICONS] Received git status response:', data);
2701
- if (data.file_path === filePath) {
2702
- socket.off('git_status_response', responseHandler);
2703
- resolve(data);
2704
- } else {
2705
- console.debug('[GIT-DIFF-ICONS] Response for different file, ignoring:', data.file_path);
2706
- }
2707
- };
2708
-
2709
- socket.on('git_status_response', responseHandler);
2710
-
2711
- // Timeout after 3 seconds
2712
- setTimeout(() => {
2713
- socket.off('git_status_response', responseHandler);
2714
- console.warn('[GIT-DIFF-ICONS] Timeout waiting for git status response');
2715
- reject(new Error('Request timeout'));
2716
- }, 3000);
2717
- });
2718
-
2719
- console.debug('[GIT-DIFF-ICONS] Sending check_git_status event');
2720
- // Send git status request
2721
- socket.emit('check_git_status', {
2722
- file_path: filePath,
2723
- working_dir: workingDir
2724
- });
2725
-
2726
- // Wait for response
2727
- const result = await responsePromise;
2728
- console.debug('[GIT-DIFF-ICONS] Git status check result:', result);
2729
-
2730
- // Only show git diff icons if git status check was successful
2731
- if (result.success) {
2732
- console.debug('[GIT-DIFF-ICONS] Git status check successful, showing icons for:', filePath);
2733
- this.showGitDiffIconsForFile(filePath);
2734
- } else {
2735
- console.debug('[GIT-DIFF-ICONS] Git status check failed, icons will remain hidden:', result.error);
2736
- }
2737
- // If git status fails, icons remain hidden (display: none)
2738
-
2739
- } catch (error) {
2740
- console.warn('[GIT-DIFF-ICONS] Git status check failed, hiding git diff icons:', error.message);
2741
- // Icons remain hidden on error
2742
- }
2743
- }
2744
-
2745
- /**
2746
- * Show git diff icons for a specific file after successful git status check
2747
- * @param {string} filePath - Path to the file
2748
- */
2749
- showGitDiffIconsForFile(filePath) {
2750
- console.debug('[GIT-DIFF-ICONS] Showing git diff icons for file:', filePath);
2751
-
2752
- // Find all git diff icons for this file path and show them
2753
- const gitDiffIcons = document.querySelectorAll(`[data-file-path="${filePath}"]`);
2754
- console.debug('[GIT-DIFF-ICONS] Found', gitDiffIcons.length, 'elements with matching file path');
2755
-
2756
- let shownCount = 0;
2757
- gitDiffIcons.forEach((icon, index) => {
2758
- console.debug('[GIT-DIFF-ICONS] Processing element', index, ':', icon);
2759
- console.debug('[GIT-DIFF-ICONS] Element classes:', icon.classList.toString());
2760
-
2761
- if (icon.classList.contains('git-diff-icon')) {
2762
- console.debug('[GIT-DIFF-ICONS] Setting display to inline for git-diff-icon');
2763
- icon.style.display = 'inline';
2764
- shownCount++;
2765
- } else {
2766
- console.debug('[GIT-DIFF-ICONS] Element is not a git-diff-icon, skipping');
2767
- }
2768
- });
2769
-
2770
- console.debug('[GIT-DIFF-ICONS] Showed', shownCount, 'git diff icons for file:', filePath);
2771
- }
2772
2595
 
2773
2596
  /**
2774
2597
  * Show notification to user
@@ -62,7 +62,13 @@ class UnifiedDataViewer {
62
62
  this.displaySession(data);
63
63
  break;
64
64
  case 'file_operation':
65
- this.displayFileOperation(data);
65
+ // Convert file tool to file operation format if needed
66
+ if (data.name && (data.params || data.tool_parameters)) {
67
+ const convertedData = this.convertToolToFileOperation(data);
68
+ this.displayFileOperation(convertedData);
69
+ } else {
70
+ this.displayFileOperation(data);
71
+ }
66
72
  break;
67
73
  case 'hook':
68
74
  this.displayHook(data);
@@ -124,6 +130,14 @@ class UnifiedDataViewer {
124
130
  return 'file_operation';
125
131
  }
126
132
 
133
+ // File tool detection - handle file tools as file operations when they have file_path
134
+ if ((data.name === 'Read' || data.name === 'Write' || data.name === 'Edit' ||
135
+ data.name === 'MultiEdit' || data.name === 'Grep' || data.name === 'Glob') &&
136
+ (data.params?.file_path || data.tool_parameters?.file_path)) {
137
+ // Convert file tool to file operation format for better display
138
+ return 'file_operation';
139
+ }
140
+
127
141
  // Hook detection
128
142
  if (data.event_type && (data.hook_name || data.subtype)) {
129
143
  return 'hook';
@@ -426,24 +440,12 @@ class UnifiedDataViewer {
426
440
  if (todos.length > 0) {
427
441
  const statusCounts = this.getTodoStatusCounts(todos);
428
442
 
429
- // Status summary bar
443
+ // Status summary - horizontal single line format
430
444
  html += `
431
- <div class="todo-status-bar">
432
- <div class="status-item completed">
433
- <span class="status-icon">✅</span>
434
- <span class="status-count">${statusCounts.completed}</span>
435
- <span class="status-label">Done</span>
436
- </div>
437
- <div class="status-item in_progress">
438
- <span class="status-icon">🔄</span>
439
- <span class="status-count">${statusCounts.in_progress}</span>
440
- <span class="status-label">Active</span>
441
- </div>
442
- <div class="status-item pending">
443
- <span class="status-icon">⏳</span>
444
- <span class="status-count">${statusCounts.pending}</span>
445
- <span class="status-label">Pending</span>
446
- </div>
445
+ <div class="todo-status-line">
446
+ <span class="status-inline">✅ ${statusCounts.completed} Done</span>
447
+ <span class="status-inline">🔄 ${statusCounts.in_progress} Active</span>
448
+ <span class="status-inline">⏳ ${statusCounts.pending} Pending</span>
447
449
  </div>
448
450
  `;
449
451
 
@@ -644,30 +646,54 @@ class UnifiedDataViewer {
644
646
  }
645
647
 
646
648
  /**
647
- * Display file operation data
649
+ * Display file operation data with file viewing capabilities
648
650
  */
649
651
  displayFileOperation(data) {
652
+ const fileName = data.file_path ? data.file_path.split('/').pop() : 'Unknown File';
653
+
650
654
  let html = `
651
655
  <div class="unified-viewer-header">
652
- <h6>📄 File: ${data.file_path}</h6>
656
+ <h6>📄 File: ${fileName}</h6>
653
657
  <span class="unified-viewer-count">${data.operations ? data.operations.length : 1} operation${data.operations && data.operations.length !== 1 ? 's' : ''}</span>
654
658
  </div>
655
659
  <div class="unified-viewer-content">
656
- <div class="detail-row">
657
- <span class="detail-label">File Path:</span>
658
- <span class="detail-value">${data.file_path}</span>
659
- </div>
660
+ <div class="primary-data">
661
+ <div class="detail-row highlight">
662
+ <span class="detail-label">📁 File Path:</span>
663
+ <span class="detail-value code">${data.file_path}</span>
664
+ </div>
660
665
  `;
661
666
 
667
+ // Add file viewing button for tracked files
668
+ if (data.file_path) {
669
+ html += `
670
+ <div class="file-actions">
671
+ <button class="file-action-btn view-file-btn"
672
+ onclick="window.showFileViewerModal && window.showFileViewerModal('${data.file_path}')"
673
+ title="View file contents with syntax highlighting">
674
+ 👁️ View File Contents
675
+ </button>
676
+ </div>
677
+ `;
678
+ }
679
+
680
+ html += `</div>`;
681
+
662
682
  if (data.operations && Array.isArray(data.operations)) {
663
683
  html += `
664
684
  <div class="detail-section">
665
- <span class="detail-section-title">Operations:</span>
685
+ <span class="detail-section-title">Operations (${data.operations.length}):</span>
666
686
  <div class="operations-list">
667
- ${data.operations.map(op => `
687
+ ${data.operations.map((op, index) => `
668
688
  <div class="operation-item">
669
- <span class="operation-type">${op.operation}</span>
670
- <span class="operation-timestamp">${this.formatTimestamp(op.timestamp)}</span>
689
+ <div class="operation-header">
690
+ <span class="operation-type">${this.getOperationIcon(op.operation)} ${op.operation}</span>
691
+ <span class="operation-timestamp">${this.formatTimestamp(op.timestamp)}</span>
692
+ </div>
693
+ <div class="operation-details">
694
+ <span class="operation-agent">by ${op.agent || 'Unknown'}</span>
695
+ ${op.workingDirectory ? `<span class="operation-dir">in ${op.workingDirectory}</span>` : ''}
696
+ </div>
671
697
  </div>
672
698
  `).join('')}
673
699
  </div>
@@ -675,6 +701,9 @@ class UnifiedDataViewer {
675
701
  `;
676
702
  }
677
703
 
704
+ // Add collapsible JSON viewer for full file data
705
+ html += this.createCollapsibleJSON(data, 'Full File Data');
706
+
678
707
  html += '</div>';
679
708
  this.container.innerHTML = html;
680
709
  }
@@ -1179,6 +1208,58 @@ class UnifiedDataViewer {
1179
1208
  return icons[status] || '❓';
1180
1209
  }
1181
1210
 
1211
+ /**
1212
+ * Get icon for file operation type
1213
+ */
1214
+ getOperationIcon(operation) {
1215
+ const icons = {
1216
+ 'read': '👁️',
1217
+ 'write': '✍️',
1218
+ 'edit': '✏️',
1219
+ 'delete': '🗑️',
1220
+ 'create': '📝',
1221
+ 'search': '🔍',
1222
+ 'list': '📂',
1223
+ 'copy': '📋',
1224
+ 'move': '📦',
1225
+ 'bash': '💻'
1226
+ };
1227
+ return icons[operation.toLowerCase()] || '📄';
1228
+ }
1229
+
1230
+ /**
1231
+ * Convert tool data to file operation format for better display
1232
+ */
1233
+ convertToolToFileOperation(toolData) {
1234
+ const params = toolData.params || toolData.tool_parameters || {};
1235
+ const filePath = params.file_path || params.path || params.notebook_path;
1236
+
1237
+ if (!filePath) {
1238
+ return toolData; // Return original if no file path
1239
+ }
1240
+
1241
+ // Create file operation format
1242
+ const operation = {
1243
+ operation: toolData.name.toLowerCase(),
1244
+ timestamp: toolData.timestamp || new Date().toISOString(),
1245
+ agent: 'Activity Tool',
1246
+ sessionId: toolData.sessionId || 'unknown',
1247
+ details: {
1248
+ parameters: params,
1249
+ tool_name: toolData.name,
1250
+ status: toolData.status || 'completed'
1251
+ }
1252
+ };
1253
+
1254
+ return {
1255
+ file_path: filePath,
1256
+ operations: [operation],
1257
+ lastOperation: operation.timestamp,
1258
+ // Preserve original tool data for reference
1259
+ originalTool: toolData
1260
+ };
1261
+ }
1262
+
1182
1263
  /**
1183
1264
  * Get todo status counts
1184
1265
  */