claude-mpm 4.2.44__py3-none-any.whl → 4.2.51__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_PM.md +43 -1
- claude_mpm/agents/INSTRUCTIONS.md +75 -1
- claude_mpm/agents/WORKFLOW.md +46 -1
- claude_mpm/agents/frontmatter_validator.py +20 -12
- claude_mpm/agents/templates/nextjs_engineer.json +277 -0
- claude_mpm/agents/templates/python_engineer.json +289 -0
- claude_mpm/agents/templates/react_engineer.json +11 -3
- claude_mpm/agents/templates/security.json +50 -9
- claude_mpm/cli/commands/agents.py +2 -2
- claude_mpm/cli/commands/uninstall.py +1 -2
- claude_mpm/cli/interactive/agent_wizard.py +3 -3
- claude_mpm/cli/parsers/agent_manager_parser.py +3 -3
- claude_mpm/cli/parsers/agents_parser.py +1 -1
- claude_mpm/constants.py +1 -1
- claude_mpm/core/error_handler.py +2 -4
- claude_mpm/core/file_utils.py +4 -12
- claude_mpm/core/log_manager.py +8 -5
- claude_mpm/core/logger.py +1 -1
- claude_mpm/core/logging_utils.py +6 -6
- claude_mpm/core/unified_agent_registry.py +18 -4
- claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +188 -0
- claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +156 -0
- claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +38 -0
- claude_mpm/dashboard/react/components/shared/FilterBar.module.css +92 -0
- claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +248 -0
- claude_mpm/dashboard/static/archive/activity_dashboard_test.html +61 -0
- claude_mpm/dashboard/static/archive/test_activity_connection.html +179 -0
- claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +68 -0
- claude_mpm/dashboard/static/archive/test_dashboard.html +409 -0
- claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +519 -0
- claude_mpm/dashboard/static/archive/test_dashboard_verification.html +181 -0
- claude_mpm/dashboard/static/archive/test_file_data.html +315 -0
- claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +243 -0
- claude_mpm/dashboard/static/archive/test_file_tree_fix.html +234 -0
- claude_mpm/dashboard/static/archive/test_file_tree_rename.html +117 -0
- claude_mpm/dashboard/static/archive/test_file_tree_tab.html +115 -0
- claude_mpm/dashboard/static/archive/test_file_viewer.html +224 -0
- claude_mpm/dashboard/static/archive/test_final_activity.html +220 -0
- claude_mpm/dashboard/static/archive/test_tab_fix.html +139 -0
- claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +1 -0
- claude_mpm/dashboard/static/built/components/activity-tree.js +1 -1
- claude_mpm/dashboard/static/built/components/agent-hierarchy.js +777 -0
- claude_mpm/dashboard/static/built/components/agent-inference.js +1 -1
- claude_mpm/dashboard/static/built/components/build-tracker.js +333 -0
- claude_mpm/dashboard/static/built/components/code-simple.js +857 -0
- claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +353 -0
- claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +235 -0
- claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +409 -0
- claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +435 -0
- claude_mpm/dashboard/static/built/components/code-viewer.js +2 -1076
- claude_mpm/dashboard/static/built/components/connection-debug.js +654 -0
- claude_mpm/dashboard/static/built/components/diff-viewer.js +891 -0
- claude_mpm/dashboard/static/built/components/event-processor.js +1 -1
- claude_mpm/dashboard/static/built/components/event-viewer.js +1 -1
- claude_mpm/dashboard/static/built/components/export-manager.js +1 -1
- claude_mpm/dashboard/static/built/components/file-change-tracker.js +443 -0
- claude_mpm/dashboard/static/built/components/file-change-viewer.js +690 -0
- 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/nav-bar.js +145 -0
- claude_mpm/dashboard/static/built/components/page-structure.js +429 -0
- claude_mpm/dashboard/static/built/components/session-manager.js +1 -1
- claude_mpm/dashboard/static/built/components/ui-state-manager.js +2 -465
- claude_mpm/dashboard/static/built/components/working-directory.js +1 -1
- claude_mpm/dashboard/static/built/connection-manager.js +536 -0
- claude_mpm/dashboard/static/built/dashboard.js +1 -1
- claude_mpm/dashboard/static/built/extension-error-handler.js +164 -0
- claude_mpm/dashboard/static/built/react/events.js +30 -0
- claude_mpm/dashboard/static/built/shared/dom-helpers.js +396 -0
- claude_mpm/dashboard/static/built/shared/event-bus.js +330 -0
- claude_mpm/dashboard/static/built/shared/event-filter-service.js +540 -0
- claude_mpm/dashboard/static/built/shared/logger.js +385 -0
- claude_mpm/dashboard/static/built/shared/page-structure.js +251 -0
- claude_mpm/dashboard/static/built/shared/tooltip-service.js +253 -0
- claude_mpm/dashboard/static/built/socket-client.js +1 -1
- claude_mpm/dashboard/static/built/tab-isolation-fix.js +185 -0
- claude_mpm/dashboard/static/css/dashboard.css +28 -5
- claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +1 -0
- claude_mpm/dashboard/static/dist/components/activity-tree.js +1 -1
- claude_mpm/dashboard/static/dist/components/agent-inference.js +1 -1
- claude_mpm/dashboard/static/dist/components/code-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/event-processor.js +1 -1
- claude_mpm/dashboard/static/dist/components/event-viewer.js +1 -1
- claude_mpm/dashboard/static/dist/components/export-manager.js +1 -1
- claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +1 -1
- claude_mpm/dashboard/static/dist/components/module-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/react/events.js +30 -0
- claude_mpm/dashboard/static/dist/socket-client.js +1 -1
- claude_mpm/dashboard/static/events.html +607 -0
- claude_mpm/dashboard/static/index.html +713 -0
- claude_mpm/dashboard/static/js/components/activity-tree.js +3 -17
- claude_mpm/dashboard/static/js/components/agent-hierarchy.js +4 -1
- claude_mpm/dashboard/static/js/components/agent-inference.js +3 -0
- claude_mpm/dashboard/static/js/components/build-tracker.js +8 -0
- claude_mpm/dashboard/static/js/components/code-viewer.js +306 -66
- claude_mpm/dashboard/static/js/components/event-processor.js +3 -0
- claude_mpm/dashboard/static/js/components/event-viewer.js +39 -2
- claude_mpm/dashboard/static/js/components/export-manager.js +3 -0
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +30 -10
- claude_mpm/dashboard/static/js/components/socket-manager.js +4 -0
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +285 -85
- claude_mpm/dashboard/static/js/components/working-directory.js +3 -0
- claude_mpm/dashboard/static/js/dashboard.js +61 -33
- claude_mpm/dashboard/static/js/socket-client.js +12 -8
- claude_mpm/dashboard/static/js/stores/dashboard-store.js +562 -0
- claude_mpm/dashboard/static/js/tab-isolation-fix.js +185 -0
- claude_mpm/dashboard/static/legacy/activity.html +736 -0
- claude_mpm/dashboard/static/legacy/agents.html +786 -0
- claude_mpm/dashboard/static/legacy/files.html +747 -0
- claude_mpm/dashboard/static/legacy/tools.html +831 -0
- claude_mpm/dashboard/static/monitors-index.html +218 -0
- claude_mpm/dashboard/static/monitors.html +431 -0
- claude_mpm/dashboard/static/production/events.html +659 -0
- claude_mpm/dashboard/static/production/main.html +715 -0
- claude_mpm/dashboard/static/production/monitors.html +483 -0
- claude_mpm/dashboard/static/socket.io.min.js +7 -0
- claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +7 -0
- claude_mpm/dashboard/static/test-archive/dashboard.html +635 -0
- claude_mpm/dashboard/static/test-archive/debug-events.html +147 -0
- claude_mpm/dashboard/static/test-archive/test-navigation.html +256 -0
- claude_mpm/dashboard/static/test-archive/test-react-exports.html +180 -0
- claude_mpm/dashboard/templates/index.html +79 -9
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +1 -1
- claude_mpm/services/agents/deployment/agent_discovery_service.py +3 -0
- claude_mpm/services/agents/deployment/agent_template_builder.py +25 -8
- claude_mpm/services/agents/deployment/agent_validator.py +3 -0
- claude_mpm/services/agents/deployment/validation/template_validator.py +13 -4
- claude_mpm/services/agents/local_template_manager.py +2 -6
- claude_mpm/services/monitor/daemon.py +1 -2
- claude_mpm/services/monitor/daemon_manager.py +2 -5
- claude_mpm/services/monitor/event_emitter.py +2 -2
- claude_mpm/services/monitor/handlers/code_analysis.py +4 -6
- claude_mpm/services/monitor/handlers/hooks.py +2 -4
- claude_mpm/services/monitor/server.py +27 -4
- claude_mpm/tools/code_tree_analyzer.py +2 -2
- {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/METADATA +1 -1
- {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/RECORD +146 -81
- claude_mpm/dashboard/static/test-browser-monitor.html +0 -470
- claude_mpm/dashboard/static/test-simple.html +0 -97
- /claude_mpm/dashboard/static/{test_debug.html → test-archive/test_debug.html} +0 -0
- {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/WHEEL +0 -0
- {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,435 @@
|
|
1
|
+
/**
|
2
|
+
* Tree Utility Functions
|
3
|
+
*
|
4
|
+
* Common utility functions extracted from code-tree.js
|
5
|
+
* Provides formatting, file type detection, and other helper functions.
|
6
|
+
*
|
7
|
+
* @module tree-utils
|
8
|
+
*/
|
9
|
+
|
10
|
+
const treeUtils = {
|
11
|
+
/**
|
12
|
+
* Get complexity level from numeric complexity
|
13
|
+
* @param {number} complexity - Complexity value
|
14
|
+
* @returns {string} Complexity level (low/medium/high)
|
15
|
+
*/
|
16
|
+
getComplexityLevel(complexity) {
|
17
|
+
if (complexity <= 5) return 'low';
|
18
|
+
if (complexity <= 10) return 'medium';
|
19
|
+
return 'high';
|
20
|
+
},
|
21
|
+
|
22
|
+
/**
|
23
|
+
* Format file size for display
|
24
|
+
* @param {number} bytes - Size in bytes
|
25
|
+
* @returns {string} Formatted size string
|
26
|
+
*/
|
27
|
+
formatFileSize(bytes) {
|
28
|
+
if (bytes === 0) return '0 B';
|
29
|
+
const k = 1024;
|
30
|
+
const sizes = ['B', 'KB', 'MB', 'GB'];
|
31
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
32
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
|
33
|
+
},
|
34
|
+
|
35
|
+
/**
|
36
|
+
* Get file extension from path
|
37
|
+
* @param {string} filePath - File path
|
38
|
+
* @returns {string} File extension (lowercase)
|
39
|
+
*/
|
40
|
+
getFileExtension(filePath) {
|
41
|
+
if (!filePath) return '';
|
42
|
+
const parts = filePath.split('.');
|
43
|
+
return parts.length > 1 ? parts.pop().toLowerCase() : '';
|
44
|
+
},
|
45
|
+
|
46
|
+
/**
|
47
|
+
* Get descriptive file type for user messages
|
48
|
+
* @param {string} fileName - File name
|
49
|
+
* @returns {string} Human-readable file type description
|
50
|
+
*/
|
51
|
+
getFileTypeDescription(fileName) {
|
52
|
+
if (!fileName) return 'File';
|
53
|
+
|
54
|
+
const ext = this.getFileExtension(fileName);
|
55
|
+
const baseName = fileName.toLowerCase();
|
56
|
+
|
57
|
+
// Special cases
|
58
|
+
if (baseName.endsWith('__init__.py')) {
|
59
|
+
return 'Python package initialization';
|
60
|
+
}
|
61
|
+
if (baseName === 'makefile') {
|
62
|
+
return 'Build configuration';
|
63
|
+
}
|
64
|
+
if (baseName.includes('config') || baseName.includes('settings')) {
|
65
|
+
return 'Configuration file';
|
66
|
+
}
|
67
|
+
if (baseName.includes('test') || baseName.includes('spec')) {
|
68
|
+
return 'Test file';
|
69
|
+
}
|
70
|
+
|
71
|
+
// By extension
|
72
|
+
const typeMap = {
|
73
|
+
'py': 'Python file',
|
74
|
+
'js': 'JavaScript file',
|
75
|
+
'ts': 'TypeScript file',
|
76
|
+
'jsx': 'React component',
|
77
|
+
'tsx': 'React TypeScript component',
|
78
|
+
'html': 'HTML document',
|
79
|
+
'css': 'Stylesheet',
|
80
|
+
'scss': 'SCSS stylesheet',
|
81
|
+
'sass': 'Sass stylesheet',
|
82
|
+
'less': 'LESS stylesheet',
|
83
|
+
'json': 'JSON data',
|
84
|
+
'md': 'Markdown document',
|
85
|
+
'txt': 'Text file',
|
86
|
+
'yml': 'YAML configuration',
|
87
|
+
'yaml': 'YAML configuration',
|
88
|
+
'xml': 'XML document',
|
89
|
+
'sql': 'SQL script',
|
90
|
+
'sh': 'Shell script',
|
91
|
+
'bash': 'Bash script',
|
92
|
+
'toml': 'TOML configuration',
|
93
|
+
'ini': 'INI configuration',
|
94
|
+
'env': 'Environment variables',
|
95
|
+
'dockerfile': 'Docker configuration',
|
96
|
+
'makefile': 'Build configuration',
|
97
|
+
'gitignore': 'Git ignore rules',
|
98
|
+
'readme': 'Documentation'
|
99
|
+
};
|
100
|
+
|
101
|
+
return typeMap[ext] || typeMap[baseName] || 'File';
|
102
|
+
},
|
103
|
+
|
104
|
+
/**
|
105
|
+
* Get file icon based on file type
|
106
|
+
* @param {string} filePath - File path
|
107
|
+
* @returns {string} Unicode emoji icon
|
108
|
+
*/
|
109
|
+
getFileIcon(filePath) {
|
110
|
+
if (!filePath) return '📄';
|
111
|
+
|
112
|
+
const ext = this.getFileExtension(filePath);
|
113
|
+
const fileName = filePath.toLowerCase().split('/').pop();
|
114
|
+
|
115
|
+
const iconMap = {
|
116
|
+
// Programming languages
|
117
|
+
'py': '🐍',
|
118
|
+
'js': '📜',
|
119
|
+
'ts': '📘',
|
120
|
+
'jsx': '⚛️',
|
121
|
+
'tsx': '⚛️',
|
122
|
+
'java': '☕',
|
123
|
+
'c': '🔷',
|
124
|
+
'cpp': '🔷',
|
125
|
+
'cs': '🔷',
|
126
|
+
'go': '🐹',
|
127
|
+
'rs': '🦀',
|
128
|
+
'rb': '💎',
|
129
|
+
'php': '🐘',
|
130
|
+
'swift': '🦉',
|
131
|
+
'kt': '🎯',
|
132
|
+
|
133
|
+
// Web files
|
134
|
+
'html': '🌐',
|
135
|
+
'css': '🎨',
|
136
|
+
'scss': '🎨',
|
137
|
+
'sass': '🎨',
|
138
|
+
'less': '🎨',
|
139
|
+
|
140
|
+
// Data files
|
141
|
+
'json': '📋',
|
142
|
+
'xml': '📰',
|
143
|
+
'csv': '📊',
|
144
|
+
'sql': '🗃️',
|
145
|
+
|
146
|
+
// Documentation
|
147
|
+
'md': '📝',
|
148
|
+
'txt': '📄',
|
149
|
+
'pdf': '📑',
|
150
|
+
'doc': '📃',
|
151
|
+
'docx': '📃',
|
152
|
+
|
153
|
+
// Configuration
|
154
|
+
'yml': '⚙️',
|
155
|
+
'yaml': '⚙️',
|
156
|
+
'toml': '⚙️',
|
157
|
+
'ini': '⚙️',
|
158
|
+
'env': '🔐',
|
159
|
+
|
160
|
+
// Scripts
|
161
|
+
'sh': '🐚',
|
162
|
+
'bash': '🐚',
|
163
|
+
'bat': '🖥️',
|
164
|
+
'ps1': '🖥️',
|
165
|
+
|
166
|
+
// Special files
|
167
|
+
'dockerfile': '🐳',
|
168
|
+
'docker-compose.yml': '🐳',
|
169
|
+
'makefile': '🔨',
|
170
|
+
'package.json': '📦',
|
171
|
+
'requirements.txt': '📦',
|
172
|
+
'gitignore': '🚫',
|
173
|
+
'.gitignore': '🚫',
|
174
|
+
'readme': '📖',
|
175
|
+
'readme.md': '📖',
|
176
|
+
'license': '📜',
|
177
|
+
'license.md': '📜'
|
178
|
+
};
|
179
|
+
|
180
|
+
// Check full filename first, then extension
|
181
|
+
return iconMap[fileName] || iconMap[ext] || '📄';
|
182
|
+
},
|
183
|
+
|
184
|
+
/**
|
185
|
+
* Count different types of AST elements
|
186
|
+
* @param {Array} elements - AST elements
|
187
|
+
* @returns {Object} Element counts
|
188
|
+
*/
|
189
|
+
getElementCounts(elements) {
|
190
|
+
const counts = {
|
191
|
+
classes: 0,
|
192
|
+
functions: 0,
|
193
|
+
methods: 0,
|
194
|
+
total: elements.length
|
195
|
+
};
|
196
|
+
|
197
|
+
elements.forEach(elem => {
|
198
|
+
if (elem.type === 'class') {
|
199
|
+
counts.classes++;
|
200
|
+
if (elem.methods) {
|
201
|
+
counts.methods += elem.methods.length;
|
202
|
+
}
|
203
|
+
} else if (elem.type === 'function') {
|
204
|
+
counts.functions++;
|
205
|
+
}
|
206
|
+
});
|
207
|
+
|
208
|
+
return counts;
|
209
|
+
},
|
210
|
+
|
211
|
+
/**
|
212
|
+
* Format element counts into a readable summary
|
213
|
+
* @param {Object} counts - Element counts
|
214
|
+
* @returns {string} Formatted summary
|
215
|
+
*/
|
216
|
+
formatElementSummary(counts) {
|
217
|
+
const parts = [];
|
218
|
+
|
219
|
+
if (counts.classes > 0) {
|
220
|
+
parts.push(`${counts.classes} class${counts.classes !== 1 ? 'es' : ''}`);
|
221
|
+
}
|
222
|
+
if (counts.functions > 0) {
|
223
|
+
parts.push(`${counts.functions} function${counts.functions !== 1 ? 's' : ''}`);
|
224
|
+
}
|
225
|
+
if (counts.methods > 0) {
|
226
|
+
parts.push(`${counts.methods} method${counts.methods !== 1 ? 's' : ''}`);
|
227
|
+
}
|
228
|
+
|
229
|
+
if (parts.length === 0) {
|
230
|
+
return 'Structural elements for tree view';
|
231
|
+
} else if (parts.length === 1) {
|
232
|
+
return parts[0] + ' found';
|
233
|
+
} else if (parts.length === 2) {
|
234
|
+
return parts.join(' and ') + ' found';
|
235
|
+
} else {
|
236
|
+
return parts.slice(0, -1).join(', ') + ', and ' + parts[parts.length - 1] + ' found';
|
237
|
+
}
|
238
|
+
},
|
239
|
+
|
240
|
+
/**
|
241
|
+
* Get node type from data
|
242
|
+
* @param {Object} node - Node data
|
243
|
+
* @returns {string} Node type
|
244
|
+
*/
|
245
|
+
getNodeType(node) {
|
246
|
+
if (!node) return 'unknown';
|
247
|
+
if (node.type) return node.type;
|
248
|
+
if (node.children && node.children.length > 0) return 'directory';
|
249
|
+
if (node.path) return 'file';
|
250
|
+
return 'unknown';
|
251
|
+
},
|
252
|
+
|
253
|
+
/**
|
254
|
+
* Check if node is a directory
|
255
|
+
* @param {Object} node - Node or node data
|
256
|
+
* @returns {boolean} True if directory
|
257
|
+
*/
|
258
|
+
isNodeDirectory(node) {
|
259
|
+
if (!node) return false;
|
260
|
+
|
261
|
+
// Handle D3 node structure
|
262
|
+
if (node.data) {
|
263
|
+
node = node.data;
|
264
|
+
}
|
265
|
+
|
266
|
+
return node.type === 'directory' ||
|
267
|
+
node.type === 'folder' ||
|
268
|
+
(node.children && node.children.length > 0) ||
|
269
|
+
node.isDirectory === true;
|
270
|
+
},
|
271
|
+
|
272
|
+
/**
|
273
|
+
* Get node icon for tree visualization
|
274
|
+
* @param {string} type - Node type
|
275
|
+
* @returns {string} Unicode icon
|
276
|
+
*/
|
277
|
+
getNodeIcon(type) {
|
278
|
+
const icons = {
|
279
|
+
'module': '📦',
|
280
|
+
'class': '🏗️',
|
281
|
+
'function': '⚡',
|
282
|
+
'method': '🔧',
|
283
|
+
'property': '📌',
|
284
|
+
'directory': '📁',
|
285
|
+
'folder': '📁',
|
286
|
+
'file': '📄',
|
287
|
+
'python': '🐍',
|
288
|
+
'javascript': '📜',
|
289
|
+
'unknown': '❓'
|
290
|
+
};
|
291
|
+
return icons[type] || icons['unknown'];
|
292
|
+
},
|
293
|
+
|
294
|
+
/**
|
295
|
+
* Sort nodes for tree display
|
296
|
+
* @param {Array} nodes - Array of nodes
|
297
|
+
* @returns {Array} Sorted nodes
|
298
|
+
*/
|
299
|
+
sortNodes(nodes) {
|
300
|
+
return nodes.sort((a, b) => {
|
301
|
+
// Directories first
|
302
|
+
const aIsDir = this.isNodeDirectory(a);
|
303
|
+
const bIsDir = this.isNodeDirectory(b);
|
304
|
+
|
305
|
+
if (aIsDir && !bIsDir) return -1;
|
306
|
+
if (!aIsDir && bIsDir) return 1;
|
307
|
+
|
308
|
+
// Then alphabetically
|
309
|
+
const aName = (a.name || a.data?.name || '').toLowerCase();
|
310
|
+
const bName = (b.name || b.data?.name || '').toLowerCase();
|
311
|
+
|
312
|
+
return aName.localeCompare(bName);
|
313
|
+
});
|
314
|
+
},
|
315
|
+
|
316
|
+
/**
|
317
|
+
* Filter nodes based on criteria
|
318
|
+
* @param {Array} nodes - Array of nodes
|
319
|
+
* @param {Object} criteria - Filter criteria
|
320
|
+
* @returns {Array} Filtered nodes
|
321
|
+
*/
|
322
|
+
filterNodes(nodes, criteria = {}) {
|
323
|
+
return nodes.filter(node => {
|
324
|
+
// Language filter
|
325
|
+
if (criteria.language && node.language !== criteria.language) {
|
326
|
+
return false;
|
327
|
+
}
|
328
|
+
|
329
|
+
// Search term filter
|
330
|
+
if (criteria.searchTerm) {
|
331
|
+
const term = criteria.searchTerm.toLowerCase();
|
332
|
+
const name = (node.name || '').toLowerCase();
|
333
|
+
const path = (node.path || '').toLowerCase();
|
334
|
+
|
335
|
+
if (!name.includes(term) && !path.includes(term)) {
|
336
|
+
return false;
|
337
|
+
}
|
338
|
+
}
|
339
|
+
|
340
|
+
// Complexity filter
|
341
|
+
if (criteria.minComplexity && node.complexity < criteria.minComplexity) {
|
342
|
+
return false;
|
343
|
+
}
|
344
|
+
if (criteria.maxComplexity && node.complexity > criteria.maxComplexity) {
|
345
|
+
return false;
|
346
|
+
}
|
347
|
+
|
348
|
+
return true;
|
349
|
+
});
|
350
|
+
},
|
351
|
+
|
352
|
+
/**
|
353
|
+
* Calculate tree statistics
|
354
|
+
* @param {Object} node - Root node
|
355
|
+
* @returns {Object} Tree statistics
|
356
|
+
*/
|
357
|
+
calculateTreeStats(node) {
|
358
|
+
const stats = {
|
359
|
+
files: 0,
|
360
|
+
directories: 0,
|
361
|
+
classes: 0,
|
362
|
+
functions: 0,
|
363
|
+
methods: 0,
|
364
|
+
lines: 0,
|
365
|
+
maxDepth: 0
|
366
|
+
};
|
367
|
+
|
368
|
+
const traverse = (n, depth = 0) => {
|
369
|
+
stats.maxDepth = Math.max(stats.maxDepth, depth);
|
370
|
+
|
371
|
+
if (this.isNodeDirectory(n)) {
|
372
|
+
stats.directories++;
|
373
|
+
} else {
|
374
|
+
stats.files++;
|
375
|
+
}
|
376
|
+
|
377
|
+
if (n.type === 'class') stats.classes++;
|
378
|
+
if (n.type === 'function') stats.functions++;
|
379
|
+
if (n.type === 'method') stats.methods++;
|
380
|
+
if (n.lines) stats.lines += n.lines;
|
381
|
+
|
382
|
+
if (n.children) {
|
383
|
+
n.children.forEach(child => traverse(child, depth + 1));
|
384
|
+
}
|
385
|
+
};
|
386
|
+
|
387
|
+
traverse(node);
|
388
|
+
return stats;
|
389
|
+
},
|
390
|
+
|
391
|
+
/**
|
392
|
+
* Get color based on complexity
|
393
|
+
* @param {number} complexity - Complexity value
|
394
|
+
* @returns {string} Color hex code
|
395
|
+
*/
|
396
|
+
getComplexityColor(complexity) {
|
397
|
+
if (!complexity || complexity <= 5) {
|
398
|
+
return '#52c41a'; // Green - low complexity
|
399
|
+
} else if (complexity <= 10) {
|
400
|
+
return '#faad14'; // Orange - medium complexity
|
401
|
+
} else {
|
402
|
+
return '#f5222d'; // Red - high complexity
|
403
|
+
}
|
404
|
+
},
|
405
|
+
|
406
|
+
/**
|
407
|
+
* Format node path for display
|
408
|
+
* @param {Object} node - Node object
|
409
|
+
* @returns {string} Formatted path
|
410
|
+
*/
|
411
|
+
formatNodePath(node) {
|
412
|
+
const parts = [];
|
413
|
+
let current = node;
|
414
|
+
|
415
|
+
while (current) {
|
416
|
+
if (current.data?.name) {
|
417
|
+
parts.unshift(current.data.name);
|
418
|
+
} else if (current.name) {
|
419
|
+
parts.unshift(current.name);
|
420
|
+
}
|
421
|
+
current = current.parent;
|
422
|
+
}
|
423
|
+
|
424
|
+
return parts.join(' / ');
|
425
|
+
}
|
426
|
+
};
|
427
|
+
|
428
|
+
// Support both module and global usage
|
429
|
+
if (typeof module !== 'undefined' && module.exports) {
|
430
|
+
module.exports = treeUtils;
|
431
|
+
} else if (typeof define === 'function' && define.amd) {
|
432
|
+
define([], () => treeUtils);
|
433
|
+
} else {
|
434
|
+
window.treeUtils = treeUtils;
|
435
|
+
}
|