claude-mpm 4.1.13__py3-none-any.whl → 4.1.14__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/dashboard/static/css/activity.css +3 -3
- claude_mpm/dashboard/static/css/code-tree.css +235 -2
- claude_mpm/dashboard/static/js/components/code-tree.js +535 -241
- {claude_mpm-4.1.13.dist-info → claude_mpm-4.1.14.dist-info}/METADATA +1 -1
- {claude_mpm-4.1.13.dist-info → claude_mpm-4.1.14.dist-info}/RECORD +10 -10
- {claude_mpm-4.1.13.dist-info → claude_mpm-4.1.14.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.13.dist-info → claude_mpm-4.1.14.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.1.13.dist-info → claude_mpm-4.1.14.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.13.dist-info → claude_mpm-4.1.14.dist-info}/top_level.txt +0 -0
claude_mpm/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.1.
|
|
1
|
+
4.1.14
|
|
@@ -664,13 +664,13 @@ body .activity-tree-container .linear-tree .tree-node.tool.privileged-tool .tree
|
|
|
664
664
|
color: #95A5A6;
|
|
665
665
|
}
|
|
666
666
|
|
|
667
|
-
/* Search Highlighting -
|
|
668
|
-
.tree-node.search-match:not(.tool) {
|
|
667
|
+
/* Search Highlighting - Specific to activity tree only */
|
|
668
|
+
.activity-tree-container .tree-node.search-match:not(.tool) {
|
|
669
669
|
background: #fff3cd !important;
|
|
670
670
|
border-left-color: #ffc107 !important;
|
|
671
671
|
}
|
|
672
672
|
|
|
673
|
-
.tree-node.search-match:not(.tool) .tree-label {
|
|
673
|
+
.activity-tree-container .tree-node.search-match:not(.tool) .tree-label {
|
|
674
674
|
background: #ffecb5;
|
|
675
675
|
padding: 2px 4px;
|
|
676
676
|
border-radius: 3px;
|
|
@@ -461,6 +461,13 @@
|
|
|
461
461
|
position: relative;
|
|
462
462
|
overflow: auto;
|
|
463
463
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
464
|
+
border-left: 1px solid #e2e8f0;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/* Visual hierarchy improvements */
|
|
468
|
+
.code-tree-container:focus-within {
|
|
469
|
+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
|
470
|
+
border-left-color: #3b82f6;
|
|
464
471
|
}
|
|
465
472
|
|
|
466
473
|
/* Loading indicator */
|
|
@@ -710,6 +717,78 @@
|
|
|
710
717
|
filter: brightness(1.1);
|
|
711
718
|
}
|
|
712
719
|
|
|
720
|
+
/* Directory node styling - make expandable directories obvious */
|
|
721
|
+
.code-node.directory circle {
|
|
722
|
+
fill: #f8fafc;
|
|
723
|
+
stroke: #3b82f6;
|
|
724
|
+
stroke-width: 2px;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
.code-node.directory:hover circle {
|
|
728
|
+
fill: #eef2ff;
|
|
729
|
+
stroke: #2563eb;
|
|
730
|
+
stroke-width: 3px;
|
|
731
|
+
filter: drop-shadow(0 2px 4px rgba(59, 130, 246, 0.3));
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
/* Expanded directory styling */
|
|
735
|
+
.code-node.directory.expanded circle {
|
|
736
|
+
fill: #dbeafe;
|
|
737
|
+
stroke: #1d4ed8;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
/* File node styling */
|
|
741
|
+
.code-node.file circle {
|
|
742
|
+
fill: #f9fafb;
|
|
743
|
+
stroke: #6b7280;
|
|
744
|
+
stroke-width: 1.5px;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
.code-node.file:hover circle {
|
|
748
|
+
fill: #f3f4f6;
|
|
749
|
+
stroke: #4b5563;
|
|
750
|
+
stroke-width: 2px;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/* Empty directory styling */
|
|
754
|
+
.code-node.directory.empty circle {
|
|
755
|
+
fill: #f9fafb;
|
|
756
|
+
stroke: #9ca3af;
|
|
757
|
+
stroke-dasharray: 3,3;
|
|
758
|
+
opacity: 0.7;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
/* Directory expand/collapse icons */
|
|
762
|
+
.expand-icon {
|
|
763
|
+
font-family: monospace;
|
|
764
|
+
font-size: 12px;
|
|
765
|
+
font-weight: bold;
|
|
766
|
+
text-anchor: middle;
|
|
767
|
+
dominant-baseline: central;
|
|
768
|
+
fill: #374151;
|
|
769
|
+
pointer-events: none;
|
|
770
|
+
transition: all 0.2s ease;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
.code-node.directory .expand-icon {
|
|
774
|
+
fill: #3b82f6;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
.code-node.directory.expanded .expand-icon {
|
|
778
|
+
fill: #1d4ed8;
|
|
779
|
+
transform: rotate(90deg);
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
.code-node.directory.loading .expand-icon {
|
|
783
|
+
fill: #f59e0b;
|
|
784
|
+
animation: spin 1s linear infinite;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
@keyframes spin {
|
|
788
|
+
from { transform: rotate(0deg); }
|
|
789
|
+
to { transform: rotate(360deg); }
|
|
790
|
+
}
|
|
791
|
+
|
|
713
792
|
/* Visualization Controls */
|
|
714
793
|
.viz-controls {
|
|
715
794
|
position: absolute;
|
|
@@ -802,6 +881,31 @@
|
|
|
802
881
|
fill: #ec4899;
|
|
803
882
|
}
|
|
804
883
|
|
|
884
|
+
/* Search match highlighting */
|
|
885
|
+
.code-node.search-match circle {
|
|
886
|
+
stroke: #fbbf24 !important;
|
|
887
|
+
stroke-width: 3px;
|
|
888
|
+
fill: #fef3c7 !important;
|
|
889
|
+
filter: drop-shadow(0 0 8px rgba(251, 191, 36, 0.6));
|
|
890
|
+
animation: searchPulse 2s ease-in-out infinite;
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
.code-node.search-match text {
|
|
894
|
+
font-weight: bold;
|
|
895
|
+
fill: #92400e;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
@keyframes searchPulse {
|
|
899
|
+
0%, 100% {
|
|
900
|
+
stroke-width: 3px;
|
|
901
|
+
opacity: 1;
|
|
902
|
+
}
|
|
903
|
+
50% {
|
|
904
|
+
stroke-width: 4px;
|
|
905
|
+
opacity: 0.8;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
|
|
805
909
|
/* Collapsed node indicator */
|
|
806
910
|
.code-node.collapsed circle {
|
|
807
911
|
fill: #e2e8f0 !important;
|
|
@@ -851,6 +955,31 @@
|
|
|
851
955
|
fill: #fef3c7 !important;
|
|
852
956
|
}
|
|
853
957
|
|
|
958
|
+
/* Enhanced loading states */
|
|
959
|
+
.code-node.loading circle {
|
|
960
|
+
stroke: #f59e0b !important;
|
|
961
|
+
fill: #fef3c7 !important;
|
|
962
|
+
animation: nodePulse 1.5s ease-in-out infinite;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
.code-node.loading text {
|
|
966
|
+
fill: #92400e;
|
|
967
|
+
font-weight: 600;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
/* Directory item count badge */
|
|
971
|
+
.item-count-badge {
|
|
972
|
+
font-size: 10px;
|
|
973
|
+
fill: #6b7280;
|
|
974
|
+
text-anchor: middle;
|
|
975
|
+
dominant-baseline: central;
|
|
976
|
+
font-weight: 500;
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
.code-node.directory:hover .item-count-badge {
|
|
980
|
+
fill: #374151;
|
|
981
|
+
}
|
|
982
|
+
|
|
854
983
|
/* Tooltips */
|
|
855
984
|
.code-tooltip {
|
|
856
985
|
position: absolute;
|
|
@@ -864,11 +993,115 @@
|
|
|
864
993
|
z-index: 1000;
|
|
865
994
|
}
|
|
866
995
|
|
|
996
|
+
/* Tree control toolbar */
|
|
997
|
+
.tree-controls-toolbar {
|
|
998
|
+
position: absolute;
|
|
999
|
+
top: 15px;
|
|
1000
|
+
right: 15px;
|
|
1001
|
+
display: flex;
|
|
1002
|
+
gap: 8px;
|
|
1003
|
+
z-index: 100;
|
|
1004
|
+
background: rgba(255, 255, 255, 0.95);
|
|
1005
|
+
backdrop-filter: blur(4px);
|
|
1006
|
+
border: 1px solid #e5e7eb;
|
|
1007
|
+
border-radius: 8px;
|
|
1008
|
+
padding: 6px;
|
|
1009
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
.tree-control-btn {
|
|
1013
|
+
padding: 6px 10px;
|
|
1014
|
+
font-size: 12px;
|
|
1015
|
+
font-weight: 500;
|
|
1016
|
+
border: 1px solid #d1d5db;
|
|
1017
|
+
background: white;
|
|
1018
|
+
color: #374151;
|
|
1019
|
+
border-radius: 4px;
|
|
1020
|
+
cursor: pointer;
|
|
1021
|
+
transition: all 0.2s ease;
|
|
1022
|
+
display: flex;
|
|
1023
|
+
align-items: center;
|
|
1024
|
+
gap: 4px;
|
|
1025
|
+
min-width: 32px;
|
|
1026
|
+
justify-content: center;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
.tree-control-btn:hover {
|
|
1030
|
+
background: #f3f4f6;
|
|
1031
|
+
border-color: #9ca3af;
|
|
1032
|
+
transform: translateY(-1px);
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
.tree-control-btn:active {
|
|
1036
|
+
transform: translateY(0);
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
.tree-control-btn.active {
|
|
1040
|
+
background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
|
|
1041
|
+
color: white;
|
|
1042
|
+
border-color: #2563eb;
|
|
1043
|
+
box-shadow: 0 2px 4px rgba(59, 130, 246, 0.3);
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
.tree-control-btn:disabled {
|
|
1047
|
+
opacity: 0.5;
|
|
1048
|
+
cursor: not-allowed;
|
|
1049
|
+
transform: none;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
/* Breadcrumb navigation */
|
|
1053
|
+
.tree-breadcrumb {
|
|
1054
|
+
position: absolute;
|
|
1055
|
+
top: 15px;
|
|
1056
|
+
left: 15px;
|
|
1057
|
+
background: rgba(255, 255, 255, 0.95);
|
|
1058
|
+
backdrop-filter: blur(4px);
|
|
1059
|
+
border: 1px solid #e5e7eb;
|
|
1060
|
+
border-radius: 8px;
|
|
1061
|
+
padding: 6px 12px;
|
|
1062
|
+
font-size: 12px;
|
|
1063
|
+
color: #4b5563;
|
|
1064
|
+
font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
|
|
1065
|
+
max-width: 400px;
|
|
1066
|
+
z-index: 100;
|
|
1067
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
.breadcrumb-path {
|
|
1071
|
+
display: flex;
|
|
1072
|
+
align-items: center;
|
|
1073
|
+
gap: 4px;
|
|
1074
|
+
font-weight: 500;
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
.breadcrumb-separator {
|
|
1078
|
+
color: #9ca3af;
|
|
1079
|
+
margin: 0 2px;
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
.breadcrumb-segment {
|
|
1083
|
+
color: #374151;
|
|
1084
|
+
cursor: pointer;
|
|
1085
|
+
padding: 2px 4px;
|
|
1086
|
+
border-radius: 3px;
|
|
1087
|
+
transition: background 0.2s ease;
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
.breadcrumb-segment:hover {
|
|
1091
|
+
background: rgba(59, 130, 246, 0.1);
|
|
1092
|
+
color: #3b82f6;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
.breadcrumb-segment.current {
|
|
1096
|
+
color: #3b82f6;
|
|
1097
|
+
font-weight: 600;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
867
1100
|
/* Code tree notifications */
|
|
868
1101
|
.code-tree-notification {
|
|
869
1102
|
position: absolute;
|
|
870
|
-
top:
|
|
871
|
-
right:
|
|
1103
|
+
top: 70px;
|
|
1104
|
+
right: 15px;
|
|
872
1105
|
padding: 12px 20px;
|
|
873
1106
|
border-radius: 6px;
|
|
874
1107
|
background: white;
|
|
@@ -4,6 +4,15 @@
|
|
|
4
4
|
* D3.js-based tree visualization for displaying AST-based code structure.
|
|
5
5
|
* Shows modules, classes, functions, and methods with complexity-based coloring.
|
|
6
6
|
* Provides real-time updates during code analysis.
|
|
7
|
+
*
|
|
8
|
+
* ===== CACHE CLEAR INSTRUCTIONS =====
|
|
9
|
+
* If tree still moves/centers after update:
|
|
10
|
+
* 1. Hard refresh: Ctrl+Shift+R (Windows/Linux) or Cmd+Shift+R (Mac)
|
|
11
|
+
* 2. Or open DevTools (F12) → Network tab → Check "Disable cache"
|
|
12
|
+
* 3. Or clear browser cache: Ctrl+Shift+Delete → Clear cached images and files
|
|
13
|
+
*
|
|
14
|
+
* Version: 2025-08-29T15:30:00Z - ALL CENTERING REMOVED
|
|
15
|
+
* Last Update: Completely disabled tree centering/movement on node clicks
|
|
7
16
|
*/
|
|
8
17
|
|
|
9
18
|
class CodeTree {
|
|
@@ -41,6 +50,8 @@ class CodeTree {
|
|
|
41
50
|
this.zoom = null; // Store zoom behavior
|
|
42
51
|
this.activeNode = null; // Track currently active node
|
|
43
52
|
this.loadingNodes = new Set(); // Track nodes that are loading
|
|
53
|
+
this.bulkLoadMode = false; // Track bulk loading preference
|
|
54
|
+
this.expandedPaths = new Set(); // Track which paths are expanded
|
|
44
55
|
}
|
|
45
56
|
|
|
46
57
|
/**
|
|
@@ -280,6 +291,12 @@ class CodeTree {
|
|
|
280
291
|
|
|
281
292
|
const container = d3.select('#code-tree-container');
|
|
282
293
|
container.selectAll('*').remove();
|
|
294
|
+
|
|
295
|
+
// Add tree controls toolbar
|
|
296
|
+
this.addTreeControls();
|
|
297
|
+
|
|
298
|
+
// Add breadcrumb navigation
|
|
299
|
+
this.addBreadcrumb();
|
|
283
300
|
|
|
284
301
|
if (!container || !container.node()) {
|
|
285
302
|
console.error('Code tree container not found');
|
|
@@ -353,22 +370,14 @@ class CodeTree {
|
|
|
353
370
|
});
|
|
354
371
|
}
|
|
355
372
|
|
|
356
|
-
//
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
} else {
|
|
365
|
-
// Linear: maintain left margin
|
|
366
|
-
this.treeGroup.attr('transform',
|
|
367
|
-
`translate(${this.margin.left + 100 + event.transform.x},${centerY + event.transform.y}) scale(${event.transform.k})`);
|
|
368
|
-
}
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
this.svg.call(this.zoom);
|
|
373
|
+
// DISABLED: All zoom behavior has been completely disabled to prevent tree movement
|
|
374
|
+
// The tree should remain completely stationary - no zooming, panning, or centering allowed
|
|
375
|
+
this.zoom = null; // Completely disable zoom behavior
|
|
376
|
+
|
|
377
|
+
// Do NOT apply zoom behavior to SVG - this prevents all zoom/pan interactions
|
|
378
|
+
// this.svg.call(this.zoom); // DISABLED
|
|
379
|
+
|
|
380
|
+
console.log('[CodeTree] All zoom and pan behavior disabled - tree is now completely stationary');
|
|
372
381
|
|
|
373
382
|
// Add controls overlay
|
|
374
383
|
this.addVisualizationControls();
|
|
@@ -560,10 +569,285 @@ class CodeTree {
|
|
|
560
569
|
if (this.socket) {
|
|
561
570
|
this.socket.emit('code:analysis:cancel');
|
|
562
571
|
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Add tree control toolbar with expand/collapse and other controls
|
|
576
|
+
*/
|
|
577
|
+
addTreeControls() {
|
|
578
|
+
const container = d3.select('#code-tree-container');
|
|
579
|
+
|
|
580
|
+
// Remove any existing controls
|
|
581
|
+
container.select('.tree-controls-toolbar').remove();
|
|
582
|
+
|
|
583
|
+
const toolbar = container.append('div')
|
|
584
|
+
.attr('class', 'tree-controls-toolbar');
|
|
585
|
+
|
|
586
|
+
// Expand All button
|
|
587
|
+
toolbar.append('button')
|
|
588
|
+
.attr('class', 'tree-control-btn')
|
|
589
|
+
.attr('title', 'Expand all loaded directories')
|
|
590
|
+
.text('⊞')
|
|
591
|
+
.on('click', () => this.expandAll());
|
|
592
|
+
|
|
593
|
+
// Collapse All button
|
|
594
|
+
toolbar.append('button')
|
|
595
|
+
.attr('class', 'tree-control-btn')
|
|
596
|
+
.attr('title', 'Collapse all directories')
|
|
597
|
+
.text('⊟')
|
|
598
|
+
.on('click', () => this.collapseAll());
|
|
599
|
+
|
|
600
|
+
// Bulk Load Toggle
|
|
601
|
+
toolbar.append('button')
|
|
602
|
+
.attr('class', 'tree-control-btn')
|
|
603
|
+
.attr('id', 'bulk-load-toggle')
|
|
604
|
+
.attr('title', 'Toggle bulk loading (load 2 levels at once)')
|
|
605
|
+
.text('↕')
|
|
606
|
+
.on('click', () => this.toggleBulkLoad());
|
|
607
|
+
|
|
608
|
+
// Layout Toggle
|
|
609
|
+
toolbar.append('button')
|
|
610
|
+
.attr('class', 'tree-control-btn')
|
|
611
|
+
.attr('title', 'Toggle between radial and linear layouts')
|
|
612
|
+
.text('◎')
|
|
613
|
+
.on('click', () => this.toggleLayout());
|
|
614
|
+
|
|
615
|
+
// Path Search
|
|
616
|
+
const searchInput = toolbar.append('input')
|
|
617
|
+
.attr('class', 'tree-control-btn')
|
|
618
|
+
.attr('type', 'text')
|
|
619
|
+
.attr('placeholder', 'Search...')
|
|
620
|
+
.attr('title', 'Search for files and directories')
|
|
621
|
+
.style('width', '120px')
|
|
622
|
+
.style('text-align', 'left')
|
|
623
|
+
.on('input', (event) => this.searchTree(event.target.value))
|
|
624
|
+
.on('keydown', (event) => {
|
|
625
|
+
if (event.key === 'Escape') {
|
|
626
|
+
event.target.value = '';
|
|
627
|
+
this.searchTree('');
|
|
628
|
+
}
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Add breadcrumb navigation
|
|
634
|
+
*/
|
|
635
|
+
addBreadcrumb() {
|
|
636
|
+
const container = d3.select('#code-tree-container');
|
|
637
|
+
|
|
638
|
+
// Remove any existing breadcrumb
|
|
639
|
+
container.select('.tree-breadcrumb').remove();
|
|
640
|
+
|
|
641
|
+
const breadcrumb = container.append('div')
|
|
642
|
+
.attr('class', 'tree-breadcrumb');
|
|
643
|
+
|
|
644
|
+
const pathDiv = breadcrumb.append('div')
|
|
645
|
+
.attr('class', 'breadcrumb-path')
|
|
646
|
+
.attr('id', 'tree-breadcrumb-path');
|
|
647
|
+
|
|
648
|
+
// Initialize with working directory
|
|
649
|
+
this.updateBreadcrumbPath('/');
|
|
650
|
+
}
|
|
563
651
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
652
|
+
/**
|
|
653
|
+
* Update breadcrumb path based on current navigation
|
|
654
|
+
*/
|
|
655
|
+
updateBreadcrumbPath(currentPath) {
|
|
656
|
+
const pathDiv = d3.select('#tree-breadcrumb-path');
|
|
657
|
+
pathDiv.selectAll('*').remove();
|
|
658
|
+
|
|
659
|
+
const workingDir = this.getWorkingDirectory();
|
|
660
|
+
if (!workingDir || workingDir === 'Loading...' || workingDir === 'Not selected') {
|
|
661
|
+
pathDiv.text('No project selected');
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// Build path segments
|
|
666
|
+
const segments = currentPath === '/' ?
|
|
667
|
+
[workingDir.split('/').pop() || 'Root'] :
|
|
668
|
+
currentPath.split('/').filter(s => s.length > 0);
|
|
669
|
+
|
|
670
|
+
segments.forEach((segment, index) => {
|
|
671
|
+
if (index > 0) {
|
|
672
|
+
pathDiv.append('span')
|
|
673
|
+
.attr('class', 'breadcrumb-separator')
|
|
674
|
+
.text('/');
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
pathDiv.append('span')
|
|
678
|
+
.attr('class', index === segments.length - 1 ? 'breadcrumb-segment current' : 'breadcrumb-segment')
|
|
679
|
+
.text(segment)
|
|
680
|
+
.on('click', () => {
|
|
681
|
+
if (index < segments.length - 1) {
|
|
682
|
+
// Navigate to parent path
|
|
683
|
+
const parentPath = segments.slice(0, index + 1).join('/');
|
|
684
|
+
this.navigateToPath(parentPath);
|
|
685
|
+
}
|
|
686
|
+
});
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* Expand all currently loaded directories
|
|
692
|
+
*/
|
|
693
|
+
expandAll() {
|
|
694
|
+
if (!this.root) return;
|
|
695
|
+
|
|
696
|
+
const expandNode = (node) => {
|
|
697
|
+
if (node.data.type === 'directory' && node.data.loaded === true) {
|
|
698
|
+
if (node._children) {
|
|
699
|
+
node.children = node._children;
|
|
700
|
+
node._children = null;
|
|
701
|
+
node.data.expanded = true;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
if (node.children) {
|
|
705
|
+
node.children.forEach(expandNode);
|
|
706
|
+
}
|
|
707
|
+
};
|
|
708
|
+
|
|
709
|
+
expandNode(this.root);
|
|
710
|
+
this.update(this.root);
|
|
711
|
+
this.showNotification('Expanded all loaded directories', 'success');
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
/**
|
|
715
|
+
* Collapse all directories to root level
|
|
716
|
+
*/
|
|
717
|
+
collapseAll() {
|
|
718
|
+
if (!this.root) return;
|
|
719
|
+
|
|
720
|
+
const collapseNode = (node) => {
|
|
721
|
+
if (node.data.type === 'directory' && node.children) {
|
|
722
|
+
node._children = node.children;
|
|
723
|
+
node.children = null;
|
|
724
|
+
node.data.expanded = false;
|
|
725
|
+
}
|
|
726
|
+
if (node._children) {
|
|
727
|
+
node._children.forEach(collapseNode);
|
|
728
|
+
}
|
|
729
|
+
};
|
|
730
|
+
|
|
731
|
+
collapseNode(this.root);
|
|
732
|
+
this.update(this.root);
|
|
733
|
+
this.showNotification('Collapsed all directories', 'info');
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Toggle bulk loading mode
|
|
738
|
+
*/
|
|
739
|
+
toggleBulkLoad() {
|
|
740
|
+
this.bulkLoadMode = !this.bulkLoadMode;
|
|
741
|
+
const button = d3.select('#bulk-load-toggle');
|
|
742
|
+
|
|
743
|
+
if (this.bulkLoadMode) {
|
|
744
|
+
button.classed('active', true);
|
|
745
|
+
this.showNotification('Bulk load enabled - will load 2 levels deep', 'info');
|
|
746
|
+
} else {
|
|
747
|
+
button.classed('active', false);
|
|
748
|
+
this.showNotification('Bulk load disabled - load 1 level at a time', 'info');
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
/**
|
|
753
|
+
* Navigate to a specific path in the tree
|
|
754
|
+
*/
|
|
755
|
+
navigateToPath(path) {
|
|
756
|
+
// Implementation for navigating to a specific path
|
|
757
|
+
// This would expand the tree to show the specified path
|
|
758
|
+
this.updateBreadcrumbPath(path);
|
|
759
|
+
this.showNotification(`Navigating to: ${path}`, 'info');
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* Search the tree for matching files/directories
|
|
764
|
+
*/
|
|
765
|
+
searchTree(query) {
|
|
766
|
+
if (!this.root || !this.treeGroup) return;
|
|
767
|
+
|
|
768
|
+
const searchTerm = query.toLowerCase().trim();
|
|
769
|
+
|
|
770
|
+
// Clear previous search highlights
|
|
771
|
+
this.treeGroup.selectAll('.code-node')
|
|
772
|
+
.classed('search-match', false);
|
|
773
|
+
|
|
774
|
+
if (!searchTerm) {
|
|
775
|
+
return; // No search term, just clear highlights
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
// Find matching nodes
|
|
779
|
+
const matchingNodes = [];
|
|
780
|
+
const searchNode = (node) => {
|
|
781
|
+
const name = (node.data.name || '').toLowerCase();
|
|
782
|
+
const path = (node.data.path || '').toLowerCase();
|
|
783
|
+
|
|
784
|
+
if (name.includes(searchTerm) || path.includes(searchTerm)) {
|
|
785
|
+
matchingNodes.push(node);
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
if (node.children) {
|
|
789
|
+
node.children.forEach(searchNode);
|
|
790
|
+
}
|
|
791
|
+
if (node._children) {
|
|
792
|
+
node._children.forEach(searchNode);
|
|
793
|
+
}
|
|
794
|
+
};
|
|
795
|
+
|
|
796
|
+
searchNode(this.root);
|
|
797
|
+
|
|
798
|
+
// Highlight matching nodes
|
|
799
|
+
if (matchingNodes.length > 0) {
|
|
800
|
+
// Get all current nodes in the tree
|
|
801
|
+
const allNodes = this.treeGroup.selectAll('.code-node').data();
|
|
802
|
+
|
|
803
|
+
matchingNodes.forEach(matchNode => {
|
|
804
|
+
// Find the corresponding DOM node
|
|
805
|
+
const domNode = this.treeGroup.selectAll('.code-node')
|
|
806
|
+
.filter(d => d.data.path === matchNode.data.path);
|
|
807
|
+
domNode.classed('search-match', true);
|
|
808
|
+
|
|
809
|
+
// Expand parent path to show the match
|
|
810
|
+
this.expandPathToNode(matchNode);
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
this.showNotification(`Found ${matchingNodes.length} matches`, 'success');
|
|
814
|
+
|
|
815
|
+
// Auto-center on first match if in radial layout - REMOVED
|
|
816
|
+
// Centering functionality has been disabled to prevent unwanted repositioning
|
|
817
|
+
// if (matchingNodes.length > 0 && this.isRadialLayout) {
|
|
818
|
+
// this.centerOnNode ? this.centerOnNode(matchingNodes[0]) : this.centerOnNodeRadial(matchingNodes[0]);
|
|
819
|
+
// }
|
|
820
|
+
} else {
|
|
821
|
+
this.showNotification('No matches found', 'info');
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
/**
|
|
826
|
+
* Expand the tree path to show a specific node
|
|
827
|
+
*/
|
|
828
|
+
expandPathToNode(targetNode) {
|
|
829
|
+
const pathToExpand = [];
|
|
830
|
+
let current = targetNode.parent;
|
|
831
|
+
|
|
832
|
+
// Build path from node to root
|
|
833
|
+
while (current && current !== this.root) {
|
|
834
|
+
pathToExpand.unshift(current);
|
|
835
|
+
current = current.parent;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
// Expand each node in the path
|
|
839
|
+
pathToExpand.forEach(node => {
|
|
840
|
+
if (node.data.type === 'directory' && node._children) {
|
|
841
|
+
node.children = node._children;
|
|
842
|
+
node._children = null;
|
|
843
|
+
node.data.expanded = true;
|
|
844
|
+
}
|
|
845
|
+
});
|
|
846
|
+
|
|
847
|
+
// Update the visualization if we expanded anything
|
|
848
|
+
if (pathToExpand.length > 0) {
|
|
849
|
+
this.update(this.root);
|
|
850
|
+
}
|
|
567
851
|
}
|
|
568
852
|
|
|
569
853
|
/**
|
|
@@ -660,6 +944,8 @@ class CodeTree {
|
|
|
660
944
|
const d3Node = this.findD3NodeByPath(searchPath);
|
|
661
945
|
if (d3Node && this.loadingNodes.has(searchPath)) {
|
|
662
946
|
this.removeLoadingPulse(d3Node);
|
|
947
|
+
this.loadingNodes.delete(searchPath); // Remove from loading set
|
|
948
|
+
console.log('🎯 [SUBDIRECTORY LOADING] Successfully completed and removed from loading set:', searchPath);
|
|
663
949
|
}
|
|
664
950
|
node.children = data.children.map(child => {
|
|
665
951
|
// Construct full path for child by combining parent path with child name
|
|
@@ -884,12 +1170,13 @@ class CodeTree {
|
|
|
884
1170
|
// Add to events display
|
|
885
1171
|
this.addEventToDisplay(`📁 Found ${(data.children || []).length} items in: ${data.name || data.path}`, 'info');
|
|
886
1172
|
|
|
887
|
-
console.log('
|
|
1173
|
+
console.log('✅ [SUBDIRECTORY LOADING] Received directory discovery response:', {
|
|
888
1174
|
path: data.path,
|
|
889
1175
|
name: data.name,
|
|
890
1176
|
childrenCount: (data.children || []).length,
|
|
891
1177
|
children: (data.children || []).map(c => ({ name: c.name, type: c.type })),
|
|
892
|
-
workingDir: this.getWorkingDirectory()
|
|
1178
|
+
workingDir: this.getWorkingDirectory(),
|
|
1179
|
+
fullEventData: data
|
|
893
1180
|
});
|
|
894
1181
|
|
|
895
1182
|
// Convert absolute path back to relative path to match tree nodes
|
|
@@ -948,6 +1235,8 @@ class CodeTree {
|
|
|
948
1235
|
// Remove loading animation
|
|
949
1236
|
if (this.loadingNodes.has(searchPath)) {
|
|
950
1237
|
this.removeLoadingPulse(d3Node);
|
|
1238
|
+
this.loadingNodes.delete(searchPath); // Remove from loading set
|
|
1239
|
+
console.log('🎯 [SUBDIRECTORY LOADING] Successfully completed and removed from loading set (hierarchy update):', searchPath);
|
|
951
1240
|
}
|
|
952
1241
|
}
|
|
953
1242
|
|
|
@@ -979,11 +1268,32 @@ class CodeTree {
|
|
|
979
1268
|
this.update(this.root);
|
|
980
1269
|
}
|
|
981
1270
|
|
|
982
|
-
|
|
1271
|
+
// Provide better feedback for empty vs populated directories
|
|
1272
|
+
if (node.children.length === 0) {
|
|
1273
|
+
this.updateBreadcrumb(`Empty directory: ${node.name}`, 'info');
|
|
1274
|
+
this.showNotification(`Directory "${node.name}" is empty`, 'info');
|
|
1275
|
+
} else {
|
|
1276
|
+
this.updateBreadcrumb(`Loaded ${node.children.length} items from ${node.name}`, 'success');
|
|
1277
|
+
this.showNotification(`Loaded ${node.children.length} items from "${node.name}"`, 'success');
|
|
1278
|
+
}
|
|
983
1279
|
this.updateStats();
|
|
984
1280
|
} else if (!node) {
|
|
1281
|
+
console.error('❌ [SUBDIRECTORY LOADING] Node not found for path:', {
|
|
1282
|
+
searchPath,
|
|
1283
|
+
originalPath: data.path,
|
|
1284
|
+
workingDir: this.getWorkingDirectory(),
|
|
1285
|
+
allTreePaths: this.getAllTreePaths(this.treeData)
|
|
1286
|
+
});
|
|
1287
|
+
this.showNotification(`Could not find directory "${searchPath}" in tree`, 'error');
|
|
985
1288
|
this.logAllPaths(this.treeData);
|
|
986
1289
|
} else if (node && !data.children) {
|
|
1290
|
+
console.warn('⚠️ [SUBDIRECTORY LOADING] Directory response has no children:', {
|
|
1291
|
+
path: data.path,
|
|
1292
|
+
searchPath,
|
|
1293
|
+
nodeExists: !!node,
|
|
1294
|
+
dataKeys: Object.keys(data),
|
|
1295
|
+
fullData: data
|
|
1296
|
+
});
|
|
987
1297
|
// This might be a top-level directory discovery
|
|
988
1298
|
const pathParts = data.path ? data.path.split('/').filter(p => p) : [];
|
|
989
1299
|
const isTopLevel = pathParts.length === 1;
|
|
@@ -1044,6 +1354,7 @@ class CodeTree {
|
|
|
1044
1354
|
const d3Node = this.findD3NodeByPath(data.path);
|
|
1045
1355
|
if (d3Node && this.loadingNodes.has(data.path)) {
|
|
1046
1356
|
this.removeLoadingPulse(d3Node);
|
|
1357
|
+
this.loadingNodes.delete(data.path); // Remove from loading set
|
|
1047
1358
|
}
|
|
1048
1359
|
// Update activity ticker
|
|
1049
1360
|
if (data.path) {
|
|
@@ -1448,11 +1759,11 @@ class CodeTree {
|
|
|
1448
1759
|
findNodeByPath(path, node = null) {
|
|
1449
1760
|
if (!node) {
|
|
1450
1761
|
node = this.treeData;
|
|
1451
|
-
|
|
1452
|
-
// Root node identified
|
|
1762
|
+
console.log('🔍 [SUBDIRECTORY LOADING] Starting search for path:', path);
|
|
1453
1763
|
}
|
|
1454
1764
|
|
|
1455
1765
|
if (node.path === path) {
|
|
1766
|
+
console.log('✅ [SUBDIRECTORY LOADING] Found node for path:', path);
|
|
1456
1767
|
return node;
|
|
1457
1768
|
}
|
|
1458
1769
|
|
|
@@ -1465,8 +1776,8 @@ class CodeTree {
|
|
|
1465
1776
|
}
|
|
1466
1777
|
}
|
|
1467
1778
|
|
|
1468
|
-
if (!node.parent) {
|
|
1469
|
-
|
|
1779
|
+
if (!node.parent && node === this.treeData) {
|
|
1780
|
+
console.warn('❌ [SUBDIRECTORY LOADING] Path not found in tree:', path);
|
|
1470
1781
|
}
|
|
1471
1782
|
return null;
|
|
1472
1783
|
}
|
|
@@ -1483,6 +1794,19 @@ class CodeTree {
|
|
|
1483
1794
|
}
|
|
1484
1795
|
}
|
|
1485
1796
|
|
|
1797
|
+
/**
|
|
1798
|
+
* Helper to collect all paths in tree for debugging
|
|
1799
|
+
*/
|
|
1800
|
+
getAllTreePaths(node) {
|
|
1801
|
+
const paths = [node.path];
|
|
1802
|
+
if (node.children) {
|
|
1803
|
+
for (const child of node.children) {
|
|
1804
|
+
paths.push(...this.getAllTreePaths(child));
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
return paths;
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1486
1810
|
/**
|
|
1487
1811
|
* Find D3 hierarchy node by path
|
|
1488
1812
|
*/
|
|
@@ -1669,7 +1993,24 @@ class CodeTree {
|
|
|
1669
1993
|
|
|
1670
1994
|
// Enter new nodes
|
|
1671
1995
|
const nodeEnter = node.enter().append('g')
|
|
1672
|
-
.attr('class',
|
|
1996
|
+
.attr('class', d => {
|
|
1997
|
+
let classes = ['node', 'code-node'];
|
|
1998
|
+
if (d.data.type === 'directory') {
|
|
1999
|
+
classes.push('directory');
|
|
2000
|
+
if (d.data.loaded === true && d.children) {
|
|
2001
|
+
classes.push('expanded');
|
|
2002
|
+
}
|
|
2003
|
+
if (d.data.loaded === 'loading') {
|
|
2004
|
+
classes.push('loading');
|
|
2005
|
+
}
|
|
2006
|
+
if (d.data.children && d.data.children.length === 0) {
|
|
2007
|
+
classes.push('empty');
|
|
2008
|
+
}
|
|
2009
|
+
} else if (d.data.type === 'file') {
|
|
2010
|
+
classes.push('file');
|
|
2011
|
+
}
|
|
2012
|
+
return classes.join(' ');
|
|
2013
|
+
})
|
|
1673
2014
|
.attr('transform', d => {
|
|
1674
2015
|
if (this.isRadialLayout) {
|
|
1675
2016
|
const [x, y] = this.radialPoint(source.x0 || 0, source.y0 || 0);
|
|
@@ -1686,9 +2027,27 @@ class CodeTree {
|
|
|
1686
2027
|
.attr('r', 1e-6)
|
|
1687
2028
|
.style('fill', d => this.getNodeColor(d))
|
|
1688
2029
|
.style('stroke', d => this.getNodeStrokeColor(d))
|
|
1689
|
-
.style('stroke-width', 2)
|
|
2030
|
+
.style('stroke-width', d => d.data.type === 'directory' ? 2 : 1.5)
|
|
2031
|
+
.style('cursor', 'pointer') // Add cursor pointer for visual feedback
|
|
2032
|
+
.on('click', (event, d) => this.onNodeClick(event, d)) // CRITICAL FIX: Add click handler to circles
|
|
1690
2033
|
.on('mouseover', (event, d) => this.showTooltip(event, d))
|
|
1691
2034
|
.on('mouseout', () => this.hideTooltip());
|
|
2035
|
+
|
|
2036
|
+
// Add expand/collapse icons for directories
|
|
2037
|
+
nodeEnter.filter(d => d.data.type === 'directory')
|
|
2038
|
+
.append('text')
|
|
2039
|
+
.attr('class', 'expand-icon')
|
|
2040
|
+
.attr('x', 0)
|
|
2041
|
+
.attr('y', 0)
|
|
2042
|
+
.attr('text-anchor', 'middle')
|
|
2043
|
+
.attr('dominant-baseline', 'central')
|
|
2044
|
+
.text(d => {
|
|
2045
|
+
if (d.data.loaded === 'loading') return '⟳';
|
|
2046
|
+
if (d.data.loaded === true && d.children) return '▼';
|
|
2047
|
+
return '▶';
|
|
2048
|
+
})
|
|
2049
|
+
.style('font-size', '10px')
|
|
2050
|
+
.style('pointer-events', 'none');
|
|
1692
2051
|
|
|
1693
2052
|
// Add labels for nodes with smart positioning
|
|
1694
2053
|
nodeEnter.append('text')
|
|
@@ -1721,21 +2080,46 @@ class CodeTree {
|
|
|
1721
2080
|
.style('fill-opacity', 1e-6)
|
|
1722
2081
|
.style('font-size', '12px')
|
|
1723
2082
|
.style('font-family', '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif')
|
|
1724
|
-
.style('text-shadow', '1px 1px 2px rgba(255,255,255,0.8), -1px -1px 2px rgba(255,255,255,0.8)')
|
|
2083
|
+
.style('text-shadow', '1px 1px 2px rgba(255,255,255,0.8), -1px -1px 2px rgba(255,255,255,0.8)')
|
|
2084
|
+
.on('click', (event, d) => this.onNodeClick(event, d)) // CRITICAL FIX: Add click handler to labels
|
|
2085
|
+
.style('cursor', 'pointer');
|
|
1725
2086
|
|
|
1726
|
-
// Add icons for node types
|
|
1727
|
-
nodeEnter.
|
|
2087
|
+
// Add icons for node types (files only, directories use expand icons)
|
|
2088
|
+
nodeEnter.filter(d => d.data.type !== 'directory')
|
|
2089
|
+
.append('text')
|
|
1728
2090
|
.attr('class', 'node-icon')
|
|
1729
2091
|
.attr('dy', '.35em')
|
|
1730
2092
|
.attr('x', 0)
|
|
1731
2093
|
.attr('text-anchor', 'middle')
|
|
1732
2094
|
.text(d => this.getNodeIcon(d))
|
|
1733
2095
|
.style('font-size', '10px')
|
|
1734
|
-
.style('fill', 'white')
|
|
2096
|
+
.style('fill', 'white')
|
|
2097
|
+
.on('click', (event, d) => this.onNodeClick(event, d)) // CRITICAL FIX: Add click handler to file icons
|
|
2098
|
+
.style('cursor', 'pointer');
|
|
2099
|
+
|
|
2100
|
+
// Add item count badges for directories
|
|
2101
|
+
nodeEnter.filter(d => d.data.type === 'directory' && d.data.children)
|
|
2102
|
+
.append('text')
|
|
2103
|
+
.attr('class', 'item-count-badge')
|
|
2104
|
+
.attr('x', 12)
|
|
2105
|
+
.attr('y', -8)
|
|
2106
|
+
.attr('text-anchor', 'middle')
|
|
2107
|
+
.text(d => {
|
|
2108
|
+
const count = d.data.children ? d.data.children.length : 0;
|
|
2109
|
+
return count > 0 ? count : '';
|
|
2110
|
+
})
|
|
2111
|
+
.style('font-size', '9px')
|
|
2112
|
+
.style('opacity', 0.7)
|
|
2113
|
+
.on('click', (event, d) => this.onNodeClick(event, d)) // CRITICAL FIX: Add click handler to count badges
|
|
2114
|
+
.style('cursor', 'pointer');
|
|
1735
2115
|
|
|
1736
2116
|
// Transition to new positions
|
|
1737
2117
|
const nodeUpdate = nodeEnter.merge(node);
|
|
1738
2118
|
|
|
2119
|
+
// CRITICAL FIX: Ensure ALL nodes (new and existing) have click handlers
|
|
2120
|
+
// This fixes the issue where subdirectory clicks stop working after tree updates
|
|
2121
|
+
nodeUpdate.on('click', (event, d) => this.onNodeClick(event, d));
|
|
2122
|
+
|
|
1739
2123
|
nodeUpdate.transition()
|
|
1740
2124
|
.duration(this.duration)
|
|
1741
2125
|
.attr('transform', d => {
|
|
@@ -1747,9 +2131,45 @@ class CodeTree {
|
|
|
1747
2131
|
}
|
|
1748
2132
|
});
|
|
1749
2133
|
|
|
2134
|
+
// Update node classes based on current state
|
|
2135
|
+
nodeUpdate.attr('class', d => {
|
|
2136
|
+
let classes = ['node', 'code-node'];
|
|
2137
|
+
if (d.data.type === 'directory') {
|
|
2138
|
+
classes.push('directory');
|
|
2139
|
+
if (d.data.loaded === true && d.children) {
|
|
2140
|
+
classes.push('expanded');
|
|
2141
|
+
}
|
|
2142
|
+
if (d.data.loaded === 'loading') {
|
|
2143
|
+
classes.push('loading');
|
|
2144
|
+
}
|
|
2145
|
+
if (d.data.children && d.data.children.length === 0) {
|
|
2146
|
+
classes.push('empty');
|
|
2147
|
+
}
|
|
2148
|
+
} else if (d.data.type === 'file') {
|
|
2149
|
+
classes.push('file');
|
|
2150
|
+
}
|
|
2151
|
+
return classes.join(' ');
|
|
2152
|
+
});
|
|
2153
|
+
|
|
1750
2154
|
nodeUpdate.select('circle.node-circle')
|
|
1751
|
-
.attr('r', 8)
|
|
2155
|
+
.attr('r', d => d.data.type === 'directory' ? 10 : 8)
|
|
1752
2156
|
.style('fill', d => this.getNodeColor(d))
|
|
2157
|
+
|
|
2158
|
+
// Update expand/collapse icons
|
|
2159
|
+
nodeUpdate.select('.expand-icon')
|
|
2160
|
+
.text(d => {
|
|
2161
|
+
if (d.data.loaded === 'loading') return '⟳';
|
|
2162
|
+
if (d.data.loaded === true && d.children) return '▼';
|
|
2163
|
+
return '▶';
|
|
2164
|
+
});
|
|
2165
|
+
|
|
2166
|
+
// Update item count badges
|
|
2167
|
+
nodeUpdate.select('.item-count-badge')
|
|
2168
|
+
.text(d => {
|
|
2169
|
+
if (d.data.type !== 'directory') return '';
|
|
2170
|
+
const count = d.data.children ? d.data.children.length : 0;
|
|
2171
|
+
return count > 0 ? count : '';
|
|
2172
|
+
})
|
|
1753
2173
|
.style('stroke', d => this.getNodeStrokeColor(d))
|
|
1754
2174
|
.attr('cursor', 'pointer');
|
|
1755
2175
|
|
|
@@ -1861,67 +2281,25 @@ class CodeTree {
|
|
|
1861
2281
|
}
|
|
1862
2282
|
|
|
1863
2283
|
/**
|
|
1864
|
-
* Center the view on a specific node (Linear layout)
|
|
2284
|
+
* REMOVED: Center the view on a specific node (Linear layout)
|
|
2285
|
+
* This method has been completely disabled to prevent unwanted tree movement.
|
|
2286
|
+
* All centering functionality has been removed from the code tree.
|
|
1865
2287
|
*/
|
|
1866
2288
|
centerOnNode(d) {
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
const currentTransform = d3.zoomTransform(this.svg.node());
|
|
1871
|
-
// Zoom in to 2x for better focus on clicked node
|
|
1872
|
-
const targetScale = currentTransform.k < 2 ? 2 : currentTransform.k;
|
|
1873
|
-
|
|
1874
|
-
// Account for the initial tree group offset
|
|
1875
|
-
const initialOffsetX = this.margin.left + 100;
|
|
1876
|
-
const initialOffsetY = this.height / 2;
|
|
1877
|
-
|
|
1878
|
-
// Calculate position to center the node accounting for the tree group's transform
|
|
1879
|
-
const x = initialOffsetX - d.y * targetScale + this.width / 2;
|
|
1880
|
-
const y = initialOffsetY - d.x * targetScale + this.height / 2;
|
|
1881
|
-
|
|
1882
|
-
this.svg.transition()
|
|
1883
|
-
.duration(750)
|
|
1884
|
-
.call(
|
|
1885
|
-
this.zoom.transform,
|
|
1886
|
-
d3.zoomIdentity
|
|
1887
|
-
.translate(x, y)
|
|
1888
|
-
.scale(targetScale)
|
|
1889
|
-
);
|
|
2289
|
+
// Method disabled - no centering operations will be performed
|
|
2290
|
+
console.log('[CodeTree] centerOnNode called but disabled - no centering will occur');
|
|
2291
|
+
return;
|
|
1890
2292
|
}
|
|
1891
2293
|
|
|
1892
2294
|
/**
|
|
1893
|
-
* Center the view on a specific node (Radial layout)
|
|
2295
|
+
* REMOVED: Center the view on a specific node (Radial layout)
|
|
2296
|
+
* This method has been completely disabled to prevent unwanted tree movement.
|
|
2297
|
+
* All centering functionality has been removed from the code tree.
|
|
1894
2298
|
*/
|
|
1895
2299
|
centerOnNodeRadial(d) {
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
const [x, y] = this.radialPoint(d.x, d.y);
|
|
1900
|
-
|
|
1901
|
-
// Get current transform or use default zoom level
|
|
1902
|
-
const currentTransform = d3.zoomTransform(this.svg.node());
|
|
1903
|
-
// Zoom in to 2x for better focus on clicked node
|
|
1904
|
-
const targetScale = currentTransform.k < 2 ? 2 : currentTransform.k;
|
|
1905
|
-
|
|
1906
|
-
// Account for the initial tree group centering
|
|
1907
|
-
const centerX = this.width / 2;
|
|
1908
|
-
const centerY = this.height / 2;
|
|
1909
|
-
|
|
1910
|
-
// Calculate translation to center the node
|
|
1911
|
-
// The tree group is centered at centerX, centerY
|
|
1912
|
-
// We need to offset by the node's position scaled
|
|
1913
|
-
const targetX = centerX - x * targetScale;
|
|
1914
|
-
const targetY = centerY - y * targetScale;
|
|
1915
|
-
|
|
1916
|
-
// Apply smooth transition to center the node with zoom
|
|
1917
|
-
this.svg.transition()
|
|
1918
|
-
.duration(750)
|
|
1919
|
-
.call(
|
|
1920
|
-
this.zoom.transform,
|
|
1921
|
-
d3.zoomIdentity
|
|
1922
|
-
.translate(targetX, targetY)
|
|
1923
|
-
.scale(targetScale)
|
|
1924
|
-
);
|
|
2300
|
+
// Method disabled - no centering operations will be performed
|
|
2301
|
+
console.log('[CodeTree] centerOnNodeRadial called but disabled - no centering will occur');
|
|
2302
|
+
return;
|
|
1925
2303
|
}
|
|
1926
2304
|
|
|
1927
2305
|
/**
|
|
@@ -2058,43 +2436,15 @@ class CodeTree {
|
|
|
2058
2436
|
.style('stroke-width', 3)
|
|
2059
2437
|
.style('opacity', 0.8);
|
|
2060
2438
|
|
|
2061
|
-
//
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
const minAngle = Math.min(...angles);
|
|
2072
|
-
const maxAngle = Math.max(...angles);
|
|
2073
|
-
const maxRadius = Math.max(...radii);
|
|
2074
|
-
|
|
2075
|
-
// Zoom to fit parent and children
|
|
2076
|
-
const angleSpan = maxAngle - minAngle;
|
|
2077
|
-
const scale = Math.min(
|
|
2078
|
-
angleSpan > 0 ? (Math.PI * 2) / (angleSpan * 2) : 2.5, // Fit angle span
|
|
2079
|
-
this.width / (2 * maxRadius), // Fit radius
|
|
2080
|
-
2.5 // Max zoom
|
|
2081
|
-
);
|
|
2082
|
-
|
|
2083
|
-
// Calculate center angle and radius
|
|
2084
|
-
const centerAngle = (minAngle + maxAngle) / 2;
|
|
2085
|
-
const centerRadius = maxRadius / 2;
|
|
2086
|
-
const centerX = centerRadius * Math.cos(centerAngle - Math.PI / 2);
|
|
2087
|
-
const centerY = centerRadius * Math.sin(centerAngle - Math.PI / 2);
|
|
2088
|
-
|
|
2089
|
-
this.svg.transition()
|
|
2090
|
-
.duration(750)
|
|
2091
|
-
.call(
|
|
2092
|
-
this.zoom.transform,
|
|
2093
|
-
d3.zoomIdentity
|
|
2094
|
-
.translate(this.width / 2 - centerX * scale, this.height / 2 - centerY * scale)
|
|
2095
|
-
.scale(scale)
|
|
2096
|
-
);
|
|
2097
|
-
}
|
|
2439
|
+
// REMOVED: Radial zoom adjustment functionality
|
|
2440
|
+
// This section previously adjusted zoom to show parent and clicked node together,
|
|
2441
|
+
// but has been completely disabled to prevent unwanted tree movement/centering.
|
|
2442
|
+
// Only visual highlighting of the parent remains active.
|
|
2443
|
+
|
|
2444
|
+
// if (this.isRadialLayout && d.parent) {
|
|
2445
|
+
// // All zoom.transform operations have been disabled
|
|
2446
|
+
// // to prevent tree movement when nodes are clicked
|
|
2447
|
+
// }
|
|
2098
2448
|
}
|
|
2099
2449
|
|
|
2100
2450
|
/**
|
|
@@ -2133,24 +2483,26 @@ class CodeTree {
|
|
|
2133
2483
|
// These execute immediately before any async operations
|
|
2134
2484
|
|
|
2135
2485
|
|
|
2136
|
-
// Center on clicked node (immediate visual effect)
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
}
|
|
2152
|
-
|
|
2153
|
-
}
|
|
2486
|
+
// Center on clicked node (immediate visual effect) - REMOVED
|
|
2487
|
+
// Centering functionality has been disabled to prevent unwanted repositioning
|
|
2488
|
+
// when nodes are clicked. All other click functionality remains intact.
|
|
2489
|
+
// try {
|
|
2490
|
+
// if (this.isRadialLayout) {
|
|
2491
|
+
// if (typeof this.centerOnNodeRadial === 'function') {
|
|
2492
|
+
// this.centerOnNodeRadial(d);
|
|
2493
|
+
// } else {
|
|
2494
|
+
// console.error('[CodeTree] centerOnNodeRadial is not a function!');
|
|
2495
|
+
// }
|
|
2496
|
+
// } else {
|
|
2497
|
+
// if (typeof this.centerOnNode === 'function') {
|
|
2498
|
+
// this.centerOnNode(d);
|
|
2499
|
+
// } else {
|
|
2500
|
+
// console.error('[CodeTree] centerOnNode is not a function!');
|
|
2501
|
+
// }
|
|
2502
|
+
// }
|
|
2503
|
+
// } catch (error) {
|
|
2504
|
+
// console.error('[CodeTree] ERROR during centering:', error, error.stack);
|
|
2505
|
+
// }
|
|
2154
2506
|
|
|
2155
2507
|
|
|
2156
2508
|
// Highlight with larger icon (immediate visual effect)
|
|
@@ -2213,12 +2565,29 @@ class CodeTree {
|
|
|
2213
2565
|
|
|
2214
2566
|
// For directories that haven't been loaded yet, request discovery
|
|
2215
2567
|
if (d.data.type === 'directory' && !d.data.loaded) {
|
|
2568
|
+
// Prevent duplicate requests
|
|
2569
|
+
if (this.loadingNodes.has(d.data.path)) {
|
|
2570
|
+
this.showNotification(`Already loading: ${d.data.name}`, 'warning');
|
|
2571
|
+
return;
|
|
2572
|
+
}
|
|
2573
|
+
|
|
2216
2574
|
// Mark as loading immediately to prevent duplicate requests
|
|
2217
2575
|
d.data.loaded = 'loading';
|
|
2576
|
+
this.loadingNodes.add(d.data.path);
|
|
2218
2577
|
|
|
2219
2578
|
// Ensure path is absolute or relative to working directory
|
|
2220
2579
|
const fullPath = this.ensureFullPath(d.data.path);
|
|
2221
2580
|
|
|
2581
|
+
// CRITICAL DEBUG: Log directory loading attempt
|
|
2582
|
+
console.log('🚀 [SUBDIRECTORY LOADING] Attempting to load:', {
|
|
2583
|
+
originalPath: d.data.path,
|
|
2584
|
+
fullPath: fullPath,
|
|
2585
|
+
nodeType: d.data.type,
|
|
2586
|
+
loaded: d.data.loaded,
|
|
2587
|
+
hasSocket: !!this.socket,
|
|
2588
|
+
workingDir: this.getWorkingDirectory()
|
|
2589
|
+
});
|
|
2590
|
+
|
|
2222
2591
|
// Sending discovery request for child content
|
|
2223
2592
|
|
|
2224
2593
|
// Store reference to the D3 node for later expansion
|
|
@@ -2229,9 +2598,19 @@ class CodeTree {
|
|
|
2229
2598
|
|
|
2230
2599
|
// Request directory contents via Socket.IO
|
|
2231
2600
|
if (this.socket) {
|
|
2601
|
+
console.log('📡 [SUBDIRECTORY LOADING] Emitting WebSocket request:', {
|
|
2602
|
+
event: 'code:discover:directory',
|
|
2603
|
+
data: {
|
|
2604
|
+
path: fullPath,
|
|
2605
|
+
depth: this.bulkLoadMode ? 2 : 1,
|
|
2606
|
+
languages: selectedLanguages,
|
|
2607
|
+
ignore_patterns: ignorePatterns
|
|
2608
|
+
}
|
|
2609
|
+
});
|
|
2610
|
+
|
|
2232
2611
|
this.socket.emit('code:discover:directory', {
|
|
2233
2612
|
path: fullPath,
|
|
2234
|
-
depth: 1, //
|
|
2613
|
+
depth: this.bulkLoadMode ? 2 : 1, // Load 2 levels if bulk mode enabled
|
|
2235
2614
|
languages: selectedLanguages,
|
|
2236
2615
|
ignore_patterns: ignorePatterns
|
|
2237
2616
|
});
|
|
@@ -2239,6 +2618,8 @@ class CodeTree {
|
|
|
2239
2618
|
this.updateBreadcrumb(`Loading ${d.data.name}...`, 'info');
|
|
2240
2619
|
this.showNotification(`Loading directory: ${d.data.name}`, 'info');
|
|
2241
2620
|
} else {
|
|
2621
|
+
console.error('❌ [SUBDIRECTORY LOADING] No WebSocket connection available!');
|
|
2622
|
+
this.showNotification(`Cannot load directory: No connection`, 'error');
|
|
2242
2623
|
}
|
|
2243
2624
|
}, 100); // 100ms delay to ensure visual effects render first
|
|
2244
2625
|
}
|
|
@@ -2589,109 +2970,22 @@ class CodeTree {
|
|
|
2589
2970
|
* Reset zoom to fit the tree
|
|
2590
2971
|
*/
|
|
2591
2972
|
resetZoom() {
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
this.
|
|
2596
|
-
|
|
2597
|
-
.call(
|
|
2598
|
-
this.zoom.transform,
|
|
2599
|
-
d3.zoomIdentity
|
|
2600
|
-
);
|
|
2601
|
-
|
|
2602
|
-
this.showNotification('Zoom reset', 'info');
|
|
2973
|
+
// DISABLED: All zoom reset operations have been disabled to prevent tree centering/movement
|
|
2974
|
+
// The tree should remain stationary and not center/move when interacting with nodes
|
|
2975
|
+
console.log('[CodeTree] resetZoom called but disabled - no zoom reset will occur');
|
|
2976
|
+
this.showNotification('Zoom reset disabled - tree remains stationary', 'info');
|
|
2977
|
+
return;
|
|
2603
2978
|
}
|
|
2604
2979
|
|
|
2605
2980
|
/**
|
|
2606
|
-
* Focus on a specific node and its subtree
|
|
2981
|
+
* REMOVED: Focus on a specific node and its subtree
|
|
2982
|
+
* This method has been completely disabled to prevent unwanted tree movement.
|
|
2983
|
+
* All centering and focus functionality has been removed from the code tree.
|
|
2607
2984
|
*/
|
|
2608
2985
|
focusOnNode(node) {
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
const descendants = node.descendants ? node.descendants() : [node];
|
|
2613
|
-
|
|
2614
|
-
if (this.isRadialLayout) {
|
|
2615
|
-
// For radial layout, calculate the bounding box in polar coordinates
|
|
2616
|
-
const angles = descendants.map(d => d.x);
|
|
2617
|
-
const radii = descendants.map(d => d.y);
|
|
2618
|
-
|
|
2619
|
-
const minAngle = Math.min(...angles);
|
|
2620
|
-
const maxAngle = Math.max(...angles);
|
|
2621
|
-
const minRadius = Math.min(...radii);
|
|
2622
|
-
const maxRadius = Math.max(...radii);
|
|
2623
|
-
|
|
2624
|
-
// Convert polar bounds to Cartesian for centering
|
|
2625
|
-
const centerAngle = (minAngle + maxAngle) / 2;
|
|
2626
|
-
const centerRadius = (minRadius + maxRadius) / 2;
|
|
2627
|
-
|
|
2628
|
-
// Convert to Cartesian coordinates
|
|
2629
|
-
const centerX = centerRadius * Math.cos(centerAngle - Math.PI / 2);
|
|
2630
|
-
const centerY = centerRadius * Math.sin(centerAngle - Math.PI / 2);
|
|
2631
|
-
|
|
2632
|
-
// Calculate the span for zoom scale
|
|
2633
|
-
const angleSpan = maxAngle - minAngle;
|
|
2634
|
-
const radiusSpan = maxRadius - minRadius;
|
|
2635
|
-
|
|
2636
|
-
// Calculate scale to fit the subtree
|
|
2637
|
-
// Use angle span to determine scale (radial layout specific)
|
|
2638
|
-
let scale = 1;
|
|
2639
|
-
if (angleSpan > 0 && radiusSpan > 0) {
|
|
2640
|
-
// Scale based on the larger dimension
|
|
2641
|
-
const angleFactor = Math.PI * 2 / angleSpan; // Full circle / angle span
|
|
2642
|
-
const radiusFactor = this.radius / radiusSpan;
|
|
2643
|
-
scale = Math.min(angleFactor, radiusFactor, 3); // Max zoom of 3x
|
|
2644
|
-
scale = Math.max(scale, 1); // Min zoom of 1x
|
|
2645
|
-
}
|
|
2646
|
-
|
|
2647
|
-
// Animate the zoom and center
|
|
2648
|
-
this.svg.transition()
|
|
2649
|
-
.duration(750)
|
|
2650
|
-
.call(
|
|
2651
|
-
this.zoom.transform,
|
|
2652
|
-
d3.zoomIdentity
|
|
2653
|
-
.translate(this.width/2 - centerX * scale, this.height/2 - centerY * scale)
|
|
2654
|
-
.scale(scale)
|
|
2655
|
-
);
|
|
2656
|
-
|
|
2657
|
-
} else {
|
|
2658
|
-
// For linear/tree layout
|
|
2659
|
-
const xValues = descendants.map(d => d.x);
|
|
2660
|
-
const yValues = descendants.map(d => d.y);
|
|
2661
|
-
|
|
2662
|
-
const minX = Math.min(...xValues);
|
|
2663
|
-
const maxX = Math.max(...xValues);
|
|
2664
|
-
const minY = Math.min(...yValues);
|
|
2665
|
-
const maxY = Math.max(...yValues);
|
|
2666
|
-
|
|
2667
|
-
// Calculate center
|
|
2668
|
-
const centerX = (minX + maxX) / 2;
|
|
2669
|
-
const centerY = (minY + maxY) / 2;
|
|
2670
|
-
|
|
2671
|
-
// Calculate bounds
|
|
2672
|
-
const width = maxX - minX;
|
|
2673
|
-
const height = maxY - minY;
|
|
2674
|
-
|
|
2675
|
-
// Calculate scale to fit
|
|
2676
|
-
const padding = 100;
|
|
2677
|
-
let scale = 1;
|
|
2678
|
-
if (width > 0 && height > 0) {
|
|
2679
|
-
const scaleX = (this.width - padding) / width;
|
|
2680
|
-
const scaleY = (this.height - padding) / height;
|
|
2681
|
-
scale = Math.min(scaleX, scaleY, 2.5); // Max zoom of 2.5x
|
|
2682
|
-
scale = Math.max(scale, 0.5); // Min zoom of 0.5x
|
|
2683
|
-
}
|
|
2684
|
-
|
|
2685
|
-
// Animate zoom to focus
|
|
2686
|
-
this.svg.transition()
|
|
2687
|
-
.duration(750)
|
|
2688
|
-
.call(
|
|
2689
|
-
this.zoom.transform,
|
|
2690
|
-
d3.zoomIdentity
|
|
2691
|
-
.translate(this.width/2 - centerX * scale, this.height/2 - centerY * scale)
|
|
2692
|
-
.scale(scale)
|
|
2693
|
-
);
|
|
2694
|
-
}
|
|
2986
|
+
// Method disabled - no focusing/centering operations will be performed
|
|
2987
|
+
console.log('[CodeTree] focusOnNode called but disabled - no focusing will occur');
|
|
2988
|
+
return;
|
|
2695
2989
|
|
|
2696
2990
|
// Update breadcrumb with focused path
|
|
2697
2991
|
const path = this.getNodePath(node);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
claude_mpm/BUILD_NUMBER,sha256=toytnNjkIKPgQaGwDqQdC1rpNTAdSEc6Vja50d7Ovug,4
|
|
2
|
-
claude_mpm/VERSION,sha256=
|
|
2
|
+
claude_mpm/VERSION,sha256=sAWQ1JyXU3b9eFcjVh2abG2B2O4q2zU4-5wBB_cdSLo,7
|
|
3
3
|
claude_mpm/__init__.py,sha256=lyTZAYGH4DTaFGLRNWJKk5Q5oTjzN5I6AXmfVX-Jff0,1512
|
|
4
4
|
claude_mpm/__main__.py,sha256=Ro5UBWBoQaSAIoSqWAr7zkbLyvi4sSy28WShqAhKJG0,723
|
|
5
5
|
claude_mpm/constants.py,sha256=I946iCQzIIPRZVVJ8aO7lA4euiyDnNw2IX7EelAOkIE,5915
|
|
@@ -179,8 +179,8 @@ claude_mpm/dashboard/static/built/components/session-manager.js,sha256=ZG__csNeB
|
|
|
179
179
|
claude_mpm/dashboard/static/built/components/socket-manager.js,sha256=LEqCS0_EABAsQVUfb6WQk152mSicK2k039zne5cKR8A,131
|
|
180
180
|
claude_mpm/dashboard/static/built/components/ui-state-manager.js,sha256=PtZs6sxNhqMMFwdlr04kDKQbgOvxtMHdjSh56KR2ZBo,134
|
|
181
181
|
claude_mpm/dashboard/static/built/components/working-directory.js,sha256=xE1ydpKDzRWrzHzfjrCiq5wbf3vDhmgQTGKS7myQcPM,15790
|
|
182
|
-
claude_mpm/dashboard/static/css/activity.css,sha256=
|
|
183
|
-
claude_mpm/dashboard/static/css/code-tree.css,sha256=
|
|
182
|
+
claude_mpm/dashboard/static/css/activity.css,sha256=ClwqYuLrq7X0-Uj8jVuMFUvsr7BPtacaeaxLoPM-nAo,29141
|
|
183
|
+
claude_mpm/dashboard/static/css/code-tree.css,sha256=x0MlVKrBBYr7XU8ndhxx7cjCe35GouhthIM32Zc9SA8,25599
|
|
184
184
|
claude_mpm/dashboard/static/css/connection-status.css,sha256=nQiMLxIFjY5MDgrVCG58VR5H1PpE1vLlgXmnn01-P64,6729
|
|
185
185
|
claude_mpm/dashboard/static/css/dashboard.css,sha256=7QlDMl1GKluf2MA_jlijTUVlMlK0RgdyfS1RLD7uv9k,75201
|
|
186
186
|
claude_mpm/dashboard/static/dist/dashboard.js,sha256=kShaKMMdwk1cKcHnXsn-3kLfYMHI14HUgGu_QJQpzZc,52792
|
|
@@ -209,7 +209,7 @@ claude_mpm/dashboard/static/js/components/activity-tree.js,sha256=358pc-N6lrJ1bf
|
|
|
209
209
|
claude_mpm/dashboard/static/js/components/agent-hierarchy.js,sha256=Xihxog_vJrk8VBEkDogV_wbye2GIFWmH71VQ1lETOHk,28243
|
|
210
210
|
claude_mpm/dashboard/static/js/components/agent-inference.js,sha256=RUVZ_fLOyDkHYjrROen_Pzzay79Bh29eXp_GRIPbIRg,37493
|
|
211
211
|
claude_mpm/dashboard/static/js/components/build-tracker.js,sha256=iouv35tNhnyx9UKtD7X1eakJkpCnvZVCrAJ_VdzsKUY,11251
|
|
212
|
-
claude_mpm/dashboard/static/js/components/code-tree.js,sha256=
|
|
212
|
+
claude_mpm/dashboard/static/js/components/code-tree.js,sha256=bLLU7MBZmTccIa3h3WCAyEwsyhRn5jicgJ7rpPPAYxQ,117432
|
|
213
213
|
claude_mpm/dashboard/static/js/components/code-viewer.js,sha256=vhesEPYOM6MggweaYvYsv7ufVbuVpIcyJPXpJXyJwpM,14453
|
|
214
214
|
claude_mpm/dashboard/static/js/components/connection-debug.js,sha256=Qxr_ofDNkxDlZAwbLnhZkXVMyuO9jOe-NMWC9VHxNnA,22196
|
|
215
215
|
claude_mpm/dashboard/static/js/components/event-processor.js,sha256=_GnAz8pxN1iyXw0O4AIR482QFyQAigEKO9IDUOUbGqc,24844
|
|
@@ -582,9 +582,9 @@ claude_mpm/utils/subprocess_utils.py,sha256=zgiwLqh_17WxHpySvUPH65pb4bzIeUGOAYUJ
|
|
|
582
582
|
claude_mpm/validation/__init__.py,sha256=YZhwE3mhit-lslvRLuwfX82xJ_k4haZeKmh4IWaVwtk,156
|
|
583
583
|
claude_mpm/validation/agent_validator.py,sha256=3Lo6LK-Mw9IdnL_bd3zl_R6FkgSVDYKUUM7EeVVD3jc,20865
|
|
584
584
|
claude_mpm/validation/frontmatter_validator.py,sha256=u8g4Eyd_9O6ugj7Un47oSGh3kqv4wMkuks2i_CtWRvM,7028
|
|
585
|
-
claude_mpm-4.1.
|
|
586
|
-
claude_mpm-4.1.
|
|
587
|
-
claude_mpm-4.1.
|
|
588
|
-
claude_mpm-4.1.
|
|
589
|
-
claude_mpm-4.1.
|
|
590
|
-
claude_mpm-4.1.
|
|
585
|
+
claude_mpm-4.1.14.dist-info/licenses/LICENSE,sha256=lpaivOlPuBZW1ds05uQLJJswy8Rp_HMNieJEbFlqvLk,1072
|
|
586
|
+
claude_mpm-4.1.14.dist-info/METADATA,sha256=zKwH7YdmTVCBMXRnV5qY9iD5_PN660U4C9_DRFlhO9M,13419
|
|
587
|
+
claude_mpm-4.1.14.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
588
|
+
claude_mpm-4.1.14.dist-info/entry_points.txt,sha256=FDPZgz8JOvD-6iuXY2l9Zbo9zYVRuE4uz4Qr0vLeGOk,471
|
|
589
|
+
claude_mpm-4.1.14.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
|
|
590
|
+
claude_mpm-4.1.14.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|