claude-mpm 4.1.11__py3-none-any.whl → 4.1.13__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 (41) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/INSTRUCTIONS.md +8 -0
  3. claude_mpm/cli/__init__.py +1 -1
  4. claude_mpm/cli/commands/monitor.py +88 -627
  5. claude_mpm/cli/commands/mpm_init.py +127 -107
  6. claude_mpm/cli/commands/mpm_init_handler.py +24 -23
  7. claude_mpm/cli/parsers/mpm_init_parser.py +34 -28
  8. claude_mpm/core/config.py +18 -0
  9. claude_mpm/core/instruction_reinforcement_hook.py +266 -0
  10. claude_mpm/core/pm_hook_interceptor.py +105 -8
  11. claude_mpm/dashboard/static/built/components/activity-tree.js +1 -1
  12. claude_mpm/dashboard/static/built/components/code-tree.js +1 -1
  13. claude_mpm/dashboard/static/built/dashboard.js +1 -1
  14. claude_mpm/dashboard/static/built/socket-client.js +1 -1
  15. claude_mpm/dashboard/static/css/activity.css +1239 -267
  16. claude_mpm/dashboard/static/css/dashboard.css +511 -0
  17. claude_mpm/dashboard/static/dist/components/activity-tree.js +1 -1
  18. claude_mpm/dashboard/static/dist/components/code-tree.js +1 -1
  19. claude_mpm/dashboard/static/dist/components/module-viewer.js +1 -1
  20. claude_mpm/dashboard/static/dist/dashboard.js +1 -1
  21. claude_mpm/dashboard/static/dist/socket-client.js +1 -1
  22. claude_mpm/dashboard/static/js/components/activity-tree.js +1193 -892
  23. claude_mpm/dashboard/static/js/components/build-tracker.js +15 -13
  24. claude_mpm/dashboard/static/js/components/code-tree.js +534 -143
  25. claude_mpm/dashboard/static/js/components/module-viewer.js +21 -7
  26. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +1066 -0
  27. claude_mpm/dashboard/static/js/connection-manager.js +1 -1
  28. claude_mpm/dashboard/static/js/dashboard.js +227 -84
  29. claude_mpm/dashboard/static/js/socket-client.js +2 -2
  30. claude_mpm/dashboard/templates/index.html +100 -23
  31. claude_mpm/services/agents/deployment/agent_template_builder.py +11 -7
  32. claude_mpm/services/cli/socketio_manager.py +39 -8
  33. claude_mpm/services/infrastructure/monitoring.py +1 -1
  34. claude_mpm/services/socketio/handlers/code_analysis.py +83 -136
  35. claude_mpm/tools/code_tree_analyzer.py +290 -202
  36. {claude_mpm-4.1.11.dist-info → claude_mpm-4.1.13.dist-info}/METADATA +1 -1
  37. {claude_mpm-4.1.11.dist-info → claude_mpm-4.1.13.dist-info}/RECORD +41 -39
  38. {claude_mpm-4.1.11.dist-info → claude_mpm-4.1.13.dist-info}/WHEEL +0 -0
  39. {claude_mpm-4.1.11.dist-info → claude_mpm-4.1.13.dist-info}/entry_points.txt +0 -0
  40. {claude_mpm-4.1.11.dist-info → claude_mpm-4.1.13.dist-info}/licenses/LICENSE +0 -0
  41. {claude_mpm-4.1.11.dist-info → claude_mpm-4.1.13.dist-info}/top_level.txt +0 -0
@@ -3603,3 +3603,514 @@ button:disabled:hover {
3603
3603
  margin-left: 28px;
3604
3604
  }
3605
3605
  }
