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.
Files changed (148) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_PM.md +43 -1
  3. claude_mpm/agents/INSTRUCTIONS.md +75 -1
  4. claude_mpm/agents/WORKFLOW.md +46 -1
  5. claude_mpm/agents/frontmatter_validator.py +20 -12
  6. claude_mpm/agents/templates/nextjs_engineer.json +277 -0
  7. claude_mpm/agents/templates/python_engineer.json +289 -0
  8. claude_mpm/agents/templates/react_engineer.json +11 -3
  9. claude_mpm/agents/templates/security.json +50 -9
  10. claude_mpm/cli/commands/agents.py +2 -2
  11. claude_mpm/cli/commands/uninstall.py +1 -2
  12. claude_mpm/cli/interactive/agent_wizard.py +3 -3
  13. claude_mpm/cli/parsers/agent_manager_parser.py +3 -3
  14. claude_mpm/cli/parsers/agents_parser.py +1 -1
  15. claude_mpm/constants.py +1 -1
  16. claude_mpm/core/error_handler.py +2 -4
  17. claude_mpm/core/file_utils.py +4 -12
  18. claude_mpm/core/log_manager.py +8 -5
  19. claude_mpm/core/logger.py +1 -1
  20. claude_mpm/core/logging_utils.py +6 -6
  21. claude_mpm/core/unified_agent_registry.py +18 -4
  22. claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +188 -0
  23. claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +156 -0
  24. claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +38 -0
  25. claude_mpm/dashboard/react/components/shared/FilterBar.module.css +92 -0
  26. claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +248 -0
  27. claude_mpm/dashboard/static/archive/activity_dashboard_test.html +61 -0
  28. claude_mpm/dashboard/static/archive/test_activity_connection.html +179 -0
  29. claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +68 -0
  30. claude_mpm/dashboard/static/archive/test_dashboard.html +409 -0
  31. claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +519 -0
  32. claude_mpm/dashboard/static/archive/test_dashboard_verification.html +181 -0
  33. claude_mpm/dashboard/static/archive/test_file_data.html +315 -0
  34. claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +243 -0
  35. claude_mpm/dashboard/static/archive/test_file_tree_fix.html +234 -0
  36. claude_mpm/dashboard/static/archive/test_file_tree_rename.html +117 -0
  37. claude_mpm/dashboard/static/archive/test_file_tree_tab.html +115 -0
  38. claude_mpm/dashboard/static/archive/test_file_viewer.html +224 -0
  39. claude_mpm/dashboard/static/archive/test_final_activity.html +220 -0
  40. claude_mpm/dashboard/static/archive/test_tab_fix.html +139 -0
  41. claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +1 -0
  42. claude_mpm/dashboard/static/built/components/activity-tree.js +1 -1
  43. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +777 -0
  44. claude_mpm/dashboard/static/built/components/agent-inference.js +1 -1
  45. claude_mpm/dashboard/static/built/components/build-tracker.js +333 -0
  46. claude_mpm/dashboard/static/built/components/code-simple.js +857 -0
  47. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +353 -0
  48. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +235 -0
  49. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +409 -0
  50. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +435 -0
  51. claude_mpm/dashboard/static/built/components/code-viewer.js +2 -1076
  52. claude_mpm/dashboard/static/built/components/connection-debug.js +654 -0
  53. claude_mpm/dashboard/static/built/components/diff-viewer.js +891 -0
  54. claude_mpm/dashboard/static/built/components/event-processor.js +1 -1
  55. claude_mpm/dashboard/static/built/components/event-viewer.js +1 -1
  56. claude_mpm/dashboard/static/built/components/export-manager.js +1 -1
  57. claude_mpm/dashboard/static/built/components/file-change-tracker.js +443 -0
  58. claude_mpm/dashboard/static/built/components/file-change-viewer.js +690 -0
  59. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +1 -1
  60. claude_mpm/dashboard/static/built/components/module-viewer.js +1 -1
  61. claude_mpm/dashboard/static/built/components/nav-bar.js +145 -0
  62. claude_mpm/dashboard/static/built/components/page-structure.js +429 -0
  63. claude_mpm/dashboard/static/built/components/session-manager.js +1 -1
  64. claude_mpm/dashboard/static/built/components/ui-state-manager.js +2 -465
  65. claude_mpm/dashboard/static/built/components/working-directory.js +1 -1
  66. claude_mpm/dashboard/static/built/connection-manager.js +536 -0
  67. claude_mpm/dashboard/static/built/dashboard.js +1 -1
  68. claude_mpm/dashboard/static/built/extension-error-handler.js +164 -0
  69. claude_mpm/dashboard/static/built/react/events.js +30 -0
  70. claude_mpm/dashboard/static/built/shared/dom-helpers.js +396 -0
  71. claude_mpm/dashboard/static/built/shared/event-bus.js +330 -0
  72. claude_mpm/dashboard/static/built/shared/event-filter-service.js +540 -0
  73. claude_mpm/dashboard/static/built/shared/logger.js +385 -0
  74. claude_mpm/dashboard/static/built/shared/page-structure.js +251 -0
  75. claude_mpm/dashboard/static/built/shared/tooltip-service.js +253 -0
  76. claude_mpm/dashboard/static/built/socket-client.js +1 -1
  77. claude_mpm/dashboard/static/built/tab-isolation-fix.js +185 -0
  78. claude_mpm/dashboard/static/css/dashboard.css +28 -5
  79. claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +1 -0
  80. claude_mpm/dashboard/static/dist/components/activity-tree.js +1 -1
  81. claude_mpm/dashboard/static/dist/components/agent-inference.js +1 -1
  82. claude_mpm/dashboard/static/dist/components/code-viewer.js +2 -0
  83. claude_mpm/dashboard/static/dist/components/event-processor.js +1 -1
  84. claude_mpm/dashboard/static/dist/components/event-viewer.js +1 -1
  85. claude_mpm/dashboard/static/dist/components/export-manager.js +1 -1
  86. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +1 -1
  87. claude_mpm/dashboard/static/dist/components/module-viewer.js +1 -1
  88. claude_mpm/dashboard/static/dist/components/session-manager.js +1 -1
  89. claude_mpm/dashboard/static/dist/components/working-directory.js +1 -1
  90. claude_mpm/dashboard/static/dist/dashboard.js +1 -1
  91. claude_mpm/dashboard/static/dist/react/events.js +30 -0
  92. claude_mpm/dashboard/static/dist/socket-client.js +1 -1
  93. claude_mpm/dashboard/static/events.html +607 -0
  94. claude_mpm/dashboard/static/index.html +713 -0
  95. claude_mpm/dashboard/static/js/components/activity-tree.js +3 -17
  96. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +4 -1
  97. claude_mpm/dashboard/static/js/components/agent-inference.js +3 -0
  98. claude_mpm/dashboard/static/js/components/build-tracker.js +8 -0
  99. claude_mpm/dashboard/static/js/components/code-viewer.js +306 -66
  100. claude_mpm/dashboard/static/js/components/event-processor.js +3 -0
  101. claude_mpm/dashboard/static/js/components/event-viewer.js +39 -2
  102. claude_mpm/dashboard/static/js/components/export-manager.js +3 -0
  103. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +30 -10
  104. claude_mpm/dashboard/static/js/components/socket-manager.js +4 -0
  105. claude_mpm/dashboard/static/js/components/ui-state-manager.js +285 -85
  106. claude_mpm/dashboard/static/js/components/working-directory.js +3 -0
  107. claude_mpm/dashboard/static/js/dashboard.js +61 -33
  108. claude_mpm/dashboard/static/js/socket-client.js +12 -8
  109. claude_mpm/dashboard/static/js/stores/dashboard-store.js +562 -0
  110. claude_mpm/dashboard/static/js/tab-isolation-fix.js +185 -0
  111. claude_mpm/dashboard/static/legacy/activity.html +736 -0
  112. claude_mpm/dashboard/static/legacy/agents.html +786 -0
  113. claude_mpm/dashboard/static/legacy/files.html +747 -0
  114. claude_mpm/dashboard/static/legacy/tools.html +831 -0
  115. claude_mpm/dashboard/static/monitors-index.html +218 -0
  116. claude_mpm/dashboard/static/monitors.html +431 -0
  117. claude_mpm/dashboard/static/production/events.html +659 -0
  118. claude_mpm/dashboard/static/production/main.html +715 -0
  119. claude_mpm/dashboard/static/production/monitors.html +483 -0
  120. claude_mpm/dashboard/static/socket.io.min.js +7 -0
  121. claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +7 -0
  122. claude_mpm/dashboard/static/test-archive/dashboard.html +635 -0
  123. claude_mpm/dashboard/static/test-archive/debug-events.html +147 -0
  124. claude_mpm/dashboard/static/test-archive/test-navigation.html +256 -0
  125. claude_mpm/dashboard/static/test-archive/test-react-exports.html +180 -0
  126. claude_mpm/dashboard/templates/index.html +79 -9
  127. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +1 -1
  128. claude_mpm/services/agents/deployment/agent_discovery_service.py +3 -0
  129. claude_mpm/services/agents/deployment/agent_template_builder.py +25 -8
  130. claude_mpm/services/agents/deployment/agent_validator.py +3 -0
  131. claude_mpm/services/agents/deployment/validation/template_validator.py +13 -4
  132. claude_mpm/services/agents/local_template_manager.py +2 -6
  133. claude_mpm/services/monitor/daemon.py +1 -2
  134. claude_mpm/services/monitor/daemon_manager.py +2 -5
  135. claude_mpm/services/monitor/event_emitter.py +2 -2
  136. claude_mpm/services/monitor/handlers/code_analysis.py +4 -6
  137. claude_mpm/services/monitor/handlers/hooks.py +2 -4
  138. claude_mpm/services/monitor/server.py +27 -4
  139. claude_mpm/tools/code_tree_analyzer.py +2 -2
  140. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/METADATA +1 -1
  141. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/RECORD +146 -81
  142. claude_mpm/dashboard/static/test-browser-monitor.html +0 -470
  143. claude_mpm/dashboard/static/test-simple.html +0 -97
  144. /claude_mpm/dashboard/static/{test_debug.html → test-archive/test_debug.html} +0 -0
  145. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/WHEEL +0 -0
  146. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/entry_points.txt +0 -0
  147. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/licenses/LICENSE +0 -0
  148. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,409 @@