3606
+
3607
+
3608
+ /* Flat Agent View Styles */
3609
+ .agent-events-flat {
3610
+ display: flex;
3611
+ flex-direction: column;
3612
+ gap: 8px;
3613
+ }
3614
+
3615
+ .agent-event-item {
3616
+ background: white;
3617
+ border-radius: 6px;
3618
+ padding: 12px;
3619
+ margin-bottom: 4px;
3620
+ border-left: 4px solid #4299e1;
3621
+ cursor: pointer;
3622
+ transition: all 0.2s;
3623
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
3624
+ }
3625
+
3626
+ .agent-event-item:hover {
3627
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
3628
+ transform: translateY(-1px);
3629
+ background: #f8fafc;
3630
+ }
3631
+
3632
+ .agent-event-header {
3633
+ display: grid;
3634
+ grid-template-columns: auto 1fr auto auto;
3635
+ gap: 12px;
3636
+ align-items: center;
3637
+ }
3638
+
3639
+ .agent-event-time {
3640
+ font-family: "SF Mono", Monaco, "Cascadia Code", monospace;
3641
+ font-size: 12px;
3642
+ color: #718096;
3643
+ background: #edf2f7;
3644
+ padding: 4px 8px;
3645
+ border-radius: 4px;
3646
+ min-width: 80px;
3647
+ text-align: center;
3648
+ }
3649
+
3650
+ .agent-event-agent {
3651
+ font-weight: 600;
3652
+ color: #2d3748;
3653
+ display: flex;
3654
+ align-items: center;
3655
+ gap: 6px;
3656
+ }
3657
+
3658
+ .agent-event-action {
3659
+ font-size: 13px;
3660
+ color: #4a5568;
3661
+ display: flex;
3662
+ align-items: center;
3663
+ gap: 4px;
3664
+ }
3665
+
3666
+ .agent-event-status {
3667
+ font-size: 12px;
3668
+ padding: 2px 6px;
3669
+ border-radius: 3px;
3670
+ font-weight: 500;
3671
+ }
3672
+
3673
+ .status-active {
3674
+ background: #c6f6d5;
3675
+ color: #22543d;
3676
+ }
3677
+
3678
+ .status-completed {
3679
+ background: #bee3f8;
3680
+ color: #2c5282;
3681
+ }
3682
+
3683
+ .status-error {
3684
+ background: #fed7d7;
3685
+ color: #742a2a;
3686
+ }
3687
+
3688
+ .status-pending {
3689
+ background: #faf089;
3690
+ color: #744210;
3691
+ }
3692
+
3693
+ .agent-event-details {
3694
+ margin-top: 8px;
3695
+ padding-left: 16px;
3696
+ font-size: 12px;
3697
+ color: #4a5568;
3698
+ font-family: "SF Mono", Monaco, "Cascadia Code", monospace;
3699
+ background: #f7fafc;
3700
+ padding: 8px 12px;
3701
+ border-radius: 4px;
3702
+ border-left: 3px solid #cbd5e0;
3703
+ }
3704
+
3705
+ /* Mobile responsive for flat view */
3706
+ @media (max-width: 768px) {
3707
+ .agent-event-header {
3708
+ grid-template-columns: 1fr;
3709
+ gap: 6px;
3710
+ }
3711
+
3712
+ .agent-event-time {
3713
+ justify-self: start;
3714
+ min-width: auto;
3715
+ }
3716
+
3717
+ .agent-event-agent {
3718
+ font-size: 14px;
3719
+ }
3720
+
3721
+ .agent-event-action {
3722
+ font-size: 12px;
3723
+ }
3724
+
3725
+ .agent-event-status {
3726
+ justify-self: end;
3727
+ }
3728
+ }
3729
+
3730
+ /* Unified Data Viewer Styles */
3731
+ .unified-viewer-header {
3732
+ display: flex;
3733
+ justify-content: space-between;
3734
+ align-items: center;
3735
+ margin-bottom: 16px;
3736
+ padding-bottom: 8px;
3737
+ border-bottom: 2px solid #e2e8f0;
3738
+ }
3739
+
3740
+ .unified-viewer-header h6 {
3741
+ margin: 0;
3742
+ color: #2d3748;
3743
+ font-size: 16px;
3744
+ font-weight: 600;
3745
+ display: flex;
3746
+ align-items: center;
3747
+ gap: 8px;
3748
+ }
3749
+
3750
+ .unified-viewer-timestamp {
3751
+ font-family: "SF Mono", Monaco, "Cascadia Code", monospace;
3752
+ font-size: 12px;
3753
+ color: #718096;
3754
+ background: #edf2f7;
3755
+ padding: 4px 8px;
3756
+ border-radius: 4px;
3757
+ }
3758
+
3759
+ .unified-viewer-status {
3760
+ font-size: 12px;
3761
+ padding: 4px 8px;
3762
+ border-radius: 4px;
3763
+ font-weight: 500;
3764
+ }
3765
+
3766
+ .unified-viewer-count {
3767
+ font-size: 12px;
3768
+ color: #4a5568;
3769
+ background: #e2e8f0;
3770
+ padding: 2px 6px;
3771
+ border-radius: 3px;
3772
+ }
3773
+
3774
+ .unified-viewer-content {
3775
+ color: #4a5568;
3776
+ line-height: 1.5;
3777
+ }
3778
+
3779
+ .detail-row {
3780
+ display: flex;
3781
+ align-items: flex-start;
3782
+ margin-bottom: 12px;
3783
+ gap: 12px;
3784
+ }
3785
+
3786
+ .detail-label {
3787
+ font-weight: 600;
3788
+ color: #2d3748;
3789
+ min-width: 120px;
3790
+ flex-shrink: 0;
3791
+ }
3792
+
3793
+ .detail-value {
3794
+ flex: 1;
3795
+ word-break: break-word;
3796
+ }
3797
+
3798
+ .detail-section {
3799
+ margin-top: 20px;
3800
+ padding-top: 16px;
3801
+ border-top: 1px solid #e2e8f0;
3802
+ }
3803
+
3804
+ .detail-section-title {
3805
+ display: block;
3806
+ font-weight: 600;
3807
+ color: #2d3748;
3808
+ margin-bottom: 12px;
3809
+ font-size: 14px;
3810
+ }
3811
+
3812
+ /* Tool and parameter display */
3813
+ .tools-list {
3814
+ display: flex;
3815
+ flex-direction: column;
3816
+ gap: 8px;
3817
+ }
3818
+
3819
+ .tool-summary {
3820
+ display: flex;
3821
+ align-items: center;
3822
+ gap: 8px;
3823
+ padding: 8px 12px;
3824
+ background: #f7fafc;
3825
+ border-radius: 6px;
3826
+ border-left: 3px solid #cbd5e0;
3827
+ }
3828
+
3829
+ .tool-icon {
3830
+ font-size: 14px;
3831
+ }
3832
+
3833
+ .tool-name {
3834
+ font-weight: 500;
3835
+ flex: 1;
3836
+ }
3837
+
3838
+ .tool-status {
3839
+ font-size: 11px;
3840
+ padding: 2px 6px;
3841
+ border-radius: 3px;
3842
+ text-transform: uppercase;
3843
+ font-weight: 600;
3844
+ }
3845
+
3846
+ .params-list {
3847
+ display: flex;
3848
+ flex-direction: column;
3849
+ gap: 12px;
3850
+ }
3851
+
3852
+ .param-item {
3853
+ background: #f7fafc;
3854
+ padding: 12px;
3855
+ border-radius: 6px;
3856
+ border-left: 3px solid #cbd5e0;
3857
+ }
3858
+
3859
+ .param-key {
3860
+ font-weight: 600;
3861
+ color: #2d3748;
3862
+ margin-bottom: 4px;
3863
+ font-size: 13px;
3864
+ }
3865
+
3866
+ .param-value {
3867
+ color: #4a5568;
3868
+ }
3869
+
3870
+ .param-text-short {
3871
+ font-family: "SF Mono", Monaco, "Cascadia Code", monospace;
3872
+ font-size: 12px;
3873
+ background: #edf2f7;
3874
+ padding: 2px 4px;
3875
+ border-radius: 3px;
3876
+ }
3877
+
3878
+ .param-text {
3879
+ font-family: "SF Mono", Monaco, "Cascadia Code", monospace;
3880
+ font-size: 12px;
3881
+ background: #edf2f7;
3882
+ padding: 8px;
3883
+ border-radius: 4px;
3884
+ white-space: pre-wrap;
3885
+ word-wrap: break-word;
3886
+ max-height: 200px;
3887
+ overflow-y: auto;
3888
+ }
3889
+
3890
+ .param-text-long {
3891
+ font-family: "SF Mono", Monaco, "Cascadia Code", monospace;
3892
+ font-size: 12px;
3893
+ background: #edf2f7;
3894
+ padding: 8px;
3895
+ border-radius: 4px;
3896
+ white-space: pre-wrap;
3897
+ word-wrap: break-word;
3898
+ max-height: 300px;
3899
+ overflow-y: auto;
3900
+ }
3901
+
3902
+ .param-json {
3903
+ font-family: "SF Mono", Monaco, "Cascadia Code", monospace;
3904
+ font-size: 11px;
3905
+ background: #1a202c;
3906
+ color: #e2e8f0;
3907
+ padding: 12px;
3908
+ border-radius: 6px;
3909
+ white-space: pre-wrap;
3910
+ word-wrap: break-word;
3911
+ max-height: 400px;
3912
+ overflow-y: auto;
3913
+ }
3914
+
3915
+ .param-error {
3916
+ color: #e53e3e;
3917
+ font-style: italic;
3918
+ }
3919
+
3920
+ /* Todo display */
3921
+ .todo-summary {
3922
+ display: flex;
3923
+ gap: 12px;
3924
+ margin-bottom: 16px;
3925
+ }
3926
+
3927
+ .status-count {
3928
+ padding: 4px 8px;
3929
+ border-radius: 4px;
3930
+ font-size: 12px;
3931
+ font-weight: 500;
3932
+ }
3933
+
3934
+ .status-count.completed {
3935
+ background: #c6f6d5;
3936
+ color: #22543d;
3937
+ }
3938
+
3939
+ .status-count.in_progress {
3940
+ background: #fbb6ce;
3941
+ color: #702459;
3942
+ }
3943
+
3944
+ .status-count.pending {
3945
+ background: #faf089;
3946
+ color: #744210;
3947
+ }
3948
+
3949
+ .todo-list {
3950
+ display: flex;
3951
+ flex-direction: column;
3952
+ gap: 8px;
3953
+ }
3954
+
3955
+ .todo-item {
3956
+ display: flex;
3957
+ align-items: flex-start;
3958
+ gap: 8px;
3959
+ padding: 8px 12px;
3960
+ background: #f7fafc;
3961
+ border-radius: 6px;
3962
+ border-left: 3px solid #cbd5e0;
3963
+ }
3964
+
3965
+ .todo-item.completed {
3966
+ border-left-color: #38a169;
3967
+ background: #f0fff4;
3968
+ }
3969
+
3970
+ .todo-item.in_progress {
3971
+ border-left-color: #d53f8c;
3972
+ background: #fef5e7;
3973
+ }
3974
+
3975
+ .todo-item.pending {
3976
+ border-left-color: #d69e2e;
3977
+ background: #fffbeb;
3978
+ }
3979
+
3980
+ .todo-icon {
3981
+ font-size: 14px;
3982
+ flex-shrink: 0;
3983
+ margin-top: 1px;
3984
+ }
3985
+
3986
+ .todo-content {
3987
+ flex: 1;
3988
+ font-size: 13px;
3989
+ line-height: 1.4;
3990
+ }
3991
+
3992
+ .todo-status {
3993
+ font-size: 11px;
3994
+ padding: 2px 6px;
3995
+ border-radius: 3px;
3996
+ text-transform: capitalize;
3997
+ font-weight: 500;
3998
+ flex-shrink: 0;
3999
+ }
4000
+
4001
+ /* Instruction display */
4002
+ .instruction-text {
4003
+ background: #f7fafc;
4004
+ padding: 12px;
4005
+ border-radius: 6px;
4006
+ border-left: 3px solid #4299e1;
4007
+ font-family: "SF Mono", Monaco, "Cascadia Code", monospace;
4008
+ font-size: 12px;
4009
+ white-space: pre-wrap;
4010
+ word-wrap: break-word;
4011
+ max-height: 300px;
4012
+ overflow-y: auto;
4013
+ }
4014
+
4015
+ /* Operations display */
4016
+ .operations-list {
4017
+ display: flex;
4018
+ flex-direction: column;
4019
+ gap: 8px;
4020
+ }
4021
+
4022
+ .operation-item {
4023
+ display: flex;
4024
+ justify-content: space-between;
4025
+ align-items: center;
4026
+ padding: 8px 12px;
4027
+ background: #f7fafc;
4028
+ border-radius: 6px;
4029
+ border-left: 3px solid #cbd5e0;
4030
+ }
4031
+
4032
+ .operation-type {
4033
+ font-weight: 500;
4034
+ color: #2d3748;
4035
+ }
4036
+
4037
+ .operation-timestamp {
4038
+ font-family: "SF Mono", Monaco, "Cascadia Code", monospace;
4039
+ font-size: 11px;
4040
+ color: #718096;
4041
+ }
4042
+
4043
+ /* Hook details */
4044
+ .prompt-text {
4045
+ background: #f7fafc;
4046
+ padding: 12px;
4047
+ border-radius: 6px;
4048
+ border-left: 3px solid #4299e1;
4049
+ font-family: "SF Mono", Monaco, "Cascadia Code", monospace;
4050
+ font-size: 12px;
4051
+ white-space: pre-wrap;
4052
+ word-wrap: break-word;
4053
+ max-height: 200px;
4054
+ overflow-y: auto;
4055
+ }
4056
+
4057
+ /* Event data JSON display */
4058
+ .event-data-json {
4059
+ font-family: "SF Mono", Monaco, "Cascadia Code", monospace;
4060
+ font-size: 11px;
4061
+ background: #1a202c;
4062
+ color: #e2e8f0;
4063
+ padding: 12px;
4064
+ border-radius: 6px;
4065
+ white-space: pre-wrap;
4066
+ word-wrap: break-word;
4067
+ max-height: 400px;
4068
+ overflow-y: auto;
4069
+ }
4070
+
4071
+ /* Tool result display */
4072
+ .tool-result {
4073
+ font-family: "SF Mono", Monaco, "Cascadia Code", monospace;
4074
+ font-size: 11px;
4075
+ background: #1a202c;
4076
+ color: #e2e8f0;
4077
+ padding: 12px;
4078
+ border-radius: 6px;
4079
+ white-space: pre-wrap;
4080
+ word-wrap: break-word;
4081
+ max-height: 400px;
4082
+ overflow-y: auto;
4083
+ }
4084
+
4085
+ /* No data states */
4086
+ .no-todos {
4087
+ text-align: center;
4088
+ color: #718096;
4089
+ font-style: italic;
4090
+ padding: 20px;
4091
+ }
4092
+
4093
+ .no-params {
4094
+ text-align: center;
4095
+ color: #718096;
4096
+ font-style: italic;
4097
+ padding: 12px;
4098
+ }
4099
+
4100
+ /* Responsive adjustments */
4101
+ @media (max-width: 768px) {
4102
+ .unified-viewer-header {
4103
+ flex-direction: column;
4104
+ align-items: flex-start;
4105
+ gap: 8px;
4106
+ }
4107
+
4108
+ .detail-row {
4109
+ flex-direction: column;
4110
+ gap: 4px;
4111
+ }
4112
+
4113
+ .detail-label {
4114
+ min-width: auto;
4115
+ }
4116
+ }
@@ -1,2 +1,2 @@
1
- class t{constructor(){this.container=null,this.svg=null,this.treeData=null,this.root=null,this.treeLayout=null,this.treeGroup=null,this.events=[],this.todoWriteStack=[],this.activeAgent=null,this.activeAgentStack=[],this.margin={top:20,right:120,bottom:20,left:120},this.width=960-this.margin.left-this.margin.right,this.height=500-this.margin.top-this.margin.bottom,this.nodeId=0,this.duration=750,this.timeRange="30min",this.searchTerm="",this.tooltip=null,this.initialized=!1}initialize(){if(console.log("ActivityTree.initialize() called, initialized:",this.initialized),this.initialized)return void console.log("Activity tree already initialized, skipping");if(this.container=document.getElementById("activity-tree-container"),!this.container&&(this.container=document.getElementById("activity-tree"),!this.container))return void console.error("Activity tree container not found in DOM");this.container.textContent&&this.container.textContent.trim()&&(console.log("Clearing existing text content from container:",this.container.textContent),this.container.textContent=""),console.log("Activity tree container found:",this.container);const t=document.getElementById("activity-tab");if(t){if(!t.classList.contains("active"))return console.log("Activity tab not active, initializing but deferring render"),this.container.textContent&&this.container.textContent.trim()&&(this.container.textContent=""),this.setupControls(),this.initializeTreeData(),this.subscribeToEvents(),void(this.initialized=!0);if(this.container.textContent&&this.container.textContent.trim()&&(console.log("Clearing container text before creating visualization"),this.container.textContent=""),this.setupControls(),this.createVisualization(),!this.svg||!this.treeGroup)return console.error("Failed to create D3 visualization elements"),void(this.container&&(this.container.innerHTML='<div style="padding: 20px; text-align: center; color: #e53e3e;">⚠️ Failed to create visualization. Please refresh the page.</div>'));this.initializeTreeData(),this.root?this.update(this.root):console.warn("Root not created, skipping initial update"),this.subscribeToEvents(),this.initialized=!0,console.log("Activity tree initialization complete")}else console.error("Activity tab panel (#activity-tab) not found in DOM")}forceShow(){if(console.log("ActivityTree.forceShow() called"),this.container||(this.container=document.getElementById("activity-tree-container")||document.getElementById("activity-tree"),this.container)){if(this.container.textContent&&this.container.textContent.trim()&&(console.log("Clearing text from container:",this.container.textContent),this.container.innerHTML=""),this.svg||this.createVisualization(),this.root||this.initializeTreeData(),this.root&&this.svg&&this.treeGroup&&this.update(this.root),this.svg){const t=this.svg.node();t&&(t.style.display="block",t.style.visibility="visible")}}else console.error("Cannot find activity tree container")}renderWhenVisible(){if(console.log("ActivityTree.renderWhenVisible() called"),this.container&&this.container.textContent&&this.container.textContent.trim()&&!this.svg&&(console.log("Clearing text content before rendering:",this.container.textContent),this.container.textContent=""),!this.initialized)return console.log("Not initialized yet, calling initialize..."),void this.initialize();this.svg||(console.log("Creating deferred visualization..."),this.createVisualization(),this.svg&&this.treeGroup&&this.root?this.update(this.root):this.root||(console.warn("No root node available, initializing tree data..."),this.initializeTreeData(),this.root&&this.svg&&this.treeGroup&&this.update(this.root))),this.root&&this.svg?(console.log("Updating tree with current data..."),this.update(this.root)):console.warn("Cannot update tree - missing components:",{hasRoot:!!this.root,hasSvg:!!this.svg,hasTreeGroup:!!this.treeGroup})}setupControls(){const t=document.getElementById("expand-all");t&&t.addEventListener("click",()=>this.expandAll());const e=document.getElementById("collapse-all");e&&e.addEventListener("click",()=>this.collapseAll());const i=document.getElementById("reset-zoom");i&&i.addEventListener("click",()=>this.resetZoom());const o=document.getElementById("time-range");o&&o.addEventListener("change",t=>{this.timeRange=t.target.value,this.filterEventsByTime()});const n=document.getElementById("activity-search");n&&n.addEventListener("input",t=>{this.searchTerm=t.target.value.toLowerCase(),this.highlightSearchResults()})}createVisualization(){if("undefined"==typeof d3)return console.error("D3.js is not loaded! Cannot create activity tree visualization."),void(this.container&&(this.container.innerHTML='<div style="padding: 20px; text-align: center; color: #e53e3e;">⚠️ D3.js is not loaded. Cannot create visualization.</div>'));const t=this.container.getBoundingClientRect();this.width=t.width-this.margin.left-this.margin.right,this.height=Math.max(500,t.height-this.margin.top-this.margin.bottom),console.log("Creating D3 visualization with dimensions:",{width:this.width,height:this.height}),d3.select(this.container).selectAll("*").remove(),this.svg=d3.select(this.container).append("svg").attr("width","100%").attr("height","100%").attr("viewBox",`0 0 ${this.width+this.margin.left+this.margin.right} ${this.height+this.margin.top+this.margin.bottom}`),this.treeGroup=this.svg.append("g").attr("class","tree-group").attr("transform",`translate(${this.margin.left},${this.margin.top})`);const e=d3.zoom().scaleExtent([.1,3]).on("zoom",t=>{this.treeGroup.attr("transform",`translate(${this.margin.left+t.transform.x},${this.margin.top+t.transform.y}) scale(${t.transform.k})`)});this.svg.call(e),this.treeLayout=d3.tree().size([this.height,this.width]),console.log("ActivityTree: Tree layout created:",this.treeLayout),this.tooltip=d3.select("body").append("div").attr("class","activity-tooltip").style("opacity",0),console.log("ActivityTree: Visualization complete, svg:",this.svg,"treeGroup:",this.treeGroup)}initializeTreeData(){if(console.log("ActivityTree: Initializing tree data"),this.treeData={name:"PM",type:"pm",icon:"🎯",children:[],_children:null},"undefined"==typeof d3)return console.error("ActivityTree: D3 is not available - cannot create hierarchy!"),void(this.container&&(this.container.innerHTML='<div style="padding: 20px; text-align: center; color: #e53e3e;">⚠️ Waiting for D3.js to load...</div>'));this.root=d3.hierarchy(this.treeData),this.root.x0=this.height/2,this.root.y0=0,console.log("ActivityTree: Root node created:",this.root),this.updateStats()}subscribeToEvents(){if(!window.socketClient)return console.warn("Socket client not available for activity tree"),void setTimeout(()=>this.subscribeToEvents(),1e3);console.log("ActivityTree: Setting up event subscription"),window.socketClient.onEventUpdate(t=>{console.log(`ActivityTree: onEventUpdate called with ${t.length} total events`);const e=t.length-this.events.length;if(e>0){const i=t.slice(this.events.length);console.log(`ActivityTree: Processing ${e} new events`,i),i.forEach(t=>{this.processEvent(t)}),this.events=[...t]}});const t=window.socketClient?.events||window.eventViewer?.events||[];t.length>0?(console.log(`ActivityTree: Processing ${t.length} existing events`,t),t.forEach(t=>{this.processEvent(t)}),this.events=[...t]):(console.log("ActivityTree: No existing events found"),this.events=[])}processEvent(t){if(!t)return void console.log("ActivityTree: Ignoring null event");let e=null;if(t.hook_event_name)e=t.hook_event_name;else if("hook"===t.type&&t.subtype){e={pre_tool:"PreToolUse",post_tool:"PostToolUse",subagent_start:"SubagentStart",subagent_stop:"SubagentStop",todo_write:"TodoWrite"}[t.subtype]}else"todo"===t.type&&"updated"===t.subtype?e="TodoWrite":"subagent"===t.type?"started"===t.subtype?e="SubagentStart":"stopped"===t.subtype&&(e="SubagentStop"):"start"===t.type&&(e="Start");if(!e)return void("hook"!==t.type&&"todo"!==t.type&&"subagent"!==t.type||console.log("ActivityTree: Cannot determine event type for:",t));console.log(`ActivityTree: Processing event: ${e}`,t);const i=new Date(t.timestamp);if(this.isEventInTimeRange(i)){switch(e){case"TodoWrite":this.processTodoWrite(t);break;case"SubagentStart":this.processSubagentStart(t);break;case"SubagentStop":this.processSubagentStop(t);break;case"PreToolUse":this.processToolUse(t);break;case"PostToolUse":this.updateToolStatus(t,"completed");break;case"Start":this.initializeTreeData(),this.update(this.root)}this.updateStats()}}processTodoWrite(t){console.log("ActivityTree: Processing TodoWrite event:",t);let e=t.todos||t.data?.todos||t.data||[];if(e&&"object"==typeof e&&e.todos&&(e=e.todos),!Array.isArray(e))return void console.log("ActivityTree: Invalid todos format in event:",t);if(0===e.length)return void console.log("ActivityTree: No todos in event");const i=e.find(t=>"in_progress"===t.status);if(!i)return void console.log("ActivityTree: No in-progress todo found");console.log("ActivityTree: Found active todo:",i);const o={name:i.activeForm||i.content,type:"todowrite",icon:"📝",content:i.content,status:i.status,timestamp:t.timestamp,children:[],_children:null,eventId:t.id};this.root?this.root.data?(this.root.data.children||(this.root.data.children=[]),console.log("ActivityTree: Adding TodoWrite node to root"),this.root.data.children.push(o),this.todoWriteStack.push({node:o,content:i.content}),console.log("ActivityTree: Calling update with root:",this.root),this.update(this.root),console.log("ActivityTree: Update complete")):console.error("ActivityTree: Root has no data!"):console.error("ActivityTree: No root node!")}processSubagentStart(t){const e=t.agent_name||t.data?.agent_name||t.data?.agent_type||t.agent_type||t.agent||"unknown",i={name:e,type:"agent",icon:this.getAgentIcon(e),timestamp:t.timestamp,children:[],_children:null,eventId:t.id,sessionId:t.session_id||t.data?.session_id};let o=null;if(this.todoWriteStack.length>0){const t=this.todoWriteStack[this.todoWriteStack.length-1];t.content&&t.content.toLowerCase().includes(e.toLowerCase())&&(o=t.node)}o||(o=this.root.data),o.children||(o.children=[]),o.children.push(i),this.activeAgent=i,this.activeAgentStack.push(i),this.update(this.root)}processSubagentStop(t){const e=t.session_id||t.data?.session_id;this.activeAgent&&this.activeAgent.sessionId===e&&(this.activeAgent.status="completed",this.activeAgentStack.pop(),this.activeAgent=this.activeAgentStack.length>0?this.activeAgentStack[this.activeAgentStack.length-1]:null),this.update(this.root)}processToolUse(t){const e=t.tool_name||t.data?.tool_name||t.tool||t.data?.tool||"unknown",i=this.getToolIcon(e),o=t.tool_parameters||t.data?.tool_parameters||t.parameters||t.data?.parameters||{},n={name:e,type:"tool",icon:i,timestamp:t.timestamp,status:"in_progress",children:[],_children:null,eventId:t.id};"Read"===e&&o.file_path?n.children.push({name:o.file_path,type:"file",icon:"📄",timestamp:t.timestamp}):"Edit"===e&&o.file_path?n.children.push({name:o.file_path,type:"file",icon:"✏️",timestamp:t.timestamp}):"Write"===e&&o.file_path?n.children.push({name:o.file_path,type:"file",icon:"💾",timestamp:t.timestamp}):"Bash"===e&&o.command?n.children.push({name:o.command.substring(0,50)+(o.command.length>50?"...":""),type:"command",icon:"⚡",timestamp:t.timestamp}):"WebFetch"===e&&o.url&&n.children.push({name:o.url,type:"url",icon:"🌐",timestamp:t.timestamp});let s=this.activeAgent||this.root.data;s.children||(s.children=[]),s.children.push(n),this.update(this.root)}updateToolStatus(t,e){const i=o=>{if(o.eventId===t.id)return o.status=e,!0;if(o.children)for(let t of o.children)if(i(t))return!0;if(o._children)for(let t of o._children)if(i(t))return!0;return!1};i(this.root.data),this.update(this.root)}getAgentIcon(t){return{engineer:"👷",research:"🔬",qa:"🧪",ops:"⚙️",pm:"📊",architect:"🏗️"}[t.toLowerCase()]||"🤖"}getToolIcon(t){return{read:"👁️",write:"✍️",edit:"✏️",bash:"💻",webfetch:"🌐",grep:"🔍",glob:"📂",todowrite:"📝"}[t.toLowerCase()]||"🔧"}update(t){if(console.log("ActivityTree: update() called with source:",t),"undefined"==typeof d3)return void console.error("ActivityTree: Cannot update - D3.js not loaded");if(!this.svg||!this.treeGroup){if(console.warn("ActivityTree: Cannot update - SVG not initialized"),!this.container)return;if(console.log("Attempting to create visualization from update()"),this.createVisualization(),!this.svg||!this.treeGroup)return void console.error("Failed to create visualization in update()")}if(!this.treeLayout){if(console.warn("ActivityTree: Cannot update - tree layout not initialized"),"undefined"==typeof d3)return;this.treeLayout=d3.tree().size([this.height,this.width]),console.log("Created tree layout in update()")}if(!t||!t.data)return void console.error("ActivityTree: Invalid source in update()",t);if(!this.root)return void console.error("ActivityTree: No root node available for update");let e;try{e=this.treeLayout(this.root)}catch(c){return void console.error("ActivityTree: Error computing tree layout:",c)}const i=e.descendants(),o=e.links();if(console.log(`ActivityTree: Updating tree with ${i.length} nodes`),1===i.length&&this.container){this.container.querySelector("svg")||console.warn("SVG element not found in container after update")}i.forEach(t=>{t.y=180*t.depth});const n=this.treeGroup.selectAll("g.node").data(i,t=>t.id||(t.id=++this.nodeId)),s=n.enter().append("g").attr("class","node").attr("transform",e=>`translate(${t.y0},${t.x0})`).on("click",(t,e)=>this.click(e));s.append("circle").attr("class",t=>`node-circle ${t.data.type}`).attr("r",1e-6).style("fill",t=>t._children?this.getNodeColor(t.data.type):"#fff").style("stroke",t=>this.getNodeColor(t.data.type)),s.append("text").attr("class","node-icon").attr("dy",".35em").attr("text-anchor","middle").style("font-size","14px").text(t=>t.data.icon||""),s.append("text").attr("class","node-label").attr("dy",".35em").attr("x",t=>t.children||t._children?-25:25).attr("text-anchor",t=>t.children||t._children?"end":"start").text(t=>t.data.name).style("fill-opacity",1e-6),s.on("mouseover",(t,e)=>this.showTooltip(t,e)).on("mouseout",()=>this.hideTooltip());const r=s.merge(n);r.transition().duration(this.duration).attr("transform",t=>`translate(${t.y},${t.x})`),r.select("circle.node-circle").attr("r",10).style("fill",t=>"in_progress"===t.data.status||t._children?this.getNodeColor(t.data.type):"#fff").attr("class",t=>{let e=`node-circle ${t.data.type}`;return"in_progress"===t.data.status&&(e+=" pulsing"),"failed"===t.data.status&&(e+=" failed"),e}),r.select("text.node-label").style("fill-opacity",1);const a=n.exit().transition().duration(this.duration).attr("transform",e=>`translate(${t.y},${t.x})`).remove();a.select("circle").attr("r",1e-6),a.select("text").style("fill-opacity",1e-6);const l=this.treeGroup.selectAll("path.link").data(o,t=>t.target.id);l.enter().insert("path","g").attr("class","link").attr("d",e=>{const i={x:t.x0,y:t.y0};return this.diagonal({source:i,target:i})}).merge(l).transition().duration(this.duration).attr("d",this.diagonal),l.exit().transition().duration(this.duration).attr("d",e=>{const i={x:t.x,y:t.y};return this.diagonal({source:i,target:i})}).remove(),i.forEach(t=>{t.x0=t.x,t.y0=t.y}),this.updateBreadcrumb(t)}diagonal(t){return`M ${t.source.y} ${t.source.x}\n C ${(t.source.y+t.target.y)/2} ${t.source.x},\n ${(t.source.y+t.target.y)/2} ${t.target.x},\n ${t.target.y} ${t.target.x}`}click(t){t.children?(t._children=t.children,t.children=null):(t.children=t._children,t._children=null),this.update(t),this.updateBreadcrumb(t)}getNodeColor(t){return{pm:"#4299e1",todowrite:"#48bb78",agent:"#ed8936",tool:"#9f7aea",file:"#38b2ac",command:"#f56565",url:"#4299e1"}[t]||"#718096"}showTooltip(t,e){const i=`\n <strong>${e.data.name}</strong><br>\n Type: ${e.data.type}<br>\n ${e.data.timestamp?`Time: ${new Date(e.data.timestamp).toLocaleTimeString()}`:""}\n ${e.data.status?`<br>Status: ${e.data.status}`:""}\n `;this.tooltip.transition().duration(200).style("opacity",.9),this.tooltip.html(i).style("left",t.pageX+10+"px").style("top",t.pageY-28+"px")}hideTooltip(){this.tooltip.transition().duration(500).style("opacity",0)}expandAll(){const t=e=>{e._children&&(e.children=e._children,e._children=null),e.children&&e.children.forEach(t)};t(this.root),this.update(this.root)}collapseAll(){const t=e=>{e.children&&(e._children=e.children,e._children.forEach(t),e.children=null)};this.root.children?.forEach(t),this.update(this.root)}resetZoom(){if(!this.svg)return void console.warn("Cannot reset zoom: SVG not initialized");const t=d3.zoom().scaleExtent([.1,3]).on("zoom",t=>{this.treeGroup.attr("transform",`translate(${this.margin.left+t.transform.x},${this.margin.top+t.transform.y}) scale(${t.transform.k})`)});this.svg.transition().duration(750).call(t.transform,d3.zoomIdentity),this.treeGroup.transition().duration(750).attr("transform",`translate(${this.margin.left},${this.margin.top})`)}isEventInTimeRange(t){if("all"===this.timeRange)return!0;const e=(new Date-t)/6e4;switch(this.timeRange){case"10min":return e<=10;case"30min":return e<=30;case"hour":return e<=60;default:return!0}}filterEventsByTime(){this.initializeTreeData(),window.eventViewer&&window.eventViewer.events&&window.eventViewer.events.forEach(t=>{this.processEvent(t)})}updateStats(){if(!this.root||!this.root.data){console.warn("ActivityTree: Cannot update stats - root not initialized");const t=document.getElementById("node-count"),e=document.getElementById("active-count"),i=document.getElementById("tree-depth");return t&&(t.textContent="1"),e&&(e.textContent="0"),void(i&&(i.textContent="0"))}const t=this.countNodes(this.root),e=this.countActiveNodes(this.root.data),i=this.getTreeDepth(this.root),o=document.getElementById("node-count"),n=document.getElementById("active-count"),s=document.getElementById("tree-depth");o&&(o.textContent=t),n&&(n.textContent=e),s&&(s.textContent=i),console.log(`ActivityTree: Stats updated - Nodes: ${t}, Active: ${e}, Depth: ${i}`)}countNodes(t){let e=1;return t.children&&t.children.forEach(t=>{e+=this.countNodes(t)}),t._children&&t._children.forEach(t=>{e+=this.countNodes(t)}),e}countActiveNodes(t){let e="in_progress"===t.status?1:0;return t.children&&t.children.forEach(t=>{e+=this.countActiveNodes(t)}),t._children&&t._children.forEach(t=>{e+=this.countActiveNodes(t)}),e}getTreeDepth(t){if(!t.children&&!t._children)return 0;const e=(t.children||t._children).map(t=>this.getTreeDepth(t));return Math.max(...e)+1}updateBreadcrumb(t){const e=[];let i=t;for(;i;)e.unshift(i.data.name),i=i.parent;const o=document.getElementById("activity-breadcrumb");o&&(o.textContent=e.join(" > "))}highlightSearchResults(){this.treeGroup.selectAll(".node-label").style("font-weight","normal").style("fill","#2d3748"),this.searchTerm&&this.treeGroup.selectAll(".node-label").style("font-weight",t=>t.data.name.toLowerCase().includes(this.searchTerm)?"bold":"normal").style("fill",t=>t.data.name.toLowerCase().includes(this.searchTerm)?"#e53e3e":"#2d3748")}}window.ActivityTree=t;const e=()=>{let e=null;const i=()=>{e||(console.log("Creating new Activity Tree instance..."),e=new t,window.activityTreeInstance=e);const i=document.getElementById("activity-tree-container")||document.getElementById("activity-tree");i&&i.textContent&&i.textContent.trim()&&(console.log("Clearing text from activity tree container before init:",i.textContent),i.textContent=""),setTimeout(()=>{console.log("Attempting to initialize Activity Tree visualization..."),e.initialize()},100)};document.querySelectorAll(".tab-button").forEach(t=>{t.addEventListener("click",t=>{"activity"===t.target.getAttribute("data-tab")&&(console.log("Activity tab button clicked, initializing tree..."),i(),e&&setTimeout(()=>{e.renderWhenVisible(),e.forceShow()},150))})}),document.addEventListener("tabChanged",t=>{t.detail&&"activity"===t.detail.newTab&&(console.log("Tab changed to activity, initializing tree..."),i(),e&&setTimeout(()=>{e.renderWhenVisible(),e.forceShow()},150))});const o=document.querySelector(".tab-button.active");o&&"activity"===o.getAttribute("data-tab")&&(console.log("Activity tab is active on load, initializing tree..."),i());const n=document.getElementById("activity-tab");n&&n.classList.contains("active")&&(console.log("Activity panel is active on load, initializing tree..."),e||i()),window.activityTree=()=>e};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e):e();
1
+ class e{constructor(){this.container=null,this.events=[],this.sessions=new Map,this.currentSession=null,this.selectedSessionFilter="all",this.timeRange="30min",this.searchTerm="",this.initialized=!1,this.expandedSessions=new Set,this.expandedAgents=new Set,this.expandedTools=new Set,this.selectedItem=null}initialize(){if(console.log("ActivityTree.initialize() called, initialized:",this.initialized),this.initialized)return void console.log("Activity tree already initialized, skipping");if(this.container=document.getElementById("activity-tree-container"),!this.container&&(this.container=document.getElementById("activity-tree"),!this.container))return void console.error("Activity tree container not found in DOM");const e=document.getElementById("activity-tab");if(e){if(!e.classList.contains("active"))return console.log("Activity tab not active, initializing but deferring render"),this.setupControls(),this.subscribeToEvents(),void(this.initialized=!0);this.setupControls(),this.createLinearTreeView(),this.subscribeToEvents(),this.initialized=!0,console.log("Activity tree initialization complete")}else console.error("Activity tab panel (#activity-tab) not found in DOM")}forceShow(){console.log("ActivityTree.forceShow() called"),this.container||(this.container=document.getElementById("activity-tree-container")||document.getElementById("activity-tree"),this.container)?(this.createLinearTreeView(),this.renderTree()):console.error("Cannot find activity tree container")}renderWhenVisible(){if(console.log("ActivityTree.renderWhenVisible() called"),!this.initialized)return console.log("Not initialized yet, calling initialize..."),void this.initialize();this.createLinearTreeView(),this.renderTree()}setupControls(){const e=document.getElementById("time-range");e&&e.addEventListener("change",e=>{this.timeRange=e.target.value,console.log(`ActivityTree: Time range changed to: ${this.timeRange}`),this.renderTree()}),document.addEventListener("sessionFilterChanged",e=>{this.selectedSessionFilter=e.detail.sessionId||"all",console.log(`ActivityTree: Session filter changed to: ${this.selectedSessionFilter} (from SessionManager)`),this.renderTree()}),document.addEventListener("sessionChanged",e=>{this.selectedSessionFilter=e.detail.sessionId||"all",console.log(`ActivityTree: Session changed to: ${this.selectedSessionFilter} (from SessionManager - backward compat)`),this.renderTree()}),setTimeout(()=>{if(window.sessionManager){const e=window.sessionManager.getCurrentFilter();e!==this.selectedSessionFilter&&(this.selectedSessionFilter=e||"all",console.log(`ActivityTree: Initialized with current session filter: ${this.selectedSessionFilter}`),this.renderTree())}},100);const t=document.getElementById("expand-all");t&&t.addEventListener("click",()=>this.expandAllSessions());const s=document.getElementById("collapse-all");s&&s.addEventListener("click",()=>this.collapseAllSessions());const n=document.getElementById("reset-zoom");n&&(n.style.display="inline-block",n.addEventListener("click",()=>this.resetZoom()));const i=document.getElementById("activity-search");i&&i.addEventListener("input",e=>{this.searchTerm=e.target.value.toLowerCase(),this.renderTree()})}createLinearTreeView(){console.log("Creating linear tree view"),this.container.innerHTML="";const e=document.createElement("div");e.id="linear-tree",e.className="linear-tree",this.container.appendChild(e),console.log("Linear tree view created")}subscribeToEvents(){if(!window.socketClient)return console.warn("Socket client not available for activity tree"),void setTimeout(()=>this.subscribeToEvents(),1e3);console.log("ActivityTree: Setting up event subscription"),window.socketClient.onEventUpdate((e,t)=>{console.log(`ActivityTree: onEventUpdate called with ${e.length} total events and ${t.size} sessions`),this.sessions.clear();for(const[n,i]of t.entries()){const e={id:n,timestamp:new Date(i.lastActivity||i.startTime||new Date),expanded:this.expandedSessions.has(n)||!0,agents:new Map,todos:[],userInstructions:[],tools:[],status:"active",currentTodoTool:null,working_directory:i.working_directory,git_branch:i.git_branch,eventCount:i.eventCount};this.sessions.set(n,e)}const s=e.length-this.events.length;if(s>0){const t=e.slice(this.events.length);console.log(`ActivityTree: Processing ${s} new events`,t),t.forEach(e=>{this.processEvent(e)})}this.events=[...e],this.renderTree(),console.log("ActivityTree: Sessions after sync with socket client:",Array.from(this.sessions.entries()))});const e=window.socketClient?.getState();if(e&&e.events.length>0){console.log(`ActivityTree: Loading existing data - ${e.events.length} events, ${e.sessions.size} sessions`),this.sessions.clear();for(const[t,s]of e.sessions.entries()){const e={id:t,timestamp:new Date(s.lastActivity||s.startTime||new Date),expanded:this.expandedSessions.has(t)||!0,agents:new Map,todos:[],userInstructions:[],tools:[],status:"active",currentTodoTool:null,working_directory:s.working_directory,git_branch:s.git_branch,eventCount:s.eventCount};this.sessions.set(t,e)}e.events.forEach(e=>{this.processEvent(e)}),this.events=[...e.events],this.renderTree(),console.log("ActivityTree: Initial sessions state:",Array.from(this.sessions.entries()))}else console.log("ActivityTree: No existing events found"),this.events=[],this.sessions.clear(),this.renderTree()}processEvent(e){if(!e)return void console.log("ActivityTree: Ignoring null event");let t,s=this.getEventType(e);if(!s)return;console.log(`ActivityTree: Processing event: ${s}`,e),e.timestamp?(t=new Date(e.timestamp),isNaN(t.getTime())&&(console.warn("ActivityTree: Invalid timestamp, using current time:",e.timestamp),t=new Date)):(console.warn("ActivityTree: No timestamp found, using current time"),t=new Date);const n=e.session_id||e.data?.session_id;if(!n)return void console.log(`ActivityTree: Skipping event without session_id: ${s}`);if(!this.sessions.has(n))return void console.warn(`ActivityTree: Session ${n} not found in authoritative sessions - skipping event`);const i=this.sessions.get(n);switch(s){case"Start":this.currentSession=i;break;case"user_prompt":this.processUserInstruction(e,i);break;case"TodoWrite":this.processTodoWrite(e,i);break;case"SubagentStart":this.processSubagentStart(e,i);break;case"SubagentStop":this.processSubagentStop(e,i);break;case"PreToolUse":this.processToolUse(e,i);break;case"PostToolUse":this.updateToolStatus(e,i,"completed")}this.updateStats()}getEventType(e){if(e.hook_event_name)return e.hook_event_name;if("hook"===e.type&&e.subtype){return{pre_tool:"PreToolUse",post_tool:"PostToolUse",subagent_start:"SubagentStart",subagent_stop:"SubagentStop",todo_write:"TodoWrite"}[e.subtype]}if("todo"===e.type&&"updated"===e.subtype)return"TodoWrite";if("subagent"===e.type){if("started"===e.subtype)return"SubagentStart";if("stopped"===e.subtype)return"SubagentStop"}return"start"===e.type?"Start":"user_prompt"===e.type||"user_prompt"===e.subtype?"user_prompt":null}processUserInstruction(e,t){const s=e.prompt_text||e.data?.prompt_text||e.prompt||"";if(!s)return;const n={id:`instruction-${t.id}-${Date.now()}`,text:s,preview:s.length>100?s.substring(0,100)+"...":s,timestamp:e.timestamp||(new Date).toISOString(),type:"user_instruction"};t.userInstructions.push(n),t.userInstructions.length>5&&(t.userInstructions=t.userInstructions.slice(-5))}processTodoWrite(e,t){let s=e.todos||e.data?.todos||e.data||[];if(s&&"object"==typeof s&&s.todos&&(s=s.todos),!Array.isArray(s)||0===s.length)return;t.todos=s.map(t=>({content:t.content,activeForm:t.activeForm,status:t.status,timestamp:e.timestamp}));const n={id:`todo-session-${t.id}-${Date.now()}`,name:"TodoWrite",type:"tool",icon:"📝",timestamp:e.timestamp,status:"active",params:{todos:s},isPrioritizedTool:!0};t.tools=t.tools.filter(e=>"TodoWrite"!==e.name),t.tools.unshift(n),t.currentTodoTool=n;const i=e.session_id||e.data?.session_id;let a=null;if(i&&t.agents.has(i))a=t.agents.get(i);else{const e=Array.from(t.agents.values()).filter(e=>"active"===e.status||"in_progress"===e.status).sort((e,t)=>new Date(t.timestamp)-new Date(e.timestamp));if(e.length>0)a=e[0];else{const e=Array.from(t.agents.values()).sort((e,t)=>new Date(t.timestamp)-new Date(e.timestamp));e.length>0&&(a=e[0])}}if(a){const t={id:`todo-agent-${a.id}-${Date.now()}`,name:"TodoWrite",type:"tool",icon:"📝",timestamp:e.timestamp,status:"active",params:{todos:s},isPrioritizedTool:!0};a.tools=a.tools.filter(e=>"TodoWrite"!==e.name),a.tools.unshift(t)}}processSubagentStart(e,t){const s=e.agent_name||e.data?.agent_name||e.data?.agent_type||e.agent_type||e.agent||"unknown",n=e.session_id||e.data?.session_id,i=n||`agent-${Date.now()}-${Math.random()}`;if(t.agents.has(i)){const s=t.agents.get(i);s.status="active",s.timestamp=e.timestamp}else{const a={id:i,name:s,type:"agent",icon:this.getAgentIcon(s),timestamp:e.timestamp,status:"active",tools:[],sessionId:n,isPM:!1};t.agents.set(i,a)}}processSubagentStop(e,t){const s=e.session_id||e.data?.session_id;if(s&&t.agents.has(s)){t.agents.get(s).status="completed"}}processToolUse(e,t){const s=e.tool_name||e.data?.tool_name||e.tool||e.data?.tool||"unknown",n=e.tool_parameters||e.data?.tool_parameters||e.parameters||e.data?.parameters||{},i=e.session_id||e.data?.session_id,a={id:`tool-${Date.now()}-${Math.random()}`,name:s,type:"tool",icon:this.getToolIcon(s),timestamp:e.timestamp,status:"in_progress",params:n,eventId:e.id};let o=null;if(i&&t.agents.has(i))o=t.agents.get(i);else{const e=Array.from(t.agents.values()).filter(e=>"active"===e.status).sort((e,t)=>new Date(t.timestamp)-new Date(e.timestamp));if(!(e.length>0))return void t.tools.push(a);o=e[0]}o&&o.tools.push(a)}updateToolStatus(e,t,s){const n=t=>{if(t.tools){const n=t.tools.find(t=>t.eventId===e.id);if(n)return n.status=s,!0}return!1};for(let i of t.agents.values())if(n(i))return;!t.tools||n(t)}renderTree(){const e=document.getElementById("linear-tree");if(!e)return;e.innerHTML="";const t=Array.from(this.sessions.values()).sort((e,t)=>new Date(t.timestamp)-new Date(e.timestamp));for(let s of t){if("all"!==this.selectedSessionFilter&&this.selectedSessionFilter!==s.id)continue;const t=this.createSessionElement(s);e.appendChild(t)}}createSessionElement(e){const t=this.expandedSessions.has(e.id)||e.expanded;let s;try{const t=e.timestamp instanceof Date?e.timestamp:new Date(e.timestamp);isNaN(t.getTime())?(s="Invalid Date",console.warn("ActivityTree: Invalid session timestamp:",e.timestamp)):s=t.toLocaleString()}catch(l){s="Invalid Date",console.error("ActivityTree: Error formatting session timestamp:",l,e.timestamp)}const n=document.createElement("div");n.className="tree-node session",n.dataset.sessionId=e.id;const i=t?"▼":"▶",a=e.agents?e.agents.size:0,o=e.todos?e.todos.length:0,r=e.userInstructions?e.userInstructions.length:0;return console.log(`ActivityTree: Rendering session ${e.id}: ${a} agents, ${r} instructions, ${o} todos at ${s}`),n.innerHTML=`\n <div class="tree-node-content" onclick="window.activityTreeInstance.toggleSession('${e.id}')">\n <span class="tree-expand-icon">${i}</span>\n <span class="tree-icon">🎯</span>\n <span class="tree-label">PM Session</span>\n <span class="tree-meta">${s} • ${a} agent(s) • ${r} instruction(s) • ${o} todo(s)</span>\n </div>\n <div class="tree-children" style="display: ${t?"block":"none"}">\n ${this.renderSessionContent(e)}\n </div>\n `,n}renderSessionContent(e){let t="";if(e.userInstructions&&e.userInstructions.length>0)for(let n of e.userInstructions.slice(-3))t+=this.renderUserInstructionElement(n,1);if(e.todos&&e.todos.length>0&&(t+=this.renderTodoChecklistElement(e.todos,1)),e.tools&&e.tools.length>0)for(let n of e.tools)t+=this.renderToolElement(n,1);const s=Array.from(e.agents.values()).sort((e,t)=>new Date(t.timestamp)-new Date(e.timestamp));for(let n of s)t+=this.renderAgentElement(n,1);return t}renderUserInstructionElement(e,t){return`\n <div class="tree-node user-instruction ${this.selectedItem&&"instruction"===this.selectedItem.type&&this.selectedItem.data.id===e.id?"selected":""}" data-level="${t}">\n <div class="tree-node-content">\n <span class="tree-expand-icon"></span>\n <span class="tree-icon">💬</span>\n <span class="tree-label clickable" onclick="window.activityTreeInstance.selectItem(${this.escapeJson(e)}, 'instruction', event)">User: "${this.escapeHtml(e.preview)}"</span>\n <span class="tree-status status-active">instruction</span>\n </div>\n </div>\n `}renderTodoChecklistElement(e,t){const s=`checklist-${Date.now()}`,n=!1!==this.expandedTools.has(s),i=n?"▼":"▶";let a=0,o=0;e.forEach(e=>{"completed"===e.status?a++:"in_progress"===e.status&&o++});let r="";r=o>0?`${o} in progress, ${a} completed`:a===e.length&&e.length>0?`All ${e.length} completed`:`${e.length} todo(s)`;let l=`\n <div class="tree-node todo-checklist" data-level="${t}">\n <div class="tree-node-content">\n <span class="tree-expand-icon" onclick="window.activityTreeInstance.toggleTodoChecklist('${s}'); event.stopPropagation();">${i}</span>\n <span class="tree-icon">☑️</span>\n <span class="tree-label">TODOs</span>\n <span class="tree-params">${r}</span>\n <span class="tree-status status-active">checklist</span>\n </div>\n `;if(n){l+='<div class="tree-children">';for(let s of e){const e=this.getCheckboxIcon(s.status),n=`status-${s.status}`,i="in_progress"===s.status?s.activeForm:s.content;l+=`\n <div class="tree-node todo-item ${n}" data-level="${t+1}">\n <div class="tree-node-content">\n <span class="tree-expand-icon"></span>\n <span class="tree-icon">${e}</span>\n <span class="tree-label">${this.escapeHtml(i)}</span>\n <span class="tree-status ${n}">${s.status.replace("_"," ")}</span>\n </div>\n </div>\n `}l+="</div>"}return l+="</div>",l}renderAgentElement(e,t){const s="active"===e.status?"status-active":"status-completed",n=this.expandedAgents.has(e.id),i=e.tools&&e.tools.length>0,a=i?n?"▼":"▶":"";let o=`\n <div class="tree-node agent ${s} ${this.selectedItem&&"agent"===this.selectedItem.type&&this.selectedItem.data.id===e.id?"selected":""}" data-level="${t}">\n <div class="tree-node-content">\n ${a?`<span class="tree-expand-icon" onclick="window.activityTreeInstance.toggleAgent('${e.id}'); event.stopPropagation();">${a}</span>`:'<span class="tree-expand-icon"></span>'}\n <span class="tree-icon">${e.icon}</span>\n <span class="tree-label clickable" onclick="window.activityTreeInstance.selectItem(${this.escapeJson(e)}, 'agent', event)">${e.name}</span>\n <span class="tree-status ${s}">${e.status}</span>\n </div>\n `;if(i&&n){o+='<div class="tree-children">';for(let s of e.tools)o+=this.renderToolElement(s,t+1);o+="</div>"}return o+="</div>",o}renderToolElement(e,t){const s=`status-${e.status}`,n=this.getToolParams(e);return`\n <div class="tree-node tool ${s} ${this.selectedItem&&"tool"===this.selectedItem.type&&this.selectedItem.data.id===e.id?"selected":""}" data-level="${t}">\n <div class="tree-node-content">\n <span class="tree-expand-icon"></span>\n <span class="tree-icon">${e.icon}</span>\n <span class="tree-label clickable" onclick="window.activityTreeInstance.selectItem(${this.escapeJson(e)}, 'tool', event)">${e.name} (click to view details)</span>\n <span class="tree-params">${n}</span>\n <span class="tree-status ${s}">${e.status}</span>\n </div>\n </div>\n `}getToolParams(e){if(!e.params)return"";if("Read"===e.name&&e.params.file_path)return e.params.file_path;if("Edit"===e.name&&e.params.file_path)return e.params.file_path;if("Write"===e.name&&e.params.file_path)return e.params.file_path;if("Bash"===e.name&&e.params.command){const t=e.params.command;return t.length>50?t.substring(0,50)+"...":t}return"WebFetch"===e.name&&e.params.url?e.params.url:""}getStatusIcon(e){return{pending:"⏸️",in_progress:"🔄",completed:"✅"}[e]||"❓"}getCheckboxIcon(e){return{pending:"⏳",in_progress:"🔄",completed:"✅"}[e]||"❓"}getAgentIcon(e){return{engineer:"👷",research:"🔬",qa:"🧪",ops:"⚙️",pm:"📊",architect:"🏗️"}[e.toLowerCase()]||"🤖"}getToolIcon(e){return{read:"👁️",write:"✍️",edit:"✏️",bash:"💻",webfetch:"🌐",grep:"🔍",glob:"📂",todowrite:"📝"}[e.toLowerCase()]||"🔧"}toggleSession(e){this.expandedSessions.has(e)?this.expandedSessions.delete(e):this.expandedSessions.add(e);const t=this.sessions.get(e);t&&(t.expanded=this.expandedSessions.has(e)),this.renderTree()}expandAllSessions(){for(let e of this.sessions.keys()){this.expandedSessions.add(e);const t=this.sessions.get(e);t&&(t.expanded=!0)}this.renderTree()}collapseAllSessions(){this.expandedSessions.clear();for(let e of this.sessions.values())e.expanded=!1;this.renderTree()}updateStats(){const e=this.countTotalNodes(),t=this.countActiveNodes(),s=this.calculateMaxDepth(),n=document.getElementById("node-count"),i=document.getElementById("active-count"),a=document.getElementById("tree-depth");n&&(n.textContent=e),i&&(i.textContent=t),a&&(a.textContent=s),console.log(`ActivityTree: Stats updated - Nodes: ${e}, Active: ${t}, Depth: ${s}`)}countTotalNodes(){let e=0;for(let t of this.sessions.values()){e+=1,e+=t.agents.size,t.userInstructions&&(e+=t.userInstructions.length),t.todos&&(e+=t.todos.length),t.tools&&(e+=t.tools.length);for(let s of t.agents.values())s.tools&&(e+=s.tools.length)}return e}countActiveNodes(){let e=0;for(let t of this.sessions.values()){if("active"===t.status&&e++,t.todos)for(let s of t.todos)"in_progress"===s.status&&e++;if(t.tools)for(let s of t.tools)"in_progress"===s.status&&e++;for(let s of t.agents.values())if("active"===s.status&&e++,s.tools)for(let t of s.tools)"in_progress"===t.status&&e++}return e}calculateMaxDepth(){let e=0;for(let t of this.sessions.values()){let s=1;t.userInstructions&&t.userInstructions.length>0&&(s=Math.max(s,2)),t.todos&&t.todos.length>0&&(s=Math.max(s,3)),t.tools&&t.tools.length>0&&(s=Math.max(s,2));for(let e of t.agents.values())e.tools&&e.tools.length>0&&(s=Math.max(s,3));e=Math.max(e,s)}return e}toggleAgent(e){this.expandedAgents.has(e)?this.expandedAgents.delete(e):this.expandedAgents.add(e),this.renderTree()}toggleTool(e){console.log("Tool expansion is disabled. Tools now show data in the left pane when clicked.")}toggleTodoChecklist(e){this.expandedTools.has(e)?this.expandedTools.delete(e):this.expandedTools.add(e),this.renderTree()}selectItem(e,t,s){s&&s.stopPropagation(),this.selectedItem={data:e,type:t},this.displayItemData(e,t),this.renderTree()}displayItemData(e,t){if("tool"===t&&"TodoWrite"===e.name&&e.params&&e.params.todos)return void this.displayTodoWriteData(e);switch(t){case"agent":this.displayAgentData(e);break;case"tool":this.displayToolData(e);break;case"instruction":this.displayInstructionData(e);break;default:this.displayGenericData(e,t)}const s=document.querySelector(".module-data-header h5");if(s){const n={agent:"🤖",tool:"🔧",instruction:"💬",session:"🎯"}[t]||"📊",i=e.name||e.agentName||e.tool_name||"Item";s.textContent=`${n} ${t}: ${i}`}}displayTodoWriteData(e){const t=e.params.todos||[],s=this.formatTimestamp(e.timestamp);let n=0,i=0,a=0;t.forEach(e=>{"completed"===e.status?n++:"in_progress"===e.status?i++:a++});let o=`\n <div class="unified-viewer-header">\n <h6>📝 TodoWrite: PM ${s}</h6>\n <span class="unified-viewer-status">${this.formatStatus(e.status)}</span>\n </div>\n <div class="unified-viewer-content">\n `;t.length>0?(o+=`\n <div class="detail-section">\n <span class="detail-section-title">Todo Summary</span>\n <div class="todo-summary">\n <div class="summary-item completed">\n <span class="summary-icon">✅</span>\n <span class="summary-count">${n}</span>\n <span class="summary-label">Completed</span>\n </div>\n <div class="summary-item in_progress">\n <span class="summary-icon">🔄</span>\n <span class="summary-count">${i}</span>\n <span class="summary-label">In Progress</span>\n </div>\n <div class="summary-item pending">\n <span class="summary-icon">⏳</span>\n <span class="summary-count">${a}</span>\n <span class="summary-label">Pending</span>\n </div>\n </div>\n </div>\n `,o+=`\n <div class="detail-section">\n <span class="detail-section-title">Todo List (${t.length} items)</span>\n <div class="todo-checklist">\n `,t.forEach((e,t)=>{const s=this.getCheckboxIcon(e.status),n="in_progress"===e.status&&e.activeForm||e.content,i=this.formatStatusClass(e.status);o+=`\n <div class="todo-checklist-item ${e.status}">\n <div class="todo-checkbox">\n <span class="checkbox-icon ${i}">${s}</span>\n </div>\n <div class="todo-text">\n <span class="todo-content">${this.escapeHtml(n)}</span>\n <span class="todo-status-badge ${i}">${e.status.replace("_"," ")}</span>\n </div>\n </div>\n `}),o+="\n </div>\n </div>\n "):o+='\n <div class="detail-section">\n <div class="no-todos">No todo items found</div>\n </div>\n ',o+=`\n <div class="detail-section">\n <span class="detail-section-title">Parameters (${Object.keys(e.params).length})</span>\n <div class="params-list">\n <div class="param-item">\n <div class="param-key">todos:</div>\n <div class="param-value">\n <pre class="param-json">${this.escapeHtml(JSON.stringify(t,null,2))}</pre>\n </div>\n </div>\n </div>\n </div>\n `,o+="</div>";const r=document.getElementById("module-data-content");r&&(r.innerHTML=o);const l=document.querySelector(".module-data-header h5");l&&(l.textContent="📝 tool: TodoWrite")}formatStatus(e){if(!e)return"unknown";return{active:"🟢 Active",completed:"✅ Completed",in_progress:"🔄 In Progress",pending:"⏳ Pending",error:"❌ Error",failed:"❌ Failed"}[e]||e}formatStatusClass(e){return`status-${e}`}formatTimestamp(e){if(!e)return"";try{const t=new Date(e);return isNaN(t.getTime())?"":t.toLocaleTimeString()}catch(t){return""}}displayAgentData(e){const t=this.formatTimestamp(e.timestamp),s=document.getElementById("module-data-content");if(!s)return;let n=`\n <div class="detail-section">\n <span class="detail-section-title">Agent Information</span>\n <div class="agent-info">\n <div class="info-item">\n <span class="info-label">Name:</span>\n <span class="info-value">${this.escapeHtml(e.name)}</span>\n </div>\n <div class="info-item">\n <span class="info-label">Status:</span>\n <span class="info-value status-${e.status}">${e.status}</span>\n </div>\n <div class="info-item">\n <span class="info-label">Timestamp:</span>\n <span class="info-value">${t}</span>\n </div>\n <div class="info-item">\n <span class="info-label">Session ID:</span>\n <span class="info-value">${e.sessionId||"N/A"}</span>\n </div>\n </div>\n </div>\n `;e.tools&&e.tools.length>0&&(n+=`\n <div class="detail-section">\n <span class="detail-section-title">Tools (${e.tools.length})</span>\n <div class="tool-list">\n `,e.tools.forEach(e=>{n+=`\n <div class="tool-item">\n <span class="tool-name">${this.escapeHtml(e.name)}</span>\n <span class="tool-status status-${e.status}">${e.status}</span>\n </div>\n `}),n+="\n </div>\n </div>\n "),s.innerHTML=n}displayToolData(e){const t=this.formatTimestamp(e.timestamp),s=document.getElementById("module-data-content");if(!s)return;let n=`\n <div class="detail-section">\n <span class="detail-section-title">Tool Information</span>\n <div class="tool-info">\n <div class="info-item">\n <span class="info-label">Name:</span>\n <span class="info-value">${this.escapeHtml(e.name)}</span>\n </div>\n <div class="info-item">\n <span class="info-label">Status:</span>\n <span class="info-value status-${e.status}">${e.status}</span>\n </div>\n <div class="info-item">\n <span class="info-label">Timestamp:</span>\n <span class="info-value">${t}</span>\n </div>\n </div>\n </div>\n `;e.params&&Object.keys(e.params).length>0&&(n+='\n <div class="detail-section">\n <span class="detail-section-title">Parameters</span>\n <div class="params-list">\n ',Object.entries(e.params).forEach(([e,t])=>{n+=`\n <div class="param-item">\n <div class="param-key">${this.escapeHtml(e)}:</div>\n <div class="param-value">${this.escapeHtml(String(t))}</div>\n </div>\n `}),n+="\n </div>\n </div>\n "),s.innerHTML=n}displayInstructionData(e){const t=this.formatTimestamp(e.timestamp),s=document.getElementById("module-data-content");if(!s)return;const n=`\n <div class="detail-section">\n <span class="detail-section-title">User Instruction</span>\n <div class="instruction-info">\n <div class="info-item">\n <span class="info-label">Timestamp:</span>\n <span class="info-value">${t}</span>\n </div>\n <div class="instruction-content">\n <div class="instruction-text">${this.escapeHtml(e.text)}</div>\n </div>\n </div>\n </div>\n `;s.innerHTML=n}displayGenericData(e,t){const s=document.getElementById("module-data-content");if(!s)return;let n=`\n <div class="detail-section">\n <span class="detail-section-title">${t||"Item"} Data</span>\n <div class="generic-data">\n <pre>${this.escapeHtml(JSON.stringify(e,null,2))}</pre>\n </div>\n </div>\n `;s.innerHTML=n}escapeHtml(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}resetZoom(){this.svg&&this.zoom&&this.svg.transition().duration(this.duration).call(this.zoom.transform,d3.zoomIdentity)}escapeJson(e){return JSON.stringify(e).replace(/'/g,"&apos;").replace(/"/g,"&quot;")}}window.ActivityTree=e;const t=()=>{let t=null;const s=()=>{t||(console.log("Creating new Activity Tree instance..."),t=new e,window.activityTreeInstance=t,window.activityTree=()=>t),setTimeout(()=>{console.log("Attempting to initialize Activity Tree visualization..."),t.initialize()},100)};document.querySelectorAll(".tab-button").forEach(e=>{e.addEventListener("click",e=>{"activity"===e.target.getAttribute("data-tab")&&(console.log("Activity tab button clicked, initializing tree..."),s(),t&&setTimeout(()=>{t.renderWhenVisible(),t.forceShow()},150))})}),document.addEventListener("tabChanged",e=>{e.detail&&"activity"===e.detail.newTab&&(console.log("Tab changed to activity, initializing tree..."),s(),t&&setTimeout(()=>{t.renderWhenVisible(),t.forceShow()},150))});const n=document.querySelector(".tab-button.active");n&&"activity"===n.getAttribute("data-tab")&&(console.log("Activity tab is active on load, initializing tree..."),s());const i=document.getElementById("activity-tab");i&&i.classList.contains("active")&&(console.log("Activity panel is active on load, initializing tree..."),t||s())};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",t):t();
2
2
  //# sourceMappingURL=activity-tree.js.map