1
+ /**
2
+ * Tree Search Functionality
3
+ *
4
+ * Search and filter functionality for the code tree visualization.
5
+ * Provides searching, filtering, and highlighting capabilities.
6
+ *
7
+ * @module tree-search
8
+ */
9
+
10
+ class TreeSearch {
11
+ constructor() {
12
+ this.searchTerm = '';
13
+ this.languageFilter = 'all';
14
+ this.complexityFilter = { min: 0, max: 999 };
15
+ this.typeFilter = 'all';
16
+ this.searchHistory = [];
17
+ this.maxHistorySize = 20;
18
+ this.debounceTimer = null;
19
+ this.debounceDelay = 300;
20
+ }
21
+
22
+ /**
23
+ * Set search term with optional debouncing
24
+ * @param {string} term - Search term
25
+ * @param {Function} callback - Callback to execute after debounce
26
+ * @param {boolean} immediate - Execute immediately without debounce
27
+ */
28
+ setSearchTerm(term, callback, immediate = false) {
29
+ this.searchTerm = term.toLowerCase();
30
+
31
+ if (callback) {
32
+ if (immediate) {
33
+ callback(this.searchTerm);
34
+ } else {
35
+ this.debounce(() => callback(this.searchTerm), this.debounceDelay);
36
+ }
37
+ }
38
+
39
+ // Add to history if not empty and not duplicate
40
+ if (term && this.searchHistory[0] !== term) {
41
+ this.searchHistory.unshift(term);
42
+ if (this.searchHistory.length > this.maxHistorySize) {
43
+ this.searchHistory.pop();
44
+ }
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Set language filter
50
+ * @param {string} language - Language to filter by
51
+ */
52
+ setLanguageFilter(language) {
53
+ this.languageFilter = language;
54
+ }
55
+
56
+ /**
57
+ * Set complexity filter
58
+ * @param {number} min - Minimum complexity
59
+ * @param {number} max - Maximum complexity
60
+ */
61
+ setComplexityFilter(min, max) {
62
+ this.complexityFilter = { min, max };
63
+ }
64
+
65
+ /**
66
+ * Set type filter
67
+ * @param {string} type - Node type to filter by
68
+ */
69
+ setTypeFilter(type) {
70
+ this.typeFilter = type;
71
+ }
72
+
73
+ /**
74
+ * Filter tree nodes based on current criteria
75
+ * @param {Object} root - Root node of the tree
76
+ * @returns {Object} Filtered tree structure
77
+ */
78
+ filterTree(root) {
79
+ if (!root) return null;
80
+
81
+ // Mark all nodes as visible initially
82
+ this.resetNodeVisibility(root);
83
+
84
+ // Apply filters
85
+ root.descendants().forEach(node => {
86
+ const shouldHide = !this.nodeMatchesFilters(node);
87
+ node.data._hidden = shouldHide;
88
+
89
+ // Mark node for search highlighting
90
+ if (this.searchTerm && !shouldHide) {
91
+ node.data._highlighted = this.nodeMatchesSearch(node);
92
+ } else {
93
+ node.data._highlighted = false;
94
+ }
95
+ });
96
+
97
+ // Ensure parent nodes are visible if any child is visible
98
+ this.ensureParentVisibility(root);
99
+
100
+ return root;
101
+ }
102
+
103
+ /**
104
+ * Check if node matches all active filters
105
+ * @param {Object} node - Node to check
106
+ * @returns {boolean} True if node matches all filters
107
+ */
108
+ nodeMatchesFilters(node) {
109
+ // Language filter
110
+ if (!this.matchesLanguageFilter(node)) {
111
+ return false;
112
+ }
113
+
114
+ // Search term filter
115
+ if (!this.matchesSearchTerm(node)) {
116
+ return false;
117
+ }
118
+
119
+ // Complexity filter
120
+ if (!this.matchesComplexityFilter(node)) {
121
+ return false;
122
+ }
123
+
124
+ // Type filter
125
+ if (!this.matchesTypeFilter(node)) {
126
+ return false;
127
+ }
128
+
129
+ return true;
130
+ }
131
+
132
+ /**
133
+ * Check if node matches language filter
134
+ * @param {Object} node - Node to check
135
+ * @returns {boolean} True if matches
136
+ */
137
+ matchesLanguageFilter(node) {
138
+ if (this.languageFilter === 'all') {
139
+ return true;
140
+ }
141
+
142
+ // Check node language
143
+ if (node.data.language === this.languageFilter) {
144
+ return true;
145
+ }
146
+
147
+ // Check if any children match (for directories)
148
+ if (node.children || node._children) {
149
+ const children = node.children || node._children;
150
+ return children.some(child => this.matchesLanguageFilter(child));
151
+ }
152
+
153
+ return false;
154
+ }
155
+
156
+ /**
157
+ * Check if node matches search term
158
+ * @param {Object} node - Node to check
159
+ * @returns {boolean} True if matches
160
+ */
161
+ matchesSearchTerm(node) {
162
+ if (!this.searchTerm) {
163
+ return true;
164
+ }
165
+
166
+ // Check node name
167
+ if (node.data.name && node.data.name.toLowerCase().includes(this.searchTerm)) {
168
+ return true;
169
+ }
170
+
171
+ // Check node path
172
+ if (node.data.path && node.data.path.toLowerCase().includes(this.searchTerm)) {
173
+ return true;
174
+ }
175
+
176
+ // Check if any children match (for directories)
177
+ if (node.children || node._children) {
178
+ const children = node.children || node._children;
179
+ return children.some(child => this.matchesSearchTerm(child));
180
+ }
181
+
182
+ return false;
183
+ }
184
+
185
+ /**
186
+ * Check if node matches complexity filter
187
+ * @param {Object} node - Node to check
188
+ * @returns {boolean} True if matches
189
+ */
190
+ matchesComplexityFilter(node) {
191
+ if (node.data.complexity === undefined) {
192
+ return true; // No complexity data, show by default
193
+ }
194
+
195
+ return node.data.complexity >= this.complexityFilter.min &&
196
+ node.data.complexity <= this.complexityFilter.max;
197
+ }
198
+
199
+ /**
200
+ * Check if node matches type filter
201
+ * @param {Object} node - Node to check
202
+ * @returns {boolean} True if matches
203
+ */
204
+ matchesTypeFilter(node) {
205
+ if (this.typeFilter === 'all') {
206
+ return true;
207
+ }
208
+
209
+ return node.data.type === this.typeFilter;
210
+ }
211
+
212
+ /**
213
+ * Check if node matches search (for highlighting)
214
+ * @param {Object} node - Node to check
215
+ * @returns {boolean} True if node should be highlighted
216
+ */
217
+ nodeMatchesSearch(node) {
218
+ if (!this.searchTerm) {
219
+ return false;
220
+ }
221
+
222
+ const name = (node.data.name || '').toLowerCase();
223
+ return name.includes(this.searchTerm);
224
+ }
225
+
226
+ /**
227
+ * Reset visibility flags on all nodes
228
+ * @param {Object} root - Root node
229
+ */
230
+ resetNodeVisibility(root) {
231
+ if (!root) return;
232
+
233
+ root.descendants().forEach(node => {
234
+ node.data._hidden = false;
235
+ node.data._highlighted = false;
236
+ });
237
+ }
238
+
239
+ /**
240
+ * Ensure parent nodes are visible if any child is visible
241
+ * @param {Object} root - Root node
242
+ */
243
+ ensureParentVisibility(root) {
244
+ // Bottom-up traversal to ensure parents are visible
245
+ const checkVisibility = (node) => {
246
+ if (node.children) {
247
+ let hasVisibleChild = false;
248
+
249
+ node.children.forEach(child => {
250
+ checkVisibility(child);
251
+ if (!child.data._hidden) {
252
+ hasVisibleChild = true;
253
+ }
254
+ });
255
+
256
+ // If node has visible children, it must be visible too
257
+ if (hasVisibleChild && node.data._hidden) {
258
+ node.data._hidden = false;
259
+ }
260
+ }
261
+ };
262
+
263
+ checkVisibility(root);
264
+ }
265
+
266
+ /**
267
+ * Search for nodes by path pattern
268
+ * @param {Object} root - Root node
269
+ * @param {string} pattern - Path pattern (supports wildcards)
270
+ * @returns {Array} Matching nodes
271
+ */
272
+ searchByPath(root, pattern) {
273
+ if (!root || !pattern) return [];
274
+
275
+ const results = [];
276
+ const regexPattern = this.pathPatternToRegex(pattern);
277
+
278
+ root.descendants().forEach(node => {
279
+ if (node.data.path && regexPattern.test(node.data.path)) {
280
+ results.push(node);
281
+ }
282
+ });
283
+
284
+ return results;
285
+ }
286
+
287
+ /**
288
+ * Convert path pattern to regex
289
+ * @param {string} pattern - Path pattern with wildcards
290
+ * @returns {RegExp} Regular expression
291
+ */
292
+ pathPatternToRegex(pattern) {
293
+ // Escape special regex characters except * and ?
294
+ const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&');
295
+ // Replace wildcards
296
+ const regexStr = escaped
297
+ .replace(/\*/g, '.*') // * matches any characters
298
+ .replace(/\?/g, '.'); // ? matches single character
299
+
300
+ return new RegExp('^' + regexStr + '$', 'i');
301
+ }
302
+
303
+ /**
304
+ * Get search suggestions based on current tree
305
+ * @param {Object} root - Root node
306
+ * @param {string} prefix - Search prefix
307
+ * @returns {Array} Suggested search terms
308
+ */
309
+ getSearchSuggestions(root, prefix = '') {
310
+ if (!root) return [];
311
+
312
+ const suggestions = new Set();
313
+ const lowerPrefix = prefix.toLowerCase();
314
+
315
+ root.descendants().forEach(node => {
316
+ if (node.data.name) {
317
+ const name = node.data.name.toLowerCase();
318
+ if (name.startsWith(lowerPrefix)) {
319
+ suggestions.add(node.data.name);
320
+ }
321
+ }
322
+ });
323
+
324
+ return Array.from(suggestions).sort().slice(0, 10);
325
+ }
326
+
327
+ /**
328
+ * Highlight search results in node labels
329
+ * @param {string} text - Text to highlight
330
+ * @param {string} term - Search term
331
+ * @returns {string} HTML with highlighted term
332
+ */
333
+ highlightSearchTerm(text, term = null) {
334
+ const searchTerm = term || this.searchTerm;
335
+
336
+ if (!searchTerm || !text) {
337
+ return text;
338
+ }
339
+
340
+ const regex = new RegExp(`(${this.escapeRegex(searchTerm)})`, 'gi');
341
+ return text.replace(regex, '<mark>$1</mark>');
342
+ }
343
+
344
+ /**
345
+ * Clear all filters
346
+ */
347
+ clearFilters() {
348
+ this.searchTerm = '';
349
+ this.languageFilter = 'all';
350
+ this.complexityFilter = { min: 0, max: 999 };
351
+ this.typeFilter = 'all';
352
+ }
353
+
354
+ /**
355
+ * Get current filter summary
356
+ * @returns {string} Human-readable filter summary
357
+ */
358
+ getFilterSummary() {
359
+ const parts = [];
360
+
361
+ if (this.searchTerm) {
362
+ parts.push(`Search: "${this.searchTerm}"`);
363
+ }
364
+ if (this.languageFilter !== 'all') {
365
+ parts.push(`Language: ${this.languageFilter}`);
366
+ }
367
+ if (this.typeFilter !== 'all') {
368
+ parts.push(`Type: ${this.typeFilter}`);
369
+ }
370
+ if (this.complexityFilter.min > 0 || this.complexityFilter.max < 999) {
371
+ parts.push(`Complexity: ${this.complexityFilter.min}-${this.complexityFilter.max}`);
372
+ }
373
+
374
+ return parts.length > 0 ? parts.join(', ') : 'No filters applied';
375
+ }
376
+
377
+ /**
378
+ * Debounce function calls
379
+ * @private
380
+ * @param {Function} func - Function to debounce
381
+ * @param {number} delay - Delay in milliseconds
382
+ */
383
+ debounce(func, delay) {
384
+ clearTimeout(this.debounceTimer);
385
+ this.debounceTimer = setTimeout(func, delay);
386
+ }
387
+
388
+ /**
389
+ * Escape regex special characters
390
+ * @private
391
+ * @param {string} str - String to escape
392
+ * @returns {string} Escaped string
393
+ */
394
+ escapeRegex(str) {
395
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
396
+ }
397
+ }
398
+
399
+ // Export as singleton for consistent state
400
+ const treeSearch = new TreeSearch();
401
+
402
+ // Support both module and global usage
403
+ if (typeof module !== 'undefined' && module.exports) {
404
+ module.exports = treeSearch;
405
+ } else if (typeof define === 'function' && define.amd) {
406
+ define([], () => treeSearch);
407
+ } else {
408
+ window.treeSearch = treeSearch;
409
+ }